Prev: 55268 Up: Map Next: 56383
55524: Test Group Objects
Used by the routine at TestEntityCells.
Finds the group of objects at a cell of the level with FindGroup and then tests the entity against each of the objects, which are three bytes each. The low five bits of the group header are the number of objects. Objects of type 132 134 and 6 are skipped. A solid block stops the entity. Type 129 is a bottle and is collected with CollectBottle. Type 133 sets bit 1 of ExitMessageFlag, the exit-closed message, while BottlesLeft is not zero. A type 131 and a type 133 once no bottles are left, is solid: the entity is pushed back to the edge and FindPathAtPosition looks for a path there. Other objects are matched with TestObjectMatch. The smaller gap is kept in field 31 and bit 6 of the flags is cleared. Purpose of that gap is not yet known.
Input
HL The position of the cell
IX The entity
TestGroupObjects 55524 LD (23737),HL Remember the cell position.
55527 CALL FindGroup Find the group of objects.
55530 RET C Return if this cell has no group.
55531 LD (23772),DE Remember the cell offset.
55535 INC D Advance the high byte of the cell offset.
55536 LD A,(IY+0) Read the group header.
55539 AND %00011111 Keep the object count.
55541 LD B,A Keep the object count aside.
55542 INC IY Step on to the first object.
55544 INC IY
55546 AND %00010000 Test bit 4, which the count mask has already cleared.
55548 JR Z,TestGroupObjects_Loop Skip the extra step. This jump is always taken.
55550 INC IY Step on another byte. This is not reached.
TestGroupObjects_Loop 55552 INC IY Advance to the type byte of the object.
55554 PUSH BC Remember the object count.
55555 LD A,(IY+1) Read the type byte.
55558 AND %10001111 Keep the type bits.
55560 CP 132 Skip an object of type 132.
55562 JP Z,TestGroupObjects_Next
55565 CP 134 Skip an object of type 134.
55567 JP Z,TestGroupObjects_Next
55570 CP 6 Skip an object of type 6.
55572 JP Z,TestGroupObjects_Next
55575 RLA Move bit 7 of the type into the carry flag.
55576 JR NC,TestGroupObjects_Player Test the object when that bit is clear.
55578 AND %00011110 Keep the shifted type bits.
55580 CP 30 Skip an object whose shifted type is 30.
55582 JP Z,TestGroupObjects_Next
TestGroupObjects_Player 55585 LD A,(IX+0) On any other frame, or for any entity but the player, test the block below.
55588 DEC A
55589 JP NZ,TestGroupObjects_Block
55592 LD A,(41693) Read the frame counter.
55595 AND %00000111 Act on every eighth frame.
55597 JP NZ,TestGroupObjects_Block Leave this path on the other frames.
55600 LD A,(IY+1) Read the type byte again.
55603 ADD A,3 Add three to the type.
55605 AND %10000100 Use bits 2 and 7 of the adjusted type.
55607 CP 132 Match the object when the result is 132.
55609 CALL Z,TestObjectMatch
Build the object's x range from its first and third bytes, then test it against the x coordinate. A type of 130 uses a fixed size of 8.
TestGroupObjects_Block 55612 LD HL,(23736) Fetch the word at TitleAnimationFrame.
55615 LD A,(IY+0) Read the first byte of the object.
55618 AND %11110000 Keep the high nibble as the low byte of the range.
55620 LD L,A Keep that nibble as the low byte of the range.
55621 LD A,(IY+2) Read the third byte of the object.
55624 ADD A,A Shift that byte up by four bits.
55625 ADD A,A
55626 ADD A,A
55627 ADD A,A
55628 AND %01110000 Use bits 4-6 as the size.
55630 ADD A,16 Add the base size of 16.
55632 LD C,A Keep the size.
55633 LD D,(IX+2) Fetch the x coordinate.
55636 LD E,(IX+3)
55639 LD A,(IY+1) Read the type byte.
55642 INC A Advance the type.
55643 AND %10000110 Use bits 1, 2 and 7.
55645 CP 130 Keep this size unless the type is 130.
55647 JR NZ,TestGroupObjects_XRange
55649 SET 2,L Mark the fixed-size object.
55651 LD C,8 Use a size of 8.
TestGroupObjects_XRange 55653 LD (55015),DE Pass the x coordinate to the overlap test.
55657 LD (55012),HL Pass the object's x range to the overlap test.
55660 LD B,(IX+11) Fetch the x extent.
55663 CALL TestRangeOverlap Test the two x ranges.
55666 JP NC,TestGroupObjects_Next Skip the object when the x ranges do not overlap.
55669 LD (56783),HL Remember the x overlap.
55672 INC IX Point the entity one byte on, so the y fields line up.
Build the object's y range in the same way, and test it against the y coordinate. IX still addresses the byte after the type, so a displacement reads the following field.
55674 LD HL,(23737) Fetch the cell position again.
55677 LD A,(IY+0) Read the first byte of the object.
55680 ADD A,A Shift it up by four bits.
55681 ADD A,A
55682 ADD A,A
55683 ADD A,A
55684 LD L,A Keep it as the low byte of the range.
55685 LD A,(IY+2) Read the third byte of the object.
55688 ADD A,A Double it.
55689 AND %01110000 Use bits 4-6 as the size.
55691 ADD A,16 Add the base size of 16.
55693 LD C,A Keep the size.
55694 LD D,(IX+4) Fetch the y coordinate.
55697 LD E,(IX+5)
55700 LD B,(IX+11) Fetch the y extent.
55703 LD A,(IY+1) Read the type byte.
55706 INC A Advance the type.
55707 AND %10000110 Use bits 1, 2 and 7.
55709 CP 130 Keep this size unless the type is 130.
55711 JR NZ,TestGroupObjects_YRange
55713 SET 2,L Mark the fixed-size object.
55715 LD C,8 Use a size of 8.
TestGroupObjects_YRange 55717 LD (55032),DE Pass the y coordinate to the overlap test.
55721 LD (55029),HL Pass the object's y range to the overlap test.
55724 CALL TestRangeOverlap Test the two y ranges.
55727 DEC IX Restore the entity address.
55729 JP NC,TestGroupObjects_Next Skip the object when the y ranges do not overlap.
55732 LD (56785),HL Remember the y overlap.
Compare the z coordinate with the object, and remember the smaller gap in field 31.
55735 LD H,(IX+8) Fetch the z coordinate.
55738 LD L,(IX+9)
55741 LD (54998),HL Pass the z coordinate to the edge test.
55744 LD A,(IY+1) Read the object's type.
55747 LD C,A Keep the type aside.
55748 AND %00001111 Use the low nibble of the type.
55750 LD L,A Keep it as the low byte of the index.
55751 LD A,C Bring bit 4 of the type down beside it.
55752 RRA
55753 RRA
55754 RRA
55755 AND %00010000 Use that bit.
55757 OR L Combine it with the low nibble.
55758 LD E,A
55759 LD HL,55219 Look this kind up in the object flags.
55762 CALL AddToAddress
55765 LD A,(HL) Read the flag byte.
55766 LD (23768),A Remember the object's flags.
55769 LD HL,(23772) Fetch the cell offset.
55772 INC H Advance its high byte.
55773 LD A,C Take the type again.
55774 AND %01110000 Use bits 4-6 as a row within the group.
55776 ADD A,L Add that row to the cell offset.
55777 LD L,A
55778 LD (54991),HL Pass the address to the edge test.
TestGroupObjects_Heights 55781 LD C,0 Start with no extra height.
55783 LD A,E A kind of 2 has no extra height.
55784 CP 2
55786 JR Z,TestGroupObjects_Overlap
55788 LD A,(IY+2) Read the third byte of the object.
55791 RRA Shift it down by two.
55792 RRA
55793 AND %00110000 Use bits 4-5 of that byte.
55795 JR NZ,TestGroupObjects_AddHeight Use the looked-up height when those bits are set.
55797 BIT 7,(IY+1) Jump to TestGroupObjects_AddHeight to use the looked-up height when the top bit is clear.
55801 JR Z,TestGroupObjects_AddHeight
55803 PUSH HL Look up a height for this kind.
55804 LD HL,55252
55807 LD A,E
55808 AND %00001111 Use the low nibble of the kind.
55810 CALL AddToAddress Look the height up.
55813 LD A,(HL) Read the height.
55814 POP HL Restore the address and use that height.
55815 JR TestGroupObjects_Height
TestGroupObjects_AddHeight 55817 ADD A,16 Add 16 to the height.
TestGroupObjects_Height 55819 LD C,A Keep the height.
The entity is only touching the block when half of either extent, less two, still covers the overlap. A deeper overlap on both axes means the entity is inside the block.
TestGroupObjects_Overlap 55820 LD A,4 Mark the entity as only touching the block.
55822 LD (56652),A
55825 LD A,(56783) Fetch the x overlap.
55828 LD B,A Keep it.
55829 LD A,(IX+11) Compare half the x extent, less two, with the overlap.
55832 SRL A
55834 SUB 2
55836 CP B
55837 JP NC,TestGroupObjects_ZRange
55840 LD A,(56785) Compare half the y extent, less two, with the overlap.
55843 LD B,A
55844 LD A,(IX+12)
55847 SRL A
55849 SUB 2
55851 CP B
55852 JP NC,TestGroupObjects_ZRange
55855 XOR A The entity is inside the block, so clear the touching flag.
55856 LD (56652),A
55859 PUSH HL Remember the edge address.
55860 LD A,(23768) Read the object's flags.
55863 RLA Compare the z coordinate directly when the top flag is clear.
55864 JR C,TestGroupObjects_Raised
55866 LD B,0 Add the overlap to the edge address.
55868 ADD HL,BC
55869 EX DE,HL
55870 LD H,(IX+8) Fetch the z coordinate.
55873 LD L,(IX+9)
55876 XOR A Subtract the edge.
55877 SBC HL,DE
55879 JR C,TestGroupObjects_Vertical Leave this object if the entity is below the edge.
55881 OR H Leave this object unless the result is within one page.
55882 JR NZ,TestGroupObjects_Vertical
55884 LD E,L The low byte is the gap.
55885 JR TestGroupObjects_SaveGap
TestGroupObjects_Raised 55887 EX DE,HL Compare the z coordinate with the z extent instead.
55888 LD H,(IX+8)
55891 LD L,(IX+9)
55894 PUSH BC
55895 LD B,0
55897 LD A,(IX+13)
55900 ADD A,6
55902 LD C,A
55903 ADD HL,BC
55904 SBC HL,DE
55906 POP BC
55907 JR C,TestGroupObjects_Vertical
55909 CALL TestWideOverlap Test a wide block.
55912 LD A,(23768) Read the object's flags.
55915 AND %01100000 Use the layout in bits 5-6.
55917 JR Z,TestGroupObjects_Gap No further height test when the layout is clear.
55919 CP 64 A layout of 64 ends the height test.
55921 JR NZ,TestGroupObjects_SaveGap
TestGroupObjects_Gap 55923 LD A,E Reduce the gap by four, and ignore a gap below four.
55924 SUB 4
55926 LD E,0
55928 JR C,TestGroupObjects_SaveGap
55930 LD E,A Keep the reduced gap.
55931 POP HL Keep the smaller of the gap and the room above the entity.
55932 PUSH HL
55933 PUSH DE
55934 LD B,0
55936 ADD HL,BC
55937 EX DE,HL
55938 XOR A
55939 LD H,(IX+8)
55942 LD L,(IX+9)
55945 SBC HL,DE
55947 POP DE
55948 JR C,TestGroupObjects_SaveGap
55950 LD A,L
55951 CP E
55952 JR C,TestGroupObjects_SaveGap
55954 LD E,L
TestGroupObjects_SaveGap 55955 LD A,(IX+31) Fetch the gap already stored for this entity.
55958 CP E Keep the stored gap when it is the smaller one.
55959 JR C,TestGroupObjects_Vertical
55961 LD (IX+31),E Remember this smaller gap.
55964 RES 6,(IX+30) Clear bit 6 of the flags.
Test the z range. The vertical speed is put back afterwards, and a stand-in value of 24 is used for the test.
TestGroupObjects_Vertical 55968 POP HL Restore the edge address.
TestGroupObjects_ZRange 55969 LD B,(IX+18) Fetch the vertical speed.
55972 PUSH BC Remember it.
55973 LD B,(IX+13) Fetch the z extent.
55976 PUSH IX Remember the entity.
55978 LD DE,65530 Move back to the byte the test reads.
55981 ADD IX,DE
55983 LD (IX+24),0 Plant 24 for the test.
55987 LD DE,(54998) Fetch the z coordinate passed to the test.
55991 CALL TestRangeOverlap Test the z range.
55994 POP IX Restore the entity.
55996 POP BC Bring the vertical speed back.
55997 LD (IX+18),B Restore the vertical speed.
56000 JP NC,TestGroupObjects_Next Leave this object when the z ranges do not overlap.
56003 BIT 7,(IX+30) Test whether the entity is moving fast.
56007 JR Z,TestGroupObjects_Positive The overlap is ordinary when the entity is not fast.
56009 BIT 7,H Test the sign of the result.
56011 JR NZ,TestGroupObjects_ZOverlap A negative result keeps the low byte.
56013 LD L,255 Force the low byte to 255.
56015 JR TestGroupObjects_ZOverlap Join the stored overlap.
TestGroupObjects_Positive 56017 BIT 7,H Test the sign of the result.
56019 JR NZ,TestGroupObjects_ZOverlap A negative result is stored as it is.
56021 INC L Raise a positive overlap by two.
56022 INC L
TestGroupObjects_ZOverlap 56023 DEC L Reduce the overlap by one.
56024 LD (56787),HL Remember the z overlap.
56027 LD A,(IY+1) Read the object's type.
56030 AND %10001111 Use the type bits that select a solid block.
56032 CP 131 A type 131 is solid.
56034 JP Z,TestGroupObjects_Solid
56037 CP 133 A type other than 133 is handled below.
56039 JR NZ,TestGroupObjects_Handle
56041 LD A,(57056) Read how many bottles are left.
56044 AND A A type 133 is solid once no bottles are left.
56045 JP Z,TestGroupObjects_Solid
TestGroupObjects_Handle 56048 LD A,(23768) Read the object's flags.
56051 RLA Test the edge when the top flag is set.
56052 CALL C,TestEdgeOverlap
56055 XOR A Clear the handled flag.
56056 LD (54692),A
56059 LD A,(23768) Read the flags again.
56062 INC A Handle the overlap unless the flags were 255.
56063 CALL NZ,HandleOverlap
56066 LD A,(IX+0) Only the player is placed against the block.
56069 DEC A
56070 JP NZ,TestGroupObjects_Special
56073 LD A,(41693) Read the frame counter.
56076 AND 7 Only on every eighth frame.
56078 JP NZ,TestGroupObjects_Special
56081 LD A,(IY+1) Read the object's type.
56084 AND %10001110 Use bits 1, 2, 3 and 7 of the type.
56086 CP 2 Only a type whose remaining bits are 2 places the player.
56088 JP NZ,TestGroupObjects_Special
56091 LD A,(54692) Read the handled flag.
56094 AND A Leave the placement when the flag is clear.
56095 JP Z,TestGroupObjects_Special
56098 LD A,(IX+31) Read the stored gap.
56101 AND A Leave the placement when a gap is already stored.
56102 JP NZ,TestGroupObjects_Special
56105 LD DE,(55015) Fetch the x edge passed to the overlap test.
56109 DEC DE Step that edge back by two.
56110 DEC DE
56111 LD HL,(55012) Fetch the other x edge.
56114 AND A Keep the first edge when it is the nearer.
56115 SBC HL,DE
56117 JR C,TestGroupObjects_XEdge
56119 LD DE,(55012) Otherwise use the other edge.
TestGroupObjects_XEdge 56123 LD A,E Keep the column of that edge.
56124 AND 240
56126 LD E,A
56127 LD (58566),DE Remember it as the position to match.
56131 LD DE,(55032) Fetch the y edge passed to the overlap test.
56135 DEC DE Step that edge back by two.
56136 DEC DE
56137 LD HL,(55029) Fetch the other y edge.
56140 AND A Keep the first edge when it is the nearer.
56141 SBC HL,DE
56143 JR C,TestGroupObjects_YEdge
56145 LD DE,(55029) Otherwise use the other edge.
TestGroupObjects_YEdge 56149 LD A,E Keep the column of that edge.
56150 AND 240
56152 LD E,A
56153 LD (58568),DE Remember it as the other position to match.
56157 LD DE,(46408) Remember the player's height for the match.
56161 LD (58570),DE
56165 JP TestGroupObjects_Special Go on to the bottle and the exit.
A solid block matches the object, raises the entity by one, and pushes it back to the edge. If it is still inside, the position is set from both edges and FindPathAtPosition looks for a path there.
TestGroupObjects_Solid 56168 CALL TestObjectMatch Match the object.
56171 LD H,(IX+8) Fetch the z coordinate.
56174 LD L,(IX+9)
56177 INC HL Raise the entity by one.
56178 LD (IX+8),H
56181 LD (IX+9),L
56184 LD A,(56652) Read the touching flag.
56187 AND A Leave this object when the entity was only touching.
56188 JR NZ,TestGroupObjects_Special
56190 LD DE,(55012) Fetch an x edge.
56194 INC E Step that edge on by three.
56195 INC E
56196 INC E
56197 LD HL,(55015) Fetch the other x edge.
56200 PUSH HL Turn that edge into a coordinate.
56201 POP BC
56202 AND A Subtract the stepped edge.
56203 SBC HL,DE
56205 BIT 7,H Jump to TestGroupObjects_PushX to push the entity the other way when the difference is negative.
56207 JR NZ,TestGroupObjects_PushX
56209 DEC BC Step the edge back.
56210 LD (IX+2),B Move the x coordinate back to that edge.
56213 LD (IX+3),C
56216 LD BC,5 Step the difference back by five.
56219 SBC HL,BC
56221 JR TestGroupObjects_TryY
TestGroupObjects_PushX 56223 INC BC Step the edge on.
56224 LD (IX+2),B Move the x coordinate on to that edge.
56227 LD (IX+3),C
56230 LD BC,4 Step the difference on by four.
56233 ADD HL,BC
TestGroupObjects_TryY 56234 JR NC,TestGroupObjects_Special Leave this object when the x push was enough.
56236 PUSH DE Remember the y edge.
56237 LD DE,(55029) Fetch a y edge.
56241 INC E Step that edge on by three.
56242 INC E
56243 INC E
56244 LD HL,(55032) Fetch the other y edge.
56247 PUSH HL Turn that edge into a coordinate.
56248 POP BC
56249 AND A Subtract the stepped edge.
56250 SBC HL,DE
56252 BIT 7,H Jump to TestGroupObjects_PushY to push the entity the other way when the difference is negative.
56254 JR NZ,TestGroupObjects_PushY
56256 DEC BC Step the edge back.
56257 LD (IX+5),B Move the y coordinate back to that edge.
56260 LD (IX+6),C
56263 LD BC,5 Step the difference back by five.
56266 SBC HL,BC
56268 JR TestGroupObjects_Place
TestGroupObjects_PushY 56270 INC BC Step the edge on.
56271 LD (IX+5),B Move the y coordinate on to that edge.
56274 LD (IX+6),C
56277 LD BC,4 Step the difference on by four.
56280 ADD HL,BC
TestGroupObjects_Place 56281 POP BC Restore the saved edge.
56282 JR NC,TestGroupObjects_Special Leave this object when the y push was enough.
56284 LD (IX+2),B Place the entity on both saved edges.
56287 LD (IX+3),C
56290 LD (IX+5),D
56293 LD (IX+6),E
56296 PUSH IY Remember the object.
56298 CALL FindPathAtPosition Find the path at this position.
56301 POP IY Restore the object.
A type 133 object shows the exit-closed message for the player while bottles remain. A type 129 object is a bottle.
TestGroupObjects_Special 56303 LD A,(IY+1) Read the type byte.
56306 AND %10001111 Keep the type bits.
56308 CP 133 Try a bottle unless the type is 133.
56310 JR NZ,TestGroupObjects_Bottle
56312 LD A,(57056) Read how many bottles are left.
56315 AND A Leave the message alone when no bottles are left.
56316 JR Z,TestGroupObjects_Next
56318 LD A,(IX+0) Show the message for the player only.
56321 DEC A
56322 JP NZ,TestGroupObjects_Next
56325 LD A,(52825) Read the exit message flag.
56328 OR %00000010 Set the exit-closed bit.
56330 LD (52825),A Update the exit message flag.
56333 JP TestGroupObjects_Next Go on to the next object.
TestGroupObjects_Bottle 56336 CP 129 Leave any object that is not a bottle.
56338 JR NZ,TestGroupObjects_Next
56340 LD A,(IX+0) Collect a bottle for the player only.
56343 DEC A
56344 JR NZ,TestGroupObjects_Next
56346 LD A,(56652) Leave the bottle if the flag at 56652 is clear.
56349 AND A
56350 JR NZ,TestGroupObjects_Next
56352 LD A,(54692) Leave the bottle if the flag at 54692 is set.
56355 AND A
56356 JR Z,TestGroupObjects_Next
56358 PUSH IX Collect the bottle, keeping the entity and the object.
56360 PUSH IY
56362 PUSH IY
56364 POP IX
56366 CALL CollectBottle
56369 POP IY
56371 POP IX
TestGroupObjects_Next 56373 INC IY Advance to the next object.
56375 INC IY
56377 POP BC Restore the object count.
56378 DEC B Take the next object until every object has been tested.
56379 JP NZ,TestGroupObjects_Loop
56382 RET Return.
Prev: 55268 Up: Map Next: 56383