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 |