HDMA Sprite demo not working...

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

HDMA Sprite demo not working...

Post by Drew Sebastino »

Sorry, for posting some thing like this, but I am starting to grow frustrated with trying to change different sprite attributes while the screen is being rendered with HDMA. I have created a code that clearly doesn't work as shown bellow that uses the "Walker" demo from the SNESstarterkit as a base.
Strange.png
Strange.png (1.15 KiB) Viewed 3995 times

Now here is the code behind it:

STZ $420C ; stop HDMA from last frame
LDY #$0404 ; information about the transfer and where to transfer (both bytes being 04 is just a coincidence)
STY $4310 ; CPU -> PPU, auto increment, 4 bytes
LDY #HDMASpriteTable
STY $4312 ; source offset
LDA #$00
STA $4314
LDA #$02
STA $420C ;start HDMA transfer

Now somewhere else in the code...

HDMASpriteTable:
.DB $90,$70,$A0,$00,$30
.DB 0

Now if anyone knows what's wrong, don't hesitate to tell me.
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Re: HDMA Sprite demo not working...

Post by Bregalad »

Sorry, for posting some thing like this, but I am starting to grow frustrated with trying to change different sprite attributes while the screen is being rendered with HDMA.
This is simply not possible to do I guess.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

So there is nothing wrong with what I wrote, It's just that the SNES doesn't accept you doing it? I guess that's why I've never seen it done before.
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: HDMA Sprite demo not working...

Post by 93143 »

http://problemkaputt.de/fullsnes.htm#sn ... ryaccesses
So, aside from the 256 known/used dot-cycles, there may (or may not) be up to 84 unused dot-cycles... possibly allowing to change OAM during Hblank(?).
http://problemkaputt.de/fullsnes.htm#sn ... attributes
During rendering, the PPU is destroying the Address register (using it internally for whatever purposes), after rendering (at begin of Vblank, ie. at begin of line 225/240, but only if not in Forced Blank mode) it reinitializes the Address from the Reload value; the same reload occurs also when deactivating forced blank anytime during the first scanline of vblank (ie. during line 225/240).
viewtopic.php?f=12&t=6758#p65562
Your write during Hblank will end up going to the high attribute table address of the last sprite the S-PPU fetched. Even if you hit a patch of empty scanlines, the address is still the last sprite fetched. Rewriting OAMADDR during Hblank will not help you.
It's not known to what extent you can modify OAM during HBlank, but it's very tricky at best; Uniracers is the only game that does it.

...

Also, doesn't that code write one byte each to OAMDATA, BGMODE, MOSAIC, and BG1SC without writing to OAMADDL/OAMADDH first? I don't think there is an HDMA mode that writes four bytes in a row to one register, and it seems you can only turn off auto-increment with general-purpose DMA...

EDIT: switched first two links to match the quotes.
Last edited by 93143 on Sat Nov 29, 2014 8:57 pm, edited 1 time in total.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

93143 wrote: It's not known to what extent you can modify OAM during HBlank, but it's very tricky at best; Uniracers is the only game that does it.
But what you are saying is that you CAN at least modify sprites in some way using HDMA? And, If Uniracers DOES do it, why does it? It is not like it's a bullet-hell game or anything. Oh, and how did you even know that?
93143 wrote:Also, doesn't that code write one byte each to OAMDATA, BGMODE, MOSAIC, and BG1SC without writing to OAMADDL/OAMADDH first? I don't think there is an HDMA mode that writes four bytes in a row to one register, and it seems you can only turn off auto-increment with general-purpose DMA...
I had been lead to believe that writing #%00000100 to $43x0 would mean I would be able to write 4 different bytes to OAM (1st being x location, 2nd being y location, 3rd being character data, and 4th being palette, flip, and priority data)instead of writing to 4 different 21xx registers. Also, I already wrote to $2101 so the SNES would know where to look for the tile data, otherwise, the sprite wouldn't have even appeared (unless I need to write to It again right before the transfer.) Finally, What do I even need to write to $2102? You can probably tell that I'm no programing genius.
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: HDMA Sprite demo not working...

Post by 93143 »

