-Anus Pee's Advanced Rom
Hacking Document v1.2-
written by: Brian Maxwell / Anus Pompous
Anus Pee's goddamn home
page!
E-Mail AnusP!
J2e
translations
E-Mail J2E Translations!
Ported and Fixed to HTML by: Mike Loranger / CataclysmX
CataclysmX's
Page
Email CataclysmX!
Get the text version HERE!
TABLE OF CONTENTS
1- Introduction
2- How Text is Normally Stored
3- Headers
4- Pointer Tables
5- Moving Text in SNES Roms
6- Physical Rom Expansion
7- Expanding text past its bank
8- Conclusion
SECTION 1 INTRODUCTION
1.0 General Stuff about this document
This document was created to help people who wish to learn about
pointer tables and SNES rom expansion. This document may be very
confusing but I tried to keep it as simple as possible! heh. I
wrote in in one night! So I'll probably have to update it later
to fix spelling errors, or make things easier to understand...
but I'm nothing more than a lazy bastard, so my hacks come first!
Anyways, if you do not know anything about rom-hacking, or you
don't know much about it, then LEARN and get some experience! the
only program you'll need to do the following is a hex editor. I
recommend "Hex
Workshop"! I also tried to write this document to be as
universal as possible, so not every rom will be modified or
expanded in the following ways. So if you have problems with this
document, then you're either hacking an EVIL rom, or something I
haven't seen yet. Or I might not have gotten my point accross..
Please, tell me how good this document is! I beg you!
1.1 History
SECTION 2 HOW TEXT IS NORMALLY STORED
2.0 Variable Length Text
In rom's text is usually stored in clumps of text strings. For
instance, one text string will appear after another, and are
usually separated by a hex value which signifies the end of a
string (not a line break!). Now the text in these clumps of text
strings (I like to call them "text blocks") won't
nessessarily have the text in the order that it appears in the
game. In NES roms this is how all of the text is usually stored,
with a "standard pointer table system". But in SNES
roms, I have found other ways in which text is stored; Some times
text will be stored in text blocks as mentioned above, but will
include some coding in between each string instead of a standard
hex to signify the end of a line. These text blocks usually don't
have pointer tables and you should be able to change the lengths
of individual strings without any problems! The only downfall to
text stored like this is the fact that it makes it harder to dump
text from it to get it translated. Examples of text that's stored
like this are the Romancing Saga games.
2.1 Constant Length text
One other way that some text is sometimes stored in SNES roms is
in a "constant length" format. This is usually how
monster names, items, ect... are stored in RPGs. The Final
Fantasy games store that kind of stuff in that format. What
Constant Length text is; It's a bunch of text (items) that have a
certain length and are not separated by hex values which signify
the end of a string. They run right into one another... For
example, the Items in Final Fantasy 4 are 9 characters long, and
they follow one another like this:
Tent FenixDownPotion BlackSwrdIronArrow
as you can see there is no specific hex value separating them.
Which means that you can use the extra space as you wish! Because
if you look there are still 5 spaces to use for Tent, so you can
make that name even longer of you wish! While this may be good
news for some things, You wont be able to exceed the maximum
amount of spaces used for each item. The only way to increase the
amount of letters you can use for Constant Length text is to
learn ASM!
2.2 Text that's just floating around
And finally, sometimes in SNES roms, there is just text floating
around in the rom on its own, not in any specific "Text
Blocks". The only way to expand these out is to move'em to
somewhere in the rom where there is room to epand them out!
(explained in more detail later on... section 5)
2.3 Something else you should know about the way SNES stores
text.
Sometimes there are Text Blocks in the rom which do not use
pointer tables. These can just simply be expanded out as you wish
without any trouble just by moving the hex values which signify
the end of a string. This is similar to the "RS" text
blocks with the coding in between each string. just move the
coding to fit text into rom. But one thing you should know is
that there is sometimes text stored in the rom (in text blocks)
that have to be expanded out in a similar mannar that the text
floating around has to be. Basically this type of text is text
just "floating around" in the rom, exept they follow
one another like text would in a standard text block.
SECTION 3 HEADERS
3.0 NES Headers
The headers in NES roms are in the first line of an NES rom in a
hex editor. the fist 16 bytes of the rom is its header. In other
words the header covers "10" hex bytes. This is an
important number to remember when editing pointer tables in NES
roms.
the header usually looks something like this:
4E45 531A 1000 1300 0000 0000 0000 0000
You'll notice that the first three bytes are the ASCII standard
for "NES"! Other info is stored here such as the mapper
number, ect....
3.1 SNES Headers
The header in SNES roms is remarkably bigger than in NES roms. It
covers 512 bytes. Or "200" hex bytes. This is also
another important number to remember. Not as important for
pointer tables though, but it is important for moving text blocks
and stuff!
the header in an SNES rom looks similar to this:
8000000000000000AABB040000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
The information here is not really important.
But if you're rom does not have a header, then ADD ONE!
(This is sometime the cause of roms not working in some
emulators)
To add a header to it, just copy a header from any SNES game that
has one, and then "Insert" the copied header into the
rom.
SECTION 4 POINTER TABLES
4.0 NES Pointer Tables
To find a pointer table for the text in your rom, it is
nessessary that you know where the text is in the rom, what hex
signifies the end of a line, and by knowing these you can then
find the beginning of the text block. Once you find the beginning
of the text block the pointer table should be IMMEDIATELY before
the text! It will look like it has a pattern to it. Figuring out
the pattern is mostly up to you, but here is pretty much how you
figure out how it works. Take an address from the beginning of a
line. (An example would be 012D63) and knock off the all extra
letters except for the last 4 digits making it 2D63. Pointer
tables store addresses in pairs so 2 hex values are needed...
break up 2D63 into pairs and you got 2 hex values.. 2D, and 63!
Now before you break up the hex values, you gotta subtract the
header from the address. Since the NES header is 10 hex bytes,
subtract 2D63 by 10 making it 2D53. Now break this up into pairs
making it 2D 53, and then re-arrange it backwards! (thats how
roms store addresses. so 2D 53, becomes 53 2D. This will tell you
one of the hex values in each pointer in the pointer tables. You
should be able to find 53 in there, but 2D might be something
else.. So you're actually looking for 53xx (where xx is unknown).
That's up to you to figure out!
an example of a pointer table followed by text in an NES rom:
019D30: 4D76 00F8 349D 3B9D 419D 449D 499D
4D9D
019D40: 529D 569D E5E3 F6CD 4ADA
70F8 F9FA FBF0
019D50: 704C FE70 4BDD CEF3 705C F64D 704C F6CF
019D60: CE70 F5DD CB70 4BF0 DDF1 F2DD F370 83B7
Explanation: Well, hex "70" signifies the end of a
string so using that you find the begining of the text block
which is at hex 019D44, and so everything before that is the
pointer table! You'll notice that 9D repeats alot in the pointer
table. Well, that is your unknown which you gotta figure out on
your own!
4.1 SNES Pointer Tables
SNES pointer tables work in the same manner, except you don't
subtract the header from it. But you gotta watch out, because
sometimes you might get an evil rom in which you GOTTA subtract
something, but thats very rare and easy to deal with once you get
the hang of it! Now also keep in mind that sometimes text in SNES
roms don't use a pointer table(Romancing SaGA). So if you can't
find one before the text, then just experiment! Try changing the
lengths of the strings by moving around the hex that signifies
the end of a string and see if it works! But if it doesn't work,
and there's no pointer table, then you're gonna have to learn how
to move text within the rom! (explained in section 5)
SECTION 5 MOVING TEXT IN SNES ROMS
5.0 Moving Text Within Banks
Now this is more heavy stuff! You might have to do this if the
text you have doesn't have a pointer table, and wont expand just
by moving the hex to signify the end of a text string. You will
also have to do this to expand text that's just floating around
in the rom. Most of the time this text is moved within Banks.
What's a bank? well... time for my explanation. A bank is a part
of the rom in which info is stored. One bank in a low-rom is 32KB
(8000 hex bytes) and in a high-rom its 64KB (10000 hex bytes).
For instince, the adress $000200 to $0081FF is the first bank
within a low-rom and $008200 to $0101FF is the 2nd bank, ect...
And in a high-rom $000200 to $0101FF is the first bank and
$020200 to $0301FF is the 2nd bank, ect... These addresses have
the $200 header included if you notice! Oh, and did I forget to
mention, the "$" before the address signifies that I'm
talking about hex values! Anyways... Most of the time text that's
just floating there, or whatever can only be moved within the
bank that it's located in. To do this you gotta start converting
the address into a pointer to that address you can find! First,
lets take some text from FF4 that's on its own (not in any
specific text block) at the address 09DEC6. Now subtract the
header from this address ($200 in SNES roms, if the game has a
header). So $09DEC6 - $200 = $09DCC6. Now, since you are just
moving one small thing, chances are, it can only be moved within
that bank! Which means that it has to be moved within $098000 to
$09FFFF (without the header, ofcourse. also note that FF4 is a
low-rom). Now the next step to do is to get rid of the 09 before
the rest of the address, since jumps within banks are stored as 2
hex bytes. So 09DCC6 becomes DCC6. Now split it up and make it
backwards so it becomes C6DC, and search for that number within
the bank, and hopefully you'll find the pointer!
Another Note: The address you are searching for must always be
between 8000 to FFFF in a low-rom, so if you're looking up a
pointer for text at 0928B0, subtract the header, knock off the
extra 09 (or whatever that may be), which makes it 26B0. Now
before you split it up and make it backwards, you gotta att $8000
to it, to make the address between 8000 to FFFF, so $26B0 + $8000
becomes $A6B0. You then re-arrange it as B0A6 and search for
that! But in a high-rom, the address can be anywhere between 0000
and FFFF since the banks are 64KB instead of 32KB.
5.1 Moving Large Text Blocks (and other stuff) To Different
Banks!
Usually Large Blocks of text will have pointers that will anable
you to move text to anywhere in the rom! This is where physical
expansion comes in handy! (explained in section 6) What you will
have to do is move text to a place where there is enough room to
expand it out. First find the place where your text begins.
(you'll have to move text and its pointer tables seperately...
This may also apply for some text just floating in the rom, but
they usally use pointers within banks to point to them.) Moving
these is basically done in the same mannor as above, exept you
gotta figure out what bank its in. The first thing to do is
subtract the header, and this following chart shows the
conversion between the actual address and the way the SNES will
read the address.
this chart is for low-roms:
HEX | Low-ROM SNES | |
---|---|---|
000000-007FFF 008000-00FFFF 010000-017FFF 018000-01FFFF 020000-027FFF 028000-02FFFF 030000-037FFF 038000-03FFFF 040000-047FFF 048000-04FFFF 050000-057FFF 058000-05FFFF 060000-067FFF 068000-06FFFF 070000-077FFF 078000-07FFFF 080000-087FFF 088000-08FFFF 090000-097FFF 098000-09FFFF 0A0000-0A7FFF 0A8000-0AFFFF 0B0000-0B7FFF 0B8000-0BFFFF 0C0000-0C7FFF 0C8000-0CFFFF 0D0000-0D7FFF 0D8000-0DFFFF 0E0000-0E7FFF 0E8000-0EFFFF 0F0000-0F7FFF 0F8000-0FFFFF 100000-107FFF 108000-10FFFF 110000-117FFF 118000-11FFFF 120000-127FFF 128000-12FFFF 130000-137FFF 138000-13FFFF 140000-147FFF 148000-14FFFF 150000-157FFF 158000-15FFFF 160000-167FFF 168000-16FFFF 170000-177FFF 178000-17FFFF 180000-187FFF |
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = |
008000-00FFFF 018000-01FFFF 028000-02FFFF 038000-03FFFF 048000-04FFFF 058000-05FFFF 068000-06FFFF 078000-07FFFF 088000-08FFFF 098000-09FFFF 0A8000-0AFFFF 0B8000-0BFFFF 0C8000-0DFFFF 0D8000-0CFFFF 0E8000-0EFFFF 0F8000-0FFFFF 108000-10FFFF 118000-11FFFF 128000-12FFFF 138000-13FFFF 148000-14FFFF 158000-15FFFF 168000-16FFFF 178000-17FFFF 188000-18FFFF 198000-19FFFF 1A8000-1AFFFF 1B8000-1BFFFF 1C8000-1CFFFF 1D8000-1DFFFF 1E8000-1EFFFF 1F8000-1FFFFF 208000-20FFFF 218000-21FFFF 228000-22FFFF 238000-23FFFF 248000-24FFFF 258000-25FFFF 268000-26FFFF 278000-27FFFF 288000-28FFFF 298000-29FFFF 2A8000-2AFFFF 2B8000-2BFFFF 2C8000-2CFFFF 2D8000-2DFFFF 2E8000-2EFFFF 2F8000-2FFFFF 308000-30FFFF |
I'm sure you see the pattern now. So lets say you have a text
block located at $080600. Subtract the header, so it becomes
$080400, and then look it up on the chart and find its new
address. so $080400 is actually $108400. Now split it up into
pairs -> 10 84 00, and re-arrange them backwards -> 008410.
Now you'll have to search for that, and remember, it might appear
more than once in the rom, so the best thing to do change all of
these addresses that appear in the rom to the new one.
A little hint: These kind of just USUALLY have "BF"
before them, so 008410, might look like BF008410.
Now for high-roms since the banks are in 64KB blocks the way the
snes addresses them is different. They don't have to be between
the 8000-FFFF crap! It just adds up like a normal adress exept it
starts at C00000. So really, all you gotta do is add $C00000 to
the hex address to get the High-rom SNES address. For example,
take hex $1AE380, subtract the header so it becomes $1AE180 and
now add $C00000 so it becomes $DAE180. And there you go! You got
yourself your pointer!
SECTION 6 PHYSICAL SNES ROM EXPANSION
Now for the easy part! In SNES roms, all you gotta do to make the
rom bigger, is just add more space to it! Of course the space
that you add HAS to be a multiple of 32KB, or $8000 hex bytes, or
1 bank.
But the roms are usually more stable if you keep them at a
muliple of 4mbits.
below is a small chart which shows stable file sizes to keep your
rom at:
(the following hex addresses include the $200 header)
MBITs | HEX BYTES | ~ SIZE |
---|---|---|
4mbit 8mbit 12mbit 16mbit 20mbit 24mbit |
$080200 $100200 $180200 $200200 $280200 $300200 |
0.5MB 1.0MB 1.5MB 2.0MB 2.5MB 3.0MB |
yada yada yada... I'm sure you see the
pattern...
well, that about does it! Don't ask me how to expand NES roms,
because I don't know how, and from what I hear it's next to
impossible!
SECTION 7 EXPANDING TEXT PAST ITS BANK
What do I have to say about this? Well, unless you're prepared to
do some ASM modifications, don't expand text past the bank that
its in. What I mean by this is, if you have a low rom and you're
expanding text, you can't have it exceed the 32KB that's
allocated for the bank, or 64KB for high-roms. What tends to
happen is the text that runs spills into the next bank tends not
to be displayed on the screen. Now I'm not sure that this is the
case with some roms, but I'm suspecting that it is because this
has happened to us in our FF4 translation. Now there is another
way to get around the problem, and that's to limit the player to
using ZSNES 2.95 because of a bug in it! But I would not
recommend using that as an alternative, because not everyone will
want to use that old version of ZSNES.
SECTION 8 CONCLUSION
Wow! I wrote all this in one night!?! Yep! Now I'm damn tired!
Anyways, Most of the stuff in this document covers stuff on SNES
roms, so if you're having trouble with NES roms, please don't
contact me, because I probably won't know about it! I only know
how to find NES pointer tables, and that's it! But SNES is a
different story! I am constantly learning more and more, and so
someday this document will probably be even better! But for now,
it remains as it is.
I would like to thank the following people:
P-Funk: | For helping me out with moving stuff within a rom |
Dark Force: | For helping me out with some technical stuff as well |
Necrosaro: | For creating his program to save time on adding up all of FF4's pointers!! (that would have taken a loooong time without him!) |
CataclysmX: | For originally porting this document into HTML and other stuff! |
Any questions/comments? Send
away to AnusP!
Any HTML comments or flames Send away to CataclysmX!
©***Copyright Issues***©
Anyone who distributes this file must not modify it in any
way, without prior consent from the author. They must also have a
link to J2E translations and Anus P's home page at the top or
bottom of the page. Thank you for your cooperation.
J2E
Translations! (http://www.members.aol.com/j2etrans/index.html)
Anus Pee's
goddamn home page! (http://members.xoom.com/anusp/)
Anus P. ©
1998