General Category > Emulators

Wish 60Hz/60fps support in emulators. Thought on emulating a CRT.

(1/3) > >>

cpcitor:
TL;DR summary:
* In practice most current machines, PC, Android, etc have 60Hz, which cannot render smooth scrolling at 50Hz.
* A CPC prod perfectly synced at 50Hz will not look good on a 60Hz screen.
* But a real hardware CPC can output 60Hz, so a CPC prod can be perfectly synced at 60fps! 
* For real-CPC based execution, it's easier+cheaper to plug a simple cable from CPC to a 60Hz monitor than find a monitor supporting 50Hz or buy an adaptor that kills the smoothness and picture quality.
* The only missing part of this puzzle is this: to ease working on 60fps prod on the CPC, wish more CPC emulators support emulating a 60Hz monitor.
* Bonus: realistic rendering of effects like RetroVirtualMachine "beam" can become possible.

Or "why caprice32 has the image below right and how this is related to 60fps/60Hz display":


hsync_slanting_caprice32_good.png
(3.23 kB, 768x540 - viewed 315 times)

People implementing an emulator might be interested in the analysis that follows.

Motivation

1. Show demos with perfectly smooth rendering.

This is only possible by mapping one CPC frame to one output frame. This is easy when framerates are close. 50.04Hz of the CPC is close to 50Hz. Frames can be played in sync and audio/video sync will not drift much quickly. This is not close to 60Hz which is current standard. This means either audio/video drift, or duplicating frames several times per second. I took this approach (one-to-one frame mapping) on the 60Hz YouTube rendering of 2021 a CPC Odyssey by cpcitor & The Other Days :: pouët.net
2021 a CPC Odyssey by cpcitor & The Other Days :: pouët.net because after the music starts, audio/video sync can drift wildly without it being a problem. This required manual adjustment and won't fit most prods in general!

Which means... to support 60fps video files on the web we can... work on hardware CPC with a 60Hz screen. Easier development environment is: support 60Hz on CPC emulators!

2. Support 60Hz on CPC emulators.

The CPC hardware and firmware supports 60Hz. A real CPC can be connected to a TV (even a recent one, provided it has analog input) through an analog cable and produce 60Hz that can be decoded. Even a PC monitor can do the job with a custom CPC-to-VGA cable. Few monitors support 50Hz through VGA because it is out of standard. With a CPC at 60Hz most monitor can accept that.

If an emulator supports a CPC configured for 60Hz, then prods can offer a 50/60Hz toggle and finally be rendered perfectly on modern displays and on video platforms (like YouTube).

This is now new: I remember in 1993 seeing a game on Atari ST where pressing space toggled between 50Hz and 60Hz display. The analog monitor adjusted, and the aspect ratio changed since there were less lines in the 60Hz mode

First thoughts about how emulator could support 50 and 60hz

This is highly technical and could very well go over the head of many readers, that's okay. Faithful emulation of the CPC monitor is similar to capturing analog video, and this is complicated. This video is interesting on the topic
https://www.youtube.com/watch?v=2a9E6Cx8Hgw . (One can guess that I worked in a company making video products that supported analog and digital output, with a high bar on excellent output quality and never missing a frame.)

CRTC = the chip that generates signals, including hsync and vsync
CRT = the tube-based monitor, the circuitry that senses hsync and vsync and tries to fit that to its expectation to drive an electron beam on a zigzag to the front of the tube.

We could concentrate on the CRTC output directly:

* "horizontal event": every time a horizontal CRTC counter says so, it triggers a hsync, that's a new line and we continue plotting pixels in the emulator's framebuffer on the next line on the left
* "vertical event": every time a vertical CRTC counter says so, it triggers a new vsync, that's is a new frame and the emulator spits a new frame and continues plotting pixels back to top of the framebuffer.

Questions:

* What happens when the time between two "event" is not close to the monitors expectations (1/15625s horizontal, 20ms vertical)?
* The signal is sometimes in steady state (identical time between hsync and vsync), with definite stable fps, but at times it is not.

