diff options
author | obskyr <powpowd@gmail.com> | 2018-07-03 04:50:33 +0200 |
---|---|---|
committer | obskyr <powpowd@gmail.com> | 2018-07-03 04:50:33 +0200 |
commit | 382fd4b50e27cea7e0f97839363235ea2eac14fa (patch) | |
tree | d9836c547ac68f14a4b1766453334812380d050b | |
parent | d26c5f6937518f891d7cb699e237e172588f4a26 (diff) | |
parent | 2dfc7fc635b13291588ba8aae65fd0ece7211799 (diff) |
Merge branch 'collisions-movements' of https://github.com/Pokeglitch/pokegold-spaceworld into master
And that's the last of the manual merges for now! Hooray!
-rw-r--r-- | constants.asm | 3 | ||||
-rw-r--r-- | constants/collision_constants.asm | 132 | ||||
-rw-r--r-- | constants/map_object_constants.asm | 4 | ||||
-rw-r--r-- | constants/metatile_constants.asm | 31 | ||||
-rwxr-xr-x | constants/movement_constants.asm | 44 | ||||
-rw-r--r-- | constants/sprite_constants.asm | 2 | ||||
-rwxr-xr-x | data/collision/collision_type_table.asm | 69 | ||||
-rwxr-xr-x | engine/events/field_moves.asm | 2 | ||||
-rwxr-xr-x | engine/overworld/object_collision.asm | 157 | ||||
-rw-r--r-- | engine/overworld/player_movement.asm | 1162 | ||||
-rw-r--r-- | engine/sprites/sprites.asm (renamed from data/sprites/sprites.asm) | 53 | ||||
-rw-r--r-- | home/copy2.asm | 4 | ||||
-rw-r--r-- | home/map.asm | 32 | ||||
-rw-r--r-- | home/map_objects.asm | 25 | ||||
-rw-r--r-- | home/talk_to_npc.asm | 12 | ||||
-rw-r--r-- | home/text.asm | 2 | ||||
-rw-r--r-- | home/tileset.asm | 20 | ||||
-rw-r--r-- | hram.asm | 16 | ||||
-rw-r--r-- | macros/wram.asm | 4 | ||||
-rw-r--r-- | shim.sym | 3 | ||||
-rw-r--r-- | wram.asm | 23 |
21 files changed, 1733 insertions, 67 deletions
diff --git a/constants.asm b/constants.asm index a9a3afa..1046662 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" @@ -37,3 +39,4 @@ INCLUDE "constants/wram_constants.asm" INCLUDE "constants/sgb_constants.asm" INCLUDE "constants/map_object_constants.asm" INCLUDE "constants/main_menu_constants.asm" +INCLUDE "constants/movement_constants.asm" diff --git a/constants/collision_constants.asm b/constants/collision_constants.asm new file mode 100644 index 0000000..ebe3856 --- /dev/null +++ b/constants/collision_constants.asm @@ -0,0 +1,132 @@ +; 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 + +NEVER_SOLID EQU 0 +SOMETIMES_SOLID EQU 1 +ALWAYS_SOLID EQU 15 diff --git a/constants/map_object_constants.asm b/constants/map_object_constants.asm index c9bce93..81c52a3 100644 --- a/constants/map_object_constants.asm +++ b/constants/map_object_constants.asm @@ -70,3 +70,7 @@ MAPOBJECTTEMPLATE_SCRIPT_POINTER rb 1 ; 9 MAPOBJECTTEMPLATE_POINTER_HI rb 1 ; a MAPOBJECTTEMPLATE_EVENT_FLAG rw 1 ; b MAP_OBJECT_TEMPLATE_LENGTH SET _RS + +PLAYER_OBJECT_INDEX EQU 1 +COMPANION_OBJECT_INDEX EQU 2 +NUM_OBJECT_STRUCTS EQU 10 diff --git a/constants/metatile_constants.asm b/constants/metatile_constants.asm new file mode 100644 index 0000000..88d54ab --- /dev/null +++ b/constants/metatile_constants.asm @@ -0,0 +1,31 @@ +; 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/constants/movement_constants.asm b/constants/movement_constants.asm new file mode 100755 index 0000000..f0c1a88 --- /dev/null +++ b/constants/movement_constants.asm @@ -0,0 +1,44 @@ + const_def
+ const FACE_DOWN ; $00
+ const FACE_UP ; $01
+ const FACE_LEFT ; $02
+ const FACE_RIGHT ; $03
+ const SLOW_STEP_DOWN ; $04
+ const SLOW_STEP_UP ; $05
+ const SLOW_STEP_LEFT ; $06
+ const SLOW_STEP_RIGHT ; $07
+ const STEP_DOWN ; $08
+ const STEP_UP ; $09
+ const STEP_LEFT ; $0a
+ const STEP_RIGHT ; $0b
+ const FAST_STEP_DOWN ; $0c
+ const FAST_STEP_UP ; $0d
+ const FAST_STEP_LEFT ; $0e
+ const FAST_STEP_RIGHT ; $0f
+ const FAST_STEP_DOWN2 ; $10
+ const FAST_STEP_UP2 ; $11
+ const FAST_STEP_LEFT2 ; $12
+ const FAST_STEP_RIGHT2 ; $13
+ const SLOW_JUMP_DOWN ; $14
+ const SLOW_JUMP_UP ; $15
+ const SLOW_JUMP_LEFT ; $16
+ const SLOW_JUMP_RIGHT ; $17
+ const JUMP_DOWN ; $18
+ const JUMP_UP ; $19
+ const JUMP_LEFT ; $1a
+ const JUMP_RIGHT ; $1b
+ const FAST_JUMP_DOWN ; $1c
+ const FAST_JUMP_UP ; $1d
+ const FAST_JUMP_LEFT ; $1e
+ const FAST_JUMP_RIGHT ; $1f
+ const FAST_JUMP_DOWN2 ; $20
+ const FAST_JUMP_UP2 ; $21
+ const FAST_JUMP_LEFT2 ; $22
+ const FAST_JUMP_RIGHT2 ; $23
+ const MOVEMENT_24 ; $24
+ const MOVEMENT_25 ; $25
+ const MOVEMENT_26 ; $26
+ const MOVEMENT_27 ; $27
+ const MOVEMENT_28 ; $28
+ const MOVEMENT_29 ; $29
+ const NO_MOVEMENT ; $2a
diff --git a/constants/sprite_constants.asm b/constants/sprite_constants.asm index 50b5d84..c53866b 100644 --- a/constants/sprite_constants.asm +++ b/constants/sprite_constants.asm @@ -91,3 +91,5 @@ const SPRITE_59 ; 59 duplicate SPRITE_OLD_LINK_RECEPTIONIST const SPRITE_EGG ; 5a const SPRITE_BOULDER ; 5b + +SPRITE_TILE_SIZE EQU 64 diff --git a/data/collision/collision_type_table.asm b/data/collision/collision_type_table.asm new file mode 100755 index 0000000..aa53802 --- /dev/null +++ b/data/collision/collision_type_table.asm @@ -0,0 +1,69 @@ +INCLUDE "constants.asm"
+
+SECTION "Collision Type Table", ROMX[$4664], BANK[$3]
+
+CollisionTypeTable: ; 03:4664
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $00
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, ALWAYS_SOLID ; $04
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $08
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, ALWAYS_SOLID ; $0C
+ db NEVER_SOLID, NEVER_SOLID, SOMETIMES_SOLID, NEVER_SOLID ; $10
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $14
+ db NEVER_SOLID, NEVER_SOLID, SOMETIMES_SOLID, NEVER_SOLID ; $18
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $1C
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $20
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, ALWAYS_SOLID ; $24
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $28
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, ALWAYS_SOLID ; $30
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $34
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $38
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $3C
+ db SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID, SOMETIMES_SOLID ; $40
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $44
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $48
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $4C
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $50
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $54
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $58
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $5C
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $60
+ db NEVER_SOLID, NEVER_SOLID, ALWAYS_SOLID, NEVER_SOLID ; $64
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $68
+ db NEVER_SOLID, NEVER_SOLID, ALWAYS_SOLID, NEVER_SOLID ; $6C
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $70
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $74
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $78
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $7C
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $80
+ db ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID ; $84
+ db ALWAYS_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $88
+ db ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID ; $8C
+ db ALWAYS_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $90
+ db ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID ; $94
+ db ALWAYS_SOLID, ALWAYS_SOLID, NEVER_SOLID, ALWAYS_SOLID ; $98
+ db ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID, ALWAYS_SOLID ; $9C
+ db ALWAYS_SOLID, ALWAYS_SOLID, NEVER_SOLID, ALWAYS_SOLID ; $A0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $A4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $A8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $AC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $B0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $B4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $B8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $BC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $C0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $C4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $C8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $CC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $D0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $D4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $D8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $DC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $E0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $E4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $E8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $EC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $F0
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $F4
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $F8
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, NEVER_SOLID ; $FC
+ db NEVER_SOLID, NEVER_SOLID, NEVER_SOLID, ALWAYS_SOLID ; $100
diff --git a/engine/events/field_moves.asm b/engine/events/field_moves.asm index 49729d2..f6e53a3 100755 --- a/engine/events/field_moves.asm +++ b/engine/events/field_moves.asm @@ -248,7 +248,7 @@ SurfScript: ; 03:5145 call MenuTextBoxBackup
ld a, PLAYER_SURF
ld [wPlayerState], a
- call Function0d02
+ call RedrawPlayerSprite
call PlayMapMusic
call MovePlayerIntoWater
call Function1fea
diff --git a/engine/overworld/object_collision.asm b/engine/overworld/object_collision.asm new file mode 100755 index 0000000..a04000b --- /dev/null +++ b/engine/overworld/object_collision.asm @@ -0,0 +1,157 @@ +INCLUDE "constants.asm"
+
+SECTION "GetSpritesNextTile", ROMX[$774a], BANK[$01]
+
+; Get the tile that the sprite will walk onto next
+GetSpritesNextTile: ; 01:774a
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld d, [hl]
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld e, [hl]
+ push bc
+ call GetCoordTile
+ pop bc
+ ret
+
+; Sets carry flag if the object (bc) next tile is a collision
+_IsObjectCollisionTileSolid: ; 01:775a
+ call GetSpritesNextTile
+ ld e, a
+ ld d, 0
+ ld hl, CollisionTypeTable
+ add hl, de
+ ld a, BANK(CollisionTypeTable)
+ call GetFarByte
+ and ALWAYS_SOLID ; also covers SOMETIMES_SOLID
+ ret z
+ scf
+ ret
+
+
+
+SECTION "_CheckObjectCollision", ROMX[$77dd], BANK[$01]
+
+; returns the carry flag if a sprite is at coords d, e
+; will not collide with sprite index stored in hEventCollisionException
+_CheckObjectCollision: ; 01:77dd
+ ld bc, wObjectStructs
+ xor a
+.loop
+ ldh [hObjectStructIndexBuffer], a
+ ld hl, OBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .next
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .check_last_position
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .check_last_position
+ ldh a, [hEventCollisionException]
+ ld l, a
+ ldh a, [hObjectStructIndexBuffer]
+ cp l
+ jr nz, .collision
+.check_last_position
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .next
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .next
+ ldh a, [hEventCollisionException]
+ ld l, a
+ ldh a, [hObjectStructIndexBuffer]
+ cp l
+ jr nz, .collision
+.next
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ldh a, [hObjectStructIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ and a
+ ret
+
+.collision
+ scf
+ ret
+
+SECTION "_CheckPlayerObjectCollision", ROMX[$7894], BANK[$01]
+
+; Sets the carry flag if the player will collide with another sprite's current or next position
+_CheckPlayerObjectCollision: ; 01:7894
+ ld a, [wPlayerNextMapX]
+ ld d, a
+ ld a, [wPlayerNextMapY]
+ ld e, a
+ ld bc, wObjectStructs
+ xor a
+
+.loop
+ ldh [hObjectStructIndexBuffer], a
+ ld hl, OBJECT_SPRITE
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .next
+ ld hl, OBJECT_NEXT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .check_last_position
+ ld hl, OBJECT_NEXT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .check_last_position
+
+; skip the player sprite
+ ldh a, [hObjectStructIndexBuffer]
+ cp PLAYER_OBJECT_INDEX
+ jr z, .next
+ jr .collision
+
+.check_last_position
+ ld hl, OBJECT_MAP_Y
+ add hl, bc
+ ld a, [hl]
+ cp e
+ jr nz, .next
+ ld hl, OBJECT_MAP_X
+ add hl, bc
+ ld a, [hl]
+ cp d
+ jr nz, .next
+ jr .collision
+
+.next
+ ld hl, OBJECT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ ldh a, [hObjectStructIndexBuffer]
+ inc a
+ cp NUM_OBJECT_STRUCTS
+ jr nz, .loop
+ xor a
+ ret
+
+.collision
+ scf
+ ret
diff --git a/engine/overworld/player_movement.asm b/engine/overworld/player_movement.asm new file mode 100644 index 0000000..0954dc2 --- /dev/null +++ b/engine/overworld/player_movement.asm @@ -0,0 +1,1162 @@ +INCLUDE "constants.asm" + +SECTION "Player Movement", ROMX[$4000], BANK[$3] + +OverworldMovementCheck:: ; 03:4000 + jp _OverworldMovementCheck + +UnusedOverworldMovementCheck:: ; 03:4003 + ld a, PLAYER_OBJECT_INDEX + ldh [hEventCollisionException], a + ld a, [wPlayerDirection] + and a + jr z, SetPlayerIdle ; player movement is disabled + ldh a, [hJoyState] + ld d, a + ld hl, wDebugFlags + bit DEBUG_FIELD_F, [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, CheckMovementSkateboard + cp PLAYER_SURF + jp z, OldCheckMovementSurf + jp CheckMovementWalkOrBike + +SetPlayerIdle: ; 03:402c + ld a, NO_MOVEMENT + +SetPlayerMovement: ; 03:402e + ld [wPlayerMovement], a + ld a, [wPlayerLastMapX] + ld [wPlayerNextMapX], a + ld a, [wPlayerLastMapY] + ld [wPlayerNextMapY], a + and a + ret + +CheckMovementWalkOrBike: ; 03:403f + call _CheckMovementWalkOrBike + jp SetPlayerMovement + +_CheckMovementWalkOrBike: ; 03:4045 + ld a, d + and D_PAD + jp z, .idle + ld a, d + bit D_DOWN_F, a + jp nz, .check_down + bit D_UP_F, a + jp nz, .check_up + bit D_LEFT_F, a + jp nz, .check_left + bit D_RIGHT_F, a + jr nz, .check_right +.idle + ld a, NO_MOVEMENT + ret + +.check_right + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerNextMapX], a + call CheckPlayerObjectCollision + jr c, .face_right + call IsPlayerCollisionTileSolid + jr nc, .move_right + jr .face_right +.move_right + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, FAST_STEP_RIGHT + ret z + ld a, STEP_RIGHT + ret +.face_right + ld a, FACE_RIGHT + ret + +.check_left: + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerNextMapX], a + call CheckPlayerObjectCollision + jr c, .face_left + call IsPlayerCollisionTileSolid + jr nc, .move_left + jr .face_left +.move_left + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, FAST_STEP_LEFT + ret z + ld a, STEP_LEFT + ret +.face_left + ld a, FACE_LEFT + ret + +.check_down + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerNextMapY], a + call CheckPlayerObjectCollision + jr c, .face_down + call IsPlayerCollisionTileSolid + jr nc, .move_down + cp OLD_COLLISION_LEDGE + jr nz, .face_down + ld a, JUMP_DOWN + ret +.move_down + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, FAST_STEP_DOWN + ret z + ld a, STEP_DOWN + ret +.face_down + ld a, FACE_DOWN + ret + +.check_up + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerNextMapY], a + call CheckPlayerObjectCollision + jr c, .face_up + call IsPlayerCollisionTileSolid + jr nc, .move_up + jr .face_up +.move_up + ld a, [wPlayerState] + cp PLAYER_BIKE + ld a, FAST_STEP_UP + ret z + ld a, STEP_UP + ret +.face_up + ld a, FACE_UP + ret + +CheckMovementDebug:: ; 03:40eb + ld a, d + call _CheckMovementDebug + jp SetPlayerMovement + +_CheckMovementDebug: ; 03:40f2 + bit D_DOWN_F, a + jr nz, .move_down + bit D_UP_F, a + jr nz, .move_up + bit D_LEFT_F, a + jr nz, .move_left + bit D_RIGHT_F, a + jr nz, .move_right + ld a, NO_MOVEMENT + ret + +.move_down + ld a, [wTileDown] + cp -1 + ld a, FAST_STEP_DOWN + ret nz + ld a, JUMP_UP + ret + +.move_up + ld a, [wTileUp] + cp -1 + ld a, FAST_STEP_UP + ret nz + ld a, JUMP_DOWN + ret + +.move_left + ld a, [wTileLeft] + cp -1 + ld a, FAST_STEP_LEFT + ret nz + ld a, JUMP_RIGHT + ret + +.move_right + ld a, [wTileRight] + cp -1 + ld a, FAST_STEP_RIGHT + ret nz + ld a, JUMP_LEFT + ret + +CheckMovementSkateboard:: ; 03:4131 + call _CheckMovementSkateboard + jp SetPlayerMovement + +_CheckMovementSkateboard: ; 03:4137 + ld a, [wSkatingDirection] + cp STANDING + jp z, .not_moving + 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 ; 03:414d + dw CheckSkateDown + dw CheckSkateUp + dw CheckSkateLeft + dw CheckSkateRight + +.not_moving ; 03:4155 + ld a, d + and D_PAD + jp z, .idle + bit D_DOWN_F, d + jp nz, CheckSkateDown + bit D_UP_F, d + jp nz, CheckSkateUp + bit D_LEFT_F, d + jp nz, CheckSkateLeft + bit D_RIGHT_F, d + jp nz, CheckSkateRight + +.idle + ld a, STANDING + ld [wSkatingDirection], a + ld a, NO_MOVEMENT + ret + +CheckSkateDown: ; 03:4177 + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerNextMapY], a + ld a, DOWN + ld [wSkatingDirection], a + call CheckPlayerObjectCollision + jr c, .collision + call IsPlayerCollisionTileSolid + jr nc, .can_skate + cp OLD_COLLISION_LEDGE + jr z, .jump + cp (OLD_COLLISION_ROCK | COLLISION_FLAG) + jr nz, .collision + +.jump + ld a, FAST_JUMP_DOWN + ret + +.can_skate + call OldIsTileCollisionGrass + jr z, .slow + ld a, FAST_STEP_DOWN + ret + +.slow + ld a, STEP_DOWN + ret + +.collision + ld a, STANDING + ld [wSkatingDirection], a + ld a, FACE_DOWN + ret + +CheckSkateUp: ; 03:41ab + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerNextMapY], a + ld a, UP + ld [wSkatingDirection], a + call CheckPlayerObjectCollision + jr c, .collision + call IsPlayerCollisionTileSolid + jr nc, .can_skate + cp (OLD_COLLISION_ROCK | COLLISION_FLAG) + jr nz, .collision + ld a, FAST_JUMP_UP + ret + +.can_skate + call OldIsTileCollisionGrass + jr z, .slow + ld a, FAST_STEP_UP + ret + +.slow + ld a, STEP_UP + ret + +.collision + ld a, STANDING + ld [wSkatingDirection], a + ld a, FACE_UP + ret + +CheckSkateLeft: ; 03:41db + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerNextMapX], a + ld a, LEFT + ld [wSkatingDirection], a + call CheckPlayerObjectCollision + jr c, .collision + call IsPlayerCollisionTileSolid + jr nc, .can_skate + cp (OLD_COLLISION_ROCK | COLLISION_FLAG) + jr nz, .collision + ld a, FAST_JUMP_LEFT + ret + +.can_skate + call OldIsTileCollisionGrass + jr z, .slow + ld a, FAST_STEP_LEFT + ret + +.slow + ld a, STEP_LEFT + ret + +.collision + ld a, STANDING + ld [wSkatingDirection], a + ld a, FACE_LEFT + ret + +CheckSkateRight: ; 03:420b + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerNextMapX], a + ld a, RIGHT + ld [wSkatingDirection], a + call CheckPlayerObjectCollision + jr c, .collision + call IsPlayerCollisionTileSolid + jr nc, .can_skate + cp (OLD_COLLISION_ROCK | COLLISION_FLAG) + jr nz, .collision + ld a, FAST_JUMP_RIGHT + ret + +.can_skate + call OldIsTileCollisionGrass + jr z, .slow + ld a, FAST_STEP_RIGHT + ret + +.slow + ld a, STEP_RIGHT + ret + +.collision + ld a, STANDING + ld [wSkatingDirection], a + ld a, FACE_RIGHT + ret + +OldIsTileCollisionGrass:: ; 03:423b +; 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:: ; 03:4247 + call _OldCheckMovementSurf + jp SetPlayerMovement + +_OldCheckMovementSurf: ; 03:424d + ld a, d + and D_PAD + bit D_DOWN_F, a + jp nz, .check_down + bit D_UP_F, a + jp nz, .check_up + bit D_LEFT_F, a + jp nz, .check_left + bit D_RIGHT_F, a + jr nz, .check_right + ld a, NO_MOVEMENT + ret + +.check_down + ld a, [wPlayerLastMapY] + inc a + ld [wPlayerNextMapY], a + call CheckPlayerObjectCollision + jr c, .face_down + call IsPlayerCollisionTileSolid + jr nc, .exit_water_down ; 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, .face_down + ld a, STEP_DOWN + ret +.face_down + ld a, FACE_DOWN + ret +.exit_water_down + call SetPlayerStateWalk + ld a, SLOW_STEP_DOWN + ret + +.check_up + ld a, [wPlayerLastMapY] + dec a + ld [wPlayerNextMapY], a + call CheckPlayerObjectCollision + jr c, .face_up + call IsPlayerCollisionTileSolid + jr nc, .exit_water_up ; 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, .face_up + ld a, STEP_UP + ret +.face_up + ld a, FACE_UP + ret +.exit_water_up + call SetPlayerStateWalk + ld a, SLOW_STEP_UP + ret + +.check_left + ld a, [wPlayerLastMapX] + dec a + ld [wPlayerNextMapX], a + call CheckPlayerObjectCollision + jr c, .face_left + call IsPlayerCollisionTileSolid + jr nc, .exit_water_left ; 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, .face_left + ld a, STEP_LEFT + ret +.face_left + ld a, FACE_LEFT + ret +.exit_water_left + call SetPlayerStateWalk + ld a, SLOW_STEP_LEFT + ret + +.check_right + ld a, [wPlayerLastMapX] + inc a + ld [wPlayerNextMapX], a + call CheckPlayerObjectCollision + jr c, .face_right + call IsPlayerCollisionTileSolid + jr nc, .exit_water_right ; 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, .face_right + ld a, STEP_RIGHT + ret +.face_right + ld a, FACE_RIGHT + ret +.exit_water_right + call SetPlayerStateWalk + ld a, SLOW_STEP_RIGHT + ret + +OldIsTileCollisionWater:: ; 03: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:: ; 03:42f8 + push bc + ld a, PLAYER_NORMAL + ld [wPlayerState], a + call RedrawPlayerSprite + pop bc + ret + +IsPlayerCollisionTileSolid:: ; 03:4303 +; 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 + callab _IsObjectCollisionTileSolid + ld a, e + pop de + ret + +CheckPlayerObjectCollision:: ; 03:4312 +; Check whether player object currentl +; collides with any other object. +; Result: +; nc - no collision +; c - collision + push de + callab _CheckPlayerObjectCollision + pop de + ret nc + jp CheckCompanionObjectCollision + +CheckCompanionObjectCollision:: ; 03:4320 +; Marks the object struct pointed to by hl +; as having collided with player object. +; If object struct (as identified by hObjectStructIndexBuffer) +; is companion, cancel collision on 5th frames. +; Result: +; nc - no collision +; c - collision + ld hl, OBJECT_FLAGS + 1 + add hl, bc + set 1, [hl] ; mark object as having collided with player + ldh a, [hObjectStructIndexBuffer] + cp COMPANION_OBJECT_INDEX + jr z, .is_companion + xor a + ld [wCompanionCollisionFrameCounter], a + scf + ret +.is_companion + ld a, [wCompanionCollisionFrameCounter] + inc a + cp 5 + ld [wCompanionCollisionFrameCounter], a + jr z, .cancel_collision + scf + ret +.cancel_collision + xor a + ld [wCompanionCollisionFrameCounter], a + ret + +_OverworldMovementCheck:: ; 03:4344 + ld a, PLAYER_OBJECT_INDEX + ldh [hEventCollisionException], a + ld a, [wPlayerDirection] + and a + jp z, SetPlayerIdle + ldh a, [hJoyState] + ld d, a + ld hl, wDebugFlags + bit DEBUG_FIELD_F, [hl] + jr z, .skip_debug_move + bit B_BUTTON_F, d + jp nz, CheckMovementDebug + +.skip_debug_move + call GetPlayerMovementByState + jp SetPlayerMovement + +GetPlayerMovementByState: ; 03:4364 + ld a, [wPlayerState] + cp PLAYER_SKATE + jp z, CheckMovementSkateboard ; FIXME: CheckMovementSkateboard already calls SetPlayerMovement + ; The skateboard doesn't work, because it uses the current + ; coordinate as player animation. + cp PLAYER_SURF + jp z, CheckMovementSurf + jp CheckMovementWalk + +CheckMovementWalk:: ; 03:4374 + ld a, [wPlayerStandingTile] + swap a + and LOW((COLLISION_TYPE_MASK >> 4) | (COLLISION_TYPE_MASK << 4)) + ld hl, .WalkingCollisionTable + jp CallJumptable + +.WalkingCollisionTable ; 03:4381 + 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 + +NoWalkMovement: ; 03:43a1 + ld a, NO_MOVEMENT + ret + +CheckMovementWalkSolid:: ; 03:43a4 + jp CheckMovementWalkRegular + +CheckMovementWalkLand:: ; 03:43a7 + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + jr nz, .force_movement + call CheckMovementWalkRegular + call SlowDownMovementWalk + ret + +.force_movement + ld b, STEP_DOWN + cp (COLLISION_LAND_S & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_UP + cp (COLLISION_LAND_N & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_LEFT + cp (COLLISION_LAND_W & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_RIGHT + cp (COLLISION_LAND_E & COLLISION_SUBTYPE_MASK) + jr z, .finish + ; fall-through --> map other codes to COLLISION_LAND_E +.finish + ld a, b + ret + +SlowDownMovementWalk: ; 03:43cf + ld b, SLOW_STEP_DOWN + cp STEP_DOWN + jr z, .finish + ld b, SLOW_STEP_UP + cp STEP_UP + jr z, .finish + ld b, SLOW_STEP_LEFT + cp STEP_LEFT + jr z, .finish + ld b, SLOW_STEP_RIGHT + cp STEP_RIGHT + jr z, .finish + ret +.finish + ld a, b + ret + +CheckMovementWalkLand2:: ; 03:43ea + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + ld b, STEP_DOWN + cp (COLLISION_LAND2_S & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_UP + cp (COLLISION_LAND2_N & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_LEFT + cp (COLLISION_LAND2_W & COLLISION_SUBTYPE_MASK) + jr z, .finish + ld b, STEP_RIGHT + cp (COLLISION_LAND2_E & COLLISION_SUBTYPE_MASK) + jr z, .finish + ; fall-through --> map other codes to COLLISION_LAND2_E +.finish + ld a, b + ret + +UnusedCheckMovementWalk60:: ; 03:4409 + jp CheckMovementWalkRegular + +CheckMovementWalkWarp:: ; 03:440c + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + jr z, .check_dpad + cp 1 + jr z, .move_down + ld a, [wPlayerStandingTile] + cp $7a + jr z, .move_down + jp CheckMovementWalkRegular +.move_down + ld a, STEP_DOWN + ret + +.check_dpad + ldh a, [hJoyState] + bit D_DOWN_F, a + jr nz, .down + bit D_UP_F, a + jr nz, .up + bit D_LEFT_F, a + jr nz, .left + bit D_RIGHT_F, a + jr nz, .right + jp NoWalkMovement + +.down + ld a, [wTileDown] + cp -1 + jp nz, CheckMovementWalkRegular + call z, .moved_out_of_bounds + ld a, FACE_DOWN + ret +.up + ld a, [wTileUp] + cp -1 + jp nz, CheckMovementWalkRegular + call z, .moved_out_of_bounds + ld a, FACE_UP + ret +.left + ld a, [wTileLeft] + cp -1 + jp nz, CheckMovementWalkRegular + call z, .moved_out_of_bounds + ld a, FACE_LEFT + ret +.right + ld a, [wTileRight] + cp -1 + jp nz, CheckMovementWalkRegular + call z, .moved_out_of_bounds + ld a, FACE_RIGHT + ret + +.moved_out_of_bounds + ret + +CheckMovementWalkMisc:: ; 03:4472 + jp CheckMovementWalkRegular + +CheckMovementWalkSpecial:: ; 03:4475 + jp CheckMovementWalkRegular + +CheckMovementWalkRegular:: ; 03:4478 + ldh a, [hJoyState] + bit D_DOWN_F, a + jp nz, CheckWalkDown + bit D_UP_F, a + jp nz, CheckWalkUp + bit D_LEFT_F, a + jp nz, CheckWalkLeft + bit D_RIGHT_F, a + jp nz, CheckWalkRight + jp NoWalkMovement + +CheckMovementWalkJump: ; 03:4491 + ldh a, [hJoyState] + bit D_DOWN_F, a + jr nz, .down + bit D_UP_F, a + jr nz, .up + bit D_LEFT_F, a + jr nz, .left + bit D_RIGHT_F, a + jr nz, .right + jp NoWalkMovement + +.down + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_S & COLLISION_SUBTYPE_MASK) + jr z, .jump_down + cp (COLLISION_JUMP_SE & COLLISION_SUBTYPE_MASK) + jr z, .jump_down + cp (COLLISION_JUMP_SW & COLLISION_SUBTYPE_MASK) + jr z, .jump_down + jp CheckWalkDown +.jump_down + ld a, JUMP_DOWN + ret + +.up + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_N & COLLISION_SUBTYPE_MASK) + jr z, .jump_up + cp (COLLISION_JUMP_NE & COLLISION_SUBTYPE_MASK) + jr z, .jump_up + cp (COLLISION_JUMP_NW & COLLISION_SUBTYPE_MASK) + jr z, .jump_up + jp CheckWalkUp +.jump_up + ld a, JUMP_UP + ret + +.left + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_W & COLLISION_SUBTYPE_MASK) + jr z, .jump_left + cp (COLLISION_JUMP_SW & COLLISION_SUBTYPE_MASK) + jr z, .jump_left + cp (COLLISION_JUMP_NW & COLLISION_SUBTYPE_MASK) + jr z, .jump_left + jp CheckWalkLeft +.jump_left + ld a, JUMP_LEFT + ret + +.right + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_JUMP_E & COLLISION_SUBTYPE_MASK) + jr z, .jump_right + cp (COLLISION_JUMP_SE & COLLISION_SUBTYPE_MASK) + jr z, .jump_right + cp (COLLISION_JUMP_NE & COLLISION_SUBTYPE_MASK) + jr z, .jump_right + jp CheckWalkRight +.jump_right + ld a, JUMP_RIGHT + ret + +CheckWalkDown:: ; 03:4502 + ld d, 0 + ld e, 1 + call CheckObjectCollision + jr c, .face_down + ld a, [wTileDown] + call CheckCollisionSolid + jr c, .face_down + ld a, STEP_DOWN + ret +.face_down + ld a, FACE_DOWN + ret + +CheckWalkUp:: ; 03:4519 + ld d, 0 + ld e, -1 + call CheckObjectCollision + jr c, .face_up + ld a, [wTileUp] + call CheckCollisionSolid + jr c, .face_up + ld a, STEP_UP + ret +.face_up + ld a, FACE_UP + ret + +CheckWalkLeft:: ; 03:4530 + ld d, -1 + ld e, 0 + call CheckObjectCollision + jr c, .face_left + ld a, [wTileLeft] + call CheckCollisionSolid + jr c, .face_left + ld a, STEP_LEFT + ret +.face_left + ld a, FACE_LEFT + ret + +CheckWalkRight:: ; 03:4547 + ld d, 1 + ld e, 0 + call CheckObjectCollision + jr c, .face_right + ld a, [wTileRight] + call CheckCollisionSolid + jr c, .face_right + ld a, STEP_RIGHT + ret +.face_right + ld a, FACE_RIGHT + ret + +CheckMovementSurf:: ; 03:455e + ld a, [wPlayerStandingTile] + swap a + and LOW((COLLISION_TYPE_MASK >> 4) | (COLLISION_TYPE_MASK << 4)) + ld hl, .SurfCollisionTable + jp CallJumptable + +.SurfCollisionTable ; 03:456b + 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:: ; 03:458b + ldh a, [hJoyState] + bit D_DOWN_F, a + jp nz, CheckSurfDown + bit D_UP_F, a + jp nz, CheckSurfUp + bit D_LEFT_F, a + jp nz, CheckSurfLeft + bit D_RIGHT_F, a + jp nz, CheckSurfRight + jp NoWalkMovement + +CheckMovementSurfWater:: ; 03:45a4 + ld a, [wPlayerStandingTile] + and COLLISION_SUBTYPE_MASK + cp (COLLISION_WATERFALL & COLLISION_SUBTYPE_MASK) + jr nz, CheckMovementSurfRegular +; waterfall + ld a, FAST_STEP_DOWN + ret + +CheckMovementSurfWater2:: ; 03:45b0 + ld a, [wPlayerStandingTile] + and COLLISION_WATER_SUBTYPE_MASK + ld d, STEP_RIGHT + jr z, .finish ; COLLISION_WATER2_E + ld d, STEP_LEFT + cp (COLLISION_WATER2_W & COLLISION_WATER_SUBTYPE_MASK) + jr z, .finish + ld d, STEP_UP + cp (COLLISION_WATER2_N & COLLISION_WATER_SUBTYPE_MASK) + jr z, .finish + ld d, STEP_DOWN + cp (COLLISION_WATER2_S & COLLISION_WATER_SUBTYPE_MASK) + jr z, .finish + ; fall-through --> no aliasing due to mask +.finish + ld a, d + ret + +CheckSurfDown: ; 03:45cd + ld d, 0 + ld e, 1 + call CheckObjectCollision + jr c, .face_down + ld a, [wTileDown] + call CheckCollisionSometimesSolid + jr c, .face_down ; 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, STEP_DOWN + ret +.face_down + ld a, FACE_DOWN + ret + +CheckSurfUp: ; 03:45e7 + ld d, 0 + ld e, -1 + call CheckObjectCollision + jr c, .face_up + ld a, [wTileUp] + call CheckCollisionSometimesSolid + jr c, .face_up ; 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, STEP_UP + ret +.face_up + ld a, FACE_UP + ret + +CheckSurfLeft: ; 03:4601 + ld d, -1 + ld e, 0 + call CheckObjectCollision + jr c, .face_left + ld a, [wTileLeft] + call CheckCollisionSometimesSolid + jr c, .face_left ; 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, STEP_LEFT + ret +.face_left + ld a, FACE_LEFT + ret + +CheckSurfRight: ; 03:461b + ld d, 1 + ld e, 0 + call CheckObjectCollision + jr c, .face_right + ld a, [wTileRight] + call CheckCollisionSometimesSolid + jr c, .face_right ; 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, STEP_RIGHT + ret +.face_right + ld a, FACE_RIGHT + ret + +SurfDismount: ; 03:4635 + jp SetPlayerStateWalk + +CheckObjectCollision:: ; 03:4638 +; 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 +; hObjectStructIndexBuffer - Event ID of colliding event + ld a, PLAYER_OBJECT_INDEX + ldh [hEventCollisionException], a + ld a, [wPlayerNextMapX] + add d + ld d, a + ld a, [wPlayerNextMapY] + add e + ld e, a + callab _CheckObjectCollision + 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, 0 + add hl, de + ld a, [hl] + pop de + ret + +SECTION "Rest of Player Movement", ROMX[$4764], BANK[$3] + +_UnusedReturnFalse:: ; 03:4764 + xor a + ret + +_UnusedReturnTrue:: ; 03:4766 + xor a + scf + ret + +CheckCollisionSometimesSolid:: ; 03:4769 +; 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 SOMETIMES_SOLID + jr z, .sometimes_solid + and a + jr z, .never_solid + jr .always_solid +.sometimes_solid + xor a + ret +.never_solid + ld a, 1 + and a + ret +.always_solid + scf + ret + + +SECTION "_RedrawPlayerSprite", ROMX[$4000], BANK[$05] + +_RedrawPlayerSprite: ; 05:4000 + call GetPlayerSprite + ld hl, vChars0 + call LoadOverworldSprite + ret + +GetPlayerSprite: ; 05:400a + ld a, [wPlayerState] + ld hl, PlayerSpriteTable + ld c, a +.loop + ld a, [hli] + cp c + jr z, .match + inc hl + cp -1 + jr nz, .loop + xor a + ld [wPlayerState], a + ld a, SPRITE_GOLD + jr .skip +.match + ld a, [hl] +.skip + ld [wUsedSprites], a + ld [wPlayerSprite], a + ld [wPlayerObjectSprite], a + ret + +PlayerSpriteTable: ; 03:402d +; state, sprite + db PLAYER_NORMAL, SPRITE_GOLD + db PLAYER_BIKE, SPRITE_GOLD_BIKE + db PLAYER_SKATE, SPRITE_GOLD_SKATEBOARD + db PLAYER_SURF, SPRITE_LAPLACE + db -1 diff --git a/data/sprites/sprites.asm b/engine/sprites/sprites.asm index b901b7a..a1dc401 100644 --- a/data/sprites/sprites.asm +++ b/engine/sprites/sprites.asm @@ -1,5 +1,58 @@ INCLUDE "constants.asm" +SECTION "LoadOverworldSprite", ROMX[$4150], BANK[$05] + +LoadOverworldSprite: ; 05:4150 + push af + call GetOverworldSpriteData + push bc + push hl + push de + ld a, [wcdaf] + bit 7, a + jr nz, .dont_copy + call Get2bpp +.dont_copy + pop de + ld hl, SPRITE_TILE_SIZE * 3 + add hl, de + ld d, h + ld e, l + pop hl + ld bc, vChars1 - vChars0 + add hl, bc + pop bc + pop af + call IsAnimatedSprite + ret c + ld a, [wcdaf] + bit 6, a + ret nz + call Get2bpp + ret + +; get the data for overworld sprite in a +; returns: gfx ptr in hl, length in c, bank in b +GetOverworldSpriteData: ; 05:417d + push hl + dec a + ld l, a + ld h, 0 + add hl, hl + add hl, hl + ld bc, OverworldSprites + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld c, [hl] + swap c + inc hl + ld b, [hl] + pop hl + ret + SECTION "OverworldSprites", ROMX[$423B], BANK[$05] overworld_sprite: MACRO diff --git a/home/copy2.asm b/home/copy2.asm index 9baad62..e74ef8b 100644 --- a/home/copy2.asm +++ b/home/copy2.asm @@ -2,8 +2,8 @@ INCLUDE "constants.asm" SECTION "Video Copy functions", ROM0[$0D02] -Function0d02:: - jpab Function14000 +RedrawPlayerSprite:: + jpab _RedrawPlayerSprite LoadFont:: ; 00:0d0a jpab LoadFontGraphics diff --git a/home/map.asm b/home/map.asm index d33242a..7b9bd71 100644 --- a/home/map.asm +++ b/home/map.asm @@ -448,8 +448,8 @@ FadeIn:: ; 23e5 ; This is not OverworldFadeIn, but I don't know what it is ret Function2407:: ; 00:2407 - ld a, $2a - ld [wcb77], a + ld a, NO_MOVEMENT + ld [wPlayerMovement], a xor a ld [wPlayerAction], a ld a, [wPlayerFacing] @@ -505,7 +505,7 @@ CheckMovingOffEdgeOfMap:: ; 245e ret .down - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] sub 4 ld b, a ld a, [wMapHeight] @@ -516,7 +516,7 @@ CheckMovingOffEdgeOfMap:: ; 245e ret .up - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] sub 4 cp -1 jr z, .ok @@ -524,7 +524,7 @@ CheckMovingOffEdgeOfMap:: ; 245e ret .left - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] sub 4 cp -1 jr z, .ok @@ -532,7 +532,7 @@ CheckMovingOffEdgeOfMap:: ; 245e ret .right - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] sub 4 ld b, a ld a, [wMapWidth] @@ -701,10 +701,10 @@ WarpCheck:: ; 259f ret GetDestinationWarpPointer: ; 25b9 - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] sub 4 ld d, a - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] sub 4 ld e, a ld a, [wCurrMapWarpCount] @@ -1028,10 +1028,10 @@ Function275e:: ; 275e ; TODO: is this used? ld [wOverworldMapAnchor + 1], a ld a, [wYCoord] and 1 - ld [wMetatileStandingY], a + ld [wMetatileNextY], a ld a, [wXCoord] and 1 - ld [wMetatileStandingX], a + ld [wMetatileNextX], a ret @@ -1075,10 +1075,10 @@ GetCoordOfUpperLeftCorner:: ; 277a ld [wOverworldMapAnchor + 1], a ld a, [wYCoord] and 1 - ld [wMetatileStandingY], a + ld [wMetatileNextY], a ld a, [wXCoord] and 1 - ld [wMetatileStandingX], a + ld [wMetatileNextX], a ret Function27C7:: ; 27c7 ; TODO @@ -1175,13 +1175,13 @@ LoadMetatiles:: ; 2822 ApplyFlashlight:: ; 285a ld hl, wTileMapBackup - ld a, [wMetatileStandingY] + ld a, [wMetatileNextY] and a jr z, .top_row ld bc, $30 ; TODO: constantify this add hl, bc .top_row - ld a, [wMetatileStandingX] + ld a, [wMetatileNextX] and a jr z, .left_col inc hl @@ -1612,7 +1612,7 @@ Function2ae5:: ret nz call OverworldStartButtonCheck ret nz - callab Functionc000 + callab OverworldMovementCheck ldh a, [hMapEntryMethod] and a ret nz @@ -1677,7 +1677,7 @@ Function2b87:: call GetJoypad call OverworldStartButtonCheck ret nz - callab Functionc000 + callab OverworldMovementCheck call Function2ba8 jr nc, .asm_2b87 callba Function824c diff --git a/home/map_objects.asm b/home/map_objects.asm index faa4bb9..c473e13 100644 --- a/home/map_objects.asm +++ b/home/map_objects.asm @@ -335,27 +335,34 @@ Function17cb:: call Bankswitch ret -CheckNonTurningSprite:: ; 00:17de - ; sets carry flag if a is equal to any of the sprites below +; sets carry flag if the sprite data includes "in-motion" sprites +IsAnimatedSprite:: ; 00:17de push hl push bc ld c, a - ld b, $ff - ld hl, .Data -.loop: + ld b, -1 + ld hl, .NonAnimatedSprites +.loop ld a, [hli] cp b - jr z, .escape + jr z, .done cp c jr nz, .loop scf -.escape: +.done pop bc pop hl ret -.Data: ; 00:17f1 - db SPRITE_KABIGON, SPRITE_POKE_BALL, SPRITE_POKEDEX, SPRITE_PAPER, SPRITE_OLD_LINK_RECEPTIONIST, SPRITE_EGG, SPRITE_BOULDER, $ff +.NonAnimatedSprites: ; 00:17f1 + db SPRITE_KABIGON + db SPRITE_POKE_BALL + db SPRITE_POKEDEX + db SPRITE_PAPER + db SPRITE_OLD_LINK_RECEPTIONIST + db SPRITE_EGG + db SPRITE_BOULDER + db -1 Function17f9:: call GetMapObject diff --git a/home/talk_to_npc.asm b/home/talk_to_npc.asm index 7f4452c..69bee3e 100644 --- a/home/talk_to_npc.asm +++ b/home/talk_to_npc.asm @@ -226,7 +226,7 @@ TextboxCleanup: ; 00:3171 Function318f: ; 00:318f callab Function140ea - call Function0d02 + call RedrawPlayerSprite ret TurnNPCTalkingTo:: ; 00:319b @@ -236,7 +236,7 @@ TurnNPCTalkingTo:: ; 00:319b ld hl, OBJECT_SPRITE add hl, bc ld a, [hl] - call CheckNonTurningSprite + call IsAnimatedSprite jr c, .Jump ld a, [wPlayerWalking] xor 04 @@ -290,12 +290,12 @@ GetInlineMapObject:: ; 00:31EB ;bc is start of object struct. if c flag set, returns distance in B and direction in C ld hl, OBJECT_NEXT_MAP_X add hl, bc - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] cp [hl] jr z, .EqualX ld hl, OBJECT_NEXT_MAP_Y add hl, bc - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] cp [hl] jr z, .EqualY and a @@ -303,7 +303,7 @@ GetInlineMapObject:: ; 00:31EB .EqualX ld hl, OBJECT_NEXT_MAP_Y add hl, bc - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] sub [hl] jr z, .Reset jr nc, .SetDown @@ -321,7 +321,7 @@ GetInlineMapObject:: ; 00:31EB .EqualY ; 3219 ld hl, OBJECT_NEXT_MAP_X add hl, bc - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] sub [hl] jr z, .Reset ; (this condition is impossible to meet) jr nc, .SetRight diff --git a/home/text.asm b/home/text.asm index 5d5f607..48662e9 100644 --- a/home/text.asm +++ b/home/text.asm @@ -232,7 +232,7 @@ NullChar:: ; 00:0f66 ret .Text: - deciram hTextErrno, 1, 2 + deciram hEventID, 1, 2 text "エラー" done diff --git a/home/tileset.asm b/home/tileset.asm index 38b9779..4512728 100644 --- a/home/tileset.asm +++ b/home/tileset.asm @@ -50,7 +50,7 @@ RefreshPlayerCoords:: ; 2d74 ld a, [wXCoord] add a, 4 ld d, a - ld hl, wPlayerStandingMapX + ld hl, wPlayerNextMapX sub [hl] ld [hl], d ld hl, wPlayerObjectXCoord @@ -61,7 +61,7 @@ RefreshPlayerCoords:: ; 2d74 ld a, [wYCoord] add a, 4 ld e, a - ld hl, wPlayerStandingMapY + ld hl, wPlayerNextMapY sub [hl] ld [hl], e ld hl, wPlayerObjectYCoord @@ -211,18 +211,18 @@ SaveScreen:: ; 2df1 RefreshTiles:: ; 2e52 call .left_right call .up_down - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] ld d, a - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] ld e, a call GetCoordTile ld [wPlayerStandingTile], a ret .up_down ; 2e67 - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] ld d, a - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] ld e, a push de inc e @@ -235,9 +235,9 @@ RefreshTiles:: ; 2e52 ret .left_right ; 2e80 - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] ld d, a - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] ld e, a push de dec d @@ -270,10 +270,10 @@ GetFacingTileCoord:: ; 2e99 ld h, [hl] ld l, a - ld a, [wPlayerStandingMapX] + ld a, [wPlayerNextMapX] add a, d ld d, a - ld a, [wPlayerStandingMapY] + ld a, [wPlayerNextMapY] add a, e ld e, a ld a, [hl] @@ -66,8 +66,8 @@ UNION hTextBoxCursorBlinkInterval:: ds 2 ; ffaf NEXTU - ds 1 ; TODO -hTextErrno:: db ; ffb0 +hEventCollisionException:: db ; ffaf +hEventID:: db ;; ffb0 NEXTU @@ -79,17 +79,13 @@ hSpriteHeight:: ; ffb0 NEXTU -hConnectionStripLength:: ; ffaf - db -hConnectedMapWidth:: ; ffb0 - db +hConnectionStripLength:: db ; ffaf +hConnectedMapWidth:: db ; ffb0 NEXTU -hMapObjectIndexBuffer:: ; ffaf - db -hObjectStructIndexBuffer:: ; ffb0 - db +hMapObjectIndexBuffer:: db ; ffaf +hObjectStructIndexBuffer:: db ; ffb0 ENDU diff --git a/macros/wram.asm b/macros/wram.asm index da67ba5..4433267 100644 --- a/macros/wram.asm +++ b/macros/wram.asm @@ -275,8 +275,8 @@ object_struct: MACRO \1Facing:: ds 1 \1StandingTile:: ds 1 ; collision \1LastTile:: ds 1 ; collision -\1StandingMapX:: ds 1 -\1StandingMapY:: ds 1 +\1NextMapX:: ds 1 +\1NextMapY:: ds 1 \1LastMapX:: ds 1 \1LastMapY:: ds 1 \1ObjectInitX:: ds 1 @@ -41,7 +41,6 @@ 02:528B Function928b 02:5695 CheckSGB -03:4000 Functionc000 03:47D5 SpawnPoints 03:488D Tilesets 03:54E6 Functiond4e6 @@ -70,8 +69,6 @@ 04:640B Function1240b 04:6C58 CheckRegisteredItem -05:4000 Function14000 -05:400A GetPlayerSprite 05:4036 RefreshSprites 05:404C CheckInteriorMap 05:405B AddIndoorSprites @@ -257,7 +257,7 @@ wVBCopyFarSize:: ds 1 ; cb71 wVBCopyFarSrc:: ds 2 ; cb72 wVBCopyFarDst:: ds 2 ; cb74 wVBCopyFarSrcBank:: ds 1 ; cb76 -wcb77:: db ; cb77 +wPlayerMovement:: db ; cb77 wMovementObject:: db ; cb78 ptrba wMovementData ; cb79 @@ -348,7 +348,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 @@ -466,15 +469,16 @@ wItemQuantity:: db ; cd7d wItemQuantityBuffer:: db ; cd7e SECTION "CD9E", WRAM0 [$CD9E] +wcd9e:: db ; cd9e -wcd9e:: - db +SECTION "CDAF", WRAM0 [$CDAF] +wcdaf:: db ; cdaf SECTION "CDB0", WRAM0 [$CDB0] wTalkingTargetType:: db ; cdb0 ;bit 0 = has engaged NPC in dialogue ;bit 1 = has engaged sign in dialogue - + SECTION "CDBA", WRAM0[$CDBA] wItemAttributeParamBuffer:: db ; cdba @@ -762,6 +766,11 @@ wRivalName:: ds 6 ; d258 ds 6 wPlayerState:: db ; d264 +; 00 - walking +; 01 - bicycle +; 02 - skateboard +; 04 - surfing + wd265:: db ; d265 wd266:: db ; d266 @@ -855,8 +864,8 @@ wOverworldMapAnchor:: ; d658 wYCoord:: db ; d65a wXCoord:: db ; d65b -wMetatileStandingY:: db ; d65c -wMetatileStandingX:: db ; d65d +wMetatileNextY:: db ; d65c +wMetatileNextX:: db ; d65d wd65e:: ; d65e db |