Accurate FDC Timing

3 November 2004

DMAC

All the wiring and DMAC registers now work as expected.

Manual Data Requests

We then set out to find out about using manual data requests (as opposed to DMA-driven ones), that are possible with the WDC1772 but are not mentioned in any Atari documents. After some investigation, we found that it does indeed work. It would be interesting to see if any programs ever used this since it is not documented.

There is one catch though; WinSTon is a line based engine and can call FDC update routines at each horizontal blank. This means data loss will occur if a program polls the FDC, whereas on the real hardware it always works since the read loop is very fast. This could be fixed by either “slowing down” the drive when non-DMA FDC usage detected, or maybe it is possible to call an FDC update on each attempt of manual DRQ... But they are both a bit of a bodge, and we do not like bodges.

WinSTon System Speed

We are now scrutinising how the emulated system speed is done in WinSTon with a view to fixing the problem with manual data requests above. Unfortunately, there is no cycle count as such, only a countdown to next interrupt event. Apparently however, the sound code had the exact same problem that we now have with the FDC code: cycle exactness was needed.

The sound code has a system clock, and that is used to sync the sound up to the real number of system clock cycles elapsed between each sound update. To keep data flowing, the sound update is called at each time a sound register is accessed (so sound modulation etc., are cycle exact this way) as well as to keep it kicking once each frame. The sound buffer based on the elapsed system clocks is generated up to the actual system clock count (i.e., the sound chip spends the same time running in “parallel” with the system. In reality it of course runs in its own timeslice up to the point of “now” from the point of last update).

The point is that by using the sound system, we think it is possible to create a similar method for accurate FDC emulation. That is, each time the FDC is accessed “manually” (i.e. CPU access) the FDC will execute whatever happened since last time it was accessed. Also, to keep it kicking, the update will be called at each horizontal blank as well. This way, manual polling will work as long as the original code worked in the first place and the emulator cycles are somewhat correct.

If the FDC is polled (accessed through the CPU instead of DMA), it will be up-to-date so it works, but will obviously be a system hog to emulate. If the FDC is run with DMA, manual updates will never be triggered, just the usual way to keep it kicking at each horizontal blank, so emulation speed will not be affected.

What happens if sound is disabled is currently unclear. The cycles are correctly counted but there might be problems. This can be solved by still emulating sound, just disabling the output.

Keeping all the above in mind, we then changed the original sound related system clock to real system clocking. Sound, FDC or whatever else clock cycles elapsed since last update can be derived from the system clock at any time. It will fail if more than 2^31 cycles passed since last update but that is only likely when emulating 2GHz CPU, not a 8MHz one...

Okay, we are happy again now.