Risolto!
In effetti è bastato inizializzare il secondo framebuffer con lo schermo già scrollato di un carattere (come è ovvio che sia)
Adesso mi manca solo l'init della colormap!
processor 6502
; Costanti
rastline = $30+((25*8)/2)-8; La rasterline iniziale é grosso modo a centro schermo
finescrline = $FA ; quella finale é nel bordo inferiore
screen0 = $3800+$8000 ; Framebuffer 0
screen1 = $3C00+$8000; ; Framebuffer 1
color = $d800 ; Memoria colore
mappointer = $4000 ; Mappa (256 "colonne" da 32 byte di cui 25 usati)
mapcolor = $4000+$2000 ; Mappa colore (256 "colonne" da 32 byte di cui 25 usati)
; Variabili zero page
; Attenzione! Questo blocco porta via 200 valori di zero page, precisamente
; da $20 a $E7; salvo variare il range non si possono usare queste locazioni
; di memoria per altri scopi
sxupc0 = $20 ; 50 valori che puntano alla colonna 0 del FB 0
sxupc1 = sxupc0+$32 ; 50 valori che puntano alla colonna 0 del FB 1
dxupc0 = sxupc1+$32 ; 50 valori che puntano alla colonna 39 del FB 0
dxupc1 = dxupc0+$32 ; 50 valori che puntano alla colonna 39 del FB 1
posx = $F9 ; Posizione nella mappa
pmap = $FA ; puntatore usato in più contesti
page = $FC ; pagina da assegnare a $D018
finescroll = $FD ; scrolling fine da assegnare a $D016
cscr = $FE ; Framebuffer (avrà valore 0/1)
; Codice
org $0801
; *********
; Sys Basic
; *********
word eop
word 7102
byte $9e,"2061",0
eop word 0
org $080D; Inizio del programma
; ********************
; Impostazioni di base
; ********************
main
sei
; Ciclo di inizializzazione della colormap e dei due framebuffer
ldy #$0
ldx #$0
lpCmpC
lda mappointer,x;carico valore
lpSMC
sta screen0 ;Aggiorna schermo
;lda #$01 ;carico valore
;lpSMCcolor
;sta color+990 ;aggiorna color map
clc ;Questo mi cambia dinamicamente il valore di screen0 e screen1 modificando il codice al volo
lda lpSMC+1 ;SCREEN0 h
adc #$28
sta lpSMC+1
bcc lpSMC1 ;Se non è modificato il carry continua il ciclo
inc lpSMC+2 ;SCREEN0 l
lpSMC1
inx
cpx #$19 ;Sei arrivato al carattere 25
bne lpCmpC ;no allora ricomincia
;si allora mi sposto alla colonna successiva
ldx #$0 ;azzero X
iny ;incrementa Y
sty lpSMC+1 ;Ricarico il valore screen0 incrementandolo di 1
lda #$B8 ;B8 è la prima parte di $3800 + $8000
sta lpSMC+2
clc ;Sposto anche mappointer in avanti di 32
lda lpCmpC+1
adc #$20
sta lpCmpC+1
bcc lpSMC2 ;Se non è modificato il carry continua il ciclo
inc lpCmpC+2
lpSMC2
cpy #$28
bne lpCmpC
; Ciclo di inizializzazione dei pointer precalcolati per l'aggiornamento della prima ed ultima colonna
ldx #$31
copyupcpointers
lda sxupdatecol0,x
sta sxupc0,x
lda sxupdatecol1,x
sta sxupc1,x
lda dxupdatecol0,x
sta dxupc0,x
lda dxupdatecol1,x
sta dxupc1,x
dex
bpl copyupcpointers
lda #$36;Libero A000-BFFF dalla BASIC ROM RAM (Freshness79)
sta $01
lda #$15;Seleziono banco 2 ($8000-$BFFF 00010101)
sta $dd00
lda #$D7;Posizione di scrolling iniziale e scrolling HW nel punto piu' a destra
sta $D016
sta finescroll
lda #$E0;Attivo schermo 0 (11100000 E0)
sta $d018
sta page
lda #$00;Indicatore dello schermo corrente
sta cscr
;Copia lo schermo già scrollato a SX su SCREEN 0
ldx #$00
lpInitScreen1
lda screen0,x
sta screen1+1,x
lda screen0+256,x
sta screen1+1+256,x
lda screen0+512,x
sta screen1+1+512,x
lda screen0+768,x
sta screen1+1+768,x
inx
bne lpInitScreen1
lda #$00 ;Continuia inizializzazione
sta $d020
sta $d021
lda #$0c
sta $d022
lda #$0b
sta $d023
jsr initIRQ
cli
jmp * ;Loop infinito
initIRQ
lda #<routineIRQ; Indirizzo codice (parte alta)
sta $0314
lda #>routineIRQ; Indirizzo codice (parte bassa)
sta $0315
lda #rastline; Raster line di attivazione IRQ raster
sta $d012
lda #$1b ; Azzera il bit 7 che sarebbe il Raster Compare: (Bit 8) di $d012
sta $D011
lda #$7f ; 01111111 BIT 7 a 0
sta $dc0d ; Azzera il bit 7 di CIA Interrupt Control Register (Read IRQs/Write Mask) per disattivarlo
sta $dd0d ; Azzera il bit 7 di CIA Interrupt Control Register (Read NMls/Write Mask) per disattivarlo
lda $dc0d ; Acknowledge di un eventuale IRQ generato dal CIA1 - assicuro che l'unica fonte di interruzione
lda $dd0d ; Acknowledge di un eventuale NMI generato dal CIA2 - sia il VIC
lda #$01 ; Abilita IRQ raster
sta $d019 ; VIC Interrupt Flag Register (Bit = 1: IRQ Occurred)
sta $d01a ; IRQ Mask Register: 1 = Interrupt Enabled
rts
routineIRQ
inc $d019 ; Dico al vic che la routine è stata eseguita
inc $d020 ; Colora una raster line per capire quanto raster consumo per scrollare
lda #<secondirq; Imposto il prossimo raster IRQ
sta $0314
lda #>secondirq
sta $0315
lda #finescrline
sta $d012
ldx $d016 ; leggo il finetune corrente
txa ; lo salvo in X
and #$07 ; quindi lo maschero per recuperare i 3 bit utili
tay ; e lo salvo in Y, questa e' la posizione corrente.
lda $DC00 ; Leggo il valore del joystick
eor #%00001100; si lavora meglio in logica positiva.
and #%00001100; Seleziono le sole direzioni sx e dx
cmp #%00000100; spostamento a sinistra?
beq jsx ; si, sposta a sinistra
cmp #%00001000; spostamento a destra?
beq dx ; si, sposta a destra
jmp lpExit ; nessun spostamento
jsx
jmp sx
dx
dex ; Aggiorno X per ottenere il nuovo valore
txa ; di scrolling fine
and #$07 ; dopo averlo opportunamente mascherato
ora #$D0 ; e "or-ato" lo salvo
sta finescroll; nella variabile che verra' poi usata nel secondo interrupt
ldx cscr ; Carico il frame (0 o 1)
tya ; uso il valore in Y precedentemente salvato per
lsr ; calcolare l'high-byte di sorgente e destinazione
ora ixbuf01,x; con una OR ottengo la sorgente
sta dxfrom+2 ;
and #$03 ; rimaschero il valore per annullare la precedente OR
ora ixbuf10,x; con questa OR ottengo la destinazione
sta dxto+2 ;
lda #$00 ; uso il carry generato dalla precedente LSR per avere il valore $00 o $80
ror ; in questo modo ho la totale distribuzione del carico
sta dxto+1 ; negli 8 spostamenti: $000,$080,$100,$180,$200,$280,$300 e $380
adc #$01 ; la sorgente (FROM) e' un carattere piu' a destra rispetto alla destinazione per avere l'effettivo
sta dxfrom+1; spostamento.
ldx #$7f ; copio i dati con un ciclo (qua si potrebbe srotolare tutto ed ottimizzare)
dxfrom
lda $ffff,x ; Indirizzo calcolato nei passaggi precedenti
dxto
sta $ffff,x ; IDEM
dex
bpl dxfrom
cpy #$00 ; Abbiamo saltato un intero carattere?
bne dxExit ; No, possiamo uscire
lda cscr ; Cambio frame
eor #$01
sta cscr
tax ; Lo metto in X per usarlo successivamente
lda page ; Cambio pagina video
eor #$10
sta page
inc posx ; incremento la posizione nella mappa
lda #$00 ; calcolo l'indirizzo base nella mappa
sta pmap ;
clc ;
lda posx ;
adc #$27 ; Aggiungo 39 alla posizione orizzontale perché stiamo aggiornando l'ultima colonna
lsr ; La rudimentale mappa che ho implementato si compone di blocchi
ror pmap ; di 32 byte che vanno da $4000 ad $8fff (256 blocchi). Ciascun
lsr ; blocco corrisponde ad una colonna verticale nello schermo perciò
ror pmap ; dei 32 byte disponibili ne uso solamente 25 (i 7 rimanenti potrebbero
lsr ; essere usati ad esempio per aggiornare la mappa colore con 1 colore
ror pmap ; ogni 4 caratteri - 7x4=28)
ora #(mappointer/$100)
sta pmap+1
lda dxupdbuf,x; Carico l'indirizzo della tabella di valori precalcolati usata
tax ; per salvare i dati nello schermo
ldy #$00
dxcpcolumn ;
lda (pmap),y; y scorre lungo i 25 byte del blocco selezionato
sta ($00),x ; x scorre nella tabella di 50 valori (25 indirizzi lo/hi)
inx ; corrispondente alle posizioni dello schermo
inx ; X=X+2 perché ogni indirizzo porta via due byte
iny ; Y=Y+1
cpy #$19 ; abbiamo copiate tutte le 25 righe?
bne dxcpcolumn
jsr scrollCdx; Aggiornamento della mappa colore (verso destra)
lda cscr
bne dxfix1
jsr fixcoldx0
jmp lpExit
dxfix1
jsr fixcoldx1
dxExit
jmp lpExit
; Gestione movimento a sinistra
; Sono indicate solamente le modifiche
; rispetto alla routine di destra
; il resto e' identico
sx
inx ; *Incremento
txa
and #$07
ora #$D0
sta finescroll
ldx cscr
tya
lsr
ora ixbuf01,x
sta sxfrom+2
and #$03
ora ixbuf10,x
sta sxto+2
lda #$00
ror
sta sxfrom+1; sorgente e
adc #$01
sta sxto+1 ; destinatario invertiti
ldx #$7f
sxfrom
lda $ffff,x
sxto
sta $ffff,x
dex
bpl sxfrom
cpy #$07 ; Valore limite diverso (7)
bne lpExit
lda cscr
eor #$01
sta cscr
tax
lda page
eor #$10
sta page
dec posx ; Decremento della posizione
lda #$00
sta pmap
lda posx ; non serve addizionare $27
lsr
ror pmap
lsr
ror pmap
lsr
ror pmap
ora #(mappointer/$100)
sta pmap+1
lda sxupdbuf,x; uso il buffer per la direzione sinistra
tax
ldy #$00
sxcpcolumn
lda (pmap),y
sta ($00),x
inx
inx
iny
cpy #$19
bne sxcpcolumn
jsr scrollCsx; spostamento verso sinistra della mappa colore
lda cscr
bne fixsx1
jsr fixcolsx0
jmp lpExit
fixsx1
jsr fixcolsx1
lpExit
dec $d020 ; Fine barra consumo CPU
iret
pla ;Pull Accumulator from Stack
tay ;transfer A to Y
pla ;Pull Accumulator from Stack
tax ;transfer A to X
pla ;Pull Accumulator from Stack
rti ; return from interrupt
secondirq
lsr $d019 ; IRQ Acknowledge
lda #<routineIRQ; Setto la routine principale
sta $0314 ; come prossimo handler del raster interrupt
lda #>routineIRQ
sta $0315
lda #rastline ; Fisso la linea alla quale avverrà l'interruzione
sta $d012
lda finescroll ; Imposto il finescroll fuori dalla zona video
sta $d016
lda page ; switch della pagina video (pure questo fuori dalla zona video)
sta $d018
bne iret ; sempre diverso da 0 qua, equivalente a jmp iret
; *****************************************
; Routine srotolate per l'update del colore
; *****************************************
scrollCdx
C01 SET 0
ldx color
REPEAT 1023
lda color+C01+1
sta color+C01
C01 SET C01 + 1
REPEND
stx color+$3ff
rts
scrollCsx
ldx color+$200
ldy color+$3ff
C01 SET 511
REPEAT 512
lda color+C01
sta color+C01+1
C01 SET C01 -1
REPEND
C01 SET 510
REPEAT 511
lda color+$200+C01
sta color+$200+C01+1
C01 SET C01 -1
REPEND
sty color
stx color+$201
rts
fixcolsx0
ROW SET 0
REPEAT 25
ldx screen0+ROW
lda $6000,x
sta color+ROW
ROW SET ROW +40
REPEND
rts
fixcolsx1
ROW SET 0
REPEAT 25
ldx screen1+ROW
lda $6000,x
sta color+ROW
ROW SET ROW +40
REPEND
rts
fixcoldx0
ROW SET 0
REPEAT 25
ldx screen0+39+ROW
lda $6000,x
sta color+39+ROW
ROW SET ROW +40
REPEND
rts
fixcoldx1
ROW SET 0
REPEAT 25
ldx screen1+39+ROW
lda $6000,x
sta color+39+ROW
ROW SET ROW +40
REPEND
rts
; *******************************************
; Puntatori e tabelle con valori precalcolati
; *******************************************
align 16
ixbuf01
.BYTE screen0/$100,screen1/$100
ixbuf10
.BYTE screen1/$100,screen0/$100
sxupdbuf
.BYTE sxupc0,sxupc1
dxupdbuf
.BYTE dxupc0,dxupc1
dxupdatecol0
.BYTE $27,$00+screen0/$100,$4F,$00+screen0/$100,$77,$00+screen0/$100
.BYTE $9F,$00+screen0/$100,$C7,$00+screen0/$100,$EF,$00+screen0/$100
.BYTE $17,$01+screen0/$100,$3F,$01+screen0/$100,$67,$01+screen0/$100
.BYTE $8F,$01+screen0/$100,$B7,$01+screen0/$100,$DF,$01+screen0/$100
.BYTE $07,$02+screen0/$100,$2F,$02+screen0/$100,$57,$02+screen0/$100
.BYTE $7F,$02+screen0/$100,$A7,$02+screen0/$100,$CF,$02+screen0/$100
.BYTE $F7,$02+screen0/$100,$1F,$03+screen0/$100,$47,$03+screen0/$100
.BYTE $6F,$03+screen0/$100,$97,$03+screen0/$100,$BF,$03+screen0/$100
.BYTE $E7,$03+screen0/$100
dxupdatecol1
.BYTE $27,$00+screen1/$100,$4F,$00+screen1/$100,$77,$00+screen1/$100
.BYTE $9F,$00+screen1/$100,$C7,$00+screen1/$100,$EF,$00+screen1/$100
.BYTE $17,$01+screen1/$100,$3F,$01+screen1/$100,$67,$01+screen1/$100
.BYTE $8F,$01+screen1/$100,$B7,$01+screen1/$100,$DF,$01+screen1/$100
.BYTE $07,$02+screen1/$100,$2F,$02+screen1/$100,$57,$02+screen1/$100
.BYTE $7F,$02+screen1/$100,$A7,$02+screen1/$100,$CF,$02+screen1/$100
.BYTE $F7,$02+screen1/$100,$1F,$03+screen1/$100,$47,$03+screen1/$100
.BYTE $6F,$03+screen1/$100,$97,$03+screen1/$100,$BF,$03+screen1/$100
.BYTE $E7,$03+screen1/$100
sxupdatecol0
.BYTE $00,$00+screen0/$100,$28,$00+screen0/$100,$50,$00+screen0/$100
.BYTE $78,$00+screen0/$100,$A0,$00+screen0/$100,$C8,$00+screen0/$100
.BYTE $F0,$00+screen0/$100,$18,$01+screen0/$100,$40,$01+screen0/$100
.BYTE $68,$01+screen0/$100,$90,$01+screen0/$100,$B8,$01+screen0/$100
.BYTE $E0,$01+screen0/$100,$08,$02+screen0/$100,$30,$02+screen0/$100
.BYTE $58,$02+screen0/$100,$80,$02+screen0/$100,$A8,$02+screen0/$100
.BYTE $D0,$02+screen0/$100,$F8,$02+screen0/$100,$20,$03+screen0/$100
.BYTE $48,$03+screen0/$100,$70,$03+screen0/$100,$98,$03+screen0/$100
.BYTE $C0,$03+screen0/$100
sxupdatecol1
.BYTE $00,$00+screen1/$100,$28,$00+screen1/$100,$50,$00+screen1/$100
.BYTE $78,$00+screen1/$100,$A0,$00+screen1/$100,$C8,$00+screen1/$100
.BYTE $F0,$00+screen1/$100,$18,$01+screen1/$100,$40,$01+screen1/$100
.BYTE $68,$01+screen1/$100,$90,$01+screen1/$100,$B8,$01+screen1/$100
.BYTE $E0,$01+screen1/$100,$08,$02+screen1/$100,$30,$02+screen1/$100
.BYTE $58,$02+screen1/$100,$80,$02+screen1/$100,$A8,$02+screen1/$100
.BYTE $D0,$02+screen1/$100,$F8,$02+screen1/$100,$20,$03+screen1/$100
.BYTE $48,$03+screen1/$100,$70,$03+screen1/$100,$98,$03+screen1/$100
.BYTE $C0,$03+screen1/$100
*=$4000
incbin "map.bin"
incbin "colors.bin"
*=$8000
incbin "chars.bin"