I thought I had all timings reasonably under control, but this was not the case. The 128 KB Spectrum models can switch between the normal screen memory (bank 5) and the shadow screen (bank 7) by writing to port #7FFD. This feature can be seen used in demos like this. I had assumed that the actual bank switch would happen instantaneously after the command was received and the correct amount of T-states had passed, but things turned out to be a bit more complicated. There is a suite of test programs zxtests-3 written by Jan Bobrowski which used to be published at http://wizard.ae.krakow.pl/~jb/qaop/tests.html. This site is not online anymore but it can be accessed on waybackmachine.org. These tests are very useful for testing emulation of various timing aspects and they have also sometimes been adapted by developers to examine specific scenarios. In 2014, Patrik Rak did some modifications to the test suite and added a test ptime which examines what happens when the screen memory is switched at different T-states. This is discussed on the World of Spectrum forum here and here. What the ptime test does is that it triggers a screen bank switch at a specific T-state which can be increased or decreased manually. Before the switch, a black screen in bank 7 is displayed, which then switches to this screen in bank 5: As the T-state at which the switch is triggered is increased, a black line from the shadow screen will appear. This is because the switch occurs after the ULA has already begun drawing the screen from the black shadow screen data. I don't have access to any 128 KB machine, but test results from a Spectrum 128 and a +3 were reported in one of the World of Spectrum forum threads and my emulator gave different results.
Generally, to achieve correct timings for the screen, an emulator needs to handle all the Z80 timings exactly correct including effects from memory- and IO-contention. Then, the ULA 8 T-state screen update cycle needs to be simulated (this is the cycle where the ULA fetches pixel and attribute data and the writes the video byte to the screen). Also, there is the timing for when the screen updates begin in a new frame and the time between pixel rows. My emulator had passed all the tests I had come across regarding screen timings so my theory was that the problem concerned the screen memory bank switch specifically . Since my emulator displayed the black line at an earlier point than what was reported for real machines I assumed that there must be a short delay after the OUT command to port #7FFD until the switch occurred. After some experimenting I found that a 3 T-state delay resulted in correct results for Spectrum 128 emulation but I couldn't find a working delay value for the +2A/+3 emulation. It turned out that the solution was to rearrange the screen update cycle slightly for these machines (which have their own version of the ULA) and then add a 2 T-state delay before the screen bank switch. An interesting thing about the update cycle is that in the WOS thread there are two different accounts of how the ptime test behaves on +3 machines. They agree regarding the pattern for the black line, but one report says that the blue pixel in the colored squares disappears just before the line enters the square, while the other report says that the blue pixel remains until it is overwritten by the black line. I noticed that if I let the emulator fetch the attribute byte one T-state after the pixel byte, the blue pixel disappeared as described in one of the reports but then the Megashock demo was broken, so put the pixel and attribute byte fetch in the same T-state. So, now my emulator behaves as reported on the World of Spectrum forum thread (with reservation for the disappearing blue pixels reported by one user). Update 2019-10-02: I found this thread on the World of Spectrum Forums where a similar test (ptime-128) is published, and I was directed by the author to this thread where there are more test reports for the test. SoftSpectrum 48 did in most cases not behave as the tested hardware so I will have to examine this topic further. Update 2019-10-06: The ptime-128 test now works correctly (according the the test results in the WOS threads) for uncontended IO ports, so the +2A/+3 emulation is OK since they don't have any IO contention, but the Sinclair 128K emulation is not correct when contended ports are used. I will get back to this topic to see what can be done.
0 Comments
|
Archives
November 2020
Categories
All
|