I have a question for anyone who's implemented a PPU for an SNES emu...
I'd like to add filtering like hq2x or whatnot at some point to my emulator, but I don't know how it would be possible to do efficiently.
Basically, the standard SNES resolution is 256x224, which easily scales to 512x448. The problem is all the extra features of the SNES. Modes 5 and 6 push the horizontal resolution to 512x224, and interlace pushes that to 512x448. There's also pseudo-512 mode, which I still don't really understand despite it being explained repeatedly to me. I think that's a mode7 only effect, though. And, most importantly: sprite interlace.
I could get around the 512 width modes 5 and 6 and interlace flag by not filtering modes 5/6 ever, which has the potential to look bad if a game swaps between mode1 and 5/6 often. I could get around the pseudo-512 using the same technique. But the interlaced sprites are the real problem. Although I've only seen one cart ever use them (SNES Test Program), I want to emulate everything. Interlaced sprites work in all video modes, including mode 1, which is usually 256x224. The only way to draw an interlaced sprite properly, is to always use an internal buffer of 512x448. But if I do that, I won't be able to filter the image anymore unless I want to use 1024x896 or better, which is totally ridiculous.
How do other emulators get around these issues? I know ZSNES just doesn't support interlaced sprites at all, but I haven't tried other emulators.
PPU question for SNES emu authors
Moderator: ZSNES Mods
Blues Brothers is the only game i can recall that uses interlaced sprites (intro text). You should try Anomie's PPU Test program.
Super Sleuth supports interlaced sprites for all modes, however modes 5 & 6 are the only modes that render single scan. All other modes render dual scan and subsequently flicker a lot. All frames are rendered at 512 x 448 regardless of what mode is current.
I have no intention of ever adding filters so i can't help you out there.
Basically all even pixels are taken from the main screen and all odd pixels from the sub screen.
Super Sleuth supports interlaced sprites for all modes, however modes 5 & 6 are the only modes that render single scan. All other modes render dual scan and subsequently flicker a lot. All frames are rendered at 512 x 448 regardless of what mode is current.
I have no intention of ever adding filters so i can't help you out there.
Code: Select all
Chapter 9. H-Pseudo 512
9.1 OUTLINE
In modes other than 5 and 6, this function provides gradation between 2 dots which are next to each other horizontally, which changes the color smoothly.
9.2 FUNCTION
This function utilizes screen addition/subtraction. The color constant addition/sub-traction can not be done at the same time that this function is performed.
Good to know another game uses it.Blues Brothers is the only game i can recall that uses interlaced sprites (intro text).
Edit: Holy crap! What in the heck was the guy on who wrote that game?! >_<
I tried the effect out on my copier, and it doesn't appear to flicker. Either it's the TV hiding the flickering really well, or it being virtually unnoticeable that half the lines in the sprite are missing.Super Sleuth supports interlaced sprites for all modes, however modes 5 & 6 are the only modes that render single scan. All other modes render dual scan and subsequently flicker a lot.
The 16x16 interlaced sprite I used looked exactly the same in 512x448 mode5 as it did in 256x224 non-interlace mode0. It could just be my eyes that are deceiving me, though. I don't understand how the screen can be rendered non-interlace, and the sprite as interlaced.
Neat that you always use 512x448 also and still maintain a decent framerate. There's something in my PPU that's just murdering performance...All frames are rendered at 512 x 448 regardless of what mode is current. I have no intention of ever adding filters so i can't help you out there.
Interesting stance on not adding filters... maybe I'll just end up doing the same thing, as I don't see an easy solution to interlaced sprites anyway.
Thanks for the feedback.
Ok, so you would basically split a 512x224 image in half, even vertical lines in one image, odd vertical lines in the other. Then you would put the first image in BG1 and enable BG1 as a mainscreen, and then put the second image in BG2 and enable that as a subscreen, and the result would be the full 512x224 image? That in and of itself should be simple enough to implement, what's going to be fun is all the crazy combinations like mosaic, EXTBG mode7, color add/sub being on and off during the frame, windowing, and all the other fun registers that interact with it.Basically all even pixels are taken from the main screen and all odd pixels from the sub screen.
IIRC we tested this in the other thread. Recall that the SNES normally outputs only one field constantly. Interlace must be enabled on BGs as well as OBJ to properly render 'interlaced' even-and-odd with both fields output. Otherwise you just get the even OBJ lines drawn one frame and the odd OBJ lines drawn the next, but both output on the one field.byuusan wrote:I don't understand how the screen can be rendered non-interlace, and the sprite as interlaced.
Sounds about right to me. Note that on the TV screen each one of those 512 dots is only ~1/3 of a single NTSC color subcarrier cycle, so fine details tend to blend together. If BG1 is solid green and BG2 is solid red, your NTSC TV will just show a solid yellow. And I suspect PAL won't be much better.Ok, so you would basically split a 512x224 image in half, even vertical lines in one image, odd vertical lines in the other. Then you would put the first image in BG1 and enable BG1 as a mainscreen, and then put the second image in BG2 and enable that as a subscreen, and the result would be the full 512x224 image?
Particularly the color math.That in and of itself should be simple enough to implement, what's going to be fun is all the crazy combinations like mosaic, EXTBG mode7, color add/sub being on and off during the frame, windowing, and all the other fun registers that interact with it.
The interesting thing was that I tested in Mode1 with interlace disabled and sprite interlacing enabled. I noticed absolutely no flickering that would be apparent if this were the case. I'll make a better test to confirm, though. I'll make every even horizontal line red, and every odd one green, and see how it gets colored on the screen.anomie wrote:IIRC we tested this in the other thread. Recall that the SNES normally outputs only one field constantly. Interlace must be enabled on BGs as well as OBJ to properly render 'interlaced' even-and-odd with both fields output. Otherwise you just get the even OBJ lines drawn one frame and the odd OBJ lines drawn the next, but both output on the one field.
1/3?? Weird. I would've guessed 1/2. Otherwise, wouldn't 256x224 only show 2/3rds color per pixel? I would imagine that would result in terrible color bleeding making most images look terrible.Sounds about right to me. Note that on the TV screen each one of those 512 dots is only ~1/3 of a single NTSC color subcarrier cycle, so fine details tend to blend together. If BG1 is solid green and BG2 is solid red, your NTSC TV will just show a solid yellow. And I suspect PAL won't be much better.
You also bring up a good point. Should we be trying to emulate the NTSC color better? Obviously if we render 512x224 with your example, we'd have red and green bars that are clearly each well defined. But the developer/artist could have intended us to see yellow there instead...
I definately have reservations about the aspect ratio differences between a TV and a monitor. The effect is extremely apparent in Der Langrisser. The character portraits are 40x48, and they look crushed in emulators, but they widen out to be perfect squares on the TV.
Do a comparison between that and with both interlacings enabled too. When i did something similar, I noticed a difference.byuusan wrote:The interesting thing was that I tested in Mode1 with interlace disabled and sprite interlacing enabled. I noticed absolutely no flickering that would be apparent if this were the case. I'll make a better test to confirm, though. I'll make every even horizontal line red, and every odd one green, and see how it gets colored on the screen.
The SNES master clock is 6 times the NTSC color subcarrier frequency, but the SNES spits out a non-hires dot every 4 master cycles. IIRC, that's why the missing dot every other frame, to change the phase of the subcarrier in relation to the dots.1/3?? Weird. I would've guessed 1/2. Otherwise, wouldn't 256x224 only show 2/3rds color per pixel? I would imagine that would result in terrible color bleeding making most images look terrible.
Mostly, it's just the fine (1-pixel-wide) detail that gets lost, and sharp edges get a bit fuzzy. The same thing happens to regular TV though.
snes9x used to (well, the released versions still do) try to blend the pseudo-hires to make yellow from red+green. And it does look kind of bad if you scale the screen to something that's not a multiple of 512 (at least without good scalers). But we decided with snes9x that if it's that important to somene they can write a NTSC filter mode.You also bring up a good point. Should we be trying to emulate the NTSC color better? Obviously if we render 512x224 with your example, we'd have red and green bars that are clearly each well defined. But the developer/artist could have intended us to see yellow there instead...
OTOH, you could take care of that easily enough with a good scaler and set it to scale to 341x224, 683x448, or whatever gives the right aspect ratio. A bad scaler will probably look worse than the crushed squares, just doubling every 3rd column or something.I definately have reservations about the aspect ratio differences between a TV and a monitor. The effect is extremely apparent in Der Langrisser. The character portraits are 40x48, and they look crushed in emulators, but they widen out to be perfect squares on the TV.