Just to mention: Just managed to load a 3-plane image on Video9000 emulation (back frame=v9958, mid frame P1 layer B and front frame P1 layer A)
That is quite a success! I managed to do that with gbasic, but not with regular basic.
could you share the full code?
Beware of doing things for VIDEO9000 instead of GFX9000 and using the v9958 as well, since GFX9000 cannot superimpose it's source with the v9958, and Video9000 users are very scarce.
Anyway, a way to transfer data from v9958 to v9990 from plain basic is very interesting!
So, please share it
Actually, I think that would be no problem. AFAIK, Video9000 implements only one port, that controls the way both (external and V9990's) images are mixed together. The transparency information resides on the Yamaha VDPs (either V99x8 and V9990 have a way to deal with it) and activating it doesn't make a software "Video9000 exclusive", unless you put some Video9000 check (and your software actively refuses to run if it don't find a Video9000 compatible card).
That said, let's check my code!
10 ' SCREEN5 to P1 image copy 20 DEFINTA-Z:SCREEN 0:INPUT"Name";A$ 30 SCREEN 5:BLOAD A$+".SC5",S 100 ' Filling V9990 Name Table information 101 ' Since the SC5 image is only 256x212 pixels, I'll only fill 1/4 table 105 ' Set VRAM address pointer to &H7C000 (Layer A Name Table) 110 OUT 100,0:OUT99,0:OUT99,192:OUT99,7 120 FOR I=0 TO 1023 125 ' Write to VRAM access port a 2-byte value (little endian) containing pattern numbers 130 OUT96,IAND255:OUT96,I\256 (ok, this is slow code, at least this first loop is small) 140 IF I>0 AND IMOD32=0 THEN FOR J=0 TO 63:OUT96,0:NEXTJ 150 NEXT I 200 ' Copying SCREEN5 pixels to P1 Layer A 210 ' Set VRAM address pointer to &H00000 (Layer A Pattern Generator Table) 230 OUT 100,0:OUT99,0:OUT99,0:OUT99,0 (OPS! got overflowed here. Quick and dirty hack, this loop should go through 32767) 240 FORI=0TO32766 245 ' Write to VRAM access port exactly what was read from VDP. (The correct V99x8 SCREEN5 start address is VDP(2) AND 96 * 32768, but this is normally zero) 250 OUT 96,VPEEK(I) 260 NEXTI (I'm used to use INPUT$ instead endless GOTO loops for pausing the code) 270 A$=INPUT$(1)
As you can see, I put some remarks to better explain the code. Note that I used decimal notation for all addresses and register contents, because BASIC handle decimal integers faster than hexa or binary integers. Also I declared all variables as Integers because this makes BASIC (specially FOR loops) faster, and still this is slow as a slug! A BLOAD ,S for V9990 is something that cannot be replaced with BASIC code; Either we'll have to stick with PowerBASIC/GBASIC, or we'll have to make a small ML subroutine to handle this. (and steal some free memory from BASIC)
To fill Layer B, you'll have to change this program to write VRAM addresses &H7D000 (Layer B Name Table) and &H40000 (Layer B Pattern Generator Table), so I duplicated the code:
300 ' Loading Layer B 301 ' Filling V9990 Name Table information 305 ' Set VRAM address pointer to &H7C000 (Layer B Name Table) 310 OUT 100,0:OUT99,0:OUT99,224:OUT99,7 320 FOR I=0 TO 2047 330 OUT96,IAND255:OUT96,I\256 340 IF I>0 AND IMOD32=0 THEN FOR J=0 TO 63:OUT96,0:NEXTJ 350 NEXT I 400 ' Copying SCREEN5 pixels to P1 Layer B 401 ' Set VRAM address pointer to &H40000 (Layer B Pattern Generator Table) 410 BLOAD"mid.sc5",S 430 OUT 100,0:OUT99,0:OUT99,0:OUT99,4 (again, nasty quickfix!) 440 FORI=0TO32766 450 OUT 96,VPEEK(I) 460 NEXTI 470 A$=INPUT$(1)
I also wrote this small program to initialize some V9990 registers to P1 Mode. Until I'm finished, this program should grow a little, as it still don't initialize pallete, BG color, scroll and plane priority registers, et cetera.
1 DEFINTA-Z:CLS 2 ' Initialize Video9000 control port: (note that if you are using a real Video9000 this value will change depending on external video source: CVBS,SVIDEO or RGB. This way we'll have RGB input active and no half tones. Zeroing this value disables Video9000 superimposition circuit) 3 OUT 111,24 4 ' Set Clock source 5 OUT103,0 6 ' Set Control Register 7 ' 130 = display on, 512k VRAM installed, /Ys is not output 8 ' 162 = display on, 512k VRAM installed, /Ys is output 9 OUT100,8:OUT99,162 10 ' Set Screen Mode Registers 11 OUT100,6:OUT99,5 12 OUT100,7:OUT99,0
Hope this is readibly and understandeable enough for you.
Addendum: I found horizontal scroll registers to be a little V9958-ish: the first register only takes on account the 3 lower bits, so to smoothly scroll one horizontal screen completely you'll have to write on two registers as you always did on V9958 (adjust reg and scroll reg). I think that's a bummer if this weren't supposed to be compatible to V9958
Look how I did it on BASIC:
10 DEFINTA-Z 20 FOR X=0 TO 255 30 OUT100,20:OUT99,X/4 40 OUT100,19;OUT99,XAND7 50 OUT100,24;OUT99,(255-X)/4 60 OUT100,23;OUT99,(255-X)AND7 70 NEXT X
And look how scrolling vertically is way simpler:
10 DEFINTA-Z 20 FOR Y=0 TO 211 30 OUT100,17:OUT99,X 40 OUT100,21;OUT99,211-Y 50 NEXT Y
Both codes scrolls Layers A and B to the opposite direction (vertically or horizontally) simultaneously.
Exelent work, tvalenca!!
Yes, your code is very clear and understandable, thanks
I hope this weekend I can test your code, together with all the other codes provided from everyone else during this past week.
I see your code will be perfectly compatible with gbasic+regular turbo-basic, so I will test this on turbo basic as well. If it works correctly, we will be much closer to be able to code for z80 on turbo basic! (only "copy" and "put sprite" equivalents will remain to be "outed" )
Good job!
Addendum: I found horizontal scroll registers to be a little V9958-ish: the first register only takes on account the 3 lower bits, so to smoothly scroll one horizontal screen completely you'll have to write on two registers as you always did on V9958 (adjust reg and scroll reg). I think that's a bummer if this weren't supposed to be compatible to V9958
30 OUT100,20:OUT99,X/4 40 OUT100,19;OUT99,XAND7
V9958 horizontal scrolling is a bit more annoying than just a bit mask, so it’s not so bad . It’s a 11-bit value which doesn’t fit in a single register either way, to put the 8 least significant bits in a register would’ve been slightly more convenient I guess but I’m sure they had their reasons.
[Edit: actually, reviewing some old code, seems like on V9958 just the lower 3 bits needs to be inverted, so it’s not as bad as I remembered.]
MSX2+ horizontal scrolling is a bit more annoying than just a bit mask, so it’s not so bad . It’s a 11-bit value which doesn’t fit in a single register either way, to put the 8 least significant bits in a register would’ve been slightly more convenient I guess but I’m sure they had their reasons.
I talked about how messy was the MSX2+ scroll and I don't remember anymore how it is!
Yes, V9990 uses two 11-bit numbers to slide the "visible window" through the actual image stored on VRAM.
Actually, there are:
Layer A: 13-bit Y coordinate and 11-bit X coordinate
Layer B: 9-bit Y coordinate and 9-bit X coordinate.
My complaint is: WHY the X coordinate bits are scattered trough the registers?
The Y coordinate for both layers are stored on only two registers, and well organized:
b7 , b6 , b5 , b4 , b3 , b2 , b1 , b0 R#17 SCAY07, SCAY06, SCAY05, SCAY04, SCAY03, SCAY02, SCAY01, SCAY00 R#18 * , * , 0 , SCAY12, SCAY11, SCAY10, SCAY09, SCAY08 R#21 SCBY07, SCBY06, SCBY05, SCBY04, SCBY03, SCBY02, SCBY01, SCBY00 R#22 0 , 0 , 0 , 0 , 0 , 0 , 0 , SCBY08 * is not relevant tho this post
But look how messy is the X coordinate registers:
b7 , b6 , b5 , b4 , b3 , b2 , b1 , b0 R#19 0 , 0 , 0 , 0 , 0 , SCAX02, SCAX01, SCAX00 R#20 SCAX10, SCAX09, SCAX08, SCAX07, SCAX06, SCAX05, SCAX04, SCAX03 R#23 0 , 0 , 0 , 0 , 0 , SCBX02, SCBX01, SCBX00 R#24 0 , 0 , SCBX08, SCBX07, SCBX06, SCBX05, SCBX04, SCBX03
So why, Yamaha, WHY???
Could they (Yamaha) possibly though that MSX developers liked scrolling on 8 pixels at once?
Probably, horizontally the per-1-pixel offsets are handled in a different manner than the per-8-pixel offsets. E.g. the one pixel offsets are handled like “set adjust” in MSX-Basic, but the eight pixel offsets are done by offsetting and wrapping the VRAM read address. (Remember that e.g. P1 works based on 8x8 tiles.)
I can imagine that it would simplify the logic if when the data lanes for these two mechanisms just have to connect to one register in stead drawing from two.
Anyway nice to see you guys having fun with the V9990. Honest, also makes me itch a little ;p.
It's like someone said: (don't remember who)
There are no limitations, just fun!
Still, I would like to have a complete BASIC solution for it. Even if I have to write it myself.
This third option has proven to leave projects in vaporware way too many times.
I am looking for a way to achieve results quickly and easily, so the chances to finish a project are higher.
The third option takes too long and it seems to be the problem with most projects beyond msx1 small games.
I partially agree with you because I think it would be good to have some tools to make easier develop with asm. For example, a pre-built code just to use or graphic libraries or what else.
Anyway, I'm keen on MSX-BASIC code
Then I have good news for you:
ASM graphic libraries to use GFX9k on ASM and even on C:
https://www.teambomba.net/gfx9klib.html
Here are also several useful tools as well.
Enjoy!
I knew that. I meant compact tools for all MSXs with IDE for developing.
Sorry for miswriting
Is there any FPGA implementation of V9990? And if, how complete?
zPasi: no.
I do not quite understand what you mean, and probably you did not understand me either, because it is not a nightmare at all, as a matter of fact it is quite simple.
I think that what Manuel is saying is that if you detect a bug in the common code for all stage*.bas, then you have to correct all the stage*.bas and test them all again. That's the "nightmare" of code duplication.
That's exactly what I meant. And the bug is only an example. What if you want to change the structure of things? Or improve the performance? Or add a new feature?