Is it just the vram data that is corrupted when doing a to fast write and will the vram pointer be updated ok?
According to OpenMsx the vram pointer is not incremented, unfortunately.
I have a splitline in my code, where I want to update ONLY the y variable of several (bordermasking) sprites.
So my code looks like this:
ld hl,BorderMaskingSpat
ld c,$98 ;port to write to and deal with the nop required wait time
outi | nop | in a,($98) | in a,($98) | in a,($98) ;write new y value, then increase vram pointer 3x
outi | nop | in a,($98) | in a,($98) | in a,($98) ;write new y value, then increase vram pointer 3x
.... repeat
The first OUTI is to write the new Y value to the Spat, then I use 3x in a,($98) just to increment Vram pointer.
Unfortunately it doesn't work. I don't have a real msx to test, so it could be working on a real msx.
Instead I have to transform this into:
ld hl,BorderMaskingSpat
ld c,$98 ;port to write to and deal with the nop required wait time
outi | nop | in a,($98) | nop | in a,($98) | nop | in a,($98)
outi | nop | in a,($98) | nop | in a,($98) | nop | in a,($98)
.... repeat
The extra wait in between the in command's are required (even if you ONLY want to increase Vram pointer).
At least in Openmsx....
If someone wants to test this on a real msx, it's worth testing it imo...
@Grauw... I would not mind, if you could review and add some missing details here, if you have better information:
https://www.msx.org/wiki/VRAM_access_speed
... These timing things have always been a total mystery to me... That is why I code for MSX tR instead. :)
Ok, let’s take a look…
In most cases MSX programmer does not need to think about speed while accessing VRAM since typically the minimum wait time between VRAM accesses is equal to 13 Z80 clock cycles (@3.58MHz)
If I read the V9938 VRAM timings (part 1) article, in section “position of access slots” it says the maximum gap between slots is 70 VDP cycles, and in section “allocation of access slots” it says the setup time for a write is 16 VDP cycles. In the section “too fast CPU access” it concludes that the minimum wait time is the sum of these, iow 86 VDP cycles or 14.33 CPU cycles.
- Sprites enabled: 70 + 16 = 86 VDP cycles (14.33 CPU cycles)
- Sprites disabled: 54 + 16 = 70 VDP cycles (11.67 CPU cycles)
- Screen disabled: 44 + 16 = 60 VDP cycles (10 CPU cycles)
- TEXT1 & TEXT2: 100 + 16 = 116 VDP cycles (19.33 CPU cycles)
The 14.33 cycles rounded up to 15 matches the title of this topic. I don’t know what the source is of that 13 cycles number on the wiki page, but it matches none of the above. The 20 cycles it mentions for TEXT2 does match, but this actually also applies to TEXT1 mode (width 40), as V9938 VRAM timings (part 2) mentions explicitly.
Edit: Oh look, the MAP already had this info in a nice table, including references to sources :).
while typical I/O instruction on MSX takes 12 cycles + two M1-waitstates, so total 14 cycles.
I’m not sure indirect I/O instructions (out (c),r
) are “typical”, direct addressing (out (n),a
) is used a lot, it seems the text should mention the both of them and also (or only) consider the faster one.
On V9958 it is possible to enable automatic waitstate insertion.
Since the wait line of the V9958 is not hooked up in any machine, this is not really the case. I suggest to either remove this line, or elaborate that it is not hooked up, otherwise it will mislead the reader.
Do not read or write to VRAM directly after the VRAM address setting on MSX1. (Wait a little with 3 x NOP for example before send data to the VRAM)
I thought this wait is only needed for reading? To allow the VDP to fetch the value? Since it is already mentioned in the bullet points earlier, where it says the read setup time is 10 cycles (source?), I don’t think it needs repeating in more vague statements like “wait a little”. Though maybe it is different for TMS9918, but that’s not very clearly stated then.
Use OUTI/INI and JP PE,$-2 instead.
Pretty sure this should be jp nz
.
This is also why I never go to to the wiki pages on MRC and prefer msx MAP.
@Grauw, a bit off topic, have you seen my email about msx map on R18 and vdp commands?
just got confirmation. Tested on a real msx
in a,($98) | nop | in a,($98)
If you leave out the nop, the Vram pointer is not incremented
So, did I understand correctly that the openMSX behaviour matches the real MSX behaviour here?
This is also why I never go to to the wiki pages on MRC and prefer msx MAP.
I rely on the MRC wiki for a lot of things, I respect the work put in by everybody, and I contribute to it too. But for programming articles I like to see a clear author and maintainer, source references, experimental confirmation. Not to say the MAP is perfect, but I think it’s harder to achieve on a wiki.
@Grauw, a bit off topic, have you seen my email about msx map on R18 and vdp commands?
Yes I have! Thanks for informing me. I will update it after I confirm, I sent a reply in the meanwhile.
just got confirmation. Tested on a real msx
in a,($98) | nop | in a,($98)
If you leave out the nop, the Vram pointer is not incremented
Great, good to know!
So, did I understand correctly that the openMSX behaviour matches the real MSX behaviour here?
yes
just got confirmation. Tested on a real msx
in a,($98) | nop | in a,($98)
If you leave out the nop, the Vram pointer is not incremented
You should test this also by displaying an image. If the pointer was not incremented in just one of the written pixels, you get a 45 degree angle (leftside) in the displayed gfx. I never saw this happen in any of my projects but only some pixels being corrupted.
CORRECTION: It does happen :-)
Whoooaaa. I finally manned up and read this deep tech article. This is totally insane puzzlework by the openmsx team (et. al)! I am amazed. We are all very grateful to the work put down here. Where is the Oscars in retro- and reverse engineering tech? Or the "Nobel Prize in Retro-Computing"?
I also found the material from Karl Guttag super amusing. Fantastic insight to the history of computing right there