Advertiser Content

Development ASM Resource Thread Page 60

Started by esperance September 19th, 2014 3:13 PM
  • 279066 views
  • 1488 replies
Male
Seen 1 Week Ago
Posted September 26th, 2019
38 posts
4.1 Years
No problem, glad to be of help!

Anyways, I've got my own idea. I don't know how much anyone cares to implement something like this, or if it's even possible. It's a pretty crazy thing to begin with. I'll still ask nonetheless.

Would it be possible to modify the GBA games to have two dedicated save files for two different people? The games already use all the space for a second save file to store a backup save. If possible, why not make a more practical use for it?

I know that this would cause problems with functions that don't require you to load up a save first, such as New Game, Options, Mystery Gift, GameCube to Game Boy Advance linking, migrating Pokémon to the Gen IV games, and save editing. My idea would be to make it so the most recently used save is the "active" save file. This way these functions interface with the active save, the Options menu reflects the settings of the active user, and New Game will save over the active save. Or, alternatively, change the New Game saving situation to be like the later games where you have to delete a save first. Then you can change the active save by loading up the "secondary" save file, which would now push the other save into secondary status.

I've always loved the idea of having multiple save files on one Pokémon cartridge. I know that it'll never be a feature in the official games, early on because of technical reasons (the first couple of generations couldn't handle it) and later on strictly for monetary reasons (buy more copies of the games!). But it'd still be a watershed moment in my eyes for it to become a reality.
yes richter, I agree with you and your idea as well. My daughter is always playing my savefiles, luckily for the switch has different profiles so she plays her own pokemon go pikachu file while she doesnt mess with mine. It's a great feature!

Sudonim

Doing things that are completely unnecessary since conception.

Male
Petalburg City
Seen August 14th, 2019
Posted July 28th, 2019
4 posts
125 Days
I'm going to go ahead and feel free to request something. So a while back i wanted to edit emerald to force only super effective moves to deal damage, and i figured the best way to do this was to edit the type chart. After doing that and playing the game, i quickly realized that editing the type chart also applies to status moves (e.g. Toxic, Growl, etc.) which is undesirable. I could have also edited the abilities for every Pokémon to have Wonder guard instead, but i feel like that's taking a lazy approach, and in that situation Slaking not having truant would make it even more over powered. So now that i have free time again i decided to come back to this project, and see if i can finally make this come to fruition. I would do this myself, but i don't understand ASM at all, and through my searching i haven't come up with any info about how i would even go about adding this rule in (I'm guessing it needs to be added to the damage calculation?).

TL;DR Wonder Guard at all times while keeping abilities and status moves in tact.
Feel free to correct my grammar and spelling.
Nice of the princess to invite us over for a picnic, eh Luigi?
I hope she made lots-a SPAGHETTI!
Seen 2 Weeks Ago
Posted September 14th, 2019
38 posts
13.4 Years
Can someone please help me with the Sitrus Berry Updates for Pokemon Emerald? I'm a bit new to ASM and not sure if I should run an overworld script with callasm command in game somewhere to change the effect the Sitrus Berry has or if I insert the pointer somewhere else in the Rom to get the desired effect out of the ASM in the First Post.

Diluting the process down to Hex and Free Space finding would be appreciated too!

Right now I've got an ASM folder with the thumb compiler. What all would I then need to copy/paste save and convert to HEX? With such a HEX code I'd insert it into freespace ending in 0 and then where do I go from here?
Seen 6 Days Ago
Posted August 27th, 2019
770 posts
12.7 Years
After spending way too much time tinkering with the build system and README, I can finally present:

Move Item [FR]

Black and White 2 introduced a feature where you can move items directly between two Pokémon in your party from within the party menu, rather than having to use the bag as middle man. This ports that feature to FR ROMs.

U.Flame

Humbled Beginner

Age 24
Male
Sapphire City
Seen 3 Days Ago
Posted 4 Weeks Ago
1,286 posts
11.5 Years
Having some issues with Spherical Ice's Dive ASM here in this thread: https://www.pokecommunity.com/showthread.php?t=257723

This is the ASM as I inserted it:
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


I had asked about this in Rom Hacking Help with no luck, since this is an ASM specific thread maybe this is a better place to ask. Basically, it functions but has problems with female players. Firstly, the Dive sprite uses the Dive overworld sprites but with the palette of the normal walking overworld sprites. It does this for both genders, but upon entering and exiting a menu or battle, the palette is corrected to the dive sprite palette. This in itself can be a non-issue if both sprites share palettes. For male players, this is the only issue.

The main problem is with female players upon entering a menu/battle, the dive sprite is reverted to the normal walking sprite. This includes behavior as well, no longer bobbing and is now able to run. There's an additional oddity if the dive and walk sprites are different sizes. The reverted sprite appears glitched, but upon another menu/battle, fully reverts to a normal looking walk state.

So what's causing female players to undo the dive state like that, and not males? One other thing I noticed is that the underwater fog still appears but the bubbles only appear after entering and exiting a menu. I tried implementing this in both my ongoing project and in vanilla Firered, no change in results. Then I checked diving in Pokemon Gaia, and found that the sprites function perfectly well for both genders, no palette issue, no reversion issue. But that the bubbles not appearing until after a menu thing is there. My main concern is just the female players breaking. The palette and bubbles issue isn't important, I can live with that, but I can't have players walking underwater.
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
Seen 1 Day Ago
Posted 4 Weeks Ago
3 posts
68 Days

Getting IVs and EVs



The routines are very similar so I ended up just combining the two routines into one. Basically given a slot number of a Pokemon in 0x8004, the routines will return the EVs or IVs, respectively, into the vars 0x8005-0x800A with 0x8003 as the IV/EV switch.


How to insert:

Compile and insert the following routine into free space:

Spoiler:

.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r5, lr}
	mov r4, #0x0
	
loop:
	cmp r4, #0x6
	bhi end
	ldr r0, =(0x20370C0) @var 0x8004 = slot number
	ldrh r0, [r0]
	mov r1, #0x64
	mul r1, r1, r0
	ldr r0, =(0x2024284)
	add r0, r0, r1
	ldr r3, =(0x20370BE)
	ldrh r3, [r3]
	cmp r3, #0x0
	beq EVs
	add r1, r1, #0x27 @IV
	b continue
	
EVs:
	add r1, r1, #0x1A
	
continue:
	ldr r2, =(0x803FBE8 +1)
	bl linker
	mov r1, r0
	@get var
	ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
	lsl r0, r4, #0x1
	add r2, r2, r0
	strh r1, [r2] @store IV in var
	add r4, r4, #0x1
	b loop

linker:
	bx r2
	
end:
	pop {r0-r5, pc}

.align 2



Usage:
setvar 0x8003 0x[anything except 0 = IV, 0 = EV]
setvar 0x8004 0x[slot number 0 to 5]
callasm 0x[this routine +1]

The variables will be:
0x8005: HP IV/EV
0x8006: Atk IV/EV
0x8007: Def IV/EV
0x8008: Spd IV/EV
0x8009: S.atk IV/EV
0x800A: S.def IV/EV
So for about the last 10 hours I've been trying to figure something out with this code.
It works completely fine, other than the fact that when I run it, it sets all 6 variables to the IV of the pokemon I specified in the scripts HP IV

Spoiler:

.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r5, lr} @loads registers r0-r5
	mov r4, #0x0 @copies 0(aka 0x0) to register r4
	
