(pseudo-)hires query

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

Post Reply
byuu

(pseudo-)hires query

Post by byuu »

I was recently trying to emulate pseudo-hires, and at the same time properly emulate true hires mode, but I ran into some problems with the color output.

Ultimately, I went with the same implementation snes9x / Super Sleuth uses: blending the even and odd pixels together and reducing the width back to 256 for pseudo-hires mode. Now, obviously the SNES isn't doing this... so what I'm wondering is if anyone has been able to come up with a better formula for matching the TV output, or if anyone wants to work with me on coming up with a better one than is being used now. I've already read all the old snes9x forum posts on this. The discussion seemed to just die with no real consensus on the best way to do this. Also, does anyone know what the problem with Kirby 3 is? I obviously can't test the game myself to see if I have it right :/

I'm also curious about true hires. I read somewhere where anomie mentioned that hires was the same as pseudo-hires, and the renderer just "skips" every other pixel.
So a tile with pixels 0-7 would actually render 0, 2, 4, and 6 to both the main and subscreens as appropriate.
However, I believe that the SNES renders 0, 2, 4, and 6 to the mainscreen, and 1, 3, 5, and 7 to the subscreen, thus actually truly rendering at 512 pixels, at least internally. Otherwise, blending the pixels back to 256 pixels would just make hires text in games look like ass.
Does anyone know for sure which method the SNES uses here?

Some screenshots for reference:

Image
SD3 when pixels are filtered back down to 256-width. Notice how much more difficult the text is to read... it appears cleaner on an NTSC TV, at least to me... note this is with the video card doing the resizing due to the window size. Doing it in software like pseudo-hires would be slightly more blurry.

Image Image
With pseudo-hires enabled (left), with pseudo-hires off (right).
That's pretty close to the TV effect (the TV effect is a little brighter)... but again, that emulation will screw up things that actually rely on the increased resolution, such as text and high-resolution textures.

Image
Another pseudo-hires example...
Reznor007
Lurker
Posts: 118
Joined: Fri Jul 30, 2004 8:11 am
Contact:

Post by Reznor007 »

Not that this is much help, but here's some screenshots from MESS from SD3 from the title screen and the text screen. The screenshots change from 256x225 to 512x225 (I think 225 is just a WIP thing while the emulation is being updated).

http://members.cox.net/rdawkins1/snes.zip
creaothceann
Seen it all
Posts: 2302
Joined: Mon Jan 03, 2005 5:04 pm
Location: Germany
Contact:

Re: (pseudo-)hires query

Post by creaothceann »

byuu wrote:blending the even and odd pixels together and reducing the width back to 256 for pseudo-hires mode.
Maybe it renders not completely down to 1:2. Imagine one SNES "pixel" (dot?) consisting of three TV "pixels":
1 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | ...

The blending effect could blur only the edges of the "SNES pixel", like this:
1 | 1 | 1 & 2 | 1 & 2 | 2 | 2 & 3 | 2 & 3 | 3 | ...

Or even with only one blended part:
1 | 1 | 1 & 2 | 2 | 2 & 3 | 3 | ...
vSNES | Delphi 10 BPLs
bsnes launcher with recent files list
MaxSt
ZSNES Developer
ZSNES Developer
Posts: 113
Joined: Wed Jul 28, 2004 7:07 am
Location: USA
Contact:

Re: (pseudo-)hires query

Post by MaxSt »

byuu wrote:blending the even and odd pixels together and reducing the width back to 256 for pseudo-hires mode.
Obviously reducing the width back to 256 is not a good idea.
byuu wrote:so what I'm wondering is if anyone has been able to come up with a better formula for matching the TV output
Well, TV is perfectly able to display 512 columns.
byuu wrote:thus actually truly rendering at 512 pixels
Yes.
byuu

Re: (pseudo-)hires query

Post by byuu »

Obviously reducing the width back to 256 is not a good idea. Well, TV is perfectly able to display 512 columns.
I'm open to suggestions. Color bleeding simply has to happen, then. If you render the 512 pixels with no blending, you end up with some really horrible output for pseudo-hires effects -- so bad that even the crushed 256-width is a million times better by comparison. Hence, I could really use a nice formula, or maybe some chrominance vs luminance output speed, and just how many dots are actually on the TV for real during interlace/non-interlace/256-width/512-width modes.
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Post by grinvader »

Well, I don't exactly know about NTSC bleeding, but here's some PAL info:
One TV pixel is roughly square, with red, green & blue from left to right. The pixels are disposed in hexagonal patterns, like this:

Code: Select all

 . .
. . .
 . .
. . .
Not really a standard dot matrix.
So to reproduce bleed, you have to apply a second-pass filter (not possible to pull it in the same pass as rendering) kind of like:

Code: Select all

