Some doubts about the HiRes mode

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Some doubts about the HiRes mode
by on (#174028)
Like I said on another topic here, I'm working on a SNES emulator, and today I decided to implement the HiRes modes 5 and 6. I was really wondering if the effort was worth it, since I can count on my fingers the games that actually make use of those modes, and I unfortunately can't count on my fingers the number of FPS I lost since I started implementing said modes.

Well, going to the point, I saw on Anomie doc that the HiRes modes will always use a 16 pixels wide tile, even on the 8x8 tile mode (so it can have either a 16x8 tile on the 8x8 mode, ie, 0x2105 bits 4-7 clear, or 16x16 on the 16x16 tiles mode). It should then render the even pixels (0, 2, 4, 6...) on the Sub Screen, and odd (1, 3, 5, 7...) on the Main Screen. This makes sense since it is supposed to create a 512 pixels wide picture on the end. Since the image is squished on the TV screen anyway, I think that what makes most sense on a emulator, is doing something like (Main[X] + Sub[X]) / 2 to get the final 256 pixels wide image, as opposed to display the whole 512 pixels on the screen.

My first doubt was wish effect the TM, TS, TMW and TSW (0x212C-0x212F) registers have on those HiRes modes. Normally, they are used to select if the pixel is rendered to the Main Screen or on the Sub Screen. But since modes 5/6 NEEDS to use the Sub Screen anyway, I guess that those registers have no effect (or they produce some weird result?)

My second doubt is what happen to the OAM objects (aka sprites) on the HiRes modes. They have a X/Y position and the X value normally only goes from -256 to 255. So I only see two possibilities to make this work on the HiRes mode, the X registers is either doubled, to take the new size into account, or the sign bit is no longer used, and the register would instead be a value between 0 and 511, and a left off-screen scrolling would be no longer possible.

Those are my doubts and I would be really thankful if someone could enlighten me on the subject.
Re: Some doubts about the HiRes mode
by on (#174033)
I believe this is what you're trying to figure out.

As for OBJ: OBJ always has a V position of 0 to 255 (8-bit value), and always has an H position of -256 to 255 (9-bit value). The MSB (9th bit) of the H position for OBJ is stored alongside the size (large/small) after the initial 128 objects in the OAM table (i.e. starts at OAM offset 257 for object 0, etc.). I've added a couple official manual screenshots depicting these things.
Re: Some doubts about the HiRes mode
by on (#174036)
gdkchan wrote:
Since the image is squished on the TV screen anyway, I think that what makes most sense on a emulator, is doing something like (Main[X] + Sub[X]) / 2 to get the final 256 pixels wide image, as opposed to display the whole 512 pixels on the screen.

Unless the user is using at least 2x display. Then you render all 512x224 pixels and stretch them to 584 pixels wide (with linear interpolation) by 448 pixels (either nearest neighbor or linear+scanlines).

It's squished but not blurred if an S-Video cable is in the multi-out connector. In my tests, hi-res luma through S-Video is perfectly clear, even if the chroma is somewhat blurred due to squishing.

Quote:
My second doubt is what happen to the OAM objects (aka sprites) on the HiRes modes.

Each sprite pixel is drawn over two hi-res pixels.
Re: Some doubts about the HiRes mode
by on (#174052)
I should add that I don't quite understand the "Since the image is squished on the TV screen anyway ..." point. The way the rest of the sentence reads, it implies that the emulator would only need to display 256 pixels in width, which is incorrect. I get the impression the OP hasn't ever seen (on actual hardware (SNES + CRT)) the visual results of mode 5 or 6 -- you can most definitely tell the difference.

I forget if Yuuyuu Hashuko (and Yuuyuu Hashuko Tokubehuten) intro screens use the interlaced feature as well (essentially achieving 512x448). Let me check... dang, NO$SNS doesn't actually show this register in the I/O map. However, it does clearly show: "PPU Resolution: 512x448", so I would say that yes, it also uses interlaced mode. :D
Re: Some doubts about the HiRes mode
by on (#174061)
tepples wrote:
Unless the user is using at least 2x display. Then you render all 512x224 pixels and stretch them to 584 pixels wide (with linear interpolation) by 448 pixels (either nearest neighbor or linear+scanlines).

It's squished but not blurred if an S-Video cable is in the multi-out connector. In my tests, hi-res luma through S-Video is perfectly clear, even if the chroma is somewhat blurred due to squishing.

Interesting, I made some tests downscaling it to 256x224 and the results looked awful, text is barely readable. Stretching it to 584 pixels will be probably pretty expensive, since this isn't even a multiple of the original resolution. I think I'll just end using 512x448 as my base resolution, this way I can fill the buffer in a fast and simple way, and can later re-scale it on my hardware renderer without any performance penalty.

tepples wrote:
Each sprite pixel is drawn over two hi-res pixels.

Thanks, idk why I didn't think in this before heh.

Also thanks to koitsu for the docs. I took a look at then, and a doubt came to my mind, and that would be what this interlace mode is. I know that the SETINI register (0x2133.0) can enable the interlace mode, that draws 224 even lines of a 448 lines frame on even frames, and 224 odd lines of a 448 lines frame on odd frames, lowering the effective refresh rate to 30Hz on NTSC or 25Hz on PAL. This is the interlace that the doc refers to, is this correct?
Re: Some doubts about the HiRes mode
by on (#174062)
gdkchan wrote:
Well, going to the point, I saw on Anomie doc that the HiRes modes will always use a 16 pixels wide tile, even on the 8x8 tile mode (so it can have either a 16x8 tile on the 8x8 mode, ie, 0x2105 bits 4-7 clear, or 16x16 on the 16x16 tiles mode). It should then render the even pixels (0, 2, 4, 6...) on the Sub Screen, and odd (1, 3, 5, 7...) on the Main Screen. This makes sense since it is supposed to create a 512 pixels wide picture on the end. Since the image is squished on the TV screen anyway, I think that what makes most sense on a emulator, is doing something like (Main[X] + Sub[X]) / 2 to get the final 256 pixels wide image, as opposed to display the whole 512 pixels on the screen.


If you interpolate back down to 256x224, games that use hires will end up looking like the right side of this image:

Image

Quote:
My first doubt was wish effect the TM, TS, TMW and TSW (0x212C-0x212F) registers have on those HiRes modes. Normally, they are used to select if the pixel is rendered to the Main Screen or on the Sub Screen. But since modes 5/6 NEEDS to use the Sub Screen anyway, I guess that those registers have no effect (or they produce some weird result?)


TM/TS/TMW/TSW have exactly the same effect as they always do. Normally, games will enable the same layers on both main and sub screens. But if they enable a layer on only one of the two screens, only every other pixel from that layer will be displayed, producing a fake-transparent dithered effect. Jurassic Park and Kirby's Dreamland 3 are two games that do this.

Quote:
My second doubt is what happen to the OAM objects (aka sprites) on the HiRes modes. They have a X/Y position and the X value normally only goes from -256 to 255. So I only see two possibilities to make this work on the HiRes mode, the X registers is either doubled, to take the new size into account, or the sign bit is no longer used, and the register would instead be a value between 0 and 511, and a left off-screen scrolling would be no longer possible.


Your first guess is correct. The sprites aren't doubled in resolution. Each sprite pixel ends up covering both a main and a sub BG pixel, and they can only be moved in units of full pixels. However, sprites are affected by clipping in the same way BGs are: if you enable the sprite layer only on main or only on sub, all sprites will have a dithered appearance.
Re: Some doubts about the HiRes mode
by on (#174063)
gdkchan wrote:
Also thanks to koitsu for the docs. I took a look at then, and a doubt came to my mind, and that would be what this interlace mode is. I know that the SETINI register (0x2133.0) can enable the interlace mode, that draws 224 even lines of a 448 lines frame on even frames, and 224 odd lines of a 448 lines frame on odd frames, lowering the effective refresh rate to 30Hz on NTSC or 25Hz on PAL. This is the interlace that the doc refers to, is this correct?

Correct: it's referring to how bits 0 and 1 of $2133 have an effect (in modes 5 and 6 only; in other modes they do nothing). Bit 0 controls whether or not the background/screen is doubled in height, and bit 1 controls OBJ rendering (doubling of vertical pixels).

With $2133 bit 0 set to 1 in mode 5 or 6, you can visually tell that the CRT refresh essentially becomes 30Hz on NTSC; there's an easily noticeable flicker.

I have no experience with PAL.
Re: Some doubts about the HiRes mode
by on (#174064)
gdkchan wrote:
Stretching it to 584 pixels will be probably pretty expensive, since this isn't even a multiple of the original resolution. I think I'll just end using 512x448 as my base resolution, this way I can fill the buffer in a fast and simple way, and can later re-scale it on my hardware renderer without any performance penalty.

That method is fine. Render at 512x448 in your emulator and scale to the final size (584x448, 876x672, 1168x896, or 1314x1008) in hardware.

Quote:
I know that the SETINI register (0x2133.0) can enable the interlace mode, that draws 224 even lines of a 448 lines frame on even frames, and 224 odd lines of a 448 lines frame on odd frames, lowering the effective refresh rate to 30Hz on NTSC or 25Hz on PAL. This is the interlace that the doc refers to, is this correct?

What it does is draw every other frame half a scanline down. Games using 480i (interlace) mode still expect the display to be capable of high motion, the ability to change the scroll position and move sprites between one field of a frame and the other.
Re: Some doubts about the HiRes mode
by on (#174069)
Thanks everyone. I'm slowly implementing HiRes stuff (it will be a bit more complicated than I initially through). I started using a base resolution of 512x448 and the result is HiRes without any distortion :mrgreen:

Image
This is from Seiken Densetsu 3. It apparently enables/disables the Horizontal HiRes mid frame to have more space for the fonts. It uses it on other places too.

Image
And this one is from Air Strike Patrol. It is pretty messed up atm, but at least the text is clear. It is out of place too, and this make me thinks that it may peharps use interlace frame flag (odd/even) somehow to position the text lines (this is not implemented yet)... That or maybe I have something messed up on my rendering code. With HiRes the advantage to have separate code to render the 8x8 and 16x16 modes are pretty much lost too (since I can have 16x8 inside the 8x8 mode), so I think I'll merge them into one.
Re: Some doubts about the HiRes mode
by on (#174077)
Yes, Air Strike Patrol uses interlace heavily on various screens, including that one.

Also, I'd reaaaaaaaaaaaally recommend you stop using that specific game to test your emulator. If you thought the hires speed-hit was bad ... you're going to want to throw your computer out the window when you find out what it does once you start an actual mission in-game =(

I'm not exaggerating when I say it's literally the most complicated game in the entire officially released library to render correctly. I'd hate to see you get bogged down or discouraged so early on, especially when you're making such great progress!

If you want to test interlace out, please try RPM Racing. That game is fully 512x448 and doesn't do anything too evil.

If you want to go through the gamut for PPU features, please try the SNES Test Program's Character Test sequence. Be sure to compare this one to a real SNES or higan so you know what to look for.
Re: Some doubts about the HiRes mode
by on (#174118)
So I implemented the interlaced mode today. It was easier than the horizontal hi-res, and following byuu's advice I used RPM racing for testing. From what I see, it is more or less correct. It have a few issues here and there that are probably not related to the hi-res mode.
ImageImage

I also couldn't help but look how A.S.P. menu was after I implemented the interlace. It is better than before too.
Image

I was also thinking that the interlace would fix the cut-off text on the snes test cart controller test, but unfortunately it didn't:
Image
Funny thing is that snes9x have a similar issue (and I believe that ZSNES too?). Anyway, I'll give it a go on higan to see how it is supposed to look on actual hardware (since I don't have a SNES).

Edit: Now thinking about it the Controller test probably uses the 239 lines overscan mode.. hmm
Re: Some doubts about the HiRes mode
by on (#174123)
That is correct: the SNES Test Program uses overscan mode in various areas.

I wasn't trying to plug my emulator, but I don't know of any others that can run the SNES Test Program fully.

The main tricks are the stars: the blinking star moving around is due to range-tile over (sprite/tile limits per scanline), and when the sprite sizes cut in half, that's OAM interlace.

The character test does an obscene amount of things, so it's great for refining a PPU core.

Really amazing how quickly you're doing all of this, by the way. It took me months to implement all PPU features.

> I also couldn't help but look how A.S.P. menu was after I implemented the interlace. It is better than before too.

Looking good now! And that's fine, just again ... don't go in-game, and don't look up why this game is infamous please. Or at least, save it for much, much later.
Re: Some doubts about the HiRes mode
by on (#174127)
I'm still wondering why did they even bother with interlaced mode in-game in RPM Racing. I mean it looks good on the title screen, but like there really isn't much detail on the tracks to make it worth it... (besides, clash with the sprites - or are those sprites meant to be hi-res too?)
Re: Some doubts about the HiRes mode
by on (#174134)
AFAIK sprites are always lo-res...
Re: Some doubts about the HiRes mode
by on (#174137)
OK, I knew about coordinates but wasn't sure on the image data. The docs seem to imply you're supposed to alternate between two sprites to achieve higher vertical resolution in interlaced mode, which I guess makes sense (at least you can double it vertically).
Re: Some doubts about the HiRes mode
by on (#174141)
Sik wrote:
I'm still wondering why did they even bother with interlaced mode in-game in RPM Racing. I mean it looks good on the title screen, but like there really isn't much detail on the tracks to make it worth it... (besides, clash with the sprites - or are those sprites meant to be hi-res too?)


The interlace effect is also extremely jarring. It makes all the cars look like they're constantly splitting in half. Might look better on an actual CRT TV, never tried it there ... but it looks terrible on LCDs and in emulators.
Re: Some doubts about the HiRes mode
by on (#174142)
byuu wrote:
It makes all the cars look like they're constantly splitting in half. [...] it looks terrible on LCDs and in emulators.
That's a classic symptom of bad deinterlacing.
Re: Some doubts about the HiRes mode
by on (#174144)
tokumaru wrote:
AFAIK sprites are always lo-res...
Sik wrote:
OK, I knew about coordinates but wasn't sure on the image data.

Sprites can be hi-res in the vertical axis in interlace mode; there's a separate bit for it in SETINI ($2133). RPM Racing apparently doesn't use it.

Horizontal hi-res is unavailable to sprites, unless (I think) the specific application you have in mind happens to work with main/sub trickery in pseudo-hires mode (most cases won't, because sprites are flattened into a layer before being sent to main/sub).

Quote:
The docs seem to imply you're supposed to alternate between two sprites to achieve higher vertical resolution in interlaced mode, which I guess makes sense (at least you can double it vertically).

No, the sprites are actually drawn at half-height, with automatic line alternation. Manual alternation is only necessary to get interlaced BG graphics outside Modes 5-6. You could leave the OBJ Interlace bit off and manually alternate the sprite graphics, but you don't need to.
Re: Some doubts about the HiRes mode
by on (#174152)
RPM Racing looks noticeably flickery and crawly on my CRT. The effect is more noticeable on some portions of the screen as opposed to others. I believe it was a poor choice to use the interlace mode for the game. For a racing game, it isn't a very fast paced game. R.C. Pro-Am, which uses a similar perspective and style runs races around RPM Racing. The flicker can get really distracting on some of the static screens, in motion the effect is not quite so bad.

While there are a lot of menu screens in RPM Racing where the mode is used with little ill-effect, in the racing portion of the game I guess it was used to give the racing backgrounds more detail, especially because the two-player split-screen is being used at all times.
Re: Some doubts about the HiRes mode
by on (#174159)
The developers themselves realized in the end that hi-res made their job more difficult than it needed to be. Back when there were a lot of articles being written on Blizzard I remember reading as much.

The Japanese version of RPM Racing unsurprisingly doesn't use interlaced high resolution mode in the actual race, I consider this the final version of the game. Check it out if you haven't seen it before, it's a major step up graphically. You can still cheat of course.
Re: Some doubts about the HiRes mode
by on (#174168)
AWJ wrote:
TM/TS/TMW/TSW have exactly the same effect as they always do. Normally, games will enable the same layers on both main and sub screens. But if they enable a layer on only one of the two screens, only every other pixel from that layer will be displayed, producing a fake-transparent dithered effect. Jurassic Park and Kirby's Dreamland 3 are two games that do this.

I believe that I implemented enough of the hires mode functionality to make Jurassic Park functional. But I have a problem through. On the even frames (in game) it seems more or less correct. But on the odd frames through, the screen turns all black because the game seems to set the screen brightness (0x2100 bits 0-3) to zero. Anyone know if it have different functionality with H hires enabled?

@byuu - Thanks for the tips, I already implemented the sprite range overflow handling and will implement the OAM interlace and priority rotation (which I guess it's responsible to make the stars swing) later. It indeed have some curious tests. On the test with the Super Mario World-like scrolling background, it will test if value from a Open Bus region (0x2184 ~ 0x21FF) is equal to the last byte of the operand of the last instruction (well actually it just does a AND by 0x20, so any value with bit 5 set will do, the expected value is 0x21 iirc). Without Open Bus emulation it just keeps stuck on that part forever.

Edit:
I figured out the problem with Jurassic Park. Looks like a the CPU will continue from a WAI instruction after an IRQ occurs even if the IRQ Disable flag is set on the P register. Now it looks correct I guess.

Image