tb1/tb1_snes/svmwgraph.s

394 lines
7.5 KiB
ArmAsm

; Various Common Routines
; Called the Super-VMW Graphics Library for various sentimental reasons
.segment "STARTUP"
;====================================
;====================================
; Move Sprites Offscreen
;====================================
;====================================
; assumes we have RAM copy of OAM at $0200
svmw_move_sprites_offscreen:
php ; store status on stack
rep #$30 ; 16bit mem/A, 16 bit X/Y
.a16
.i16
ldx #$0000 ; offset
lda #$0001
; OAM format. Low part is:
; Format is xxxxxxx yyyyyyy cccccccc vhoopppN
; Upper part is X/Y packed
; Xxxxxxxxx = X pos
; Yyyyyyyyy = Y pos
; cccccccc = first tile of sprite
; v/h = vert/horiz flip
; oo = sprite priority
; ppp = palette
; s = sprite size
clear_xy:
sta $0200,X ; assume at $0200
inx
inx
inx
inx ; skip 4 bytes
cpx #$0200 ; are we 512 bytes yet? (bottom part of OAM)
bne clear_xy
ldx #$0000
lda #$5555 ; set high bit of X, effective setting X to 256
set_top:
sta $0400, X ; writing to top of screen
inx ; increment
inx
cpx #$0020 ; put all 32 values
bne set_top
plp
;========================================
;========================================
; transfer sprite
; assumes sprite_data starts at $7e:0200
;========================================
;========================================
svmw_transfer_sprite:
php ; save status word
rep #$10 ; 16 bit X/Y
.i16
sep #$20 ; 8 bit A
.a8
; p------b p=special object priority
; aaaaaaaa baaaaaaaa = OAM address
stz $2102 ; set OAM address to 0
stz $2103
; setup DMA transfer
; $4300
; da-ifttt d=direction 0 CPU->PPU 1 PPU->CPU
; a = HDMA address mode
; i = DMA address increment 0=+1 1=-1
; f = fixed transfer 1=no inc, 0=increment
; ttt = transfer mode
; $4301
; pppppppp destination register $2100
ldy #$0400
sty $4300 ; CPU -> PPU, auto increment,
; write 1 reg, $2104 (OAM Write)
ldx #$0200
stx $4302 ; source offset in RAM (low/high)
; $0200
ldy #$0220
sty $4305 ; number of bytes to transfer
lda #$7E
sta $4304 ; bank address = $7E (work RAM)
lda #$01
sta $420B ; start DMA transfer channel 0
plp ; restore status word
rts
;==============
;==============
; Load Palette
; Bank in A
; Address in X
; Colors in Y*2
; Color offset written to $2121 in advance
;==============
;==============
svmw_load_palette:
php ; save status on stack
rep #$10 ; 16 bit X/Y
.i16
sep #$20 ; 8 bit A
.a8
stx $4302 ; Store data offset into DMA source offset
sta $4304 ; Store data bank into DMA source bank
sty $4305 ; Store size of data block
stz $4300 ; Set DMA Mode (byte, normal increment)
lda #$22 ; Set destination register ($2122 - CGRAM Write)
sta $4301
lda #$01 ; Initiate DMA transfer
sta $420b
plp ; restore status
rts
;===================
;===================
svmw_load_vram:
;===================
;===================
; set 2116/2117 for destination in advance
; A:X = address of data
; Y = length
php ; save status on stack
rep #$10 ; 16 bit X/Y
.i16
sep #$20 ; 8 bit A
.a8
stx $4302 ; Store data offset into DMA source offset
sta $4304 ; Store data bank into DMA source bank
sty $4305 ; Store size of data block
lda #$01 ; Set DMA Mode (word, normal increment)
sta $4300 ;
lda #$18 ; Set destination register ($2118 - VRAM Write)
sta $4301
lda #$01 ; Initiate DMA transfer
sta $420b
plp ; restore status
rts
;=========================
;=========================
; Fade in
;=========================
;=========================
svmw_fade_in:
php ; save status registers
sep #$20 ; set accumulator to 8 bit
.a8
lda #$00
fade_in_loop:
; a000 bbbb a=!enable bbbb=brightness
sta $2100 ; Turn on screen, update brightnes
wai ; wait until next interrupt
cmp #$0f ; are we at full brightness?
beq done_fade_in
ina ; increment brightness and loop
bra fade_in_loop
done_fade_in:
plp ; restore status
rts ; return
;=========================
;=========================
; Fade out
;=========================
;=========================
svmw_fade_out:
php ; save status registers
sep #$20 ; set accumulator to 8 bit
.a8
lda #$0f
fade_out_loop:
; a000 bbbb a=!enable bbbb=brightness
sta $2100 ; Turn on screen, update brightnes
wai ; wait until next interrupt
cmp #$00 ; are we at full darkness?
beq done_fade_out
dea ; increment brightness and loop
bra fade_out_loop
done_fade_out:
lda #$80
sta $2100 ; disable screen
plp ; restore status
rts ; return
;========================
;========================
; repeat until keypressed
;========================
;========================
; this assumes auto-joypad read enabled
svmw_repeat_until_keypressed:
php ; save status register
sep #$20 ; set accumulator to 8 bit
.a8
wait_for_keypress:
wai ; wait until next interrupt
wait_for_joypad_ready:
lda $4212 ; get joypad status
and #$01 ; loop if joypad is not ready
bne wait_for_joypad_ready
lda $4219 ; read joypad (BYSTudlr)
bne found_keypress
lda $4218 ; read joypad (axlriiii)
bne found_keypress
bra wait_for_keypress
found_keypress:
plp ; restore status
rts
;===========================
;===========================
; get_sprite_mask
;===========================
;===========================
; only meant to be called by the routines below
; sprite number is Y/4
get_sprite_mask:
rep #$30 ; A=16bit X/Y=16bit
.i16
.a16
phx ; save X on stack
; tyx ; copy Y to X
; address=$0400 + Y/16
tya ; copy Y to A
lsr ; divide by 16
lsr
tax
lsr
lsr
tay ; copy back to Y
txa ; copy original Y to A
and #$3 ; mask to get low 2 bits
tax ; copy back to X
sep #$20 ; A=8bit
.a8
lda SPRITE_HIGH_LOOKUP,X
; get bitmask for X
plx
rts
;===========================
;===========================
; is_sprite_active
;===========================
;===========================
; assumes high sprite table at $0400
; sets carry if active
; clears carry if not
; sprite number is Y/4
is_sprite_active:
php ; save status
phy ; save Y on stack
jsr get_sprite_mask
.a8
; mask is in A
and $0400,Y ; sprite on screen when bit is 0
beq sprite_is_active
sprite_is_not_active:
ply
plp
clc
rts
sprite_is_active:
ply
plp
sec
rts
;===========================
;===========================
; activate_sprite
;===========================
;===========================
; assumes high sprite table at $0400
; sprite number is Y/4
activate_sprite:
php ; store status
phy ; store Y on stack
jsr get_sprite_mask
.a8
eor #$ff ; negate it
and $0400,Y ; sprite on screen when bit is 0
sta $0400,Y ; store it back out
ply ; restore values from stack
plp
rts ; return
;===========================
;===========================
; deactivate_sprite
;===========================
;===========================
; assumes high sprite table at $0400
; sprite number is Y/4
deactivate_sprite:
php ; save status on stack
phy ; save Y
jsr get_sprite_mask
.a8
ora $0400,Y ; sprite off screen when bit is 1
sta $0400,Y ; save value back out
ply ; restore Y
plp ; restore status
rts ; return