mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2026-01-28 23:40:51 +11:00
Add initializer module for VDP
This commit is contained in:
parent
fd84d3abbb
commit
d1dcdd1381
18 changed files with 1008 additions and 7 deletions
591
src/vdp_utils.s
Normal file
591
src/vdp_utils.s
Normal file
|
|
@ -0,0 +1,591 @@
|
|||
.rtmodel version,"1"
|
||||
.rtmodel core,"6502"
|
||||
|
||||
.extern _Zp
|
||||
.extern VDP_MEM, VDP_REG
|
||||
|
||||
.section code,text
|
||||
|
||||
|
||||
;;; vdp_point_to_vram_xy:
|
||||
;;; Readies the VDP registers to write on a tile at XY
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [_Zp[4]]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_point_to_vram_xy:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
lda #0x00
|
||||
sta zp:T_VADD_H$
|
||||
lda zp:P_Y$
|
||||
sta zp:T_VADD_L$
|
||||
|
||||
;; Shift Y five times to the left to get the offset for the ROW in VRAM
|
||||
ldx #5
|
||||
ShiftOffset$:
|
||||
asl zp:T_VADD_L$
|
||||
rol zp:T_VADD_H$
|
||||
dex
|
||||
bne ShiftOffset$
|
||||
|
||||
clc
|
||||
|
||||
; Calculate the VRAM address
|
||||
lda zp:P_X$
|
||||
adc zp:T_VADD_L$
|
||||
sta zp:T_VADD_L$
|
||||
ldx zp:P_NT_IDX$
|
||||
lda NameTablesList,x
|
||||
adc zp:T_VADD_H$
|
||||
sta zp:T_VADD_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:T_VADD_L$
|
||||
sta VDP_REG
|
||||
lda zp:T_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_set_tile:
|
||||
;;; Prints the provided ASCII string at the specified coordinates
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [A]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;; - tile index [_Zp[2]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_set_tile:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_TILE$: .equ _Zp+2
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
sta zp:P_NT_IDX$
|
||||
|
||||
jsr vdp_point_to_vram_xy
|
||||
|
||||
lda zp:P_TILE$
|
||||
sta VDP_MEM
|
||||
|
||||
EOS$:
|
||||
rts
|
||||
|
||||
;;; vdp_print_string:
|
||||
;;; Prints the provided ASCII string at the specified coordinates (newlines and control chars are not supported)
|
||||
;;; Parameters:
|
||||
;;; - nametable index in vram [A]
|
||||
;;; - X coordinate [_Zp[0]]
|
||||
;;; - Y coordinate [_Zp[1]]
|
||||
;;; - string address [_Zp[2], _Zp[3]]: Address of the beginning of data to write
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 5, 6
|
||||
;;;
|
||||
vdp_print_string:
|
||||
T_VADD_H$: .equ _Zp+6
|
||||
T_VADD_L$: .equ _Zp+5
|
||||
P_NT_IDX$: .equ _Zp+4
|
||||
P_DATA_H$: .equ _Zp+3
|
||||
P_DATA_L$: .equ _Zp+2
|
||||
P_Y$: .equ _Zp+1
|
||||
P_X$: .equ _Zp+0
|
||||
|
||||
sta zp:P_NT_IDX$
|
||||
|
||||
jsr vdp_point_to_vram_xy
|
||||
|
||||
ldy #0x00
|
||||
NextChar$:
|
||||
lda (zp:P_DATA_L$),y
|
||||
beq EOS$
|
||||
sec
|
||||
sbc #0x20
|
||||
sta VDP_MEM
|
||||
iny
|
||||
bne NextChar$
|
||||
|
||||
EOS$:
|
||||
rts
|
||||
|
||||
;;; vdp_write_vram:
|
||||
;;; Write the provided data into VRAM at specified address
|
||||
;;; Parameters:
|
||||
;;; - data address [_Zp[0], _Zp[1]]: Address of the beginning of data to write
|
||||
;;; - data length [_Zp[2], _Zp[3]]: Length of data to write
|
||||
;;; - VRAM address [_Zp[4], _Zp[5]]: Start address of data in VRAM
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3
|
||||
;;;
|
||||
vdp_write_vram:
|
||||
P_VADD_H$: .equ _Zp+5
|
||||
P_VADD_L$: .equ _Zp+4
|
||||
P_DLEN_H$: .equ _Zp+3
|
||||
P_DLEN_L$: .equ _Zp+2
|
||||
P_DATA_H$: .equ _Zp+1
|
||||
P_DATA_L$: .equ _Zp+0
|
||||
|
||||
; Decrement length by one, so or the loop would do an off-by-one write
|
||||
sec
|
||||
lda zp:P_DLEN_L$
|
||||
sbc #1
|
||||
sta zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_H$
|
||||
sbc #0
|
||||
sta zp:P_DLEN_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:P_VADD_L$
|
||||
sta VDP_REG
|
||||
lda zp:P_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
|
||||
; Actually write data into VRAM
|
||||
ldx zp:P_DLEN_H$
|
||||
ldy #0x00
|
||||
CopyLoop$:
|
||||
lda (zp:P_DATA_L$),y
|
||||
sta VDP_MEM
|
||||
iny
|
||||
bne SkipHIncr$ ; Check if we did overflow. In case, increment the high byte of the address
|
||||
inc zp:P_DATA_H$
|
||||
SkipHIncr$:
|
||||
dec zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_L$
|
||||
cmp #0xFF
|
||||
bne CopyLoop$
|
||||
dex
|
||||
bpl CopyLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_fill_vram:
|
||||
;;; Fill VRAM with a specific byte
|
||||
;;; Parameters:
|
||||
;;; - fill value [A]
|
||||
;;; - data length [_Zp[0], _Zp[1]]: Length of data to write
|
||||
;;; - VRAM address [_Zp[2], _Zp[3]]: Start address of data in VRAM
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 0, 1, 2, 4
|
||||
;;;
|
||||
vdp_fill_vram:
|
||||
T_FILLVAL$: .equ _Zp+4
|
||||
P_VADD_H$: .equ _Zp+3
|
||||
P_VADD_L$: .equ _Zp+2
|
||||
P_DLEN_H$: .equ _Zp+1
|
||||
P_DLEN_L$: .equ _Zp+0
|
||||
|
||||
sta zp:T_FILLVAL$
|
||||
|
||||
; Decrement length by one, so or the loop would do an off-by-one write
|
||||
sec
|
||||
lda zp:P_DLEN_L$
|
||||
sbc #1
|
||||
sta zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_H$
|
||||
sbc #0
|
||||
sta zp:P_DLEN_H$
|
||||
|
||||
; Setup the VDP to write into VRAM
|
||||
lda zp:P_VADD_L$
|
||||
sta VDP_REG
|
||||
lda zp:P_VADD_H$
|
||||
ora #0x40
|
||||
sta VDP_REG
|
||||
|
||||
; Fill the VRAM
|
||||
ldx zp:P_DLEN_H$
|
||||
CopyLoop$:
|
||||
lda zp:T_FILLVAL$
|
||||
sta VDP_MEM
|
||||
|
||||
dec zp:P_DLEN_L$
|
||||
lda zp:P_DLEN_L$
|
||||
cmp #0xFF
|
||||
bne CopyLoop$
|
||||
dex
|
||||
bpl CopyLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_detect:
|
||||
;;; Check if a VDP is present
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: 0xFF in A if VDP is present, 0 otherwise
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A
|
||||
;;;
|
||||
vdp_detect:
|
||||
lda #0x00
|
||||
sta VDP_REG
|
||||
lda #0x40
|
||||
sta VDP_REG
|
||||
|
||||
lda #0x55
|
||||
sta VDP_MEM
|
||||
lda #0xAA
|
||||
sta VDP_MEM
|
||||
|
||||
lda #0x00
|
||||
sta VDP_REG
|
||||
sta VDP_REG
|
||||
|
||||
eor VDP_MEM
|
||||
eor VDP_MEM
|
||||
|
||||
cmp #0xFF
|
||||
beq VdpFound$
|
||||
lda #0x00
|
||||
VdpFound$:
|
||||
rts
|
||||
|
||||
;;; vdp_hide_sprites:
|
||||
;;; Marks all sprites as hidden
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_hide_sprites:
|
||||
ldy #0
|
||||
HideLoop$:
|
||||
tya
|
||||
|
||||
jsr vdp_hide_sprite
|
||||
|
||||
iny
|
||||
cpy #25
|
||||
bne HideLoop$
|
||||
|
||||
rts
|
||||
|
||||
;;; vdp_hide_sprite:
|
||||
;;; Mark a single sprite as hidden
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_hide_sprite:
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda #0xC0
|
||||
sta SpriteAttributeTable,x
|
||||
rts
|
||||
|
||||
;;; vdp_show_sprite:
|
||||
;;; Enable a single sprite in the game grid
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_show_sprite:
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda SAT_Y_Map,y
|
||||
sta SpriteAttributeTable,x
|
||||
rts
|
||||
|
||||
;;; vdp_set_sprite_tile:
|
||||
;;; Set the current tile index for a specific sprite
|
||||
;;; Parameters:
|
||||
;;; - sprite number [A]
|
||||
;;; - tile index [_Zp [0]]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;;
|
||||
vdp_set_sprite_tile:
|
||||
P_TILE_IDX$:.equ _Zp+0
|
||||
asl zp:P_TILE_IDX$ ; We're using 2x2 tile sprites
|
||||
asl zp:P_TILE_IDX$
|
||||
|
||||
tay
|
||||
ldx SAT_RowCol_Trans_Table,y
|
||||
lda zp:P_TILE_IDX$
|
||||
sta SpriteAttributeTable+2,x
|
||||
rts
|
||||
|
||||
;;; vdp_switch_nt:
|
||||
;;; Switch shown nametable
|
||||
;;; Parameters:
|
||||
;;; - name table index [A]
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, X
|
||||
;;;
|
||||
vdp_switch_nt:
|
||||
tax
|
||||
lda NameTablesList,x
|
||||
lsr a
|
||||
lsr a
|
||||
sta VDP_REG
|
||||
lda #0x82
|
||||
sta VDP_REG
|
||||
rts
|
||||
|
||||
;;; vdp_write_registers:
|
||||
;;; Initialize the registers of the VDP, using the provided byte array
|
||||
;;; Parameters:
|
||||
;;; - data address [_Zp[0], _Zp[1]]: Address of the beginning of initialization data, a 16 byte array
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y
|
||||
;;;
|
||||
vdp_write_registers:
|
||||
P_REG_H$: .equ _Zp+1
|
||||
P_REG_L$: .equ _Zp+0
|
||||
|
||||
; Write the register sequence
|
||||
ldy #0x00
|
||||
RegLoop$:
|
||||
lda (zp:P_REG_L$),y
|
||||
sta VDP_REG
|
||||
iny
|
||||
cpy #16
|
||||
bne RegLoop$
|
||||
|
||||
rts
|
||||
|
||||
vdp_irq_handler:
|
||||
lda VDP_REG ; Clear the interrupt
|
||||
|
||||
jsr _vdp_write_interleaved_sat
|
||||
|
||||
rti
|
||||
|
||||
;;; _vdp_write_interleaved_sat:
|
||||
;;; Updates SAT at 0x300 with sprite multiplexing
|
||||
;;; Parameters: none
|
||||
;;;
|
||||
;;; Returns: nothing
|
||||
;;;
|
||||
;;; Clobbers:
|
||||
;;; - A, Y, X
|
||||
;;; - Zp 1, 2, 3, 4, 5, 6, 7
|
||||
;;;
|
||||
_vdp_write_interleaved_sat:
|
||||
T_COUNT$: .equ _Zp+7
|
||||
T_SATB_IDX$: .equ _Zp+6
|
||||
T_DEST_H$: .equ _Zp+5
|
||||
T_DEST_L$: .equ _Zp+4
|
||||
T_DLEN_H$: .equ _Zp+3
|
||||
T_DLEN_L$: .equ _Zp+2
|
||||
T_DATA_H$: .equ _Zp+1
|
||||
T_DATA_L$: .equ _Zp+0
|
||||
|
||||
lda #0x00
|
||||
sta zp:T_DEST_L$
|
||||
lda #0x03
|
||||
sta zp:T_DEST_H$
|
||||
|
||||
lda CurrentByteTableOffset
|
||||
cmp #5
|
||||
bne NoOverflow$
|
||||
lda #0
|
||||
sta CurrentByteTableOffset
|
||||
NoOverflow$:
|
||||
asl a
|
||||
sta zp:T_SATB_IDX$
|
||||
|
||||
lda #4
|
||||
sta zp:T_COUNT$
|
||||
|
||||
WriteLoop$:
|
||||
lda #20
|
||||
sta zp:T_DLEN_L$
|
||||
lda #00
|
||||
sta zp:T_DLEN_H$
|
||||
|
||||
lda zp:T_SATB_IDX$
|
||||
tax
|
||||
|
||||
lda SAT_Block_Table,x
|
||||
sta zp:T_DATA_L$
|
||||
lda SAT_Block_Table+1,x
|
||||
sta zp:T_DATA_H$
|
||||
|
||||
jsr vdp_write_vram
|
||||
|
||||
clc
|
||||
lda zp:T_DEST_L$
|
||||
adc #20
|
||||
sta zp:T_DEST_L$
|
||||
|
||||
lda zp:T_SATB_IDX$
|
||||
adc #0x02
|
||||
sta zp:T_SATB_IDX$
|
||||
dec zp:T_COUNT$
|
||||
bpl WriteLoop$
|
||||
|
||||
inc CurrentByteTableOffset
|
||||
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;
|
||||
.section data,data
|
||||
|
||||
SpriteAttributeTable:
|
||||
; Organized in columns
|
||||
SAT_Col1:
|
||||
.byte 0xC0, 0x08, 0x30, 0x01 ; Col 1
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
.byte 0xC0, 0x08, 0x30, 0x01
|
||||
SAT_Col2:
|
||||
.byte 0xC0, 0x30, 0x30, 0x01 ; Col 2
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
.byte 0xC0, 0x30, 0x30, 0x01
|
||||
SAT_Col3:
|
||||
.byte 0xC0, 0x58, 0x30, 0x01 ; Col 3
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
.byte 0xC0, 0x58, 0x30, 0x01
|
||||
SAT_Col4:
|
||||
.byte 0xC0, 0x80, 0x30, 0x01 ; Col 4
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
.byte 0xC0, 0x80, 0x30, 0x01
|
||||
SAT_Col5:
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01 ; Col 5
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
.byte 0xC0, 0xA8, 0x30, 0x01
|
||||
; Unused
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
.byte 0xD0, 0x00, 0x30, 0x00
|
||||
|
||||
SAT_RowCol_Trans_Table:
|
||||
.byte 0, 20, 40, 60, 80
|
||||
.byte 4, 24, 44, 64, 84
|
||||
.byte 8, 28, 48, 68, 88
|
||||
.byte 12, 32, 52, 72, 92
|
||||
.byte 16, 36, 56, 76, 96
|
||||
|
||||
SAT_Y_Map:
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x07
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x27
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x47
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x67
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
.byte 0x87
|
||||
|
||||
SAT_Block_Table:
|
||||
.word SAT_Col1
|
||||
.word SAT_Col2
|
||||
.word SAT_Col3
|
||||
.word SAT_Col4
|
||||
.word SAT_Col5
|
||||
.word SAT_Col1
|
||||
.word SAT_Col2
|
||||
.word SAT_Col3
|
||||
.word SAT_Col4
|
||||
.word SAT_Col5
|
||||
|
||||
; Contains a list of VRAM addresses corresponding to every page
|
||||
NameTablesList:
|
||||
NT_P0: .byte 0x00
|
||||
NT_P1: .byte 0x14
|
||||
|
||||
|
||||
CurrentByteTableOffset:
|
||||
.byte 0x00
|
||||
|
||||
;;;
|
||||
;;;
|
||||
;;; Exported symbols
|
||||
.public vdp_write_vram
|
||||
.public vdp_detect
|
||||
.public vdp_write_registers
|
||||
.public vdp_hide_sprites
|
||||
.public vdp_hide_sprite
|
||||
.public vdp_show_sprite
|
||||
.public vdp_switch_nt
|
||||
.public vdp_set_sprite_tile
|
||||
.public vdp_print_string
|
||||
.public vdp_set_tile
|
||||
.public vdp_point_to_vram_xy
|
||||
.public vdp_irq_handler
|
||||
|
||||
.public SpriteAttributeTable ; We'll need to set change visibility and values
|
||||
.public NT_P0, NT_P1
|
||||
Loading…
Add table
Add a link
Reference in a new issue