PDA

View Full Version : Development: Day/Night Switching of Wild Pokémon


Jambo51
December 2nd, 2010, 2:58 PM
I would like to note that the general framework for these hacks were based on an idea that a Brazilian hacker had, his name escapes me right now, but some credit must be given to him/her!

These routines DO NOT support the new RTC and Day and Night Feature developed by Prime unless you use the same RAM offsets. Even if you do, I would ideally like to redevelop these routines to use the new system Prime has developed as it would be more efficient.

FireRed (Extensively Tested)

First up is the routine which will make the wild Pokémon's level load correctly, rather than loading random garbage data after the repointing process is complete.

Wild Pokémon Day/Night Level Loading Routine


.text /*Basic THUMB Headers, should be included in all ASM Routines*/
.align 2
.thumb
.thumb_func
.global daynightlevelswitch

main:
sub r0, r0, r4 /*Subtracts the value of R4 from R0, giving us a clean pointer to use*/
ldr r2, hour /*Loads the ram offset 0x03005542 to R2*/
ldrb r2, [r2, #0x0] /*Loads the byte contained in the offset*/
cmp r2, #0x15 /*Compares R2 (The Hour) with 0x15 - 9PM - Change it if you want*/
bge night /*If greater than or equal to, go to "night"*/
cmp r2, #0x12
bge evening
cmp r2, #0x9 /*Compares R2 (The Hour) with 0x9 - 9AM - Change it if you want*/
bge day /*If greater than or equal to, go to "day"*/
cmp r2, #0x6
bge morning
night: add r2, r0, #0x4
b check
evening: add r2, r0, #0x0
add r2, #0xC
b check
morning: add r2, r0, #0x0
add r2, #0x8
b check
day: add r2, r0, #0x0
check: ldrb r1, [r2, #0x3] /*Loads the byte stored at the pointer's location plus 3 for checking*/
cmp r1, #0xFF
beq nodata
cmp r1, #0x8 /*Compares R2 with 0x08, the tell tale sign of a rom pointer, which is what should be stored here if you are using this hack*/
bne nextnormal /*If not equal, load as usual - Thanks Shiny Quagsire!*/
ldr r0, [r2, #0x0] /*Loads the word stored at the location pointed to in R2, the pointer to the wild data*/
nextnormal: add r0, r4, r0 /*Adds the number of bytes from the start of the table that the wild Pokémon slot the game has selected is*/
add r4, r0, #0x0 /*Adds the contents of R0 into R4*/
ldrb r0, [r4, #0x1] /*Loads the upper level limit for the Pokémon if they're stored systematically*/
ldrb r1, [r4, #0x0] /*Loads the lower level limit*/
cmp r0, r1 /*Compares the levels*/
bcc here /*If R0 < R1 goto "here"*/
ldrb r5, [r4, #0x0] /*Loads the lower level limit into R5*/
b here2
here: ldrb r5, [r4, #0x1] /*Reverses the lower and upper level limits to*/
ldrb r0, [r4, #0x0] /*avoid bugs if R0 was smaller than R1 above*/
here2: sub r4, r0, r5 /*Subtracts upper and lower level limits and stores results into R4*/
add r4, #0x1 /*Not entirely sure why, but it's from the original code, and is important for level loading, as leaving it out leads to odd bugs*/
lsl r4, r4, #0x18 /*This line and the next line make sure that you are only passing a byte to the next part of the routine, so it doesn't bug out*/
lsr r4, r4, #0x18
ldr r2, return /*Loads the return offset to R2*/
bx r2 /*Executes a Branch and Exchange goto to the offset contained within the register, ensuring it remains in THUMB mode by being 1 greater than the wanted location*/
var_decrypt: ldr r1, vardecrypt
bx r1
nodata: sub r2, r2, r0
cmp r2, #0xC
beq night
b day
.align
hour: .word 0x03005542
return: .word 0x08082915
vardecrypt: .word 0x0806E455
var_4fff: .word 0x00004FFF /*Replace this with whatever variable you would like to use*/



So, insert the code below at 0x080828FA where the XXXXXX is replaced with the reverse hex pointer plus one of the newly inserted code.

01 4A 10 47 00 00 XX XX XX 08

This sorts the level loading part of the routine, but we haven't actually modified the Pokémon loading part of it yet. So, now we have to insert another routine to actually make that work.


.text
.align 2
.thumb
.thumb_func
.global daynightwildswitch
main:
ldr r0, [r7, #0x4]
push {r0}
ldr r0, var_4fff
bl var_decrypt
ldrh r0, [r0, #0x0]
cmp r0, #0x1
bge swarm
pop {r0}
push {r2}
daynight: ldr r2, hour
ldrb r2, [r2, #0x0]
cmp r2, #0x15 /*9PM - Change it if you want*/
bge night
cmp r2, #0x12
bge evening
cmp r2, #0x9 /*9AM - Change it if you want*/
bge day
cmp r2, #0x6
bge morning
night: add r2, r0, #0x4
b check
evening: add r2, r0, #0x0
add r2, #0xC
b check
morning: add r2, r0, #0x0
add r2, #0x8
b check
day: add r2, r0, #0x0
check: ldrb r1, [r2, #0x3]
cmp r1, #0xFF
beq nodata
cmp r1, #0x8
bne nextnormal
ldr r0, [r2, #0x0]
nextnormal: add r0, r4, r0
ldrh r0, [r0, #0x2]
back: ldr r1, lastpokemon
strh r0, [r1, #0x0]
add r1, r5, #0x0
pop {r2}
ldr r3, Back
bx r3
swarm: pop {r0}
ldr r0, var_4ffe
bl var_decrypt
sub r2, r0, #0x2
ldr r1, currentmap
ldrb r1, [r1, #0x0]
ldrh r2, [r2, #0x0]
cmp r1, r2
bne daynightone
ldrh r0, [r0, #0x0]
b back
var_decrypt: ldr r1, vardecrypt
bx r1
daynightone: ldr r0, [r7, #0x4]
push {r0}
b daynight
nodata: sub r2, r2, r0
cmp r2, #0xC
beq night
b day
.align
Back: .word 0x08082b51
lastpokemon: .word 0x0300555C
hour: .word 0x03005542
vardecrypt: .word 0x0806E455
var_4fff: .word 0x00004FFF /*Replace this with whatever variable you would like to use*/
var_4ffe: .word 0x00004FFE /*Replace this with whatever variable you would like to use*/
currentmap: .word 0x03005558



This routine performs a similar function to the level modification part from above. Changing the pointer to the wild data into a pointer to a table of pointers to wild data.

Insert the assembled routine and then modify the data at 0x08082B48 so that it repoints to the new routine's location plus 1:
00490847XXXXXX08

For the swarming code, you need to set the variable 0x4FFF to 0x2 or greater, and then set the variable 0x4FFE with the Pokémon number you want to be swarming.
eg. I want Taillow to swarm on Route 4:

setvar 0x4FFF 0x2
setvar 0x4FFE PKMN_TAILLOW
setvar 0x4FFD 0x68

The way the code works is that it always overwrites the standard Pokémon loading routine for the given map until you change one of the above parameters. How you do this is entirely up to you.

These 2 routines together allow you to have different pokémon at day and night, but read in more or less exactly the same way as before, meaning you can rely on it to produce common Pokémon more often than rare ones in the same way as any modified data in A-Map.

There is another, entirely optional, hack related to this, which is having different wild Pokémon encounter rates between day and night. This hack also reads the ability byte of your first Pokémon, looking for specific conditions to be met. If your lead Pokémon has certain abilities (the list isn't yet complete, and some of the effects still need some research) then the wild encounter rate can be halved or doubled. For all of the abilities listed below, they only apply if the Pokémon with the ability is in slot 1. Otherwise, it'll work as per usual.

Current list of supported abilities:
Arena Trap (Doubles)
Illuminate (Doubles)
Sand Veil (Halves in Sandstorm)
Stench (Halves)
Swarm (Doubles)
White Smoke (Halves)


Anyhoo, the game reads the encounter rate like so:
This is for Route 1, but all encounter rates are stored in the same style:
DD 00 00 00
But it only reads the first byte of this. What a waste of space! So, I figured we could use this space to store upto an extra 3 encounter rates, making a total of 4 for every map! (Remember, the maximum encounter rate is 255 or 0xFF, meaning that even with all of them set to maximum, it will fit in here snugly. :D

This code makes the bytes following the normal encounter rate become encounter rates too, separate from the normal one, and only read when the hour byte is above or below a certain value.



.text
.align 2
.thumb
.thumb_func
.global daynightencounterratehack
main:
push {r0}
ldr r0, hour
ldrb r0, [r0, #0x0]
cmp r0, #0x15 /*9PM - Change it if you want*/
bge night
cmp r0, #0x12
bge evening
cmp r0, #0x9 /*9AM - Change it if you want*/
bge day
cmp r0, #0x6
bge morning
night: pop {r0}
ldrb r1, [r0, #0x3]
b check
evening: pop {r0}
ldrb r1, [r0, #0x2]
b check
morning: pop {r0}
ldrb r1, [r0, #0x1]
check: cmp r1, #0x0
beq day2
b new
day: pop {r0}
day2: ldrb r1, [r0, #0x0]
new: push {r0-r7}
ldr r0, partystart /*Everything from here until the next comment is HackMew's code*/
mov r5, #0x6
add r0, r4, #0x0
mov r1, #0x8
ldr r3, readdata
bl bxr3
add r6, r0, #0x0
add r0, r4, #0x0
mov r1, #0x2E
ldr r3, readdata
bl bxr3
add r1, r0, #0x0
add r0, r6, #0x0
ldr r3, getability
bl bxr3 /*End of HackMew's code*/
cmp r0, #0x1
beq divide
cmp r0, #0x8
beq sandveil
cmp r0, #0x38
beq double
cmp r0, #0x44
beq double
cmp r0, #0x47
beq double
cmp r0, #0x49
beq divide
pop {r0-r7}
return: cmp r1, #0x4F
bhi one
cmp r1, #0x9
bls two
add r0, r1, #0x0
ldr r1, place
bx r1
divide: pop {r0-r7}
push {r0}
push {r1}
push {r2}
add r0, r1, #0x0
mov r1, #0x2
mov r2, #0x0
swi #0x6
pop {r2}
pop {r1}
add r1, r0, #0x0
pop {r0}
b return
double: pop {r0-r7}
push {r2}
mov r2, #0x2
mul r1, r2
pop {r2}
b return
bxr3: bx r3 /*This one line of code is also HackMew's, but it somehow ended up down here*/
two: mov r0, #0x8
b Back
one: mov r0, #0x0
Back: ldr r4, placetwo
bx r4
sandveil: ldr r0, weatherlocation
ldrb r0, [r0, #0x0]
cmp r0, #0x8
bne no
b divide
no: pop {r0-r7}
b return
.align
placetwo: .word 0x080832CF
weatherlocation: .word 0x03005564
hour: .word 0x03005542
partystart: .word 0x02024284
readdata: .word 0x0803FBE9
getability: .word 0x08040D39
place: .word 0x080832BB



Insert the following hex string at 0x08083278:
00 49 08 47 XX XX XX 08

Where one again, the XXXXXX is the reverse hex pointer to the new routine's location.

So, it marks them out like so for the 4 time set up I have created.
DD MM EE NN
I left the day encounter rate at the start in order to have the routine be as compatible with the original rom's data as possible.

Anyway, the code reads this byte, then runs some simple checks (credit for that particular part of the code goes to HackMew as it is taken almost wholesale from his Flame Body hack, which I suggest you all try out!), and based on the results of these checks, either halves, doubles, or continues with the given encounter rate. It then returns to the original routine for writing to memory.

OK, now a quick lesson on how to get the tables set up right.
Again, for a benchmark I'll use Route 1's data, but it can be expanded to every single wild data table in the game.

This is the Route 1 grass wild data as standard in the rom:

15 00 00 00 60 8E 3C 08


In order for the game to read this properly with the new routines, you need to repoint the pointer to a free space location in the rom. A good location for this would be 0x08B00000 as it's empty and has more than enough free space to hold the new data.

So, at 0xB00000, copy and paste the pointer to the original wild data. This will serve as our daytime data. Then after it, place another pointer to an empty area of the rom. Anywhere will do, as long as you have enough free space to put the correct number of wild Pokémon in. That will make it work, although you should obviously fill the new table with Pokémon data. This new table serves as our night time data. So, now whenever we encounter a wild Pokémon at night, it'll be loaded from the night time data, rather than the day time data.

Here is one final, separate routine which writes the map you are currently in and the weather on said map to a ram offset so that the routines above can use them to determine whether certain conditional modifications should be activated. (This is because I couldn't find either written to the ram although they are obviously written to the ram at some point by the actual routine).

.text
.align 2
.thumb
.thumb_func
.global headerreadinghack
main:
stmia r1!, {r2, r3, r6}
ldr r0, [r0, #0x0]
push {r5}
push {r6}
lsl r6, r6, #0x8
lsr r6, r6, #0x18
ldr r5, currentmaploc
strb r6, [r5, #0xC]
pop {r6}
push {r6}
lsl r6, r6, #0x18
lsr r6, r6, #0x18
strb r6, [r5, #0x0]
pop {r6}
pop {r5}
mov r7, #0x4
str r0, [r1, #0x0]
ldr r1, [r5, #0x0]
ldrh r0, [r4, #0x12]
strh r0, [r1, #0x32]
ldr r0, returntooriginal
bx r0
.align
currentmaploc: .word 0x03005558
returntooriginal: .word 0x080552A7



Insert the following code at 0x0805529A:
01 4F 38 47 00 00 XX XX XX 08



Emerald (Basic Testing)


Level Loading Routine:
.text
.align 2
.thumb
.thumb_func
.global daynightlevelswitch

main:
ldr r2, hour
ldrb r2, [r2, #0x0]
cmp r2, #0x21
bge night
cmp r2, #0x18
bge even
cmp r2, #0x9
bge day
cmp r2, #0x6
bge morn
night: add r2, r0, #0x4
b check
even: add r2, r0, #0x0
add r2, #0xC
b check
morn: add r2, r0, #0x0
add r2, #0x8
b check
day: add r2, r0, #0x0
check: ldrb r1, [r2, #0x3]
cmp r1, #0xFF
beq nodata
cmp r1, #0x8
bne nextnormal
ldr r0, [r2, #0x0]
nextnormal: add r4, r0, r4
ldrb r0, [r4, #0x1]
ldrb r1, [r4, #0x0]
cmp r0, r1
bcc here
ldrb r7, [r4, #0x0]
add r6, r0, #0x0
b here2
here: ldrb r7, [r4, #0x1]
ldrb r6, [r4, #0x0]
here2: sub r4, r6, r7
add r4, #0x1
lsl r4, r4, #0x18
lsr r4, r4, #0x18
ldr r2, return
bx r2
nodata: sub r2, r2, r0
cmp r2, #0xC
beq night
b day
night2: add r2, r0, #0x4
b check
timeupdate: ldr r1, time
bx r1
.align
hour: .word 0x03000DC4
return: .word 0x080B4C93
time: .word 0x0802F589


Insert at 0x080B4C76:
01 4A 10 47 00 00 XX XX XX XX

Pokémon Loading Routine
.text
.align 2
.thumb
.thumb_func
.global daynightwildswitch
main:
pop {r0}
ldrb r0, [r0, #0x0]
push {r3,r4}
lsl r4, r0, #0x2
ldr r0, [r5, #0x4]
daynight: ldr r1, hour
ldrb r1, [r1, #0x0]
cmp r1, #0x21
bge night
cmp r1, #0x18
bge evening
cmp r1, #0x9
bge day
cmp r1, #0x6
bge morning
night: add r1, r0, #0x4
b check
evening: add r1, r0, #0x0
add r2, #0xC
b check
day: add r1, r0, #0x0
b check
morning: add r1, r0, #0x0
add r2, #0x8
check: ldrb r3, [r1, #0x3]
cmp r3, #0xFF
beq nodata
cmp r3, #0x8
bne nextnormal
ldr r0, [r1, #0x0]
nextnormal: add r0, r0, r4
ldrh r0, [r0, #0x2]
pop {r3,r4}
add r1, r4, #0x0
ldr r6, Back
bx r6
nodata: sub r2, r2, r0
cmp r2, #0xC
beq night
b day
.align
Back: .word 0x080B5015
hour: .word 0x03000DC4


Overwrite the code at 0x080B500A onwards with the following:
01 B4 00 48 00 47 XX XX XX XX

In order for this to work properly, you need to update the RTC's time appropriately. But how to do this when Emerald only calls the time update routine when warping or connecting? Use the code shown in this post: http://www.pokecommunity.com/showpost.php?p=6395043&postcount=41. If you use that code and patch the time update routine onto the main loop of the game, the time updates once every frame! This means it works more like interdpth's RTC code for FireRed. A much better solution IMHO.

Ruby (Not Started Yet)

Shiny Quagsire
December 3rd, 2010, 10:21 PM
Nice job! I haven't read it through completely, but I will after I get some rest. :p

One thing you could do is explain what each original routine does, what arguments are loaded through the registers, and how the routine modifies this.

aSeRo141414
December 4th, 2010, 4:11 PM
nice! this looks nice, keep it up and I see some of it is from HackMew

Elite Trainer Red
December 6th, 2010, 11:54 AM
:D I've been working on the tool so far got the GUI down got most of the code but running into a few bugs will post it here and the tool section when i've finished doing it ;) preview attatched as an attatchment

Shiny Quagsire
December 6th, 2010, 2:41 PM
I could help with the tool. But some advice from me is:

1. Make the window smaller, or items bigger. There is too much empty space
2. More options, if possible and simpler user interface. Instead of making them insert hex, make the program convert it to hex.
3.Why make a program? If you do that, then D/N Pokemon will be less common.

adrift
December 6th, 2010, 5:16 PM
3.Why make a program? If you do that, then D/N Pokemon will be less common.
I believe you mean more common, not less common.

Plus, this routine is very useful. I have been looking into information on this for quite some time now, to no avail. Thanks!

Shiny Quagsire
December 6th, 2010, 7:13 PM
Yeah, I meant that. Anyways, I improved the code so that it is backward compatible with original game data. At the beginning, add this before pushing r0:

mov r1, r0
ldrb r1, [r1, #0x3]
cmp r1, #0x8
bne normal

//Add the following lines after back:
normal:
add r0, r4, r0
ldrh r0, [r0, #0x2]
ldr r3, Back
bx r3


What this does is it checks for an 08 3 bytes after r0, which would be where your day pointer is. If not, it uses the pokemon table as normal data, like the game normally would. The byte that is actually checked is the flipped byte of the pokemon's species. Luckily, no pokemon goes over the number 2,048, so the check works. Another check you could add is to, instead of loading another pokemon data table, check the byte loaded into r0 after this instruction:

ldrh r0, [r0, #0x2]

This loads the pokemon's data, and once loaded, it can be checked. So let's say we wanted a pidgey to turn into a hoothoot. You could add this to next:

next:
ldr r0, [r0, #0x0]
add r0, r4, r0
ldrh r0, [r0, #0x2]
ldr r3, hour
ldrb r3, [r0, #0x0]
cmp r3, #0x15 /*9PM - Change it if you want*/
bge hoothoot
b back
hoothoot: cmp r0, #0x10 /*Is it pidgey?*/
bne back /*If not, return to normal*?
mov r0, #0xA3 /*Change pokemon to hoothoot*/
b back


Also, It's pretty tedious to hex edit pokemon, so I'm going to create a tool sometime. It's not too hard in fact, since it's such a simple format:

[MinLV][MaxLV][Species][Species]


edit: I've also added backward support for the levels. Simply add this before pushing r0 at the beginning:

ldrb r2, [r2, #0x3]
cmp r2, #0x8
bne nextnormal


Add nextnormal to the second line in next:


next: ldr r0, [r0, #0x0] /*Loads the word stored at the location pointed to in R0, the pointer to the wild data*/
nextnormal:add r0, r4, r0 /*Adds the number of bytes from the start of the table that the wild Pokémon slot the game has selected is*/
add r4, r0, #0x0 /*Adds the contents of R0 into R4*/
ldrb r0, [r4, #0x1] /*Loads the upper level limit for the Pokémon if they're stored systematically*/

...

This essentially does the same thing as before. It checks if the pointer exists, and if not, it treats the table data as the normal pokemon data.

Jambo51
December 7th, 2010, 8:47 AM
Yeah, I meant that. Anyways, I improved the code so that it is backward compatible with original game data. At the beginning, add this before pushing r0:

mov r1, r0
ldrb r1, [r1, #0x3]
cmp r1, #0x8
bne normal

//Add the following lines after back:
normal:
add r0, r4, r0
ldrh r0, [r0, #0x2]
ldr r3, Back
bx r3


What this does is it checks for an 08 3 bytes after r0, which would be where your day pointer is. If not, it uses the pokemon table as normal data, like the game normally would. The byte that is actually checked is the flipped byte of the pokemon's species. Luckily, no pokemon goes over the number 2,048, so the check works. Another check you could add is to, instead of loading another pokemon data table, check the byte loaded into r0 after this instruction:

ldrh r0, [r0, #0x2]

This loads the pokemon's data, and once loaded, it can be checked. So let's say we wanted a pidgey to turn into a hoothoot. You could add this to next:

next:
ldr r0, [r0, #0x0]
add r0, r4, r0
ldrh r0, [r0, #0x2]
ldr r3, hour
ldrb r3, [r0, #0x0]
cmp r3, #0x15 /*9PM - Change it if you want*/
bge hoothoot
b back
hoothoot: cmp r0, #0x10 /*Is it pidgey?*/
bne back /*If not, return to normal*?
mov r0, #0xA3 /*Change pokemon to hoothoot*/
b back


Also, It's pretty tedious to hex edit pokemon, so I'm going to create a tool sometime. It's not too hard in fact, since it's such a simple format:

[MinLV][MaxLV][Species][Species]


edit: I've also added backward support for the levels. Simply add this before pushing r0 at the beginning:

ldrb r2, [r2, #0x3]
cmp r2, #0x8
bne nextnormal


Add nextnormal to the second line in next:


next: ldr r0, [r0, #0x0] /*Loads the word stored at the location pointed to in R0, the pointer to the wild data*/
nextnormal:add r0, r4, r0 /*Adds the number of bytes from the start of the table that the wild Pokémon slot the game has selected is*/
add r4, r0, #0x0 /*Adds the contents of R0 into R4*/
ldrb r0, [r4, #0x1] /*Loads the upper level limit for the Pokémon if they're stored systematically*/

...

This essentially does the same thing as before. It checks if the pointer exists, and if not, it treats the table data as the normal pokemon data.

Thanks man! I'll add these improvements in when I get home from work. I can't believe i didn't put these checks in myself XD. I don't pretend to br a great ASM hacker, i'm still learning most of it.

Elite Trainer Red
December 7th, 2010, 10:55 AM
^_^ I have taken the critisism (Spelling Fail) and am now working with it
will update soon

Diegoisawesome
December 7th, 2010, 4:14 PM
I would totally love this addition if it could support Emerald and have Morning added, too.
It would probably be simple to do, but I'm too lazy to do it myself ATM.

Shiny Quagsire
December 7th, 2010, 4:18 PM
I would totally love this addition if it could support Emerald and have Morning added, too.
It would probably be simple to do, but I'm too lazy to do it myself ATM.

Since emerald is based off of fire red, it was actually only a search for a few bytes. The routine is at 080b4c76 for the level routine. However, it may be loaded differently, so I'll have to check if it's safe. ;)

edit: Actually, the code from all games is exactly the same, except for when the data is written. Here are the level offsets:


Emerald: 080b4c76
Ruby: 08084d32


Unfortunatly, the wild data loading is very different. I'll have to dive a bit deeper on that one.

colcolstyles
December 7th, 2010, 4:22 PM
Since emerald is based off of fire red, it was actually only a search for a few bytes.

Mind backing that up with some evidence?

Shiny Quagsire
December 7th, 2010, 4:44 PM
Mind backing that up with some evidence?

Sure. I'm not a liar, and I always back up my evidence.

Level loading from Fire Red:

080828FA 00C MOVS R4, R0
080828FC 00C LDRB R0, [R4,#1]
080828FE 00C LDRB R1, [R4]
08082900 00C CMP R0, R1
08082902 00C BCC loc_08082908


Level Loading From Emerald:


ROM:080B4C76 MOVS R4, R0
ROM:080B4C78 LDRB R0, [R4,#1]
ROM:080B4C7A LDRB R1, [R4]
ROM:080B4C7C CMP R0, R1
ROM:080B4C7E BCC loc_80B4C86


And finally, Ruby:


ROM:08084D32 MOVS R4, R0
ROM:08084D34 LDRB R0, [R4,#1]
ROM:08084D36 LDRB R1, [R4]
ROM:08084D38 CMP R0, R1
ROM:08084D3A BCC loc_8084D40



As you can see, it's essencially the same thing. If you were to look in IDA or VBA's decompiler, you'd see the same thing, but with a few different registers here and there.

colcolstyles
December 7th, 2010, 5:56 PM
I meant provide evidence that Emerald is based off of Fire Red.

Jambo51
December 8th, 2010, 5:17 AM
I would totally love this addition if it could support Emerald and have Morning added, too.
It would probably be simple to do, but I'm too lazy to do it myself ATM.

Adding morning would be very easy. In fact I originally developed it to support 4 times of day, morning, day, evening and night, but decided to cut it down for use as it takes a lot of work to manually hex edit the Pokémon in. As for Emerald support, I guess I could have a look and see if I can apply the principle, if not necessarily the exact same routine, to the rom. Although in order for me to do that, someone would need to supply me with the ram location of the RTC in an Emerald rom, as, unlike FR, it already has an RTC built in so I can't just look at the inserted routine of the D/N routine.

I-shadez
December 8th, 2010, 6:57 AM
another tutorial thats helped alot, thanks OP

Shiny Quagsire
December 8th, 2010, 3:35 PM
Adding morning would be very easy. In fact I originally developed it to support 4 times of day, morning, day, evening and night, but decided to cut it down for use as it takes a lot of work to manually hex edit the Pokémon in. As for Emerald support, I guess I could have a look and see if I can apply the principle, if not necessarily the exact same routine, to the rom. Although in order for me to do that, someone would need to supply me with the ram location of the RTC in an Emerald rom, as, unlike FR, it already has an RTC built in so I can't just look at the inserted routine of the D/N routine.

Yeah, I'll be doing morning, and I'm developing a wild pokemon data editor for this D/N System. I'll post some pics later. As for the RTC, I'm sure ColColStyles might know it, since he does a lot of emerald hacking. ;)

Jambo51
December 8th, 2010, 4:43 PM
I look forward to seeing this tool, for my own use as well as for other XD :D.

I, in the mean time, will endeavour to port the code over to as many versions of the roms as I can. I'll start by extending support to Ruby and Emerald's english versions, and then go from there. Hopefully, the routines will be in exactly the same place for other language roms, thus requiring no modification. The routines should, in theory, be identical, if not necessarily in exactly the same place.

And I asked colcolstyles for any info he may have on the RTC in Emerald, hopefully he'll be able to provide me with at least a starting point to go from :D

Shiny Quagsire
December 8th, 2010, 6:06 PM
I look forward to seeing this tool, for my own use as well as for other XD :D.

I, in the mean time, will endeavour to port the code over to as many versions of the roms as I can. I'll start by extending support to Ruby and Emerald's english versions, and then go from there. Hopefully, the routines will be in exactly the same place for other language roms, thus requiring no modification. The routines should, in theory, be identical, if not necessarily in exactly the same place.

And I asked colcolstyles for any info he may have on the RTC in Emerald, hopefully he'll be able to provide me with at least a starting point to go from :D

The code isn't in the exact same place.

Sure. I'm not a liar, and I always back up my evidence.

Level loading from Fire Red:

080828FA 00C MOVS R4, R0
080828FC 00C LDRB R0, [R4,#1]
080828FE 00C LDRB R1, [R4]
08082900 00C CMP R0, R1
08082902 00C BCC loc_08082908


Level Loading From Emerald:


ROM:080B4C76 MOVS R4, R0
ROM:080B4C78 LDRB R0, [R4,#1]
ROM:080B4C7A LDRB R1, [R4]
ROM:080B4C7C CMP R0, R1
ROM:080B4C7E BCC loc_80B4C86


And finally, Ruby:


ROM:08084D32 MOVS R4, R0
ROM:08084D34 LDRB R0, [R4,#1]
ROM:08084D36 LDRB R1, [R4]
ROM:08084D38 CMP R0, R1
ROM:08084D3A BCC loc_8084D40



As you can see, it's essencially the same thing. If you were to look in IDA or VBA's decompiler, you'd see the same thing, but with a few different registers here and there.

Jambo51
December 9th, 2010, 8:37 AM
I know it's not in exactly the same place between Ruby, FireRed and Emerald, but it may be in exactly the same locations in an English Fire Red rom and a Spanish Fire Red rom. I'll need to have a look. I don't expect them to be, but they'll more than likely be very similarly placed, and the actual routine should (in theory) be identical. So no rewriting for a Spanish rom, simply insert at a different location. I will have to rewrite the routines to work with Emerald after having a quick look at the offsets posted by shiny quagsire, but only because it uses different registers. I couldn't get Ruby to open in VHA-SDL-H (probably a messed up rom) but I'll have a look shortly.

Shiny Quagsire
December 17th, 2010, 5:33 PM
Alrighty! I've finally finished DN Pokemon Data Editor! The download is in an attachment as a zip file. Keep in mind this is only in it's early versions, and may have a bug in it. If you find a bug, contact me by way of PM.

destinedjagold
December 18th, 2010, 3:32 PM
So, is this research, and this new tool, can change the PKMN in the wild depending if it's day or night, just like in the 2nd generation of games?

Shiny Quagsire
December 18th, 2010, 3:36 PM
So, is this research, and this new tool, can change the PKMN in the wild depending if it's day or night, just like in the 2nd generation of games?

Yup. And soon morning and evening, if everything goes along right.

altariaking
December 18th, 2010, 3:43 PM
I have an idea for the tool. How about instead of having the Pokemons names listed alphabetically, have the names of Pokemon from the rom listed by their pokedex order? Because I inserted a fakemon over another Pokemon, and since it's name isn't there, I can't remember which Pokemon I replaced, and the Pokemon are listed alphabetically, it makes it hard to find :\

Edit: For some reason it freezes when I run into a wild Pokemon at night :\

Diegoisawesome
December 18th, 2010, 3:48 PM
I THOUGHT I had the offset for the time in Emerald! I looked through my notes, and here it is: 0x03005CFA.
The reason that you probably didn't find it is probably that it doesn't update unless you do special things, like entering a new map, using a command\special that causes the time to be reloaded, etc.

Jambo51
December 27th, 2010, 4:36 AM
I THOUGHT I had the offset for the time in Emerald! I looked through my notes, and here it is: 0x03005CFA.
The reason that you probably didn't find it is probably that it doesn't update unless you do special things, like entering a new map, using a command\special that causes the time to be reloaded, etc.

Hmmm, seems really like it was built for efficiency rather than realism. I don't suppose there's any way we could use interdpth's FR RTC instead - Adapt it for use on Emerald. However, the routine I developed would be able to use it, it'd just not work properly because it'd be reading a static time which isn't updated until you leave the map.

Darthatron
December 27th, 2010, 6:32 AM
Hmmm, seems really like it was built for efficiency rather than realism. I don't suppose there's any way we could use interdpth's FR RTC instead - Adapt it for use on Emerald. However, the routine I developed would be able to use it, it'd just not work properly because it'd be reading a static time which isn't updated until you leave the map.

Just put a write-breakpoint on that area of the RAM, and find the routine that updates it, then call it before a battle/your routine is initiated. Would that not work?

Jambo51
December 28th, 2010, 1:30 AM
Just put a write-breakpoint on that area of the RAM, and find the routine that updates it, then call it before a battle/your routine is initiated. Would that not work?

Yes, that would work, but as colcolstyles posted before, the rtc only updates when the map is refreshed (i think) or when you change map. I'd have to add an extra part to my routine to make it work, assuming that it updates on refresh. Certainly doable, but a pain nonetheless.

Darthatron
December 28th, 2010, 1:44 AM
Yes, that would work, but as colcolstyles posted before, the rtc only updates when the map is refreshed (i think) or when you change map. I'd have to add an extra part to my routine to make it work, assuming that it updates on refresh. Certainly doable, but a pain nonetheless.

Not JUST when a map is entered. If you find the routine that refreshes the time, then you could call it before your routine is used. Simple.

Jambo51
December 28th, 2010, 9:12 AM
Not JUST when a map is entered. If you find the routine that refreshes the time, then you could call it before your routine is used. Simple.

Yeah, good point. Sorry, I don't know why I missed that before XD. Still, it's a lot of work for a rom i'll almost certainly never use myself.

Diegoisawesome
January 8th, 2011, 7:45 AM
Hey, Jambo51, I have another RTC address for Emerald you may or may not be interested in: 03000DC0. This one has years, day of the week, and other fun things... in binary-coded decimal, however. This means that the hex value that's there looks like is real decimal value.
Ex. 10:30 looks like 0x10 0x30.

Jambo51
January 8th, 2011, 7:50 AM
Hey, Jambo51, I have another RTC address for Emerald you may or may not be interested in: 03000DC0. This one has years, day of the week, and other fun things... in binary-coded decimal, however. This means that the hex value that's there looks like is real decimal value.
Ex. 10:30 looks like 0x10 0x30.

Interestingly, this one is automatically updated every time I enter the battle screen. IF it's done before my battle routine, this could be the answer to the Day/Night Routine for emerald!

Diegoisawesome
January 8th, 2011, 7:53 AM
Interestingly, this one is automatically updated every time I enter the battle screen. IF it's done before my battle routine, this could be the answer to the Day/Night Routine for emerald!
I thought that you had already found the time updater, though.
Actually, it doesn't update upon entering battle. It's probably your call to the updater that's doing it.

Jambo51
January 8th, 2011, 8:13 AM
I thought that you had already found the time updater, though.
Actually, it doesn't update upon entering battle. It's probably your call to the updater that's doing it.

It was indeed my call to the time updater routine which was updating it. I changed the ram offset for the hour byte in both routines, and modified the compare so that they would be in hex-decimal. The routine should work perfectly now! Thanks for the help!

colcolstyles
January 8th, 2011, 4:41 PM
The thing with the data at '0x03000dc0' is that they aren't offset based on the time that the player input. The data there are just what the game reads from the RTC. The game later takes the time there and offsets it based on the player's input. For example, if the time on a player's computer is 9:00 but the player enters 10:00 during the clock-setting special, then the time at '0x03000dc0' will say 9:00 but the time at '0x03005cfa' will be 10:00.

Jambo51
January 9th, 2011, 7:55 AM
The thing with the data at '0x03000dc0' is that they aren't offset based on the time that the player input. The data there are just what the game reads from the RTC. The game later takes the time there and offsets it based on the player's input. For example, if the time on a player's computer is 9:00 but the player enters 10:00 during the clock-setting special, then the time at '0x03000dc0' will say 9:00 but the time at '0x03005cfa' will be 10:00.

OK, thanks for letting me know that. I do have an idea to sort it though! What I plan to do is to store the "pre-update" time and the "post-update" time. I subtract the 2 to obtain the difference between the 2, then use that difference to update the main time! Does that make sense? A roundabout way of fixing it, but I haven't the will or knowledge to go digging around the ROM for the proper update routine. As both times would be updated at the same time, they would never be out of sync, allowing this idea to work.

Shiny Quagsire
January 10th, 2011, 7:21 AM
The thing with the data at '0x03000dc0' is that they aren't offset based on the time that the player input. The data there are just what the game reads from the RTC. The game later takes the time there and offsets it based on the player's input. For example, if the time on a player's computer is 9:00 but the player enters 10:00 during the clock-setting special, then the time at '0x03000dc0' will say 9:00 but the time at '0x03005cfa' will be 10:00.

Theoretically, wouldn't the 0x03000dc0 offset be blank on an individual cart, or be set to the time of the other RTC? I'm probably wrong, but it's a possible answer. I don't think it'd be pre-set, because Japan and the USA have different time zones.

colcolstyles
January 10th, 2011, 2:37 PM
Theoretically, wouldn't the 0x03000dc0 offset be blank on an individual cart, or be set to the time of the other RTC? I'm probably wrong, but it's a possible answer. I don't think it'd be pre-set, because Japan and the USA have different time zones.

I'm not sure what you're trying to say. Here, '0x03000dc0' is where the game writes the RTC data immediately after they are read from the RTC chip. When the game is being emulated on a PC, the time will be whatever time it is on the player's computer. If the game is on a game pak (with a RTC chip), then it just reads whatever the RTC gives it. Then, at a later time, the game reads the hour, minute, and second bytes from '0x03000dc0', converts them to hexadecimal, offsets them based on a value which is calculated when the player sets the clock in his/her room, and then stores the new values at '0x03005cfa'. At least, that's my understanding of it.

Jambo51
January 10th, 2011, 3:42 PM
I'm not sure what you're trying to say. Here, '0x03000dc0' is where the game writes the RTC data immediately after they are read from the RTC chip. When the game is being emulated on a PC, the time will be whatever time it is on the player's computer. If the game is on a game pak (with a RTC chip), then it just reads whatever the RTC gives it. Then, at a later time, the game reads the hour, minute, and second bytes from '0x03000dc0', converts them to hexadecimal, offsets them based on a value which is calculated when the player sets the clock in his/her room, and then stores the new values at '0x03005cfa'. At least, that's my understanding of it.

What I'm meaning is that the time update routine I found (the one which updates 0x03000DC0) can be used to update the main one manually, as long as it's updated at the same time. What I would do is load the values of the RTC at 0x03000DC0 before updating into the registers, then update the time. Then calculate the difference in time between the pre-update time and the post update time. Then using that difference, update the time at the offset 0x03005CFA.

Does that make sense?

Luiz Felipe Apolinário
January 12th, 2011, 3:08 PM
Jambo you have to do make a patch with your asm already inserted in the pokemon firered for me to test the tool's shiny Quagsire? If you can do it I would greatly appreciate it. Thank you for your attention!

Jambo51
January 12th, 2011, 3:58 PM
Jambo you have to do make a patch with your asm already inserted in the pokemon firered for me to test the tool's shiny Quagsire? If you can do it I would greatly appreciate it. Thank you for your attention!

Sorry, but a straight up patch is a VERY bad idea because it might overwrite another hacker's hard worked on data. If I had the know how, I'd write a tool which inserts the routines in a sensible location for you, but I don't. Shiny Quagsire's tool is outdated and was designed for a much older version of the routine. AFAIK, he's working on updating it, and is trying to build the routine insertion into it.

EDIT: I patched the time update routine onto the main loop on Emerald by using this routine:

.text
.align 2
.thumb
.thumb_func
.global timeupdatemainloop

main:
push {r0-r3}
bl timeupdate
pop {r0-r3}
pop {r0}
lsl r0, r0, #0x18
cmp r0, #0x0
bne there
bl thatplace
pop {r0}
bx r0
there: ldr r0, place
bx r0
thatplace: ldr r0, thatplace2
bx r0
timeupdate: ldr r1, timeupdt
bx r1
.align
place: .word 0x080004D5
thatplace2: .word 0x0800051D
timeupdt: .word 0x0802F589


In order for this to work, go to 0x080004CA, and stick the following code in instead:
01 B4 00 48 00 47 XX XX XX 08

What this does is makes the time update routine be called once a frame no matter where in the game you are or what you are doing.

Shiny Quagsire
January 25th, 2011, 7:33 AM
Shiny Quagsire's tool is outdated and was designed for a much older version of the routine. AFAIK, he's working on updating it, and is trying to build the routine insertion into it.


I actually had a version that worked, but when I tried to wipe my computer, the flash drive that had our backed up info died. Luckily I had the old source code lying around in my own flash drive, which had my hacking stuff, so I'm trying to back that up to the newer version.

Sythe_Lord0102
February 11th, 2011, 1:42 PM
This is just a suggestion that may make things more complicated than they may need to be, but here it is: Variable length of the days by season.

I'm suggesting it because I've lived in areas where daylight will last for about twenty hours during summer(Prince George, British Columbia, Canada), and it always felt like the cold would set in earlier and longer, with the nights lasting just as long during winter. I've also known people who've lived close enough to the equator that for most of their lives, they've only known one type of season, despite the calendar saying that its winter or spring. One thing that I've seen in the section "What makes a good ROM" is how realistic it is, and it would add a very realistic element to the game if it changed the length of the days for each season and changed the weather in the battle with each season (ex: if the climate was tropical, it would either be raining or sunny, likely with little to no variation on the length of days).

Granted, it may be a little to hard to do the coding for, so I can understand if this suggestion is overlooked for now.

Suggestion for how it could work if the idea is taken seriously: using something similar to the Header section of Advance Map, with the added option of Climate.

I'm not very good at coding, but I am good at testing. I'll take a look at the most recent version of the D/N program and test it on a spare ROM if somebody can send me the link for it.

Edit: Also posting the idea of length of days being able to change by season in the section entitled "Research: Seasons in Fire Red" started by Shiny Quagsire. This idea may also be more appropriate there.

Shiny Quagsire
February 11th, 2011, 2:36 PM
This is just a suggestion that may make things more complicated than they may need to be, but here it is: Variable length of the days by season.

I'm suggesting it because I've lived in areas where daylight will last for about twenty hours during summer(Prince George, British Columbia, Canada), and it always felt like the cold would set in earlier and longer, with the nights lasting just as long during winter. I've also known people who've lived close enough to the equator that for most of their lives, they've only known one type of season, despite the calendar saying that its winter or spring. One thing that I've seen in the section "What makes a good ROM" is how realistic it is, and it would add a very realistic element to the game if it changed the length of the days for each season and changed the weather in the battle with each season (ex: if the climate was tropical, it would either be raining or sunny, likely with little to no variation on the length of days).

Granted, it may be a little to hard to do the coding for, so I can understand if this suggestion is overlooked for now.

Suggestion for how it could work if the idea is taken seriously: using something similar to the Header section of Advance Map, with the added option of Climate.

I'm not very good at coding, but I am good at testing. I'll take a look at the most recent version of the D/N program and test it on a spare ROM if somebody can send me the link for it.

Edit: Also posting the idea of length of days being able to change by season in the section entitled "Research: Seasons in Fire Red" started by Shiny Quagsire. This idea may also be more appropriate there.

Actually, that'd have to be done in the D/N system itself. This just makes pokemo vary from day to night.

Jambo51
February 14th, 2011, 1:13 PM
I could however, slightly rewrite the coding to support differing Pokémon by season, but it just makes the already massive tables needed for just the day to night transition even bigger.

As for the actual on screen seasonal transition...? Not even my ASM, so wrong thread my friend.

On topic - Have you finished rewriting the tool shiny quagsire?

<TG> AspiroX
March 3rd, 2011, 8:45 AM
This seems awesome! :D
Well, with a tool it would make this function very common, although without a tool i wouldnt be able to use it (as of right now.. xD).

Good luck, I'll be following this thread! :3

Baronnecro
March 5th, 2011, 3:53 PM
ty I was very interested in this very much. you must be credited when I use this.

GoGoJJTech
August 23rd, 2013, 11:38 AM
What's the purpose of the variable in the level loading routine?

Shiny Quagsire
August 23rd, 2013, 11:44 AM
What's the purpose of the variable in the level loading routine?

I believe it's for swarming, but it seems that the code for that was moved to the other routine, so you could take the variable code out and save yourself a few bytes of freespace.

GoGoJJTech
August 23rd, 2013, 11:45 AM
Awesome, thanks. I was looking, and thought "..."

Sorry about double posting, but where are the wild data pointers located? The example was about route 1, yet I have no idea where the other pointers are.

Sorry for TRIPLE posting, but I have yet to find out how this table is stored. I found a pointer to the wild data in route 1, yet the table it's aligned in seems awkward. Anyone have an explanation?

Hound of Justice
September 19th, 2013, 9:47 AM
I hope you make this for emerald :)

AlphaDrache
November 24th, 2013, 1:40 PM
Hey,

I used the routine for my german emerald rom.
I works. The wild Pokémon change during night but sometimes the game freezes when the player walks through the grass (day and night time).
I have no idea why. I only changed the offsets in the routine to make it fit. I'm sure that they are correct because I found them by searching the bytes from the englisch version in the german version.
Can anyone help me please?

Furthermore I can say with the help of the disassembler of the VBA that the code loops endless between that part:

.check:
ldrb r3, [r1, #0x3]
cmp r3, #0xFF
beq .nodata
cmp r3, #0x8
bne .nextnormal
ldr r0, [r1, #0x0]

Maybe your code has a bug.
I don't know if it works perfectly for other ones in emerald?

Akumu Nigiyaka
January 21st, 2014, 2:37 AM
Hi, I wanted to know if I can use it on a French ROM, or if i can't, did you know how I can make it ?


( Sorry if I do not write correctly English, I'm French, and I just learnd English on School =X )


PS: It's really a good job, hope its work on French ROM

GoGoJJTech
January 22nd, 2014, 7:53 AM
Hi, I wanted to know if I can use it on a French ROM, or if i can't, did you know how I can make it ?


( Sorry if I do not write correctly English, I'm French, and I just learnd English on School =X )


PS: It's really a good job, hope its work on French ROM

To do it, you'd need to find the offsets in the French version then change them in the routine.

~Ɓαitøt~
January 22nd, 2014, 11:45 AM
Hi, I wanted to know if I can use it on a French ROM, or if i can't, did you know how I can make it ?


( Sorry if I do not write correctly English, I'm French, and I just learnd English on School =X )

You're everywhere decidedly ^^ !
Otherwise, as I told you that I will look for French Version.

Shiny Quagsire
January 31st, 2014, 8:15 PM
You're everywhere decidedly ^^ !
Otherwise, as I told you that I will look for French Version.

Just as a rule of thumb in the hacking scene we prefer to work with one version to make things easier offset-wise, so if you're going to be doing a lot of ASM additions, small patches to the ROM at specific offsets, and maybe even graphics hacking it's generally best to work with the standard ROM, or in this case BPRE v1.0. You'll find a lot more support there, especially once I roll out built-in Day/Night pokemon into MEH.

pengoy
April 18th, 2014, 6:40 AM
if i try to use this with prime-dialga's DNS, what offsets would be replaced in the ASM code given?

adrift
April 18th, 2014, 6:10 PM
if i try to use this with prime-dialga's DNS, what offsets would be replaced in the ASM code given?

The only offsets that will change are the RAM offsets for the time, I believe.

pengoy
April 19th, 2014, 12:44 AM
The only offsets that will change are the RAM offsets for the time, I believe.
thanks for answering me! :D

you mean this: "...hour: .word 0x03005542..."

using prime's DNS, thats the ram offset for the time... or am i into something else with this?

hackiosa
April 19th, 2014, 8:49 AM
http://board.romresources.net/board6-romhacking/board19-romhacking-tools/13652-beta-pok%C3%A9dan-enter-the-nightmare/

Hi here you can find a tool / asm routine that is able to do the job with prime-dialgas DNS ;)

adrift
April 19th, 2014, 2:39 PM
thanks for answering me! :D

you mean this: "...hour: .word 0x03005542..."

using prime's DNS, thats the ram offset for the time... or am i into something else with this?

Yeah, that is what I meant. Just change that to the appropriate RAM offset and it should work.

pengoy
April 19th, 2014, 10:35 PM
Yeah, that is what I meant. Just change that to the appropriate RAM offset and it should work.

that, i shall do!
thank you! :)

Lance32497
November 12th, 2014, 1:35 AM
Alrighty! I've finally finished DN Pokemon Data Editor! The download is in an attachment as a zip file. Keep in mind this is only in it's early versions, and may have a bug in it. If you find a bug, contact me by way of PM.

How to use it?
I always got an error in my ADVMAP when I use it

Here are the screenies:
http://i.imgur.com/hD8fi7s.png
http://i.imgur.com/91X8Wlb.png

Shiny Quagsire
November 13th, 2014, 2:17 PM
How to use it?
I always got an error in my ADVMAP when I use it

Here are the screenies:
http://i.imgur.com/hD8fi7s.png
http://i.imgur.com/91X8Wlb.png

That's because it modifies how the data is actually read, making it incompatible with A-Map after you convert it to the new D/N format. Currently MEH has support for D/N pokemon editing although it's a tiny bit buggy so be aware of that.

Lance32497
November 14th, 2014, 12:34 AM
That's because it modifies how the data is actually read, making it incompatible with A-Map after you convert it to the new D/N format. Currently MEH has support for D/N pokemon editing although it's a tiny bit buggy so be aware of that.

Yah, a bit buggy ^_^
Tried it in 7 times but when I load the rom in v-boy, it results in whitescreen,
I also tried to fire a clean rom, and as I expect, it loads smoothly....

Any tutorials on how to use it in a safest way?