loop:
	cmp r4, #0x6 @finds the difference between the value in register r4 and the number 6(aka 0x6)
	bhi end @I believe this is roughly equivalent to if(r4==6) goto end
	ldr r0, =(0x20370C0) @var 0x8004 = slot number
	ldrh r0, [r0] @loads register r0 at the offset stored in r0 (set right before this to 0x20370C0) ONLY A HALFWORD IS LOADED
	mov r1, #0x64 @copies 100(aka 0x64) to register r1
	mul r1, r1, r0 @multiplies r0(the value at 0x20370C0/var 0x8004) by r1(100 aka 0x64) and stores the result in r1
	ldr r0, =(0x2024284) @loads register r0 at offset 0x2024284, upon inspection of this memory location, it is where the pokemon in your party are stored
	add r0, r0, r1 @adds the value in r1 to the offset r0 is loaded at, getting the party member location
	ldr r3, =(0x20370BE) @loads register r3 at 0x20370BE, the location of var 0x8003
	ldrh r3, [r3] @reads the halfword at 0x20370BE and writes it to r3, aka sets r3 equal to var 8003
	cmp r3, #0x0 @checks if r3(at this point effectively var 0x8003) is 0
	beq EVs @goes to evs if var 0x8003 is 0
	add r1, r1, #0x27 @IV r1 at this point is equal to the offset at whatever pokemon party number you want, adding 0x27 sets the offset to the ivs section of the pokemon's data
	b continue @goes to continue
	
