; Product : Gfx9000 library
; Version : 0.7
; Main code by : Marcel delorme
; Support code : BiFi
; Bitbust : Arjan Bakker
include "g9klib.inc"
MODULE G9k
;----------------------------------------------------------------------------;
; Gfx9000 general functions ;
;----------------------------------------------------------------------------;
Reset:
; Function : Resets v9990, Deletes Palette, Sprites off,stops current blit operation, puts V9990 in correct RAM config and disables display
; Input : None
; Output : None
; Notes : Doesn't change current adjust
; Modifies : A,B
G9kReadReg G9K_DISPLAY_ADJUST + G9K_DIS_INC_READ
PUSH AF ; Save adjust value
; Set reset state
LD A,G9K_SYS_CTRL_SRS
OUT (G9K_SYS_CTRL),A
; Clear reset state
XOR A,A
OUT (G9K_SYS_CTRL),A
POP AF
OUT (G9K_REG_DATA),A ; Restore adjust value
G9kWriteReg G9K_OPCODE,G9K_OPCODE_STOP
G9kWriteReg G9K_CTRL,G9K_CTRL_DIS_SPD+G9K_CTRL_VRAM512
; Clear current palette
G9kWriteReg G9K_PALETTE_PTR,0 ; A becomes 0
LD B,64 * 3
OUT (G9K_PALETTE),A
DJNZ $-2
; OUT (G9K_OUTPUT_CTRL),A ; Set output GFX9000
RET
SetScreenMode:
; A = Mode
; B = Bit per dot
; C = Image size
; D = Interlace
; E = Palette control register
LD L,A
ADD A,A
ADD A,L ; A = A * 3
LD HL,G9K_MODE_TABLE
ADD_HL_A
LD A,G9K_SCREEN_MODE0
OUT (G9K_REG_SELECT),A
LD A,(HL) ; Get fixed settings for mode reg 6
INC HL
OR A,B ; Set bits per dot
OR A,C ; Set image size
OUT (G9K_REG_DATA),A
LD A,(HL) ; Get fixed settings for mode reg 7
INC HL
DEC D
INC D ; Is d 0?
JR Z,$+4
OR A,G9K_SCR1_EO+G9K_SCR1_IL
OUT (G9K_REG_DATA),A
LD A,(HL)
OUT (G9K_SYS_CTRL),A
G9kWriteReg G9K_PALETTE_CTRL,e
RET
G9K_MODE_TABLE
; Pattern mode 1 (P1)
DB G9K_SCR0_P1+G9K_SCR0_DTCLK4
DB 0
DB G9K_SYS_CTRL_XTAL
; Pattern mode 2 (P2)
DB G9K_SCR0_P2+G9K_SCR0_DTCLK4
DB 0
DB G9K_SYS_CTRL_XTAL
; Bitmap 256 * 212 (B1)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK4
DB 0
DB G9K_SYS_CTRL_XTAL
; Bitmap 384 * 240 (B2)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK2
DB 0
DB G9K_SYS_CTRL_MCKIN
; Bitmap 512 * 212 (B3)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK2
DB 0
DB G9K_SYS_CTRL_XTAL
; Bitmap 768 * 212 (B4)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK
DB 0
DB G9K_SYS_CTRL_MCKIN
; Bitmap 640 * 400 (B5)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK
DB G9K_SCR1_HSCN
DB G9K_SYS_CTRL_XTAL
; Bitmap 640 * 480 (B6)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK
DB G9K_SCR1_HSCN+G9K_SCR1_C25M
DB G9K_SYS_CTRL_XTAL
; Bitmap 1024 * 212 (B7) (undocumented mode)
DB G9K_SCR0_BITMAP+G9K_SCR0_DTCLK
DB 0
DB G9K_SYS_CTRL_XTAL
SetAdjust:
; Function: Adjustment of Gfx9000 display
; L/T C R/B
; Input : BC => B -> Horizontal adjustment (-7 -> 0 -> 8)
; C -> Vertical adjustment (-7 -> 0 -> 8)
; Modifies: AF, BC
;
LD A,B
ADD A,7
CP 16
CCF
RET C ; ERROR IN HORIZONTAL ADJUST
SUB 7
NEG
AND 15
LD B,A
LD A,C
ADD A,7
CP 16
CCF
RET C ; ERROR IN VERTICAL ADJUST
SUB 7
NEG
AND 15
RLCA
RLCA
RLCA
RLCA
OR B
LD B,A
G9kWriteReg G9K_DISPLAY_ADJUST,B
RET
SetVramWrite:
; Function : Sets Vram write address
; Input : E:HL VRAM address
; Output : none
; Modifies : A,C
LD A,G9K_WRITE_ADDR
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
OUT (C),L
OUT (C),H
OUT (C),E
RET
SetVramRead:
; Function : Sets Vram read address
; Input : E:HL VRAM address
; Output : none
; Modifies : A,C
LD A,G9K_READ_ADDR
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
OUT (C),L
OUT (C),H
OUT (C),E
RET
Detect:
; Input : none
; Output : Z=detected , NZ=not detected
; Modifies : A,C,E,H,L,F
; Works but could be saver
LD E,0
LD H,E
LD L,E
CALL SetVramWrite
LD A,0A2h
OUT (G9K_VRAM),A
LD E,0
LD H,E
LD L,E
CALL SetVramRead
IN A,(G9K_VRAM)
CP A,0A2h
RET
DisplayEnable:
; Modifies A
G9kReadReg G9K_CTRL+G9K_DIS_INC_READ
OR A,G9K_CTRL_DISP
OUT (G9K_REG_DATA),A
RET
DisplayDisable:
; Modifies A
G9kReadReg G9K_CTRL+G9K_DIS_INC_READ
AND A,255-G9K_CTRL_DISP
OUT (G9K_REG_DATA),A
RET
SpritesEnable:
; Modifies A
G9kReadReg G9K_CTRL+G9K_DIS_INC_READ
AND A,255-G9K_CTRL_DIS_SPD
OUT (G9K_REG_DATA),A
RET
SpritesDisable:
; Modifies A
G9kReadReg G9K_CTRL+G9K_DIS_INC_READ
OR A,G9K_CTRL_DIS_SPD
OUT (G9K_REG_DATA),A
RET
SetScrollX:
; Set Horizontal scroll
; In: HL => Left X-position
; Uses: AF, HL
PUSH HL
LD A,G9K_SCROLL_LOW_X
OUT (G9K_REG_SELECT),a
LD A,L
AND A,7
OUT (G9K_REG_DATA),A
LD A,L
SRL H
RRA
SRL H
RRA
SRL H
RRA
OUT (G9K_REG_DATA),A
POP HL
RET
SetScrollY:
; Function : Sets Scroll Y
; Input : HL = Y
; Output : none
; Modifies : A
G9kWriteReg G9K_SCROLL_LOW_Y,L
LD A,(SCROLL_MODE)
OR A,H
OUT (G9K_REG_DATA),A
RET
IFNDEF G9K_DISABLE_PATTERN
SetScrollXB:
; Set Horizontal scroll
; In: HL => Left X-position
; Uses: AF, BC, HL
LD A,G9K_SCROLL_LOW_X_B
OUT (G9K_REG_SELECT),a
LD A,L
AND A,7
OUT (G9K_REG_DATA),A
LD A,L
SRL H
RRA
SRL H
RRA
SRL H
RRA
OUT (G9K_REG_DATA),A
RET
SetScrollYB:
; Function : Sets Scroll Y Layer B
; Input : HL = Y
; Output : none
; Modifies : A
G9kWriteReg G9K_SCROLL_LOW_Y_B,L
LD A,H
OUT (G9K_REG_DATA),A
RET
ENDIF
SetScrollMode:
; Vertical Scroll mode of Gfx9000
;
; In: AF => A -> 0 = Roll by image space size
; 1 = Roll by 256 lines
; 2 = Roll by 512 lines
; Uses: AF, B
AND A,3
RRCA
RRCA
LD (SCROLL_MODE),A
RET
SCROLL_MODE DB 0
SetBackDropColor:
; Change back drop color on Gfx9000
; In: A => A -> Back drop color
; Uses: AF
;
PUSH AF
LD A,G9K_BACK_DROP_COLOR
OUT (G9K_REG_SELECT),A
POP AF
AND A,63
OUT (G9K_REG_DATA),A
RET
;----------------------------------------------------------------------------;
; Gfx9000 palette functions ;
;----------------------------------------------------------------------------;
WritePalette:
; HL=pointer to palette data
; C=Palette pointer offset
; B=Number of bytes to write
; Modifies : AF,BC,HL
G9kWriteReg G9K_PALETTE_PTR,C
LD C,G9K_PALETTE
OTIR
RET
ReadPalette:
; HL=pointer to buffer wherin palette data is stored
; C=Palette pointer offset
; B=Number of bytes to read
;
G9kWriteReg G9K_PALETTE_PTR,C
LD C,G9K_PALETTE
INIR
RET
;----------------------------------------------------------------------------;
; Gfx9000 blitter functions ;
;----------------------------------------------------------------------------;
DrawFilledBox:
; HL = pointer to parameters (format: left,top,width,height)
; DE = Color
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
LD BC,8*256+G9K_REG_DATA
G9kCmdWait
OTIR
LD A,G9K_FC
OUT (G9K_REG_SELECT),A
OUT (C),E
OUT (C),D ; Set color
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LMMV
RET
DrawLine:
; HL = pointer to parameters
; DE = Color
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
LD BC,8*256+G9K_REG_DATA
G9kCmdWait
OTIR
LD A,G9K_FC
OUT (G9K_REG_SELECT),A
OUT (C),E
OUT (C),D ; Set color
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LINE
RET
DrawBox:
; HL = pointer to parameters (format: left,top,width,height)
PUSH HL
LD A,G9K_ARG
OUT (G9K_REG_SELECT),A
LD BC,6*256+G9K_REG_DATA
G9kCmdWait
XOR A,A
OUT (G9K_REG_DATA),A ; Clear argument register
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
OTIR
XOR A,A
OUT (G9K_REG_DATA),A
OUT (G9K_REG_DATA),A ; Write MI
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LINE ; Draw upper line
POP HL
PUSH HL
LD A,G9K_ARG
OUT (G9K_REG_SELECT),A
LD B,4
G9kCmdWait
LD A,G9K_ARG_MAJ
OUT (G9K_REG_DATA),A
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
OTIR
INC HL
INC HL
OUTI
OUTI
; MI stays the same
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LINE ; Draw left line
POP HL
PUSH HL
LD A,G9K_ARG
OUT (G9K_REG_SELECT),A
G9kCmdWait
XOR A,A
OUT (G9K_REG_DATA),A ; Clear argument register
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
OUTI
OUTI ; Write left
LD C,(HL)
INC HL
LD B,(HL)
INC HL ; top
LD E,(HL)
INC HL
LD D,(HL)
INC HL ; Width
LD A,(HL)
INC HL
LD H,(HL) ; Height
LD L,A
ADD HL,BC ; Calc top+height
LD C,G9K_REG_DATA
OUT (C),L
OUT (C),H ; Write Y
OUT (C),E
OUT (C),D ; Write MJ
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LINE ; Draw bottom line
POP HL
LD A,G9K_ARG
OUT (G9K_REG_SELECT),A
;DE = width
LD A,(HL)
INC HL
PUSH HL
LD H,(HL)
LD L,A ; Left
ADD HL,DE ; Left+width
G9kCmdWait
LD A,G9K_ARG_MAJ
OUT (G9K_REG_DATA),A
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
OUT (C),L
OUT (C),H ; Write X
POP HL
INC HL
OUTI
OUTI ; Write Y
INC HL
INC HL
OUTI
OUTI ; Height (MJ)
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LINE ; Draw right line
RET
SetupCopyRamToXY:
; Input : HL = pointer to parameters (format: left,top,width,height)
; Modifies: A,BC,HL
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
LD BC,8*256+G9K_REG_DATA
G9kCmdWait
OTIR
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LMMC
RET
CopyRamToXY:
; HL = Pointer to data
; BC = Bytes to copy
LD A,B
LD B,C
INC B
DEC B
JR Z,$+3
INC A
LD C,G9K_CMD_DATA
OTIR
DEC A
JP NZ,$-3
RET
SetupCopyXYToRam:
; HL = pointer to parameters (format: left,top,width,height)
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD BC,4*256+G9K_REG_DATA
G9kCmdWait
OTIR
LD B,4
LD A,G9K_NX
OUT (G9K_REG_SELECT),A
OTIR
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LMCM
RET
CopyXYToRam:
; HL = Pointer to data
; BC = Bytes to copy
LD A,B
LD B,C
INC B
DEC B
JR Z,$+3
INC A
LD C,G9K_CMD_DATA
INIR
DEC A
JP NZ,$-3
RET
CopyXYToXY:
; HL = Pointer to data (format: SourceX,SourceY,DestX,DestY,Width,height) struct G9K_COPY_XY_XY
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD BC,12*256+G9K_REG_DATA
G9kCmdWait
OTIR
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LMMM
RET
CopyXYToRegisterXY
; HL = Pointer to G9B_BOX struct
; IX = Dest X
; IY = Dest Y
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
G9kCmdWait
OUTI
OUTI ; SourceX
OUTI
OUTI ; SourceY
LD A,IXL
OUT (G9K_REG_DATA),A
LD A,IXH
OUT (G9K_REG_DATA),A; DestX
LD A,IYL
OUT (G9K_REG_DATA),A
LD A,IYH
OUT (G9K_REG_DATA),A; DestY
OUTI
OUTI ; Width
OUTI
OUTI ; Height
G9kWriteReg G9K_OPCODE,G9K_OPCODE_LMMM
RET
CopyVramToXY:
; HL = Pointer to data (format: SourceAddress,DestX,DestY,Width,height)
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD BC,11*256+G9K_REG_DATA
G9kCmdWait
OUTI
OUT (G9K_REG_DATA),A ; dummy write
OTIR
G9kWriteReg G9K_OPCODE,G9K_OPCODE_BMXL
RET
CopyXYToVram:
; HL = Pointer to data (format: SourceX,SourceY,DestAddress,Width,height)
; Modifies AF,HL,BC
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD BC,5*256+G9K_REG_DATA
G9kCmdWait
OTIR
OUT (G9K_REG_DATA),A ; dummy write
LD B,6
OTIR
G9kWriteReg G9K_OPCODE,G9K_OPCODE_BMLX
RET
CopyVramToVram:
; HL = Pointer to data (format: SrcAddress,DestAddress,NrBytes)
; Modifies AF,HL,BC
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
G9kCmdWait
OUTI ; Source Low
OUT (G9K_REG_DATA),A ; dummy write
OUTI ; Source mid
OUTI ; Source high
OUTI ; Destination Low
OUT (G9K_REG_DATA),A ; dummy write
OUTI ; Destination mid
OUTI ; Destination High
OUTI ; Number of bytes Low
OUT (G9K_REG_DATA),A ; dummy write
OUTI ; Number of bytes mid
OUTI ; Number of bytes High
G9kWriteReg G9K_OPCODE,G9K_OPCODE_BMLL
RET
SetPoint:
; HL = X
; DE = Y
; Under Construction
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
OUT (C),L
OUT (C),H
OUT (C),E
OUT (C),D
G9kCmdWait
RET
SetCmdWriteMask:
; HL = mask value
G9kWriteReg G9K_WRITE_MASK,L
LD A,H
OUT (G9K_REG_DATA),A
RET
SetCmdColor:
; HL = color value
G9kWriteReg G9K_FC,L
LD A,H
OUT (G9K_REG_DATA),A
RET
SetCmdBackColor:
; HL = color value
G9kWriteReg G9K_BC,L
LD A,H
OUT (G9K_REG_DATA),A
RET
CopyRamToVram:
; Function : Data transfer from CPU to VRAM
; Input : HL = pointer to buffer, BC=number of bytes to send
; Output : none
; Modifies : A,B,C,HL
LD A,B
LD B,C
LD C,G9K_VRAM
INC B
DEC B
JR Z,.a
INC A
.a
OTIR
DEC A
JP NZ,.a
RET
;----------------------------------------------------------------------------;
; Gfx9000 font functions ;
;----------------------------------------------------------------------------;
IFNDEF G9K_DISABLE_VFF
OpenVff:
; Input A = ram or vram. 0 = load data in vram, 1 = load font data in ram
; DE = Pointer to Font file name
; IX = Pointer to VFF object
LD (IX+VFF_OBJECT.ramFont),A
PUSH IX
XOR A,A
CALL File.FileOpen
POP IX
RET NZ ; Error opening
PUSH IX
LD HL,3 ; ID
LD DE,VFF_DATA_ID
CALL File.FileRead ; Load Id
POP IX
RET NZ ; Error reading
PUSH IX
PUSH BC ; Save file handle
LD B,3
LD HL,VFF_DATA_ID
LD DE,VFF_ID
CALL String.StringCompare
LD A,_NOVFF
POP BC
POP IX
RET NZ ; Not a VFF file
LD (IX),B ; Save file handle
LD DE,IX
INC DE
INC DE
LD HL,21 ; Load header
JP File.FileRead
VFF_ID DB "VFF"
VFF_DATA_ID DS 3,0
LoadFont:
; Function : Loads VFF font data
; Input : IX = Pointer to VFF object
; : IY = Pointer to font offset table, if it's zero it's not loaded
; : HL = Pointer to buffer for loading, or if it's a ram font the destination address
; : BC = Vram low word font data offset. If it's a ram font the pointer for buffer loading is used as font data offset
; Output : Z = succeded NZ= not succeded, A = error number
LD A,(IX+VFF_OBJECT.ramFont)
OR A,A
JR Z,.noRamFont
LD BC,HL
.noRamFont
PUSH IX
PUSH HL
LD (IX+VFF_OBJECT.vramOffset),BC ; Store Vram font offset
LD HL,512 ; Font offset table size
LD B,(IX + VFF_OBJECT.fileHandle) ; File hanlde
LD DE,IY ; Pointer to offset table
LD (IX+VFF_OBJECT.ptrOffsetTable),DE ; Store pointer to font character offset table
CALL File.FileRead ; Load font offset table
POP DE ; Pointer to buffer
POP IX
RET NZ ; Return if loading failed
LD HL,(IX+VFF_OBJECT.dataSize)
PUSH HL
PUSH DE ; Pointer to buffer
CALL File.FileRead
POP DE
POP HL
RET NZ ; Loading failed
; If it is ram font then copy to vram is skipped
LD A,(IX+VFF_OBJECT.ramFont)
DEC A
RET Z
PUSH DE ; Pointer to buffer
PUSH HL ; data size
LD HL,(IX+VFF_OBJECT.vramOffset)
LD E,7 ; High byte font address always 7
CALL SetVramWrite
POP BC ; data size
POP HL ; Pointer to buffer
CALL CopyRamToVram
XOR A,A
RET
SetFont:
; Input IX = Pointer to VFF object
PUSH AF
PUSH HL
PUSH DE
LD A,(IX + VFF_OBJECT.width)
LD (currentFont.width),A
LD A,(IX + VFF_OBJECT.height)
LD (currentFont.height),A
; Copy pointer to font offset table in print functions
LD HL,(IX + VFF_OBJECT.ptrOffsetTable)
IFNDEF G9K_DISABLE_VFF_VRAM
LD (PrintStringVram.fontTablePtr+1),HL
LD (PutCharVram.fontTablePtr+1),HL
ENDIF
IFNDEF G9K_DISABLE_VFF_RAM
LD (PrintStringRam.fontTablePtr+1),HL
LD (PutCharRam.fontTablePtr+1),HL
ENDIF
INC HL
INC HL
LD A,(HL) ; offset to second char is also the character size
LD (currentFont.charSize),A
LD A,(IX+VFF_OBJECT.vramOffset+0)
IFNDEF G9K_DISABLE_VFF_VRAM
LD (PrintStringVram.fontVramOffset+1),A
LD (PutCharVram.fontVramOffset+1),A
ENDIF
IFNDEF G9K_DISABLE_VFF_RAM
LD (PrintStringRam.fontRamOffset+1),A
LD (PutCharRam.fontRamOffset+1),A
ENDIF
LD A,(IX+VFF_OBJECT.vramOffset+1)
IFNDEF G9K_DISABLE_VFF_VRAM
LD (PrintStringVram.fontVramOffset+2),A
LD (PutCharVram.fontVramOffset+2),A
ENDIF
IFNDEF G9K_DISABLE_VFF_RAM
LD (PrintStringRam.fontRamOffset+2),A
LD (PutCharRam.fontRamOffset+2),A
ENDIF
LD A,(IX+VFF_OBJECT.ramFont)
IFNDEF G9K_DISABLE_VFF_VRAM
LD HL,PrintStringVram
LD DE,PutCharVram
ENDIF
OR A,A
JR Z,.end
IFNDEF G9K_DISABLE_VFF_RAM
LD HL,PrintStringRam
LD DE,PutCharRam
ENDIF
.end:
LD (PrintString+1),HL
LD (PutChar+1),DE
POP DE
POP HL
POP AF
RET
PrintString:
JP 0
PutChar:
JP 0
IFNDEF G9K_DISABLE_VFF_VRAM
PrintStringVram:
; Function : Print ASCIIZ String
; Input : IX = X
; : IY = Y
; ; DE = Pointer to txt
; Output : DE = Pointer to byte after term char
; : IX = modified to x after printed string
; Modifies ; AF,BC,DE,HL,IX
LD (currentFont.x),IX
LD (currentFont.y),IY
.loop
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD A,(DE)
INC DE
OR A,A ; End of ASCIIZ string
RET Z
.fontTablePtr LD BC,0 ;VFF.FONT_TABLE
LD L,A
LD H,0
ADD HL,HL
ADD HL,BC
LD A,(currentFont.width) ; Next Char
LD C,A
LD B,0
ADD IX,BC ; Precalculation
LD C,(HL)
INC HL
LD B,(HL) ; vram offset of character
.fontVramOffset LD HL,0 ; vram font base address offset low word
ADD HL,BC
LD C,G9K_REG_DATA
G9kCmdWait
OUT (C),L ; Vram address Low byte
LD A,0
OUT (C),A ; Looks stuppid but else it doens't work on turbo r
OUT (C),H ; Vram addres Mid byte
LD HL,currentFont.vramAddress
OUTI ; Vram high address
OUTI ; X low byte
OUTI ; X high byte
OUTI ; Y low byte
OUTI ; Y high byte
OUTI ; Width
LD A,0
OUT (C),A ; Width High byte always 0
OUTI ; Height
LD A,0 ; Height High byte always 0
OUT (C),A ; Looks stuppid but else it doens't work in turbo r
G9kWriteReg G9K_OPCODE,G9K_OPCODE_CMMM
LD (currentFont.x),IX
JP .loop
PutCharVram:
; Function : Print a character
; Input : E = Character
; Output ; IX = modified to x after printed character
; Modifies ; AF,BC,DE,HL,IX
.fontTablePtr LD BC,0
LD L,A
LD H,0
ADD HL,HL
ADD HL,BC
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD A,(currentFont.width) ; Next Char
LD C,A
LD B,0
ADD IX,BC ; Precalculation
LD C,(HL)
INC HL
LD B,(HL) ; vram offset of character
.fontVramOffset LD HL,0 ; vram font base address offset low word
ADD HL,BC
LD C,G9K_REG_DATA
G9kCmdWait
OUT (C),L ; Vram address Low byte
LD A,0
OUT (C),A ; Looks stuppid but else it doens't work on turbo r
OUT (C),H ; Vram addres Mid byte
LD HL,currentFont.vramAddress
OUTI ; Vram high address
OUTI ; X low byte
OUTI ; X high byte
OUTI ; Y low byte
OUTI ; Y high byte
OUTI ; Width
LD A,0
OUT (C),A ; Width High byte always 0
OUTI ; Height
LD A,0 ; Height High byte always 0
OUT (C),A ; Looks stuppid but else it doens't work in turbo r
G9kWriteReg G9K_OPCODE,G9K_OPCODE_CMMM
LD (currentFont.x),IX
RET
ENDIF
IFNDEF G9K_DISABLE_VFF_RAM
PrintStringRam:
; Function : Print ASCIIZ String
; Input : IX = X
; : IY = Y
; ; DE = Pointer to txt
; Output : DE = Pointer to byte after term char
; : IX = modified to x after printed string
; Modifies ; AF,BC,DE,HL,IX
LD (currentFont.x),IX
LD (currentFont.y),IY
.loop
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
LD A,(DE)
INC DE
OR A,A ; End of ASCIIZ string
RET Z
; Calculate the font data pointer address in ram
.fontTablePtr LD BC,0
LD L,A
LD H,0
ADD HL,HL
ADD HL,BC
; Precalculate next character offset
; This is done here to minimize wasted time on waiting for the v9990 to finish
LD A,(currentFont.width) ; Next Char
LD C,A
LD B,0
ADD IX,BC ; Precalculation
; Get the address of the character data in ram
LD C,(HL)
INC HL
LD B,(HL) ; ram offset of character
.fontRamOffset LD HL,0 ; ram font base address offset low word
ADD HL,BC
PUSH HL
LD C,G9K_REG_DATA
G9kCmdWait
LD HL,currentFont.x
OUTI ; X low byte
OUTI ; X high byte
OUTI ; Y low byte
OUTI ; Y high byte
OUTI ; Width
LD A,0
OUT (C),A ; Width High byte always 0
OUTI ; Height
LD A,0 ; Height High byte always 0
OUT (C),A ; Looks stuppid but else it doens't work in turbo r
G9kWriteReg G9K_OPCODE,G9K_OPCODE_CMMC
; Store addres of next X position
LD (currentFont.x),IX
; Wait for v9990 to recieve data
G9kWaitComReady
; Send character data to vdp
POP HL ; Pointer to font data in ram
LD A,(currentFont.charSize)
LD B,A
LD C,G9K_CMD_DATA
OTIR
JP .loop
PutCharRam:
; Function : Print a character
; Input : A = Character
; Output ; IX = modified to x after printed character
; Modifies ; AF,BC,DE,HL,IX
; Calculate the font data pointer address in ram
.fontTablePtr LD BC,0
LD L,A
LD H,0
ADD HL,HL
ADD HL,BC
LD A,G9K_DS_X
OUT (G9K_REG_SELECT),A
; Precalculate next character offset
; This is done here to minimize wasted time on waiting for the v9990 to finish
LD A,(currentFont.width) ; Next Char
LD C,A
LD B,0
ADD IX,BC ; Precalculation
; Get the address of the character data in ram
LD C,(HL)
INC HL
LD B,(HL) ; ram offset of character
.fontRamOffset LD HL,0 ; ram font base address offset low word
ADD HL,BC
PUSH HL
LD C,G9K_REG_DATA
G9kCmdWait
LD HL,currentFont.x
OUTI ; X low byte
OUTI ; X high byte
OUTI ; Y low byte
OUTI ; Y high byte
OUTI ; Width
LD A,0
OUT (C),A ; Width High byte always 0
OUTI ; Height
LD A,0 ; Height High byte always 0
OUT (C),A ; Looks stuppid but else it doens't work in turbo r
G9kWriteReg G9K_OPCODE,G9K_OPCODE_CMMC
; Store addres of next X position
LD (currentFont.x),IX
; Wait for v9990 to recieve data
G9kWaitComReady
; Send character data to vdp
POP HL ; Pointer to font data in ram
LD A,(currentFont.charSize)
LD B,A
LD C,G9K_CMD_DATA
OTIR
RET
ENDIF
Locate:
; Set X and Y position for putchar
; Value in IX is also needed for the putchar so don't overwrite it
LD (currentFont.x),IX
LD (currentFont.y),IY
RET
currentFont
.vramAddress DB 7 ; High Byte
.x DW 0
.y DW 0
.width DB 8 ; Font Size
.height DB 8 ;
.charSize DB 0 ; Char size in bytes.
ENDIF
;----------------------------------------------------------------------------;
; Gfx9000 bitmap functions ;
;----------------------------------------------------------------------------;
IFNDEF G9K_DISABLE_G9B
OpenG9B:
; Input : DE = Pointer to file name asciiz
; Output : HL = Pointer to G9B header data, NZ = error , Error code in A
; Modifies:
PUSH HL
XOR A,A
CALL File.FileOpen
POP HL
RET NZ ; Error opening
PUSH HL
LD HL,5 ; ID + HEADER LENGTH
LD DE,G9B_DATA_ID
CALL File.FileRead
POP HL
RET NZ ; Error reading
PUSH HL
PUSH BC ; Save file handle
LD B,3
LD HL,G9B_DATA_ID
LD DE,G9B_ID
CALL String.StringCompare
LD A,_NOG9B
POP BC
POP HL
RET NZ ; Not a G9B file
LD (HL),B ; Save handle in G9B struct
INC HL
INC HL
EX DE,HL
LD HL,(G9B_HEADER_SIZE)
JP File.FileRead
ReadG9B:
; IX = Pointer to G9B object struct
; DE = Pointer to load buffer
; BC = Size of load buffer
; HL = Destination X
; IY = Destination Y
; A = Palette offset in bytes. Only valid with palette modes. If a = 255 palette not loaded
PUSH AF ; Palette pointer
LD (G9B_COPY_PARMS),HL
LD (G9B_COPY_PARMS+2),IY
LD A,(IX+G9B_OBJECT.width+0)
LD (G9B_COPY_PARMS+4),A
LD A,(IX+G9B_OBJECT.width+1)
LD (G9B_COPY_PARMS+5),A ; Copy X
LD A,(IX+G9B_OBJECT.height+0)
LD (G9B_COPY_PARMS+6),A
LD A,(IX+G9B_OBJECT.height+1)
LD (G9B_COPY_PARMS+7),A ; Copy Y
LD HL,G9B_COPY_PARMS
POP AF ; Palette pointer
PUSH BC
PUSH DE
PUSH AF ; Palette pointer
CALL SetupCopyRamToXY
POP BC
LD C,B ; C = palette pointer
CALL NZ,ReadG9BPalette
POP DE
POP BC
RET NZ ; Error Loading palette
LD HL,CopyRamToXY
LD (ReadToG9K.copyMode+1),HL ; Set copy mode
IFNDEF G9K_DISABLE_BITBUST
LD A,(IX + G9B_OBJECT.compression)
AND A,07FH
CP A,G9B_COMPRESSION_BITBUST
JP Z,G9kBitBustXY
ENDIF
ReadG9B.Load
LD A, (IX+G9B_OBJECT.dataSize+2)
LD HL,(IX+G9B_OBJECT.dataSize)
ReadG9B.0
PUSH HL
POP IY ; Save low word, because this is the last block
OR A,A
SBC HL,BC
SBC A,0 ; Calculate block size
JR C,ReadG9B.1 ; Jumps when last block is reached
PUSH AF ; Size still to read high byte
PUSH HL ; Size still to read low word
PUSH BC ; buffer size
LD HL,BC ; Block size is buffer size
LD B,(IX + G9B_OBJECT.fileHandle) ; Get file handle
CALL ReadToG9K
POP BC ; buffer size
POP HL ; Size still to read low word
POP AF ; Size still to read high byte
JP ReadG9B.0
ReadG9B.1
PUSH IY
POP HL
LD B,(IX) ; Get file handle
JP ReadToG9K
CalcG9BVramSize:
; Input IX = Pointer to G9B header data
; Output E:HL = data size
LD DE,(IX + G9B_OBJECT.width)
LD BC,(IX + G9B_OBJECT.height)
; Calculate number of pixels
CALL Math.BCMulDE32 ; Result BC:HL
LD E,C
LD A,(IX + G9B_OBJECT.bitDepth)
JP CalcDataSize
CalcDataSize
;input E:HL=number of pixels
; A=bits per dot
CP A,16
JR Z,.calc16bit
CP A,8
RET Z
LD B,1
CP A,4
JR Z,.shiftLoop
LD B,2
.shiftLoop
SRL E
RR H
RR L
DJNZ .shiftLoop
RET
.calc16bit
ADD HL,HL
RL E
RET
ReadG9BLinear:
; IX = Pointer to G9B header data
; DE = Pointer to load buffer
; BC = Size of load buffer
; IYL:HL = Vram destination address
; A = Palette offset in bytes. Only valid with in palette modes, A = 255 palette not loaded
PUSH AF
PUSH BC
PUSH DE ; Pointer to buffer
LD E,IYL
CALL SetVramWrite
POP DE
POP BC
POP AF
PUSH DE
PUSH BC
LD C,A ; C = palette pointer
CALL NZ,ReadG9BPalette
POP BC
POP DE
RET NZ ; Error Loading palette
LD HL,CopyRamToVram
LD (ReadToG9K.copyMode+1),HL
IFNDEF G9K_DISABLE_BITBUST
LD A,(IX + G9B_OBJECT.compression)
AND A,07FH
CP A,G9B_COMPRESSION_BITBUST
JP Z,G9kBitBustLinear
ENDIF
JP ReadG9B.Load
ReadToG9K:
; Input B = FileHandle
; DE = Pointer to buffer
; HL = Bytes to read
PUSH DE
PUSH IX
PUSH DE ; Pointer to buffer
PUSH HL ; Bytes to read
CALL File.FileRead
POP BC ; Bytes to read
POP HL ; Pointer to buffer
.copyMode CALL CopyRamToXY
POP IX
POP DE
RET
ReadG9BPalette:
; IX = Pointer to G9B object struct
; C = Palette pointer (max 192), if 255 skip loading palette
; DE = Pointer to buffer
INC C
RET Z ; C = 255 skip loading
DEC C
LD A,(IX+G9B_OBJECT.nrColors)
OR A,A
RET Z ; Nothing to load
LD B,A
ADD A,A
ADD A,B ; Number of colors * 3 = size on disk
LD H,0
LD L,A
PUSH HL ; Bytes to read
PUSH DE ; Pointer to buffer
LD B,(IX + G9B_OBJECT.fileHandle)
CALL File.FileRead ; Saves BC
POP HL ; Pointer to buffer
POP DE ; Bytes to read
RET NZ ; Error reading palette
LD B,E
JP WritePalette
G9B_ID DB "G9B"
G9B_DATA_ID DS 3,0
G9B_HEADER_SIZE DW 0
G9B_COPY_PARMS DW 0
DW 0
DW 0
DW 0
IFNDEF G9K_DISABLE_BITBUST
G9kBitBustXY:
LD HL,CopyRamToXY
JR G9kBitBust
G9kBitBustLinear:
LD HL,CopyRamToVram
G9kBitBust:
LD (.copyFunction+1),HL
PUSH DE
LD B,(IX + G9B_OBJECT.fileHandle) ; Get file handle
LD DE,.BLOCKS
LD HL,1
CALL File.FileRead
POP DE
RET NZ ; Read error
.loop
PUSH DE
LD DE,.BLOCK_SIZE
LD HL,2
CALL File.FileRead
POP DE ; pointer to buffer
RET NZ ; Read error
PUSH DE ; pointer to buffer
LD HL,(.BLOCK_SIZE)
CALL File.FileRead
POP DE ; pointer to buffer
RET NZ ; Read error
PUSH BC
LD HL,(.BLOCK_SIZE) ; bytes
ADD HL,DE ; Calculate Address to depack to
PUSH DE ; pointer to buffer
PUSH HL ; Pointer to decompress to
EX DE,HL ; HL = Address of packed data
CALL bitbuster.depack_raw
; DE = Address of first byte after decompressed data
POP HL ; Pointer to decompressed data
PUSH HL
EX DE,HL
OR A,A
SBC HL,DE ; Calculate bytes to send to the vdp
LD BC,HL ; Bytes to send
POP HL ; Pointer to decompressed data
.copyFunction CALL CopyRamToVram
POP DE ; pointer to buffer
POP BC
LD A,(.BLOCKS)
DEC A
LD (.BLOCKS),A
JP NZ,.loop
RET
.BLOCKS DB 0
.BLOCK_SIZE DW 0
ENDIF
ENDIF
Close:
; HL = Pointer to G9B/VFF header object
; Modifies: B
LD B,(IX)
PUSH IX
CALL File.FileClose
POP IX
LD (IX),0 ; clear handle
RET
;----------------------------------------------------------------------------;
; Gfx9000 Mouse cursor functions ;
;----------------------------------------------------------------------------;
IFNDEF G9K_DISABLE_CURSOR
SetCursorXY:
; Both cursors are set at the same,because the data is 1 bit. So both cursors
; are needed to make a good cursor.
; input : HL=X
; : DE=Y
; Modifies : A,C
; Set V9990 address = #7FE00
XOR A,A
OUT (G9K_REG_SELECT),A
OUT (G9K_REG_DATA),A
LD A,0FEh
OUT (G9K_REG_DATA),A
LD A,7
OUT (G9K_REG_DATA),A
; "First" cursor
LD C,G9K_VRAM
OUT (C),E ; Y cordinate low byte
OUT (C),E ; Dummy
OUT (C),D ; Y cordinate high byte
OUT (C),D ; Dummy
OUT (C),L ; X cordinate low byte
OUT (C),L ; Dummy
LD A,(CURSOR0_ATTRIB)
OR A,H ; Set color atributes
OUT (G9K_VRAM),A ; X cordinate High byte and color
OUT (G9K_VRAM),A ; Dummy
; "Second" cursor
OUT (C),E ; Y cordinate low byte
OUT (C),E ; Dummy
OUT (C),D ; Y cordinate high byte
OUT (C),D ; Dummy
OUT (C),L ; X cordinate low byte
OUT (C),L ; Dummy
LD A,(CURSOR1_ATTRIB)
OR A,H
OUT (G9K_VRAM),A ; X cordinate High byte and color
RET
SetCursorPattern:
RET
SetCursorAttrib:
; Input A = Cursor Number ( 0 or 1)
LD HL,CURSOR0_ATTRIB
OR A,A
JR Z,$+3
INC HL
LD (HL),A
RET
CURSOR0_ATTRIB DB 0
CURSOR1_ATTRIB DB 0
ENDIF
;----------------------------------------------------------------------------;
; Gfx9000 Pattern mode functions ;
;----------------------------------------------------------------------------;
IFNDEF G9K_DISABLE_PATTERN
SetPatternData:
; DE = Ptr to pattern data
; HL = Pattern number
; A = Layer number (0=A,1=B)
; Modifies: A,BC,HL
PUSH DE
ADD A,A
LD (PAT.LAYER_SEL_SC),A
LD (PAT.LAYER_SEL_DS),A
ADD HL,HL
ADD HL,HL
ADD HL,HL
LD A,L
LD (PAT.X),A
LD A,H
ADD A,A
ADD A,A
ADD A,A
LD (PAT.Y),A
LD HL,PAT.X
CALL SetupCopyRamToXY
POP HL
LD BC,8*8
JP CopyRamToXY
GetPatternData:
; DE = Ptr to buffer to write pattern data in
; HL = Pattern number
; A = Layer number (0=A,1=B)
; Modifies: A,BC,HL
PUSH DE
ADD A,A
LD (PAT.LAYER_SEL_SC),A
LD (PAT.LAYER_SEL_DS),A
ADD HL,HL
ADD HL,HL
ADD HL,HL
LD A,L
LD (PAT.X),A
LD A,H
ADD A,A
ADD A,A
ADD A,A
LD (PAT.Y),A
LD HL,PAT.X
CALL SetupCopyXYToRam
POP HL
LD BC,8*8
JP CopyXYToRam
PAT.X DB 0
PAT.LAYER_SEL_SC DB 0
PAT.Y DB 0,0
PAT.WIDTH DB 8
PAT.LAYER_SEL_DS DB 0
PAT.HEIGHT DB 8,0
SetPattern:
; HL = Pattern number in generator table (on screen patterns 0 to A=8159,B=7679)
; DE = Pattern number in name table (on screen patterns 0 to 4095)
; A = Layer number (0=A,1=B)
PUSH DE
ADD HL,HL
LD DE,0C000h
OR A,A
JR Z,$+5
LD DE,0E000h
ADD HL,DE
LD E,7
CALL SetVramWrite
POP DE
LD A,E
OUT (G9K_VRAM),A
LD A,D
OUT (G9K_VRAM),A
RET
GetPattern:
; Input DE = Pattern number in name table (on screen patterns 0 to 4095)
; Output HL = Pattern number in generator table (on screen patterns 0 to A=8159,B=7679)
; A = Layer number (0=A,1=B)
PUSH DE
ADD HL,HL
LD DE,0C000h
OR A,A
JR Z,$+5
LD DE,0E000h
ADD HL,DE
LD E,7
CALL SetVramRead
POP DE
IN A,(G9K_VRAM)
LD L,A
IN A,(G9K_VRAM)
LD H,A
RET
PCopyVramToVram:
; NOTE: Not finished yet
; HL = Pointer to data (format: SrcAddress,DestAddress,NrBytes)
; Modifies AF,HL,BC
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
LD C,G9K_REG_DATA
G9kCmdWait
; DestAddress address <40000h layer A
; DestAddress address >40000h layer B
; Addresses need to be shifted to the left
LD A,(HL)
INC HL
ADD A,A
OUT (G9K_REG_DATA),A ; Source low
OUT (G9K_REG_DATA),A ; dummy write
LD A,(HL)
INC HL
RLA
OUT (G9K_REG_DATA),A ; Source mid
LD A,(HL)
INC HL
RLA
OUT (G9K_REG_DATA),A ; Source high
;OUTI ; Destination Low
;OUT (G9K_REG_DATA),A ; dummy write
;OUTI ; Destination mid
;OUTI ; Destination High
;OUTI ; Number of bytes Low
;OUT (G9K_REG_DATA),A ; dummy write
;OUTI ; Number of bytes mid
;OUTI ; Number of bytes High
G9kWriteReg G9K_OPCODE,G9K_OPCODE_BMLL
RET
PCopyVramToVramARegister:
; NOTE: Not finished yet
; Function: Copy vram to vram where destination is in layer A
; address value 00000h to 7FFFFh
; IYL:HL = start address
; IYH:DE = destination address
; IXL:BC = nr of bytes
LD A,G9K_SC_X
OUT (G9K_REG_SELECT),A
; Prepare the addresses
G9kCmdWait
ENDIF
;----------------------------------------------------------------------------;
; Gfx9000 Pattern mode sprite functions ;
;----------------------------------------------------------------------------;
IFNDEF G9K_DISABLE_SPRITES
SetSprite:
; B = Sprite Number (0 to 124)
; Set V9990 address = base 03FE00h + sprite number*4
XOR A,A
OUT (G9K_REG_SELECT),A
LD A,B
LD B,0
ADD A,A
ADD A,A
OUT (G9K_REG_DATA),A ; Low address
RL B
LD A,0FEh
ADD A,B
OUT (G9K_REG_DATA),A ; Mid
LD A,03h
OUT (G9K_REG_DATA),A ; High
RET
ENDIF
;----------------------------------------------------------------------------;
; Gfx9000 Interrupt functions ;
;----------------------------------------------------------------------------;
SetIntLine:
; HL = int line
G9kWriteReg G9K_INT_V_LINE_LO,L
LD A,H
OUT (G9K_REG_DATA),A
RET
ENDMODULE