So anyway, I've been sort of crapping around with SNES code in order to build my understanding of how this works and possibly eventually make my own game for lulz (Flappy Bird, anyone?)There's a lot of helpful stuff on the superfamicom.org wiki to read about which has made it a lot easier for me.Anyway, one thing I'm finding it especially difficult to grasp an understanding of is how you can display sprites on the screen. For example, how would I add just a stationary sprite to, say, the "walker" demo found in Neviksti’s Snes Starterkit?So I make a borderless 32x32 pcx image and then run it through PCX2SNES and then get the .clr and .pic files.I then know I'm supposed to add it to the bottom of my .asm file like so:

After spending a day or so studying the code, looking at other relevant code in other examples and reading stuff on superfamicom wiki, I can't really understand what exactly to do to just display my sprite stationary on the screen somewhere.I know there are sprite numbers, but how do I assign a number? In the walker example, the main sprite appears to be put onto the screen using the following code:

;setup the video modes and such, then turn on the screen JSR SetupVideo

It looks like the sprite number is #$54. If I change it to #$53 or 55, the walking guy sprite just disappears while I expected it to show a different sprite instead. Obviously there's more to it that I haven't been able to figure out by studying or trial and error. Can anyone help me with this?

My goal is to just get any sprite to appear in the walker example just so I can understand what exactly has to be done to do this again in a game of my own.

In short, you should have a section of RAM that represents what you want the contents of OAM to be, and then during NMI/Vblank (or force blank, where the display is turned off) you upload that RAM copy into the actual OAM.

There's actually two tables. The first is 512 bytes and each sprite gets four bytes. This is where you select the sprite tile to use, X and Y position, and most attributes. The second is 32 bytes (called the OAM high table) and represents four sprites per byte. You'll need this to set the sprite size and allow it to go partway off the left side of the screen.

By the way, the register at $2101 is how you tell the PPU where in VRAM your sprite tiles are stored.

Edit: By sprite numbers do you mean the OAM index, or the sprite tile? The sprite tile can be considered as the Nth tile into a 128x128 graphic region of sprite graphics. As for the OAM index, that is up to you.

By writing to the registers mid-frame, I didn't mean that I wanted sprite changes to take effect mid-frame. dougeff's post implied that you could upload OAM whenever, but be able to control when the newly uploaded OAM table is applied, so you'd only upload the 32-byte high table in the NMI routine and it'd work the same but you'd be doing it faster.

In short, you should have a section of RAM that represents what you want the contents of OAM to be, and then during NMI/Vblank (or force blank, where the display is turned off) you upload that RAM copy into the actual OAM.

I understand that much. There's a low byte and a high byte. These contain data for the table having to do with telling the system how to use my sprite. As seen on the given link, it shows the record format for the low table and the high table and what the values are. But I can't find where they did this in the walker example.

By random guessing it looks like in the walker example, this is how they assign the high table, using the address you said:

So A3 converted from hex to binary is 10100011 or 163 in decimal. It's supposed to contain bits from the first byte of the low table? Right? According to this link this means that the sprite size is 101 which is 32x32 or 64x64 which makes sense. Not sure how to interpret the 011 at the end. Its "base selection bits" which is 3. Hmm. The sprite in question starts at $6000 and is #$2800 in size so that can't be it. How does register 2101 tell the PPU where the sprites are stores again? I don't understand.

So in the current code, the OAM address for the sprite I presume is being added is 0, So I would redo that whole bit of code to add a second sprite except set 2102 and 2103 to 1 instead of 0 for sprite ID 1? But where is the part that says where the VRAM address and range is?Here is all the code I have at vblank and below:

Where on here is there any evidence of setting up the low table or high tables like in the link you provided? Is there an example somewhere where someone has programmed 2 independent sprites that I could look at and contrast that vs this? I'm sure I would be able to figure it out on my own if I had one of those but until then I'm trying to decode how it's done from here.

But thanks everyone for the help so far I hope I'm eventually able to figure this out.

I understand that much. There's a low byte and a high byte. These contain data for the table having to do with telling the system how to use my sprite. As seen on the given link, it shows the record format for the low table and the high table and what the values are. But I can't find where they did this in the walker example.

Be careful not to confuse low byte and high byte with low table and high table. Those are two different concepts.

Xeraster wrote:

By random guessing it looks like in the walker example, this is how they assign the high table, using the address you said:

This doesn't affect the OAM table, it's just telling the PPU where the sprite graphics are stored in VRAM, which is a separate section of memory from OAM.

Quote:

Its "base selection bits" which is 3. Hmm. The sprite in question starts at $6000

