- 29
- Posts
- 10
- Years
- Seen Feb 3, 2020
Here's a fun one! Do you want to do something BIG in the second Gen pokemon games? Is the 2MB(minus original content) limit too small for you? Do you just want 2MB for your exclusive use? Well, expanding your ROM allows all of these things!
BE AWARE THAT INCREASING THE ROM SIZE FORCES THE RTC TO NO LONGER WORK. THE TIME OF DAY WILL NOT CHANGE UNLESS THE PLAYER CHANGES IT. THIS IS SLIGHTLY MORE USEFUL FOR GEN I ROMS WHO DID NOT HAVE AN RTC, ONLY AN MBC3.
SEE PART 4 FOR A METHOD OF SIMULATING THE RTC WITH AN IN-GAME CLOCK.
You will need:
BE AWARE THAT INCREASING THE ROM SIZE FORCES THE RTC TO NO LONGER WORK. THE TIME OF DAY WILL NOT CHANGE UNLESS THE PLAYER CHANGES IT. THIS IS SLIGHTLY MORE USEFUL FOR GEN I ROMS WHO DID NOT HAVE AN RTC, ONLY AN MBC3.
SEE PART 4 FOR A METHOD OF SIMULATING THE RTC WITH AN IN-GAME CLOCK.
You will need:
Code:
A Pokemon Gold, Silver, or Crystal ROM(Actually, I'm sure this works with Gen I roms as well)
A hex editor(Because PKSV won't let me do what I want!)
PKSV(We're going to abuse PKSV a teeny tiny bit.)
1. Open your ROM in a Hex Editor
Change the bytes 0x147 and 0x148 to 1B and 07 respectively.
Change the bytes 0x147 and 0x148 to 1B and 07 respectively.
2. Open PKSV by itself
In your untitled file write the following code:
Code:
#org 0x3FFFFD
2call 0x0000
3. Open ROM and Compile
Open your ROM in PKSV then click on Compile.
You are done! The above code causes PKSV to create a 4MB ROM with an extra 128 readable memory banks as long as you made the the changes to addresses 0x147 and 0x148.
Don't believe me? Try it out!
In order to create an 8MB Pokemon ROM you simply need to change 0x3FFFFD to 0x7FFFFD and byte 0x148 inside the ROM to 0x08.
To access the upper 4MB of data you first need to create an assembly routine that writes 0x1 to 0x3000 to have the MBC 5 bank use the upper 0x400000 bytes available to it.
Here's a quick example:
Open your ROM in PKSV then click on Compile.
You are done! The above code causes PKSV to create a 4MB ROM with an extra 128 readable memory banks as long as you made the the changes to addresses 0x147 and 0x148.
Don't believe me? Try it out!
NewBarkFatMan.pks said:'Written for Pokemon Gold
#org 0x12009B
'-----------------------------------
2jump 0x65B0
#org 0x1225B0
3jump 0x400080
#org 0x200000
loadfont
2writetext 0x400A
closetext
3jump 0x65B448
#org 0x1225B4
loadfont '0x1225B4
2writetext 0x65C0
closetext
jumptextfaceplayer 0x427E ' 0x12027E
#org 0x1225C0
= Test Output\nTest Output\lTest Output\nTest Output\pTest Output\e
#org 0x20000A
= Text read from:\n0x20000A\e
#org 0x12027E
= Yo, [PLAYER]!\pI hear PROF.ELM\ndiscovered some\lnew [POKé]MON.\e
In order to create an 8MB Pokemon ROM you simply need to change 0x3FFFFD to 0x7FFFFD and byte 0x148 inside the ROM to 0x08.
To access the upper 4MB of data you first need to create an assembly routine that writes 0x1 to 0x3000 to have the MBC 5 bank use the upper 0x400000 bytes available to it.
Here's a quick example:
Code:
; Access the lower 0x400000 bytes(0x000000 - 0x3FFFFF)
; F5 3E 00 EA 00 30 F1
push af
ld a,0x00
LD 3000,a
pop af
; Access the upper 0x400000 bytes(0x400000 - 0x7FFFFF)
; F5 3E 01 EA [SIZE=2]00 30 F1
push af[/SIZE]
ld a,0x01
LD 3000,a
pop af
4. RTC Simulation
So, lets say that you want to hack Gold, you need the extra space(or just want to work in completely new space), and you need the time of day to change and for time based events to be able to occur. What are you to do?
In-Game Clock!
This means that we'll make a faux RTC which will update based on the game timer(in my method, it actually is the game timer. It over-takes it and uses the second counter to count Minutes, Hours, and Days.
This has two parts. The first part is the write assembly, the second part is the read assembly.
The write assembly will be placed in the blank space at the beginning of the ROM (0x0064 specifically.
The read assembly will be placed at 0x047F, and will over-write the existing RTC check functions. The read assembly will also call the write assembly.
A quick note about this: Minutes show up 1-to-1, so it looks a little weird. Every 6 in-game minutes is one hour, and every 2:24 or 144 Minutes(2 hours and 24 minutes) is one in game day. You're free to change it to your liking if you'd prefer. Just change the minutes in the write assembly to affect the length of an hour;
Write assembly:
Bytes, Length: 0x22:
Read Assembly:
Bytes, Length: 0x2A:
With this method, I feel that the best way to go about it is to always set the clock in-game to 12:00 PM or 12:00 AM, and the day to Sunday, or Monday based on your start of the week preference. This makes changing the time very easy by editing them in memory through your emulator's memory editor, or by using Gameshark.
Gameshark:
Additionally, the time bytes are stored like this once you apply this patch:
If you make any changes to the code, do NOT mess with 0xD1EA.
This byte controls whether or not the timer is running. Setting it to a value greater than 0 will disable it.
In-Game Clock!
This means that we'll make a faux RTC which will update based on the game timer(in my method, it actually is the game timer. It over-takes it and uses the second counter to count Minutes, Hours, and Days.
This has two parts. The first part is the write assembly, the second part is the read assembly.
The write assembly will be placed in the blank space at the beginning of the ROM (0x0064 specifically.
The read assembly will be placed at 0x047F, and will over-write the existing RTC check functions. The read assembly will also call the write assembly.
A quick note about this: Minutes show up 1-to-1, so it looks a little weird. Every 6 in-game minutes is one hour, and every 2:24 or 144 Minutes(2 hours and 24 minutes) is one in game day. You're free to change it to your liking if you'd prefer. Just change the minutes in the write assembly to affect the length of an hour;
Write assembly:
Code:
[FONT=Monospace]ROM0:0064 21 ED D1 ld hl,D1ED
ROM0:0067 7E ld a,(hl)
ROM0:0068 FE 06 cp a,06 ; Checks to see if the current number of minutes. Change this to effectively change the length of an hour.
ROM0:006A 30 01 jr nc,006D
ROM0:006C C9 ret
ROM0:006D 36 00 ld (hl),00
ROM0:006F 2B dec hl
ROM0:0070 7E ld a,(hl)
ROM0:0071 3C inc a
ROM0:0072 77 ld (hl),a
ROM0:0073 FE 18 cp a,18
ROM0:0075 30 01 jr nc,0078
ROM0:0077 C9 ret
ROM0:0078 36 00 ld (hl),00
ROM0:007A 2B dec hl
ROM0:007B 7E ld a,(hl)
ROM0:007C 3C inc a
ROM0:007D 77 ld (hl),a
ROM0:007E FE 07 cp a,07
ROM0:0080 30 01 jr nc,0083
ROM0:0082 C9 ret
ROM0:0083 36 00 ld (hl),00
ROM0:0085 C9 ret [/FONT]
Code:
21 ED D1 7E FE 06 30 01 C9 36 00 2B 7E 3C 77 FE 18 30 01 C9 36 00 2B 7E 3C 77 FE 07 30 01 C9 36 00 C9
Code:
[FONT=Monospace]ROM0:047F CD 64 00 call 0064
ROM0:0482 21 EE D1 ld hl,D1EE
ROM0:0485 7E ld a,(hl)
ROM0:0486 E0 93 ld (ff00+93),a
ROM0:0488 2B dec hl
ROM0:0489 7E ld a,(hl)
ROM0:048A E0 92 ld (ff00+92),a
ROM0:048C 2B dec hl
ROM0:048D 7E ld a,(hl)
ROM0:048E E0 91 ld (ff00+91),a
ROM0:0490 2B dec hl
ROM0:0491 7E ld a,(hl)
ROM0:0492 E0 90 ld (ff00+90),a
ROM0:0494 CD F1 30 call 30F1
ROM0:0497 C9 ret
ROM0:0498 00 nop
ROM0:0499 00 nop
ROM0:049A 00 nop
ROM0:049B 00 nop
ROM0:049C 00 nop
ROM0:049D 00 nop
ROM0:049E 00 nop
ROM0:049F 00 nop
ROM0:04A0 00 nop
ROM0:04A1 00 nop
ROM0:04A2 00 nop
ROM0:04A3 00 nop
ROM0:04A4 00 nop
ROM0:04A5 00 nop
ROM0:04A6 00 nop
ROM0:04A7 00 nop [/FONT]
Code:
CD 64 00 21 EE D1 7E E0 93 2B 7E E0 92 2B 7E E0 91 2B 7E E0 90 CD F1 30 C9 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0
Gameshark:
Code:
01XXEBD1 - Set Day, replace XX with 00 - 06
01XXECD1 - Set Hour, replace XX with 00 - 17
01XXEDD1 - Set Minutes, replace XX with 00 - 05
01XXEED1 - Set Day, replace XX with 00 - 3B
Code:
[FONT=Monospace]
0xD1EB - Day (0-6)
0xD1EC - Hour (0-23)
0xD1ED - Minutes (0-5)
0xD1EE - Seconds (0-59)[/FONT]
If you make any changes to the code, do NOT mess with 0xD1EA.
This byte controls whether or not the timer is running. Setting it to a value greater than 0 will disable it.
Last edited: