summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTauwasser <Tauwasser@tauwasser.eu>2018-06-24 23:15:07 +0200
committerTauwasser <Tauwasser@tauwasser.eu>2018-06-24 23:15:07 +0200
commit906ea8bdfcf024cb5011948a319764047f8fa41f (patch)
tree09eb3057dbe02c6a019f977eb159d7da6c728879
parent57481cc9421d2ea830480d3c1cb5b9f5c7d907aa (diff)
engine: disassemble player movement (WIP)
Signed-off-by: Tauwasser <Tauwasser@tauwasser.eu>
-rw-r--r--constants.asm2
-rw-r--r--constants/collision_constants.asm128
-rw-r--r--constants/metatile_constants.asm32
-rw-r--r--data/collision/collision_type_table.binbin0 -> 256 bytes
-rw-r--r--engine/overworld/player_movement.asm1115
-rw-r--r--home/map.asm2
-rw-r--r--shim.sym1
-rw-r--r--wram.asm9
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
new file mode 100644
index 0000000..c70e2bd
--- /dev/null
+++ b/data/collision/collision_type_table.bin
Binary files differ
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
diff --git a/shim.sym b/shim.sym
index 8390904..da80057 100644
--- a/shim.sym
+++ b/shim.sym
@@ -58,7 +58,6 @@
02:528B Function928b
02:5695 CheckSGB
-03:4000 Functionc000
03:47D5 SpawnPoints
03:488D Tilesets
03:54E6 Functiond4e6
diff --git a/wram.asm b/wram.asm
index b196ac4..62a4a23 100644
--- a/wram.asm
+++ b/wram.asm
@@ -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]