On MSX1 the function "SetSpritePattern" ends by setting 'sprite pattern generator table' (VDP register #6) to 0000h instead of 3800h. It is not wanted but perhaps it is a succession of "OUT" too fast that causes the problem
You can write to VDP registers at any speed you wish. The access speed restriction only applies to VRAM writes (due to the underlying "access slots" system). So there must be another cause.
Although I do notice in the Fusion-C source on Github it seems to use OTIR for outputting VRAM data to 98H (see OutPorts called from SetSpritePattern), which is too fast for the TMS9918 (23 cycles where 29 are required), so the pattern would appear corrupted on a real MSX1.
Yes, two problems with "VDP" Fusion-C functions on MSX 1 ;
- function OutPorts uses otir on 98h port > causes corrupted data in pattern
- function VpokeFirst sets VRAM address (to write) using ACPAGE system parameter, which is a MSX 2 parameter > causes 'sprite pattern generator table' set to 0000h
Ok I see ! C Is too fast for MSX1
So how can I fix that with a smart solution ?
Fix the library and send patches to Ericb .
As for workarounds, you could blank the screen while setting up the patterns, then the transfer speed limit to I/O port 98H is temporarily lifted. And you could manually initialise the ACPAGE system variable to the expected value if it runs on MSX1.
On MSX1 the function "SetSpritePattern" ends by setting 'sprite pattern generator table' (VDP register #6) to 0000h instead of 3800h. It is not wanted but perhaps it is a succession of "OUT" too fast that causes the problem
workaround:
By adding VDPwrite(6,7);
after the last SetSpritePattern, sprites will be displayed.
This workaround didn't work.
Also Calling HideDisplay(); before and ShowDisplay(); after didn't work as a workaround.
Neither did doing both suggested workarounds in combination.
Ok I see ! C Is too fast for MSX1
So how can I fix that with a smart solution ?
Maybe some inline assembler NOPs, adding enough cycles to wait for the slower VDP. Not too many people would be calling SetSpritePattern in a loop, so the extra cycles wouldn't matter too much.
Ok I see ! C Is too fast for MSX1
So how can I fix that with a smart solution ?
Haha, I missed that I was responding to ericb. He can send patches to himself .
As for ACPAGE, you should check the MSX version and simply not set register 14 when it’s <2. Due to mirroring (AND 7) any register access >= 8 will overwrite another register on TMS9918.
As for the loop in OutPorts, change the outi
to:
Loop: outi jr nz,Loop
That takes 31 cycles per loop instead of 23, and satisfies the VDP transfer speed requirement of 8 µs. Since this is slower than necessary for other transfers, you may want to consider making a version of OutPorts specific for VRAM transfer.
On MSX1 the function "SetSpritePattern" ends by setting 'sprite pattern generator table' (VDP register #6) to 0000h instead of 3800h. It is not wanted but perhaps it is a succession of "OUT" too fast that causes the problem
workaround:
By adding VDPwrite(6,7);
after the last SetSpritePattern, sprites will be displayed.
This workaround didn't work.
Also Calling HideDisplay(); before and ShowDisplay(); after didn't work as a workaround.
Neither did doing both suggested workarounds in combination.
I don't have MSX1 with disk system to try, but with openMSX it works for me with Panasonic CF-2700 configuration :
And you could manually initialise the ACPAGE system variable to the expected value if it runs on MSX1.
This workaround (writing 0 there) is no good since I didn’t realise it is overwriting register 6 due to mirroring. You could set ACPAGE to 7 (on MSX1 only!), but it’s a bit yucky. A better workaround is the one suggested by akumajo, calling VDPwrite(6,7); after writing to VRAM to restore register 6. It’s best to patch the library though, like I described earlier.
Instead of using the Ouports function inside the SetSpritePattern, I can use the CopyRamToVram function
-> its source code is inside source/lib/vram.s
It's a port of msx-c routine from Ascii. And it includes vdp write routine that works for MSX1 and MSX2
I think this will solve the problem.
What do you think ?