News: 11 March 2016 - Forum Rules, Mobile Version
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia

Author Topic: Adding sprite data to a ROM & modifying color pallettes in attribute tables  (Read 410 times)

spookgoblin

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
Hey guys!

I know I've been posting a lot of these "please hold my hand" type of posts lately (and I'm truly grateful for all your help--it's been invaluable!), but I've got a few fresh problems on my hands and I wanted to plead for your assistance once more.  I put it in my head that I would be getting this ROM completed and dumped to a cart before December, but this isn't a reasonable goal if I'm figuring it out all by my lonesome.

The first issue:
I have modified the logo of the title screen in Castlevania 1.  It's supposed to say "Butlervania" now, but the "C" in the logo is a oddly-shaped sprite with no data in the hollow part of the "C."  I've already got my artwork prepared, but in order to turn that "C" into a "B," the sprite needs to be mostly rectangular.  I'm weary of straight up adding in a new hex data to the ROM because I'm fairly certain there's a plethora of pointers that will get screwed up in the process.  Something tells me the solution, then, lies in ASM--which I have ZERO experience with.  That's where I am hoping to employ the skills of a kind soul whom is far wiser than I.

The second issue:
In changing the logo's text, I had to make the entire thing 16 pixels wider.  This moved the "C" (what will become the "B") 8 pixels left.  In doing so, two 8x8 portions of the sprite nudged its way into another part of the attribute table and fudged with the colors.  I get the basic concept of how these tables work, but I have no idea how to go about finding them in the ROM or changing their values.  Any help in the matter would be fantastic!

Thanks in advance for your help, guys!
You're the best!

Psyklax

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
    • Psyklax Translations
Re: Adding sprite data to a ROM & modifying color pallettes in attribute tables
« Reply #1 on: September 25, 2017, 05:04:04 pm »
I don't really understand the first issue, but I can help with the second.

The attribute table lies after the name table in the PPU's RAM. So if you know where your graphics are in VRAM, the attribute table is just after it. It's changed the same way anything in VRAM is changed: the CPU picks a value, picks the PPU address and writes to it, both using registers. So the debugger is how you find out how the game writes to the attribute table.

Every game does it a different way, depending on the programmers preference. Sometimes, the background uses the same palette for most of the screen, so the code could just say "start at the top, here's the value, now write it to everything". Sometimes a title screen is more complicated, so it says "start at the top, get the values in sequence from this place, and write them one after the other". Castlevania is probably the latter, but the way to find out is to (in FCEUX) make a write breakpoint for the part of the attribute table you're interested in, and see what happens.

First you should mess with the attribute table in the hex editor to see where you need to change it. Just type other values like 00 or FF, and find the part of the screen you need. Set the breakpoint on that, reset and see what happens. Often it's first written with something blank, then changed to the value that's needed. This is where a little assembly knowledge is needed, but it's actually not that complicated.

When it breaks at the point of storing the key value to that address, you can look in the debugger before it and see where that value came from. If you're lucky, it'll say something like LDA $XXXX, with X being somewhere above $8000 (the ROM). Then you can go there in RAM, click "go here in ROM file" and hey presto, you've probably got the list of values for the attribute table. You can try changing these in the ROM and see what happens.

If you need more info about how the attribute table actually works, better to go to nesdev, as I can't explain everything here. :) If anything doesn't make sense, just ask. Actually, I'll take a five minute look at Castlevania now, just to check...

EDIT: Hold on... you just said the SPRITE "nudged its way into another part of the attribute table and fudged with the colors". What? Sprites don't use the attribute table. It doesn't matter where they are on screen, they each have their own palette. Well, I hope what I wrote was informative, but now I don't understand what you mean. :D

EDIT2: Okay, so I changed the background attribute table in five minutes, and figuring out the sprite part didn't take much longer. $1B107 in the ROM is the byte that affects the top left of the C, changing to 0F ensures that moving it left keeps the correct palette. Meanwhile, $1AB9 is the start of the sprites for the title screen, in the same format as it appears in the sprite RAM (though the X and Y positions are modified by the game, as is standard). I don't know what exactly went wrong for you, but I hope this helps a tad.
« Last Edit: September 25, 2017, 06:22:43 pm by Psyklax »

spookgoblin

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
Re: Adding sprite data to a ROM & modifying color pallettes in attribute tables
« Reply #2 on: September 25, 2017, 08:19:20 pm »
Ack!  In the heat of the moment I confused my terms.  Because of how the "C" in the logo is a hybrid of a sprite and BG tiles, I must have muddled it up in my brain and combined them -_-

Either way, what you wrote should be very helpful!  I'll let you know if I have any questions.
Thank you so much!

To clarify what I was talking about for my first little conundrum, here's an image that will hopefully shed some light on things:



