4.6 Poking Structs

4.6.2 Mapping Structs

Once defined, struct types can be referred by name. For example, we can map the SBM header at the beginning of our file p.sbm like this:

(poke) SBM_Header @ 0#B
SBM_Header {
  magic=[0x53UB,0x42UB,0x4dUB],
  ppl=0x5UB,
  lines=0x7UB
}

The value resulting from the mapping is a struct value. The fields of struct values are accessed using the familiar dot-notation:

(poke) var header = SBM_Header @ 0#B
(poke) header.ppl * header.lines
35UB

The total number of pixels in the image is 35. Note how both header.ppl and header.lines are indeed unsigned byte values, and thus the result of the multiplication is also an unsigned byte. This could be problematic if the image contained more than 255 pixels, but this can be prevented by using a cast:

(poke) header.ppl as uint * header.lines
35U

Now the second operand header.lines is promoted to a 32-bit unsigned value before the multiplication is performed. Consequently, the result of the operation is also 32-bit wide (note the suffix of the result.)

4.6.3 Modifying Mapped Structs

Remember when we wanted to crop a SBM image by removing the first and last row? We updated the header in a byte by byte manner, like this:

(poke) byte @ 3#B = 3
(poke) byte @ 4#B = 7

Now that we have the header mapped in a variable, updating it is much more easy and convenient. The dot-notation is used to update the contents of a struct field, by placing it at the left hand side of an assignment:

(poke) header.ppl = 3
(poke) header.lines = 7

This updates the pixel per line and the number of lines, in the IO space:

(poke) dump :size 5#B
76543210  0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789ABCDEF
00000000: 5342 4d03 07                             SBM..