Finalmente un post giusto nel posto giusto!
A buoni intenditori...
Allora Elder, premesso che i CIA sono gli integrati che conosco di meno nel biscottone, credo comunque di poterti chiarire le idee almeno su come si comporta il primo dei due.
Il punto focale é che il 6510 ha un solo piedino IRQ (più un NMI ma non c'entra con questo discorso).
Ciò comporta due cose:
- qualsiasi sorgente di interruzione (VIC/CIA/Porta espansione..) deve necessariamente agire su quel pin per 'triggerare' un IRQ
- il 6510 non ha nessun modo "autonomo" per capire chi possa aver generato l'IRQ: lui sa solo che deve salvare lo status flag e l'IP e poi saltare alla routine puntata da $fffe/$ffff
Nella tua routine avevi impostato $fffe/$ffff e $0314/$0315: impostare la prima é coppia é corretto, impostare la seconda é inutile.
Mi spiego meglio.
Il 6510, in risposta ad un IRQ, salta sempre (SEMPRE!) all'indirizzo puntato da $fffe/$ffff. Ora, se il kernal é attivo (leggi, se le ROM sono visibili) tale coppia viene letta appunto dalla ROM e punta all'handler del kernal(indirizzo $ff48). Questo handler in sostanza va ad eseguire a sua volta la routine puntata da $0314/$0315.
Ecco da dove arriva la seconda coppia.
E' chiaro che levando la ROM sparisce il puntamento ad $ff48 e perciò $0314/$0315 diventano due locazioni come le altre.
Il punto quindi é determinare nell'unico handler a disposizione chi sia stato a produrre l'IRQ; ci sono almeno due modi per risolvere il problema, io ho scelto quello che mi ricordo meglio.
- puoi leggere il bit 7 di $d019 (quando é attivo significa che é stato generato un IRQ dal VIC)
- puoi leggere non-mi-ricordo-dove nel CIA1 (in modo analogo c'é un bit che indica se é stato generato un IRA dal CIA1)
Altro miniappunto: negli interrupt handler non serve salvare lo status flag perché ci pensa il processore quando esegue l'IRQ (ed in modo analogo ripristina il flag con RTI).
Il codice (ho modificato qualcosina anche sulla parte di vibrazione anche se probabilmente non é come la intendevi tu).
*=$0801
.byte $0a,$08,$0a,$00,$9e,$32,$30,$36,$32
.byte $00,$00,$00,$00; a BASIC SYS LINE FOR STARTING CODE AT $080E
*=$080e
sei
; Blocco l'NMI altrimenti salta tutto (manca l'handler del NMI)!
lda #$7f
sta $dd0d
lda $dd0d
ldx #$ff
txs; Reset Stack pointer
;Via la rom, mappo piu ram
lda #$35; Select big bank without roms
sta $01; Change to big bank
;punto irq CIA
lda #<irq
sta $fffe; Set low IRQ adress in selected bank
lda #>irq
sta $ffff; Set high IRQ adress in selected bank
;Abilito tutti gli interrupts
;generati dai timer
lda #$7f
sta $dc0d; Clear IRQ interruptmask for CIA
;Timer A control register. Bits:
;Bit #0: 0 = Stop timer; 1 = Start timer.
;Bit #1: 1 = Indicate timer underflow on port B bit #6.
;Bit #2: 0 = Upon timer underflow, invert port B bit #6; 1 = upon timer underflow, generate a positive edge on port B bit #6 for 1 system cycle.
;Bit #3: 0 = Timer restarts upon underflow; 1 = Timer stops upon underflow.
;Bit #4: 1 = Load start value into timer.
;Bit #5: 0 = Timer counts system cycles; 1 = Timer counts positive edges on CNT pin.
;Bit #6: Serial shift register direction; 0 = Input, read; 1 = Output, write.
;Bit #7: TOD speed; 0 = 60 Hz; 1 = 50 Hz.
lda $dc0e
ora #%10011000
and #%11110110
sta $dc0e; count o2 pulses and forceload and continious and stop
; timer A
tay; Save for later use in y
waitrst; allineo il CIA ad una certa posizione dello schermo
lda $d012
cmp #$90
bne waitrst
;4cc7 = un frame
lda #$c7; Cia time $4cc7 is a frame on a pal system with old
; cia (6526) 63 cycles per line * 312 lines - 1
sta $dc04
lda #$4c
sta $dc05; Set timer A to one frame
lda #$81
sta $dc0d; Activate CIA timer A irq
tya
ora #%00000001; Start CIA Timer A
sta $dc0e
lda #$01
sta $d012
asl $d019
lda #$01
sta $d01a; Accendi raster interrupts
cli
jmp *; do nothing while no IRQ, just jump to this line
IRQbyVic
inc $d020
asl $d019; ACK interrupt
jmp skip
;CIA IRQ
irq
pha; 3 cycles
txa; 2 cycles
pha; 4 cycles
tya; 2 cycles
pha; 4 cycles
bit $d019; E' stato il VIC a generare l'IRQ
bmi IRQbyVic; Si => vai alla routine specifica
IRCbyCIA
; No, allora é stato il timer del CIA
lda $dc0d; 4 cycles;Acknowledge CIA timer a interrupt
;Shakero lo schermo
lda $d011
eor #%00000111
sta $d011
lda $d016
eor #%00000111
sta $d016
skip ; Da qua escono entrambi gli IRQ
pla
tay
pla
tax
pla
rti