diff options
author | Marcus Huderle <huderlem@gmail.com> | 2021-05-03 20:34:08 -0500 |
---|---|---|
committer | Marcus Huderle <huderlem@gmail.com> | 2021-05-03 20:34:08 -0500 |
commit | 22964879cfadf73916e27c219fc52001f773c144 (patch) | |
tree | 0e6a64100d5fd895eaa67601116a45076b943f45 | |
parent | 01ba6dc960b7b5f08f6f599a1d7ecc52d4260359 (diff) |
Document stage collision handling logic
-rw-r--r-- | engine/pinball_game/ball_init/ball_init.asm | 4 | ||||
-rw-r--r-- | engine/pinball_game/flippers.asm | 32 | ||||
-rw-r--r-- | engine/pinball_game/slot.asm | 4 | ||||
-rw-r--r-- | home.asm | 266 | ||||
-rw-r--r-- | wram.asm | 21 |
5 files changed, 184 insertions, 143 deletions
diff --git a/engine/pinball_game/ball_init/ball_init.asm b/engine/pinball_game/ball_init/ball_init.asm index e545c00..e56d43a 100644 --- a/engine/pinball_game/ball_init/ball_init.asm +++ b/engine/pinball_game/ball_init/ball_init.asm @@ -13,9 +13,9 @@ InitBallForStage: ; 0x83ba ld [wBallYVelocity], a
ld [wBallYVelocity + 1], a
ld [wd7ae], a
- ld [wd7af], a
+ ld [wLeftFlipperState], a
ld [wd7b2], a
- ld [wd7b3], a
+ ld [wRightFlipperState], a
ld [wd7b0], a
ld [wd7b1], a
ld [wd7b4], a
diff --git a/engine/pinball_game/flippers.asm b/engine/pinball_game/flippers.asm index 57475e4..20e9686 100644 --- a/engine/pinball_game/flippers.asm +++ b/engine/pinball_game/flippers.asm @@ -13,9 +13,9 @@ HandleFlippers: ; 0xe0fe Func_e118: ; 0xe118
call PlayFlipperSoundIfPressed
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
ld [wLeftFlipperAnimationState], a
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
ld [wRightFlipperAnimationState], a
ld hl, wKeyConfigLeftFlipper
call IsKeyPressed2
@@ -26,7 +26,7 @@ Func_e118: ; 0xe118 jr nz, .asm_e13b
ld hl, $0333
.asm_e13b
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
and a
jr nz, .asm_e145
bit 7, h
@@ -45,7 +45,7 @@ Func_e118: ; 0xe118 ld [wd7b1], a
ld a, [wd7ae]
ld c, a
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
ld b, a
add hl, bc
bit 7, h
@@ -62,7 +62,7 @@ Func_e118: ; 0xe118 ld a, l
ld [wd7ae], a
ld a, h
- ld [wd7af], a
+ ld [wLeftFlipperState], a
ld hl, wKeyConfigRightFlipper
call IsKeyPressed2
ld hl, -$0333
@@ -72,7 +72,7 @@ Func_e118: ; 0xe118 jr nz, .asm_e18e
ld hl, $0333
.asm_e18e
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
and a
jr nz, .asm_e198
bit 7, h
@@ -91,7 +91,7 @@ Func_e118: ; 0xe118 ld [wd7b4 + 1], a
ld a, [wd7b2]
ld c, a
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
ld b, a
add hl, bc
bit 7, h
@@ -108,7 +108,7 @@ Func_e118: ; 0xe118 ld a, l
ld [wd7b2], a
ld a, h
- ld [wd7b3], a
+ ld [wRightFlipperState], a
ret
PlayFlipperSoundIfPressed: ; 0xe1ce
@@ -152,7 +152,7 @@ CheckLeftFlipperCollision: inc c
ld a, [wLeftFlipperAnimationState]
ld [$ffc2], a
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
ld [$ffc3], a
call ReadFlipperCollisionAttributes
ld a, [wFlipperCollision]
@@ -186,7 +186,7 @@ CheckRightFlipperCollision: ; 0xe226 inc c
ld a, [wRightFlipperAnimationState]
ld [$ffc2], a
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
ld [$ffc3], a
call ReadFlipperCollisionAttributes
ld a, [wFlipperCollision]
@@ -603,11 +603,11 @@ HandleFlipperCollision: ; 0xe442 ld a, $1
ld [wIsBallColliding], a
xor a
- ld [wBallPositionPointerOffsetFromStageTopLeft], a
- ld [wBallPositionPointerOffsetFromStageTopLeft + 1], a
+ ld [wBallPositionTileOffset], a
+ ld [wBallPositionTileOffset + 1], a
ld [wCurCollisionAttribute], a
- ld [wd7f6], a
- ld [wd7f7], a
+ ld [wCurCollisionTileOffset], a
+ ld [wCurCollisionTileOffset + 1], a
ld a, [hFlipperYCollisionAttribute]
sla a
ld c, a
@@ -666,7 +666,7 @@ DrawFlippers: ; 0xe4a1 ld c, a
push hl
ld hl, LeftFlipperOAMIds
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
ld e, a
ld d, $0
add hl, de
@@ -698,7 +698,7 @@ DrawFlippers: ; 0xe4a1 sub e
ld c, a
ld hl, RightFlipperOAMIds
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
ld e, a
ld d, $0
add hl, de
diff --git a/engine/pinball_game/slot.asm b/engine/pinball_game/slot.asm index 232afcf..67e0bf8 100644 --- a/engine/pinball_game/slot.asm +++ b/engine/pinball_game/slot.asm @@ -28,10 +28,10 @@ Func_ed8e: ; 0xed8e call UpdateBottomText
call CleanOAMBuffer
rst AdvanceFrame
- ld a, [wd7af]
+ ld a, [wLeftFlipperState]
and a
jr nz, .asm_edac
- ld a, [wd7b3]
+ ld a, [wRightFlipperState]
and a
jr nz, .asm_edac
ld a, [hGameBoyColorFlag]
@@ -2644,47 +2644,50 @@ SetBallVelocity: ; 0x22a7 CheckStageCollision: ; 0x22b5 ld a, [wBallXPos + 1] - sub $4 + sub 4 push af and $7 ld [wSubTileBallXPos], a ; sub-tile position pop af and $f8 - ld c, a + ld c, a ; c = tile x pos ld a, [wBallYPos + 1] - sub $4 + sub 4 push af and $7 ld [wSubTileBallYPos], a pop af and $f8 - ld b, a + ld b, a ; b = tile y pos ld l, b ; bc contains tile coords of ball position + ; Calculate the tile offset for the ball's position, as if the + ; board was composed of a 1D array starting from the top-left + ; going left-to-right. ld h, $0 sla l rl h sla l - rl h ; b was multiplied by 4 (y tile position) + rl h ; b was multiplied by 4 ((y tile) * 32) srl c srl c - srl c ; c was divided by 8 (x tile position) + srl c ; c was divided by 8 (x tile) ld b, $0 add hl, bc ld a, l - ld [wBallPositionPointerOffsetFromStageTopLeft], a + ld [wBallPositionTileOffset], a ld a, h - ld [wBallPositionPointerOffsetFromStageTopLeft + 1], a + ld [wBallPositionTileOffset + 1], a ld a, [wStageCollisionMapPointer] ld c, a ld a, [wStageCollisionMapPointer + 1] ld b, a - add hl, bc ; hl = address of upper-left collision byte + add hl, bc ; hl = address of ball tile's collision attribute ld a, [hLoadedROMBank] push af ld a, [wStageCollisionMapBank] ld [hLoadedROMBank], a ld [MBC5RomBank], a - ld bc, $001f ; number of tiles wide - 1 + ld bc, 32 - 1 ; stage's number of tiles wide - 1 ld a, [hli] ld [wUpperLeftCollisionAttribute], a ld a, [hl] @@ -2705,16 +2708,16 @@ CheckStageCollision: ; 0x22b5 ld a, [wSubTileBallXPos] sla a ld c, a - ld b, $0 - ld hl, SubTileXPos_CollisionDataPointers + ld b, 0 + ld hl, CollisionTests add hl, bc ld e, [hl] inc hl ld d, [hl] ld a, [wSubTileBallYPos] ld c, a - ld b, $10 ; number of times to loop over .asm_233d -.asm_233d + ld b, 16 ; length of wCollisionPointTests +.testCollisionPointLoop push bc ld a, [de] inc de @@ -2728,18 +2731,23 @@ CheckStageCollision: ; 0x22b5 ld hl, wUpperLeftCollisionAttribute add hl, bc ld a, [hl] - call Func_248a - jr nc, .asm_235e + call TryLoadSpecialCollisionMask + jr nc, .staticMask + ; Load the special mask pointer. + ; hl = pointer to array of collision masks. pop af and $7 ld c, a ld b, $0 add hl, bc - jr .asm_237b + jr .testCollisionPoint -.asm_235e +.staticMask ld c, a - ld b, $0 + ld b, $0 ; bc = static collision mask id + ; Multiply bc by 8. Each collision mask is an + ; 8x8-tile of 1-bit-per-pixel data. Therefore, + ; each collision mask tile is 8 bytes. sla c rl b sla c @@ -2750,13 +2758,14 @@ CheckStageCollision: ; 0x22b5 ld a, [hli] ld h, [hl] ld l, a - add hl, bc + add hl, bc ; hl = pointer to collision mask tile pop af - and $7 + and $7 ; a = y subtile offset ld c, a ld b, $0 add hl, bc -.asm_237b +.testCollisionPoint + ; hl = pointer to the collision mask row for the y position ld a, [de] inc de and [hl] @@ -2764,20 +2773,20 @@ CheckStageCollision: ; 0x22b5 ld a, [de] inc de ld c, a - ld hl, wd7c9 + ld hl, wCollisionPointTests add hl, bc pop af ld [hl], a pop bc dec b - jr nz, .asm_233d + jr nz, .testCollisionPointLoop pop af ld [hLoadedROMBank], a ld [MBC5RomBank], a - ld hl, wd7c9 + ld hl, wCollisionPointTests ld de, wd7d9 - ld b, $4 -.asm_239a + ld b, 4 +.copyLoop ld a, [hli] ld [de], a inc de @@ -2791,44 +2800,47 @@ CheckStageCollision: ; 0x22b5 ld [de], a inc de dec b - jr nz, .asm_239a - ld hl, wd7c9 + jr nz, .copyLoop + ld hl, wCollisionPointTests ld de, $0000 - ld b, $0 + ld b, 0 ld a, [hl] and a - jr z, .asm_23c1 -.asm_23b5 + jr z, .findNextCollisionPoint +.findNextCollisionPoint2 + ; This loop is nearly identical to .findNextCollisionPoint + ; It exists to handle the improbable (impossible?) event that + ; the ball could be completely inside a collision wall. ld a, [hli] inc b and a - jr z, .asm_23c1 + jr z, .findNextCollisionPoint ld a, b - cp $11 - jr nc, .asm_23ee - jr .asm_23b5 + cp 16 + 1 + jr nc, .determinedCollisionStatus + jr .findNextCollisionPoint2 -.asm_23c1 +.findNextCollisionPoint ld a, [hli] inc b and a - jr nz, .asm_23cd + jr nz, .handleCollisionPoint ld a, b - cp $11 - jr nc, .asm_23ee - jr .asm_23c1 + cp 16 + 1 + jr nc, .determinedCollisionStatus + jr .findNextCollisionPoint -.asm_23cd +.handleCollisionPoint push de ld d, $1 ld c, b dec c -.asm_23d2 +.findNextFailedCollisionPoint ld a, [hli] inc b inc d and a - jr nz, .asm_23d2 + jr nz, .findNextFailedCollisionPoint dec d ld a, b dec a @@ -2836,18 +2848,21 @@ CheckStageCollision: ; 0x22b5 and $f swap c or c - ld c, a - ld a, d + ld c, a ; c = (index of first collision point << 8) | (index of last consecutive collision point) + ld a, d ; d = number of consecutive successful collision points cp e pop de - jr c, .asm_23e9 - ld e, a - ld d, c -.asm_23e9 + jr c, .updatedMaxConsecutivePoints + ld e, a ; e = max number of consecutive successful collision points + ld d, c ; d = (index of first collision point << 8) | (index of last consecutive collision point) +.updatedMaxConsecutivePoints ld a, b - cp $10 - jr c, .asm_23c1 -.asm_23ee + cp 16 + jr c, .findNextCollisionPoint +.determinedCollisionStatus + ; e = maximum number of consecutive successful collision points + ; d = the start and last index of that consecutive string of collision points (wCollisionPointTests) + ; the hi nybble is the start index, lo nybble is the end index ld a, e ld [wIsBallColliding], a and a @@ -2858,12 +2873,17 @@ CheckStageCollision: ; 0x22b5 ld [hLoadedROMBank], a ld [MBC5RomBank], a push de + ; Based on the start and end collision point indices, look + ; up the corresponding normal angle for them. ld e, d - ld d, $0 + ld d, 0 ld hl, CollisionForceAngles add hl, de ld a, [hl] ld [wCollisionNormalAngle], a + ; Again, based on the start and end collision point indices, apply + ; position offsets to position the ball safely outside of the wall + ; it collided with. sla e rl d ld hl, CollisionYDeltas @@ -2895,73 +2915,84 @@ CheckStageCollision: ; 0x22b5 ld a, d and $f sub e - jr nc, .asm_2449 - add $10 -.asm_2449 + jr nc, .loadTestPointOffsets + add 16 +.loadTestPointOffsets + ; e = start index of consecutive collision points + ; a = length of consecutive collision points + ; The rest of the code here determines which of + ; the collision mask tiles was the one that triggered + ; the collision. It can be multiple tiles, so it uses + ; first collision test point that was colliding. Then, + ; that tile's collision attribute is saved in wCurCollisionAttribute. add e add e inc a and $1e ld c, a - ld b, $0 - ld hl, SubTileBallPosDeltas + ld b, 0 + ld hl, BallCollisionTestPointOffsets add hl, bc ld a, [wSubTileBallXPos] - add $4 + add 4 add [hl] bit 3, a ld c, b - jr z, .asm_2462 - ld c, $2 -.asm_2462 + jr z, .checkY + ld c, 2 +.checkY ld a, [wSubTileBallYPos] - add $4 + add 4 inc hl add [hl] bit 3, a - jr z, .asm_246e + jr z, .saveCollisionAttribute inc c -.asm_246e +.saveCollisionAttribute ld hl, wUpperLeftCollisionAttribute add hl, bc ld a, [hl] ld [wCurCollisionAttribute], a ld hl, BallPositionPointerOffsetDeltas add hl, bc - ld a, [wBallPositionPointerOffsetFromStageTopLeft] + ld a, [wBallPositionTileOffset] add [hl] - ld [wd7f6], a - ld a, [wBallPositionPointerOffsetFromStageTopLeft + 1] - adc $0 - ld [wd7f7], a + ld [wCurCollisionTileOffset], a + ld a, [wBallPositionTileOffset + 1] + adc 0 + ld [wCurCollisionTileOffset + 1], a ret -Func_248a: ; 0x248a +TryLoadSpecialCollisionMask: ; 0x248a +; If it's a special collision mask attribute, load the +; pointer to its mask and set the carry flag. +; If it's a regular static collision mask attribute, simply +; reset the carry flag and don't return anything. push af ld a, [wCurrentStage] bit 0, a - jr nz, .asm_2495 + jr nz, .bottomStage pop af and a ret -.asm_2495 +.bottomStage pop af cp $d0 ccf ret nc cp $e0 - jr nc, .asm_24ab + jr nc, .notAnimatedMonCollision sub $d0 sla a sla a sla a ld l, a - ld h, $c4 + ld h, (wMonAnimatedCollisionMask >> 8) scf ret -.asm_24ab +.notAnimatedMonCollision push de sub $e0 ld b, a @@ -2970,20 +3001,20 @@ Func_248a: ; 0x248a jr nc, .bonusStage bit 4, b ld hl, BottomLeftCollisionMasks - ld a, [wd7af] - jr z, .asm_24c8 + ld a, [wLeftFlipperState] + jr z, .checkFlipperPosition res 4, b ld hl, BottomRightCollisionMasks - ld a, [wd7b3] -.asm_24c8 + ld a, [wRightFlipperState] +.checkFlipperPosition ld de, $0080 - cp $7 - jr c, .asm_24d5 + cp 7 + jr c, .loadMaskPointer add hl, de - cp $e - jr c, .asm_24d5 + cp 14 + jr c, .loadMaskPointer add hl, de -.asm_24d5 +.loadMaskPointer ld e, b sla e sla e @@ -2996,20 +3027,20 @@ Func_248a: ; 0x248a .bonusStage bit 4, b ld hl, BottomLeftBonusStageCollisionMasks - ld a, [wd7af] - jr z, .asm_24f2 + ld a, [wLeftFlipperState] + jr z, .checkFlipperPosition2 res 4, b ld hl, BottomRightBonusStageCollisionMasks - ld a, [wd7b3] -.asm_24f2 + ld a, [wRightFlipperState] +.checkFlipperPosition2 ld de, $0080 - cp $7 - jr c, .asm_24ff + cp 7 + jr c, .loadMaskPointer2 add hl, de - cp $e - jr c, .asm_24ff + cp 14 + jr c, .loadMaskPointer2 add hl, de -.asm_24ff +.loadMaskPointer2 ld e, b sla e sla e @@ -3023,7 +3054,7 @@ BallPositionPointerOffsetDeltas: db $00, $20 db $01, $21 -SubTileBallPosDeltas: +BallCollisionTestPointOffsets: db 4, 0 db 4, 1 db 3, 3 @@ -3041,17 +3072,24 @@ SubTileBallPosDeltas: db 3, -3 db 4, -1 -SubTileXPos_CollisionDataPointers: ; 0x252e - dw SubTileXPos_CollisionData0 - dw SubTileXPos_CollisionData1 - dw SubTileXPos_CollisionData2 - dw SubTileXPos_CollisionData3 - dw SubTileXPos_CollisionData4 - dw SubTileXPos_CollisionData5 - dw SubTileXPos_CollisionData6 - dw SubTileXPos_CollisionData7 - -SubTileXPos_CollisionData0: ; 0x253e +; These tables facilitate testing the 16 collision points around the ball's origin. +; Each table corresponds to an x sub-tile offset for a base point 4 pixels up and left of +; the ball's origin. +; +; First byte: y sub-tile offset, if its greater than 8, it bleeds over to the next tile in the 2x2 tile region +; Second byte: bitmask to test against the 1bpp collision mask's row +; Third byte: index of wCollisionPointTests to save the result in +CollisionTests: ; 0x252e + dw CollisionTest_X0 + dw CollisionTest_X1 + dw CollisionTest_X2 + dw CollisionTest_X3 + dw CollisionTest_X4 + dw CollisionTest_X5 + dw CollisionTest_X6 + dw CollisionTest_X7 + +CollisionTest_X0: ; 0x253e db $00, $10, $0B db $00, $08, $0C db $00, $04, $0D @@ -3069,7 +3107,7 @@ SubTileXPos_CollisionData0: ; 0x253e db $08, $08, $04 db $08, $04, $03 -SubTileXPos_CollisionData1: ; 0x256e +CollisionTest_X1: ; 0x256e db $00, $08, $0B db $00, $04, $0C db $00, $02, $0D @@ -3087,7 +3125,7 @@ SubTileXPos_CollisionData1: ; 0x256e db $08, $04, $04 db $08, $02, $03 -SubTileXPos_CollisionData2: ; 0x259e +CollisionTest_X2: ; 0x259e db $00, $04, $0B db $00, $02, $0C db $00, $01, $0D @@ -3105,7 +3143,7 @@ SubTileXPos_CollisionData2: ; 0x259e db $08, $02, $04 db $08, $01, $03 -SubTileXPos_CollisionData3: ; 0x25ce +CollisionTest_X3: ; 0x25ce db $00, $02, $0B db $00, $01, $0C db $10, $80, $0D @@ -3123,7 +3161,7 @@ SubTileXPos_CollisionData3: ; 0x25ce db $08, $01, $04 db $18, $80, $03 -SubTileXPos_CollisionData4: ; 0x25fe +CollisionTest_X4: ; 0x25fe db $00, $01, $0B db $10, $80, $0C db $10, $40, $0D @@ -3141,7 +3179,7 @@ SubTileXPos_CollisionData4: ; 0x25fe db $18, $80, $04 db $18, $40, $03 -SubTileXPos_CollisionData5: ; 0x262e +CollisionTest_X5: ; 0x262e db $10, $80, $0B db $10, $40, $0C db $10, $20, $0D @@ -3159,7 +3197,7 @@ SubTileXPos_CollisionData5: ; 0x262e db $18, $40, $04 db $18, $20, $03 -SubTileXPos_CollisionData6: ; 0x265e +CollisionTest_X6: ; 0x265e db $10, $40, $0B db $10, $20, $0C db $10, $10, $0D @@ -3177,7 +3215,7 @@ SubTileXPos_CollisionData6: ; 0x265e db $18, $20, $04 db $18, $10, $03 -SubTileXPos_CollisionData7: ; 0x268e +CollisionTest_X7: ; 0x268e db $10, $20, $0B db $10, $10, $0C db $10, $08, $0D @@ -1751,7 +1751,7 @@ wd7ad:: ; 0xd7ad wd7ae:: ; 0xd7ae ds $1 -wd7af:: ; 0xd7af +wLeftFlipperState:: ; 0xd7af ds $1 wd7b0:: ; 0xd7b0 @@ -1763,7 +1763,7 @@ wd7b1:: ; 0xd7b1 wd7b2:: ; 0xd7b2 ds $1 -wd7b3:: ; 0xd7b3 +wRightFlipperState:: ; 0xd7b3 ds $1 wd7b4:: ; 0xd7b4 @@ -1816,18 +1816,21 @@ wSubTileBallYPos:: ; 0xd7c4 wUpperLeftCollisionAttribute:: ; 0xd7c5 ds $1 - wLowerLeftCollisionAttribute:: ; 0xd7c6 ds $1 - wUpperRightCollisionAttribute:: ; 0xd7c7 ds $1 - wLowerRightCollisionAttribute:: ; 0xd7c8 ds $1 -wd7c9:: ; 0xd7c9 - ds $10 +wCollisionPointTests:: ; 0xd7c9 +; When the ball is tested for stage collision, there are 16 +; individual points around the center of the ball that are +; tested to see if they are inside a collision mask. This +; buffer holds the results of each of those tests. The order +; of the points is clockwise, starting directly 4 pixels right +; of the ball's center. + ds 16 wd7d9:: ; 0xd7d9 ds $10 @@ -1863,13 +1866,13 @@ wStageCollisionMasksBank:: ; 0xd7f1 wd7f2:: ; 0xd7f2 ds $1 -wBallPositionPointerOffsetFromStageTopLeft:: ; 0xd7f3 +wBallPositionTileOffset:: ; 0xd7f3 dw wCurCollisionAttribute:: ; 0xd7f5 ds $1 -wd7f6:: ; 0xd7f6 +wCurCollisionTileOffset:: ; 0xd7f6 ds $1 wd7f7:: ; 0xd7f7 |