lundi 23 février 2009

Exemple d'interruption sur Vblank

Dans cet exemple on va simplement desactiver le Background grâce au Vblank interrupt sur IRQ1. A l'aide d'un compteur initialisé à 60 et décrémenté à chaque Vblank, on désactivera l'affichage lorque celui arrivera à 0 (ce qui doit faire une seconde).

Cet exemple sert surtout à comprendre comment fonctionne les IRQs sur PC Engine.
Quelque soit l'interruption provoqué par le VDC, c'est l'irq1 qui receptionne, du coup il est important de tester tous les bits du VDC Status Register $0000, ce qui nous permettra d'identifier l'origine de l'interruption.

Pour cela nous avons l'instruction BBS ou BBR qui testera le bit voulu et effectuera un branchement en fonction de son statut.

L'ensemble des sources (code et binaires) est disponible ici : vblank_irq.7z

; ----------------
; DISPLAY A BACKGROUND
; 02/03/2009
; Enguerrand SOULIER
; -----------------

vdc_sr = $20F6 ; vdc status register copy
bg_display = $20F7 ; vdc control register copy

.org $2200
irq_cnt: .ds 1

.bank 0
.org $FFF6

.dw _irq2
.dw _irq1
.dw _timer
.dw _nmi
.dw _reset

.org $E000
.db "Create by Peperocket"

; -------------
; INTERRUPT HANDLER
; -------------

_irq2:
nop
rti

_irq1:
pha
lda $0000
sta vdc_sr ; copy of video status register
bbs5 vdc_sr,l5 ; goto l5 if vblank
pla
rti

_timer:
pha
stz $1403 ; write for avoid infinity loop !
rti

_nmi:
nop
rti

_reset:
sei
csh
cld

lda #$FF
tam #0

lda #$F8
tam #1

stz $2000
tii $2000,$2001,$1FFF

ldx #$FF
txs

lda #$01
tam #2

lda #$3C
sta $2200

jmp main

;------------------------
; vsync interrupt
; ----------------------

l5:
dec irq_cnt
beq .cnt_int ; if equal zero, goto cnt_int for disable display
pla
rti

.cnt_int:
st0 #5 ; disable display
lda #$00
sta $0002
pla
rti

; -------------
; CODE
; -------------
main:
cli
lda #$05 ; enable irq1
sta $1402

st0 #5 ; disable display
lda #$00
sta $0002

st0 #$0B ; HDR Horizontal Display Width for 256*240 display
st1 #$1F
st2 #$03

st0 #$0D ; VDR Vertical Diplay Width for 256*240 display
st1 #$EF
st2 #$00


st0 #9 ; init bat size 32*32
st1 #0
st2 #0

d01:
lda #bank(test_set)
tam #page(test_set)
inc a
tam #3
inc a
tam #4
inc a
tam #5
inc a
tam #6

st0 #0
st1 #0
st2 #$10
st0 #2

tia test_set,$0002,$7000


d02:
lda #bank(test_pal)
tam #page(test_pal)

stz $402
stz $403
tia test_pal,$404,$200

d03:
lda #bank(test_map)
tam #page(test_map)

st0 #0
st1 #0
st2 #0
st0 #2
tia test_map,$0002,$700

st0 #5
lda #$C8
sta $0002

.inf_loop:
jmp .inf_loop

; -----------
; DATA
; -----------
.bank 1
.org $4000

test_pal:
.incbin "pce_pal.bin"

test_map:
.incbin "pce_map.bin"

test_set:
.incbin "pce_set.bin"

J'utiliserais le timer la prochaine fois pour vous montrer comment on fait clignoter un background ou un sprite....

0 commentaires: