The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > Fan Games > Binary ROM Hacking > Binary Hack Research & Development
Reload this Page Code ASM Resource Thread

Notices
For all updates, view the main page.

Binary Hack Research & Development Got a well-founded knack with your binary Pokémon hacks? Love reverse-engineering them? For the traditional Pokémon ROM hacker, this is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!

Ad Content
Reply
 
Thread Tools
  #1476   Link to this post, but load the entire thread.  
Old October 26th, 2019 (4:52 PM). Edited October 26th, 2019 by Flarbley.
Flarbley Flarbley is offline
 
Join Date: Oct 2019
Posts: 3
I'm having a problem with shiny odds, compiled all three parts but when I clear the textbox after receiving my starter the game resets, any idea what I did wrong?
Reply With Quote
  #1477   Link to this post, but load the entire thread.  
Old October 28th, 2019 (11:20 AM). Edited November 4th, 2019 by ghoulslash.
ghoulslash's Avatar
ghoulslash ghoulslash is offline
 
Join Date: Mar 2016
Gender: Male
Posts: 238
[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:
Code:
.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!
__________________

Pokeemerald Works
Reply With Quote
  #1478   Link to this post, but load the entire thread.  
Old December 7th, 2019 (4:54 AM).
Tacobell24's Avatar
Tacobell24 Tacobell24 is offline
 
Join Date: Nov 2018
Posts: 232
Quote:
Originally Posted by DarkPsychic View Post
Pokemon LoathingFriendship Evolution:
Code:
.text
.align 2
.thumb
.thumb_func
.global loathFriendship

main:
push {r0-r7}
add r0, r6, r7
lsl r0, r0, #0x3
add r0, r2, r0
add r3, r0, r3
ldrb r2, [r3, #0x2]
mov r0, r8
bl decrypt
mov r11, r0
pop {r0-r7}
mov r1, r11
cmp r1, #0x10
blo max_lowhappy
b exit

max_lowhappy:
mov r10, r3
pop {r0-r7}
mov r1, r10
ldr r0, evolution_loc
bx r0

exit:
pop {r0-r7}
ldr r0, no_evo
bx r0

decrypt: 
push {r0-r7}
mov r1, #0x20
ldr r2, decryptpoke
bx r2

.align 2
no_evo: .word 0x08043111
evolution_loc: .word 0x0804310D
decryptpoke: .word 0x0803FBE9
The Pokemons happiness must be between 0-10 to trigger the evolution.
To insert follow instructions in this thread.

I hope some find this useful.
I thought about trade evolution basically being just this.
A Pokemon so depressed it evolves...
It took me 50+ pages to find this. But thanks brotato. This is exactly what I need 👍
Reply With Quote
  #1479   Link to this post, but load the entire thread.  
Old December 17th, 2019 (12:49 PM). Edited September 18th, 2020 by BluRose.
BluRose BluRose is offline
blu rass
 
Join Date: Apr 2014
Location: michigan tech
Age: 22
Gender: Male
Nature: Timid
Posts: 812
headbutt trees (fire red)

so basically i was talking with petuh 2 days ago about how rusty i probably am at strict assembly

so here i am! i made a thing

Spoiler:
Code:
@ the whole headbutt tree system
@ it implements jpan's behavior byte hack as well as the headbutt system in the space that the old routine took up.  when he said it was overly inefficient, he meant it!
@ compile this and then go to the offset 0x806D1F0 in the resulting .bin output.  copy everything there until the next block of zeros.  paste it to offset 0x6D1F0 in your rom.
@ there are various parameters you can play around with.  most of these are primarily the tables halfway through this.
@ i tried to comment it throughout!

@ now, in amap, there's the one field that is primarily used in wild encounter spots.  it's 2 when wild grass and 4 when surfing on water encounters.
@ because we won't be walking on the headbutt tree, we can use this field to our advantage.
@ cur_mapdata_block_get_field_at(s16 x, s16 y, u8 field) references a bunch of other routines, but eventually, it boils down to a bunch of preset fields or'd with the header info.
@ the first is 0x1FF, or the 9 least significant bits.  this is the behavior byte itself.
@ the second is 0x3E00, or the next 5 bits in terms of significance.  this allows for 2^5 (32) bits for use for our table.
@ note that the entry entered in this table should be multiplied by 2 because of the way that amap (incorrectly) displays the data.  this allows the code below to reference it properly.
@ screens are given in the post.

.text
.align 2
.thumb
.thumb_func

.org 0x08044EC8

@ returns r0 = pseudorandom number
random: 
	.hword 0x4A04

.org 0x08058F48

@ returns r0 = (metatile behavior long or blockinfo_bit_masks[field]) >> blockinfo_bit_right_shift_num[field]
cur_mapdata_block_get_field_at: @ (s16 x, s16 y, u8 field)
	push {r4, lr}

.org 0x0806CE38

@ writes the next pos and height to the pointer given in r0
player_get_next_pos_and_height: @ (*[s16 x, s16 y, u8 height])
	push {r4, r5, lr}

.org 0x0806D1F0 

@ this assembly routine is a modded version of jpan's behavior byte hack that decreases space required for the table while slightly increasing what's needed for the code
onpress_a_get_script_tile:
	lsl r1, r1, #0x18
	lsr r0, r1, #0x18
	cmp r0, #0x80
	blt _not_governed @ we don't care about entries less than h80
	sub r0, r0, #0x80
	lsl r0, r0, #0x2
	ldr r1, behavior_table_ref @ load the table pointer here
	add r0, r0, r1
	ldr r0, [r0] @ load the script pointer here
	b _return_loc
_not_governed:
	mov r0, #0
_return_loc:
	mov pc, lr

.align 2

behavior_table_ref:
	.word behavior_table

behavior_table: @ for the playerfacing behaviors
	.word 0
	.word 0x081A7606 @ bookshelf
	.word 0x081A760F @ market shelf
	.word 0x081A6955 @ pc
	.word 0
	.word 0x081A6C32 @ town map
	.word 0x081A764E @ tv
	.word 0x081A76E7 @ pokemon center
	.word 0x081A76DE @ pokemon mart
	.word 0x081A7657 @ cabinet
	.word 0x081A7660 @ cooking smells great!
	.word 0x081A7669 @ dresser
	.word 0x081A7672 @ snacks
	.word 0x081BBFD8 @ wireless
	.word 0x081BB8A7 @ not available
	.word 0x081A7702 @ questionnaire
	@ 0x90
	.word 0x081A7618 @ fridge
	.word 0x081A76F0 @ indigo plateau
	.word 0x081A76F9 @ indigo plateau 2
	.word 0x081A763C @ blueprint
	.word 0x081A767B @ pokemon pics
	.word 0x081A7684 @ complex machine.  better not touch it!
	.word 0x081A768D @ telephone
	.word 0x081A762A @ complex numbers
	.word 0x081A7696 @ ads
	.word 0x081A769F @ tasty food
	.word 0x081A76A8 @ trash can
	.word 0x081A76B1 @ cup
	.word 0
	.word 0
	.word 0x081A76CC @ lights
	.word 0x081A76D5 @ tools
	@ 0xA0
	.word 0x081A7633 @ random machine
	.word 0x081A7621 @ consoles
	.word 0x081A7645 @ robbery
	.word 0x081C549C @ timer
@ now, i personally added headbutt_script here, but it can go in any one of the zeros above.  just make sure that you note the entry correctly!
	.word headbutt_script @ headbutt tree behavior byte (0xA4)

.equ table_amount, 3
.equ terminate, 0xFE @ only rule here is that it isn't a pokemon you want to appear in a tree.  if you wanted to use pokemon index 254, go for it i guess, but change this
.equ var_begin, 0x020270B8

headbutt_tree:
	push {r4-r6, lr}
	ldr r0, var_8000 @ position_ptr	
@ the below branch will store the position in front of the player's x in var_8000, y in var_8001, and the height in the most significant byte of var_8002
@ this is because it writes to the pointer in r0
	bl player_get_next_pos_and_height
	ldr r4, var_8000
	ldrh r0, [r4] @ x
	ldrh r1, [r4, #2] @ y
	mov r2, #1 @ field id
@ the field entry 1 is 5 bits of the second behavior byte thing in advancemap.  this means we can have up to 32 headbutt tables denoted by even numbers from 0-64 in amap.
@ this is explained further above
	bl cur_mapdata_block_get_field_at
	lsl r0, r0, #0x18
	lsr r4, r0, #0x18 @ r4 = table number
@ part below catches invalid tables and prevents them from working
	cmp r4, #table_amount
	bge _nothingfell
	ldr r0, tableoftables_ref
	lsl r1, r4, #2 @ r1 = table number * 4
	ldr r4, [r0, r1] @ r4 = table pointer to the relevant one
@ below, generate a random number less than 100 to emulate chance
	bl random @ r0 = random()
	mov r1, #100
	bl __umodsi3 @ r0 = r0 % 100
	mov r5, #0 @ set up the loop counter
	ldr r6, terminate_byte
	
@ at this point, r0 = random() % 100, r4 = table pointer, r5 = loop counter, r6 = terminator
_loop:
	mov r1, #7 @ 7 being the size of each entry
	mul r1, r5, r1
	add r3, r4, r1 @ store the current entry's pointer in r3
	ldrh r2, [r3] @ seems to be very finicky at times, loading random values from the surroundings?
	lsl r2, r2, #0x10
	lsr r2, r2, #0x10
	cmp r2, r6
	beq _nothingfell
	ldrb r2, [r3, #6] @ load the chance of this entry into r2
	cmp r0, r2
	ble _somethingfell
	add r5, r5, #1 @ increment the loop counter
	b _loop

_somethingfell:
	mov r4, r3
@ at this point, r4 is the table entry we care about.  don't touch it
	bl random @ generate a new random number
	@ r0 = random()
	ldrb r2, [r4, #2] @ load the lower level
	ldrb r1, [r4, #3] @ load the higher level
	sub r1, r1, r2 @ subtract the lower level from the higher level, store it as the parameter for modulo
	bl __umodsi3
	@ r0 = random() % (highlevel - lowlevel)
	ldrb r2, [r4, #2] @ load the lower level again bc umodsi ****in w the value
	add r1, r0, r2 @ level parameter
	ldrh r0, [r4] @ species parameter
	ldrh r2, [r4, #4] @ item parameter
	bl create_scripted_mon
	ldr r0, var_8000
	mov r1, #0
	strh r1, [r0, #0x18] @ store 0 into var_800D
	b _end

_nothingfell:
	ldr r0, var_8000
	mov r1, #0xFF
	strh r1, [r0, #0x18] @ store 0xFF into var_800D
	
_end:
	pop {r4-r6}
	pop {r1} @ this is the return method used by many of the script stuff so
	bx r1

.align 2

@ used to store the position struct
var_8000:
	.word (var_begin + (0x8000 * 2))
	
terminate_byte:
	.word terminate

tableoftables_ref:
	.word tableoftables

@ note that, in order to expand the tables, you need to add another entry here for each of the tables.
tableoftables:
	.word lowencounter
	.word medencounter
	.word highencounter

@ bunch of defines to make the below better readable
.equ caterpie, 10
.equ metapod, 11
.equ butterfree, 12
.equ weedle, 13
.equ kakuna, 14
.equ beedrill, 15
.equ exeggcute, 102
.equ exeggutor, 103
.equ tangela, 114
.equ pinsir, 127
.equ snorlax, 143
.equ pineco, 204
.equ heracross, 214

@ a sample item
.equ brightpowder, 179

@.org 0x08XXXXXX @ optional repoint of the tables below in case you want a higher amount of pokemon.

@ here's the table format:
@ [2 bytes - species] [1 byte - lower level] [1 byte - higher level] [2 bytes] - item it can hold] [1 byte - chance it will appear]
@ the chance byte at the very end is subtracted from the previous entry in the tables in order to get that specific entry's chance of showing up.
@ sample entries are below:

lowencounter:
	.hword weedle		@ species
	.byte 5				@ lower level
	.byte 7 			@ higher level
	.hword brightpowder @ item
	.byte 20			@ chance
	
	.hword kakuna 		@ species
	.byte 12 			@ lower level
	.byte 15 			@ higher level
	.hword 0 			@ no item
	.byte 40			@ chance:  40 - 20 (weedle's entry above) = 20
	
	.hword beedrill 
	.byte 60 
	.byte 70 
	.hword brightpowder 
	.byte 100			@ chance:  100 - 40 (kakuna's entry above) = 60
	
	.hword terminate

@ this table represents an instance where we don't have to get a pokemon 100% of the time.  the code handles it!
medencounter:
	.hword caterpie 
	.byte 5 
	.byte 7 
	.hword brightpowder 
	.byte 35
	
	.hword metapod 
	.byte 12 
	.byte 15 
	.hword 0 
	.byte 45
	
	.hword butterfree 
	.byte 60 
	.byte 70 
	.hword brightpowder 
	.byte 50
	
	.hword terminate
	@ 50% of the time, a pokemon won't fall.

highencounter:
	.hword exeggcute 
	.byte 10 
	.byte 12 
	.hword 0 
	.byte 40
	
	.hword tangela 
	.byte 20 
	.byte 25 
	.hword 0 
	.byte 60

	.hword heracross
	.byte 17
	.byte 22
	.hword brightpowder
	.byte 90
	
	.hword snorlax 
	.byte 50 
	.byte 60 
	.hword brightpowder 
	.byte 100
	
	.hword terminate

@ optional insert of the script.  there's still about hB0 bytes left over after the script is inserted, allowing for about 19 EXTRA mon entries (on top of the 10 there already)
@ repoint if so desired.  the assembly will take care of it!
@.org 0x08XXXXXX 

.equ headbutt, 0x1D
.equ lastresult, 0x800D

headbutt_script: @ this is included here for the dynamic compiling so that you don't have to care.  feel free to edit it though
	.byte 0x6A 
	
	.byte 0x7C 
	.hword headbutt
	
	.byte 0x21 
	.hword lastresult
	.hword 0x06 
	
	.byte 0x06 
	.byte 0x01
	.word no_headbutt_in_party

	.byte 0x9D 
	.byte 0x00 
	.hword lastresult
	
	.byte 0x7F 
	.byte 0x00 
	.hword lastresult
	
	.byte 0x82 
	.byte 0x01 
	.hword headbutt
	
	.byte 0x0F 
	.byte 0x00 
	.word text_headbutt_in_party
	.byte 0x09 
	.byte 0x05 

	.byte 0x21 
	.hword lastresult
	.hword 0x00

	.byte 0x06 
	.byte 0x01 
	.word said_no

	.byte 0x0F 
	.byte 0x00 
	.word text_poke_used_atk
	.byte 0x09 
	.byte 0x04 

	.byte 0x68 

	.byte 0x9C 
	.hword 0x2

	.byte 0x27 

@ the callasm is here
	.byte 0x23 
	.word headbutt_tree + 1

@ this comparison here prevents the dowildbattle from happening if lastresult is 0xFF (the chance was higher than the highest chance defined in the table)
@ lastresult's modification is in the assembly above
	.byte 0x21 
	.hword lastresult
	.hword 0xFF 
	
	.byte 0x06 
	.byte 0x01 
	.word tree_was_undisturbed

	.byte 0x0F 
	.byte 0x00 
	.word text_exclamation
	.byte 0x09 
	.byte 0x06

	.byte 0xB7 

	.byte 0x6C 

	.byte 0x02 

	.byte 0xFF 

no_headbutt_in_party:
	.byte 0x0F 
	.byte 0x00 
	.word text_cant_headbutt
	.byte 0x09 
	.byte 0x06 
	
	.byte 0x6C 
	
	.byte 0x02 
	
	.byte 0xFF 
	
said_no: @ closes the textbox
	.byte 0x68 

	.byte 0x6C 

	.byte 0x02 

	.byte 0xFF 

tree_was_undisturbed:
	.byte 0x0F 
	.byte 0x00 
	.word text_tree_undisturbed
	.byte 0x09 
	.byte 0x06 
	
	.byte 0x6C 
	
	.byte 0x02 
	
	.byte 0xFF 
	
text_headbutt_in_party: @ This tree can be headbutted! Would you like to use headbutt?
	.byte 0xCE 
	.byte 0xDC 
	.byte 0xDD 
	.byte 0xE7 
	.byte 0x00 
	.byte 0xE8 
	.byte 0xE6 
	.byte 0xD9 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xD7 
	.byte 0xD5 
	.byte 0xE2 
	.byte 0x00 
	.byte 0xD6 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xDC 
	.byte 0xD9 
	.byte 0xD5 
	.byte 0xD8 
	.byte 0xD6 
	.byte 0xE9 
	.byte 0xE8 
	.byte 0xE8 
	.byte 0xD9 
	.byte 0xD8 
	.byte 0xAB 
	.byte 0xFE 
	.byte 0xD1 
	.byte 0xE3 
	.byte 0xE9 
	.byte 0xE0 
	.byte 0xD8 
	.byte 0x00 
	.byte 0xED 
	.byte 0xE3 
	.byte 0xE9 
	.byte 0x00 
	.byte 0xE0 
	.byte 0xDD 
	.byte 0xDF 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xE8 
	.byte 0xE3 
	.byte 0x00 
	.byte 0xE9 
	.byte 0xE7 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xC2 
	.byte 0xD9 
	.byte 0xD5 
	.byte 0xD8 
	.byte 0xD6 
	.byte 0xE9 
	.byte 0xE8 
	.byte 0xE8 
	.byte 0xAC 
	.byte 0xFF 
	.byte 0x00 
	.byte 0xFF 
	
text_poke_used_atk: @ [string1] used [string2]!
	.byte 0xFD 
	.byte 0x02 
	.byte 0x00 
	.byte 0xE9 
	.byte 0xE7 
	.byte 0xD9 
	.byte 0xD8 
	.byte 0x00 
	.byte 0xFD 
	.byte 0x03 
	.byte 0xAB 
	.byte 0xFF 
	.byte 0x00 
	.byte 0xFF 

text_exclamation: @ Whoa!
	.byte 0xD1 
	.byte 0xDC 
	.byte 0xE3 
	.byte 0xD5 
	.byte 0xAB 
	.byte 0xFF
	.byte 0x00 
	.byte 0xFF 

text_cant_headbutt: @ This tree looks like Pokémon can live in it.
	.byte 0xCE 
	.byte 0xDC 
	.byte 0xDD 
	.byte 0xE7 
	.byte 0x00 
	.byte 0xE8 
	.byte 0xE6 
	.byte 0xD9 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xE0 
	.byte 0xE3 
	.byte 0xE3 
	.byte 0xDF 
	.byte 0xE7 
	.byte 0x00 
	.byte 0xE0 
	.byte 0xDD 
	.byte 0xDF 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xCA 
	.byte 0xE3 
	.byte 0xDF 
	.byte 0x1B 
	.byte 0xE1 
	.byte 0xE3 
	.byte 0xE2 
	.byte 0x00 
	.byte 0xD7 
	.byte 0xD5 
	.byte 0xE2 
	.byte 0xFE 
	.byte 0xE0 
	.byte 0xDD 
	.byte 0xEA 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xDD 
	.byte 0xE2 
	.byte 0x00 
	.byte 0xDD 
	.byte 0xE8 
	.byte 0xAD 
	.byte 0xFF 
	.byte 0x00 
	.byte 0xFF 

text_tree_undisturbed: @ But the tree remained undisturbed...
	.byte 0xBC 
	.byte 0xE9 
	.byte 0xE8 
	.byte 0x00 
	.byte 0xE8 
	.byte 0xDC 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xE8 
	.byte 0xE6 
	.byte 0xD9 
	.byte 0xD9 
	.byte 0x00 
	.byte 0xE6 
	.byte 0xD9 
	.byte 0xE1 
	.byte 0xD5 
	.byte 0xDD 
	.byte 0xE2 
	.byte 0xD9 
	.byte 0xD8 
	.byte 0xFE 
	.byte 0xE9 
	.byte 0xE2 
	.byte 0xD8 
	.byte 0xDD 
	.byte 0xE7 
	.byte 0xE8 
	.byte 0xE9 
	.byte 0xE6 
	.byte 0xD6 
	.byte 0xD9 
	.byte 0xD8 
	.byte 0xAD 
	.byte 0xAD 
	.byte 0xAD 
	.byte 0xFF 
	.byte 0x00

.org 0x080A029C

create_scripted_mon: @ (u16 species, u8 level, u16 item)
	push {r4-r7, lr}
	
.org 0x081E4684

@ returns r0 = dividend % divisor
__umodsi3: @ (u16 dividend, u16 divisor)
	cmp r1, #0
this is also downloadable here.

this implements a modified jpan's behavior byte hack so that it takes up far less space (only affects the behavior byte entries it governs). it then adds a new entry, a pointer to the script that's also dynamically compiled. by default, this new one is behavior byte 0xA4!

in its purest form, you need to configure the tables and then compile it using your favorite asm compiling software. go to 0x806D1F0 and copy it until the zeros are reached. note that you will need to edit the tables in there as you so desire.
each new table needs to be referenced in tableoftables so that the code will read it.
copy that over to 0x6D1F0 in your fire red v1.0 rom. that's it! all you have to do.

tables are split into entries for each pokemon, each 7 bytes:
[2 bytes] - species
[1 byte] - lower level
[1 byte] - higher level
[2 bytes] - item
[1 byte] - chance of appearing (when subtracted from the previous entry's chance entry, it gives the specific entry's chance of appearing

this will generate a pokemon of the defined species with a random level between lower level and higher level with the item in the table.

in editing the tables, there's an .equ for table_amount. edit that to accomodate the new tables; it's currently at 3.

now, i tried to label it as well as i could. ask me any questions you have on the code ahaha

this system works by loading separate tables based on the second byte in advancemap labeled "behavior byte" when given a certain behavior byte. you know, this one:



in classic amap fashion, this is rather wrong

what happens in the code is that all 4 of those are considered one 4-byte word and the game retrieves the values it wants in various fields

everything that wants to retrieve a value from this area eventually references 0x8058F1C, or blockinfo_get_field in knizz's idb.
it takes the blockinfo and a field value and returns the value of that field.

blockinfo_get_field uses the words at 352EF0, or's it w the blockinfo (the 4 bytes from the block editor in amap), and returns the result shifted right by the corresponding entry in the byte array at 352F10. this results in a neat return value.

field 0 is the behavior byte field, like the main one, but is also 1 bit from the second byte (it's 9 bits long)
the one that is kind of labeled in amap

field 1 is then part of the second byte labeled as a behavior byte. this is the field i used in this to try not to rewrite anything too extensively
within the second byte, we split it down into bits:

[7] [6] [5] [4] [3] [2] [1] [0]

field 1 is bits 1-5 (NOT zero!). they are bold in the above example. this is why the grass is 2, and the water is 4; the values for field 1 for these respective values are actually 1 and 2!

what this practically means? the second byte is the table number * 2. so if i wanted to use table 3 (the 4th table because of 0-indexing), then i would put 6 in that second field.
for ease of editing, a bunch of equ's for various bug pokemon are included in the file. brightpowder is also the only defined item, but that can be changed if you so desire.

so that tree in the amap screen up there? it's a headbutt tree (behavior byte 0xA4) that accesses table 2.

ONE NOTE ON THIS

you have 0x358 bytes to work with here. if you go to 0x806D1F0 in the compiled binary and select all those bytes and the size is over 0x358, then you will be overwriting surfing code.
you have up to 0x6D548.
this supports easy repointing, be it the tree tables or the script. either way, just uncomment one of the org's and change it to the place where free space is.

with all that done, you should have a new headbutt tree system in your game! see you next time~



EDIT: also i have half a mind to take thread ownership. i'll start compiling a list of everything here and links to them w descriptions when i have free time tomorrow and then ask if i can take over after everything is compiled
__________________
heyo check out my github:

BluRosie
highlights:
battle engine for heartgold
various feature branches in heart gold (fairy type, odd egg, mud slopes)

i'm a big part of the development team of pokemon firegold! all the code that i develop for that hack is also on my github

also on discord: BluRose#0412
Reply With Quote
  #1480   Link to this post, but load the entire thread.  
Old December 22nd, 2019 (2:30 AM). Edited November 14th, 2021 by ~Andrea.
~Andrea's Avatar
~Andrea ~Andrea is offline
 
Join Date: Oct 2012
Gender: Male
Posts: 247
Colored Stats based on Nature[RUBY]
To implement this feature, only one routine is needed:
Spoiler:

Code:
.THUMB
.ALIGN 2

PUSH {R0-R7}
MOV R0, R5
PUSH {R1-R7}
BL GET_NATURE
POP {R1-R7}
LDR R1, = 0x081FD070
MOV R2, #5
MUL R0, R2
ADD R6, R0, R1

MOV R4, #1
LOOP:
MOV R0, R5

MOV R2, PC
ADD R2, R2, #0x74
LDRB R1, [R2, R4]
MOV R7, R1

GET_DATA:
PUSH {R1-R7}
BL GET_MON_DATA
POP {R1-R7}
MOV R1, R0
LDR R0, .BUFFER
PUSH {R0-R7}
BL INT_TO_DEC
POP {R0-R7}

MOV R0, R4
MOV R1, #3
PUSH {R1-R7}
BL MOD
POP {R1-R7}
LSL R3, R0, #1
ADD R3, R3, #7

LDR R0, .BUFFER
MOV R1, #0xF

MOV R2, #22
CMP R4, #3
BLT COLORED

ADD R2, R2, #9

COLORED:
SUB R7, R7, #0x3B
LDRB R7, [R6, R7]

CMP R7, #0
BEQ PRINT_STR
CMP R7, #0xFF
BEQ LOWER

UPPER:
MOV R1, #0xB
B PRINT_STR

LOWER:
MOV R1, #0xC

PRINT_STR:
PUSH {R0-R7}
MOV R4, #36
BL PRINT
POP {R0-R7}
ADD R4, R4, #1
CMP R4, #6
BNE LOOP
POP {R0-R7}

LDR R0, = 0x080A0048+1
BX R0

GET_NATURE:
LDR R1, = 0x0803F464+1
BX R1

PRINT:
LDR R4, = 0x080A1F48+1
BX R4

GET_MON_DATA:
LDR R2, = 0x0803CB60+1
BX R2

INT_TO_DEC:
LDR R2, = 0x08006DDC+1
BX R2

MOD:
LDR R2, = 0x081E0F08+1
BX R2

.ALIGN 2
.BUFFER:	.WORD 	0x020231CC
.TABLE:		.BYTE 	0x3A
		.BYTE 	0x3B
		.BYTE 	0x3C
		.BYTE 	0x3E
		.BYTE 	0x3F
		.BYTE 	0x3D
		.HWORD 	0

After compiling the routine in a free offset, go to 0x09FFBC and overwrite the bytes with 00480047xxxxxx08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).
__________________
Reply With Quote
  #1481   Link to this post, but load the entire thread.  
Old January 8th, 2020 (2:13 AM).
eMMe97 eMMe97 is offline
 
Join Date: Jan 2015
Posts: 51
Quote:
Originally Posted by Koople View Post
Side Quest Menu [FR]

This hack converts the PC item storage menu into a side quest menu, or task list, etc.

Here is the repository, the compilation instructions are included in the readme. You will need to define your own parameters/ram in src/headers/defs.asm and create your own tables of string pointers for all of the quest names, descriptions, item images, and quest details. I kept the item image part to allow hackers to include items that might be symbolic of their quest, eg. a scroll or key or pokeball.

To use in a script (XSE)
Code:
writebytetooffset 0x1 <your questflag ram in src/headers/defs.asm>
fadescreen 0x1
callasm 0x80EBCD9
waitstate
Enjoy! And please let me know of any bugs.
I have a lot of problem with this Side Quest Menu...I make some screens

Item Menu doesn't show the item name



Item menu without item show ?????? 0x0 item



Quest Menu doesn't show quest name with activate flag ON

Reply With Quote
  #1482   Link to this post, but load the entire thread.  
Old January 8th, 2020 (7:49 AM).
Neon Skylar's Avatar
Neon Skylar Neon Skylar is offline
 
Join Date: May 2014
Location: Venezuela n_n
Gender: Male
Posts: 75
This is the code to show icon on pause menu for Ruby by Andrea.. I need help to insert it on emerlad

.THUMB
.ALIGN 2
@08071174 00490847XXXXXX08
@080711C8 MOVS R0, #0x16 @coordinata x
@08071208 lunghezza cursore
@0807120E posizione X cursore

PUSH {R0-R7}
LDR R1, = 0x06008020
LDR R0, = 0x087200D0
MOV R2, #0x15
LSL R2, #4
SWI 0xC

LSL R2, #2
ADD R0, R2

MOV R3, #1
LSL R3, #10

LDR R1, = 0x0202EC48
MOV R2, #8
SWI 0xC
LDR R4, = 0x0202FEB3
LDRB R4, [R4]
CMP R4, #0x16
BNE ICONE
ADD R1, R1, R3
SWI 0xC

ICONE:
MOV R6, #0

MOV R0, #1
LSL R0, #11
ADD R0, #1
BL CHECKFLAG
CMP R0, #0
BEQ PARTY

ADD R6, #1
MOV R0, #0
MOV R1, #0
BL SPAWN

PARTY:
MOV R0, #1
LSL R0, #11
BL CHECKFLAG
CMP R0, #0
BEQ ALTRO

MOV R0, #1
ADD R6, #1
CMP R6, #2
BEQ CONTROLLO
MOV R0, #0
CONTROLLO:
MOV R1, #1
BL SPAWN

ALTRO:
LDR R5, = 0x0202E8FD
LDRB R5, [R5]

MOV R7, #2
LOOP2:
MOV R0, R6
MOV R1, R7
BL SPAWN
ADD R6, #1
ADD R7, #1
CMP R6, R5
BNE LOOP2

FINE:
POP {R0-R7}
POP {R4-R7,PC}

SPAWN:
LSL R0, #7
LDR R2, = 0x0600F8A8
ADD R0, R2
MOV R3, #6
MUL R1, R3
ADD R1, #1
MOV R2, #0xC0
LSL R2, #8
ADD R1, R2
MOV R2, #0
MOV R3, #0
LOOP:
STRH R1, [R0]
ADD R0, #2
ADD R1, #1
ADD R2, #1
CMP R2, #3
BNE LOOP
ADD R0, #0x3A
MOV R2, #0
ADD R3, #1
CMP R3, #2
BNE LOOP
BX LR

CHECKFLAG:
PUSH {R0}
LDR R0, = 0x08069341
MOV R10, R0
POP {R0}
BX R10
Reply With Quote
  #1483   Link to this post, but load the entire thread.  
Old January 8th, 2020 (8:02 PM).
Ruux Ruux is offline
 
Join Date: Oct 2016
Gender: Male
Posts: 13
I want to change the amount of experience given by pokemon in Fire Red. I could go through and manually update the values of each pokemon, but I'm just wondering if anybody knows where to find the offset where the experience formula is.
Reply With Quote
  #1484   Link to this post, but load the entire thread.  
Old January 15th, 2020 (5:30 AM). Edited January 15th, 2020 by Dr. POP.
Dr. POP's Avatar
Dr. POP Dr. POP is offline
 
Join Date: Sep 2009
Location: Mt. Silver
Gender: Male
Posts: 119
Quote:
Originally Posted by FBI View Post

Pokemon Storage (outside the PC)



Basically, in it's current state, this is effectively a storage system. It stores Pokemon and can be interacted with by the player to withdraw or deposit Pokemon. It's standalone from the PC storage system and is also much smaller (I've limited it to 6, but it can go upto 47). Some things that you will be able to do with this routine (and conjunction with some smaller ones) include:
- Extra Pokemon storage, you can possibly get a little over 1 box worth
- Flash back battles (complete swap between stored Pokemon and party Pokemon with capabilities to swap back)
- Carry a party of greater than 6 Pokemon (you can use the 2nd party for HM slaves, or whatever)
- Trade evolver guy! He will take your Pokemon and then when you come back it can be evolved! (silent evolution ftw!)
- Separate Daycare holding larger amount of Pokemon at once

I've tested it thoroughly and there doesn't seem to be any problems. I will be adding more and more features into this because I believe that it has the potential to become a very useful feature.
Currently planning to add:
- Party swap completely all in one go (this will actually be in the very near future..maybe today even :P)
- Partial swapping (believe it or not, this is hard because there's no graphical support)
- Suggest me more :D

Spoiler:
How to insert:

Compile into free space the following routine:
Spoiler:

Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0, r4, lr}
	ldr r0, .FROM
	ldr r1, [r0]
	cmp r1, #0x0 @party
	beq addParty

addStorage:
	ldr r0, .STORAGE
	sub r0, r0, #0x1
	ldrb r1, [r0]
	cmp r1, #0x6 @limit of storage. Change depending on your space situation
	beq end
	add r0, r0, #0x1
	mov r2, #0x50
	cmp r1, #0x0
	beq skipline
	sub r1, r1, #0x1
	mul r1, r1, r2
	add r0, r0, r1 @destination
	ldr r1, =(0x20370C0)
	ldrb r1, [r1]
	ldr r2, .PARTY
	mov r3, #0x64
	mul r1, r1, r3
	add r1, r1, r2 @source
	mov r2, #0x50 @size
	ldr r3, =(0x8040B08 +1) @func
	bl linker
	@need to fix up Player's party slots
	ldr r1, =(0x20370C0)
	ldrb r1, [r1]
	cmp r1, #0x5
	beq writeLastZero
	mov r2, #0x5
	sub r2, r2, r1
	mov r3, #0x64
	mul r2, r2, r3 @size
	ldr r0, .PARTY
	mul r1, r1, r3
	add r0, r0, r1 @dest
	add r3, r3, r0
	mov r1, r3      @src
	ldr r3, =(0x8040B08 +1) @func
	bl linker
	

writeLastZero:
	ldr r0, =(0x2024478)
	mov r1, #0x0
	mov r2, #0x64
	ldr r3, =(0x81E5ED8 +1)
	bl linker

correctCounters:
	ldr r0, .STORAGE
	sub r0, r0, #0x1
	ldrb r2, [r0]  @pks in storage counter
	ldr r1, =(0x2024029)
	ldrb r3, [r1] @pks in party
	add r2, r2, #0x1
	strb r2, [r0]
	sub r3, r3, #0x1
	strb r3, [r1]
	b end
	


addParty:
	ldr r0, =(0x2024029)
	ldrb r0, [r0]
	cmp r0, #0x6
	beq end
	ldr r1, .PARTY
	mov r2, #0x64
	mul r0, r0, r2
	add r0, r0, r1 @destination
	mov r4, r0
	ldr r3, .STORAGE
	ldr r1, =(0x20370C0) @var 0x8004 determines which slot of storage to take from
	ldrb r1, [r1]
	mov r2, #0x50 @size
	mul r1, r1, r2
	add r1, r1, r3 @source
	ldr r3, =(0x8040B08 +1) @func
	bl linker
	@update stats 
	mov r0, r4
	ldr r3, =(0x803E47C +1)
	bl linker
	@adjust the storage
	ldr r0, =(0x20370C0)
	ldrb r0, [r0]
	cmp r0, #0x5 @storage limit minus 1
	beq writeZero
	mov r2, #0x5
	sub r2, r2, r0
	mov r3, #0x50
	mul r2, r2, r3 @size
	ldr r1, .STORAGE
	mul r0, r0, r3
	add r0, r0, r1 @dest
	add r3, r3, r0
	mov r1, r3      @src
	ldr r3, =(0x8040B08 +1) @func
	bl linker

writeZero:
	ldr r0, .STORAGE
	mov r1, #0xC8
	lsl r1, r1, #0x1
	add r0, r0, r1
	mov r1, #0x0
	mov r2, #0x50
	ldr r3, =(0x81E5ED8 +1)
	bl linker

updateCounters:
	ldr r0, .STORAGE
	sub r0, r0, #0x1
	ldrb r2, [r0]
	ldr r1, =(0x2024029)
	ldrb r3, [r1]
	sub r2, r2, #0x1
	strb r2, [r0]
	add r3, r3, #0x1
	strb r3, [r1]

end:
	pop {r0-r4, pc}	

linker:
	bx r3	
	
.align 2

.FROM:
	.word 0x20270B8 + (0x8000 *2)

.STORAGE:
	.word 0x203C001 @storage location

.PARTY:
	.word 0x2024284 @player's party


Here's a compiled version:
Code:
11 B5 38 48 01 68 00 29 32 D0 37 48 01 38 01 78 06 29 65 D0 01 30 50 22 51 43 40 18 34 49 09 78 32 4A 64 23 59 43 89 18 50 22 32 4B 00 F0 59 F8 2F 49 09 78 05 29 0B D0 05 22 52 1A 64 23 5A 43 2A 48 59 43 40 18 1B 18 19 1C 2A 4B 00 F0 49 F8 29 48 00 21 64 22 29 4B 00 F0 43 F8 22 48 01 38 02 78 27 49 0B 78 01 32 02 70 01 3B 0B 70 37 E0 23 48 00 78 06 28 33 D0 1C 49 64 22 50 43 40 18 04 1C 19 4B 1A 49 09 78 50 22 51 43 C9 18 19 4B 00 F0 27 F8 20 1C 1B 4B 00 F0 23 F8 14 48 00 78 05 28 0B D0 05 22 12 1A 50 23 5A 43 0E 49 58 43 40 18 1B 18 19 1C 0F 4B 00 F0 13 F8 0A 48 C8 21 49 00 40 18 00 21 50 22 0C 4B 00 F0 0A F8 06 48 01 38 02 78 0A 49 0B 78 01 3A 02 70 01 33 0B 70 1F BD 18 47 B8 70 03 02 01 C0 03 02 84 42 02 02 C0 70 03 02 09 0B 04 08 78 44 02 02 D9 5E 1E 08 29 40 02 02 7D E4 03 08
Usage:

The routine itself manages party storage and storage extraction. What you need to do is determine which one it performs.
If you want to remove a Pokemon from the party and into storage, setvar 0x8000 anything but zero
if you want to remove a Pokemon from storage, setvar 0x8000 0x0
Which variable you used can be changed, as always, by editing the pointer at the bottom of the routine.
The next thing is variable 0x8004. I use this variable to determine the slot of extraction for both the Party and the Storage system.
If I wanted to take the 3rd Pokemon in the party and put it in storage:
setvar 0x8004 0x2
setvar 0x8000 0x1
callasm 0x[routine] +1

The reason for this is to support easy use of special 0x9F. Though you can use copyvar, I suppose.

Finally, the routine writes to RAM a counter, which keeps track of how many Pokemon are in the storage.
This is written at 0x203C000, and can be retrieved by using the "copybyte" scripting command. For example:
copybyte 0x20370D0 0x203C000 'puts the storage counter into variable 0x800D (lastresult).

I tried to keep it simple, and do the work inside the routine, hopefully that paid off.
Here's a very poor sample script. Poor because it handles all the cases, but it doesn't display the system's full potential :P

Spoiler:

PKSV script.
Code:
#dyn 0x740000
#org @start
lock
faceplayer
copybyte 0x20370D0 0x203C000 ' storage count into last result
compare LASTRESULT 0x0
if == jump @putOnly
msgbox @add
callstd MSG_YESNO 'want to take?
compare LASTRESULT 0x1
if == jump @addParty
jump @putOnly

#org @putOnly
countpokemon
copyvar 0x8000 0x800D
compare 0x8000 0x1
if <= jump @greetings
msgbox @put
callstd MSG_YESNO 'want to put?
compare LASTRESULT 0x1
if == jump @addStorage
msgbox @exit
callstd MSG_NORMAL
release
end

#org @addStorage
setvar 0x8000 0x1
special 0x9F
waitspecial
countpokemon
compare LASTRESULT 0x8004
if < jump @noSelection
callasm 0x[routine +1]
msgbox @gave
callstd MSG_NORMAL
release
end


#org @addParty
setvar 0x8000 0x0
countpokemon
compare LASTRESULT 0x6
if == jump @fullP
msgbox @store
callstd MSG_NORMAL
setvar 0x8004 0x0 'gotta rework this to work a better way
callasm 0x[routine +1]
fanfare 0x101
msgbox @complete
callstd MSG_NORMAL
release
end

#org @greetings
msgbox @hello
callstd MSG_NORMAL
release
end

#org @fullP
msgbox @full
callstd MSG_NORMAL
release
end

#org @noSelection
msgbox @exit
callstd MSG_NORMAL
release
end

#org @full
= You're party is full!

#org @hello
= Hi, I can't do anything\nyour slots are full or empty\lor mine are full while yours are\lfull[.]

#org @complete
= I gave it back.

#org @store
= Alright, I'll give it to you.

#org @gave
= Thanks for giving me this.

#org @exit
= Alright, next time then.

#org @add
= Want your Pokemon back?

#org @put
= Want to give me a pokemon?


That's it for now. Keep an eye out for "addons" for this routine in the future :)
Sorry for the double post. I like seperate posts for my routines to keep the first post's links neat :x
It seems that the memory location for the storage system (0x203C000) has been used already by another ASM routine my ROM base (Leon/UltimaSoul's) has implemented. I cannot find which exact memory locations are free, but I figured the best shot would be 0x203CC00.

I have tried to amend the routine by simply changing the memory location in the routine under .STORAGE. However, unfortunately the game freezes when the ASM routine is called. What is the best way to relocate the storage system to free memory space? Am I missing something obvious? Thanks in advance for any help!
Reply With Quote
  #1485   Link to this post, but load the entire thread.  
Old February 1st, 2020 (10:47 AM). Edited February 1st, 2020 by Zeturic.
Zeturic's Avatar
Zeturic Zeturic is offline
 
Join Date: Mar 2007
Posts: 787
Functional Pokérus [FR]

This allows Pokérus to be caught randomly, spread between Pokémon, and (optionally) cured. It also includes a
special
for checking if a Pokémon in the player's party has Pokérus, for use in a Nurse Joy script.

Curing Pokérus is based on walking around, not on an RTC.

Several of the Pokérus related functions included here were lifted directly (or with small modifications) from pokeemerald.

Let me know if you have issues.
Reply With Quote
  #1486   Link to this post, but load the entire thread.  
Old February 8th, 2020 (7:36 PM). Edited February 8th, 2020 by Zeturic.
Zeturic's Avatar
Zeturic Zeturic is offline
 
Join Date: Mar 2007
Posts: 787
More Options For In-Game Trades [FR]

It allows you to have In-Game Trades that come with/at/in:
  • Static levels, like in newer games
  • Pokérus
  • Custom movesets
  • PP bonuses
  • Poké Balls other than the default

You can also use it as a sort of trade editor, because it extracts the in-game trade data from your ROM in a compilable form you can modify.

Let me know if you run into issues.

Spoiler:

I originally posted several of these as standalone ASM hacks. I decided to bring them together by reimplementing them in C instead of having so many
bpre-trade-whatever
repositories on my Github. I have privated the repos containing the standalone ASM versions, and deleted the posts about them. Sorry for any confusion.
Reply With Quote
  #1487   Link to this post, but load the entire thread.  
Old February 9th, 2020 (3:40 PM).
Super Versekr Dark Super Versekr Dark is offline
 
Join Date: Jan 2017
Gender: Male
Posts: 79
Quote:
Originally Posted by ~Andrea View Post
Colored Stats based on Nature[RUBY]
To implement this feature, only one routine is needed:
Spoiler:

Code:
.THUMB
.ALIGN 2

PUSH {R0-R7}
LDR R1, = 0x02018009
LDRB R1, [R1]
MOV R0, #0x64
MUL R1, R0
LDR R0, = 0x03004360
ADD R0, R0, R1
PUSH {R1-R7}
BL GET_NATURE
POP {R1-R7}
LDR R1, = 0x081FD070
MOV R2, #5
MUL R0, R2
ADD R5, R0, R1

MOV R4, #1
LOOP:
LDR R1, = 0x2018009
LDRB R1, [R1]
MOV R0, #0x64
MUL R0, R1
LDR R1, = 0x03004360
ADD R0, R0, R1

MOV R2, PC
ADD R2, R2, #0x74
LDRB R1, [R2, R4]
MOV R7, R1

GET_DATA:
PUSH {R1-R7}
BL GET_MON_DATA
POP {R1-R7}
MOV R1, R0
LDR R0, .BUFFER
PUSH {R0-R7}
BL INT_TO_DEC
POP {R0-R7}

MOV R0, R4
MOV R1, #3
PUSH {R1-R7}
BL MOD
POP {R1-R7}
LSL R3, R0, #1
ADD R3, R3, #7

LDR R0, .BUFFER
MOV R1, #0xF

MOV R2, #22
CMP R4, #3
BLT COLORED

ADD R2, R2, #9

COLORED:
SUB R7, R7, #0x3B
LDRB R7, [R5, R7]

CMP R7, #0
BEQ PRINT_STR
CMP R7, #0xFF
BEQ LOWER

UPPER:
MOV R1, #0xB
B PRINT_STR

LOWER:
MOV R1, #0xC

PRINT_STR:
PUSH {R0-R7}
MOV R4, #36
BL PRINT
POP {R0-R7}
ADD R4, R4, #1
CMP R4, #6
BNE LOOP
POP {R0-R7}

LDR R0, = 0x080A0048+1
BX R0

GET_NATURE:
LDR R1, = 0x0803F464+1
BX R1

PRINT:
LDR R4, = 0x080A1F48+1
BX R4

GET_MON_DATA:
LDR R2, = 0x0803CB60+1
BX R2

INT_TO_DEC:
LDR R2, = 0x08006DDC+1
BX R2

MOD:
LDR R2, = 0x081E0F08+1
BX R2

.ALIGN 2
.BUFFER:	.WORD 	0x020231CC
.TABLE:		.BYTE 	0x3A
		.BYTE 	0x3B
		.BYTE 	0x3C
		.BYTE 	0x3E
		.BYTE 	0x3F
		.BYTE 	0x3D
		.HWORD 	0

After compiling the routine in a free offset, go to 0x09FFBC and overwrite the bytes with 00480047xxxxxx08.
Instead of the XX, will be entered the offset of previous routine + 1 and in Little Endian format (example: 08123456 -> 57 34 12 08).
How to invert the colors from red to blue?
Reply With Quote
  #1488   Link to this post, but load the entire thread.  
Old February 12th, 2020 (3:23 AM).
ShinypikachuX's Avatar
ShinypikachuX ShinypikachuX is offline
 
Join Date: Sep 2017
Posts: 44
Is it possible to make gym leaders have Pokemon based on your average party level ?
Reply With Quote
  #1489   Link to this post, but load the entire thread.  
Old March 4th, 2020 (5:27 PM).
Super Versekr Dark Super Versekr Dark is offline
 
Join Date: Jan 2017
Gender: Male
Posts: 79
Quote:
Originally Posted by FBI View Post
Thanks. Though I would like to point out, to use them all you really need to know is how to insert them and what they do. I've documented a guide on how to insert for beginners (it's a link in the FAQ first post). If you don't understand something or don't see how some routine works, feel free to ask!


:3



I'm still not understanding the incentive to randomizing the starting Pokemon. I suppose it would be a small bit of "game change" if someone were to play your hack more than once, but the feature seems a little useless to me :/



Yeah it definitely could, and should read off of a table. I'll have to redo that little bit :x


Battle Modes addon: Delete fainted Pokemon



For those hackers who like minigames, this routine will delete Pokemon who have fainted in battle. There's a few things that need to happen for this effect to occur.

1) Pokemon who die in battle must be deleted
2) Eggs are spared
3) Pokemon who die outside of battle must be deleted (Poison or another similar effect)

However, if you put this in turn basis, you will NEED to make another routine to delete the Player's party if he/she loses the match. This is because the turn counter isn't reached on the last turn the player loses :x

If you're lazy like me you can just put this routine in as a battle by move addon and cover the whiteout case. Which is actually fine. It's rather fast, because it deletes the Pokemon as they die, so the worse case scenario is unforeseeable. And if a Pokemon dies it will only need to loop 5 times only doing operations on one of the 5 loops. If you're curious looping a maximum of 21 times is the worst case scenario (all 6 of your Pokemon die in 1 turn i.e never, and even if that did happen it'd be done in less .25 seconds). So it's fine to put in the battle by move section without expecting the game to lag.


How to insert:
Insert as addon to battle modes battle by move.
You will notice that near the start of the routine there is some commented out code (denoted by a prefix "@" symbol). That's for a flag check. Change [flag/4] = your flag/4 in hex if you want to toggle by flag. Of course the normal battle mode toggle flag should be used as well.

Spoiler:

Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r5, lr}
	@mov r0, #0x[flag/4]
	@lsl r0, r0, #0x2
	@ldr r3, =(0x806E6D0 +1)
	@bl linker
	@cmp r0, #0x0
	@beq end
	ldr r0, =(0x2023E8A)
	ldrb r0, [r0]
	cmp r0, #0x0
	beq realEnd
	mov r5, #0x0

loop:
	ldr r0, =(0x2024029)
	ldrb r4, [r0]
	cmp r5, r4
	beq end
	ldr r0, =(0x2024284)
	mov r1, #0x64
	mul r1, r1, r5 @slot
	add r0, r0, r1 @address
	mov r1, #0x39 @C_HP
	ldr r3, =(0x803FBE8 +1)
	bl linker
	cmp r0, #0x0
	beq adjustSlots

skip:
	add r5, r5, #0x1
	b loop


adjustSlots:
	cmp r5, #0x5
	bge writeLastZero	
	mov r2, #0x5
	sub r2, r2, r5
	mov r0, #0x64
	mul r2, r2, r0 @size
	mov r1, r5
	mul r1, r1, r0
	ldr r0, =(0x2024284)
	add r0, r0, r1 @dest
	mov r1, #0x64
	add r1, r0, r1 @src
	ldr r3, =(0x8040B08 +1)
	bl linker


writeLastZero:
	ldr r0, =(0x2024478)
	mov r1, #0x0
	mov r2, #0x64
	ldr r3, =(0x81E5ED8 +1)
	bl linker

correctCounters:
	ldr r0, =(0x2024029)
	ldrb r1, [r0]
	sub r1, r1, #0x1
	strb r1, [r0]
next:
	mov r5, #0x0
	b loop	

end:
	ldr r0, =(0x2024029)
	ldrb r0, [r0]
	cmp r0, #0x0
	bne realEnd
	mov r0, #0x5E
	lsl r0, r0, #0x4
	ldr r3, =(0x806E6A8 +1)
	bl linker
	b realEnd


linker:
	bx r3

realEnd:
	pop {r0-r5, pc}


.align 2



Usage:
If you opted to use a flag, set it to allow further battles to delete Pokemon as they faint. If you didn't just sit back and let the unicorns inside the game do the rest.

I need help for pokemon ruby routine:

Spoiler:
.text
.align 2
.thumb
.thumb_func

main:
push {r0-r5, lr}
@mov r0, #0x94
@lsl r0, r0, #0x2
@ldr r3, =(0x8069340 +1)
@bl linker
@cmp r0, #0x0
@beq end
ldr r0, =(0x202252E)
ldrb r0, [r0]
cmp r0, #0x0
beq realEnd
mov r5, #0x0

loop:
ldr r0, =(0x20226D1)
ldrb r4, [r0]
cmp r5, r4
beq end
ldr r0, =(0x2022928)
mov r1, #0x64
mul r1, r1, r5 @slot
add r0, r0, r1 @address
mov r1, #0x39 @C_HP
ldr r3, =(0x803cb60 +1)
bl linker
cmp r0, #0x0
beq adjustSlots

skip:
add r5, r5, #0x1
b loop


adjustSlots:
cmp r5, #0x5
bge writeLastZero
mov r2, #0x5
sub r2, r2, r5
mov r0, #0x64
mul r2, r2, r0 @size
mov r1, r5
mul r1, r1, r0
ldr r0, =(0x2022928)
add r0, r0, r1 @dest
mov r1, #0x64
add r1, r0, r1 @src
ldr r3, =(0x803D910 +1)
bl linker


writeLastZero:
ldr r0, =(0x2022B24)
mov r1, #0x0
mov r2, #0x64
ldr r3, =(0x81E275C +1)
bl linker

correctCounters:
ldr r0, =(0x20226D1)
ldrb r1, [r0]
sub r1, r1, #0x1
strb r1, [r0]
next:
mov r5, #0x0
b loop

end:
ldr r0, =(0x20226D1)
ldrb r0, [r0]
cmp r0, #0x0
bne realEnd
mov r0, #0x5E
lsl r0, r0, #0x4
ldr r3, =(0x8069318 +1)
bl linker
b realEnd


linker:
bx r3

realEnd:
pop {r0-r5, pc}


.align 2
Reply With Quote
  #1490   Link to this post, but load the entire thread.  
Old March 11th, 2020 (4:52 PM).
dearman4's Avatar
dearman4 dearman4 is offline
 
Join Date: Nov 2017
Location: Michigan
Age: 30
Gender: Male
Nature: Quirky
Posts: 620
Quote:
Originally Posted by FBI View Post

Temporarily disabling EXP gains from battle



It was brought to my attention by some requesters that for their battle/tournament events they wouldn't want their Pokemon leveling up. This routine disables the exp gains in battle. Note that the player can still use stuff like Rare Candy to level. The fix to that is exactly the same as this, but with slight modifications. I hope you don't give the player a chance to rare candy in battle though or I will go to your hack's thread and severly criticize your lack of common sense :c


How to insert:

Compile and insert the following routine into free space:

Spoiler:

Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r3}
	mov r0, #0xFF
	lsl r0, r0, #0x1
	add r0, r0, #0x4
	ldr r2, =(0x806E6D0 +1) @checkflag 0xFF *0x2 + 4 = 0x202
	bl linker
	cmp r0, #0x1
	beq skip
	pop {r0-r3}
	cmp r0, #0x64
	beq noCrash
	ldr r0, =(0x8021D24 +1)
	bx r0
	
skip:
	pop {r0-r3}
	
noCrash:
	ldr r1, [r5]
	add r1, #0x53
	ldrb r0, [r1]
	ldr r2, =(0x8021D04 +1)

linker:
	bx r2
		
.align 2
Here's a compiled version:
Code:
0F B4 FF 20 40 00 04 30 07 4A 00 F0 0C F8 01 28 04 D0 0F BC 64 28 02 D0 04 48 00 47 0F BC 29 68 53 31 08 78 02 4A 10 47 D1 E6 06 08 25 1D 02 08 05 1D 02 08


Now navigate to 0x21CFA and insert the following byte changes:
Code:
00 00 00 49 08 47 XX XX XX 08
Where XX XX XX is the reverse hex pointer to where you inserted this routine +1.

Usage:

If flag 0x202 is set, the EXP gains will be disabled. Obviously, to re-enable just clear the flag.
Currently the way I'm doing this is by making the game act like the player's party is already max level, so therefore they don't gain exp :)
Is there a way to do this in Emerald? Also, is there a way to have a flag reduce experience gain by half in Emerald? I've implemented the gen VI exp share asm but that gives 100% to every pokemon, I would really like to have the amount be configurable!
__________________
My ROM hack, Pokemon Emerald Final:
https://www.pokecommunity.com/showthread.php?p=9898603
My beginner's devkit tutorial:
https://www.pokecommunity.com/showthread.php?t=411844
Reply With Quote
  #1491   Link to this post, but load the entire thread.  
Old March 27th, 2020 (1:41 AM).
AkameTheBulbasaur's Avatar
AkameTheBulbasaur AkameTheBulbasaur is offline
Akame Marukawa of Iyotono
 
Join Date: May 2013
Location: A place :D
Age: 25
Gender: Male
Nature: Docile
Posts: 408
Shiny ShowPokePic (For FireRed)

If you use these two routines, then if you set Var 0x8003 to 0x1, before using the showpokepic command in an NPC script, then the Pokemon in the resulting picture will appear Shiny!

Spoiler:
/* Put 00 49 08 47 XX XX XX 08 at 0x8398C */
.text
.align 2
.thumb
.thumb_func
.global ShinyPalette

CheckVar:
ldr r1, .Var8003
ldrh r1, [r1]
cmp r1, #0x1
beq Shiny

Normal:
ldr r1, .NormalPal
lsl r4, r0, #0x3
add r4, r4, r1
ldrh r1, [r4, #0x4]
b Return

Shiny:
ldr r1, .ShinyPal
lsl r4, r0, #0x3
add r4, r4, r1
ldrh r1, [r4, #0x4]

Return:
str r1, [sp, #0xC]
mov r1, #0x0
ldr r2, .Return
bx r2

.align 2
.Var8003: .word 0x020370BE
.NormalPal: .word 0x0823730C
.ShinyPal: .word 0x082380CC
.Return: .word 0x08083999


Spoiler:
/* Put 00 49 08 47 XX XX XX 08 0x44198 */
.text
.align 2
.thumb
.thumb_func
.global ShinyPalette

CheckVar:
ldr r1, .Var8003
ldrh r1, [r1]
cmp r1, #0x1
beq Shiny

Normal:
cmp r0, #0x7
bls Shiny
lsl r0, r4, #0x3
ldr r1, .NormalPal
b Return

Shiny:
lsl r0, r4, #0x3
ldr r1, .ShinyPal

Return:
ldr r4, .Return
bx r4

.align 2
.Var8003: .word 0x020370BE
.NormalPal: .word 0x0823730C
.ShinyPal: .word 0x082380CC
.Return: .word 0x080441AD




(First picture is with 0x8003 = 0x1, second is without).
__________________
"The human sacrificed himself, to save the Pokemon. I pitted them against each other, but not until they set aside their differences did I see the true power they all share deep inside. I see now that the circumstances of one's birth are irrelevant; it is what you do with the gift of life that determines who you are." -Mewtwo
Reply With Quote
  #1492   Link to this post, but load the entire thread.  
Old April 13th, 2020 (10:57 AM).
ScizorBlade's Avatar
ScizorBlade ScizorBlade is offline
Sup Dogg
 
Join Date: Apr 2020
Location: One Island
Gender: Male
Posts: 39
Quote:
Originally Posted by Pokemon_XY View Post

Time Box triggered along with the Start Menu


Preview: (Click to see the GIF animation)
Attachment 77173
The routines are only for FR. I haven't found any bugs in it. However, the CPU will run much more instructions so that it will be a bit (really?) slower when you open the 'pokemon', 'bag'..... menus.
1) Insert the RTC routine via the tool 'DNS'.
2) Insert these routines and do the byte changes:
Routine I:
Spoiler:
byte changes:
Code:
0x6F09C - 00 48 00 47 XX+1 XX XX 08
change all the 0x8750000 in the routine to the insert offset of the routine. 
change all the 0x8750001 in the routine to the insert offset + 1 of the routine.
routine:
Code:
.thumb
bl box_func
ldr r1, =0x20370FF
ldrb r0, [r1]
add r0, #1
strb r0, [r1]
mov r0, #0
add sp, sp, #0xC
pop {r4, pc}
.ltorg

box_func:
push {r4, lr}
ldr r4, =0x2037101
ldr r0, =(0x8750000 + rbox_config)
ldr r3, =0x8003ce5
bl call_r3
strb r0, [r4]
ldr r3, =0x8003fa1
bl call_r3
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x80F6F1D
bl call_r3
bl print_string
ldr r0, =(0x8750001 + print_string)
mov r1, #2
ldr r3, =0x807741D
bl call_r3
ldr r1, =0x20370C0
strh r0, [r1]
pop {r4, pc}
.ltorg

print_string:
push {r4-r7, lr}
sub sp, sp, #0xC
ldr r0, =0x2021cd0
add r7, r0, #0
ldr r1, =0x300553c
ldrb r5, [r1, #7] @minute
ldrb r6, [r1, #8] @second
ldrb r1, [r1, #6] @hour
mov r2, #1
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
bl go_padding
ldr r0, =0x2021CF0
add r7, r0, #0
add r1, r5, #0
mov r2, #1
mov r3, #2
ldr r4, =0x8008e79
bl call_r4
bl go_padding
ldr r0, =0x2021d04
add r7, r0, #0
add r1, r6, #0
mov r2, #1
mov r3, #2
ldr r4, =0x8008e79
bl call_r4
bl go_padding
ldr r5, =0x2021D18
ldr r1, =(0x8750000 + string)
add r0, r5, #0
ldr r3, =0x8008FCD
bl call_r3
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #3
str r1, [sp]
mov r1, #0xff
str r1, [sp, #4]
mov r1, #0
str r1, [sp, #8]
mov r1, #2
add r2, r5, #0
mov r3, #4
ldr r4, =0x8002C49
bl call_r4
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #2
ldr r3, =0x8003F21
bl call_r3
add sp, sp, #0xC
pop {r4-r7, pc}
.ltorg

go_padding:
push {lr}
ldrb r0, [r7]
cmp r0, #0
bne back
mov r0, #0xa1
strb r0, [r7]
back:
pop {pc}

call_r3:
bx r3

call_r4:
bx r4

.align 2
rbox_config:
.byte 0x0 @bg_id
.byte 0x1 @x
.byte 0x1 @y
.byte 0xa @width
.byte 0x2 @height
.byte 0xf
.hword 0x8 @tileset_ofs
.word 0x8419f76 @pixels

.align 2
string: 
.byte 0xce, 0xdd, 0xe1, 0xd9, 0xf0, 0xfd, 0x2, 0xf0, 0xfd, 0x3, 0xf0, 0xfd, 0x4, 0xff

Routine II:
Spoiler:
byte changes:
Code:
0x6EF1E - 00 00 00 49 08 47 YY+1 YY YY 08
routine:
Code:
.thumb
cmp r0, #1
beq safari
ldr r0, =0x20370C0
ldrh r0, [r0]
ldr r3, =0x8077509
bl call_r3

safari:
ldr r4, =0x02037101
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x806ef29

call_r3:
bx r3

Routine III:
Spoiler:
byte changes:
Code:
0x6f4e8 - 00 48 00 47 ZZ+1 ZZ ZZ 08
routine:
Code:
.thumb
push {lr}
ldr r0, =0x20370c0
ldrh r0, [r0]
ldr r3, =0x8077509
bl call_r3
ldr r1, =0x20370F0
ldr r0, =0x806f5a5
str r0, [r1]
mov r0, #0
pop {pc}
call_r3:
bx r3
In the byte change there are some XX XX XX, YY YY YY and ZZ ZZ ZZ. What are those?
Reply With Quote
  #1493   Link to this post, but load the entire thread.  
Old April 15th, 2020 (4:25 AM). Edited April 15th, 2020 by furlan92.
furlan92 furlan92 is offline
 
Join Date: Apr 2020
Posts: 1
Quote:
Originally Posted by RuFF View Post

I encountered a bug on custom give pokemon.

If the specie number is 5, the level of the pokemon will also be 5 no matter what the value you put in var 0x8001.


Okay, the real problem here is if your specie number is greater than 411 then the level of the pokemon you get is not correct.

EDIT: I have extended Pokemon. I'm using pokefreak890's base

EDITEDIT: I found the fix

Code:
.language: .word 0x081E9F11
.stat: .word 0x08254784    Change this to the location where your Pokemon Data is.
.exp: .word 0x08253AE4
I don't know if there are other stuffs that needs to be change. You only need to do this if you have extended the number of Pokemon in you rom.

EDITEDITEDIT: For some reason there are still problems to some Pokemon.

Sometimes you get Level 0, sometimes 100, sometimes 58.
I hope someone can fix this.


Did anyone ever make a fix for this? I'm trying to use it now and I can't control the level of the Pokemon.

EDIT: It works if you change the Pokemon data location.
Reply With Quote
  #1494   Link to this post, but load the entire thread.  
Old April 28th, 2020 (7:22 AM). Edited April 28th, 2020 by Pyxal.
Pyxal's Avatar
Pyxal Pyxal is offline
It's pronounced pixel.
 
Join Date: Jul 2019
Location: Pakistan
Age: 17
Posts: 987
Greetings, everybody.

Question:
Has anybody got the Rival Naming Routine by Jambo51?
I believe the post [link] has died. Any help would be appreciated, and I under stand if Jambo has prohibited from spreading it.
This isn't a request, but a favour.


Cheers.
__________________
Reply With Quote
  #1495   Link to this post, but load the entire thread.  
Old May 13th, 2020 (5:45 AM).
Pekin's Avatar
Pekin Pekin is offline
Wigglytuff is and has always been on acid.
 
Join Date: Mar 2009
Location: Denmark
Age: 29
Gender: Male
Nature: Relaxed
Posts: 282
Hey all, I have a question that I was hoping someone here could help me out with. Spherical Ice was kind enough to send me some scripts and routines for me to edit to implement the "Madam Celadon" NPC feature from the Let's Go games into my Fakemon FireRed hack - you know, an NPC you talk to which predicts the nature for future encounters, at least for a set amount of time - or, steps. The first two scripts and the first asm routine I don't have any trouble editing and inserting, but the second asm routine gives me some error messages that I don't really know how to tackle. I hope it's cool if I post everything here.

The "Mrs. Nature" script is inserted at 3B1B44
The "Nature manipulation" routine is inserted at 34F050
The "Wore off" script is inserted at 3ADDD4
And the "Pedometer" routine is supposed to be inserted at 3ADE14, but I can't convert it to a .bin file without getting these error messages:
Code:
pedometer.asm:30: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:39: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:51: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:58: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:61: Warning: Failed to find real start of function: call_via_r2
pedometer.asm:28: Error: invalid offset, value too big (0xFFFFFFFC)
I'm wondering if there's a different way I'm supposed to convert these, though, the only way I know is to put the .asm file in the same folder as thumb.bat, then navigate there with command prompt and type in "thumb routine.asm routine.bin" or something like that. I've noticed that this gives me some ridiculously long files with these routines - I can tell that it's because the new routine is generated at the specified offset, and the new pointer is included and everything, I'm just wondering if I'm supposed to be doing something different.

Anyway, here's what I got from Spherical Ice, all credit goes to him. I hope it's okay to post this here, he was a little too busy himself. Everything is pretty much the way I've inserted it - I'll edit the dialogue later, but other than that, the offsets and everything should match the way I've been inserting these.

Spoiler:
"Mrs. Nature" XSE script:
Spoiler:
Code:
#dynamic 0x3B1B44

#define VAR_FLOWER_TO_WATER 0x40A9
#define VAR_FLOWER_TO_THIN 0x40AB
#define VAR_NATURE 0x40B0
#define VAR_FORTUNE_PEDOMETER 0x40B1

#org @start
lock
textcolor 0x1
msgbox @string1 MSG_KEEPOPEN
showmoney 0x0 0x0 0x0
msgbox @string2 MSG_YESNO
compare LASTRESULT 0x1
if 0x1 goto @snippet1
msgbox @string3 MSG_NORMAL
hidemoney 0x0 0x0
release
end

#org @snippet1
checkmoney 0x2710 0x0
compare LASTRESULT 0x1
if 0x5 goto @snippet2
hidemoney 0x0 0x0
msgbox @string4 MSG_KEEPOPEN
preparemsg @string5
multichoice 0x0 0x0 0x1E 0x1
copyvar 0x8004 LASTRESULT
compare 0x8004 0x0
if 0x1 goto @snippet3
compare 0x8004 0x1
if 0x1 goto @snippet4
compare 0x8004 0x2
if 0x1 goto @snippet5
compare 0x8004 0x3
if 0x1 goto @snippet6
compare 0x8004 0x4
if 0x1 goto @snippet7
goto @snippet8

#org @snippet2
msgbox @string6 MSG_NORMAL
hidemoney 0x0 0x0
release
end

#org @snippet3
setvar VAR_FLOWER_TO_WATER 0x1
goto @snippet9

#org @snippet4
setvar VAR_FLOWER_TO_WATER 0x2
goto @snippet9

#org @snippet5
setvar VAR_FLOWER_TO_WATER 0x3
goto @snippet9

#org @snippet6
setvar VAR_FLOWER_TO_WATER 0x4
goto @snippet9

#org @snippet7
setvar VAR_FLOWER_TO_WATER 0x5
goto @snippet9

#org @snippet8
msgbox @string7 MSG_NORMAL
release
end

#org @snippet9
msgbox @string8 MSG_KEEPOPEN
preparemsg @string9
multichoice 0x0 0x0 0x1E 0x1
copyvar 0x8004 LASTRESULT
compare 0x8004 0x0
if 0x1 goto @snippet10
compare 0x8004 0x1
if 0x1 goto @snippet11
compare 0x8004 0x2
if 0x1 goto @snippet12
compare 0x8004 0x3
if 0x1 goto @snippet13
compare 0x8004 0x4
if 0x1 goto @snippet14
goto @snippet8

#org @snippet10
setvar VAR_FLOWER_TO_THIN 0x1
goto @snippet15

#org @snippet11
setvar VAR_FLOWER_TO_THIN 0x2
goto @snippet15

#org @snippet12
setvar VAR_FLOWER_TO_THIN 0x3
goto @snippet15

#org @snippet13
setvar VAR_FLOWER_TO_THIN 0x4
goto @snippet15

#org @snippet14
setvar VAR_FLOWER_TO_THIN 0x5
goto @snippet15

#org @snippet15
msgbox @string10 MSG_NORMAL
spriteface 0x1 0x2
pause 0x10
msgbox @string11 MSG_NORMAL
pause 0x10
spriteface 0x1 0x1
msgbox @string12 MSG_KEEPOPEN
sound 0x15
applymovement 0x1 @move1
waitmovement 0x0
checksound
call @snippet16
msgbox @string13 MSG_KEEPOPEN
pause 0x30
closeonkeypress
showmoney 0x0 0x0 0x0
msgbox @string14 MSG_KEEPOPEN
sound 0xF8
paymoney 0x2710 0x0
updatemoney 0x0 0x0 0x0
checksound
closeonkeypress
setvar VAR_FORTUNE_PEDOMETER 0x0
hidemoney 0x0 0x0
release
end

#org @snippet16
compare VAR_FLOWER_TO_WATER 0x1
if 0x1 goto @snippet17
compare VAR_FLOWER_TO_WATER 0x2
if 0x1 goto @snippet18
compare VAR_FLOWER_TO_WATER 0x3
if 0x1 goto @snippet19
compare VAR_FLOWER_TO_WATER 0x4
if 0x1 goto @snippet20
goto @snippet21

#org @snippet17
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet22
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet23
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet24
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet25
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet26
return

#org @snippet18
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet27
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet28
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet29
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet30
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet31
return

#org @snippet19
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet32
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet33
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet34
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet35
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet36
return

#org @snippet20
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet37
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet38
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet39
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet40
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet41
return

#org @snippet21
compare VAR_FLOWER_TO_THIN 0x1
if 0x1 call @snippet42
compare VAR_FLOWER_TO_THIN 0x2
if 0x1 call @snippet43
compare VAR_FLOWER_TO_THIN 0x3
if 0x1 call @snippet44
compare VAR_FLOWER_TO_THIN 0x4
if 0x1 call @snippet45
compare VAR_FLOWER_TO_THIN 0x5
if 0x1 call @snippet46
return

#org @snippet22
setvar VAR_NATURE 0x1
bufferstring 0x0 @string15
return

#org @snippet23
setvar VAR_NATURE 0x2
bufferstring 0x0 @string16
return

#org @snippet24
setvar VAR_NATURE 0x4
bufferstring 0x0 @string17
return

#org @snippet25
setvar VAR_NATURE 0x5
bufferstring 0x0 @string18
return

#org @snippet26
setvar VAR_NATURE 0x3
bufferstring 0x0 @string19
return

#org @snippet27
setvar VAR_NATURE 0x6
bufferstring 0x0 @string20
return

#org @snippet28
setvar VAR_NATURE 0x7
bufferstring 0x0 @string21
return

#org @snippet29
setvar VAR_NATURE 0x9
bufferstring 0x0 @string22
return

#org @snippet30
setvar VAR_NATURE 0xA
bufferstring 0x0 @string23
return

#org @snippet31
setvar VAR_NATURE 0x8
bufferstring 0x0 @string24
return

#org @snippet32
setvar VAR_NATURE 0x10
bufferstring 0x0 @string25
return

#org @snippet33
setvar VAR_NATURE 0x11
bufferstring 0x0 @string26
return

#org @snippet34
setvar VAR_NATURE 0x13
bufferstring 0x0 @string27
return

#org @snippet35
setvar VAR_NATURE 0x14
bufferstring 0x0 @string28
return

#org @snippet36
setvar VAR_NATURE 0x12
bufferstring 0x0 @string29
return

#org @snippet37
setvar VAR_NATURE 0x15
bufferstring 0x0 @string30
return

#org @snippet38
setvar VAR_NATURE 0x16
bufferstring 0x0 @string31
return

#org @snippet39
setvar VAR_NATURE 0x18
bufferstring 0x0 @string32
return

#org @snippet40
setvar VAR_NATURE 0x19
bufferstring 0x0 @string33
return

#org @snippet41
setvar VAR_NATURE 0x17
bufferstring 0x0 @string34
return

#org @snippet42
setvar VAR_NATURE 0xB
bufferstring 0x0 @string35
return

#org @snippet43
setvar VAR_NATURE 0xC
bufferstring 0x0 @string36
return

#org @snippet44
setvar VAR_NATURE 0xE
bufferstring 0x0 @string37
return

#org @snippet45
setvar VAR_NATURE 0xF
bufferstring 0x0 @string38
return

#org @snippet46
setvar VAR_NATURE 0xD
bufferstring 0x0 @string39
return

#org @string1
= Hmm[.]\p[.]\pAha!\nYes!\pShall I foresee the Nature of\nthose allies you have yet to meet?

#org @string2
= I'll charge you just [$]10,000.\nWouldn't you like to know?

#org @string3
= Hmm[.]\nYes, perhaps it's best[.]

#org @string4
= Well then, let me ask you a few\nquestions.

#org @string5
= [red_fr]There are five flowers before you.\nWhich do you water?

#org @string6
= You don't have enough money!\nSomething so powerful isn't free!

#org @string7
= Hm[.] Well, return when you change\nyour mind.

#org @string8
= Heh.\nI see, I see[.]

#org @string9
= [red_fr]Now, among the flowers I mentioned,\nwhich would you thin, if needed?

#org @string10
= Understood[.]\nNow I will look into your future.

#org @string11
= [.] [.] [.] [.]\n[.] [.] [.] [.]\p[.] [.] [.] [.]\n[.] [.] [.] [.]\p[.] [.] [.] [.]\n[.] [.] [.] [.]\pAha!

#org @string12
= Fate is guiding your path.\pThe encounters you will have are\nlikely to have[.]

#org @string13
= Yes!\nA[buffer1][red_fr] Nature!

#org @string14
= I will accept your payment now.\nThank you!

#org @string15
=  [green_fr]Hardy

#org @string16
=  [green_fr]Lonely

#org @string17
= n [green_fr]Adamant

#org @string18
=  [green_fr]Naughty

#org @string19
=  [green_fr]Brave

#org @string20
=  [green_fr]Bold

#org @string21
=  [green_fr]Docile

#org @string22
= n [green_fr]Impish

#org @string23
=  [green_fr]Lax

#org @string24
=  [green_fr]Relaxed

#org @string25
=  [green_fr]Modest

#org @string26
=  [green_fr]Mild

#org @string27
=  [green_fr]Bashful

#org @string28
=  [green_fr]Rash

#org @string29
=  [green_fr]Quiet

#org @string30
=  [green_fr]Calm

#org @string31
=  [green_fr]Gentle

#org @string32
=  [green_fr]Careful

#org @string33
=  [green_fr]Quirky

#org @string34
=  [green_fr]Sassy

#org @string35
=  [green_fr]Timid

#org @string36
=  [green_fr]Hasty

#org @string37
=  [green_fr]Jolly

#org @string38
=  [green_fr]Naive

#org @string39
=  [green_fr]Serious

#org @move1
#raw 0x62
#raw 0xFE


Nature manipulation ASM routine:
Spoiler:
Code:
.thumb

.equ free, 0x34F050
.equ VAR_NATURE, 0x40B0
.equ ABILITY_SYNCHRONIZE, 0x1C

.equ rom, 0x08000000

.org 0x3DDA4, 0xFF
    ldr r0, =(rom + main + 1)
    bx r0
.pool

.org free, 0xFF
main:
	ldr r0, [sp, #0x2C]
	lsl r0, r0, #0x18
	lsr r5, r0, #0x18
	lsl r1, r1, #0x10
	lsr r1, r1, #0x10
	mov r8, r1
	lsl r2, r2, #0x18
	lsr r7, r2, #0x18
	lsl r3, r3, #0x18
	lsr r6, r3, #0x18
fortune_check:
    push {r5}
    ldr r0, =(VAR_NATURE)
    bl var_load
    lsl r0, r0, #0x18
    lsr r5, r0, #0x18
fortune:
    cmp r5, #0
    beq skip_fortune
    cmp r5, #24
    bhi skip_fortune
    sub r0, r5, #1
    pop {r5}
    mov r5, r0
    b end
skip_fortune:  
    pop {r5}  
	bl rand
	lsl r0, r0, #0x18
	lsr r0, r0, #0x18
	cmp r0, #0
	bls end
synccheck:
	ldr r0, party_player
	mov r1, #0x2E
	mov r2, #0x0
	bl getattr
	mov r4, r0
	ldr r0, party_player
	mov r1, #0xB
	mov r2, #0x0
	bl getattr
	ldr r2, base_stats
	ldr r2, [r2]
	mov r1, #0x1C
	mul r0, r1
	add r2, r0, r2
	cmp r4, #0x0
	beq ability0
ability1:
	ldrb r1, [r2, #0x17]
	b checkability
	
ability0:
	ldrb r1, [r2, #0x16]
checkability:
	cmp r1, #ABILITY_SYNCHRONIZE
	bne end
copynature:
	ldr r0, party_player
	mov r1, #0x0
	mov r2, #0x0
	bl getattr
	bl getnature
	lsl r0, r0, #0x18
	lsr r5, r0, #0x18
end:
	ldr r0, return
	bx r0
	
rand:
	ldr r3, =(0x08044EC8|1)
	bx r3
	
getattr:
	ldr r3, =(0x0803FBE8|1)
	bx r3
	
getnature:
	ldr r3, =(0x08042EB4|1)
	bx r3

var_load:
	ldr r1, =(0x0806E568|1)
	bx r1
	
	
.align 2
.pool
	base_stats:	.word 0x080001BC
	return:	.word 0x0803DDB8|1
	party_player:	.word 0x02024284


"Fortune wore off" XSE script:
Spoiler:
Code:
#dynamic 0x3ADDD4

#org @start
msgbox @string1 MSG_SIGN
end

#org @string1
= It seems as if the fortune\nforetold has worn off[.]


Pedometer ASM routine: (This is the one that's giving me trouble, when I try to convert it to a .bin file)
Spoiler:
Code:
.thumb

.equ free, 0x3ADE14
.equ VAR_FORTUNE_PEDOMETER, 0x40B1
.equ STEPS_TO_RESET_PEDOMETER, 2999
.equ scr_fortune_wore_off, 0x3ADDD4
.equ rom, 0x08000000

.org 0x3DDA4, 0xFF
    ldr r0, =(rom + main + 1)
    bx r0
.pool

.org free, 0xFF
main:
    push {r4-r6,lr}
    bl fortune_teller_pedometer

end:
    pop {r4-r6}
    pop {r2}

call_via_r2:
    bx r2

fortune_teller_pedometer:
    push {lr}    
    ldr r0, fortune_teller_nature
    ldr r2, =(0x0806E568|1)
    bl call_via_r2
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    cmp r0, #0
    beq fortune_teller_return
    ldr r4, =(VAR_FORTUNE_PEDOMETER)
    ldr r5, =(STEPS_TO_RESET_PEDOMETER)
    mov r0, r4
    ldr r2, =(0x0806E568|1)
    bl call_via_r2
    lsl r0, r0, #0x10
    lsr r1, r0, #0x10
    ldr r2, =(0x0806E584|1)
    cmp r1, r5
    bhi fortune_teller_pedometer_at_max
    
fortune_teller_increment:
    add r1, #1
    lsl r1, r1, #0x10
    lsr r1, r1, #0x10
    mov r0, r4
    bl call_via_r2
    b fortune_teller_return

fortune_teller_pedometer_at_max:
    ldr r0, =VAR_FORTUNE
    mov r1, #0
    ldr r2, =(0x0806E584|1)
    bl call_via_r2
    ldr r0, =(0x083ADDD4|1)
    ldr r2, =(0x08069AE4|1)
    bl call_via_r2
    
fortune_teller_return:
    pop {pc}

.pool
__________________
Check out my ROM Hacks:

Fakemon FireRed: the Wiki and the ROM Hacks Studio post (Finished and playable!)

Pekin's Ruby Hack: the Wiki (My first hack - not nearly as well made or polished as Fakemon FireRed)
Reply With Quote
  #1496   Link to this post, but load the entire thread.  
Old May 16th, 2020 (9:26 AM). Edited May 17th, 2020 by Team Embrace.
Team Embrace's Avatar
Team Embrace Team Embrace is offline
Team Embrace Boss
 
Join Date: Jan 2019
Gender: Male
Nature: Jolly
Posts: 30
Hey everybody. First I would like to thank Andrea for successfully porting the physical/special split to Pokémon Ruby. Can someone take his ASM routine and update it to work with an expanded move table?
Spoiler:
.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x081FB12C
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0


In my modification the attack table starts at offset 0x900000. If more information is needed about my offsets I can provide that.
Reply With Quote
  #1497   Link to this post, but load the entire thread.  
Old May 16th, 2020 (4:00 PM).
Super Versekr Dark Super Versekr Dark is offline
 
Join Date: Jan 2017
Gender: Male
Posts: 79
Quote:
Originally Posted by Team Embrace View Post
Hey everybody. First I would like to thank Andrea for successfully porting the physical/special split to Pokémon Ruby. Can someone take his ASM routine and update it to work with an expanded move table?
Spoiler:
.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x081FB12C
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0


In my modification the attack table starts at offset 9000. If more information is needed about my offsets I can provide that.
Change this for new table.

AttackData=1FB12C
Reply With Quote
  #1498   Link to this post, but load the entire thread.  
Old May 17th, 2020 (8:41 AM).
Team Embrace's Avatar
Team Embrace Team Embrace is offline
Team Embrace Boss
 
Join Date: Jan 2019
Gender: Male
Nature: Jolly
Posts: 30
Quote:
Change this for new table.
AttackData=1FB12C
Thanks for your reply Super Dark. I think my last post wasn't clear enough I am not talking about updating an editor's tool like PGE to support the expanded move table I've already done that. What I'm asking about is how to update Andrea's ASM routine to support the expanded move table in my ROM. Although I think were on the right track I wonder if change I posted below will work or do any other numbers need to be changed?
Spoiler:

.THUMB
.ALIGN 2

LDR R1, = 0x02024BE6
LDRH R1, [R1]

MOV R0, #0xC
MUL R1, R0
LDR R0, = 0x08900000
ADD R0, R0, R1

LDRB R0, [R0, #10]

CMP R0, #0
BEQ PHYSICAL

LDR R0, = 0x0803C132+1
BX R0

PHYSICAL:
LDR R0, = 0x0803BFC4+1
BX R0
Reply With Quote
  #1499   Link to this post, but load the entire thread.  
Old May 19th, 2020 (7:56 AM).
Team Embrace's Avatar
Team Embrace Team Embrace is offline
Team Embrace Boss
 
Join Date: Jan 2019
Gender: Male
Nature: Jolly
Posts: 30
Quote:
Originally Posted by PokeChu View Post
Greetings, everybody.

Question:
Has anybody got the Rival Naming Routine by Jambo51?
I believe the post [link] has died. Any help would be appreciated, and I under stand if Jambo has prohibited from spreading it.
This isn't a request, but a favour.


Cheers.
Naming the Rival from the Overworld:
Spoiler:

The Code:

.text
.align 2
.thumb
.thumb_func
.global rivalnamingingame
main:
push {r0-r4,lr}
ldr r0, place
str r0, [sp, #0x4]
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
mov r0, #0x4
mov r2, #0x0
mov r3, #0x0
bl place2
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
ldrb r0, [r1, #0x0]
cmp r0, #0xFF
beq failsafe
cmp r0, #0x0
beq failsafe
return: pop {r0-r4}
pop {pc}
place2: ldr r4, actualroutine
bx r4
failsafe: ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
strb r2, [r1, #0x0]
cmp r2, #0xFF
beq return
add r0, #0x1
add r1, #0x1
b loop
.align
place: .word 0x080568E1
ramlocation: .word 0x03005008
standard: .word 0x00003A4C
actualroutine: .word 0x0809D955
rivalname: .word 0x08FFFFFF

Where to insert: Anywhere! This routine is called from a script in the game, and as such, doesn't need to be carefully linked into existing routines. All you need to do is remember the rule of THUMB, add 1 to the offset when calling it!

Explanation: It's what it says on the tin, it lets you name your rival from the in game overworld, allowing for Silver like naming, or indeed, any other possibility you can come up with. The rivalname: .word 0x08FFFFFF is for if the player leaves the name box blank. It will fill it with a standard name instead. This standard name is up to you to create. Simply compile a name with XSE, and point that pointer to it.

You also need to put this routine in the game, or else it won't be able to load past the intro without naming the rival. All it does is temporarily write a holding name to the rival buffer so that the game doesn't crash.

.text
.align 2
.thumb
.thumb_func
.global rivalnamingskip
main:
ldr r1, [r6, #0x0]
ldr r0, number
mov r8, r0
add r1, r8
push {r1}
ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
cmp r2, #0xFF
beq end
strb r2, [r1, #0x0]
add r0, #0x1
add r1, #0x1
b loop
end: strb r2, [r1, #0x0]
pop {r1}
mov r0, sp
ldr r3, return
bx r3
.align
number: .word 0x00003A4C
rivalname: .word 0x08FFFFFF
return: .word 0x08054A75

Where to insert: Navigate to 0x54A6A, and change the following bytes to this:
01 49 08 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: It simply writes a placeholder name into the [rival] buffer so the game doesn't crash. Obviously, you shouldn't be using the [rival] buffer until the player has named the rival, so it shouldn't be a problem.

To make this work, navigate to 0x103690, and change the pointer there to 0x1307D1.


OG post by tajaros
Reply With Quote
  #1500   Link to this post, but load the entire thread.  
Old May 19th, 2020 (11:34 AM).
Pyxal's Avatar
Pyxal Pyxal is offline
It's pronounced pixel.
 
Join Date: Jul 2019
Location: Pakistan
Age: 17
Posts: 987
Quote:
Originally Posted by Team Embrace View Post
Naming the Rival from the Overworld:
Spoiler:

The Code:

.text
.align 2
.thumb
.thumb_func
.global rivalnamingingame
main:
push {r0-r4,lr}
ldr r0, place
str r0, [sp, #0x4]
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
mov r0, #0x4
mov r2, #0x0
mov r3, #0x0
bl place2
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
ldrb r0, [r1, #0x0]
cmp r0, #0xFF
beq failsafe
cmp r0, #0x0
beq failsafe
return: pop {r0-r4}
pop {pc}
place2: ldr r4, actualroutine
bx r4
failsafe: ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
strb r2, [r1, #0x0]
cmp r2, #0xFF
beq return
add r0, #0x1
add r1, #0x1
b loop
.align
place: .word 0x080568E1
ramlocation: .word 0x03005008
standard: .word 0x00003A4C
actualroutine: .word 0x0809D955
rivalname: .word 0x08FFFFFF

Where to insert: Anywhere! This routine is called from a script in the game, and as such, doesn't need to be carefully linked into existing routines. All you need to do is remember the rule of THUMB, add 1 to the offset when calling it!

Explanation: It's what it says on the tin, it lets you name your rival from the in game overworld, allowing for Silver like naming, or indeed, any other possibility you can come up with. The rivalname: .word 0x08FFFFFF is for if the player leaves the name box blank. It will fill it with a standard name instead. This standard name is up to you to create. Simply compile a name with XSE, and point that pointer to it.

You also need to put this routine in the game, or else it won't be able to load past the intro without naming the rival. All it does is temporarily write a holding name to the rival buffer so that the game doesn't crash.

.text
.align 2
.thumb
.thumb_func
.global rivalnamingskip
main:
ldr r1, [r6, #0x0]
ldr r0, number
mov r8, r0
add r1, r8
push {r1}
ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
cmp r2, #0xFF
beq end
strb r2, [r1, #0x0]
add r0, #0x1
add r1, #0x1
b loop
end: strb r2, [r1, #0x0]
pop {r1}
mov r0, sp
ldr r3, return
bx r3
.align
number: .word 0x00003A4C
rivalname: .word 0x08FFFFFF
return: .word 0x08054A75

Where to insert: Navigate to 0x54A6A, and change the following bytes to this:
01 49 08 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: It simply writes a placeholder name into the [rival] buffer so the game doesn't crash. Obviously, you shouldn't be using the [rival] buffer until the player has named the rival, so it shouldn't be a problem.

To make this work, navigate to 0x103690, and change the pointer there to 0x1307D1.


OG post by tajaros
I am so sorry! I had found this routine and forgot to mention it here. Terribly sorry.
__________________
Reply With Quote
Reply

Quick Reply

Join the conversation!

Create an account to post a reply in this thread, participate in other discussions, and more!

Create a PokéCommunity Account
Ad Content
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -8. The time now is 8:46 AM.