Espozo wrote:
93143 wrote: It's not known to what extent you can modify OAM during HBlank, but it's very tricky at best; Uniracers is the only game that does it.
But what you are saying is that you CAN at least modify sprites in some way using HDMA? And, If Uniracers DOES do it, why does it?
Not even byuu knows that. All he knows is that he has to emulate writes to HiOAM as he described in the post I linked; otherwise Uniracers doesn't work.

As he says, sprite size and X-position high bit aren't a very useful thing to be able to write to...
I had been lead to believe that writing #%00000100 to $43x0 would mean I would be able to write 4 different bytes to OAM (1st being x location, 2nd being y location, 3rd being character data, and 4th being palette, flip, and priority data)instead of writing to 4 different 21xx registers.
You can't write to OAM. You can only write to a register ($2104) that's designed to copy the value you write to it into OAM at the location you specify in $2102-03 - or not, if OAM is locked/otherwise occupied. VRAM and CGRAM work the same way.

Writing %0xxxx100 to $43x0 sets HDMA to write to the target B-bus address ($04 in this case), then the one above it, then the one above that, then finally one more above that. For a similar example, if you want to change CGRAM with HDMA, you'd set $43x0 to %0xxxx011 or %0xxxx111, with the target being $2121. That way, you write the target CGRAM address to $2121 (twice, but what other choice do we have?) and then the colour data to $2122.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: HDMA Sprite demo not working...

Post by tepples »

Espozo wrote:And, If Uniracers DOES [modify sprites during the picture], why does it? It is not like it's a bullet-hell game or anything.
Just a guess, but split screen usually means you need to keep sprites from penetrating from one player's view to the other's.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

So I finally fixed my code to where I'm not writing to 4 different registers and surely enough, the game was back to normal as in the background was fixed, but nothing happened sprite-wise (in zsnes, no sprites would even appear on the screen, which really shows how "accurately" it emulates the SNES). After reading what byu said changing OAM using HDMA and how the values go wherever they want to, It seem overly complicated and not really worth it. Also, what is force blank? does the screen get shut off while its rendering and allow you to write some values over again? I heard byu say it's how Super Mario Kart is able to change all the sprites around. Lastly, can force blank happen more than once and how do you set it up?
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: HDMA Sprite demo not working...

Post by 93143 »

Espozo wrote:It seem overly complicated and not really worth it.
I suppose that would depend on what you managed to get it to do. The bullet hell form of this trick would be epic, but I'm not sure it's possible, and even if it is it might be prohibitively finicky...
Also, what is force blank? does the screen get shut off while its rendering and allow you to write some values over again? I heard byu say it's how Super Mario Kart is able to change all the sprites around. Lastly, can force blank happen more than once and how do you set it up?
http://problemkaputt.de/fullsnes.htm#snesppucontrol

Force blank (or forced blank) is just the state where bit 7 of $2100 is set, meaning the display is turned off. Rendering doesn't happen, and a black signal is sent to the TV. In this state, you can send data to VRAM, CGRAM and OAM freely, as if the screen were in vertical blanking (though it's been suggested there might be a delay before VRAM opens up, which I suppose might apply to OAM too). You can do this whenever you want, on an interrupt or whatever, just by writing to $2100. I imagine you could even set up HDMA to do it...

http://wiki.superfamicom.org/snes/show/Registers
Note that force blank CAN be disabled mid-scanline. However, this can result in glitched graphics on that scanline, as the internal rendering buffers will not have been updated during force blank. Current theory is that BGs will be glitched for a few tiles (depending on how far in advance the PPU operates), and OBJ will be glitched for the entire scanline.
If I recall correctly, the above is why you can't use it during HBlank to force OAM open... or can you? Based on fullsnes, I suspect that if a lot of sprites are present, turning the display off during HBlank would cause the PPU to not do certain critical steps to prepare the sprites for the next scanline, but it looks like the theory is tentative in this area, and I can't recall if there's another reason not to do this.

It has been stated pretty bluntly that force blank during HBlank is incompatible with sprites: viewtopic.php?f=12&t=11920&start=15#p135154
I have a feeling I should know why this is, but I can't think of it right now.