colour[x][y].blue += (colour[x-1][y-1].blue + 2*colour[x-1][y].blue + colour[x-1][y+1].blue)/bleed_intensity;
colour[x][y].red += (colour[x+1][y-1].red + 2*colour[x+1][y].red + colour[x+1][y+1].red)/bleed_intensity;
If you keep bleed_intensity variable, you can let the user choose his bleeding setting from very heavy (low values) to nonexistant (high values).
If you make it togglable (with & w/o bleeding) a single unsigned byte for intensity is enough.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
Pepper

Post by Pepper »

I don't know if it helps, but Steve snake (author of kega) has a render mode that is fairly good at reproducing the color bleeding effects of the tv, thus allowing games that rely on this to look accurate.
WolfWings
Hazed
Posts: 52
Joined: Wed Nov 02, 2005 1:31 pm

Post by WolfWings »

I'd like to point out that you're slightly mis-explaining how PAL (and NTSC CRTs as well) work. The hexagon grid does exist, but it's MUCH smaller than individual pixels, and some CRTs have used non-hexagonal grids. In effect it's nothing more than using a hex-grid to interleave a relatively flat field of red, green, and blue-glowing material that is activated by an electron beam.

To actually simulate the 'bluring' effect that most TVs show, the most accurate approach is to actually encode the RGB buffer into either BT.470 or BT.709 color-space, run a blur filter over the non-chrominance/colour channels, re-convert to RGB and possibly upscale and apply a scanline effect.

Quick demonstration of the effect through BT.470:
Image

Quick demonstration of the effect through BT.709:
Image

And skipping the blurring step:
Image

Note that the order of operations for the above images is BT.blurring, upscaling 2x, 50-percent scanlines. Also, BT.470 and BT.709 do have specific differences, BT.709 is more-or-less the international interchange standard colourspace for converting to/from digital formats across NTSC, PAL, and SECAM, while BT.470 is mostly only used in older PAL equipment. You can ignore BT.470 most of the time, BT.709 has been in use as BT.601 since 1987 and only adds specific support for higher-resolution HDTV settings (1125 and 1250 lines), and has a 'sequel' in BT.709-4 that only adds support for 1080i resolution.

Edit: And as a quick side-note, you can look here for equations for converting between RGB and YUV.
Last edited by WolfWings on Tue Aug 01, 2006 6:11 pm, edited 1 time in total.
[img]http://wolfwings.us/sigs/WolfWings.jpg[/img]
byuu

Post by byuu »

run a blur filter over the non-chrominance/colour channels
It was my impression that luminance had more resolution (per se) than chrominance... and that both had a tendency to "bleed" into neighboring pixels.
Also, just blurring the image is kind of vague. If the source width is 512 pixels, what would that be blurred down to for output? Raising the resolution is not really an option.
Specifically, are there any specifications on how many unique pixels of horizontal resolution actually appear on NTSC TVs? That would help to guess the resampling resolution, and then I could adjust the bleed factor until I get something close to the TV output.
WolfWings
Hazed
Posts: 52
Joined: Wed Nov 02, 2005 1:31 pm

Post by WolfWings »

byuu wrote:
run a blur filter over the non-chrominance/colour channels
It was my impression that luminance had more resolution (per se) than chrominance... and that both had a tendency to "bleed" into neighboring pixels.
Also, just blurring the image is kind of vague. If the source width is 512 pixels, what would that be blurred down to for output? Raising the resolution is not really an option.
Specifically, are there any specifications on how many unique pixels of horizontal resolution actually appear on NTSC TVs? That would help to guess the resampling resolution, and then I could adjust the bleed factor until I get something close to the TV output.
Sorry, when I said a 'blur' filter, I specifically meant a linear, 3x3 box-style blur filter, the 'add 9 pixels together, divide by 9' type. :-)

And that's what I said, or meant to say, run the blur over the color planes. I typoed. And the problem with trying to say how many 'pixels' are in an NTSC signal is... infinite. NTSC is analog, it has no actual limit to the pixel resolution, it is a purely-analog format. 720 is generally considered the upper limit, but that's only an upper limit. 719 pixels can be just as accurately shown on-screen as 720 pixels, for example. The screen is NOT 720 pixels wide. The screen has a concept of lines, but no concept at all of pixels. Hell, you can mix the horizontal resolution of the screen from line to line as long as each line lasts the same amount of physical time. It's akin to trying to say the sample-rate of a phonograph record. The two terms don't translate between each other.

