diff options
author | Tauwasser <Tauwasser@tauwasser.eu> | 2018-06-24 23:15:07 +0200 |
---|---|---|
committer | Tauwasser <Tauwasser@tauwasser.eu> | 2018-06-24 23:15:07 +0200 |
commit | 906ea8bdfcf024cb5011948a319764047f8fa41f (patch) | |
tree | 09eb3057dbe02c6a019f977eb159d7da6c728879 | |
parent | 57481cc9421d2ea830480d3c1cb5b9f5c7d907aa (diff) |
engine: disassemble player movement (WIP)
Signed-off-by: Tauwasser <Tauwasser@tauwasser.eu>
-rw-r--r-- | constants.asm | 2 | ||||
-rw-r--r-- | constants/collision_constants.asm | 128 | ||||
-rw-r--r-- | constants/metatile_constants.asm | 32 | ||||
-rw-r--r-- | data/collision/collision_type_table.bin | bin | 0 -> 256 bytes | |||
-rw-r--r-- | engine/overworld/player_movement.asm | 1115 | ||||
-rw-r--r-- | home/map.asm | 2 | ||||
-rw-r--r-- | shim.sym | 1 | ||||
-rw-r--r-- | wram.asm | 9 |
8 files changed, 1286 insertions, 3 deletions
diff --git a/constants.asm b/constants.asm index c559622..9da5ddc 100644 --- a/constants.asm +++ b/constants.asm @@ -24,6 +24,8 @@ INCLUDE "constants/landmark_constants.asm" INCLUDE "constants/map_constants.asm" INCLUDE "constants/map_setup_constants.asm" INCLUDE "constants/tileset_constants.asm" +INCLUDE "constants/collision_constants.asm" +INCLUDE "constants/metatile_constants.asm" INCLUDE "constants/map_data_constants.asm" INCLUDE "constants/script_constants.asm" diff --git a/constants/collision_constants.asm b/constants/collision_constants.asm new file mode 100644 index 0000000..580d397 --- /dev/null +++ b/constants/collision_constants.asm @@ -0,0 +1,128 @@ +; collision IDs are built like this: +; 76543210 +; \__/|\_/ +; | | \-- SubType +; | \---- Flag +; \------ Type +; +; What exactly flag means or if it +; means anything is up to Type. +; Old Types: +; ??? +; New Types: +; 0 - Regular 8 - ??? +; 1 - Trees, Grass etc. 9 - Special Talk Action +; 2 - Water A - Jump Action +; 3 - Water 2 B - unused +; 4 - Land C - unused +; 5 - Land 2 D - unused +; 6 - ??? E - unused +; 7 - Warps F - unused + +COLLISION_TYPE_MASK EQU $f0 +COLLISION_SUBTYPE_MASK EQU $07 +COLLISION_WATER_SUBTYPE_MASK EQU $03 + +COLLISION_FLAG EQU $08 + +; old collision constants + +OLD_COLLISION_TYPE_REGULAR EQU $00 +OLD_COLLISION_TYPE_SCENERY EQU $10 +OLD_COLLISION_TYPE_WATER EQU $20 +OLD_COLLISION_TYPE_WATER2 EQU $40 + +OLD_COLLISION_WALKABLE EQU $00 +OLD_COLLISION_SOLID EQU $01 +OLD_COLLISION_FLOOR EQU $03 +OLD_COLLISION_WALL EQU $04 + +OLD_COLLISION_LEDGE EQU $11 + +OLD_COLLISION_WATER2_S EQU $40 + +OLD_COLLISION_ROCK EQU $51 + +OLD_COLLISION_CARPED EQU $60 +OLD_COLLISION_DOOR EQU $61 + +OLD_COLLISION_SIGNPOST EQU $70 +OLD_COLLISION_SHOP_SIGN EQU $71 +OLD_COLLISION_MART_ITEM EQU $72 +OLD_COLLISION_COUNTER EQU $73 + +OLD_COLLISION_CUT_TREE EQU $80 +OLD_COLLISION_GRASS EQU $82 + +; new collision constants + +COLLISION_TYPE_REGULAR EQU $00 +COLLISION_TYPE_SCENERY EQU $10 +COLLISION_TYPE_WATER EQU $20 +COLLISION_TYPE_WATER2 EQU $30 +COLLISION_TYPE_LAND EQU $40 +COLLISION_TYPE_LAND2 EQU $50 +COLLISION_TYPE_UNK EQU $60 +COLLISION_TYPE_WARPS EQU $70 +COLLISION_TYPE_UNKN2 EQU $80 +COLLISION_TYPE_SPECIAL EQU $90 +COLLISION_TYPE_JUMP EQU $A0 + +COLLISION_WALKABLE EQU $00 +COLLISION_SOLID EQU $07 +COLLISION_CUT_TREE EQU $12 +COLLISION_GRASS EQU $18 + +; water collisions + +COLLISION_WATER EQU $21 +COLLISION_WATERFALL EQU $22 +COLLISION_WATER_SOLID EQU $27 + +; water collisions 2 +COLLISION_WATER2_E EQU $30 +COLLISION_WATER2_W EQU $31 +COLLISION_WATER2_N EQU $32 +COLLISION_WATER2_S EQU $33 +; $34..$37 will behave like COLLISION_WATER2_E..COLLISION_WATER2_S + +; land collisions +COLLISION_LAND_SLOW EQU $40 +COLLISION_LAND_E EQU $41 +COLLISION_LAND_W EQU $42 +COLLISION_LAND_N EQU $43 +COLLISION_LAND_S EQU $44 +; $45..$47 will behave like COLLISION_LAND_E + +; land collisions 2 +COLLISION_LAND2_E EQU $50 +COLLISION_LAND2_W EQU $51 +COLLISION_LAND2_N EQU $52 +COLLISION_LAND2_S EQU $53 +; $54..$57 will behave like COLLISION_LAND2_E + + +; warp collisions +COLLISION_CARPET EQU $70 +COLLISION_DOOR EQU $71 +COLLISION_STEPS EQU $72 + +; special collisions +COLLISION_COUNTER EQU $90 +COLLISION_BOOKCASE EQU $91 +COLLISION_PC EQU $93 +COLLISION_RADIO EQU $94 +COLLISION_SIGNPOST EQU $95 +COLLISION_STRAIGHT_SIGNPOST EQU $97 + +; jump collisions +; perform jump in marked direction, else +; regular walking +COLLISION_JUMP_E EQU $a0 +COLLISION_JUMP_W EQU $a1 +COLLISION_JUMP_N EQU $a2 +COLLISION_JUMP_S EQU $a3 +COLLISION_JUMP_SE EQU $a4 +COLLISION_JUMP_SW EQU $a5 +COLLISION_JUMP_NE EQU $a6 +COLLISION_JUMP_NW EQU $a7 diff --git a/constants/metatile_constants.asm b/constants/metatile_constants.asm new file mode 100644 index 0000000..8d86ac5 --- /dev/null +++ b/constants/metatile_constants.asm @@ -0,0 +1,32 @@ + +; all outside tileset share certain metatiles +; this is used in overworld code when editing the map +; D - dirt +; L - lawn +; T - small tree +; C - cut tree +; G - grass +METATILE_GROUND EQU $01 ; DD + ; DD +METATILE_LAWN EQU $04 ; LL + ; LL +METATILE_SMALL_TREES_N EQU $25 ; TT + ; LL +METATILE_SMALL_TREES_W EQU $28 ; TL + ; TL +METATILE_SMALL_TREES_E EQU $2a ; LT + ; LT +METATILE_CUT_SE_TREES_N EQU $30 ; TT + ; LC +METATILE_CUT_NW_TREES_E EQU $31 ; CT + ; LT +METATILE_CUT_NE_TREE_NW EQU $32 ; TC + ; LL +METATILE_CUT_NE_TREE_SE EQU $33 ; LC + ; LT +METATILE_SMALL_TREE_NW EQU $34 ; TL + ; LL +METATILE_SMALL_TREE_SE EQU $35 ; TL + ; LL +METATILE_GRASS EQU $3b ; GG + ; GG diff --git a/data/collision/collision_type_table.bin b/data/collision/collision_type_table.bin Binary files differnew file mode 100644 index 0000000..c70e2bd --- /dev/null +++ b/data/collision/collision_type_table.bin diff --git a/engine/overworld/player_movement.asm b/engine/overworld/player_movement.asm new file mode 100644 index 0000000..44938aa --- /dev/null +++ b/engine/overworld/player_movement.asm @@ -0,0 +1,1115 @@ +INCLUDE "constants.asm" + +SECTION "Player Movement", ROMX[$4000], BANK[$3] + +OverworldMovementCheck:: + jp _OverworldMovementCheck + +UnusedOverworldMovementCheck:: + ld a, $01 + ldh [hEventCollisionException], a + ld a, [wPlayerDirection] + and a + jr z, _SetPlayerIdle ; player movement is disabled + ldh a, [hJoyState] + ld d, a + ld hl, wce63 + bit 1, [hl] + jr z, .skip_debug_move + bit B_BUTTON_F, d + jp nz, CheckMovementDebug +.skip_debug_move + ld a, [wPlayerState] + cp PLAYER_SKATE + jp z, OldCheckMovementSkateboard + cp PLAYER_SURF + jp z, OldCheckMovementSurf + jp CheckMovementWalkOrBike +_SetPlayerIdle: + ld a, $2a +_SetPlayerAnimation: + ld [wcb77], a + ld a, [wPlayerLastMapX] + ld [wPlayerStandingMapX], a + ld a, [wPlayerLastMapY] + ld [wPlayerStandingMapY], a + and a + ret + +CheckMovementWalkOrBike: + call _CheckMovementWalkOrBike + jp _SetPlayerAnimation + +_CheckMovementWalkOrBike: + ld a, d + and (D_DOWN | D_UP | D_LEFT | D_RIGHT) + jp z, .done + ld a, d + bit D_DOWN_F, a + jp nz, .moveDown + bit D_UP_F, a + jp nz, .moveUp + bit D_LEFT_F, a + jp nz, .moveLeft + bit D_RIGHT_F, a + jr nz, .moveRight +.done: + ld a, $2a + ret +.moveRight: + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerStandingMapX], a + call _CheckPlayerObjectCollision + jr c, .faceRight + call IsPlayerCollisionTileSolid + jr nc, .canMoveRight + jr .faceRight +.canMoveRight + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, $0f + ret z + ld a, $0b + ret +.faceRight: + ld a, $03 + ret + +.moveLeft: + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerStandingMapX], a + call _CheckPlayerObjectCollision + jr c, .faceLeft + call IsPlayerCollisionTileSolid + jr nc, .canMoveLeft + jr .faceLeft +.canMoveLeft + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, $0e + ret z + ld a, $0a + ret +.faceLeft: + ld a, $02 + ret + +.moveDown: + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerStandingMapY], a + call _CheckPlayerObjectCollision + jr c, .faceDown + call IsPlayerCollisionTileSolid + jr nc, .canMoveDown + cp OLD_COLLISION_LEDGE + jr nz, .faceDown +.jumpDown: + ld a, $18 + ret +.canMoveDown + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, $0c + ret z + ld a, $08 + ret +.faceDown: + ld a, $00 + ret + +.moveUp: + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerStandingMapY], a + call _CheckPlayerObjectCollision + jr c, .faceUp + call IsPlayerCollisionTileSolid + jr nc, .canMoveUp + jr .faceUp +.canMoveUp + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, $0d + ret z + ld a, $09 + ret +.faceUp: + ld a, $01 + ret + +CheckMovementDebug:: + ld a, d + call _CheckMovementDebug + jp _SetPlayerAnimation + +_CheckMovementDebug: + bit D_DOWN_F, a + jr nz, .moveDown + bit D_UP_F, a + jr nz, .moveUp + bit D_LEFT_F, a + jr nz, .moveLeft + bit D_RIGHT_F, a + jr nz, .moveRight +.idle: + ld a, $2a + ret +.moveDown: + ld a, [wTileDown] + cp $ff + ld a, $0c + ret nz + ld a, $19 + ret +.moveUp: + ld a, [wTileUp] + cp $ff + ld a, $0d + ret nz + ld a, $18 + ret +.moveLeft: + ld a, [wTileLeft] + cp $ff + ld a, $0e + ret nz + ld a, $1b + ret +.moveRight: + ld a, [wTileRight] + cp $ff + ld a, $0f + ret nz + ld a, $1a + ret + +OldCheckMovementSkateboard:: + call _OldCheckMovementSkateboard + jp _SetPlayerAnimation + +_OldCheckMovementSkateboard: + ld a, [wSkatingDirection] + cp $ff + jp z, .skateStand + push de + ld e, a + ld d, $00 + ld hl, .skateMovementTable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop de + jp hl +.skateMovementTable: + dw .skateDown + dw .skateUp + dw .skateLeft + dw .skateRight + +.skateStand: + ld a, d + and (D_DOWN | D_UP | D_LEFT | D_RIGHT) + jp z, .done + bit D_DOWN_F, d + jp nz, .skateDown + bit D_UP_F, d + jp nz, .skateUp + bit D_LEFT_F, d + jp nz, .skateLeft + bit D_RIGHT_F, d + jp nz, .skateRight +.done: + ld a, $ff + ld [wSkatingDirection], a + ld a, $2a + ret + +.skateDown: + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerStandingMapY], a + ld a, $00 + ld [wSkatingDirection], a + call _CheckPlayerObjectCollision + jr c, .skateDownCollision + call IsPlayerCollisionTileSolid + jr nc, .canSkateDown + cp OLD_COLLISION_LEDGE + jr z, .skateJumpDown + cp (OLD_COLLISION_ROCK | COLLISION_FLAG) + jr nz, .skateDownCollision +.skateJumpDown: + ld a, $1c + ret +.canSkateDown: + call OldIsTileCollisionGrass + jr z, .skateDownSlowly + ld a, $0c + ret +.skateDownSlowly: + ld a, $08 + ret +.skateDownCollision: + ld a, $ff + ld [wSkatingDirection], a + ld a, $00 + ret + +.skateUp: + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerStandingMapY], a + ld a, $01 + ld [wSkatingDirection], a + call _CheckPlayerObjectCollision + jr c, .skateUpCollision + call IsPlayerCollisionTileSolid + jr nc, .canSkateUp + cp $59 + jr nz, .skateUpCollision +.skateJumpUp: + ld a, $1d + ret +.canSkateUp: + call OldIsTileCollisionGrass + jr z, .skateUpSlowly + ld a, $0d + ret +.skateUpSlowly: + ld a, $09 + ret +.skateUpCollision: + ld a, $ff + ld [wSkatingDirection], a + ld a, $01 + ret + +.skateLeft: + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerStandingMapX], a + ld a, $02 + ld [wSkatingDirection], a + call _CheckPlayerObjectCollision + jr c, .skateLeftCollision + call IsPlayerCollisionTileSolid + jr nc, .canSkateLeft + cp $59 + jr nz, .skateLeftCollision +.skateJumpLeft: + ld a, $1e + ret +.canSkateLeft: + call OldIsTileCollisionGrass + jr z, .skateLeftSlowly + ld a, $0e + ret +.skateLeftSlowly: + ld a, $0a + ret +.skateLeftCollision: + ld a, $ff + ld [wSkatingDirection], a + ld a, $02 + ret + +.skateRight: + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerStandingMapX], a + ld a, $03 + ld [wSkatingDirection], a + call _CheckPlayerObjectCollision + jr c, .skateRightCollision + call IsPlayerCollisionTileSolid + jr nc, .canSkateRight + cp $59 + jr nz, .skateRightCollision +.skateJumpRight: + ld a, $1f + ret +.canSkateRight: + call OldIsTileCollisionGrass + jr z, .skateRightSlowly + ld a, $0f + ret +.skateRightSlowly: + ld a, $0b + ret +.skateRightCollision: + ld a, $ff + ld [wSkatingDirection], a + ld a, $03 + ret + +OldIsTileCollisionGrass:: +; Check whether collision ID in a is +; grass +; Result: +; nz - not grass +; z - grass + cp $82 + ret z + cp $83 + ret z + cp $8a + ret z + cp $8b + ret + +OldCheckMovementSurf:: + call _OldCheckMovementSurf + jp _SetPlayerAnimation + +_OldCheckMovementSurf: + ld a, d + and (D_DOWN | D_UP | D_LEFT | D_RIGHT) + bit D_DOWN_F, a + jp nz, .trySurfDown + bit D_UP_F, a + jp nz, .trySurfUp + bit D_LEFT_F, a + jp nz, .trySurfLeft + bit D_RIGHT_F, a + jr nz, .trySurfRight +.idle: + ld a, $2a + ret + +.trySurfDown: + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerStandingMapY], a + call _CheckPlayerObjectCollision + jr c, .faceDown + call IsPlayerCollisionTileSolid + jr nc, .surfDownLand ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call OldIsTileCollisionWater + jr c, .faceDown +.surfDown: + ld a, $08 + ret +.faceDown: + ld a, $00 + ret +.surfDownLand: + call SetPlayerStateWalk + ld a, $04 + ret + +.trySurfUp: + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerStandingMapY], a + call _CheckPlayerObjectCollision + jr c, .faceUp + call IsPlayerCollisionTileSolid + jr nc, .surfUpLand ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call OldIsTileCollisionWater + jr c, .faceUp +.surfUp: + ld a, $09 + ret +.faceUp: + ld a, $01 + ret +.surfUpLand: + call SetPlayerStateWalk + ld a, $05 + ret + +.trySurfLeft: + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerStandingMapX], a + call _CheckPlayerObjectCollision + jr c, .faceLeft + call IsPlayerCollisionTileSolid + jr nc, .surfLeftLand ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call OldIsTileCollisionWater + jr c, .faceLeft +.surfLeft: + ld a, $0a + ret +.faceLeft: + ld a, $02 + ret +.surfLeftLand + call SetPlayerStateWalk + ld a, $06 + ret + +.trySurfRight + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerStandingMapX], a + call _CheckPlayerObjectCollision + jr c, .faceRight + call IsPlayerCollisionTileSolid + jr nc, .surfRightLand ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call OldIsTileCollisionWater + jr c, .faceRight +.surfRight: + ld a, $0b + ret +.faceRight: + ld a, $03 + ret +.surfRightLand + call SetPlayerStateWalk + ld a, $07 + ret + +OldIsTileCollisionWater:: ; c2ee (3:42ee) +; Check if collision ID in a is water +; Input: +; a - collision ID +; Result: +; c - water +; nc - not water + and COLLISION_TYPE_MASK + cp OLD_COLLISION_TYPE_WATER + ret z + cp OLD_COLLISION_TYPE_WATER2 + ret z + scf + ret + +SetPlayerStateWalk:: + push bc + ld a, PLAYER_NORMAL + ld [wPlayerState], a + call RedrawPlayerSprite + pop bc + ret + +IsPlayerCollisionTileSolid:: +; Return whether the collision under player's feet +; is solid/sometimes solid or non-solid. +; Clobbers: a +; Results: +; a - collision ID under player's feet +; nc - non-solid +; c - solid/sometimes solid + push de + ld bc, wPlayerStruct + ld hl, $775a + ld a, $01 + call FarCall_hl + ld a, e + pop de + ret + +_CheckPlayerObjectCollision:: +; Check whether player object currentl +; collides with any other object. +; Result: +; nc - no collision +; c - collision + push de + ld hl, $7894 + ld a, $01 + call FarCall_hl + pop de + ret nc + jp _CheckCompanionObjectCollision + +_CheckCompanionObjectCollision:: +; Marks the object struct pointed to by hl +; as having collided with player object. +; If object struct (as identified by hEventID) +; is companion, cancel collision on 5th frames. +; Result: +; nc - no collision +; c - collision + ld hl, (wPlayerFlags + 1) - wPlayerStruct + add hl, bc + set 1, [hl] ; mark object as having collided with player + ldh a, [hEventID] + cp $02 + jr z, .isCompanion + xor a + ld [wCompanionCollisionFrameCounter], a + scf + ret +.isCompanion + ld a, [wCompanionCollisionFrameCounter] + inc a + cp $05 + ld [wCompanionCollisionFrameCounter], a + jr z, .cancelCollision + scf + ret +.cancelCollision + xor a + ld [wCompanionCollisionFrameCounter], a + ret + +_OverworldMovementCheck:: + ld a, $01 + ldh [hEventCollisionException], a + ld a, [wPlayerDirection] + and a + jp z, _SetPlayerIdle + ldh a, [hJoyState] + ld d, a + ld hl, wce63 + bit 1, [hl] + jr z, .skip_debug_move + bit B_BUTTON_F, d + jp nz, CheckMovementDebug +.skip_debug_move + call .checkMovementRelease + jp _SetPlayerAnimation + +.checkMovementRelease: + ld a, [wPlayerState] + cp PLAYER_SKATE + jp z, OldCheckMovementSkateboard ; FIXME: OldCheckMovementSkateboard already calls _SetPlayerAnimation + ; The skateboard doesn't work, because it uses the current + ; coordinate as player animation. + cp PLAYER_SURF + jp z, CheckMovementSurf + jp CheckMovementWalk + +CheckMovementWalk:: + ld a, [wPlayerStandingTile] + swap a + and LOW((COLLISION_TYPE_MASK >> 4) | (COLLISION_TYPE_MASK << 4)) + ld hl, .walkingCollisionTable + jp CallJumptable + +.walkingCollisionTable: + dw CheckMovementWalkRegular ; regular + dw CheckMovementWalkSolid ; trees, grass, etc. + dw CheckMovementWalkSolid ; water + dw CheckMovementWalkSolid ; water current + dw CheckMovementWalkLand ; slowdown and fixed movement + dw CheckMovementWalkLand2 ; fixed movement + dw CheckMovementWalkRegular ; ??? + dw CheckMovementWalkWarp ; warps + dw CheckMovementWalkMisc ; ??? + dw CheckMovementWalkSpecial ; counters, signposts, book cases + dw CheckMovementWalkJump ; jumps + dw CheckMovementWalkRegular ; unused -- movement prohibit not yet implemented + dw CheckMovementWalkRegular ; unused + dw CheckMovementWalkRegular ; unused + dw CheckMovementWalkRegular ; unused + dw CheckMovementWalkRegular ; unused + +_MovementDone: + ld a, $2a + ret + +CheckMovementWalkSolid:: + jp CheckMovementWalkRegular + +CheckMovementWalkLand:: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + jr nz, .slowdown + call CheckMovementWalkRegular + call .slowMovementDown + ret +.slowdown + ld b, $08 + cp (COLLISION_LAND_S & COLLISION_SUBTYPE_MASK) + jr z, .slowdownDone + ld b, $09 + cp (COLLISION_LAND_N & COLLISION_SUBTYPE_MASK) + jr z, .slowdownDone + ld b, $0a + cp (COLLISION_LAND_W & COLLISION_SUBTYPE_MASK) + jr z, .slowdownDone + ld b, $0b + cp (COLLISION_LAND_E & COLLISION_SUBTYPE_MASK) + jr z, .slowdownDone + ; fall-through --> map other codes to COLLISION_LAND_E +.slowdownDone + ld a, b + ret +.slowMovementDown: + ld b, $04 + cp $08 + jr z, .slowMovementDownDone + ld b, $05 + cp $09 + jr z, .slowMovementDownDone + ld b, $06 + cp $0a + jr z, .slowMovementDownDone + ld b, $07 + cp $0b + jr z, .slowMovementDownDone + ret +.slowMovementDownDone + ld a, b + ret + +CheckMovementWalkLand2:: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + ld b, $08 + cp (COLLISION_LAND2_S & COLLISION_SUBTYPE_MASK) + jr z, .done + ld b, $09 + cp (COLLISION_LAND2_N & COLLISION_SUBTYPE_MASK) + jr z, .done + ld b, $0a + cp (COLLISION_LAND2_W & COLLISION_SUBTYPE_MASK) + jr z, .done + ld b, $0b + cp (COLLISION_LAND2_E & COLLISION_SUBTYPE_MASK) + jr z, .done + ; fall-through --> map other codes to COLLISION_LAND2_E +.done + ld a, b + ret + +UnusedCheckMovementWalk60:: + jp CheckMovementWalkRegular + +CheckMovementWalkWarp:: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + jr z, .exitWarpDpadDirection + cp $01 + jr z, .exitWarpDownNoBoundsCheck + ld a, [wPlayerStandingTile] + cp $7a + jr z, .exitWarpDownNoBoundsCheck + jp CheckMovementWalkRegular +.exitWarpDownNoBoundsCheck + ld a, $08 + ret +.exitWarpDpadDirection + ldh a, [hJoyState] + bit D_DOWN_F, a + jr nz, .exitWarpDown + bit D_UP_F, a + jr nz, .exitWarpUp + bit D_LEFT_F, a + jr nz, .exitWarpLeft + bit D_RIGHT_F, a + jr nz, .exitWarpRight + jp _MovementDone +.exitWarpDown + ld a, [wTileDown] + cp $ff + jp nz, CheckMovementWalkRegular + call z, _ReportMovementOutOfBounds +.faceDown: + ld a, $00 + ret +.exitWarpUp + ld a, [wTileUp] + cp $ff + jp nz, CheckMovementWalkRegular + call z, _ReportMovementOutOfBounds +.faceUp: + ld a, $01 + ret +.exitWarpLeft + ld a, [wTileLeft] + cp $ff + jp nz, CheckMovementWalkRegular + call z, _ReportMovementOutOfBounds +.faceLeft: + ld a, $02 + ret +.exitWarpRight + ld a, [wTileRight] + cp $ff + jp nz, CheckMovementWalkRegular + call z, _ReportMovementOutOfBounds +.faceRight: + ld a, $03 + ret + +_ReportMovementOutOfBounds:: + ret + +CheckMovementWalkMisc:: + jp CheckMovementWalkRegular + +CheckMovementWalkSpecial:: + jp CheckMovementWalkRegular + +CheckMovementWalkRegular:: + ldh a, [hJoyState] + bit D_DOWN_F, a + jp nz, TryWalkDown + bit D_UP_F, a + jp nz, TryWalkUp + bit D_LEFT_F, a + jp nz, TryWalkLeft + bit D_RIGHT_F, a + jp nz, TryWalkRight + jp _MovementDone + +CheckMovementWalkJump: + ldh a, [hJoyState] + bit D_DOWN_F, a + jr nz, .checkJumpDown + bit D_UP_F, a + jr nz, .checkJumpUp + bit D_LEFT_F, a + jr nz, .checkJumpLeft + bit D_RIGHT_F, a + jr nz, .checkJumpRight + jp _MovementDone +.checkJumpDown: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_S & COLLISION_SUBTYPE_MASK) + jr z, .jumpDown + cp (COLLISION_JUMP_SE & COLLISION_SUBTYPE_MASK) + jr z, .jumpDown + cp (COLLISION_JUMP_SW & COLLISION_SUBTYPE_MASK) + jr z, .jumpDown + jp TryWalkDown +.jumpDown: + ld a, $18 + ret +.checkJumpUp: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_N & COLLISION_SUBTYPE_MASK) + jr z, .jumpUp + cp (COLLISION_JUMP_NE & COLLISION_SUBTYPE_MASK) + jr z, .jumpUp + cp (COLLISION_JUMP_NW & COLLISION_SUBTYPE_MASK) + jr z, .jumpUp + jp TryWalkUp +.jumpUp: + ld a, $19 + ret +.checkJumpLeft: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_W & COLLISION_SUBTYPE_MASK) + jr z, .jumpLeft + cp (COLLISION_JUMP_SW & COLLISION_SUBTYPE_MASK) + jr z, .jumpLeft + cp (COLLISION_JUMP_NW & COLLISION_SUBTYPE_MASK) + jr z, .jumpLeft + jp TryWalkLeft +.jumpLeft: + ld a, $1a + ret +.checkJumpRight + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_E & COLLISION_SUBTYPE_MASK) + jr z, .jumpRight + cp (COLLISION_JUMP_SE & COLLISION_SUBTYPE_MASK) + jr z, .jumpRight + cp (COLLISION_JUMP_NE & COLLISION_SUBTYPE_MASK) + jr z, .jumpRight + jp TryWalkRight +.jumpRight + ld a, $1b + ret + +TryWalkDown:: + ld d, 0 + ld e, 1 + call _CheckObjectCollision + jr c, .faceDown + ld a, [wTileDown] + call CheckCollisionSolid + jr c, .faceDown +.moveDown: + ld a, $08 + ret +.faceDown: + ld a, $00 + ret + +TryWalkUp:: + ld d, 0 + ld e, -1 + call _CheckObjectCollision + jr c, .faceUp + ld a, [wTileUp] + call CheckCollisionSolid + jr c, .faceUp +.moveUp: + ld a, $09 + ret +.faceUp: + ld a, $01 + ret + +TryWalkLeft:: + ld d, -1 + ld e, 0 + call _CheckObjectCollision + jr c, .faceLeft + ld a, [wTileLeft] + call CheckCollisionSolid + jr c, .faceLeft +.moveLeft: + ld a, $0a + ret +.faceLeft: + ld a, $02 + ret + +TryWalkRight:: + ld d, 1 + ld e, 0 + call _CheckObjectCollision + jr c, .faceRight + ld a, [wTileRight] + call CheckCollisionSolid + jr c, .faceRight +.moveRight: + ld a, $0b + ret +.faceRight: + ld a, $03 + ret + +CheckMovementSurf:: + ld a, [wPlayerStandingTile] + swap a + and LOW((COLLISION_TYPE_MASK >> 4) | (COLLISION_TYPE_MASK << 4)) + ld hl, .surfCollisionTable + jp CallJumptable + +.surfCollisionTable + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfWater + dw CheckMovementSurfWater2 + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + dw CheckMovementSurfRegular + +CheckMovementSurfRegular:: + ldh a, [hJoyState] + bit D_DOWN_F, a + jp nz, TrySurfDown + bit D_UP_F, a + jp nz, TrySurfUp + bit D_LEFT_F, a + jp nz, TrySurfLeft + bit D_RIGHT_F, a + jp nz, TrySurfRight + jp _MovementDone + +CheckMovementSurfWater:: + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_WATERFALL & COLLISION_SUBTYPE_MASK) + jr nz, CheckMovementSurfRegular +.waterfall: + ld a, $0c + ret + +CheckMovementSurfWater2:: + ld a, [wPlayerStandingTile] + and COLLISION_WATER_SUBTYPE_MASK + ld d, $0b + jr z, .done ; COLLISION_WATER2_E + ld d, $0a + cp (COLLISION_WATER2_W & COLLISION_WATER_SUBTYPE_MASK) + jr z, .done + ld d, $09 + cp (COLLISION_WATER2_N & COLLISION_WATER_SUBTYPE_MASK) + jr z, .done + ld d, $08 + cp (COLLISION_WATER2_S & COLLISION_WATER_SUBTYPE_MASK) + jr z, .done + ; fall-through --> no aliasing due to mask +.done + ld a, d + ret + +TrySurfDown: + ld d, 0 + ld e, 1 + call _CheckObjectCollision + jr c, .faceDown + ld a, [wTileDown] + call CheckCollisionSometimesSolid + jr c, .faceDown ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call nz, SurfDismount + ld a, $08 + ret +.faceDown: + ld a, $00 + ret + +TrySurfUp: + ld d, 0 + ld e, -1 + call _CheckObjectCollision + jr c, .faceUp + ld a, [wTileUp] + call CheckCollisionSometimesSolid + jr c, .faceUp ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call nz, SurfDismount + ld a, $09 + ret +.faceUp: + ld a, $01 + ret + +TrySurfLeft: + ld d, -1 + ld e, 0 + call _CheckObjectCollision + jr c, .faceLeft + ld a, [wTileLeft] + call CheckCollisionSometimesSolid + jr c, .faceLeft ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call nz, SurfDismount + ld a, $0a + ret +.faceLeft: + ld a, $02 + ret + +TrySurfRight: + ld d, 1 + ld e, 0 + call _CheckObjectCollision + jr c, .faceRight + ld a, [wTileRight] + call CheckCollisionSometimesSolid + jr c, .faceRight ; FIXME: This assumes cut-trees are solid, which they aren't. + ; You can walk into them from water because of this. + call nz, SurfDismount + ld a, $0b + ret +.faceRight: + ld a, $03 + ret +SurfDismount: + jp SetPlayerStateWalk + +_CheckObjectCollision:: +; Check if coordinates relative +; to player collide with another object +; Clobbers: +; a, hl +; Input: +; de - Relative coords x, y +; Output: +; nc - no collision +; c - collision +; hEventID - Event ID of colliding event + ld a, $01 + ldh [hEventCollisionException], a + ld a, [wPlayerStandingMapX] + add d + ld d, a + ld a, [wPlayerStandingMapY] + add e + ld e, a + ld hl, $77dd + ld a, $01 + call FarCall_hl + ret nc + jp _CheckCompanionObjectCollision + +CheckCollisionSolid:: +; Checks whether collision ID in a +; is solid or not. +; Clobbers: +; hl +; Input: +; a - collision ID +; Result: +; a - collision type +; c - solid +; nc - not solid + call GetCollisionType + and a + ret z + scf + ret + +GetCollisionType:: +; Get collision type for collision ID in a +; Clobbers: hl +; Input: +; a - collision ID +; Result: +; a - collision type +; 00 - not solid +; 01 - sometimes solid (cut tree, water etc.) +; 0F - always solid + push de + ld hl, .collisionTypeTable + ld e, a + ld d, $00 + add hl, de + ld a, [hl] + pop de + ret + +.collisionTypeTable: +INCBIN "data/collision/collision_type_table.bin" + +_UnusedReturnFalse:: + xor a + ret + +_UnusedReturnTrue:: + xor a + scf + ret + +CheckCollisionSometimesSolid:: +; Checks whether collision ID in a +; is sometimes, always or never solid. +; Clobbers: +; hl +; Input: +; a - collision ID +; Result: +; c - always solid +; nc - sometimes not solid, check a +; a - result +; 00 - sometimes solid +; 01 - never solid + call GetCollisionType + cp $01 + jr z, .sometimesSolid + and a + jr z, .solid + jr .alwaysSolid +.sometimesSolid: + xor a + ret +.solid: + ld a, $01 + and a + ret +.alwaysSolid: + scf + ret diff --git a/home/map.asm b/home/map.asm index 8105781..8c03d9f 100644 --- a/home/map.asm +++ b/home/map.asm @@ -1679,7 +1679,7 @@ Function2b87:: call GetJoypad call OverworldStartButtonCheck ret nz - callab Functionc000 + callab OverworldMovementCheck call Function2ba8 jr nc, .asm_2b87 callba Function824c @@ -58,7 +58,6 @@ 02:528B Function928b 02:5695 CheckSGB -03:4000 Functionc000 03:47D5 SpawnPoints 03:488D Tilesets 03:54E6 Functiond4e6 @@ -343,7 +343,10 @@ wMovementBufferObject:: db ; cc3b wMovementBuffer:: ; cc3f ds 55 -SECTION "CC9C", WRAM0[$CC9C] +SECTION "CC9A", WRAM0[$CC9A] + +wSkatingDirection:: db ; cc9a +wCompanionCollisionFrameCounter:: db ; cc9b wUnknownWordcc9c:: ; cc9c dw @@ -735,6 +738,10 @@ wRivalsName:: ds 6 ; d258 SECTION "PlayerState", WRAM0[$D264] wPlayerState:: db ; d264 +; 00 - walking +; 01 - bicycle +; 02 - skateboard +; 04 - surfing SECTION "D4AB", WRAM0[$D4A9] |