Not answering these questions prevents from faithfully emulating a number of situations.

A basic emulator would have currently crude solutions to this (like, a hsync or vsync is the event to consider), but will this be enough to render all prods?
To their defense I would say: different CRTs react differently, so most prod avoid it, although some demos use it.

Conclusion: a faithful emulation of 50Hz/60Hz and some demos benefits from a CRT model.

Adding a CRT model and considering the signal downstream

What's a CRT model?  It's an answer to "what to do when facing early, late or absent hsync/vsync signals from the emulated CRTC?".

CRT behavior

Monitors of the era adapted to a few missing or extra lines (a.k.a vsync happening a little too early or late) without much noticeable visually. This means slight deviations from the theoretical framerate were just obeyed without problem.

Facing unexpected (or absent) hsync/vsync signals, CRT behavior is this: the CRT "hunts" for the signal.

* Unexpected horizontal timing results in generating a horizontal beam return at an "arbitrary" time. Visually this causes possibly wild slants of vertical lines into diagonals, with pixel or even subpixel horizontal shifts.
* Unexpected vertical timing results in generating a vertical beam return at "arbitrary" time. Visually this causes possibly wild "rolling" of the picture up or down.

Notice that when the monitor is "rolling", it does refresh the screen repeatedly but at a different framerate, depending on the monitor, so not 50Hz not 60Hz, something even different.

So, what about 50Hz vs. 60Hz then?

Hunting is when CRT could not catch the vsync in the expected time slot. The "expected time slot" is dependent on 50Hz/60Hz monitor devices. Notice that a GT-65 monitor with its "vertical sync" knob fits this model if you think of the knob as "manual adjust of expected delay between two vsync".

In practice, a 50/60Hz bi-sync CRT model would solve our goals.

How to do that in an emulator: adjust the expected time slot for the vsync signal so that a 50Hz vsync interval is recognized, a 60Hz vsync interval is also recognized, and depending on the case, the vertical line density (lines per inch) is adjusted.

Great! So, supporting 60Hz in an emulator can be simple! Now, what about fine timing details?

My current setup has 3 screens with respectively 60.03 59.95 and 50.01 Hz. This means that a program cannot generate a highly realistic rendering when not knowing on which screen it is, or even worse when its window spans multiple monitors. This means this corner case has to be "delegated to downstream" (not trying to handle it oneself).


There are two use cases:
* targetting interactive use on a PC desktop, possibly multimonitor, or a video capture to a modern format (MPEG family)
* targetting demo with perfectly smooth scrolling on a rigid platform with exact known framerate, or full-screen rendering on a monitor with known characteristics (think Raspberry Pi on a HDMI TV)

Timing option "Free": The first use case is well suited to formalizing with "free timing" of every frame. This fits the MPEG model of video streams: every frame in MPEG comes with a PTS "Presentation TimeStamp". The emulator would generate images (stable or rolling) and whenever its emulated CRT model would command the electron beam to fly back (stable or rolling), it would spit the frames as they come (using SDL API or any other, like FFMPEG), with PTS information if the API supports. This is "simple" and the best solution when running on a desktop environment or unknown framerate downstream equipment. When you get a "refresh-on-demand" screen on your desktop, you'll want this.

Timing option "Fixed": assume a display framerate, like the one of the HDMI TV connected to the Pi, or the fixed framerate expected by the target video platform. Emulate what the CRT monitor would display, and spit frames at the exact rate required downstream. This is formally sound. It does not match current multi-screen setup. It implies a specific step, somethings to do when the "ideal, free" timestamps are far from the fixed rhythm. That's where extremely realistic emulation becomes possible.