This what you see with a ROM where the "C" sprite is partially corrupted and with only the sprites being displayed in FCEUX.  As you can see, there's a 16x16 chunk missing in the center-right (forming a crescent shape).  I need a rectangular shape in order to make a "B."
« Last Edit: September 27, 2017, 02:03:57 pm by spookgoblin »

Psyklax

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
    • Psyklax Translations
Re: Adding sprite data to a ROM & modifying color pallettes in attribute tables
« Reply #3 on: September 26, 2017, 04:25:25 am »
I don't know why the tiles all look messed up (unless you did that on purpose, in which case I STILL don't understand why :) ) but if there's a space, it's because there are no sprites there. The only way you'll get sprites there is to add them, which could be a problem because I'm not sure you have the space to do so. The game is weird in how it cycles each sprite through each sprite slot for some reason, and in the ROM you might be limited for space. Of course you might be able to fill that space with background tiles instead: I'm not sure why they even use sprites for the title. I'll have a quick look later.

EDIT: Now I understand why they used sprites: colour limitations. Backgrounds and sprites can only use three distinct colours in any 8x8 tile (or 16x16 area in backgrounds), plus a universal background/invisible colour. By using them together, you can use more colours in the same space. In your case, you may be able to move some sprites over and add new background tiles or something. Since I don't know exactly what you've done here, I can't say much more.
« Last Edit: September 26, 2017, 06:17:44 am by Psyklax »

spookgoblin

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
Re: Adding sprite data to a ROM & modifying color pallettes in attribute tables
« Reply #4 on: September 26, 2017, 03:18:39 pm »
The image is one I took a while ago--it doesn't reflect what I'm trying to do with the ROM.  The tiles look wonky because I was attempting to track down where the sprites were being rendered.  Turns out I stumbled across the addresses where they were being DRAWN.  Either way, it helped me understand the shape of the sprite so I kept the image.

The only sprites that I'm aware of on the main title screen are the bat and the "C."  I think your recent suggestion might be the ticket, though.  I could probably grab few a sprite tiles from the top/bottom section of the "C" , change it to the middle section of the "B," and move it there.
It will be some time before I can attempt it, but it's a great idea!  Thanks for the tip :)
If I hit another roadblock (or a success), I'll post it up.
« Last Edit: September 27, 2017, 02:04:36 pm by spookgoblin »

spookgoblin

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
I don't know why the tiles all look messed up (unless you did that on purpose, in which case I STILL don't understand why :) ) but if there's a space, it's because there are no sprites there. The only way you'll get sprites there is to add them, which could be a problem because I'm not sure you have the space to do so. The game is weird in how it cycles each sprite through each sprite slot for some reason, and in the ROM you might be limited for space. Of course you might be able to fill that space with background tiles instead: I'm not sure why they even use sprites for the title. I'll have a quick look later.

EDIT: Now I understand why they used sprites: colour limitations. Backgrounds and sprites can only use three distinct colours in any 8x8 tile (or 16x16 area in backgrounds), plus a universal background/invisible colour. By using them together, you can use more colours in the same space. In your case, you may be able to move some sprites over and add new background tiles or something. Since I don't know exactly what you've done here, I can't say much more.

Okay, so at the very least, I know that the PPU addresses I'm looking for are:

$23C1
$23C9
$23D9

But I haven't been able to track down the ROM address using the method you described.  I found a line in the debugger that said:

LDA $00FE = $1E

But I couldn't navigate to the ROM address by going to $00FE in RAM and right-clicking as there was no "Go to in ROM" option at those addresses :O
Any ideas?

Psyklax

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
    • Psyklax Translations
I found a line in the debugger that said:

LDA $00FE = $1E

But I couldn't navigate to the ROM address by going to $00FE in RAM and right-clicking as there was no "Go to in ROM" option at those addresses :O
Any ideas?

