mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1050 lines
30 KiB
1050 lines
30 KiB
;======================================================================
|
|
; XOSERA DRIVER FOR RCBUS XOSERA CARD
|
|
;
|
|
; WRITTEN BY: ROB GOWIN -- 01/19/2025
|
|
;======================================================================
|
|
;
|
|
; TODO:
|
|
; * LOOK AT FONT STUFF IN MORE DETAIL
|
|
;
|
|
;======================================================================
|
|
; XOSERA DRIVER - CONSTANTS
|
|
;======================================================================
|
|
;
|
|
;XOS_BASE .EQU $E0
|
|
;
|
|
DEVECHO "XOSERA: "
|
|
DEVECHO "IO="
|
|
DEVECHO XOS_BASE
|
|
DEVECHO "\n"
|
|
;
|
|
#IF (XOSSIZ=V80X30)
|
|
XOS_ROWS_CONST .EQU 30
|
|
XOS_COLS_CONST .EQU 80
|
|
#ENDIF
|
|
#IF (XOSSIZ=V80X60)
|
|
XOS_ROWS_CONST .EQU 60
|
|
XOS_COLS_CONST .EQU 80
|
|
#ENDIF
|
|
|
|
; XOSERA MAIN REGISTER
|
|
|
|
ZXM_SYS_CTRL .EQU XOS_BASE
|
|
ZXM_INT_CTRL .EQU XOS_BASE+2
|
|
ZXM_TIMER .EQU XOS_BASE+4
|
|
ZXM_RD_XADDR .EQU XOS_BASE+6
|
|
ZXM_WR_XADDR .EQU XOS_BASE+8
|
|
ZXM_XDATA .EQU XOS_BASE+10
|
|
ZXM_RD_INCR .EQU XOS_BASE+12
|
|
ZXM_RD_ADDR .EQU XOS_BASE+14
|
|
ZXM_WR_INCR .EQU XOS_BASE+16
|
|
ZXM_WR_ADDR .EQU XOS_BASE+18
|
|
ZXM_DATA .EQU XOS_BASE+20
|
|
ZXM_DATA_2 .EQU XOS_BASE+22
|
|
ZXM_PIXEL_X .EQU XOS_BASE+24
|
|
ZXM_PIXEL_Y .EQU XOS_BASE+26
|
|
ZXM_UART .EQU XOS_BASE+28
|
|
ZXM_FEATURE .EQU XOS_BASE+30
|
|
|
|
; See: https:;github.com/XarkLabs/Xosera/blob/master/REFERENCE.md
|
|
|
|
; Xosera XR Memory Regions (size in 16-bit words)
|
|
XR_CONFIG_REGS .EQU 0x0000 ; (R/W) 0x0000-0x0007 8 config/ctrl registers
|
|
XR_PA_REGS .EQU 0x0010 ; (R/W) 0x0010-0x0017 8 playfield A video registers
|
|
XR_PB_REGS .EQU 0x0018 ; (R/W) 0x0018-0x001F 8 playfield B video registers
|
|
XR_AUDIO_REGS .EQU 0x0020 ; (-/W) 0x0020-0x002F 16 audio playback registers
|
|
XR_BLIT_REGS .EQU 0x0040 ; (-/W) 0x0040-0x0049 10 blitter registers
|
|
XR_TILE_ADDR .EQU 0x4000 ; (R/W) 0x4000-0x53FF tile glyph/tile map memory
|
|
XR_TILE_SIZE .EQU 0x1400 ; 4096+1024 x 16-bit tile glyph/tile map memory
|
|
XR_COLOR_ADDR .EQU 0x8000 ; (R/W) 0x8000-0x81FF 2 x A & B color lookup memory
|
|
XR_COLOR_SIZE .EQU 0x0200 ; 2 x 256 x 16-bit words (0xARGB)
|
|
XR_COLOR_A_ADDR .EQU 0x8000 ; (R/W) 0x8000-0x80FF A 256 entry color lookup memory
|
|
XR_COLOR_A_SIZE .EQU 0x0100 ; 256 x 16-bit words (0xARGB)
|
|
XR_COLOR_B_ADDR .EQU 0x8100 ; (R/W) 0x8100-0x81FF B 256 entry color lookup memory
|
|
XR_COLOR_B_SIZE .EQU 0x0100 ; 256 x 16-bit words (0xARGB)
|
|
XR_POINTER_ADDR .EQU 0x8200 ; (-/W) 0x8200-0x82FF 256 word 32x32 4-bpp pointer image
|
|
XR_POINTER_SIZE .EQU 0x0100 ; 256 x 16-bit words (4-bit pixels)
|
|
XR_COPPER_ADDR .EQU 0xC000 ; (R/W) 0xC000-0xC5FF copper memory (16-bit words)
|
|
XR_COPPER_SIZE .EQU 0x0600 ; 1024+512 x 16-bit copper memory words
|
|
|
|
; XR Extended Register / Region (accessed via XM_RD_XADDR/XM_WR_XADDR and XM_XDATA)
|
|
; Video Config and Copper XR Registers
|
|
XR_VID_CTRL .EQU 0x00 ; (R /W) display control and border color index
|
|
XR_COPP_CTRL .EQU 0x01 ; (R /W) display synchronized coprocessor control
|
|
XR_AUD_CTRL .EQU 0x02 ; (- /-) TODO: audio channel control
|
|
XR_SCANLINE .EQU 0x03 ; (R /W) read scanline (incl. offscreen), write signal video interrupt
|
|
XR_VID_LEFT .EQU 0x04 ; (R /W) left edge of active display window (typically 0)
|
|
XR_VID_RIGHT .EQU 0x05 ; (R /W) right edge of active display window +1 (typically 640 or 848)
|
|
XR_POINTER_H .EQU 0x06 ; (- /W) pointer sprite raw H position
|
|
XR_POINTER_V .EQU 0x07 ; (- /W) pointer sprite raw V position / pointer color select
|
|
; Playfield A Control XR Registers
|
|
XR_PA_GFX_CTRL .EQU 0x10 ; (R /W ) playfield A graphics control
|
|
XR_PA_TILE_CTRL .EQU 0x11 ; (R /W ) playfield A tile control
|
|
XR_PA_DISP_ADDR .EQU 0x12 ; (R /W ) playfield A display VRAM start address
|
|
XR_PA_LINE_LEN .EQU 0x13 ; (R /W ) playfield A display line width in words
|
|
XR_PA_HV_FSCALE .EQU 0x14 ; (R /W ) playfield A horizontal and vertical fractional scale
|
|
XR_PA_H_SCROLL .EQU 0x15 ; (R /W ) playfield A horizontal and vertical fine scroll
|
|
XR_PA_V_SCROLL .EQU 0x16 ; (R /W ) playfield A horizontal and vertical fine scroll
|
|
XR_PA_LINE_ADDR .EQU 0x17 ; (- /W ) playfield A scanline start address (loaded at start of line)
|
|
; Playfield B Control XR Registers
|
|
XR_PB_GFX_CTRL .EQU 0x18 ; (R /W ) playfield B graphics control
|
|
XR_PB_TILE_CTRL .EQU 0x19 ; (R /W ) playfield B tile control
|
|
XR_PB_DISP_ADDR .EQU 0x1A ; (R /W ) playfield B display VRAM start address
|
|
XR_PB_LINE_LEN .EQU 0x1B ; (R /W ) playfield B display line width in words
|
|
XR_PB_HV_FSCALE .EQU 0x1C ; (R /W ) playfield B horizontal and vertical fractional scale
|
|
XR_PB_H_SCROLL .EQU 0x1D ; (R /W ) playfield B horizontal and vertical fine scroll
|
|
XR_PB_V_SCROLL .EQU 0x1E ; (R /W ) playfield B horizontal and vertical fine scroll
|
|
XR_PB_LINE_ADDR .EQU 0x1F ; (- /W ) playfield B scanline start address (loaded at start of line)
|
|
|
|
; Default 1-bpp font glyphs in TILE memory (total 0x1400 words)
|
|
FONT_ST_8x16_ADDR .EQU XR_TILE_ADDR + 0x0000
|
|
FONT_ST_8x16_SIZE .EQU 0x800
|
|
FONT_ST_8x8_ADDR .EQU XR_TILE_ADDR + 0x0800
|
|
FONT_ST_8x8_SIZE .EQU 0x400
|
|
FONT_PC_8x8_ADDR .EQU XR_TILE_ADDR + 0x0C00
|
|
FONT_PC_8x8_SIZE .EQU 0x400
|
|
FONT_HEX_8x8_ADDR .EQU XR_TILE_ADDR + 0x1000
|
|
FONT_HEX_8x8_SIZE .EQU 0x400
|
|
|
|
TILE_CTRL_TILE_VRAM_F .EQU 0x0100
|
|
TILE_CTRL_DISP_TILEMEM_F .EQU 0x0200
|
|
|
|
; GET XOSERA MAIN REGISTER REG_NUM VALUE INTO DE.
|
|
#DEFINE XM_GETW(REG_NUM) \
|
|
#defcont \ LD C,REG_NUM
|
|
#defcont \ IN D,(C)
|
|
#defcont \ INC C
|
|
#defcont \ IN E,(C)
|
|
|
|
; SET XOSERA MAIN REGISTER REG_NUM TO VALUE IN DE.
|
|
#DEFINE XM_SETW(REG_NUM) \
|
|
#defcont \ LD C,REG_NUM
|
|
#defcont \ OUT (C),D
|
|
#defcont \ INC C
|
|
#defcont \ OUT (C),E
|
|
|
|
; SET LOW BYTE OF XOERA MAIN REGISTER REG_NUM TO VALUE IN A.
|
|
#DEFINE XM_SETBL(REG_NUM) \
|
|
#defcont \ LD C,REG_NUM+1
|
|
#defcont \ OUT (C),A
|
|
|
|
SYNC_RETRIES .EQU 250
|
|
|
|
TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER
|
|
|
|
;======================================================================
|
|
; XOSERA DRIVER - INITIALIZATION
|
|
;======================================================================
|
|
;
|
|
XOS_PREINIT:
|
|
LD IY,XOS_IDAT ; POINTER TO INSTANCE DATA
|
|
; JP KBD_PREINIT ; INITIALIZE KEYBOARD
|
|
RET
|
|
;
|
|
XOS_INIT:
|
|
LD IY,XOS_IDAT ; POINTER TO INSTANCE DATA
|
|
;
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("XOSERA: IO=0x$")
|
|
LD A,XOS_BASE
|
|
CALL PRTHEXBYTE
|
|
CALL XOS_PROBE ; CHECK FOR HW PRESENCE
|
|
JR Z,XOS_INIT1 ; CONTINUE IF HW PRESENT
|
|
;
|
|
; HARDWARE NOT PRESENT
|
|
PRTS(" NOT PRESENT$")
|
|
OR $FF
|
|
RET
|
|
;
|
|
XOS_INIT1:
|
|
; RETRIEVE SOME CONFIGURATION INFO FROM XOSERA AND PRINT IT
|
|
LD A,' '
|
|
CALL COUT
|
|
CALL XOS_SHOW_INFO
|
|
|
|
CALL XOS_VDAINI
|
|
|
|
; ADD OURSELVES TO VDA DISPATCH TABLE
|
|
LD BC,XOS_FNTBL ; BC := FUNCTION TABLE ADDRESS
|
|
LD DE,XOS_IDAT ; DE := XOSERA INSTANCE DATA PTR
|
|
CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED
|
|
|
|
; INITIALIZE EMULATION
|
|
LD C,A ; C := ASSIGNED VIDEO DEVICE NUM
|
|
LD DE,XOS_FNTBL ; DE := FUNCTION TABLE ADDRESS
|
|
LD HL,XOS_IDAT ; HL := XOSERA INSTANCE DATA PTR
|
|
CALL TERM_ATTACH ; DO IT
|
|
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
;----------------------------------------------------------------------
|
|
; XOS_SHOW_INFO:
|
|
; XOSERA HAS SOME BUILD-TIME INFO STORED IN THE UPPER 128 OF COPPER
|
|
; MEMORY. RETRIEVE THAT INFO AND DISPLAY IT.
|
|
;----------------------------------------------------------------------
|
|
|
|
XOS_SHOW_INFO:
|
|
LD DE,$C580 ; LAST 128 BYTES OF XOSERA COPPER MEM
|
|
XM_SETW(ZXM_RD_XADDR)
|
|
XOS_SHOW_INFO1:
|
|
XM_GETW(ZXM_XDATA) ; GET INFO DATA IN DE
|
|
LD A,D
|
|
CP 0
|
|
JR Z,XOS_SHOW_INFO2 ; EXIT LOOP IF D == 0
|
|
PUSH DE
|
|
CALL COUT ; PRINT THE CHAR IN D (COPIED TO A)
|
|
POP DE
|
|
LD A,E
|
|
CP 0
|
|
JR Z,XOS_SHOW_INFO2 ; EXIT LOOP IF E == 0
|
|
CALL COUT ; PRINT THE CHAR IN E (COPIED TO A)
|
|
JR XOS_SHOW_INFO1
|
|
XOS_SHOW_INFO2:
|
|
RET
|
|
|
|
;----------------------------------------------------------------------
|
|
; XOS_DETECT: DETECT PRESENCE OF A XOSERA BOARD
|
|
;
|
|
; READ XOSERA RD_INCR REGISTER, THEN XOR WITH CONSTANT TO CHANGE IT.
|
|
; WRITE XOR'D VALUE TO RD_INCR, THEN READ BACK. IF A MATCH,
|
|
; XOSERA BOARD IS DETECTED.
|
|
; EITHER WAY, RESTORE ORIGINAL RD_INCR THEN RETURN RESULT IN A.
|
|
; RESULT IN A: 0 IF VALUES MATCH, -8 (HARDWARE NOT PRESENT) OTHERWISE.
|
|
;----------------------------------------------------------------------
|
|
|
|
XOS_DETECT:
|
|
XM_GETW(ZXM_RD_INCR) ; DE := XOSERA RD_INCR REGISTER
|
|
PUSH DE ; SAVE A COPY
|
|
LD A,D
|
|
XOR $F5
|
|
LD D,A ; XOR RD_INCR MSB WITH $F5
|
|
LD A,E
|
|
XOR $FA
|
|
LD E,A ; XOR RD_INCR LSB WITH $FA
|
|
; DE = TEST_INCR = RD_INCR ^ 0xF5FA;
|
|
LD H,D
|
|
LD L,E ; SAVE TEST_INCR TO HL
|
|
XM_SETW(ZXM_RD_INCR) ; WRITE NEW RD_INCR VALUE
|
|
LD DE,$0000
|
|
XM_GETW(ZXM_RD_INCR) ; READ IT BACK INTO DE
|
|
LD A,H
|
|
CP D
|
|
JR NZ,XOS_DETECT1 ; D & H THE SAME?
|
|
LD A,L
|
|
CP E
|
|
JR NZ,XOS_DETECT1 ; E & L THE SAME?
|
|
XOR A ; YEP, LOOKS GOOD
|
|
JP XOS_DETECT2
|
|
XOS_DETECT1:
|
|
LD A,-8 ; READBACK VALUE DID NOT MATCH. SIGNAL HARDWARE NOT PRESENT
|
|
XOS_DETECT2:
|
|
; RESTORE THE ORGINAL VALUE OF RD_INCR
|
|
POP DE
|
|
XM_SETW(ZXM_RD_INCR)
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; XOS_PROBE: PROBE FOR XOSERA, TRY UP TO `SYNC_RETRIES` TIMES, WAITING
|
|
; 10MS BETWEEN SYNC ATTEMPTS.
|
|
; RETURN IN A: 0 IF A XOSERA_BOARD IS DETECTED, OR -8 (HARDWARE NOT
|
|
; DETECTED) OTHERWISE.
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_PROBE:
|
|
LD B,SYNC_RETRIES
|
|
XOS_PROBE1:
|
|
CALL XOS_DETECT ; Z FLAG SET IF XOSERA DETECTED, CLEAR IF NOT
|
|
JR Z,XOS_PROBE2
|
|
; OUR ATTEMPT TO SYNC DID NOT WORK, SO WAIT 10MS TO TRY AGAIN
|
|
PUSH BC
|
|
LD DE,625 ; 625 * 16US = 10000US = 10MS
|
|
CALL VDELAY
|
|
POP BC
|
|
DJNZ XOS_PROBE1
|
|
LD A,-8 ; FAILED TO SYNC AFTER SEVERAL ATTEMPTS.
|
|
XOS_PROBE2:
|
|
; A WILL BE ZERO OR -8. SET THE Z FLAG ACCORDINGLY.
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; XOS_CLR_TEXT_SCR: CALL FILL TO CLEAR ENTIRE ROWS*COLS TEXT SCREEN.
|
|
;----------------------------------------------------------------------
|
|
XOS_CLR_TXT_SCR:
|
|
LD A,(XOS_COLS) ; COMPUTE HOW MANY WORDS TO FILL
|
|
LD H,A
|
|
LD A,(XOS_ROWS)
|
|
LD E,A
|
|
CALL MULT8
|
|
LD B,H
|
|
LD C,L ; BC := WORD COUNT = ROWS * COLS
|
|
LD HL,(XOS_POS)
|
|
PUSH HL ; SAVE CURRENT CURSOR POS
|
|
LD HL,(XOS_OFF)
|
|
LD (XOS_POS),HL ; TELL FILL TO START AT 0,0 (POS = XOS_OFF)
|
|
LD A,$20 ; FILL WITH SPACE (AND CURRENT ATTR)
|
|
CALL XOS_FILL
|
|
CALL REVERSE_CURSOR_POS ; BIT OF A HACK
|
|
POP HL
|
|
LD HL,(XOS_POS) ; RESTORE ORIGINAL CURSOR POS
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; XOS_WRITE_XREGS: WRITE A GROUP OF XOSERA EXTENDED REGISTERS.
|
|
; HL POINTS TO SETUP TABLE, B HAS NUMBER OF WORDS.
|
|
; DE HAS FIRST XOSERA XREG ADDRESS
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_WRITE_XREGS:
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
XOS_WRITE_XREGS1:
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
INC HL
|
|
XM_SETW(ZXM_XDATA)
|
|
DEC B
|
|
JR NZ,XOS_WRITE_XREGS1
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; XOS_WRITE_PALETTE_B
|
|
; WHEN WRITING PALETTE B, WE NEED TO SET THE ALPHA VALUE TO $F
|
|
; SO THAT THE GRAPHICS/TEXT OVERLAP WORKS CORRECTLY. EXCEPT THAT
|
|
; WE DON'T WANT THIS FOR THE ZERO ENTRY SO HANDLE THAT SEPERATELY.
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_WRITE_PALETTE_B:
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
INC HL
|
|
XM_SETW(ZXM_XDATA)
|
|
DEC B
|
|
XOS_WRITE_PALETTE_B1:
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
INC HL
|
|
LD A,D
|
|
OR $F0 ; SET ALPHA VALUE TO $F
|
|
LD D,A
|
|
XM_SETW(ZXM_XDATA)
|
|
DEC B
|
|
JR NZ,XOS_WRITE_PALETTE_B1
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; XOS_COPY_FONT_TO_VRAM
|
|
; COPY THE 8 X 8 ST FONT IN THE EXTENDED REGISTER AREA TO THE
|
|
; UPPER 1K OF VRAM. USED IN 80 X 60 MODE, BUT NOT IN
|
|
; 80 X 30 MODE.
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_COPY_FONT_TO_VRAM:
|
|
; SEE IF THE FONT HAS ALREADY BEEN COPIED. IF SO VRAM ADDRESS
|
|
; $FC04 WILL HAVE THE VALUE $183C.
|
|
LD DE,$FC04
|
|
XM_SETW(ZXM_RD_ADDR)
|
|
XM_GETW(ZXM_DATA)
|
|
LD A,D
|
|
CP $18
|
|
JR NZ,XOS_COPY_FONT_TO_VRAM1
|
|
LD A,E
|
|
CP $3C
|
|
JR NZ,XOS_COPY_FONT_TO_VRAM1
|
|
; FONT HAS ALREADY BEEN COPIED TO VRAM. JUST RETURN
|
|
RET
|
|
XOS_COPY_FONT_TO_VRAM1:
|
|
LD DE,FONT_ST_8x8_ADDR ; READ FROM FONT AREA
|
|
XM_SETW(ZXM_RD_XADDR)
|
|
LD DE,$FC00
|
|
XM_SETW(ZXM_WR_ADDR) ; WRITE TO VRAM
|
|
LD DE,$0001
|
|
XM_SETW(ZXM_WR_INCR) ; MAKE SURE WR INCR IS NONE
|
|
LD BC,FONT_ST_8x8_SIZE ; LOOP COUNTER
|
|
XOS_COPY_FONT_TO_VRAM2:
|
|
PUSH BC
|
|
XM_GETW(ZXM_XDATA)
|
|
XM_SETW(ZXM_DATA)
|
|
; CHECK COUNT
|
|
POP BC
|
|
DEC BC ; DECREMENT COUNT
|
|
LD A,B ; TEST FOR
|
|
OR C ; ... ZERO
|
|
RET Z ; DONE IF SO
|
|
JR XOS_COPY_FONT_TO_VRAM2
|
|
|
|
XOS_HW_SETUP:
|
|
LD DE,XR_VID_CTRL
|
|
LD HL,XOS_BASE_INIT
|
|
LD B,8
|
|
CALL XOS_WRITE_XREGS
|
|
|
|
; INITIALIZE PLAYFIELD A FOR BITMAP GRAPHICS
|
|
LD DE,XR_PA_REGS
|
|
LD HL,PF_640x480x4
|
|
LD B,7
|
|
CALL XOS_WRITE_XREGS
|
|
|
|
; INITIALIZE PLAYFIELD B FOR 80x30 TEXT MODE
|
|
LD DE,XR_PB_REGS
|
|
#IF (XOSSIZ=V80X60)
|
|
LD HL,PF_80X60_TILED
|
|
#ELSE
|
|
LD HL,PF_80X30_TILED
|
|
#ENDIF
|
|
LD B,7
|
|
CALL XOS_WRITE_XREGS
|
|
|
|
; INITIALIZE THE PALETTE FOR PLAYFIELD A
|
|
LD DE,XR_COLOR_A_ADDR
|
|
LD HL,XOS_PALETTE
|
|
LD B,16
|
|
CALL XOS_WRITE_XREGS
|
|
|
|
; INITIALIZE THE PALETTE FOR PLAYFIELD B
|
|
LD DE,XR_COLOR_B_ADDR
|
|
LD HL,XOS_PALETTE
|
|
LD B,16
|
|
CALL XOS_WRITE_PALETTE_B
|
|
|
|
; INITIALIZE THE COPPER PROGRAM WE ARE USING TO 'LETTERBOX'
|
|
; A 640 X 400 BITMAP ON A 640 X 480 DISPLAY. SEE COPPER NOTES
|
|
; WAY BELOW.
|
|
|
|
LD DE,$C100
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
LD DE,(PF_640x480x4) ; DE := PA_GFX_CTRL
|
|
XM_SETW(ZXM_XDATA)
|
|
LD A,E
|
|
OR $80
|
|
LD E,A ; DE := PA_GFX_CTRL WITH BLANK BIT SET
|
|
XM_SETW(ZXM_XDATA)
|
|
|
|
LD DE,XR_COPPER_ADDR
|
|
LD HL,XOS_COPPER
|
|
LD B,19
|
|
CALL XOS_WRITE_XREGS
|
|
|
|
LD DE,XR_COPP_CTRL ; ENABLE THE COPPER
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
LD DE,$8000
|
|
XM_SETW(ZXM_XDATA)
|
|
|
|
LD A,$0F ; SET DEFAUL PIXEL MASK
|
|
XM_SETBL(ZXM_SYS_CTRL)
|
|
LD DE,$0001
|
|
XM_SETW(ZXM_WR_INCR) ; SET DEFAULT READ/WRITE INCREMENTS
|
|
XM_SETW(ZXM_RD_INCR)
|
|
RET
|
|
;
|
|
;======================================================================
|
|
; XOSERA DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS
|
|
;======================================================================
|
|
;
|
|
XOS_FNTBL:
|
|
.DW XOS_VDAINI
|
|
.DW XOS_VDAQRY
|
|
.DW XOS_VDARES
|
|
.DW XOS_VDADEV
|
|
.DW XOS_VDASCS
|
|
.DW XOS_VDASCP
|
|
.DW XOS_VDASAT
|
|
.DW XOS_VDASCO
|
|
.DW XOS_VDAWRC
|
|
.DW XOS_VDAFIL
|
|
.DW XOS_VDACPY
|
|
.DW XOS_VDASCR
|
|
.DW XKBD_STAT
|
|
.DW XKBD_FLUSH
|
|
.DW XKBD_READ
|
|
.DW XOS_VDARDC
|
|
#IF (($ - XOS_FNTBL) != (VDA_FNCNT * 2))
|
|
.ECHO "*** INVALID VGA FUNCTION TABLE ***\n"
|
|
!!!!!
|
|
#ENDIF
|
|
|
|
XOS_VDAINI:
|
|
LD A,$0F ; BRIGHT WHITE FG, BLACK BG
|
|
LD (XOS_ATTR),A
|
|
LD A,0
|
|
LD (XOS_RUB),A
|
|
LD A,80
|
|
LD (XOS_COLS),A
|
|
LD A,XOS_ROWS_CONST
|
|
LD (XOS_ROWS),A
|
|
#IF (XOSSIZ=V80X60)
|
|
LD HL,$4000
|
|
#ELSE
|
|
LD HL,$4800
|
|
#ENDIF
|
|
LD (XOS_OFF),HL
|
|
LD (XOS_POS),HL
|
|
; FONT DATA FOR 80x30 MODE WILL STAY IN TILE MEM, BUT
|
|
; FONT DATA FOR 80X60 MODE WILL LIVE IN VRAM. SO WE
|
|
; NEED TO COPY THE ST 8X8 FONT TO VRAM. WE MUST DO THIS
|
|
; BEFORE CLEARING THE TEXT SCREEN BECAUSE THE SCREEN
|
|
; DATA IS STORED WHERE FONT CURRENTLY RESIDES.
|
|
LD A,$0F
|
|
XM_SETBL(ZXM_SYS_CTRL) ; SET VRAM WRITE MASK
|
|
CALL XOS_COPY_FONT_TO_VRAM
|
|
CALL XOS_CLR_TXT_SCR ; CLEAR THE TEXT SCREEN
|
|
CALL XOS_HW_SETUP
|
|
; CALL XOS_CLR_GRAPHICS_SCR ; CLEAR THE GRAPHICS SCREEN
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDAQRY:
|
|
LD C,$00 ; MODE ZERO IS ALL WE KNOW
|
|
LD A,(XOS_ROWS)
|
|
LD D,A
|
|
LD A,(XOS_COLS)
|
|
LD E,A
|
|
LD HL,$0 ; EXTRACTION OF CURRENT BITMAP DATA NOT SUPPORTED YET
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDARES:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDADEV:
|
|
LD C,0 ; C := ATTRIBUTES (UNDEFINED)
|
|
LD D,VDADEV_XOSERA ; D := DEVICE TYPE
|
|
LD E,0 ; E := PHYSICAL UNIT IS ALWAYS ZERO
|
|
LD H,0 ; H := 0, DRIVER HAS NO MODES
|
|
LD L,XOS_BASE ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDASCS:
|
|
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED (YET)
|
|
RET
|
|
|
|
XOS_VDASCP:
|
|
; UNREVERSE THE CURRENT CURSOR
|
|
CALL REVERSE_CURSOR_POS
|
|
CALL XOS_XY ; SET CURSOR POSITION
|
|
; REVERSE VIDEO THE CHARACTER AT THE NEW CURSOR POSITION
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDASAT:
|
|
; INCOMING IS: -----RUB (R=REVERSE, U=UNDERLINE, B=BLINK)
|
|
;
|
|
; JUST SAVE THE VALUE AND FALL THROUGH. ONLY REVERSE IS
|
|
; SUPPORTED WHICH IS IMPLEMENTED BELOW.
|
|
LD A,E
|
|
LD (XOS_RUB),A ; SAVE IT
|
|
JR XOS_VDASCO1 ; IMPLEMENT SETTING
|
|
|
|
XOS_VDASCO:
|
|
; WE HANDLE ONLY PER-CHARACTER COLORS (D=0)
|
|
LD A,D ; GET CHAR/SCREEN SCOPE
|
|
OR A ; CHARACTER?
|
|
JR NZ,XOS_VDASCO2 ; IF NOT, JUST RETURN
|
|
LD A,E
|
|
LD (XOS_ATTR),A ; SAVE COLOR INFO
|
|
XOS_VDASCO1:
|
|
; CHECK FOR REVERSE VIDEO
|
|
LD A,(XOS_RUB) ; GET RUB SETTING
|
|
BIT 2,A ; REVERSE IS BIT 2
|
|
JR Z,XOS_VDASCO2 ; DONE IF REVERSE VID NOT SET
|
|
; IMPLEMENT REVERSE VIDEO
|
|
LD A,(XOS_ATTR) ; GET ATTRIBUTE
|
|
RLCA ; SWAP FG/BG COLORS
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
LD (XOS_ATTR),A ; SAVE NEW VALUE
|
|
XOS_VDASCO2:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDAWRC:
|
|
CALL REVERSE_CURSOR_POS
|
|
LD A,E ; CHARACTER TO WRITE GOES IN A
|
|
CALL XOS_PUTCHAR ; PUT IT ON THE SCREEN
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDAFIL:
|
|
CALL REVERSE_CURSOR_POS
|
|
LD A,E ; FILL CHARACTER GOES IN A
|
|
LD B,H
|
|
LD C,L ; FILL LENGTH GOES IN BC
|
|
CALL XOS_FILL ; DO THE FILL
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDACPY:
|
|
; LENGTH IN HL, SOURCE ROW/COL IN DE, DEST IS XOS_POS
|
|
; BLKCPY USES: HL=SOURCE, DE=DEST, BC=COUNT
|
|
CALL REVERSE_CURSOR_POS
|
|
PUSH HL ; SAVE LENGTH
|
|
CALL XOS_XY2IDX ; ROW/COL IN DE -> SOURCE ADR IN HL
|
|
PUSH DE
|
|
LD DE,(XOS_OFF) ; ADD IN VRAM START OFFSET
|
|
ADD HL,DE
|
|
POP DE
|
|
POP BC ; RECOVER LENGTH IN BC
|
|
LD DE,(XOS_POS) ; PUT DEST IN DE
|
|
; LD A,0 ; SOURCE IS MEMORY
|
|
CALL XOS_BLKCPY ; DO A BLOCK COPY
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XOS_VDASCR:
|
|
CALL REVERSE_CURSOR_POS
|
|
LD A,E
|
|
OR A ; SET FLAGS
|
|
RET Z ; IF ZERO, WE ARE DONE
|
|
JP M,XOS_VDASCR1 ; E IS NEGATIVE, REVERSE SCROLL
|
|
CALL XOS_RSCROLL ; SCROLL FORWARD 'E' LINES
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
XOS_VDASCR1:
|
|
NEG ; A IS NEGATIVE, BUT NEED IT POSITIVE
|
|
LD E,A ; LINES TO SCROLL TO E
|
|
CALL XOS_SCROLL ; SCROLL REVERSE 'E' LINES
|
|
CALL REVERSE_CURSOR_POS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
XKBD_STAT:
|
|
XKBD_FLUSH:
|
|
XKBD_READ:
|
|
OR $FF ; RETURN FAILURE STATUS
|
|
RET
|
|
|
|
XOS_VDARDC:
|
|
XOR A
|
|
RET
|
|
|
|
;
|
|
;======================================================================
|
|
; XOSERA DRIVER - PRIVATE DRIVER FUNCTIONS
|
|
;======================================================================
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_XY:
|
|
CALL XOS_XY2IDX ; CONVERT ROW/COL TO BUF IDX
|
|
LD DE,(XOS_OFF)
|
|
ADD HL,DE
|
|
LD (XOS_POS),HL ; SAVE THE RESULT (DISPLAY POSITION)
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; CONVERT XY COORDINATES IN DE INTO LINEAR INDEX IN HL
|
|
; D=ROW, E=COL
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_XY2IDX:
|
|
LD A,E ; SAVE COLUMN NUMBER IN A
|
|
LD H,D ; SET H TO ROW NUMBER
|
|
PUSH AF
|
|
LD A,(XOS_COLS)
|
|
LD E,A ; SET E TO ROW LENGTH
|
|
CALL MULT8 ; MULTIPLY TO GET ROW OFFSET
|
|
POP AF
|
|
LD E,A ; GET COLUMN BACK
|
|
ADD HL,DE ; ADD IT IN
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; REVERSE_CURSOR_POS - REVERSE VIDEO THE CHARACTER AT THE CURRENT
|
|
; CURSOR POSITION.
|
|
;----------------------------------------------------------------------
|
|
;
|
|
REVERSE_CURSOR_POS:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
LD DE,(XOS_POS)
|
|
XM_SETW(ZXM_RD_XADDR)
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
XM_GETW(ZXM_XDATA) ; GET THE ATTRIBUTE/CHAR AT CURSOR INTO DE
|
|
LD A,D
|
|
RLCA ; SWAP FG/BG COLORS
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
LD D,A
|
|
XM_SETW(ZXM_XDATA)
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; WRITE VALUE IN A TO CURRENT XOSERA BUFFER POSITION, ADVANCE CURSOR
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_PUTCHAR:
|
|
; SETUP DE WITH TILEMEM ADDRESS
|
|
LD DE,(XOS_POS)
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
; SETUP CHAR/ATTR IN DE
|
|
LD E,A ; CHARACTER TO E
|
|
LD A,(XOS_ATTR) ; ATTRIBUTE
|
|
LD D,A ; ... TO D
|
|
; WRITE CHAR & ATTR
|
|
XM_SETW(ZXM_XDATA)
|
|
; UPDATE CURRENT POSITION
|
|
LD HL,(XOS_POS) ; GET CURSOR POSITION
|
|
INC HL ; INCREMENT
|
|
LD (XOS_POS),HL
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; FILL AREA IN BUFFER WITH SPECIFIED CHARACTER AND CURRENT COLOR/ATTRIBUTE
|
|
; STARTING AT THE CURRENT FRAME BUFFER POSITION
|
|
; A: FILL CHARACTER
|
|
; BC: NUMBER OF CHARACTERS TO FILL
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_FILL:
|
|
LD H,A ; CACHE FILL CHAR IN H
|
|
; SETUP DE WITH INITIAL BUFFER ADDRESS
|
|
LD DE,(XOS_POS) ; GET CURRENT POSITION
|
|
PUSH BC ; PRESERVE BC (C USED BY MACRO)
|
|
XM_SETW(ZXM_WR_XADDR) ; SET VRAM WRITE ADDRESS
|
|
POP BC ; RESTORE BC
|
|
|
|
XOS_FILL1:
|
|
; FILL ONE POSITION (ATTR & CHAR)
|
|
LD E,H ; CHARACTER TO E
|
|
LD A,(XOS_ATTR) ; ATTRIBUTE
|
|
LD D,A ; ... TO D
|
|
PUSH BC ; PRESERVE BC (C USED BY MACRO)
|
|
XM_SETW(ZXM_XDATA) ; WRITE CHAR & ATTR
|
|
POP BC ; RESTORE BC
|
|
|
|
; CHECK COUNT
|
|
DEC BC ; DECREMENT COUNT
|
|
LD A,B ; TEST FOR
|
|
OR C ; ... ZERO
|
|
JR Z,XOS_FILL2 ; DONE IF SO
|
|
|
|
; UPDATE CURSOR POSITION
|
|
PUSH HL
|
|
LD HL,(XOS_POS) ; GET CURSOR POSITION
|
|
INC HL ; INCREMENT
|
|
LD (XOS_POS),HL
|
|
POP HL
|
|
JR XOS_FILL1
|
|
XOS_FILL2:
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; BLOCK COPY BC BYTES FROM HL (SOURCE) TO DE (DEST).
|
|
;----------------------------------------------------------------------
|
|
;
|
|
XOS_BLKCPY:
|
|
PUSH BC ; COUNT ==> TOS
|
|
; SETUP XOSERA VRAM READ ADDRESS FROM HL
|
|
PUSH DE
|
|
LD D,H
|
|
LD E,L
|
|
XM_SETW(ZXM_RD_XADDR)
|
|
|
|
; SETUP XOSERA VRAM WRITE ADDRESS FROM DE
|
|
POP DE
|
|
XM_SETW(ZXM_WR_XADDR)
|
|
XOS_BLKCPY1:
|
|
; GET NEXT SOURCE WORD INTO DE
|
|
XM_GETW(ZXM_XDATA)
|
|
; WRITE DE TO DEST WORD
|
|
XM_SETW(ZXM_XDATA)
|
|
|
|
; DECREMENT BYTE COUNT AND CHECK FOR COMPLETION
|
|
EX (SP),HL ; GET COUNT, SAVE HL
|
|
DEC H ; DECREMENT
|
|
LD A,H ; TEST FOR
|
|
CP L ; ... ZERO
|
|
EX (SP),HL ; COUNT BACK TO TOS, RESTORE HL
|
|
JR NZ,XOS_BLKCPY1 ; LOOP IF NOT ZERO
|
|
POP BC ; CLEAN UP STACK
|
|
RET ; DONE
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; SCROLL ENTIRE SCREEN FORWARD BY ONE OR MORE LINES (CURSOR POSITION UNCHANGED)
|
|
;----------------------------------------------------------------------
|
|
; NUMBER OF LINES TO SCROLL COMES IN E
|
|
|
|
XOS_SCROLL:
|
|
; DEST ADDR IS START OF LAST ROW
|
|
PUSH DE ; SAVE SCROLL LINE COUNT
|
|
PUSH DE ; SAVE IT TWICE
|
|
PUSH DE ; SAVE IT THRICE
|
|
LD A,(XOS_ROWS)
|
|
DEC A
|
|
LD H,A ; H := ROWS - 1
|
|
LD A,(XOS_COLS)
|
|
LD E,A
|
|
CALL MULT8
|
|
LD B,H
|
|
LD C,L
|
|
LD HL,(XOS_OFF)
|
|
ADD HL,BC ; HL := DEST TILEMEM ADDRESS
|
|
; SOURCE ADDRESS is DEST ADDRESS - (COLS * LINES)
|
|
POP DE ; RESTORE LINE COUNT IN E
|
|
PUSH HL ; SAVE DEST ADDRESS SO WE CAN USE H
|
|
LD A,(XOS_COLS)
|
|
LD H,A
|
|
CALL MULT8
|
|
LD D,H
|
|
LD E,L ; DE := COLS * LINES
|
|
POP HL ; RESTORE DEST ADDR BACK TO HL
|
|
PUSH HL
|
|
OR A ; CLEAR CARRY
|
|
SBC HL,DE ; HL := SOURCE ADDR
|
|
POP BC ; BC := DEST ADDRESS
|
|
LD A,(XOS_ROWS)
|
|
POP DE ; GET SCROLL LINE COUNT IN TO E
|
|
SUB E
|
|
LD D,B
|
|
LD E,C ; RESTORE DE AS DEST ADDR
|
|
LD B,A ; B := ROWS - LINE COUNT => LOOP COUNTER
|
|
; USE BLKCPY TO COPY ONE ROW
|
|
XOS_SCROLL1:
|
|
PUSH HL ; HL IS SOURCE ADDR FOR BLOCK COPY
|
|
PUSH DE ; DE IS DEST ADDR FOR BLOCK COPY
|
|
PUSH BC ; B IS OUR LOOP COUNTER
|
|
LD A,(XOS_COLS) ; EXCEPT THAT BLOCK COPY USES BC FOR COPY COUNT
|
|
LD C,A
|
|
LD B,0
|
|
CALL XOS_BLKCPY
|
|
POP BC ; RESTORE LOOP COUNTER
|
|
; CHECK COUNT
|
|
DEC B
|
|
JR Z,XOS_SCROLL2 ; MOVE ON TO FILL WHEN DONE
|
|
|
|
; DECREMENT SOURCE AND DEST BY ONE ROW
|
|
POP HL ; HL := DEST ADDRESS
|
|
LD A,(XOS_COLS)
|
|
LD E,A
|
|
LD D,0
|
|
OR A ; CLEAR CARRY
|
|
SBC HL,DE ; HL := UPDATED DEST ADDRESS (DEST ADDR - COLS)
|
|
POP DE ; DE := SOURCE ADDR
|
|
PUSH HL ; SAVE UPDATED DEST TEMPORARILY
|
|
LD H,D
|
|
LD L,E
|
|
LD A,(XOS_COLS)
|
|
LD E,A
|
|
LD D,0
|
|
OR A ; CLEAR CARRY
|
|
SBC HL,DE ; HL := UPDATED SOURCE ADDRESS
|
|
POP DE ; DE := UPDATED DEST ADDRESS
|
|
JR XOS_SCROLL1 ; LOOP AROUND
|
|
XOS_SCROLL2:
|
|
POP DE
|
|
POP HL ; CLEAN UP STACK
|
|
POP DE ; RESTORE SCROLL LINE COUNT
|
|
; NOW FILL THE E LINES AT THE TOP OF THE SCREEN.
|
|
; FIRST, SAVE OFF CURRENT CURSOR POSITION, THE SET IT TO 0,0
|
|
LD HL,(XOS_POS)
|
|
PUSH HL
|
|
LD HL,(XOS_OFF)
|
|
LD (XOS_POS),HL ; CURSOR POSITION NOW 0,0
|
|
; COMPUTE THE NUMBER OF BYTES FILL WHICH IS COLS * LINES
|
|
LD A,(XOS_COLS)
|
|
LD H,A
|
|
CALL MULT8
|
|
LD B,H
|
|
LD C,L
|
|
LD A,$20 ; FILL CHAR IS SPACE
|
|
CALL XOS_FILL
|
|
POP HL
|
|
LD (XOS_POS),HL ; RESTORE ORIGINAL CURSOR POSITION
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; REVERSE SCROLL ENTIRE SCREEN BY ONE LINE (CURSOR POSITION UNCHANGED)
|
|
;----------------------------------------------------------------------
|
|
; NUMBER OF LINES TO SCROLL COMES IN E
|
|
|
|
XOS_RSCROLL:
|
|
PUSH DE ; SAVE SCROLL LINE COUNT
|
|
PUSH DE ; NEED IT OFF THE STACK TWICE
|
|
PUSH DE ; NEED IT OFF THE STACK THRICE
|
|
; DEST ADDR IS ROW=0, COL=0
|
|
LD DE,(XOS_OFF)
|
|
XM_SETW(ZXM_WR_XADDR) ; SET DEST ADDR IN XOSERA
|
|
POP DE ; RESTORE SCROLL LINE COUNT IN E
|
|
; SOURCE ADDR (HL) = XOS_OFF + XOS_COLS * E
|
|
LD A,(XOS_COLS)
|
|
LD H,A
|
|
CALL MULT8 ; HL := XOS_COLS * E
|
|
LD BC,(XOS_OFF)
|
|
ADD HL,BC ; HL := SOURCE ADDR := XOS_OFF + XOS_COLS * E
|
|
LD D,H
|
|
LD E,L
|
|
XM_SETW(ZXM_RD_XADDR) ; SET SOURCE ADDR IN XOSERA
|
|
; COMPUTE THE COUNT OF WORDS TO MOVE = COLS * (ROWS - LINES)
|
|
POP DE ; RESTORE SCROLL LINE COUNT IN E
|
|
LD A,(XOS_ROWS)
|
|
SUB E
|
|
LD H,A ; H := ROWS - LINES
|
|
LD A,(XOS_COLS)
|
|
LD E,A ; E := COLS
|
|
CALL MULT8
|
|
LD B,H
|
|
LD C,L ; BC = COUNT := COLS * (ROW - LINES)
|
|
PUSH BC ; SAVE FOR LATER USE BY FILL
|
|
XOS_RSCROLL1:
|
|
PUSH BC ; MACROS BELOW ALTER C, SO SAVE
|
|
XM_GETW(ZXM_XDATA) ; TRANSFER A WORD FROM TILEMEM SRC TO DEST
|
|
XM_SETW(ZXM_XDATA)
|
|
POP BC ; RESTORE LOOP COUNT
|
|
; CHECK COUNT
|
|
DEC BC ; DECREMENT COUNT
|
|
LD A,B ; TEST FOR
|
|
OR C ; ... ZERO
|
|
JR Z,XOS_RSCROLL2 ; MOVE ON TO FILL WHEN DONE
|
|
JR XOS_RSCROLL1
|
|
XOS_RSCROLL2:
|
|
; NOW DO THE FILL OF THE EXPOSED LINES AT THE BOTTOM OF THE SCREEN.
|
|
; DESTINATION VRAM ADDRESS FOR THIS FILL IS THE COUNT FROM ABOVE PLUS VRAM OFFSET
|
|
POP BC ; RESTORE COUNT
|
|
POP DE ; RESTORE LINES IN E
|
|
LD A,(XOS_COLS)
|
|
LD H,A
|
|
PUSH BC ; SAVE COUNT AGAINT
|
|
CALL MULT8 ; HL := XOS_COLS * LINES
|
|
LD B,H
|
|
LD C,L ; BC NOW HAS FILL WORD COUNT
|
|
POP HL ; RESTORE SCROLL WORD COUNT TO HL
|
|
LD DE,(XOS_OFF)
|
|
ADD HL,DE ; ADD IN OFFSET
|
|
LD D,H
|
|
LD E,L ; DE NOW HAS DEST VRAM ADDR
|
|
LD HL,(XOS_POS) ; XOS_FILL USES XOS_POS AS DEST
|
|
PUSH HL ; SAVE CURRENT CURSOR POSITION
|
|
LD (XOS_POS),DE
|
|
LD A,$20 ; USE SPACE TO FILL (USING CURRENT COLOR/ATTR)
|
|
CALL XOS_FILL
|
|
POP HL
|
|
LD (XOS_POS),HL ; RESTORE PREVIOUS CURSOR POSITION
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; XOSERA DRIVER - DATA
|
|
;==================================================================================================
|
|
;
|
|
XOS_ATTR: .DB 0 ; CURRENT COLOR
|
|
XOS_POS: .DW 0 ; CURRENT DISPLAY POSITION
|
|
XOS_OFF: .DW 0 ; SCREEN START OFFSET INTO XOSERA VRAM
|
|
XOS_RUB: .DB 0 ; REVERSE/UNDERLINE/BLINK (-----RUB)
|
|
XOS_COLS: .DB 0 ; NUMBER OF COLUMNS
|
|
XOS_ROWS: .DB 0 ; NUMBER OF ROWS
|
|
|
|
XOS_BASE_INIT:
|
|
.DW $0000 ; XR_VID_CTRL => NO PLAYFIELD COLOR SWAP. BORDER CORDER = 0
|
|
.DW $0000 ; XR_COPP_CTRL => DISABLE COPPER
|
|
.DW $0000 ; XR_AUD_CTRL => DISABLE AUDIO
|
|
.DW $0000 ; XR_SCANLINE => JUST SET TO ZERO
|
|
.DW $0000 ; XR_VID_LEFT => LEFT EDGE OF ACTIVE DISPLAY => 0
|
|
.DW 640 ; XR_VID_RIGHT => RIGHT EDGE OF ACTIVE DISPLAY => 640
|
|
.DW $0000 ; XR_POINTER_H => HIDE POINTER, SO SET TO 0
|
|
.DW $0000 ; XR_POINTER_V => HIDE POINTER, SO SET TO 0
|
|
|
|
PF_640x480x4:
|
|
; CONFIGURE PLAYFIELD FOR 640x480x4BPP BITMAP GRAPHICS (LETTERBOXED TO 640 X 400)
|
|
.DW $0050 ; GFX_CTRL
|
|
.DW $0000 ; TILE_CTRL => IGNORED IN BITMAP MODE
|
|
.DW $0000 ; DISP_ADDR => START OF VRAM
|
|
.DW $00A0 ; LINE_LEN => 640 PIXELS WIDE / 4 PIXELS PER WORD = 160d
|
|
.DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING
|
|
.DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING
|
|
.DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING
|
|
|
|
PF_80X30_TILED:
|
|
; CONFIGURE PLAYFIELD FOR 80 X 30 TILED MODE
|
|
; TILEMAP AND 8x16 FONT DATA BOTH RESIDE IN TILEMEM (AS OPPOSED TO VRAM)
|
|
.DW $0000 ; GFX_CTRL
|
|
.DW FONT_ST_8x16_ADDR | TILE_CTRL_DISP_TILEMEM_F | 15; TILE_CTRL => (LAST ONE IS TILE HEIGHT - 1)
|
|
.DW FONT_ST_8x16_ADDR + FONT_ST_8x16_SIZE ; DISP_ADDR => TILEMAP STATS JUST AFTER FONT DATA IN TILEMEM.
|
|
.DW $0050 ; LINE_LEN => 80 COLS
|
|
.DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING
|
|
.DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING
|
|
.DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING
|
|
|
|
PF_80X60_TILED:
|
|
; CONFIGURE PLAYFIELD FOR 80 X 60 TILED MODE
|
|
; TILEMAP WILL RESIDE IN TILEMEM, BUT DATA IS AT $FC00 IN VRAM
|
|
.DW $0000 ; GFX_CTRL
|
|
.DW $FC00 | TILE_CTRL_DISP_TILEMEM_F | TILE_CTRL_TILE_VRAM_F | 7; TILE_CTRL => (LAST ONE IS TILE HEIGHT - 1)
|
|
.DW $4000 ; DISP_ADDR => TILEMAP STARTS AT BEGINNING OF TILEMEM
|
|
.DW $0050 ; LINE_LEN => 80 COLS
|
|
.DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING
|
|
.DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING
|
|
.DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING
|
|
|
|
XOS_PALETTE:
|
|
; SET THE FIRST SIXTEEN ENTRIES OF A XOSERA PALETTE TO MATCH WHAT IS EXPECTED BY ROMWBW.
|
|
.DW $0000 ; 0: BLACK
|
|
.DW $0A00 ; 1: RED
|
|
.DW $00A0 ; 2: GREEN
|
|
.DW $0A50 ; 3: BROWN
|
|
.DW $000A ; 4: BLUE
|
|
.DW $0A0A ; 5: MAGENTA
|
|
.DW $00AA ; 6: CYAN
|
|
.DW $0AAA ; 7: WHITE
|
|
.DW $0555 ; 8: GRAY
|
|
.DW $0F55 ; 9: LIGHT RED
|
|
.DW $05F5 ; 10: LIGHT GREEN
|
|
.DW $0FF5 ; 11: YELLOW
|
|
.DW $055F ; 12: LIGHT BLUE
|
|
.DW $0F5F ; 13: LIGHT MAGENTA
|
|
.DW $05FF ; 14: LIGHT CYAN
|
|
.DW $0FFF ; 15: BRIGHT WHITE
|
|
|
|
; XOSERA HAS A BUILT-IN AMIGA-ISH COPROCESSOR. WE USE IT HERE TO LIMIT THE GRAPHICS
|
|
; BITMAP DISPLAY TO 600x400. THIS IS REQUIRED BECAUSE WHILE XOSERA OUTPUTS a 640 X 480
|
|
; BY 60 HZ VGA SIGNAL, THERE IS NOT ENOUGH VRAM FOR A FULL 640 X 480 X 4BPP BITMAP. SO WE
|
|
; RESTRICT TO 640x400 AND USE SOME COPPER TRICKS TO BLANK THE OTHER 80 LINES OF
|
|
; THE DISPLAY. ESSENTIALLY WE ARE 'LETTERBOXING' A 640 X 400 BITMAP IN THE VERTICAL
|
|
; CENTER OF A 640 X 480 DISPLAY. NOTE THAT TEXT MODE STILL USES THE ENTIRE 640 X 480
|
|
; DISPLAY.
|
|
|
|
XOS_COPPER:
|
|
.DW $D101,$0800 ; LDM $C101
|
|
.DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; start the frame by blanking the display
|
|
.DW $2828 ; VPOS #40 ; Wait for line 40
|
|
.DW $0800,$0000 ; LDI #0
|
|
.DW $1800,$0017 ; STM XR_PA_LINE_ADDR
|
|
.DW $D100,$0800 ; LDM $C100 ; get value of XR_PA_GFX_CTRL with BLANK bit NOT set
|
|
.DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; unblank playfield A
|
|
.DW $D101,$0800 ; LDM $C101 ; get value of XR_PA_GFX_CTRL with BLANK bit set
|
|
.DW $29B8 ; VPOS #440 ; wait until vertical line 440
|
|
.DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; blank playfield A
|
|
.DW $2BFF ; VPOS #V_EOF ; wait until end of frame
|
|
;
|
|
;==================================================================================================
|
|
; XOSERA DRIVER - INSTANCE DATA
|
|
;==================================================================================================
|
|
;
|
|
XOS_IDAT:
|
|
.DB KBDMODE_NONE
|
|
.DB 0
|
|
.DB 0
|
|
|
|
XOS_IDAT2:
|
|
.DB KBDMODE_NONE
|
|
.DB 0
|
|
.DB 0
|
|
|