Indeed, the problem we face with timing option "fixed" is very similar to filming the virtual CRT with a camera. This is interesting as it allows a level of realism that no other option can provide. One can fade pixels depending on the exact time the electron beam passed on it ("remanence effect"). This is the "beam effect" RetroVirtualMachine has been faking because its emulation model does not allow to reproduce if faithfully. With this option "fixed", the actual beam effect could be emulated accurately! It would also emulate the exact reason why filming an actual original CPC screen with a modern camera or smartphone yields awful results. But being emulated this can be tweaked at will: for example, one can define an emulated remanence profile. This reminds me how some professional cameras have had for the last 20 years a button to lock to an external monitor just by aiming at it and pressing a button: they would film the scene normally, but that screen would be perfectly stable, removing all flicker and beam artifacts. Once you get there it's relatively simple to do. This is what we can do in emulation.

Summary

That was tough! To summarize:

* It is possible for CPC prods to support 50 and 60 fps output. 50Hz for original CRT, 60Hz for VGA screens not supporting 50Hz, for TVs, for Youtube and other online platforms.
* Hardware-wise, 60fps prods that render perfectly on Youtube without a hack are possible with a real CPC and an analog video capture card (google for "VGA capture").
* Emlulator-wise, the CRT model and discussion above allows emulators to support CPC prods targetting 60 fps output.

Test criteria for emulator support of 60fps

* See if emulator offers an explicit or implicit 60Hz option. If explicit, enable it. Some emulator may detect 60Hz automatically.
* Configure emulated CPC to output a 60Hz signal.
* See if image is stable.
* See if emulated video stream indeed spits 60 frames every second.

Quick experiment

Trying to hack an emulator to switch from 50 to 60Hz (or from "#define FRAME_PERIOD_MS 20.0" which would be 16.666ms but that gets truncated to 16, oh gosh) very much depends on how the emulator is organized. It's very easy to mix up 20ms as basic block for an arbitrary "abstract time frame" and 20ms as an actual output framerate. No success so far.

* Arnoldemu WIP: supports 50/60Hz option in menu which toggles LK4 which has firmware do the right thing! But arnoldemu isn't updated and difficult to compile nowadays. Actual FPS not measured.
* https://floooh.github.io/tiny8bit/ : stable image. Actual FPS not measured.
* Caprice 32: image rolls. No clean success on hacking the source code.
* cpcec 32: image rolls. No clean success on hacking the source code.

Unknown:

* Winape: can you tell here?
* Others: can you tell here?

Other quick experiments

Cpcec and caprice32 both react well to : out &bc00,9 : out &bd00,3 . This generated two images 320x100 stacked and not one 320x100 image at 100Hz. Supporting 60Hz implies more flexibility.

cpcec does not emulate the slanting, it just snaps the next line to the steady state position, something no CRT of the era does.
caprice32 emulates the slanting.


hsync_slanting_caprice32_good.png
(3.23 kB, 768x540 - viewed 315 times)

Details about 60Hz on original CPC hardware.

The CPC *can* produce a 60Hz video output, by programming the CRTC to switch to a new frame after fewer than the 312.5 lines of PAL timing. This is seldom discussed, e.g. on https://www.cpcwiki.eu/forum/amstrad-cpc-hardware/60hz-cpc/msg4856/#msg4856

Even the stock firmware in ROM supports 60Hz! To be more precise, at CPC reset, first bytes of ROM sets mode 1 then sets CRTC registers for 50 or 60Hz depending on a wire on the motherboard. This is explained in sections 12 and 13 of official firmware guide, see http://www.cpcwiki.eu/index.php/Soft968:_CPC_464/664/6128_Firmware .

In BASIC it is as easy to activate as:


--- Code: ---out &bc00,4 : out bd00, &1f     # (0x1F+1)*8 lines = 256
out &bc00,7 : out bd00, &1b    # Adjust vertical position

# ROM does this:
out &bc00,5 : out bd00, &6      # +6 = 262.   15625Hz (line frequency) / 262 = 59.63Hz
# firmware documentation says it should have been 4
out &bc00,5 : out bd00, &4      # +4 = 260.   15625Hz (line frequency) / 260 = 60.096Hz
--- End code ---

But although 60Hz CPC were made and sold in the US, this is seldom known.