EVs:
	add r1, r1, #0x1A
	
continue:
	ldr r2, =(0x803FBE8 +1) @I think this sets register r2 equal to the offset 0x803FBE9
	bl linker @branches to linker and stores the current offset in the link register(r14)
	mov r1, r0 @copies r0 to r1
	@get var
	ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
	lsl r0, r4, #0x1 @I think shifts r0 to the left(subtracts 1 from r0)
	add r2, r2, r0
	strh r1, [r2] @store IV in var
	add r4, r4, #0x1 @adds 1 to the value of r4, allowing the assembly to terminate once it runs 6 times
	b loop @goes to loop

linker:
	bx r2 @branches to the offset stored in r2
	
end:
	pop {r0-r5, pc}

.align 2


I've taken the code and put in comments on each line summarizing what I understand each line to do. Am I mistaken? Am I completely wrong?

Spoiler:

//---------------
#org 0x2514D0
lock
faceplayer
msgbox 0x82515D0 MSG_YESNO //"Would you like to know the\npotent..."
compare LASTRESULT 0x0
if 0x1 goto 0x8251570
setvar 0x8003 0x1
setvar 0x8004 0x0
callasm 0x8251C51
buffernumber 0x0 0x8005
buffernumber 0x1 0x8006
msgbox 0x8251610 MSG_NORMAL //"HP: [buffer1] IVs\nAttack: [buffer..."
buffernumber 0x0 0x8007
buffernumber 0x1 0x8008
msgbox 0x8251630 MSG_NORMAL //"Defence: [buffer1] IVs\nSpeed: [bu..."
buffernumber 0x0 0x8009
buffernumber 0x1 0x800A
msgbox 0x8251650 MSG_NORMAL //"Special Attack: [buffer1] IVs\nSpe..."
end

//---------------
#org 0x251570

//---------
// Strings
//---------
#org 0x2515D0
= Would you like to know the\npotential of your Pokémon?

#org 0x251610
= HP: [buffer1] IVs\nAttack: [buffer2] IVs 

#org 0x251630
= Defence: [buffer1] IVs\nSpeed: [buffer2] IVs

#org 0x251650
= Special Attack: [buffer1] IVs\nSpecial Defence: [buffer2] IVs.


with the compiled thing ending up as

0x08251C50        3F B5 00 24 05 2C 17 D8 0C 48 00 88 64 21 41 43
0x08251C60        0B 48 40 18 0B 4B 1B 88 00 2B 01 D0 27 31 00 E0
0x08251C70        1A 31 09 4A 00 F0 07 F8 01 1C 08 4A 60 00 12 18
0x08251C80        11 80 01 34 E6 E7 10 47 3F BD C0 46 C0 70 03 02 
0x08251C90        86 42 02 02 BE 70 03 02 E9 FB 03 08 C4 70 03 02
Everything I have there follows the implementation instructions to a T, yet the memory still shows

