• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

How to expand Pokemon G/S/C Roms(Up to 8MB!)

29
Posts
9
Years
  • Age 30
  • 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:
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.



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!

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:
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]
Bytes, Length: 0x22:
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
Read Assembly:
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]
Bytes, Length: 0x2A:
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
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:
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
Additionally, the time bytes are stored like this once you apply this patch:

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:

Dr. Seuss

Will finish GS Chronicles, I swear!
523
Posts
10
Years
A little question ¿How calculate the pointer of a adress up to 0x3FFFFF? because when the Rom size is 4MB the last bank is 0xFF.
 
29
Posts
9
Years
  • Age 30
  • Seen Feb 3, 2020
A little question ¿How calculate the pointer of a adress up to 0x3FFFFF? because when the Rom size is 4MB the last bank is 0xFF.

FF:7FFF = 0x3FFFFF
I'm not really sure what you're asking.

Did you mean 0x7FFFFF?
See the bottom part about writing to the MBC by using ASM.
 

C me

Creator of Pokemon League Of Legends
681
Posts
10
Years
  • Age 27
  • Seen Apr 9, 2021
I have 3 questions:

Why does the RTC no longer work when doing this?

Is there a way to make the RTC work again after doing this?

If not, is there a way to reverse this so the RTC works again?

Thank You
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
I have 3 questions:

Why does the RTC no longer work when doing this?

Is there a way to make the RTC work again after doing this?

If not, is there a way to reverse this so the RTC works again?

Thank You
The thing that you're supposed to write to rom addresses 0x147-0x148 defines both the rom size, and cartidge type (along with memory bank controller = "MBC") used in the game.
So by writing "1B" to 0x147, you automatically disable the real time clock from the game but at the same time, enable the usage of the rom data up to 8MB. So to answer to your question, no, it's not possible but reversing it back should work just fine.

More info here:
http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
http://gbdev.gg8.se/wiki/articles/Memory_Bank_Controllers

P.S
Pokemon Gold and Silver roms contain quite a lot of free space as their own so if you want to hack them, and unless you do something crazy (like enter loads of new music tracks and graphics to the game), you won't even need to expand the rom data past 2MB.
 
29
Posts
9
Years
  • Age 30
  • Seen Feb 3, 2020
The thing that you're supposed to write to rom addresses 0x147-0x148 defines both the rom size, and cartidge type (along with memory bank controller = "MBC") used in the game.
So by writing "1B" to 0x147, you automatically disable the real time clock from the game but at the same time, enable the usage of the rom data up to 8MB. So to answer to your question, no, it's not possible but reversing it back should work just fine.

More info here:
http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header
http://gbdev.gg8.se/wiki/articles/Memory_Bank_Controllers

P.S
Pokemon Gold and Silver roms contain quite a lot of free space as their own so if you want to hack them, and unless you do something crazy (like enter loads of new music tracks and graphics to the game), you won't even need to expand the rom data past 2MB.

That only applies to original hardware. Emulators do not have the same restriction. At the same time, you'd have a difficult time finding a real MBC5 cartridge to write to, so it's not much of an issue in 2014.

On top of that, the RTC can be modified(The functions accessing the RTC) to work using assembly to control the time value; however, it can't be used as a real clock without the emulator specifically supporting a custom MBC5+RAM+BATT+RTC cartridge.

My first idea was setting it so that every 1 minute of game time = 10 minutes on the RTC since game time and the RTC must be calculated separately, and the routines to check the RTC can be repointed and force to do whatever you want them to.

To help with this, the in-game timer can be found at 0xD1EB(Pokemon Gold) And looks like this:
Code:
0xD1EB - Hours (2 Byte)
0xD1ED - Minutes
0xD1EE - Seconds
0xD1EF - Frames (60/second)
It clears itself at 0xFFFF Hours, 0x3C Minutes, 0x3C Seconds, and 0x3C Frames.

Routine for accessing RTC:
View attachment 73136

Real simple routine. It shouldn't take much effort to have it read from D1EB-D1EE, then have it call a routine instead of reading the bytes for the day. Chances are that the bytes D1E9 and D1EA can be used for storing the day and you can just do (Hours % 24) and just start the game as whatever that day happens to be. My guess is that the game just applies a delta to the days anyways, so it shouldn't matter. Easy peasy.

EDIT: DO NOT USE 0xD1EA to store the day. 0xD1EA controls the timer. Setting it higher than 0 will disable it.
 
Last edited:
55
Posts
6
Years
  • Age 37
  • Seen Nov 24, 2023
I know this is very old but I am going crazy to find a way to expand the rom and the instructions above are not to clear for me. Can someone give me a step by step to increase the rom size? Where do I find the 0x147 and 0x148 for example in a Hex Editor?

I am new to this...
 
Back
Top