Author
|
Topic: In need of some conceptual help (Read 640 times)
|
Spikeman
Guest
|
|
« on: May 28, 2007, 04:28:02 pm » |
|
The problem I'm having seems simple enough, but I could use a conceptual explanation of how to accomplish my goal (like NC says, concepts help A LOT). The issue: I'm translating some menu names which are displayed as sprites. The problem is that they are displayed as one or two letter pieces, and some of these pieces are reused (see images). (Ignore the other garbled text, that's me trying to change something else, the problem there is that the tilemaps are compressed. I've isolated the compressions routine but I haven't deciphered it yet.) Alright, so I've tried some debugging and finding how it stores what pieces are used where, but I couldn't really find anything. There's plenty of space to store the extra graphics, so I just need to modify where it loads each piece from and what pieces are used (along with X/Y coordinates). Any suggestions?
|
|
« Last Edit: May 29, 2007, 01:08:08 am by Spikeman »
|
|
|
|
Kajitani-Eizan
Guest
|
|
« Reply #1 on: May 29, 2007, 02:48:02 am » |
|
the problem there is that the tilemaps are compressed. I've isolated the compressions routine but I haven't deciphered it yet.)
first things first... you sure it isn't just using the standard GBA LZSS, RLE, or Huffman compression? use a version of VBA that has logging enabled (VisualBoyAdvanceDev.exe is what i have lying around), go to logging, and check the SWI logging checkbox. this should indicate to you any time the BIOS is called to decompress LZSS/Huffman/RLE (among other things). (if you don't see any text at all after checking the box and playing the game for a few moments, you probably don't have the right version of VBA.) you should be able to use this to see when and from where the tilemaps are loaded, using what compression scheme. of course, if they were retarded and didn't use one of those three, this is useless advice next, i would suggest setting a breakpoint on some memory address associated with the sprites of the text you're looking for and figure out where, geographically, in the ROM it's happening. then do a VBA tracer dump and look for code executed from around the parts of the ROM you found using breakpointing. oh yeah, one other thing... is it reusing the *sprites*, or just reusing the letters? i mean, does it somehow have one sprite in multiple places, or multiple sprites whose letters all change when you change one? if it's the latter (i don't even recall if the former is actually possible), are you sure you're not mistaking compressed text for uncompressed text? i forget if you know all this already, and if so, i apologize for only giving generic information that you already know
|
|
|
|
Nightcrawler
Guest
|
|
« Reply #2 on: May 29, 2007, 12:17:34 pm » |
|
So, what am I looking at in the screenshots? I'm assuming, the part you're talking about is the 'EM' that you changed in the first screenshot and it shows up on the second screenshot which you expected to still be in all Japanese. Is that right?
I'm trusting your ability level that the text is indeed sprites which would mean they're stored in a sprite table with x/y pixel specific coordinates which is what it seems like from your post.
Sprites don't have to be the same size. I'm not sure what sizes GBA offers, but it's more than just one. So it could be perfectly normal that one sprite may be the size of one letter and another may be the size of two. Sprite size information should also be in the sprite table.
As for why a sprite appears to be used in more than one place, it's the same concept as reused tiles. You have your sprite table that can keep track of a bunch of sprites. Well, for each sprite, it points to somewhere in VRAM that contains the graphical data to be used for that sprite. It just so happens, you can set it up so say ALL the sprites use the SAME graphic.
So, you could set up the sprite table to display say 64 'EM' sprites all over the screen. It would take up no more VRAM space than just storing 'EM' ONCE.
It's just like tiles and a tilemap really. No difference other than the sprite table is more complex because it contains more information than a tilemap and you can do more with sprites.
So, the hack is going to be along the same lines as if it were tiles. It's two fold. First, you need to make sure all the graphical data is loaded. Second, you'll need to make sure the correct sprites in the sprite table point to(or are set to use) the graphical data you want them to.
The first thing you can do before jumping in head first is to learn a bit about the GBA sprite table if you haven't already and see if my assessment is correct. You'll know this by looking up data for the 'EM' sprites that are used in the two screens. If I was correct, you'll find they both point to via index the same spot in VRAM thus using the same data, but still being two different sprites.
|
|
|
|
Spikeman
Guest
|
|
« Reply #3 on: May 29, 2007, 05:03:58 pm » |
|
I've isolated the code that loads the sprites, but what it seems to be doing is loading the tiles for the sprites on that menu screen and then creating the sprites. It does this for each screen. So in short, the tiles don't end up being stored in the same place in VRAM.
Also, you're right about the different sprite sizes, and as far as the reused parts go it's a little strange. For example say three menus are "ITEMS", "EMAIL", and"MAP" (not actually, this is just an example, it's really in Japanese). One part of the graphics data would be stored as "EMA", and the "EM" would be loaded and used as a sprite in "ITEMS" and "EMAIL", and the "MA" would be used in "MAP". The sprites are almost all one or two characters, but there may have been one that was bigger. Another issue is that the English characters are 8x16 and the Japanese ones are 16x16, so I'll need to resize some of the sprites.
I know how the GBA stores sprites (I think this is what you mean by "sprite table"), but the thing is I can't figure out how the game stores the sprites. I'm pretty sure it loads them by DMA (which I know enough about), so would they be stored the same way they're stored in the sprite table?
|
|
|
|
KaioShin
Guest
|
|
« Reply #4 on: May 29, 2007, 05:14:30 pm » |
|
I know how the GBA stores sprites (I think this is what you mean by "sprite table"), but the thing is I can't figure out how the game stores the sprites. I'm pretty sure it loads them by DMA (which I know enough about), so would they be stored the same way they're stored in the sprite table?
DMA doesn't alter the data, so yes, it should be in ROM exactly like it appears in RAM, unless it wasn't DMA'd but uncompressed or sth. But I guess they wouldn't compress single tiles, pretty pointless.
|
|
|
|
creaothceann
Guest
|
|
« Reply #5 on: May 29, 2007, 05:49:58 pm » |
|
Couldn't it be copied to RAM, decompressed there and then uploaded to VRAM?
|
|
|
|
Tauwasser
Guest
|
|
« Reply #6 on: May 30, 2007, 03:44:11 am » |
|
That's usually it. Most gba games use a sprite-builder type of thing. Instead of having each and every x/y value and palette defined for the whole sprite, they just generate sprites in wram and then dma to oam. When I look at your screens, you probably didn't resize the sprite for "I" (in ITEMS), did you? If so, your spritebuilder probably takes into account the width information for each letter. So you might want to either set a breakpoint in the width table (if the game has that...) or look for when certain registers contain 0x08 or 0x10. No$GBA offers that function. On the other hand, you can totally dismiss all this and trace back from the dma source. Say, you load the screen the first time and catch where it dma'd from. Then you exit and set a breakpoint to that wram location. No you enter the screen again and should also be somewhere in the code for building these sprites. Then you can figure out what it loads when and how and where from cYa, Tauwasser
|
|
|
|
Nightcrawler
Guest
|
|
« Reply #7 on: May 30, 2007, 08:48:05 am » |
|
Ok, so the sprites are created on demand and the data is loaded in to VRAM then. So, what you need to do is find out how it determines the source data to load for that sprite. You'll want to change the source data for the second sprite that loads the unwanted 'EM'. Tauwasser's got it. You're just going to have to keep working backwards based on what you know. When I said sprite table, I was referring to the OAM table. That's the final table sprite data ends up on. It's the one which the system accesses to actually make the magic happen on screen. Go backwards from there. Find out how that data gets into the OAM table. As mentioned, DMA was probably used. You'll find that data came from RAM somewhere. Then find out how that data got there. Was it decompressed from somewhere? Loaded from somewhere? Perhaps moved from another location in RAM? Or perhaps even pieced together by an algorithm? Don't be too fixated on expecting to find a certain thing or you may miss what's actually occurring. Keep moving back and you'll get it. That's the time consuming hard part of course.
|
|
|
|
Spikeman
Guest
|
|
« Reply #8 on: May 31, 2007, 12:34:37 am » |
|
It looks like what Tauwasser said is right, it creates all the sprites in RAM and then DMAs them all into OAM. I found the chunk of code that sets up each sprite in the RAM, but what I'm having trouble finding is where it sets up the registers that that routine takes. It seems to do all the sprites at once, in a loop. Multiple places load the values into place, most likely because the some sprites are the same sizes. I think my problem is not knowing enough debugging theory. I'll check the documents again, but any recommendations?
|
|
|
|
Tauwasser
Guest
|
|
« Reply #9 on: May 31, 2007, 04:28:04 am » |
|
http://nocash.emubase.de/gbatek.htmThere you go. All you need to know about OAM data. Also, you're probably stumbed because the game loads all the data from RAM as well, right? It usually goes like this: Game loads data offsets etc to ram, calls routine, routine reads from ram and writes oam data to ram, dma to oam region. Just set conditional write breakpoints (I think they do exists) and you'll find the code that loads certain things in no time Usually first you'd want to find out how the text is stored. Like, what format tells the game to use the "MS" tiles. Then you need to find out when the respective data is written to ram and only then you can attempt to edit it I hate gba for that exact reason, everything is nested into each other so it's really hard to find anything missing the main loop and stuff :-/ cYa, Tauwasser
|
|
|
|
Spikeman
Guest
|
|
« Reply #10 on: June 01, 2007, 04:46:12 pm » |
|
Thanks guys! After around another 2 hours of debugging I finally found where one part of the data was stored and led to the rest of it! The strange thing was that the two pieces of data that represent the size and shape of the sprites and the x-coordinate, where ORed together, and the size/shape were stored as an index of what I call "canned" sizes, a list generated when the game is loaded. So it was pretty crazy, but I finally found out how the data is stored, I'll post screenshots when I put in the new titles.
|
|
|
|
|