0x020370BD        00 01 00 00 00 19 00 19 00 19 00 19 00 19 00 19
0x020370CD        00 19 00 01 00 02 00 04 00 00 00 00 00 FF 00 01
and just to make sure it wasn't a statistical fluke, I ran the same script with 5 or so more randomly encountered pokemon and ran them through an IV calculator. Each time, the HP IV shown by the ASM was correct, but then copied it to every other variable set in the script.
Seen 1 Day Ago
Posted 4 Weeks Ago
3 posts
68 Days

Getting IVs and EVs



The routines are very similar so I ended up just combining the two routines into one. Basically given a slot number of a Pokemon in 0x8004, the routines will return the EVs or IVs, respectively, into the vars 0x8005-0x800A with 0x8003 as the IV/EV switch.


How to insert:

Compile and insert the following routine into free space:

Spoiler:

.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r5, lr}
	mov r4, #0x0
	
loop:
	cmp r4, #0x6
	bhi end
	ldr r0, =(0x20370C0) @var 0x8004 = slot number
	ldrh r0, [r0]
	mov r1, #0x64
	mul r1, r1, r0
	ldr r0, =(0x2024284)
	add r0, r0, r1
	ldr r3, =(0x20370BE)
	ldrh r3, [r3]
	cmp r3, #0x0
	beq EVs
	add r1, r1, #0x27 @IV
	b continue
	
EVs:
	add r1, r1, #0x1A
	
continue:
	ldr r2, =(0x803FBE8 +1)
	bl linker
	mov r1, r0
	@get var
	ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
	lsl r0, r4, #0x1
	add r2, r2, r0
	strh r1, [r2] @store IV in var
	add r4, r4, #0x1
	b loop

linker:
	bx r2
	
end:
	pop {r0-r5, pc}

.align 2



Usage:
setvar 0x8003 0x[anything except 0 = IV, 0 = EV]
setvar 0x8004 0x[slot number 0 to 5]
callasm 0x[this routine +1]

The variables will be:
0x8005: HP IV/EV
0x8006: Atk IV/EV
0x8007: Def IV/EV
0x8008: Spd IV/EV
0x8009: S.atk IV/EV
0x800A: S.def IV/EV
So for about the last 10 hours I've been trying to figure something out with this code.
It works completely fine, other than the fact that when I run it, it sets all 6 variables to the IV of the pokemon I specified in the scripts HP IV

Spoiler:

.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r5, lr} @loads registers r0-r5
	mov r4, #0x0 @copies 0(aka 0x0) to register r4
	
loop:
	cmp r4, #0x6 @finds the difference between the value in register r4 and the number 6(aka 0x6)
	bhi end @I believe this is roughly equivalent to if(r4==6) goto end
	ldr r0, =(0x20370C0) @var 0x8004 = slot number
	ldrh r0, [r0] @loads register r0 at the offset stored in r0 (set right before this to 0x20370C0) ONLY A HALFWORD IS LOADED
	mov r1, #0x64 @copies 100(aka 0x64) to register r1
	mul r1, r1, r0 @multiplies r0(the value at 0x20370C0/var 0x8004) by r1(100 aka 0x64) and stores the result in r1
	ldr r0, =(0x2024284) @loads register r0 at offset 0x2024284, upon inspection of this memory location, it is where the pokemon in your party are stored
	add r0, r0, r1 @adds the value in r1 to the offset r0 is loaded at, getting the party member location
	ldr r3, =(0x20370BE) @loads register r3 at 0x20370BE, the location of var 0x8003
	ldrh r3, [r3] @reads the halfword at 0x20370BE and writes it to r3, aka sets r3 equal to var 8003
	cmp r3, #0x0 @checks if r3(at this point effectively var 0x8003) is 0
	beq EVs @goes to evs if var 0x8003 is 0
	add r1, r1, #0x27 @IV r1 at this point is equal to the offset at whatever pokemon party number you want, adding 0x27 sets the offset to the ivs section of the pokemon's data
	b continue @goes to continue
	
