Prev: E6C6 Up: Map Next: E6EC
E6C8: Rotate Player Cursor Attributes
Used by the routine at F85D.
This is a pretty confusing routine, it's used for rotating the attribute values of the players cursor. These are stored in a table at CursorAttributes.
The reason why this is complicated is simply down to how the data is stored... Rather than hold the attribute bytes sequentially, they're held as: top row x 4 bytes, left side x 1 byte, right side x 1 byte, left side x 1 byte, right side x 1 byte and lastly, the bottom row x 4 bytes.
This makes them a lot easier to draw, as the whole thing can then be drawn left-to-right one row at a time (see Draw_Cursor).
Hopefully the rotation problem is clear already, this isn't a matter of just moving every byte along one position - in order to rotate, a look up table is used to track the positions at Table_CursorAttributePositions.
This table should also hopefully make things clearer:
Address Before After 1 Pass After 2 Passes Position
Attribute Byte Attribute Byte Attribute Byte
E6AF 09 76 36 Top byte 1 (left)
E6B0 49 09 76 Top byte 2
E6B1 12 49 09 Top byte 3
E6B2 52 12 49 Top byte 4 (right)
E6B3 76 36 6D Middle top byte 1 (left)
E6B4 1B 52 12 Middle top byte 2 (right)
E6B5 36 6D 2D Middle bottom byte 1 (left)
E6B6 5B 1B 52 Middle bottom byte 2 (right)
E6B7 6D 2D 64 Bottom byte 1 (left)
E6B8 2D 64 24 Bottom byte 2
E6B9 64 24 5B Bottom byte 3
E6BA 24 5B 1B Bottom byte 4 (right)
On the top row, it's very simple to shift each byte one position to the right but when you reach the end of that row, the subsequent address isn't just next in the sequence. Instead, it's "Middle top byte 2 (right)" as shown in the table which is two positions after "Top byte 4 (right)". Likewise, the next position for the middle section is again, two positions after this one and the bottom row moves in the opposite direction entirely in order to achieve the circular motion!
This creates a wonderful effect as shown here:
moving-game-cursor-animation
PlayerCursor_AttributesRotator E6C8 LD HL,$E6AF Set HL to point to CursorAttributes.
E6CB LD IX,$E6BB Set IX to point to Table_CursorAttributePositions which is the rotation order table.
E6CF LD DE,$0000 Initialise DE to 0000.
E6D2 LD B,$0B Set a counter in B for 0B attribute byte positions.
Grab the first attribute byte value and store it in C for the last part...
E6D4 LD C,(HL) Fetch the first byte from the cursor attributes pointer and store it in C.
This is a loop which rotates the attributes 0B times, each time moving an attribute from the position specified in the table to the current position.
PlayerCursor_AttributesRotator_Loop E6D5 PUSH HL Stash the current position in CursorAttributes on the stack.
E6D6 LD E,(IX+$00) Fetch the current position in the rotation order and store it in E.
E6D9 INC IX Move to the next entry in rotation table.
E6DB LD HL,$E6AF Add CursorAttributes with DE and store the result in HL.
E6DE ADD HL,DE
E6DF LD A,(HL) Fetch a byte from the calculated attribute byte pointer and store it in A.
E6E0 LD ($E6C6),HL Store the calculated attribute byte pointer at *TempAttributeStore.
E6E3 POP HL Restore the cursor attributes pointer from the stack.
E6E4 LD (HL),A Write the byte to the cursor attributes pointer.
E6E5 LD HL,($E6C6) Restore the calculated attribute byte pointer at *TempAttributeStore back to HL.
E6E8 DJNZ PlayerCursor_AttributesRotator_Loop Decrease the attribute byte counter by one and loop back to PlayerCursor_AttributesRotator_Loop until the attribute byte counter is zero.
Write the first attribute byte value we stored in C to the second position in the attributes table.
E6EA LD (HL),C Write the stored attribute byte in C to *HL.
E6EB RET Return.
Prev: E6C6 Up: Map Next: E6EC