V9990 Initialising

Por HAL6128

Supporter (2)

Imagen del HAL6128

26-03-2023, 20:06

Hello MSX community,
pretty new to this forum I'm a Amstrad CPC user who bought a V9990 Powergraph graphic card for the CPC computer range.

Of course I have already read a lot about the V9990 from your site (V9990) and I was running e.g. a demo (youtube) which is spread around, I'm eager to write own programs using the VDP. But first I have to understand the principles of that card.
I tried this by disassembling the files of the demo. And, of course, it is not as simple as I thought in the very first beginning.

The demo itself is splitted into different parts ([url=https://www.cpcwiki.eu/forum/amstrad-cpc-hardware/using-symbos-with-the-gfx9000-(msx-grapics-card)/msg156979/#msg156979]robot file[/url]).
Where the other parts are simple enough to understand (loading background into VRAM or controlling the sprites) is the the first part of the demo - the file is called "clear" not so "clear". I stumbled over a question which I wasn't able to answer and hopefully one of you might be able to answer?
Disassembling the file showed following steps:
1. Detection of the V9990 (just simple > write a value into VRAM, read it back and compare)
2. Reset the V9990 by IN the register DISPLAY ADJUST > set all ports to 0 (SYSTEM CONTROL Register) > set XTAL1 terminal
(SYSTEM CONTROL Register) > restore DISPLAY ADJUST > disable cursor + select 512kB VRAM > (CONTROL Register)
> reset palette pointer > and set all 64 colours (RGB) to 0

now here comes two parts which I don't understand

As far as I have seen the demo works generally in P1 Mode (two screen which are scrolling parallax) but first in step
3. there is SCREEN MODE Register (#6) set with a Bitmap-Mode (&97) for the sprites (&07F080 address VRAM)
and
4. SCREEN MODE Register (#6,7) is set with P1 Mode set.

Is this possible to set two different modes on the V9990?
I mean, if I delete the first SCREEN MODE Register set then the sprites (of the jumping robot) are missing.
And if I delete the second SCREEN MODE Register set part then the background is missing.

I'm somehow lost and I need some guidance.
You are much more experienced than me!

Login sesión o register para postear comentarios

Por Prodatron

Paragon (1843)

Imagen del Prodatron

27-03-2023, 13:29

Hi CPC fellow, maybe you can have a look at G9KLIB written by MSD (finally he is alive again Tongue ), it should help a lot:
https://www.teambomba.net/gfx9klib.html

Check the files g9klib.asm (see "SetScreenMode") and g9klib.inc (see registers "G9K_SCREEN_MODE0", "G9K_SCREEN_MODE1" and the bit definitions at "G9K_SCR0_..." and "G9K_SCR1_...").

You can find the settings for each mode at G9K_MODE_TABLE in g9klib.asm. There are additional settings like image size and bits per dot, which can be used in different modes. I am not familiar with the pattern modes, but I am using these standard settings for the bitmap modes, and it works well.

You can't activate bitmap and pattern mode at the same time. Also there are no sprites in bitmap mode, they are only available in pattern mode (in bitmap mode you only have a "cursor", which can be used e.g. for the mouse pointer).

Por HAL6128

Supporter (2)

Imagen del HAL6128

27-03-2023, 14:20

Hi Prodatron!!
Thank you for the link & hint to the library.

What I have seen from the disassembly of the "clear." file is that it follows in the beginning the g9ktest.asm file of the library.
But it includes a weird third step where there's a call to the code below (call setscreenmode1).
In the forth step there's another call to the setscreenmode2 call (as it is in the library, with a modetable and so on).

For what reason is the 3. CALL ? (It defines a VRAM address to &07F080 and then set a Bitmap mode not completly). Maybe I have misunderstood the step?

In the 4. CALL with Register A = 0 (= G9K_SCR0_P1 EQU 0 ; Select P1 mode) and with BC = &0104 = (G9K_SCR0_4BIT; EQU 1 ; 4 bits/dot // G9K_SCR0_XIM512 EQU 4 ; Image size = 512) is sets the P1-Mode.

I wonder why?

;Ports
	System_Control	equ #FF67
	Register_Data 	equ #FF63
	Register_Select equ #FF64
	Palette_Data	equ #FF61
	VRAM_Data 	equ #FF60
	Output_Control	equ #FF6F
;Register
	REGISTER_vram_write_address equ #0 	;0   Register VRAM Write address set
	REGISTER_vram_read_address equ #3 	;3   Register VRAM Read address set
	REGISTER_palette_control equ #D		;13  Register PALETTE CONTROL
	REGISTER_palette_pointer equ #E		;14  Register PALETTE POINTER
	REGISTER_sprite_pattern_generator	;25  Register SPRITE PATTERN
	REGISTER_argument equ #2C			;44  Register ARGUMENT
	REGISTER_logical_operation equ #2D	;45  Register LOP
	REGISTER_write_mask equ #2E			;46 - 47 Register WRITE MASK
	REGISTER_font_color					;48 - 49 Register FONT COLOR
;+++ MAIN PROGRAM +++
org #6000
; detect V9990
	CALL detect
	RET NZ				; if not detected return to BASIC
; reset V9990
	CALL reset
; set screen mode (part 1 - sprites / robot + fire & jumping light) ????
	CALL    screenmode1
; set screen mode second time (part 2 - background Pattern Mode 1)	
	LD      A,#00		; (00) Pattern Mode 1
	LD      BC,#0104	; B = 1 (512 dots) / C = 4 (Image size)
	LD      DE,#0000	; D = 0 (no interlace) / E = 0 (No Palette control register)
	CALL    screenmode2

...


; --- START PROC screenmode1 ---
screenmode1: 
	DI
	PUSH    BC
		;set VRAM Write address &07F080
        LD      A,#00				; VRAM WRITE ADDRESS select R#0
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#80				;&80
        LD      BC,Register_Data
        OUT     (C),A
        LD      A,#01				; VRAM WRITE ADDRESS select R#1
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#F0				;&F0
        LD      BC,Register_Data
        OUT     (C),A
        LD      A,#02				; VRAM WRITE ADDRESS select R#2
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#07				;&07
        LD      BC,Register_Data
        OUT     (C),A
		
		;set SCREEN Mode
        LD      A,#06				; SCREEEN MODE Register (6)
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#97				; (97) %1001 0111 (151) = 1. Nibble = Bitmap mode + XTAL1/2_MCKIN/2 - 2. Nibble = 512 dots + 16 bits/dot
        LD      BC,Register_Data
        OUT     (C),A

		;set Control
        LD      A,#08				; CONTROL Register (8)
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#A2				; %1010 0010 (162) = Display appear according to VRAM content + Sprite displayed - YS enable + read transfer is executed - VRAM write transfer is not executed + DREQ terminal remain high - 256k word x 4 bit VRAM configuration (512k byte)
        LD      BC,Register_Data
        OUT     (C),A
	POP     BC
	EI
	RET

; --- START PROC screenmode2 ---
; Input:
; A = Mode (Pattern-Mode (P1=0,P2=1) Bitmap-Mode (B1=2 to B6=7))
; B = Bit per dot
; C = Image size
; D = Interlace
; E = Palette control register
screenmode2:  
	DI
	LD      L,A
	ADD     A,A
	ADD     A,L				; A = A*3 > after 3 bytes of data there will be another screen configuration
							; offset 0,3,6,9,12,15 (2 Pattern & 6 Bitmap configurations)
							; P1 = 0 > A = 0
	LD      HL,modetable	; Mode table address
	ADD     A,L				; add address to A to get offset entry
	LD      L,A				; HL will become right entry (nothing changed if A = 0)
	JR      NC,setscreenmode_1		; just in case if address became > 255
	INC     H
setscreenmode_1:  
	LD      A,06h			; select Screen Mode register (R#6)
	PUSH    BC
        LD      BC,Register_Select
        OUT     (C),A
	POP     BC
	LD      A,(HL)			; get first byte out of table (Mode + Dot clock)
	INC     HL				; pointer to next byte
	OR      B				; mask A with bits per dots
	OR      C				; mask A with image size
	PUSH    BC
        LD      BC,Register_Data
        OUT     (C),A		; write value to R#6
	POP     BC
	LD      A,(HL)			; get second byte out of table (Interlace + different selection)
	INC     HL				; pointer to next byte
	DEC     D
	INC     D				; testing of D = 0 (interlace / no interlace)
	JR      Z,setscreenmode_2			; if no go to setscreenmode_2
	OR      06h							; if yes then mask A with #06 (%0000 0110)
setscreenmode_2:
	PUSH    BC
        LD      BC,Register_Data
        OUT     (C),A		; write value to R#7
	POP     BC
	LD      A,(HL)			; get third byte out of table (System Control Value / Master clock)
	PUSH    BC
        LD      BC,System_Control	; select SYSTEM CONTROL Port
        OUT     (C),A		; write value
	POP     BC

	PUSH    BC
        LD      A,#0D		; choose Palette Control Register (13)
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,E			; load palette number
        LD      BC,Register_Data
        OUT     (C),A
	POP     BC
	EI
	RET

; +++ Tables

modetable:
	db 0,0,0		;Pattern mode 1      (P1)
	;DB G9K_SCR0_P1 (0) + G9K_SCR0_DTCLK4 (0)
	;DB 0
	;DB G9K_SYS_CTRL_XTAL (0)
	
	db #40,0,0		;Pattern mode 2      (P2)
	;DB G9K_SCR0_P2 (64) + G9K_SCR0_DTCLK4 (0)
	;DB 0
	;DB G9K_SYS_CTRL_XTAL (0)
	
	db #80,0,0		; Bitmap 256 * 212    (B1)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK4 (0)
	;DB 0
	;DB G9K_SYS_CTRL_XTAL (0)

	db #90,0,#01	; Bitmap 384 * 240    (B2)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK2 (16) = 144 (#90)
	;DB 0
	;DB G9K_SYS_CTRL_MCKIN (1)

	db #90,0,0 		; Bitmap 512 * 212    (B3)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK2 (16) = 144 (#90)
	;DB 0
	;DB G9K_SYS_CTRL_XTAL (0)
	
	db #A0,00,#01 	; Bitmap 768 * 212    (B4)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK (32) = 160 (#A0)
	;DB 0
	;DB G9K_SYS_CTRL_MCKIN (1)
	
	db #A0,#01,00 	; Bitmap 640 * 400    (B5)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK (32) = 140 (#A0)
	;DB G9K_SCR1_HSCN (1)
	;DB G9K_SYS_CTRL_XTAL (0)

	db #A0,#41,00	; Bitmap 640 * 480    (B6)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK (32) = 140 (#A0)
	;DB G9K_SCR1_HSCN (1) + G9K_SCR1_C25M (64) = 65 (#41)
	;DB G9K_SYS_CTRL_XTAL (0)

	db #A0,00,00	; Bitmap 1024 * 212   (B7) (undocumented mode)
	;DB G9K_SCR0_BITMAP (128) + G9K_SCR0_DTCLK (32) = 140 (#A0)
	;DB 0
	;DB G9K_SYS_CTRL_XTAL (0)

Por Prodatron

Paragon (1843)

Imagen del Prodatron

28-03-2023, 10:41

This part of the "screenmode1" routine...

		;set SCREEN Mode
        LD      A,#06				; SCREEEN MODE Register (6)
        LD      BC,Register_Select
        OUT     (C),A
        LD      A,#97				; (97) %1001 0111 (151) = 1. Nibble = Bitmap mode + XTAL1/2_MCKIN/2 - 2. Nibble = 512 dots + 16 bits/dot
        LD      BC,Register_Data
        OUT     (C),A

...doesn't make sense for me. Register #6 is overwritten/set again in the next call ("screenmode2" routine), so this part seems to be useless. Maybe they reused code from another project and just copied it in.
What happens, if you leave it out?
The other parts of the "screenmode1" routine are probably required.

Por pizzapower

Master (165)

Imagen del pizzapower

28-03-2023, 15:02

Hey, HAL6128. I recommend you visit MSX Banzai! or study the MSX Top Secret pdf. This is how I set P1 mode:

        ; Set MCS=XTAL1 (1st LSB)
        ld      a, #0x00
        out     (0x67), a ; system control port
        ; select R#6
        ld      a, #0x06
        out     (0x64), a ; register select port
        ; write 0x05 to R#6
        ld      a, #0x05
        out     (0x63), a ; register data port
        ; write 0x00 to R#7
        ld      a, #0x00
        out     (0x63), a ; register data port
        ; select R#13
        ld      a, #0x0d
        out     (0x64), a ; register select port
        ; write 0x00 to R#13
        ld      a, #0x00
        out     (0x63), a ; register data port