EVs:
	add r1, r1, #0x1A
	
continue:
	ldr r2, =(0x803FBE8 +1) @I think this sets register r2 equal to the offset 0x803FBE9
	bl linker @branches to linker and stores the current offset in the link register(r14)
	mov r1, r0 @copies r0 to r1
	@get var
	ldr r2, =(0x20370C2) @using vars 0x8005-0x800A
	lsl r0, r4, #0x1 @I think shifts r0 to the left(subtracts 1 from r0)
	add r2, r2, r0
	strh r1, [r2] @store IV in var
	add r4, r4, #0x1 @adds 1 to the value of r4, allowing the assembly to terminate once it runs 6 times
	b loop @goes to loop

linker:
	bx r2 @branches to the offset stored in r2
	
end:
	pop {r0-r5, pc}

.align 2


with the compiled thing ending up as

0x08251C50        3F B5 00 24 05 2C 17 D8 0C 48 00 88 64 21 41 43
0x08251C60        0B 48 40 18 0B 4B 1B 88 00 2B 01 D0 27 31 00 E0
0x08251C70        1A 31 09 4A 00 F0 07 F8 01 1C 08 4A 60 00 12 18
0x08251C80        11 80 01 34 E6 E7 10 47 3F BD C0 46 C0 70 03 02 
0x08251C90        86 42 02 02 BE 70 03 02 E9 FB 03 08 C4 70 03 02
I've taken the code and put in comments on each line summarizing what I understand each line to do. Am I mistaken? Am I completely wrong?

Spoiler:

//---------------
#org 0x2514D0
lock
faceplayer
msgbox 0x82515D0 MSG_YESNO //"Would you like to know the\npotent..."
compare LASTRESULT 0x0
if 0x1 goto 0x8251570
setvar 0x8003 0x1
setvar 0x8004 0x0
callasm 0x8251C51
buffernumber 0x0 0x8005
buffernumber 0x1 0x8006
msgbox 0x8251610 MSG_NORMAL //"HP: [buffer1] IVs\nAttack: [buffer..."
buffernumber 0x0 0x8007
buffernumber 0x1 0x8008
msgbox 0x8251630 MSG_NORMAL //"Defence: [buffer1] IVs\nSpeed: [bu..."
buffernumber 0x0 0x8009
buffernumber 0x1 0x800A
msgbox 0x8251650 MSG_NORMAL //"Special Attack: [buffer1] IVs\nSpe..."
end

//---------------
#org 0x251570

//---------
// Strings
//---------
#org 0x2515D0
= Would you like to know the\npotential of your Pokémon?

#org 0x251610
= HP: [buffer1] IVs\nAttack: [buffer2] IVs 

#org 0x251630
= Defence: [buffer1] IVs\nSpeed: [buffer2] IVs

#org 0x251650
= Special Attack: [buffer1] IVs\nSpecial Defence: [buffer2] IVs.


Everything I have there follows the implementation instructions to a T, yet the memory still shows

0x020370BD        00 01 00 00 00 19 00 19 00 19 00 19 00 19 00 19
0x020370CD        00 19 00 01 00 02 00 04 00 00 00 00 00 FF 00 01
and just to make sure it wasn't a statistical fluke, I ran the same script with 5 or so more randomly encountered pokemon and ran them through an IV calculator. Each time, the HP IV shown by the ASM was correct, but then copied it to every other variable set in the script.

FBI

Free supporter

Male
Unknown Island
Seen 1 Hour Ago
Posted 4 Weeks Ago
1,906 posts
6.8 Years
Hi, first of all I'd like to apologize for the mistake. I haven't tested that code, and it's in assembly so a semantic error here and there tend to be around for some of them. A quick skim through it, it does seem like there is a minor error.