If you're starting at 512xY and want to get down to 256xZ, then I'd recommend downscaling the image in YUV colourspace to 256xZ, then run the blur filter as before, and keep it at that. Alternatively, though with possibly added CPU load, run a proper Guassian RLE or IIR blur filter (look up the terms, basically a spherical blur instead of a flat box blur) of 5x5 THEN downscaling the image then back-converting to RGB again.
Last edited by WolfWings on Tue Aug 01, 2006 6:11 pm, edited 1 time in total.
[img]http://wolfwings.us/sigs/WolfWings.jpg[/img]
Reznor007
Lurker
Posts: 118
Joined: Fri Jul 30, 2004 8:11 am
Contact:

Post by Reznor007 »

byuu wrote:
run a blur filter over the non-chrominance/colour channels
It was my impression that luminance had more resolution (per se) than chrominance... and that both had a tendency to "bleed" into neighboring pixels.
Also, just blurring the image is kind of vague. If the source width is 512 pixels, what would that be blurred down to for output? Raising the resolution is not really an option.
Specifically, are there any specifications on how many unique pixels of horizontal resolution actually appear on NTSC TVs? That would help to guess the resampling resolution, and then I could adjust the bleed factor until I get something close to the TV output.
The actual resolution varies based on the specific CRT you are talking about. You don't really have to worry about chrominance or luminance unless you are specifically going for a NTSC/PAL blur effect, as the CRT itself operates on normal RGB like the SNES itself.
byuu

Post by byuu »

I found a good webpage that explained horizontal resolution a little better... they say it's based on some signal frequency thing that usually caps at 4.2mhz, but colors can be written on both the high and low pulses (whatever that means), so you get 8.4mhz / 525 lines / 30 = ~533 pixels of horizontal resolution. And any speeds much faster than 4.2mhz interferes with the audio signal which is at 4.5mhz or something.
Of course, this applies to luma only. Chrominance is only transmitted at ~0.5mhz or so (it really depends on the source signal), so you end up with ~80 pixels worth of chroma data per scanline. That seems chaotically low to me, though. And supposedly NTSC TV broadcasts only carry ~40 pixels of chroma. I know we aren't as sensitive to color, but damn...
Also found a good explanation of NTSC overscan. Used to prevent the picture from shrinking when power is reduced to the set or something.

OK, so I know how to extract luma (it's just Y in that formula), but how do I get a raw value for chroma? Should I just extract U+V, and then average both and write those back, while leaving luma alone?

I was thinking of dropping chroma to 256 or 128, so that I could use simple bitshifting for the blurring instead of any multiplication or tables.
Reznor007
Lurker
Posts: 118
Joined: Fri Jul 30, 2004 8:11 am
Contact:

Post by Reznor007 »

Overscan is actually to hide the analog nature of NTSC and PAL. If you adjust your overscan(in the TV service mode) you can see scrambled lines at the top which are the closed caption information (I'm thinking it was line 21 that CC info is transmitted on). Overscan is just to make sure that your full screen is filled with "proper" picture instead of edges/garbled static since not all over-the-air/cable systems send on exactly the same frequencies.
Nightcrawler
Romhacking God
Posts: 922
Joined: Wed Jul 28, 2004 11:27 pm
Contact:

Post by Nightcrawler »

I don't really fully understand how TV's work yet either, but the more and more information I discover and understand about them, the more I keep thinking how much of an old peice of crap TV's are. They are worse than the floppy drive! We're still using core technology in a TV that is over 50 years old! We're WAY overdue to make the switch to digital. And a TV isn't even about analog vs. digital. It's about analog within the limitation of 50+ year old technology. In fact, I'm amazed TV's produce as good of a picture as they do sometimes.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
The Dumper
Rookie
Posts: 11
Joined: Wed Jul 28, 2004 5:03 pm

Post by The Dumper »

Have you done tests on the SNES for this? Would putting different simple regular patterns of pixels on the screen and seeing how they get displayed help figure out how they are combined/filtered? Picking different algorithms because they look better is a reasonable thing to do but it would be nice to know the SNES algorithm too.
byuu wrote:Also, does anyone know what the problem with Kirby 3 is? I obviously can't test the game myself to see if I have it right :/
I don't know anything about a Kirby 3 problem. You can't test it because you don't have the game? This is Kirby Dream Land 3? I think I have it around somewhere. If it will help I can attempt to verify specific spots in the game. Do you have emulator generated images that you want to check against reference images?
byuu

Post by byuu »

Have you done tests on the SNES for this?
No, but anomie has. I need to do my own, I've been putting it off, though.
I don't know anything about a Kirby 3 problem. You can't test it because you don't have the game?
There's water somewhere in the game that when Kirby walks into, you're supposed to be able to see kirby in it at 50% translucency. According to some snes9x forum posts from 2003-2004, snes9x has a hack that allows Jurassic Park to work, and turning that on breaks Kirby. So the pseudo-hires, in effect, works on one or the other. Why they chose Jurassic Park over Kirby, though, is beyond me.

I cannot test the game because bsnes does not emulate the SA-1 coprocessor :/
Post Reply