Hi! This year I've started to learn Z80 assembly and do some coding experiments on the Spectravideo 328, so I've been reading up on the TMS9918A, Z80 and so on. I have experience from programming C64 / 6502 for about a decade. Currently I'm developing with WLA-Z80 and testing in the OpenMSX emulator, as well as programming an EEPROM cartridge now and again for testing on my real SV-328.
To set the stage, when I started developing on C64, the first step (the easiest way) to get going to sync code to each video frame was to make a loop that checked the current rasterline on the VIC-chip until a certain rasterline occurred, then execute the code for that video frame and return back to the loop to wait for the next rasterline occurrence.
The next logical step from there was to setup an IRQ that pointed to the frame code and make the VIC-chip generate the interrupt, so that no "check rasterline loop" was necessary.
I'm at the first step on the SV-328. I understand that the TMS9918A sets a frame flag (7th bit) when it reaches the last active line of the video frame, and every time you read the register the frame flag is reset. The code I've used until now has been:
VdpStatus = $85 (on Spectravideo) - in a, (VdpStatus) ; read value from VdpStatus cp $7f jr c, - ; wait until frame flag is set (carry is set if greater than $7f)
So now to my problem. In OpenMSX (emulating SV-328) this works perfectly. On my real SV-328 however it ...mostly works? It works maybe 90-95% of the time, but now and again it's like it doesn't register the frame flag for that video frame (but still resets it), so it will wait a complete frame until the next flag is set.
My questions are:
- Is this behaviour unique to SV-328 or does it happen on MSX machines too?
- Why does it happen? Is this a timing issue, perhaps I am reading the VdpStatus too often?
- Is this solved completely by setting up an IRQ instead?
Thanks for reading!