So I am trying to read a file into a record, specified like so:
type U32 is new Interfaces.Unsigned_32;
type U16 is new Interfaces.Unsigned_16;
type U8 is new Interfaces.Unsigned_8;
type Rotation_t is range 0 .. 3 with Size => 2;
type Tilenum_t is new Interfaces.Unsigned_8;
type Padding_t is range 0 .. 7 with Size => 3;
type Tile is record
Tilenum : Tilenum_t;
XFlipped : Boolean;
YFlipped : Boolean;
Rotation : Rotation_t;
TriFlipped : Boolean;
Padding : Padding_t;
Height : U8;
end record with Size => 24;
for Tile use
record
-- first byte
Tilenum at 0 range 0 .. 7; -- 1111 1111 0000 0000 0000 0000
-- second byte
XFlipped at 0 range 8 .. 8; -- 0000 0000 1000 0000 0000 0000
YFlipped at 0 range 9 .. 9; -- 0000 0000 0100 0000 0000 0000
Rotation at 0 range 10 .. 11; -- 0000 0000 0011 0000 0000 0000
TriFlipped at 0 range 12 .. 12; -- 0000 0000 0000 1000 0000 0000
Padding at 0 range 13 .. 15; -- 0000 0000 0000 0111 0000 0000
-- third byte
Height at 0 range 16 .. 23; -- 0000 0000 0000 0000 1111 1111
end record;
for Tile'Bit_Order use System.Low_Order_First;
for Tile'Scalar_Storage_Order use System.Low_Order_First;
Note that information comes in by 3 bytes at a time. On disk, I have:
# hexdump -C
# we are only interested in second line: first one is metadata
00000000 6d 61 70 20 0a 00 00 00 65 00 00 00 50 00 00 00 |map ....e...P...|
00000010 11 00 00 11 00 00 11 00 00 11 00 00 11 00 00 11 |................|
Now, reading this file (Tile'Read (...)
) produces flipped results:
# ada reads:
Tilenum= 17 XFlipped=FALSE YFlipped=FALSE Rotation= 1 TriFlipped=FALSE Padding= 0 Height= 17
Tilenum= 0 XFlipped=FALSE YFlipped=TRUE Rotation= 0 TriFlipped=FALSE Padding= 1 Height= 0
Tilenum= 0 XFlipped=TRUE YFlipped=FALSE Rotation= 0 TriFlipped=TRUE Padding= 0 Height= 0
Tilenum= 17 XFlipped=FALSE YFlipped=FALSE Rotation= 1 TriFlipped=FALSE Padding= 0 Height= 17
# same as above, in numerical form:
0x11 [b:0001 0000] 0x11
0x00 [b:0100 0001] 0x00
0x00 [b:1000 1000] 0x00
0x11 [b:0001 0000] 0x11
While I would expect the result to be:
0x11 0 0
0x11 0 0
0x11 0 0
...
I am not sure to understand why 0x11
gets split into 2 nibbles ([0001 0001]
) which are being read in two different times. (I would expect bytes to be simply flipped but being kept as a whole).
I deduce I am doing something terribly wrong.
Any help?
I don't know what 0x11
and 0x00
mean. When asking Ada questions, please use Ada notation and terminology.
According to ARM 13.13.2(9/3), "For composite types, the Write or Read attribute for each component is called in canonical order, which is ... positional aggregate order for a record." In other words, doing
T : Tile;
...
Tile'Read (F, T);
is equivalent to
declare
F1 : Tilenum_T;
begin
Tilenum_T'Read (F, F1);
T.Tilenum := F1;
end;
declare
F2 : Boolean;
begin
Boolean'Read (F, F2);
T.Xflipped := F2;
end;
and so on. Each of these calls to Read
reads at least one stream element (usually a byte), so Tile'Read
reads 7 bytes.
It may be possible to redefine Tile'Read
so it works. Much simpler and more likely to succeed is defining
type Tile_As_Bytes is array (1 .. 3) of U8 with Size => 24;
reading 3 bytes into an object of Tile_As_Bytes
, and using Ada.Unchecked_Conversion
to convert it to a Tile
.