I have noticed that even higan's accuracy core doesn't correctly emulate the effect of turning on the display too late during HBlank (the real system will glitch where higan won't). This is edge case territory, so if you wanted to find anything out you'd have to test on hardware. I might try it myself some time...
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

Well, I tried to turn off the screen using HDMA and this is what I got... (I'm a work in progress)
strange2.png
strange2.png (1.4 KiB) Viewed 3920 times
At least something IS being done with $2100 as there are black bars running horizontally across the screen (that aren't BG's or Sprites).

Again... Here's what I wrote:

LDA #$80
STA $2100 ; Turn the screen back on

STZ $420C
LDA #$00
STA $4310 ; CPU -> PPU, auto increment, write 1 reg, $2100
LDA #$00
STA $4311
LDY #ForceBlankTable
STY $4312 ; source offset
LDA #$00
STA $4314 ; bank address = $7E (work RAM)
LDA #$02
STA $420C ;start HDMA transfer

Later...

ForceBlankTable:
.DB $60,$80 ; Turns off the screen after line $60
.DB 0

Regarding updating everything while the screen is off, how do you arrange everything? Would you put the part that gets updated in force blank between where you turn the screen off and where you turn the screen on? (If that makes any sense) Also, about graphics being messed up after force blanking mid screen, How is Super Mario Kart able to transfer sprite Data using force blank then? I don't see any abnormalities with the graphics.

Lastly, How would you be able to test the games on real hardware? I'm guessing there is some sort of way to burn custom ROMs on an SNES cartridge? I know that there are special carts that people have made that allow you to play games from an SD card like the SD2SNES, but personally, I don't think my mother would let me buy a $200 cart (you have no idea how hard it was for me to convince her to get R-Type III :roll: )
Last edited by Drew Sebastino on Sat Nov 29, 2014 10:58 pm, edited 1 time in total.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: HDMA Sprite demo not working...

Post by tepples »

One cheap way to get started is the INL-HiLoROM flash cart from infiniteneslives.com.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

Thanks for the information. Oh, tepples, while you're hear, can you explain why force blank during HBlank is incompatible with sprites like you said in that one topic I wrote? (sorry for filling up a full post with just this...)
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: HDMA Sprite demo not working...

Post by tepples »

The NES PPU fetches sprite patterns during horizontal blanking. Based on what I know about the Super NES's background fetch pattern, as well as the difference between the 32 sprite and 34 sliver limits, it's overwhelmingly likely that the Super NES PPU does likewise. So you won't get any sprites on the line after the horizontal blanking period in which you forced blanking.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: HDMA Sprite demo not working...

Post by Drew Sebastino »

tepples wrote:So you won't get any sprites on the line after the horizontal blanking period in which you forced blanking.
Will you get sprites on consecutive lines though? Oh, When you were talking about 32 sprites per scan line and everything like that, it reminded me of a question I was eventually going to ask. I know that the SNES has 272 sprite pixels per scan line, but what counts as a sprite pixel? Does the whole width of the sprite count toward the sprite pixel per scan line, or just any tile with information on it? E.g. an 8x8 bullet tile in a 16x16 sprite. Also, do color 0 pixels count toward the sprite pixel per scan line limit in those tiles? Lastly, are pixels from a sprite that is partially off screen count toward the limit?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: HDMA Sprite demo not working...

Post by tepples »

Espozo wrote:I know that the SNES has 272 sprite pixels per scan line
Which equals 34 8x1 pixel slivers. It takes two dots during hblank to fetch each sliver.
but what counts as a sprite pixel? Does the whole width of the sprite count toward the sprite pixel per scan line
Yes. The PPU doesn't know that part of the width is unused until it has spent time fetching all slivers in the width.
Also, do color 0 pixels count toward the sprite pixel per scan line limit in those tiles?
Yes. The PPU doesn't know that the pixels in a sliver are color 0 until it has spent time fetching the sliver.
Lastly, are pixels from a sprite that is partially off screen count toward the limit?
Apparently so, as long as -w <= x <= 256. (Yes, that's <= and not the more efficient < because Nintendo was lazy.) If you want to hide a sprite, put it at (384, 224).
Post Reply