Well first of all you need to know how the NES's RAM works: $FE is in zero page, and is part of the NES's working RAM, i.e. what it uses to do stuff during a game. From $0000 to $07FF is the 2KB internal RAM, and everything between that and $2000 is just a mirror of it. So of course you can't "go to in ROM" there because that's not the ROM. :) The ROM is located between $8000 and $FFFF: which part of the ROM depends on what the mapper has given to the RAM at that moment. This is a quirk of the NES hardware, that it only has 32KB available for the ROM so to use more you need to swap it in and out (this is for the program (PRG) but the same restrictions apply for the character (CHR) ROM too - except that's just 8KB). Check this for details:

http://wiki.nesdev.com/w/index.php/CPU_memory_map

Okay, let me look at those three PPU addresses you gave and see if I can find them in the ROM for you.

So I write click on $23C1 in PPU RAM and set a write breakpoint to find out how $AA got there. Reset... first $FF is written to it, so I click Run, and next I see $AA is written to it: in the debugger it says "STA PPU_DATA", which means "store what's in A to the PPU_DATA register", which is the register the CPU uses to write things to PPU RAM. So how did $AA get in the Accumulator (that is, A)? Well, look directly above it:
LDA ($01),Y @ $B0F5 = #$AA
This means "load the Accumulator with a byte, and get the address for it by reading the address at $01 and adding Y to it". Now, this might sound confusing, so let's look at the screen.

We can go to $01 in CPU RAM and see that it has $C4, and $02 has $B0. Because the CPU is little-endian, it means the least significant byte goes first. In practice, that means we swap them. So $C4B0 becomes $B0C4. So the command says "go to $B0C4 plus Y". The debugger tells us that Y currently contains $31. What's $B0C4 plus $31? Why, $B0F5 of course, which is what is written in the debugger - as well as it telling us that $AA is what it found there.

So we now go to $B0F5 in CPU RAM and find $AA, surprise surprise, but we come across a problem. We only want to change $23C1, but if we look around it, we see $AA in $23C0 to $23C7, but at $B0F5 we only see one $AA. This is because the program is written to say "write $AA here, and do it 8 times". So if you wanted to change one of those $AA bytes, you'll need a bit more work. And it's getting late so I'll leave that for now. :D

Anyway, where is $B0F5 in the ROM? Well, go there in RAM, right-click "go here in ROM file" and it's at $1B105. Change $AA to, say, $FF, reset, and voila: the top part of the screen has gone all green. Now you see why the program told to write $AA all along the top: it's where those big grey squares are.

Which means I have to ask: are you sure you want $23C1? The others maybe, but that one doesn't seem to affect your new title.

Anyway, I'm tired now... I hope I've got you started though. :)

(P.S: I wrote all of the following before I realised that those three PPU addresses you mentioned were in the attribute table, not the name table. Now, it may be useful to you, or not... but I spent a while writing it so I'm not gonna delete it if it might be useful :D )

First of all, understand the difference between background and sprites, because they are very different indeed. The current background is stored in the PPU RAM between $2000 and $2FFF in the form of a nametable. When a value is placed here, it references something in the pattern table (between $0000 and $1FFF) which is where the graphics are located. Sprites, on the other hand, are located in object attribute memory (OAM) which is apparently part of the PPU but for some reason appears at $200 in the CPU RAM. I don't know why, I just roll with it. This has four values: X and Y position, the tile number (again, referring to the pattern table) and a byte for attributes (flip horizontal or vertical, for example). I'll give you this link before I continue:
https://wiki.nesdev.com/w/index.php/PPU

Let's say you know there's a background tile at $23C1 that you want to replace with something else (this is just an example, not necessarily what you're doing). I go to $23C1 in PPU memory in FCEUX and see, for example, $C2. Now, the program told the PPU to put that there: the CPU reads the program, and sends the info to the PPU through registers (i.e. it first picks the address - $23C1 - and writes it to the address register, then picks the tile - $C2 - and writes it to the PPU writing register. So, we need to know where in the code is the instruction to say "put $C2 at $23C1". Now, for a title screen graphic with lots of tiles, you'll probably just find a list of tiles and it writes them one by one from the upper-left of the screen, because it's easier. But anyway, I can right-click and set a write breakpoint for $23C1 in the PPU RAM and it'll break whenever that address is written to.

So I reset the NES and of course it breaks, probably because it writes $00 to it to clear the screen. But at some point it will break because it's writing $C2 to it. So I look at the debugger to see where that $C2 came from, and as I said in a previous post, if you're lucky, it'll say it loaded the Accumulator with $C2, and it got that from somewhere between $8000 and $FFFF - the ROM. If you're unlucky, it'll say somewhere lower than that, meaning you have to do a write breakpoint to THERE and find out how it got THERE.

Sprites are a different kettle of fish, because obviously they're not so static: they can fly all over the place, and so they may be in the ROM slightly differently, but it's still possible to find them, of course. This time you'll want to figure out which sprite you're looking for in the $200 to $2FF section and set a write breakpoint to the byte that tells you the tile. Same process as the background tiles from there, pretty much.

EDIT: I just re-read my first post in this thread: I already told you where in the ROM to find this stuff... and about the ROM being above $8000. Well, hopefully you can now figure out how I got there. :D

spookgoblin

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
Wow, Psyklax!
Thanks for all the info.  I appreciate your willingness to help me understand :)
I've not had a chance to put any of this into practice, but I think I get the bulk of your explanation.  Hopefully I'm able to connect the dots and get where I need to go!
Stay tuned!

Psyklax

  • Sr. Member
  • ****
  • Posts: 389
    • View Profile
    • Psyklax Translations
Wow, Psyklax!
Thanks for all the info.  I appreciate your willingness to help me understand :)

That's what I'm here for. :) I'm a teacher in real life, so I just like to help people learn ROM hacking since I know how to do it myself.

As I mentioned in the post, the latter part was written before it occurred to me that $23C1 is the attribute table, and that, after all, was the title of your thread. It may be useful too, but if you've got this far, it may all be obvious stuff. But I imagine the debugging stuff will be of great help to you. :)