U.Flame

Humbled Beginner

Age 24
Male
Sapphire City
Seen 16 Hours Ago
Posted 3 Days Ago
1,285 posts
11.4 Years
I recently implement Spherical Ice's and Sqeetz's Dive in Firered ASM seen in this thread: https://www.pokecommunity.com/showthread.php?t=257723

It all seemed to work nicely until I noticed the palette for the female dive sprite was a bit off. After going into a menu or battle, returning the the overworld shows that the sprite has completely glitched. Then going into a menu or battle again and returning shows the sprite in it's default non-dive version. This includes behavior as the sprite no longer bobs, and can run underwater, essentially undoing the dive state.

After testing this with the male player, I noticed that the palette is very slightly different, similar but not as noticeable as the female player. But unlike the female player, the sprite remains functional and even has the palette corrected.

So what's causing the female version to break like this? Why are their palettes off until entering and leaving a menu? Did I do something wrong or is the problem in the asm itself? Here is the code as I implemented it. The only changes made were in the "Change these" section, listing the free space offset and the dive sprite number. The free 0x400 bytes of free space and dive flag didn't need to be changed as the code takes up 0x244 bytes and the badge flag is unchanged. I followed the instructions as listed. Changed the file from .asm to .s as the assembly command lists it. Either file format seems to have no difference when opening in Notepad++. Then I assembled it with Windows command line, created an IPS patch using the base file included in the original post and the newly output file generated from the assembly. Then patched that to my ROM.

Spoiler:
.thumb
.global firered_dive

@ FireRed v1.0 HM08 DIVE Port
@ Credits: Spherical Ice, Squeetz

@ CHANGE THESE:
.equ offset, 0xB7DCB0 @ ROM address of 0x400 bytes of free space
.equ OW_MALE_DIVE, 148 @ male player's diving overworld sprite number
.equ OW_FEMALE_DIVE, 149 @ female player's diving overworld sprite number
.equ FLAG_ALLOW_DIVE, 0x827 @ flag which allows the use of Dive
@ YOU MUST CHANGE THE ABOVE VALUES

@ INSTALL:
@ 1. Change the .equ values above, labelled CHANGE THESE
@ 2. If you wish to disable badge checking, follow the DISABLE BADGE CHECKING instructions below
@ 3. Save this file
@ 4. Assemble this file using the following command:
@ thumb firered_dive.s firered_dive.gba
@ 5. Create a .IPS patch using Lunar IPS:
@ Use the included base.gba file as the base ROM
@ Use the newly generated firered_dive.gba file as the modified ROM
@ 6. Patch your FireRed v1.0 ROM with the generated .IPS patch
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ DISABLE BADGE CHECKS:
@ Find and remove the appropriately labelled lines of code below
@ Ctrl + F: REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ MAKE DIVE POSSIBLE IN MAPS:
@ Set the second behaviour byte of Dive-able tiles to the value of DIVE_TILE_BYTE below (0x23 by default)
@ Set their second behaviour byte of Emerge-able tiles to the value of EMERGE_TILE_BYTE below (0x24 by default)
@ Set underwater maps' light level (the Type: field in the Header view on AdvanceMap) to Underwater (0x5)
@ Create Emerge map connections to underwater maps leading to their surface maps
@ Create Dive map connections to surface maps leading to their underwater maps
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ Changing these is optional (they are the default FireRed currently)
.equ OW_MALE_WALK, 0 @ male player's normal, walking overworld sprite number
.equ OW_MALE_CYCLE, 1 @ male player's cycling overworld sprite number
.equ OW_MALE_SURF, 2 @ male player's surfing/"sat down" overworld sprite number
.equ OW_MALE_ITEM_0, 3 @ male player's first item usage overworld sprite number
.equ OW_MALE_FISH, 4 @ male player's fishing overworld sprite number
.equ OW_MALE_ITEM_1, 5 @ male player's second item usage overworld sprite number
.equ OW_FEMALE_WALK, 7 @ female player's normal, walking overworld sprite number
.equ OW_FEMALE_CYCLE, 8 @ female player's cycling overworld sprite number
.equ OW_FEMALE_SURF, 9 @ female player's surfing/"sat down" overworld sprite number
.equ OW_FEMALE_ITEM_0, 10 @ female player's first item usage overworld sprite number
.equ OW_FEMALE_FISH, 11 @ female player's fishing overworld sprite number
.equ OW_FEMALE_ITEM_1, 12 @ female player's second item usage overworld sprite number
.equ DIVE_TILE_BYTE, 0x23 @ second behaviour byte value for diving
.equ EMERGE_TILE_BYTE, 0x24 @ second behaviour byte value for emerging
.equ FLAG_ALLOW_RUN, 0x82F @ flag which allows the use of the Running Shoes
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@ DO NOT CHANGE THESE VALUES:
.equ rom, 0x08000000
@ DO NOT CHANGE THE ABOVE VALUES

@ Hooks and branches
.org 0x5BA30, 0xFF
ldr r0, =(disable_running_underwater + rom + 1)
bx r0
.pool

