![]() |
Routines |
| Prev: D4B2 | Up: Map | Next: D5D4 |
|
Follows previous section at D4B2
|
||||
|
This routine handles the room's foreground objects - originally set up at C501, and stored in data sets at 7F01.
|
||||
| D4FC | LD A,($EAB7) | Get room number | ||
| D4FF | CP $E0 | Is it a vertical tunnel room ( >= room 224)? | ||
| D501 | JP NC,$D6D2 | If so, no foreground objects - skip this routine | ||
| D504 | LD HL,($EB70) | Get pointer to foreground scenery room object data (7F01) | ||
|
Copy item set data bytes into various working buffer addresses:
|
||||
| D507 | LD ($EABE),HL | Store pointer to object data in address pointer buffer | ||
| D50A | LD A,(HL) | First byte of data set | ||
| D50B | INC HL | |||
| D50C | CP $FF | Is it end-of-data? | ||
| D50E | JP Z,$D5D4 | If so, skip out of this routine | ||
| D511 | LD B,A | Store first byte in B register (used as a counter and checked later at D581) | ||
| D512 | LD A,(HL) | Second byte of data set | ||
| D513 | INC HL | |||
| D514 | LD ($EB47),A | Store second byte of set | ||
| D517 | LD A,(HL) | Get third byte of set - item's horizontal position in room (in character/8-pixel steps) | ||
| D518 | INC HL | |||
| D519 | LD ($EB48),A | Store horizontal position for item | ||
| D51C | LD A,(HL) | Get fourth byte of set | ||
| D51D | INC HL | |||
| D51E | LD ($EB49),A | Store byte 4 of set | ||
| D521 | LD A,(HL) | Get fifth byte of set - item's vertical position from top of playing area (in pixels) | ||
| D522 | INC HL | |||
| D523 | LD ($EB4A),A | Store vertical position for item | ||
| D526 | LD ($EAD2),A | Store in second buffer | ||
| D529 | LD E,(HL) | Get address pointer to item graphics | ||
| D52A | INC HL | |||
| D52B | LD D,(HL) | |||
| D52C | INC HL | |||
| D52D | LD ($EACD),DE | ...and store in graphic address pointer buffer | ||
|
Convert horizontal position from characters to pixels:
|
||||
| D531 | LD HL,($EB47) | Get horizontal co-ordinate in 8-pixel/character steps (high byte = H register the important bit) | ||
| D534 | LD D,H | Copy to DE register pair | ||
| D535 | LD E,L | |||
| D536 | ADD HL,HL | x 2 | ||
| D537 | SBC A,A | Use the carry flag to identify whether it's a negative or positive offset (left/right) | ||
| D538 | ADD HL,HL | x 4 | ||
| D539 | RLA | The RLA rotates increase (or decrease if negative) the accumulator, and this gives us an idea of which screen (i.e. left/right of the current viewport) the scenery object is in | ||
| D53A | ADD HL,HL | x 8 | ||
| D53B | RLA | |||
| D53C | LD ($EAD4),A | ...Store the rotated byte indicating horizontal screen/viewport number in current room | ||
| D53F | LD A,H | The high byte of HL contains the rest of the horizontal position of the object | ||
| D540 | LD C,A | |||
| D541 | LD ($EAD3),A | Store it | ||
|
Check Maroc's horizontal movement speed/direction and move the foreground scenery objects accordingly:
|
||||
| D544 | LD A,($EB04) | Maroc's horizontal movement speed
|
||
| D547 | LD L,A | |||
| D548 | RLA | |||
| D549 | SBC A,A | Using an RLA followed by a SBC means the carry flag indicates left/right direction using the H register (e.g. 255 = Maroc moving right, 0 = Maroc moving left) | ||
| D54A | LD H,A | Store this value in the high byte (H), which will cause an addition/subtraction in the next instructions, depending on left/right direction. | ||
| D54B | ADD HL,HL | x 2 | ||
| D54C | ADD HL,HL | x 4 | ||
| D54D | ADD HL,HL | x 8 | ||
| D54E | ADD HL,HL | x 16 (this is the extra that moves the foreground scenery 2x faster than other room elements) | ||
| D54F | ADD HL,DE | Add speed offset to horizontal screen position | ||
| D550 | LD ($EB47),HL | ...and store | ||
|
The high byte (H) of the calculation calculated byte is a character square co-ordinate, the low byte (L) containing a fractions/remainder value. Multiply by 8 to convert to pixel values.
|
||||
| D553 | ADD HL,HL | x 2 | ||
| D554 | SBC A,A | Use the carry bit to determine whether the offset value is negative or positive (depending on direction) | ||
| D555 | ADD HL,HL | x 4 | ||
| D556 | RLA | |||
| D557 | ADD HL,HL | x 8 | ||
| D558 | RLA | |||
| D559 | LD ($EACC),A | Store the high byte - indicating negative (255) or positive (0) | ||
| D55C | LD A,H | And the low byte, containing the horizontal pixel co-ordinate | ||
| D55D | LD ($EACB),A | |||
| D560 | CP C | Has the scenery item's horizontal position changed at all? | ||
| D561 | JR Z,$D565 | |||
| D563 | INC B | If so, increment a flag in B register | ||
| D564 | INC B | |||
|
Check vertical movement speed/direction and move the foreground scenery objects accordingly:
|
||||
| D565 | LD HL,($EB49) | Get vertical screen pixel co-ordinate | ||
| D568 | EX DE,HL | Copy into DE register | ||
| D569 | LD A,($EB05) | Get vertical movement speed/direction (negative = Maroc moving down, positive = Maroc moving up) | ||
| D56C | LD L,$00 | Clear L register | ||
| D56E | SRA A | Divide speed offset by 2... | ||
| D570 | RR L | Rotate carry remainder offset into L register | ||
| D572 | SRA A | Divide speed offset by 4... | ||
| D574 | RR L | Rotate carry remainder offset into L register | ||
| D576 | LD H,A | |||
| D577 | ADD HL,DE | Add the offset to the vertical pixel position | ||
| D578 | LD ($EB49),HL | ...and store new position. | ||
| D57B | LD A,H | Has the scenery item's vertical position changed at all? | ||
| D57C | CP D | |||
| D57D | JR Z,$D581 | |||
| D57F | INC B | If so, increment a flag in B register | ||
| D580 | INC B | |||
|
Check if either horizontal or vertical position has changed - the B register has been updated if so:
|
||||
| D581 | LD A,B | |||
| D582 | CP $02 | |||
| D584 | JR C,$D5A2 | Carry here means neither position has changed - no need to erase anything so skip the next few instructions | ||
|
The item has moved, so it'll need erasing at its pre-move position:
|
||||
| D586 | LD A,$00 | Set draw/erase flag to 0 (ERASE) | ||
| D588 | LD ($EACF),A | |||
| D58B | CALL $DDA1 | Erase the foreground scenery item | ||
| D58E | LD A,($EACB) | |||
| D591 | LD ($EAD3),A | Copy the item's calculated horizontal (pixel) screen position into working graphic buffer | ||
| D594 | LD A,($EB4A) | |||
| D597 | LD ($EAD2),A | Copy the item's calculated vertical (pixel) screen position into working graphic buffer | ||
| D59A | LD A,($EACC) | |||
| D59D | LD ($EAD4),A | Also copy the horizontal co-ordinate high byte | ||
| D5A0 | JR $D5AB | |||
|
Check for item movement again:
|
||||
| D5A2 | CP $00 | |||
| D5A4 | JR NZ,$D5AB | |||
| D5A6 | LD ($EAD5),A | Flag indicating whether (any part of) graphic needs drawing on screen - nothing's changed movement-wise since last check, so set to zero | ||
| D5A9 | JR $D5B3 | ...and skip draw routine | ||
|
Item needs drawing on screen:
|
||||
| D5AB | LD A,$01 | Set draw/erase flag to 1 (DRAW) | ||
| D5AD | LD ($EACF),A | |||
| D5B0 | CALL $DDA1 | Draw the foreground scenery item | ||
|
Copy scenery item data into data sets at 7F01
|
||||
| D5B3 | LD HL,($EABE) | (Copy of) pointer to scenery item data at 7F01 | ||
| D5B6 | LD A,($EAD5) | Flag indicating whether (any part of) graphic is visible on screen | ||
| D5B9 | LD (HL),A | Store in (first byte of) scenery data item | ||
| D5BA | INC HL | |||
| D5BB | LD A,($EB47) | |||
| D5BE | LD (HL),A | Put horizontal object position overflow/precision offset into byte 2 of set | ||
| D5BF | INC HL | |||
| D5C0 | LD A,($EB48) | |||
| D5C3 | LD (HL),A | Put horizontal object position into byte 3 of set | ||
| D5C4 | INC HL | |||
| D5C5 | LD A,($EB49) | |||
| D5C8 | LD (HL),A | Put vertical object position overflow/precision offset into byte 4 of set | ||
| D5C9 | INC HL | |||
| D5CA | LD A,($EB4A) | |||
| D5CD | LD (HL),A | Put vertical object position into byte 5 of set | ||
| D5CE | INC HL | Move pointer along to next data set item at 7F01 | ||
| D5CF | INC HL | |||
| D5D0 | INC HL | |||
| D5D1 | JP $D507 | Continue to deal with (move, erase and draw) foreground scenery items | ||
|
Next routine is at D5D4 (after all foreground scenery items dealt with)
|
||||
| Prev: D4B2 | Up: Map | Next: D5D4 |