See ROM disassembly by @arnoldemu at http://cpctech.cpc-live.com/docs/os.asm lines 1435-1477:


--- Code: ---;----------------------------------------------------------------
; RST 0 - LOW: RESET ENTRY
0000 01897f    ld      bc,$7f89 ; select mode 1, disable upper rom, enable lower rom
0003 ed49      out     (c),c ; select mode and rom configuration
0005 c39105    jp      $0591

(...)

0591 f3        di     
0592 0182f7    ld      bc,$f782
0595 ed49      out     (c),c

0597 0100f4    ld      bc,$f400 ;; initialise PPI port A data
059a ed49      out     (c),c

059c 0100f6    ld      bc,$f600 ;; initialise PPI port C data
;; - select keyboard line 0
;; - PSG control inactive
;; - cassette motor off
;; - cassette write data "0"
059f ed49      out     (c),c ;; set PPI port C data

05a1 017fef    ld      bc,$ef7f
05a4 ed49      out     (c),c

05a6 06f5      ld      b,$f5 ;; PPI port B inputs
05a8 ed78      in      a,(c)
05aa e610      and     $10
05ac 21d505    ld      hl,$05d5 ;; end of CRTC data for 50Hz display
05af 2003      jr      nz,$05b4         
05b1 21e505    ld      hl,$05e5 ;; end of CRTC data for 60Hz display

;; initialise display
;; starting with register 15, then down to 0
05b4 010fbc    ld      bc,$bc0f
05b7 ed49      out     (c),c ; select CRTC register
05b9 2b        dec     hl
05ba 7e        ld      a,(hl) ; get data from table
05bb 04        inc     b
05bc ed79      out     (c),a ; write data to selected CRTC register
05be 05        dec     b
05bf 0d        dec     c
05c0 f2b705    jp      p,$05b7

;; continue with setup...
05c3 1820      jr      $05e5            ; (+$20)

;; CRTC data for 50Hz display
05c5 defb &3f, &28, &2e, &8e, &26, &00, &19, &1e, &00, &07, &00,&00,&30,&00,&c0,&00
;; CRTC data for 60Hz display
05d5 defb &3f, &28, &2e, &8e, &1f, &06, &19, &1b, &00, &07, &00,&00,&30,&00,&c0,&00

--- End code ---

roudoudou:
As MANY CPC productions are neither 50Hz nor 60Hz, maybe a free-sync support?

cpcitor:

--- Quote from: roudoudou on 09:10, 25 May 21 ---As MANY CPC productions are neither 50Hz nor 60Hz, maybe a free-sync support?

--- End quote ---

Hi @roudoudou . Do you mean "neither *exactly* 50 or 60Hz"? Or do you mean they commited to more important deviations?

Can you give examples and elaborate?

roudoudou:
The Abduction of Oscar Z, 20350 nops between each frame in the menu => 49.14Hz
Examples are numerous

TotO:
Well...

If you really want to display the CPC correctly in an emulator, you just have to either display in 100Hz (like SugarBox does) or use a screen that supports 50Hz, and there are a lot of them in LCD, whether it is TV or PC monitors. Youtube can display 50Hz recording too. The problem is not just the frequency but the visual rendering anyway, and an LCD will probably never display CPC as well as a CRT.

Why we have to make 60Hz on a machine, which will therefore penalize users of real CPCs, to have to turn the dial behind their CTM each time it is necessary to change frequencies, to please people who use and program for emulators... We walk on the head.

Most PCs and other tablets / smartphones will be freeSync in the near future, so it's a sword in the water. As a reminder, running a program at 60Hz also means reducing the number of scanlines to display to keep the same machine time per frame.

Finally, if you want to see what 60Hz gives in a game on CPC, just launch Pac-Man Emulator which allows to toggle between 50Hz/60Hz by pressing SPACE from the service menu (TAB).

Navigation

[0] Message Index

[#] Next page

Go to full version
Powered by SMFPacks Media Embedder
Powered by SMFPacks Alerts Pro Mod
Powered by SMFPacks Mentions Pro Mod