add r1, r1, #0x27 @IV
This line of code I assume gets the HP IV, however, it will always be 0x27, and therefore not get any subsequent IVs.
That line should be replaced by:
add r1, r4, #0x27
If the assembler says the above line is invalid, try:
add r1, r1, r4
add r1, r1, #0x27
Hopefully that does the trick.
...
Seen 1 Day Ago
Posted 4 Weeks Ago
3 posts
68 Days
Hi, first of all I'd like to apologize for the mistake. I haven't tested that code, and it's in assembly so a semantic error here and there tend to be around for some of them. A quick skim through it, it does seem like there is a minor error.

add r1, r1, #0x27 @IV
This line of code I assume gets the HP IV, however, it will always be 0x27, and therefore not get any subsequent IVs.
That line should be replaced by:

add r1, r4, #0x27
If the assembler says the above line is invalid, try:

add r1, r1, r4
add r1, r1, #0x27
Hopefully that does the trick.
Hey FBI, thanks for the reply, and I'm happy to say that
add r1, r1, r4
add r1, r1, #0x27
did the trick perfectly! It seems to be displaying the correct IVs for each stat now and isn't causing any issues. Again, thank you so much for the help.
Male
Seen 10 Hours Ago
Posted 4 Days Ago
129 posts
3.7 Years
[FR] Map Music Loader

This small hack loads map music by a variable rather than the map header (if the variable is set to a non-zero value). just set MUSIC_VAR to some variable value and compile, insert into free space, and overwrite the corresponding bytes at 0x55D70 (found at top of routine).

In a script, set the variable to a specific song ID, and the game will play that song ID after trainerbattles and warps (perhaps others that I have not thought of or tested).

Spoiler:
.text
.align 2
.thumb
.thumb_func
.global LoadMapMusic
/*
load song regardless of map default

hook at 55D70 via r0
	aka 00 48 00 47 xx+1 xx xx 08
*/

.equ MUSIC_VAR, 0x4XXX	@some free variable in save block

Main:
	push {r1-r3}
	ldr r0, .var
	bl GetVarVal
	pop {r1-r3}
	cmp r0, #0x0
	beq LoadFromMapHeader
	pop {pc}
	
LoadFromMapHeader:
	ldrb r0, [r1]
	ldr r2, =(0x08055D78 +1)
	bx r2
	
GetVarVal:
	ldr r2, =(0x0806e568 +1)
	bx r2
	
.align 2
.var: .word MUSIC_VAR


Enjoy!
Seen 2 Days Ago
Posted 2 Days Ago
6 posts
10 Days
I combined this into 1 routine and cut the total size down a lot. All credit to DizzyEgg of course, this is nothing compared to creating the mod in the first place.

.text
.thumb
.thumb_func
.align 2

@ 0x1C379E: 02 30 00 4A 10 47 XX+1 XX XX 08
@ 0x1C3864: 00 4A 10 47 XX+1 XX XX 08

main:
	@ at this point... r0 contains our return address (- 8). Convenient!
	push {r5-r7}
	
	@ save return address for later.
	mov r6, r0
	add r6, #0x8
	
	@ to determine what function we were called from:
	@ if it was right stats, r9 is 0. if it was left stats, r9 has something in it.
	mov r7, r9 @ can't really use hi registers in thumb, mov it down.
	@ so, to check the function type: cmp r7, #0. eq means right stats.
	
	sub sp, sp, #0x20
	ldr r0, [r4] @pokemon summary pointer. we're free to use r4 after this.
	add r0, #0xA3 @poke nature
	ldrb r1, [r0]
	ldr r0, nature_stat_table
	
	mov r2, #5
	mul r2, r1
	
	mov r1, sp
	mov r5, #0
	
	add r2, r2, r0 @r2 contains nature info
	cmp r7, #0
	beq right_stats_begin


@@ LEFT STAT COLORING BEGIN @@@

