Prev: 6A35 Up: Map Next: 6B42
6AB5: Expand object
This is only ever called by setup_room. It expands the run length encoded object with the given index into indices in the visible tile array.
Objects have the following format:
Each object starts with two bytes which specify its dimensions:
<w> <h> Width in tiles, Height in tiles
Which are then followed by a repetition of the following bytes:
<t> Literal: Emit a single tile <t>
<$FF> <$FF> Escape: Emit a single tile $FF
<$FF> <c=128..254> <t> Repetition: Emit tile <t> count (<c> AND 127) times
<$FF> <c=64..79> <t> Ascending range: Emit tile <t> then <t+1> then <t+2> and so on, up to <t+(c AND 15)>
<$FF> <other> Other encodings are not used
Tile references of zero produce no output.
Used by the routine at setup_room.
Input
A Object index.
DE Tile array location to expand to.
expand_object 6AB5 ADD A,A Fetch the object pointer from interior_object_defs[A] into HL
6AB6 LD HL,$7095
6AB9 LD C,A
6ABA LD B,$00
6ABC ADD HL,BC
6ABD LD A,(HL)
6ABE INC HL
6ABF LD H,(HL)
6AC0 LD L,A
6AC1 LD B,(HL) Fetch the object's width (in tiles)
6AC2 INC HL
6AC3 LD C,(HL) Fetch the object's height (in tiles)
6AC4 INC HL
6AC5 LD A,B Self modify the "LD B,$xx" at end_of_row to load the tile-width into B
6AC6 LD ($6AE7),A
Start main expand loop
expand 6AC9 LD A,(HL) Fetch the next byte
6ACA CP $FF Is it an escape byte? (interiorobjecttile_ESCAPE/$FF)
6ACC JR NZ,write_tile Jump if not
Handle an escape byte - indicating an encoded sequence
6ACE INC HL Step over the escape byte
6ACF LD A,(HL) Fetch the next byte
6AD0 CP $FF Is it also an escape byte?
6AD2 JR Z,write_tile Jump to tile write op if so - we'll emit $FF (Note: Could jump two instructions later)
6AD4 AND $F0 Isolate the top nibble - the top two bits are flags (Note: This could move down to before the $40 test without affecting anything)
6AD6 CP $80 Is it >= 128?
6AD8 JR NC,repetition Jump to repetition handling if so
6ADA CP $40 Is it == 64?
6ADC JR Z,range Jump to range handling if so
write_tile 6ADE AND A Write out the tile if it's non-zero
6ADF JR Z,expand_object_0
6AE1 LD (DE),A
expand_object_0 6AE2 INC HL Move to next input byte
6AE3 INC DE Move to next output byte
6AE4 DJNZ expand ...loop while width counter B is non-zero
end_of_row 6AE6 LD B,$01 Reset width counter. Self modified by 6AC5
6AE8 LD A,$18 Width of tile buffer is 24
6AEA SUB B Tile buffer width minus width of object gives the rowskip
6AEB ADD A,E Add A to DE to move by rowskip
6AEC LD E,A
6AED JR NC,expand_object_1
6AEF INC D
expand_object_1 6AF0 DEC C Decrement row counter
6AF1 JR NZ,expand ...loop to expand while row > 0
6AF3 RET Return
Escape + 128..255 case: emit a repetition of the same byte
repetition 6AF4 LD A,(HL) Fetch flags+count byte
6AF5 AND $7F Mask off top bit to get repetition counter/length
6AF7 EX AF,AF' Bank repetition counter
6AF8 INC HL Move to the next tile value
6AF9 LD A,(HL) Fetch a tile value
6AFA EX AF,AF' Unbank repetition counter ready for the next bank
Start of repetition loop
repetition_loop 6AFB EX AF,AF' Bank the repetition counter
6AFC AND A Is the tile value zero?
6AFD JR Z,expand_object_2 Jump if so, avoiding the write
6AFF LD (DE),A Write it
expand_object_2 6B00 INC DE Move to next tile output byte
6B01 DJNZ repetition_end Decrement the width counter. Jump over the end-of-row code to repetition_end if it's non-zero
Ran out of width / end of row
6B03 LD A,($6AE7) Fetch width (from self modified instruction) into A'
6B06 LD B,A Reset width counter
6B07 LD A,$18 Width of tile buffer is 24
6B09 SUB B Tile buffer width minus width of object gives the rowskip
6B0A ADD A,E Add A to DE to move by rowskip
6B0B LD E,A
6B0C JR NC,expand_object_3
6B0E INC D
expand_object_3 6B0F LD A,(HL) Fetch the next tile value (reload)
6B10 DEC C Decrement the row counter
6B11 RET Z Return if it hit zero
repetition_end 6B12 EX AF,AF' Unbank the repetition counter
6B13 DEC A Decrement the repetition counter
6B14 JR NZ,repetition_loop ...loop if non-zero
6B16 INC HL Advance the data pointer
6B17 JR expand Jump to main expand loop
Escape + 64..79 case: emit an ascending range of bytes
Trivial bug: This self-modifies the INC A at expand_object_increment at the end of the loop body, but nothing else in the code modifies it! Possible evidence that other encodings (e.g. 'DEC A') were attempted.
range 6B19 LD A,$3C Make the instruction at expand_object_increment an 'INC A'
6B1B LD ($6B28),A
6B1E LD A,(HL) Fetch flags+count byte
6B1F AND $0F Mask off the bottom nibble which contains the range counter
6B21 EX AF,AF' Bank the range counter
6B22 INC HL Move to the first tile value
6B23 LD A,(HL) Get the first tile value
6B24 EX AF,AF' Unbank the range counter ready for the next bank
Start of range loop
range_loop 6B25 EX AF,AF' Bank the range counter
6B26 LD (DE),A Write the tile value (Note: We assume it's non-zero)
6B27 INC DE Move to the next tile output byte
expand_object_increment 6B28 INC A Increment the tile value. Self modified by 6B1B
6B29 DJNZ range_end Decrement width counter. Jump over the end-of-row code to range_end if it's non-zero
Ran out of width / end of row
6B2B PUSH AF Stash the tile value
6B2C LD A,($6AE7) Fetch width (from self modified instruction) into A'
6B2F LD B,A Reset width counter
6B30 LD A,$18 Width of tile buffer is 24
6B32 SUB B Tile buffer width minus width of object gives the rowskip
6B33 ADD A,E Add A to DE to move by rowskip
6B34 LD E,A
6B35 JR NC,expand_object_4
6B37 INC D
expand_object_4 6B38 POP AF Unstash the tile value
6B39 DEC C Decrement row counter
6B3A RET Z Return if it hit zero
range_end 6B3B EX AF,AF' Unbank the range counter
6B3C DEC A Decrement the range counter
6B3D JR NZ,range_loop ...loop if non-zero
6B3F INC HL Advance the data pointer
6B40 JR expand Jump to main expand loop
Prev: 6A35 Up: Map Next: 6B42