![]() |
Routines |
| Prev: B4B8 | Up: Map | Next: B53E |
|
This returns the nearest door to the hero.
Used by the routines at action_lockpick and action_key.
|
||||||||||
| get_nearest_door | B4D0 | LD A,($68A0) | Get the global current room index | |||||||
| B4D3 | AND A | Is it room_0_OUTDOORS? | ||||||||
| B4D4 | JR Z,gnd_outdoors | Jump forward to handle outdoors if so | ||||||||
|
Bug: Could avoid this jump instruction by using fallthrough instead.
|
||||||||||
| B4D6 | JP gnd_indoors | Otherwise jump forward to handle indoors | ||||||||
|
Outdoors.
Locked doors 0..4 include exterior doors.
|
||||||||||
| gnd_outdoors | B4D9 | LD B,$05 | Set B for five iterations | |||||||
| B4DB | LD HL,$F05D | Point HL at the locked door indices | ||||||||
|
Start loop
|
||||||||||
| gnd_outdoors_loop | B4DE | LD A,(HL) | Fetch the door index and door_LOCKED flag | |||||||
| B4DF | AND $7F | Mask off door_LOCKED flag to get the door index alone | ||||||||
| B4E1 | EXX | Switch register banks for this iteration | ||||||||
| B4E2 | CALL get_door | Turn a door index into a door_t pointer in HL | ||||||||
| B4E5 | PUSH HL | Preserve the door_t pointer | ||||||||
| B4E6 | CALL door_in_range | Call door_in_range. C is clear if it's in range | ||||||||
| B4E9 | POP HL | Restore door_t pointer | ||||||||
| B4EA | JR NC,gnd_in_range | Jump forward if in range | ||||||||
| B4EC | INC HL | Advance HL to the next door_t | ||||||||
| B4ED | INC HL | |||||||||
| B4EE | INC HL | |||||||||
| B4EF | INC HL | |||||||||
| B4F0 | CALL door_in_range | Call door_in_range. C is clear if it's in range | ||||||||
| B4F3 | JR NC,gnd_in_range | Jump forward if in range | ||||||||
| B4F5 | EXX | Unbank | ||||||||
| B4F6 | INC HL | Advance to the next door index and flag in locked_doors | ||||||||
| B4F7 | DJNZ gnd_outdoors_loop | ...loop | ||||||||
| B4F9 | RET | Return with Z clear (from the INC HL above) (not found) | ||||||||
| gnd_in_range | B4FA | EXX | Unbank | |||||||
| B4FB | XOR A | Set Z flag (found) | ||||||||
| B4FC | RET | Return | ||||||||
|
Indoors.
Locked doors 2..8 include interior doors.
|
||||||||||
| gnd_indoors | B4FD | LD HL,$F05F | Point HL at the third locked door index | |||||||
|
Bug: Ought to be 7 iterations.
|
||||||||||
| B500 | LD B,$08 | Set B for eight iterations | ||||||||
|
Start loop
|
||||||||||
| gnd_indoors_loop | B502 | LD A,(HL) | Fetch the door index and door_LOCKED flag | |||||||
| B503 | AND $7F | Mask off door_LOCKED flag to get the door index alone | ||||||||
| B505 | LD C,A | Keep in C for use during the loop | ||||||||
|
Search interior doors for the door index in C.
|
||||||||||
| B506 | LD DE,$81D6 | Point DE at interior_doors | ||||||||
|
Start loop (inner)
|
||||||||||
| gnd_indoors_loop_2 | B509 | LD A,(DE) | Fetch an interior door index | |||||||
| B50A | CP $FF | Is it door_NONE? (end of list) | ||||||||
| B50C | JR Z,gnd_next | Jump if so | ||||||||
| B50E | AND $7F | Mask off door_REVERSE flag to get the door index alone | ||||||||
| B510 | CP C | Is it a locked door index? | ||||||||
| B511 | JR Z,gnd_found | Jump if so | ||||||||
| B513 | INC DE | Otherwise advance to the next interior door index | ||||||||
|
There's no termination condition here where you might expect a test to see if we've run out of doors, but since every room has at least one door it *must* find one.
|
||||||||||
| B514 | JR gnd_indoors_loop_2 | ...loop | ||||||||
|
Start loop
|
||||||||||
| gnd_next | B516 | INC HL | Advance to the next door index and flag in locked_doors | |||||||
| B517 | DJNZ gnd_indoors_loop | ...loop | ||||||||
| B519 | OR $01 | Clear the Z flag (not found) | ||||||||
| B51B | RET | Return | ||||||||
| gnd_found | B51C | LD A,(DE) | Fetch an interior door index | |||||||
| B51D | EXX | Switch register banks until we return | ||||||||
| B51E | CALL get_door | Turn a door index into a door_t pointer in HL | ||||||||
| B521 | INC HL | Advance door pointer to door.pos.x | ||||||||
| B522 | EX DE,HL | Move the door pointer into DE | ||||||||
| B523 | LD HL,$81A4 | Point HL at saved_pos_x | ||||||||
| B526 | LD B,$02 | Set B for two iterations (two axis) | ||||||||
|
Note: This treats saved_pos as an 8-bit quantity in a 16-bit container.
Start loop -- once for each axis
On each axis if ((door - 2) <= pos and (door + 3) >= pos) then we're good.
|
||||||||||
| get_nearest_door_0 | B528 | LD A,(DE) | Fetch door.pos.x/y | |||||||
| B529 | SUB $03 | Compute the lower bound by subtracting 3 | ||||||||
| B52B | CP (HL) | Is lower bound >= saved_pos_x/y? | ||||||||
| B52C | JR NC,gnd_exx_next | Jump if so (out of bounds - try the next door) | ||||||||
| B52E | ADD A,$06 | Compute the upper bound by adding 6 | ||||||||
| B530 | CP (HL) | Is upper bound < saved_pos_x/y? | ||||||||
| B531 | JR C,gnd_exx_next | Jump if so (out of bounds - try the next door) | ||||||||
| B533 | INC HL | Advance to the next saved_pos axis | ||||||||
| B534 | INC HL | |||||||||
| B535 | INC DE | Advance to the next door.pos axis | ||||||||
| B536 | DJNZ get_nearest_door_0 | ...loop | ||||||||
|
If we arrive here then we're within the bounds
|
||||||||||
| B538 | EXX | Switch back | ||||||||
| B539 | XOR A | Set Z flag (found) | ||||||||
| B53A | RET | Return | ||||||||
| gnd_exx_next | B53B | EXX | Switch back | |||||||
| B53C | JR gnd_next | ...loop | ||||||||
| Prev: B4B8 | Up: Map | Next: B53E |