left_stats_begin:
	ldr r3, left_stats_string

handle_hp:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #6
	bne handle_hp
	add r3, #6
	add r1, #6
	mov r5, #0

handle_atk:
	ldrb r0, [r2]
	cmp r0, #1
	beq red_font_atk
	cmp r0, #0xFF
	bne copy_atk
	bl blue_font
	b copy_atk

red_font_atk:
	bl red_font

copy_atk:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #3
	bne copy_atk
	add r3, #3
	add r1, #3
	mov r5, #0

handle_def:
	add r2, #1
	ldrb r0, [r2]
	cmp r0, #1
	beq red_font_def
	cmp r0, #0xFF
	beq blue_font_def
	bl default_font
	b copy_def

red_font_def:
	bl red_font
	b copy_def

blue_font_def:
	bl blue_font

copy_def:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #3
	bne copy_def
	b return

@@@ LEFT STAT COLORING END @@


@@@ RIGHT STAT COLORING BEGIN @@@

right_stats_begin:
	add r2, #3 @r2 contains beg of spatk stat
	ldr r3, right_stats_string

handle_spatk:
	ldrb r0, [r2]
	cmp r0, #1
	beq red_font_spatk
	cmp r0, #0xFF
	bne copy_spatk
	bl blue_font
	b copy_spatk

red_font_spatk:
	bl red_font

copy_spatk:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #3
	bne copy_spatk
	add r3, #3
	add r1, #3
	mov r5, #0

handle_spdef:
	add r2, #1
	ldrb r0, [r2]
	cmp r0, #1
	beq red_font_spdef
	cmp r0, #0xFF
	beq blue_font_spdef
	bl default_font
	b copy_spdef

red_font_spdef:
	bl red_font
	b copy_spdef

blue_font_spdef:
	bl blue_font

copy_spdef:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #3
	bne copy_spdef
	add r3, #3
	add r1, #3
	mov r5, #0

handle_spd:
	sub r2, #2
	ldrb r0, [r2]
	cmp r0, #1
	beq red_font_spd
	cmp r0, #0xFF
	beq blue_font_spd
	bl default_font
	b copy_spd

red_font_spd:
	bl red_font
	b copy_spd

blue_font_spd:
	bl blue_font

copy_spd:
	ldrb r0, [r3, r5]
	strb r0, [r1, r5]
	add r5, #1
	cmp r5, #3
	bne copy_spd
	b return

@@@ RIGHT STAT COLORING END @@@


@@@ FONT FUNCTIONS BEGIN @@@

blue_font: @FC 01 07
	mov r4, #7 @color of the lowered stat
	b font_common

red_font: @FC 01 05
	mov r4, #5 @color of the raised stat
	b font_common

default_font: @FC 01 01
	mov r4, #1 @color of the regular stats
	@ just fall through to font_common (no need to branch)

font_common:
	mov r0, #0xFC
	strb r0, [r1]
	add r1, #1
	mov r0, #1
	strb r0, [r1]
	add r1, #1
	strb r4, [r1]
	add r1, #1
	bx lr

@@@ FONT FUNCTIONS END @@@


return:
	ldr r0, displayed_string
	mov r1, sp
	ldr r2, special_f7_string_fct
	bl x_r2
	cmp r7, #0
	beq skip_mov_r0_r9
	mov r0, r9
skip_mov_r0_r9:
	add sp, sp, #0x20
	mov r2, r6
	pop {r5-r7}
x_r2:
	bx r2


.align 2
nature_stat_table: .word 0x0831E818
left_stats_string: .word 0x0861CE82
right_stats_string: .word 0x0861CE8E
displayed_string: .word 0x02021FC4
special_f7_string_fct: .word 0x081AFC29
This routine highlights the numeric values of the increasing/decreasing stats, but I would like to see the stat labels (ex. ATTACK, DEFENSE etc.) being highlighted instead. How can I tackle this?
Advertiser Content