Author
|
Topic: More room to insert translated text? (Read 2 times)
|
gamingjustin
Guest
|
 |
« on: January 26, 2009, 08:47:26 pm » |
|
Hi all. Lately I've been working on a translation of Megami Tensei II for NES. I've been using Tile Layer Pro, Relative Search and WindHex32 to create and implement tables. All's well on that end. This being my first time hacking/translating I was positive I'd run into a roadblock, though. So sure enough, here it is...
I don't know how to effectively insert the translated text I wrote. I discovered how to expand the size of the ROM in WindHex32 but I can't figure out how to utilize that new space. I can only write directly over the original text, I can't squeeze in more. I could really use some more room-- not too keen on writing like a caveman just to fit everything.
Also, sorry if this is a common question, but I'm not able to find any solutions...
Thanks in advance for any and all input!
|
|
|
|
Ryusui
Guest
|
 |
« Reply #1 on: January 26, 2009, 09:45:15 pm » |
|
You have two options, though there's nothing stopping you from using both in tandem: compression, and expanding the ROM. Both options will require some ASM knowledge - i.e., you'll have to hack the game's code.
A simple dictionary scheme (a.k.a. "multi-tile encoding", or MTE) should suffice. As for expanding the ROM, I can assume that the game's pointers don't include a bank byte, in which case you'll have to add one (it'll take some hacking, but d4s actually pulled it off in Breath of Fire 2: the bank bytes are stored in a separate pointer block).
|
|
|
|
gamingjustin
Guest
|
 |
« Reply #2 on: January 26, 2009, 10:16:04 pm » |
|
Thanks for pointing me in the right direction, Ryusui. Looks like I'll be readin' for a while-- plenty of documentation here. And hey I recognize your name from another forum. I should have figured you'd be a regular here!
|
|
|
|
KingMike
Guest
|
 |
« Reply #3 on: January 26, 2009, 10:36:43 pm » |
|
Is WindHex really smart enough to expand NES ROMs correctly? (NES ROM expansion is somewhat mapper-dependant. Most games' PRG-ROM can be properly expanded by doubling the space, but it usually needs to be added before the last 16KB (as most mappers map the last 16KB of PRG-ROM permanently to the CPU space). However, there are exceptions. I've done two Namco games using the same mapper as MT2. I guess it's just a coding style, but they both used mirror bank numbers (that is, when writing to the bankswap registers, the value written would be ANDed with the last real bank. So if the last real bank was #0F, and it tried swapping bank $97 in, it would actually swap bank 7 in (#$97 AND #$0F = #$07). As a result, all extra space had to be added at the beginning of the ROM.
*The rest is off-topic to this game*
(I think Dragon Scroll might have needed this to be expanded, but there was enough free space in the fixed bank I could fit DTE+dictionary to fit the translation in without expansion) And MMC1 with 512KB PRG is another weird case (supposedly 1MB would have been more complex, but I suspect it was just oberservations based on the bad ROM of Dragon Warrior 4 (was a similar bad dump of DQ4 in circulation?), since no real cart had MMC1+1MB PRG).
|
|
|
|
Ryusui
Guest
|
 |
« Reply #4 on: January 27, 2009, 11:48:53 pm » |
|
Is WindHex really smart enough to expand NES ROMs correctly? (NES ROM expansion is somewhat mapper-dependant. Most games' PRG-ROM can be properly expanded by doubling the space, but it usually needs to be added before the last 16KB (as most mappers map the last 16KB of PRG-ROM permanently to the CPU space). However, there are exceptions. I've done two Namco games using the same mapper as MT2. I guess it's just a coding style, but they both used mirror bank numbers (that is, when writing to the bankswap registers, the value written would be ANDed with the last real bank. So if the last real bank was #0F, and it tried swapping bank $97 in, it would actually swap bank 7 in (#$97 AND #$0F = #$07). As a result, all extra space had to be added at the beginning of the ROM.
*The rest is off-topic to this game*
(I think Dragon Scroll might have needed this to be expanded, but there was enough free space in the fixed bank I could fit DTE+dictionary to fit the translation in without expansion) And MMC1 with 512KB PRG is another weird case (supposedly 1MB would have been more complex, but I suspect it was just oberservations based on the bad ROM of Dragon Warrior 4 (was a similar bad dump of DQ4 in circulation?), since no real cart had MMC1+1MB PRG).
Translation for the uninitiated: NES programming is some complicated crap.Let me introduce you to the concept of address space. A game console's hardware uses a range of addresses to access all its myriad forms of storage in one big chunk. What addresses correspond to what varies wildly depending on the platform, but the part we need to concern ourselves with is ROM address space. On the NES, we have 32Kb of ROM address space, from $8000 to $FFFF: once upon a time, this was the ironclad upper bound for NES ROM size, and that was all well and good until games needed more space. So companies began to devise their own methods of circumventing the NES' storage space limits. Thus began the age of mappers. A mapper is a system by which ROMs in excess of 32Kb can be "mapped" to the NES' ROM address space: the ROM is, for all intents and purposes, neatly divided into chunks of equal size - usually called banks - which are swapped in and out of access as needed. If you need help visualizing the concept, think of the ROM as a book and the banks as individual pages - you can only read one at a time, and if you need information or instructions that aren't on the current page, you flip to the page you need. (Appropriately enough, the word "page" describes a similar concept in computing: you've probably heard the term already in the context of the dreaded-but-nebulous "Page Fault Error".) What ensued in Japan was that practically every company that developed for the NES ended up devising its own mapper, resulting in a babel of conflicting methods that plagues emulator authors (and romhackers) to this day. In America - IN AMERICA! - Nintendo put its foot down and mandated the use of standard mappers, meaning that there are only five different mappers in the U.S. (and that games that were incompatible with these mappers had to be reprogrammed, hence such oddities as the missing intro and color cycling effect in the American version of Contra). Standardized bank swapping schemes became the norm in ensuing generations, such as the Game Boy and SNES, and the expanded address space of the GBA and DS obviates the use of bank swapping entirely. But NES romhackers have to contend with this relic of the past and its arcane logic. Oh, and to answer your question: no, it's not smart enough. It just pads the ROM with extra bytes.
|
|
|
|
KingMike
Guest
|
 |
« Reply #5 on: January 28, 2009, 12:51:08 am » |
|
Not every company in Japan. Pretty much just a few of the larger ones, who could afford hardware R&D.  Bandai, Konami, Namco, Sunsoft, Irem, Jaleco, Taito. Capcom is the one NES publisher I can immediately think of that I'm surprised didn't use custom mappers, considering they're a major arcade developer. Okay, I guess Hudson is another surprise. Actually, I guess there were quite a few mappers if varients included. Do we count the multiple MMC3 varients? 
|
|
|
|
Lindblum
Guest
|
 |
« Reply #6 on: January 28, 2009, 12:05:02 pm » |
|
I've faced translation size issues, but I don't know if they're related to yours. NES can only have one 32kB bank of ROM loaded at a time to PRG-ROM ($8000-$FFFF). In a text-dedicated bank I'd expect to see the text arrays (as you've found via relative searching), preceded by the text pointer arrays. Though it depends on implementation, you can sorta recognize pointer arrays like: XX 81 XX 81 XX 82 XX 84 XX 84 XX 84 XX 87 ...
In the example every 2 bytes is a big-endian address to where the text will be loaded in to PRG-ROM, each pointing to the next consecutive text string, so the address value keeps ascending. If you know where something is in ROM you can calculate where it will appear when it appears in PRG-ROM, and then you will know what its address bytes will be. If you talk to someone, the game may load a bank number and pointer array index. If you figure out how, then you can move this person's line to a bank with free memory to hold it, except you'll have to add another pointer into that bank's array, and adjust all the other pointers there because the new pointer shifts all the preexisting text by 2 bytes. WHEW! Whatever you took from that, you have to have a process for matching lines with their pointers, and for correcting the pointers when you insert custom text.
|
|
|
|
RedComet
Guest
|
 |
« Reply #7 on: January 28, 2009, 12:42:11 pm » |
|
My advice: find an existing bank that has enough free space and stick your text there. Then you just have to hack the code to swap banks to read text from the new location. No expansion necessary. This is really effective if you combine it with compression (MTE and huffman, ftw, baby). 
|
|
|
|
KingMike
Guest
|
 |
« Reply #8 on: January 28, 2009, 02:03:08 pm » |
|
Might be a bit tough. If the dialouge reading routine is not in the fixed bank ($C000-FFFF in many mappers, but it's only $E000-FFFF in Namco-106 (which MT2 uses)), you'll need free space in the same offset within the bank. (such if the code were at ROM $1000 and you were swapping the bank at $10000-11FFF in, you'd need free space at $11000 ($1000 bytes into the bank), since as soon as you write to the bankswap register, the bank will swap and you want to be sure the new contents at the PC (program counter) are working code) (so like if the instruction writing to the bankswap register was at $1006-1008, you'd want to continue the dialouge routine at $11009).
|
|
|
|
gamingjustin
Guest
|
 |
« Reply #9 on: January 30, 2009, 03:05:12 pm » |
|
Just want to say thanks for all the suggestions and help. I have to say, though, that "newbie" doesn't even begin to describe my lack of familiarity with rom hacking/programing! I was able to figure out the table stuff-- a big achievement for me-- to get the dialog/text to translate, but that might be as far as I can go for now. With each successive post I read I came closer to the realization that, man, this take some serious dedication and work-- gotta know the game backwards and forwards, inwards and outwards. I sorta thought I could just plop the text back in!
So with that said, I appreciate the help, it's interesting to read and I might come back to it some day with a fresh attitude and more knowledge under my belt. I might pick at this project some more, but it's mostly personal and I was curious to see what translating a game entailed. Thanks.
|
|
|
|
Ryusui
Guest
|
 |
« Reply #10 on: January 30, 2009, 03:21:44 pm » |
|
With each successive post I read I came closer to the realization that, man, this take some serious dedication and work-- gotta know the game backwards and forwards, inwards and outwards. I sorta thought I could just plop the text back in! The corollary to my well-quoted mantra - "anything is possible with enough time, effort and cursing" - is "it's never as easy as you think it is". (Just look at Sylvanian Families for GBC.) This said, I wouldn't say you have to know the entire game that well...just one very specific part of it. You'll also need to find out the details about MT2's mapper: namely, how it handles bank swapping. If worse comes to worse, you may have to use a different mapper. (Changing the mapper a game uses is as simple as modifying the relevant byte in the 10NES header...of course, if the mapper isn't similar to the one the game already uses, you'll have to change the game to suit. This will require that you know the game "backwards and forwards, inwards and outwards". ^_^;)
|
|
|
|
KingMike
Guest
|
 |
« Reply #11 on: January 30, 2009, 04:06:17 pm » |
|
If the OP doesn't know ASM, that'd be the big part.
The Namcot-106 registers are simple: (the CPU registers, anyways) $E000-E7FF is the register for PRG $8000. Write the desired bank number to any address between $E000 and E7FF to swap it in to $8000-9FFF. $E800-EFFF swaps $A000-BFFF. $F000-F7FF swaps $C000-DFFF. Expansion would likely be one of two things. 1) Game is expecting bank value to be ANDed with actual size (noticable if the game is writing values >$1F to the bankswap registers). Expansion is to add 256KB to the beginning of the ROM (after the header). 2) Game is writing real bank values to the bankswap registers. Expansion is to copy the first 240KB, then add 256KB blank space, then copy the remainder of the ROM file (last 16KB program and 256KB graphics ROM). Then update the header (double the value at offset $00004 in the ROM file).
As for headers, I like to take advantage of the huge address space that isn't mapped to ROM or RAM ($0800-5FFF). I modify the pointer reading routine, so that it will check the pointer, and if it is within that address space, process my custom pointer format, bankswap and reload the pointer, and continue with the original code. (what I've before is to use one byte as a bank and the other byte as a string). That way, I can load my custom pointers without making the game crash when it encounters an unchanged string.
|
|
|
|
|