So you uploaded the sprite graphic to word address 0x6000? Be careful, as the VRAM address registers go by word address, not byte address. Be careful not to upload to the wrong region. But in this case if it's at word address 0x6000 then you have the base selection bits set correctly.

Now here's the thing: In the OAM data format, the third byte of form 'cccccccc' is a tile offset, not an address offset. So to display the sprite graphic you uploaded to word address 0x6000 you should use 0 for this byte.

Quote:

So in the current code, the OAM address for the sprite I presume is being added is 0, So I would redo that whole bit of code to add a second sprite except set 2102 and 2103 to 1 instead of 0 for sprite ID 1?

You don't need to do this by hand. The OAM DMA transfer will send all the sprites for you in one go.

This does the actual DMA transfer to OAM. See the value that's getting stored in $4302? That's the address in main RAM of what gets sent to OAM. In this example it's hardcoded to 0x400. I'm not sure why. It's probably an error in the example. It should probably refer to the SpriteBuf variable label mentioned in previous code snippets. So the SpriteBuf is where you want to make your changes.

This does the actual DMA transfer to OAM. See the value that's getting stored in $4302? That's the address in main RAM of what gets sent to OAM. In this example it's hardcoded to 0x400. I'm not sure why. It's probably an error in the example. It should probably refer to the SpriteBuf variable label mentioned in previous code snippets. So the SpriteBuf is where you want to make your changes.

OOOOH that $0400 thing makes sense now, because in the SpriteInit section, SpriteBuf1 is defined as $0400, so it's the same. So in order to code a second sprite, I could use write the 4 bytes of data starting with $0404. But then I have to use the high table to write the next parts and it's 2 bits per sprite, just like you said in the very first thing you said when you first replied to this thread.Now the first sprite writes #$54 to $0600 aka SpriteBuf2. For a second sprite, would I want to use #$55? Because in binary that's already 01010100. There's already 2 BG layers which logically I would expect to use up the first 2 bits. Then the 1 working sprite I already have which should be occupying bits 5 and 6 (0 for x coord 9th bit, and 1 for large sprite size), so #$55 would make it 01010101, giving my desired 2nd sprite 0 for bit 7 and 1 for bit 1. Right?

Also, once I do that, I should be able to go the part where it does the DMA transfers. But then instead of writing $0400 to registers $4300 and $4302, it would be $0404 and I would set the OAM address to 1 on registers $2102 and $2103. Is this a correct assumption?

I know I'm a noob but thanks for taking the time to help me so far.

EDIT: I'm trying to do that idea I just wrote about. It almost works except I still don't know how to use the sprite I put in the VRAM at $9000 AND it messes up the background into glitchy weirdness. BUT HEY, I got a second sprite to display. NOW I'm starting to get somewhere! (almost)

You did mention that the DMA OAM transfer is supposed to send all the sprites in one go. I couldn't get that to work (because I'm probably doing something wrong). So I just have 2 of those DMA transfer sprite data blocks. Here's what it looks like:

That DMA to OAM code is already there in the VBlank handler, so you don't need to write it again elsewhere. You'll notice in the comments that the number of bytes it transfers is 0x220, which is the full size of OAM, hence it transfers all sprites.

Since you mentioned that SpriteBuf1 is at 0x400 and SpriteBuf2 is at 0x600, then SpriteBuf1 must correspond to the low table and SpriteBuf2 the high table. While you're still getting the hang of the OAM format, I would suggest just playing with the low table for now and then learning the high table later. But for sprite number 0, you'd change the low table at the first four bytes in SpriteBuf1, and the first two bits (first byte) of SpriteBuf2. For sprite number 1, you'll change the low table at SpriteBuf1 + 4, and for the high table it's still the first byte of SpriteBuf2.

Now might be a good time to learn about how index addressing works. The idea is you set the X index register to, say, 4 (a four byte offset, or sprite number 1), and then use code like the following to do the store:

There's already 2 BG layers which logically I would expect to use up the first 2 bits.

No, the BG layers have nothing to do with OAM. It's all sprites. Remember, the S-PPU is fixed-function; you can't trade sprites for BG layers. You get 128 sprites no matter what. You can't even turn off sprites, except by moving them offscreen.

Count the entries. There are exactly 512 bytes in low OAM, four bytes for each sprite. There are exactly 32 bytes in high OAM, with four sprites to a byte. That's 128 sprites.

EDIT: Sorry if that sounded condescending. I'm feeling a bit harried right now for unrelated reasons, and I was trying to make the point as clear as possible.

Who is online

Users browsing this forum: No registered users and 7 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum