Hallo all !
Got a question about the mandatory wait states between reads and writes.
I read that you have to wait 15 T-states (on msx2, screen 5, while not on Vblank or when screen is disabled) in between reads and writes.
On http://map.grauw.nl/articles/vdp_tut.php I found this piece of code:
SetVdp_Write:
rlc h
rla
rlc h
rla
srl h
srl h
di
out (#99),a
ld a,14 + 128
out (#99),a
ld a,l
nop
out (#99),a
ld a,h
or 64
ei
out (#99),a
ret
So I see there is a nop placed, to wait in between the two out (#99),a instructions.
the ld a,l is only 4 T-states and the nop is also 4 T-states.
That means there are 8-states in total in between the two out (#99),a instructions.
But we have to have 15 T-states.....
That's when I realised that the out (#99),a are actually 3 instructions/cycles.
out (#99),a 3 cycles 11 Tstates(4,3,4)
The first (4 T-states) cycle and the second (3 T-states) cycle set the address, while only the third (4 T-states) cycle actually writes the data.
So if you have
out (#99),a 3 cycles 11 Tstates(4,3,4)
ld a,l 1 cycle 4 Tstates(4)
nop 1 cycle 4 Tstates(4)
out (#99),a 3 cycles 11 Tstates(4,3,4)
You do actually have exactly 15 T-states in between the write instructions.
ld a,l (4) + nop (4) + the first two cycles of out (#99),a (4,3) = 4 + 4 + 4 + 3 = 15 T-states.
I finally understand the required nop instruction now.
Please correct me if I'm wrong.
I wanted to optimise my own code, and removed the nop (because I didn't do the math, and didn't understand it properly).
On BlueMsx it worked fine, but then on OpenMsx it was a mess.
I realise that the required wait states are not emulated on Bluemsx.
ok, fine... Now comes my real question:
Up until now I wrote my Spat (sprite attribute table) like this:
ld hl,spat ;sprite attribute table
ld c,$98 ; port to write to
call outix128 ; 32 (sprites) * 4 bytes
now this is all good and well. Every sprite has 4 bytes in the spat:
y, x, pattern number, color code
I realised I never use the 3d and the fourth byte (I set them only once at initialisation), so I tried to speed up my routine, removed the 3d and 4th byte of each sprite in my spat in ram, and changed the routine into this:
ld hl,spat ;sprite attribute table
ld c,$98 ; port to write to
outi|outi|in a,($98)|in a,($98)
outi|outi|in a,($98)|in a,($98)
outi|outi|in a,($98)|in a,($98)
... 32 times
So basically the first outi is to write the y coordinate, the second outi is to write the x coordinate and then I use two times in a,($98) ONLY to increment the vram pointer. I have no interest in the value that is returned in a.
Once again... this piece of code works fine in BlueMsx, but OpenMsx says: Nah ah !!
So my question is, how exactly should I make the above code ?
Should it be this:
outi|outi|nop|in a,($98)|nop|in a,($98)
outi|outi|nop|in a,($98)|nop|in a,($98)
outi|outi|nop|in a,($98)|nop|in a,($98)
... 32 times
or this:
outi|outi|nop|in a,($98)|nop|nop|in a,($98)
outi|outi|nop|in a,($98)|nop|nop|in a,($98)
outi|outi|nop|in a,($98)|nop|nop|in a,($98)
... 32 times
and why ?
both of the above 2 examples work fine in OpenMsx, but the first one doesn't respect 15 T-states between the two in a,($98) instructions...
Please advise