.org 0x5C7F4, 0xFF
.word player_overworld_list + rom

.org 0x5C826, 0xFF
ldr r1, =(get_gender_from_sprite + rom + 1)
bx r1
.pool

.org 0x5C9B0, 0xFF
.word walkrun_overworld_list + rom

.org 0x5C9BA, 0xFF
cmp r2, #3

.org 0x5C9F4, 0xFF
.word walkrun_overworld_list + rom

.org 0x6CB30, 0xFF
ldr r0, =(check_for_events + rom + 1)
bx r0
.pool

.org 0x6CCCC, 0xFF
ldr r1, =(check_dive + rom + 1)
bx r1
.pool

.org 0x6DF78, 0xFF
b 0x6DF84

.org 0x35B854, 0xFF
.word change_sprite_to_diving + rom + 1

.org 0x471EEC, 0xFF
.word player_behaviour_dive + rom + 1

.org offset, 0xFF
@ New data
player_overworld_list:
.byte OW_MALE_WALK, OW_FEMALE_WALK
.byte OW_MALE_CYCLE, OW_FEMALE_CYCLE
.byte OW_MALE_SURF, OW_FEMALE_SURF
.byte OW_MALE_ITEM_0, OW_FEMALE_ITEM_0
.byte OW_MALE_FISH, OW_FEMALE_FISH
.byte OW_MALE_ITEM_1, OW_FEMALE_ITEM_1
.byte OW_MALE_DIVE, OW_FEMALE_DIVE

walkrun_overworld_list:
.byte OW_MALE_WALK, 0b00001
.byte OW_MALE_CYCLE, 0b00010
.byte OW_MALE_SURF, 0b01000
.byte OW_MALE_DIVE, 0b10000
.byte OW_FEMALE_WALK, 0b00001
.byte OW_FEMALE_CYCLE, 0b00010
.byte OW_FEMALE_SURF, 0b01000
.byte OW_FEMALE_DIVE, 0b10000

