DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦0a1277319⟧ Ada Source

    Length: 43008 (0xa800)
    Types: Ada Source
    Notes: 03_class, FILE, R1k_Segment, e3_tag, package body Xlbp_Text, seg_004f8d

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦this⟧ 

E3 Source Code



with Xlbt_Arithmetic;  
use Xlbt_Arithmetic;  
with Xlbt_Basic;  
use Xlbt_Basic;  
with Xlbt_Font;  
use Xlbt_Font;  
with Xlbt_Misc;  
use Xlbt_Misc;  
with Xlbt_Reply;  
use Xlbt_Reply;  
with Xlbt_Request;  
use Xlbt_Request;  
with Xlbt_String;  
use Xlbt_String;  
with Xlbt_Text;  
use Xlbt_Text;

with Xlbp_Font;  
use Xlbp_Font;  
with Xlbp_Gc;  
use Xlbp_Gc;  
with Xlbt_Reply;  
use Xlbt_Reply;

with Xlbip_Get_Reply;  
use Xlbip_Get_Reply;  
with Xlbip_Internal;  
use Xlbip_Internal;  
with Xlbip_Put_Request;  
use Xlbip_Put_Request;

package body Xlbp_Text is
------------------------------------------------------------------------------
-- X Library Text - 8-bit characters
--
-- Xlbp_Text - Handle drawing of 8-bit characters
------------------------------------------------------------------------------
-- Copyright 1989 - 1991 by Rational, Santa Clara, California.
-- Copyright 1987 - 1989 by Digital Equipment Corporation, Maynard, Mass.
-- Copyright 1987 - 1989 by Massachusetts Institute of Technology,
--                          Cambridge, Massachusetts.
--
--                  All Rights Reserved.
--
-- Permission to use, copy, modify, and distribute this software and its
-- documentation for any purpose and without fee is hereby granted,
-- provided that the above copyright notice(s) appear in all copies and that
-- both that copyright notice(s) and this permission notice appear in
-- supporting documentation, and that the names of Digital, MIT, or Rational
-- not be used in advertising or publicity pertaining to distribution of
-- the software without specific, written prior permission.
--
-- Digital, MIT, and Rational disclaim all warranties with regard to this
-- software, including all implied warranties of merchantability and fitness,
-- in no event shall Digital, MIT, or Rational be liable for any special,
-- indirect or consequential damages or any damages whatsoever resulting from
-- loss of use, data or profits, whether in an action of contract, negligence
-- or other tortious action, arising out of or in connection with the use or
-- performance of this software.
------------------------------------------------------------------------------

--\x0c
    procedure X_Draw_String (Display  : X_Display;  
                             Drawable : X_Drawable;  
                             Gc       : X_Gc;  
                             X        : S_Short;  
                             Y        : S_Short;  
                             Text     : X_String) is
------------------------------------------------------------------------------
-- X_Draw_String
------------------------------------------------------------------------------
        Str_Length       : S_Natural := Text'Length;  
        Datalength       : S_Natural;  
        Partial_N_Chars  : S_Natural := Str_Length;  
        Elt              : X_Text_Elt;  
        Character_Offset : S_Natural := Text'First;  
    begin

----Do nothing for an empty string.

        if Str_Length = 0 then  
            return;  
        end if;

----Lock the display and flush changes to the GC we are about to use.

        Lock_Display (Display);  
        begin  
            Private_X_Flush_Gc (Display, Gc);

----Send the request header; figure out the actual request length.  The length
--  is that of the header plus the text plus the number of sub-headers we need
--  to describe all of the up-to 254 character sub-blocks we are sending.

            Datalength :=  
               (X_Text_Elt'Size / 8) * ((Str_Length + 253) / 254) + Str_Length;  
            Put_X_Poly_Text8_Request  
               (Display,  
                (Kind     => Poly_Text8,  
                 Length   => X_Poly_Text8_Request'Size / 32 +  
                                U_Short ((Datalength + 3) / 4),  
                 Pad      => 0,  
                 Drawable => Drawable,  
                 Gc       => Gc.Gid,  
                 X        => X,  
                 Y        => Y),  
                Datalength);

----Send as many full 254 character blocks as we can.

            Elt := (Deltaa => 0,  
                    Length => 254);  
            while Partial_N_Chars > 254 loop  
                Put_X_Text_Elt_Unaligned (Display, Elt);  
                Put_X_String_Unaligned  
                   (Display,  
                    Text (Character_Offset .. Character_Offset + 253));  
                Partial_N_Chars  := Partial_N_Chars - 254;  
                Character_Offset := Character_Offset + 254;  
            end loop;

----Send the last not-full character block if there is one.

            if Partial_N_Chars /= 0 then  
                Elt := (Deltaa => 0,  
                        Length => U_Char (Partial_N_Chars));  
                Put_X_Text_Elt_Unaligned (Display, Elt);  
                Put_X_String_Unaligned (Displa,  
                                        Text (Character_Offset .. Text'Last));

----Pad request out to a 32-bit boundary if necessary

                if Datalength rem 4 /= 0 then  
                    Put_U_Char_Array_Unaligned  
                       (Display, (1 .. 4 - Datalength rem 4 => 0));  
                end if;  
            end if;

----Catch unexpected exceptions.

        exception  
            when others =>  
                Unlock_Display (Display);  
                raise;  
        end;

----Unlock; sync; and return;

        Unlock_Display (Display);  
        Sync_Handle (Display);

    end X_Draw_String;

--\x0c
    procedure X_Draw_Image_String (Display  : X_Display;  
                                   Drawable : X_Drawable;  
                                   Gc       : X_Gc;  
                                   X        : S_Short;  
                                   Y        : S_Short;  
                                   Text     : X_String) is
------------------------------------------------------------------------------
-- X_Draw_Image_String
------------------------------------------------------------------------------
        Character_Offset   : S_Natural := Text'First;  
        First_Time_Through : Boolean   := True;  
        Cur_X              : S_Short   := X;  
        Cur_Length         : S_Natural := Text'Length;  
        Last_X             : S_Short   := 0;  
        Unit               : S_Natural;  
    begin

----Lock the display and flush changes to the GC we are about to use.

        Lock_Display (Display);  
        begin  
            Private_X_Flush_Gc (Display, Gc);

----Loop until all of the characters are done.

            while Cur_Length > 0 loop

----Figure out how many characters to do this pass.

                if Cur_Length > 255 then  
                    Unit := 255;  
                else  
                    Unit := Cur_Length;  
                end if;

----If we just did a group then we must figure out how wide it was before we
--  can do the next group.

                if First_Time_Through then  
                    First_Time_Through := False;  
                else  
                    declare  
                        Direction : X_Font_Direction;  
                        Ascent    : S_Short;  
                        Descent   : S_Short;  
                        Overall   : X_Char_Struct;  
                        Font      : X_Font_Struct;  
                    begin

----Unlock; get the font we're using; check the extent of the last 255
--  characters; and lock up again.

                        Unlock_Display (Display);

                        Font := X_Query_Font (Display, (Id => Gc.Gid.Id));  
                        if Font = None_X_Font_Struct then  
                            return;  
                        end if;

                        X_Text_Extents (Font,  
                                        Text (Character_Offset - 255 ..  
                                                 Character_Offset - 1),  
                                        Direction,  
                                        Ascent,  
                                        Descent,  
                                        Overall);

                        Free_X_Font_Struct (Font);

                        Lock_Display (Display);

                        Cur_X := Last_X + S_Short (Overall.Width);  
                    end;  
                end if;

----Send out a request for this group of characters.

                Last_X := Cur_X;  
                Put_X_Image_Text8_Request  
                   (Display,  
                    (Kind     => Image_Text8,  
                     Length   => X_Image_Text8_Request'Size / 32 +  
                                    U_Short ((Unit + 3) / 4),  
                     N_Chars  => U_Char (Unit),  
                     Drawable => Drawable,  
                     Gc       => Gc.Gid,  
                     X        => Cur_X,  
                     Y        => Y),  
                    Unit);

----Put out the characters for this group.

                Put_X_String  
                   (Display,  
                    Text (Character_Offset .. Character_Offset + Unit - 1));  
                Character_Offset := Character_Offset + Unit;  
                Cur_Length       := Cur_Length - Unit;  
            end loop;

----Catch unexpected exceptions.

        exception  
            when others =>  
                Unlock_Display (Display);  
                raise;  
        end;

----Unlock; sync; and return;

        Unlock_Display (Display);  
        Sync_Handle (Display);

    end X_Draw_Image_String;

--\x0c
    procedure X_Draw_Text (Display  : X_Display;  
                           Drawable : X_Drawable;  
                           Gc       : X_Gc;  
                           X        : S_Short;  
                           Y        : S_Short;  
                           Items    : X_Text_Item_Array) is
------------------------------------------------------------------------------
-- X_Draw_Text
------------------------------------------------------------------------------
        Length             : S_Natural := 0;  
        Font               : U_Char_Array (1 .. 5);  
        Partial_N_Chars    : S_Natural;  
        Partial_Delta      : S_Short;  
        Elt                : X_Text_Elt;  
        First_Time_Through : Boolean;  
        Character_Offset   : S_Natural;  
        Chars              : X_String_Pointer;  
    begin

----Lock the display and flush changes to the GC we are about to use.

        Lock_Display (Display);  
        begin  
            Private_X_Flush_Gc (Display, Gc);

----Process each of the Items in turn.  Calculate the total size of the extra
--  data in this request.

            for I in Items'Range loop

----Font changes are 5 bytes; a 255 byte, plus size of Font id.

                if Items (I).Font /= None_X_Font then  
                    Length := Length + 1 + X_Font'Size / 8;  
                end if;

----If there's a Delta then we will send one Text_Elt for each 128 of the
--  Delta amount.

                if Items (I).Deltaa /= 0 then  
                    if Items (I).Deltaa > 0 then  
                        Length :=  
                           Length + X_Text_Elt'Size / 8 *  
                                       S_Natural  
                                          ((Items (I).Deltaa + 126) / 127);  
                    else  
                        Length :=  
                           Length +  
                              X_Text_Elt'Size / 8 *  
                                 S_Natural  
                                    ((abs (Items (I).Deltaa) + 127) / 128);  
                    end if;  
                end if;

----If there are characters then they will be sent in 254 character chunks with
--  a Text_Elt header for each chunk.

                Chars := Items (I).Chars;  
                if Chars'Length > 0 then  
                    Length := Length +  
                                 X_Text_Elt'Size / 8 *  
                                    S_Natural ((Chars'Length + 253) / 254 - 1);  
                    if Items (I).Deltaa = 0 then
                        ----We share with the last Delta if possible.
                        Length := Length + X_Text_Elt'Size / 8;  
                    end if;  
                    Length := Length + Chars'Length;  
                end if;  
            end loop;

----Send the request header.

            Put_X_Poly_Text8_Request  
               (Display,  
                (Kind     => Poly_Text8,  
                 Length   =>  
                    X_Poly_Text8_Request'Size / 32 + U_Short (Length + 3) / 4,  
                 Pad      => 0,  
                 Drawable => Drawable,  
                 Gc       => Gc.Gid,  
                 X        => X,  
                 Y        => Y),  
                Length);

----Process each of the Items in turn.  Put them into the Display buffer.

            for I in Items'Range loop

----If this guy is doing a font change then put him out.  To mark a font shift,
--  write a 255 byte followed by the 4 bytes of font ID, big-end (most
--  significant bits) first.  Update our local GC with the new font.

                if Items (I).Font /= None_X_Font then  
                    Font (1) := 255;  
                    Font (2) := U_Char (Items (I).Font.Id.Number / 2 ** 24);  
                    Font (3) := U_Char (Items (I).Font.Id.Number /  
                                        2 ** 16 rem 16#100#);  
                    Font (4) := U_Char (Items (I).Font.Id.Number /  
                                        2 ** 8 rem 16#100#);  
                    Font (5) := U_Char (Items (I).Font.Id.Number rem 16#100#);  
                    Put_U_Char_Array_Unaligned (Display, Font);  
                    Gc.Values.Font := Items (I).Font;  
                end if;

----If there's a Delta then process that.

                Partial_Delta := Items (I).Deltaa;  
                if Partial_Delta /= 0 then  
                    while Partial_Delta < -128 or else Partial_Delta > 127 loop  
                        if Partial_Delta > 0 then  
                            Elt           := (Deltaa => 127,  
                                              Length => 0);  
                            Partial_Delta := Partial_Delta - 127;  
                        else  
                            Elt           := (Deltaa => -128,  
                                              Length => 0);  
                            Partial_Delta := Partial_Delta + 128;  
                        end if;  
                        Put_X_Text_Elt_Unaligned (Display, Elt);  
                    end loop;  
                    if Partial_Delta /= 0 and then  
                       Items (I).Chars'Length = 0 then  
                        Elt := (Deltaa => S_Char (Partial_Delta),  
                                Length => 0);  
                        Put_X_Text_Elt_Unaligned (Display, Elt);  
                    end if;  
                end if;

----If there are characters then process them.

                Chars              := Items (I).Chars;  
                Partial_N_Chars    := Chars'Last;  
                First_Time_Through := True;  
                Character_Offset   := Chars'First;

----Do them in lumps of 254 at a time to begin with.

                while Partial_N_Chars > 254 loop  
                    if First_Time_Through then  
                        First_Time_Through := False;  
                        Elt                := (Deltaa => S_Char (Partial_Delta),  
                                               Length => 254);  
                        Put_X_Text_Elt_Unaligned (Display, Elt);  
                        Partial_Delta := 0;  
                    else  
                        Elt := (Deltaa => 0,  
                                Length => 254);  
                        Put_X_Text_Elt_Unaligned (Display, Elt);  
                    end if;  
                    Put_X_String_Unaligned  
                       (Display,  
                        Chars (Character_Offset .. Character_Offset + 253));  
                    Partial_N_Chars  := Partial_N_Chars - 254;  
                    Character_Offset := Character_Offset + 254;  
                end loop;

----Finish off the last few characters; if any.

                if Partial_N_Chars /= 0 then  
                    Elt := (Deltaa => S_Char (Partial_Delta),  
                            Length => U_Char (Partial_N_Chars));  
                    Put_X_Text_Elt_Unaligned (Display, Elt);  
                    Put_X_String_Unaligned  
                       (Display,  
                       Chars (Character_Offset .. Chars'Last));  
                end if;  
            end loop;

----Pad request out to a 32-bit (4 byte) boundary.

            Length := Length rem 4;  
            if Length /= 0 then  
                Put_U_Char_Array_Unaligned (Display, (1 .. 4 - Length => 0));  
            end if;

----Catch unexpected exceptions.

        exception  
            when others =>  
                Unlock_Display (Display);  
                raise;  
        end;

----Unlock; sync; and return;

        Unlock_Display (Display);  
        Sync_Handle (Display);  
        return;

    end X_Draw_Text;

--\x0c
    procedure X_Query_Text_Extents (Display      :     X_Display;  
                                    Font         :     X_Font;  
                                    Text         :     X_String;  
                                    Direction    : out X_Font_Direction;  
                                    Font_Ascent  : out S_Short;  
                                    Font_Descent : out S_Short;  
                                    Overall      : out X_Char_Struct) is
------------------------------------------------------------------------------
-- X_Query_Text_Extents
------------------------------------------------------------------------------
        Str_Length : constant S_Natural := Text'Length;  
        Rep        : X_Reply_Contents;  
        Succ       : X_Status;  
    begin


----Lock the display and flush changes to the GC we are about to use.

        Lock_Display (Display);  
        begin

----Send the request.

            Put_X_Query_Text_Extents_Request  
               (Display, (Kind       => Query_Text_Extents,  
                          Length     => X_Query_Text_Extents_Request'Size / 32 +  
                                           U_Short (Str_Length + 3) /  
                                              2,  -- Yes, 2; not 4.
                          Font       => Font,  
                          Odd_Length =>  
                             From_Boolean ((Str_Length rem 2) /= 0)));


----Send the string; each character is sent as 2 bytes.

            declare  
                Buf : U_Char_Array (1 .. S_Natural (Str_Length * 2));  
            begin  
                for I in reverse 0 .. Str_Length - 1 loop  
                    Buf (I * 2 + 1) := 0;  
                    Buf (I * 2 + 2) := X_Character'Pos (Text (Text'First + I));  
                end loop;  
                Put_U_Char_Array (Display, Buf);  
            end;

----Read the reply.

            Get_Reply (Display => Display,  
                       Code    => Query_Text_Extents,  
                       Reply   => Rep,  
                       Extra   => 0,  
                       Discard => True,  
                       Status  => Succ);

----If we got failure then return that.

            if Succ = Failed then  
                Direction    := Font_Left_To_Right;  
                Font_Ascent  := 0;  
                Font_Descent := 0;  
                Overall      := None_X_Char_Struct;  
                return;  
            end if;

----Return the results.

            Direction    := Rep.Query_Text_Extents.Draw_Direction;  
            Font_Ascent  := Rep.Query_Text_Extents.Font_Ascent;  
            Font_Descent := Rep.Query_Text_Extents.Font_Descent;  
            Overall      :=  
               (Ascent     => Rep.Query_Text_Extents.Overall_Ascent,  
                Descent    => Rep.Query_Text_Extents.Overall_Descent,  
                Width      => S_Short (Rep.Query_Text_Extents.Overall_Width),  
                Lbearing   => S_Short (Rep.Query_Text_Extents.Overall_Left),  
                Rbearing   => S_Short (Rep.Query_Text_Extents.Overall_Right),  
                Attributes => (others => False));

----Catch unexpected exceptions.

        exception  
            when others =>  
                Unlock_Display (Display);  
                raise;  
        end;

----Unlock; sync; and return;

        Unlock_Display (Display);  
        Sync_Handle (Display);

    end X_Query_Text_Extents;

--\x0c
    procedure Ci_Get_Char_Info_1d (Fs    :        X_Font_Struct;  
                                   Char  :        U_Char;  
                                   Cs    : in out X_Char_Struct;  
                                   Found : out    Boolean) is  
    begin  
        if Fs.Per_Char = None_X_Char_Struct_List_2d then  
            Cs    := Fs.Min_Bounds;  
            Found := True;  
        elsif 0 in Fs.Per_Char'Range (1) and then  
              Char in Fs.Per_Char'Range (2) then  
            Cs := Fs.Per_Char (0, Char);  
            if Ci_Non_Exist_Char (Cs) then  
                Found := False;  
            else  
                Found := True;  
            end if;  
        else  
            Found := False;  
        end if;  
    end Ci_Get_Char_Info_1d;

--\x0c
    procedure Ci_Get_Default_Info_1d (Fs    :        X_Font_Struct;  
                                      Cs    : in out X_Char_Struct;  
                                      Found : out    Boolean) is  
    begin  
        Ci_Get_Char_Info_1d (Fs,  
                             Fs.Default_Char.Char2,  
                             Cs,  
                             Found);  
    end Ci_Get_Default_Info_1d;

--\x0c
    procedure X_Text_Extents (Font         :     X_Font_Struct;  
                              Text         :     X_String;  
                              Direction    : out X_Font_Direction;  
                              Font_Ascent  : out S_Short;  
                              Font_Descent : out S_Short;  
                              Overall      : out X_Char_Struct) is
------------------------------------------------------------------------------
-- X_Text_Extents
------------------------------------------------------------------------------
        N_Found  : S_Natural := 0;         -- number of characters found
        Def      : X_Char_Struct;        -- info about default char
        Cs       : X_Char_Struct;  
        Have_Def : Boolean;  
        Found    : Boolean;  
        Ovrall   : X_Char_Struct;  
    begin

        Ci_Get_Default_Info_1d (Font, Def, Have_Def);

        Direction    := Font.Direction;  
        Font_Ascent  := Font.Ascent;  
        Font_Descent := Font.Descent;

-- Iterate over the input string getting the appropriate * char struct.
-- The default (which may be null if there is no def_char) will be returned
-- if the character doesn't exist.  On the first time * through the loop,
-- assign the values to overall; otherwise, compute * the new values.

        for I in Text'Range loop

            Ci_Get_Char_Info_1d  
               (Font, U_Char (X_Character'Pos (Text (I))), Cs, Found);

            if not Found then  
                if Have_Def then  
                    Cs := Def;  
                else  
                    goto Continue;  
                end if;  
            end if;  
            if N_Found = 0 then  
                Overall := Cs;  
            else  
                Ovrall.Ascent   := Max (Ovrall.Ascent, Cs.Ascent);  
                Ovrall.Descent  := Max (Ovrall.Descent, Cs.Descent);  
                Ovrall.Lbearing := Min (Ovrall.Lbearing,  
                                        Ovrall.Width + Cs.Lbearing);  
                Ovrall.Rbearing := Max (Ovrall.Rbearing,  
                                        Ovrall.Width + Cs.Rbearing);  
                Ovrall.Width    := Ovrall.Width + Cs.Width;  
            end if;  
            N_Found := N_Found + 1;

            <<Continue>> null;  
        end loop;

----If there were no characters, then set everything to 0.

        if N_Found = 0 then  
            Overall := None_X_Char_Struct;  
        else  
            Overall := Ovrall;  
        end if;

    end X_Text_Extents;

--\x0c
    function X_Text_Width (Font : X_Font_Struct;  
                           Text : X_String) return S_Long is
------------------------------------------------------------------------------
-- X_Text_Width
------------------------------------------------------------------------------
        Def      : X_Char_Struct;        -- info about default char
        Cs       : X_Char_Struct;  
        Have_Def : Boolean;  
        Found    : Boolean;  
        Width    : S_Long;  
    begin

        Ci_Get_Default_Info_1d (Font, Def, Have_Def);

-- Iterate over the input string getting the appropriate * char struct.
-- The default (which may be null if there is no def_char) will be returned
-- if the character doesn't exist.  On the first time * through the loop,
-- assign the values to overall; otherwise, compute * the new values.

        Width := 0;  
        for I in Text'Range loop

            Ci_Get_Char_Info_1d  
               (Font, U_Char (X_Character'Pos (Text (I))), Cs, Found);

            if not Found then  
                if Have_Def then  
                    Width := Width + S_Long (Def.Width);  
                end if;  
            else  
                Width := Width + S_Long (Cs.Width);  
            end if;  
        end loop;  
        return Width;

    end X_Text_Width;

--\x0c
end Xlbp_Text;  

E3 Meta Data

    nblk1=29
    nid=0
    hdr6=52
        [0x00] rec0=28 rec1=00 rec2=01 rec3=068
        [0x01] rec0=11 rec1=00 rec2=02 rec3=084
        [0x02] rec0=14 rec1=00 rec2=03 rec3=024
        [0x03] rec0=00 rec1=00 rec2=29 rec3=034
        [0x04] rec0=1c rec1=00 rec2=04 rec3=00c
        [0x05] rec0=18 rec1=00 rec2=05 rec3=05c
        [0x06] rec0=00 rec1=00 rec2=28 rec3=002
        [0x07] rec0=20 rec1=00 rec2=06 rec3=028
        [0x08] rec0=1b rec1=00 rec2=07 rec3=030
        [0x09] rec0=03 rec1=00 rec2=27 rec3=00c
        [0x0a] rec0=19 rec1=00 rec2=08 rec3=02c
        [0x0b] rec0=00 rec1=00 rec2=26 rec3=018
        [0x0c] rec0=18 rec1=00 rec2=09 rec3=042
        [0x0d] rec0=22 rec1=00 rec2=0a rec3=012
        [0x0e] rec0=00 rec1=00 rec2=25 rec3=00c
        [0x0f] rec0=19 rec1=00 rec2=0b rec3=014
        [0x10] rec0=02 rec1=00 rec2=24 rec3=03e
        [0x11] rec0=18 rec1=00 rec2=0c rec3=054
        [0x12] rec0=18 rec1=00 rec2=0d rec3=02a
        [0x13] rec0=15 rec1=00 rec2=0e rec3=05e
        [0x14] rec0=14 rec1=00 rec2=0f rec3=004
        [0x15] rec0=01 rec1=00 rec2=23 rec3=010
        [0x16] rec0=16 rec1=00 rec2=10 rec3=02a
        [0x17] rec0=00 rec1=00 rec2=22 rec3=05a
        [0x18] rec0=16 rec1=00 rec2=11 rec3=02a
        [0x19] rec0=00 rec1=00 rec2=21 rec3=002
        [0x1a] rec0=20 rec1=00 rec2=12 rec3=064
        [0x1b] rec0=18 rec1=00 rec2=13 rec3=01a
        [0x1c] rec0=00 rec1=00 rec2=20 rec3=01a
        [0x1d] rec0=1d rec1=00 rec2=14 rec3=00a
        [0x1e] rec0=17 rec1=00 rec2=15 rec3=006
        [0x1f] rec0=00 rec1=00 rec2=1f rec3=024
        [0x20] rec0=1e rec1=00 rec2=16 rec3=02c
        [0x21] rec0=00 rec1=00 rec2=1e rec3=006
        [0x22] rec0=18 rec1=00 rec2=17 rec3=01a
        [0x23] rec0=19 rec1=00 rec2=18 rec3=012
        [0x24] rec0=00 rec1=00 rec2=1d rec3=02a
        [0x25] rec0=1a rec1=00 rec2=19 rec3=04c
        [0x26] rec0=00 rec1=00 rec2=1c rec3=00c
        [0x27] rec0=1c rec1=00 rec2=1a rec3=012
        [0x28] rec0=13 rec1=00 rec2=1b rec3=000
    tail 0x217006fba81978374fdcc 0x42a00088462063203