johannes-fetz / joengine

Jo Engine is an open source 2D and 3D game engine for the Sega Saturn written in C under MIT license
http://jo-engine.org/
MIT License
205 stars 32 forks source link

JO_480p Makefile Option #30

Open slinga-homebrew opened 4 years ago

slinga-homebrew commented 4 years ago

Hi Johannes,

I was looking at different resolutions for Jo Engine and I just wanted to document my thoughts, I don't expect you to change anything. I am not an expert on this so I could very well be completely wrong.

1) JO_480p seems to be misnamed. While the Saturn does have a high resolution 480p mode, I believe JO_480p is actually enabling the 480i mode. So perhaps JO_480i would be the correct name. 2) Is there a reason TV_704x480 was used as the resolution instead of 640x480? I imagine 640x480 would look better on most displays. Again, this is outside of my knowledge. 3) When in 480i mode, I believe the framerate is halved to 30 fps. Testing with my project it does appear to be running at half the speed. However the JO_FRAMERATE variable isn't changed and I believe is always 1. 4) 480p support would be fun =). But I imagine a pain. And very limited use as it would require a SCART cable and I'm not sure what TVs would be able to handle the signal. And from my understanding 480p runs at 15 fps.

ponut64 commented 4 years ago

Commenting here instead of segaXtreme forums so Jo can read it :)

  1. "jo_480p" is indeed 480i. Better names would be "jo_standard_res" and "jo_high_res".

  2. For "704x480", we focus on the fact that 352 is the base scanline width. 704 is double that of 352. The Saturn runs at a higher clockspeed when 352 is used as the base width instead of 320. However, 704x480 might not be the most efficient res, but its better than 640x480. The most efficient is 352x224 / 704x448. 352x448 is also possible.

  3. Here we are getting down to the specifics of interlaced video. NTSC signal is indeed about 60hz. However, the standard TV signal is only about 30 fps. That's because the video signal is interlaced. You get half a frame each pulse. In displaying interlaced video from the Saturn, it is no different. The video system can only output a maximum of 30 frames per second in interlaced video because the signal is limited to 60 hz.

This also shows another problem, because VDP1's framebuffer size is 512x256 in size and VDP2's display window of that is a fixed size. To render interlaced video, VDP1 has to draw the odd scanlines, framebuffer change and erase must be executed, VDP2 must encode the "done" framebuffer as the odd scanlines, then VDP1 has to go back over the same command list for the even scanlines. Thus, VDP1's speed in interlaced video modes is effectively halved. That shouldn't be a surprise because its double the pixels -- duh, right? But you experience two blanking periods for every frame on VDP1. That's about 5ms of render time lost to hardware complications.

Hi-res progressive scan modes have the similar problem. VDP1 has to write to some half of the framebuffer, change and erase, while VDP2 is stitching them together. But in this case, you can output 60Hz you just still lose 5ms to hardware complication (so you have very little time!).

Though I understand your comment is about representing this necessary change in frame-rate to the programmer. The JO_FRAMERATE variable is some abstraction of SGL's system variable, SynchConst. SynchConst represents the system synchronization timing as some division of the video signal timing. In progressive scan modes, you have 1 for 1/1 blanking periods or 60hz. You have 2 for 1/2 blanking periods or 30hz, 3 for 1/3 for 20hz, etc. In interlaced video, the signal is only complete every 30hz, so 1/1 represents 30hz. 2 represents 15hz.

Instead of relying on this system variable, you can use jo_fixed_point_time and retrieve the data from the jo engine variable "delta_time".

  1. SGL has no abstractions for 480p. Jo would have to engineer that from the hardware manuals himself.
fafling commented 4 years ago

@ponut64 There are 60 different fields per second in NTSC, and each field is displayed one at a time on a CRT TV, all the odd ones, then all the even ones, etc...

On the hardware level of Sega Saturn, nothing prevents to draw a different picture on each field with VDP1 when it's set to double interlace, using different command lists that you can change during vblank. Of course, due to the offset of one scanline between fields, this results in combing effects, which are transient on a CRT TV due to afterglow of one field over the next, but which can become very obvious on modern progressive display if video post processing combines consecutive fields in one frame without any other deinterlacing.

I think it might just be SGL implementation that makes it repeat the same command list for 2 consecutive fields when VDP1 is set to double interlace.

When VDP1 is set in high res, its framebuffer becomes 8 bpp which doubles its width. In progressive mode, it draws a complete frame each time, not half.

On topic, why not ""jo_480i", or more generic "jo_double_interlace" ?

ponut64 commented 4 years ago

thonk i forgot to mention that the high-res modes force vdp1 to be 8bpp which makes it 512x512

I did mean that each pulse of normal TV is even field then odd field, but it is helpful to be more specific as you say as "half a frame" could mean different.

In high progressive scan modes like 704x224, how does it draw the whole frame at once? VDP1 knows it's only one draw period. It's just, even with a 512x512 framebuffer, you can't get 640 or 704 width. I thought it would have to do a change & erase period.

Unless, instead of going to 512x512, they re-order it bitwise to do 1024x256

As usual you are the one with the best answers :)

asking these Q's on the discord server help me work through my stupidity instead of just vomiting it out in a paragraph

fafling commented 4 years ago

Yes, high res framebuffer is 8 bpp 1024x256. A 704x224 drawing area fits in.

8 bpp framebuffer 512x512 is rotation8 : a standard res framebuffer that can be rotated without its limits becoming visible on screen.

ponut64 commented 4 years ago

I'm sure at one point I knew all of this reading the manuals... but then I read some other part of some other manual and stopped messing with it so I forgot...