@ New code
disable_running_underwater:
ldr r6, =(0x02037078) @ walkrun_state
ldrb r1, [r6, #0] @ walkrun->bitfield
mov r0, #16
and r0, r1
cmp r0, #0
bne i_forgot_what_this_label_is
mov r0, #2
and r5, r0
cmp r5, #0
beq cannot_run
ldr r0, =(FLAG_ALLOW_RUN)
ldr r3, =(0x0806E6D0+1) @ flag_check
bl call_via_r3
lsl r0, r0, #24
lsr r0, r0, #24
cmp r0, #0
beq cannot_run
ldr r2, =(0x02036E38) @ npc_states
ldrb r1, [r6, #5]
lsl r0, r1, #3
add r0, r0, r1
lsl r0, r0, #2
add r0, r0, r2
ldrb r0, [r0, #30]
ldr r3, =(0x080BD488+1) @ is_tile_to_run_on
bl call_via_r3
cmp r0, #0
bne cannot_run

can_run:
ldr r0, =(0x0805BA5A+1)
bx r0

i_forgot_what_this_label_is:
ldr r0, =(0x0805BA9E+1)
bx r0

cannot_run:
ldr r0, =(0x0805BA8C+1)
bx r0

.pool

get_gender_from_sprite:
lsl r0, r0, #24
lsr r0, r0, #24
cmp r0, #OW_MALE_DIVE
beq male
cmp r0, #OW_FEMALE_DIVE
beq female
cmp r0, #OW_FEMALE_FISH
bgt male
cmp r0, #OW_FEMALE_WALK
blt male

female:
mov r0, #1
b return_to_x5C838

male:
mov r0, #0

return_to_x5C838:
ldr r1, =(0x0805C838 + 1)
bx r1
.pool

check_for_events:
mov r0, #0x80
and r0, r1
cmp r0, #0
beq check_aftermove
bl consider_dive_emerging
cmp r0, #1
beq something_happened

check_aftermove:
ldrb r1, [r5]
mov r0, #0x40
and r0, r1
cmp r0, #0
beq check_move
ldr r0, =(0x0806CB38 + 1)
bx r0

something_happened:
ldr r0, =(0x0806CB6C + 1)
bx r0

check_move:
ldr r0, =(0x0806CB74 + 1)
bx r0
.pool

consider_dive_emerging:
push {lr}
@ REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(FLAG_ALLOW_DIVE)
ldr r1, =(0x0806E6D0 + 1) @ checkflag
bl call_via_r1
cmp r0, #0
beq no_emerging
@ REMOVE THE ABOVE 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(0x02036DFC) @ map_header
ldrb r0, [r0, #23] @ map_header->light_level
cmp r0, #5
bne no_emerging
bl get_block_secondary_role
cmp r0, #EMERGE_TILE_BYTE
bne no_emerging
ldr r0, =(0x081BE3D4) @ emerge_script
ldr r1, =(0x08069AE4 + 1) @ script_start
bl call_via_r1
mov r0, #1
b dive_return

no_emerging:
mov r0, #0

dive_return:
pop {r1}
bx r1
.pool

check_dive:
ldrb r1, [r5]
mov r0, #1
and r0, r1
cmp r0, #0
beq no_dive
bl consider_diving
cmp r0, #1
beq something_happened

no_dive:
ldrb r1, [r5]
mov r0, #4
and r0, r1
cmp r0, #0
beq something
ldr r2, =(0x0806CCD6 + 1)
bx r2

something:
ldr r0, =(0x0806CCFC + 1)
bx r0
.pool

consider_diving:
push {lr}
@ REMOVE THE FOLLOWING 5 LINES TO DISABLE BADGE CHECK
ldr r0, =(FLAG_ALLOW_DIVE)
ldr r1, =(0x0806E6D0 + 1) @ checkflag
bl call_via_r1
cmp r0, #0
beq cant_dive
@ REMOVE THE ABOVE 5 LINES TO DISABLE BADGE CHECK
bl get_block_secondary_role
cmp r0, #DIVE_TILE_BYTE
bne cant_dive
ldr r0, =(0x081BE38B) @ dive_script
ldr r1, =(0x08069AE4 + 1) @ script_start
bl call_via_r1
mov r0, #1
b dive_pop

cant_dive:
mov r0, #0

dive_pop:
pop {r1}
bx r1
.pool

get_block_secondary_role:
push {r4, lr}
sub sp, sp, #4
mov r4, sp
add r4, #2
mov r0, sp
mov r1, r4
ldr r3, =(0x0805C538 + 1) @ player_get_pos_to
bl call_via_r3
mov r0, sp
mov r1, #0
ldsh r0, [r0, r1]
mov r2, #0
ldsh r1, [r4, r2]
lsl r0, r0, #16
asr r0, r0, #16
lsl r1, r1, #16
asr r1, r1, #16
mov r2, #8
ldr r3, =(0x08058F48 + 1) @ cur_mapdata_block_get_field_at
bl call_via_r3
lsl r0, r0, #16
lsr r0, r0, #24
add sp, sp, #4
pop {r4}
pop {r1}
bx r1
.pool

player_behaviour_dive:
push {r4, lr}
ldr r0, =(0x02037078) @ walkrun_state
ldrb r0, [r0, #5] @ walkrun_state->npcid
lsl r4, r0, #3
add r4, r4, r0
lsl r4, r4, #2
ldr r0, =(0x02036E38) @ npc_states
add r4, r4, r0
mov r0, #6
ldr r3, =(0x0805C808 + 1) @ get_sprite_for_player
bl call_via_r3
add r1, r0, #0
lsl r1, r1, #24
lsr r1, r1, #24
add r0, r4, #0
ldr r3, =(0x081507BC + 1) @ npc_change_sprite_call
bl call_via_r3
ldrb r1, [r4, #24]
lsr r1, r1, #4
add r0, r4, #0
ldr r3, =(0x0805F218 + 1) @ npc_turn
bl call_via_r3
mov r0, #16
ldr r3, =(0x0805C970 + 1) @ change_sprite_bitfield
bl call_via_r3
ldrb r0, [r4, #4]
ldr r3, =(0x080DC6B0 + 1) @ bobbing
bl call_via_r3
strb r0,[r4, #26]
pop {r4}
pop {r0}
bx r0
.pool

change_sprite_to_diving:
push {lr}
mov r0, #4

set:
ldr r1, =(0x08150498 + 1) @ set_player_behaviour
bl call_via_r1
pop {r1}

call_via_r1:
bx r1

call_via_r3:
bx r3
.pool

.org 0xFFFFFF, 0xFF
.byte 0xFF


One more thing I noticed that's less about the changes made and more about how Firered handles the underwater weather in general. The fog appears as normal, but it's not until a menu/battle is entered then exited do bubbles appear. Is there any way to correct that as well so the underwater bubbles appear by default? Not as big a priority though, first I just want the female player sprite to not break.

Just tested on vanilla Firered as well. The results were the same, the female sprite becomes un-dived in both appearence and behavior.
Hacks I'm working on:
(Name in Progress) My main project, actively in development
Tales of Link GBA Remake: Secondary project, developing whenever I'm able.
3rd Gen Multiplayer Project: Research and development, really just experimenting for the moment
Pokemon Cursed/Creepy White: Group project, on hiatus for now with plans to return eventually.
Animal Crossing Wild World playing as an animal: experimental, messing with models and textures

Hacks I've worked on in the past:
Pokemon Ruby Destiny Broken Timeline (pre-reboot) - Assisted with maps
Pokemon HeartGold Prince Boo Edition - Experimental project with three small changes. Made at the request of YouTube LPer PrinceBoo21.

Recently came to realize I know significantly less than I thought I did. Basically, years of self-taught experience amounted to very little. After seeking tutorials and help, I've become more competent, but I have a long way to go. I look forward to learning more, in the meantime, I'll call myself a beginner, not a veteran.

Times I've been ninja'd: 18
Times I've ninja'd people: 3