Ready64 Forum

Commodore 64 => Programmazione, Grafica e Musica => Topic aperto da: Elder0010 - 14 Marzo 2011, 20:21:07

Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 14 Marzo 2011, 20:21:07
In riferimento al codice di Ian Coog:
http://ready64.org/smf/index.php?topic=1837 - aggiunto link

Codice: [Seleziona]

; 07: ora e' stabile!
; abbiamo trovato i valori per temporizzare il raster e ora c'e' una riga
; stabile, sia con lo schermo acceso che spento

    *=$0801
    include basicline.s
    sei
    lda #<irq
    ldx #>irq
    sta $0314
    stx $0315
    lda #$01
    sta $d019
    sta $d01a
    lda #$80
    sta $d012
    lda #$1b
    sta $d011
    lda #$7f
    sta $dc0d
    lda $dc0d
    cli
    rts
irq
    lda #$01
    sta $d019
    bit $24
    bit $24
    bit $24
    bit $24
    inc $d020
    ldx #$0b
    dex
    bne *-1

    dec $d020
    jmp $ea31

Se ho capito bene, facendo riferimento a un sistema PAL:
In ogni rasterline standard la routine deve durare 63 cicli per avere un raster stabile (no flicker)
In ogni badline 23 cicli.

Per routine intendo tutto l'irq, per cui da lda#$01 a jmp $ea31 compresi.

Eppure ho provato a fare i conti utilizzando
<a href='http://www.c64-wiki.com/index.php/Category:Machine_language_instruction' target='_blank'>questa tabella</a> e il conto viene:

   lda #$01 (2 cicli)
   sta $d019 (4 cicli)
   bit $24 (3 cicli, istruzione ripetuta 4 volte quindi 12 cicli totali)
   inc $d020 (6 cicli)
   ldx #$0b (2 cicli)
   e fino a qui siamo a 2+4+12+6+2 = 26 cicli.

Dopodichè inizia un iterazione: 11 volte due istruzioni da 2 cicli, per cui 4*11 = 44 cicli.

    dec $d020 6 cicli
    jmp $ea31 3 cicli

Per un totale di: 26+44+6+3 = 79 cicli  :huh:

Il raster risulta invece stabile, per cui sbaglio io qualcosa nei conti, ma non riesco a capire cosa!
Grazie per la pazienza ragazzi :)
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 14 Marzo 2011, 23:54:58
 Dunque... innanzitutto il codice sopra non genera un raster veramente stabile (iAN non averne a male, niente di personale ;) ).
Per vederlo é sufficiente usare vice e, nel menu VIC-II, impostare i bordi a debug: noterai che sulla destra il punto di partenza della linea (il punto in cui la cpu esegue inc $d020) non é perfettamente stabile ma oscilla.
Questa instabilità é legata al modo col quale vengono servite le interruzioni: se un'interruzione viene 'triggerata' durante l'esecuzione di un'istruzione, il 6510 non la servirà fintanto che non avrà terminato l'istruzione stessa. Tale oscillazione, quindi, dipende dalla durata dell'istruzione che stava eseguendo la CPU nel momento in cui é stato ricevuto l'IRQ. Per istruzioni particolarmente lunghe (inc assoluto/lsr assoluto ecc) si può arrivare anche a 6 cicli di ritardo.
Esistono almeno due metodi molto usati per ovviare al problema:
- doppio raster interrupt
- timer sincronizzato
E' probabile ne esistano degli altri ma si tratta sostanzialmente di variazioni sul tema.
Personalmente conosco bene il primo e meno bene il secondo ma, se vuoi sapere qualcosa su come funzionano, chiedi pure.
Un modo più rapido (ma non altrettanto efficace) di creare un raster stabile si basa invece sul fatto che in una badline il VIC, prima di sottrarre il bus alla cpu, permette ad essa 3 cicli di write: se quindi si posiziona oculatamente una istruzione RMW (read modify write) come ad esempio una INC, immediatamente prima che il VIC prenda possesso del bus, si può fare in modo di assorbire ritardi di 1,2 o 3 cicli.
Chiaro che se la differenza supera i 3 il "giochino" non funziona più.
Ok, questa era la premessa... veniamo ai tuoi conti.
E' tutto giusto, ma manca una parte!
Quando viene generata un'interruzione, oltre a salvare lo status register e l'IP, il 6510 prende i valori delle locazioni di memoria $FFFE ed $FFFF e le mette nell'instruction pointer. Nel 64 quelle due locazioni puntano ad $FF48, se disassembly l'area troverai la seguente routine:
Codice: [Seleziona]
last instr. ;x
IRQ ;7
PHA ;3
TXA ;2
PHA ;3
TYA ;2
PHA ;3
TSX ;2
LDA $0104,X;4
AND #$10;2
BEQ $FF58;3
JMP ($0316);skip
JMP ($0314);5 - 36+x
In sostanza quando viene eseguito il salto alla routine puntata da $0314/$0315 il processore ha già eseguito 36 cicli (+x dipendente dall'istruzione durante la quale si é verificata l'interruzione).
Nel tuo conto erano questi a mancare.
La routine che ti propongo qua sotto é una rivisitazione di quella che hai postato e sfrutta il metodo 'rapido' che ti ho illustrato.
Codice: [Seleziona]
*=$0801    
include basicline.s
sei
lda #<irq
ldx #>irq
sta $0314
stx $0315
lda #$01
sta $d019
sta $d01a
lda #$82;Importante: dev'essere la riga prima di una badline!!
sta $d012
lda #$1b
sta $d011
lda #$7f
sta $dc0d
lda #$c8
sta $d016
lda $dc0d
cli
rts

irq
ldx #$00 ;2 (si parte da 36+x)
inc $ffff;6
inc $ffff;6
inc $ffff,x;7
inc $d020;6 (27+36+x) => (Saltata un'intera linea) + x

bit $ff;3+x Questa é la badline
inc $ffff;9+x Qui parte della differenza viene assorbita (max 3 cicli)

dec $d020;6
lda #$01 ;2
sta $d019;4
jmp $ea31
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 16 Marzo 2011, 21:57:17
Non incollo il codice perchè è un po lungo e non vorrei "floodare" il forum :)

Ho ragionato un po' sulle cose che hai scritto, e ho fatto diversi esperimenti, ora i conti tornano.

A questo punto ho tentato la strada del doppio interrupt.

La logica che ho applicato è questa (spero sia corretta)

init del programma
set up primo interrupt

primo_interrupt
    set up secondo interrupt

secondo_interrupt
      chiamate a procedure (logica del programma)         

     set up primo interrupt


In allegato la prova che ho fatto, con 3 interrupts:

Il primo si limita a puntare il secondo
Il secondo disegna una rasterbar di 10 linee nella zona superiore (bordo)
Il terzo disegna una rasterbar di 1 linea al centro dello schermo e cicla i colori delle rasterbars

Ho provato a muovere la linea centrale, e c'è un flicker regolare: penso si tratti delle badlines. Per risolvere, dovrei creare delle timing tables dal quale pescare il valore giusto di ritardo a seconda della linea in cui mi trovo, penso!

Allego il sorgente, e il compilato :)

 
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 17 Marzo 2011, 02:58:29
 ...no! :D
Non funziona così la tecnica del doppio raster.
Quello che hai fatto tu é creare un secondo raster interrupt totalmente slegato dal primo.
Cerco di metterti nella strada giusta perché secondo me hai tranquillamente i mezzi per farcela da solo.
Il problema da risolvere é fare in modo che l'interruzione dovuta ad una raster line non accumuli un eccessivo ritardo a causa di un'istruzione (al momento del trigger) troppo lunga. Dunque... perché doppio raster?
La cpu, nella sua normale esecuzione, incontra istruzioni di qualsiasi lunghezza: il primo raster interrupt di fatto serve ad "impossessarci" della cpu, impostare un nuovo raster interrupt e assicurarci che quando questo secondo interrupt verrà chiamato la cpu starà eseguendo un'istruzione più corta possibile (2 cicli).
A quel punto, nel secondo interrupt sapremo con certezza che potremo essere in sincrono col raster o al massimo in ritardo di un ciclo: sarà sufficiente eliminare quest'ultimo ciclo di incertezza per avere la cpu totalmente sincronizzata con il raster.
Hint1
Il primo raster interrupt non necessita un'uscita ($EA31) perché... non deve arrivarci!
Hint2
I due interrupt sono nested: il secondo avviene durante l'esecuzione del primo.
PS: pensaci, pensaci e ripensaci. Raggiungere il raster stabile e capire come lo si é ottenuto apre la strada a diversi effetti ottenibili con il VIC.
Buon divertimento!
 
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 17 Marzo 2011, 09:16:58
 ahha bocciato alla grande  :lol:  

sfida accettata! Ora ci penso su e vedo cosa riesco a combinare!!  
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 17 Marzo 2011, 15:22:46
 Cosi' credo di essere su una buona strada, anche se ancora non va! Ho visto un po' di esempi in rete, e ho provato a riproporre quello che ho capito.

Sia in modalità standard che debug dei bordi la linea non inizia dal punto giusto, perchè il salto jsr rasterbars viene fatto troppo presto. Inoltre non cè un flickering continuo: la linea è ferma ma a intervalli regolari si sposta di qualche px :(.



Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

  tax
  stx $d020
  stx $d021
  lda #$0b ; spegnamo il bit che controlla l'accensione dello schermo
      sta $d011
  
      sei
      lda #<irqpre
      ldx #>irqpre
      sta $0314
      stx $0315
    
      sta $d01a
      lda #$34    
  sta $d012
  lda #$1b    
  sta $d011
      lda #$7f
      sta $dc0d
      lda $dc0d
  
  
      cli

hold
  jmp hold



irqpre
  
  lda #<irq
      ldx #>irq
      sta $0314
      stx $0315
  
  inc $d019
  inc $d012
            
 
;Aggiungo una serie di nop per "non fare nulla" intanto che
               ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
  
  
irq
  nop
  jsr rasterbars
  
  lda #<irqpre
             ldx #>irqpre
      sta $0314
      stx $0315
  
  inc $d019
  lda #$34    
  sta $d012
  jmp $ea31
  

rasterbars
  
   nop
   lda colors
   sta $d020
   sta $d021
  
   ldx #$0a
   dex
   bne *-1
  
   lda #0
   sta $d020
   sta $d021
      
   rts
  

dir   .byte $0
offs   .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06

 
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 18 Marzo 2011, 15:15:35
 ... in effetti il 2° interrupt non viene mai chiamato.
Nella routine preirq hai configurato correttamente il secondo IRQ ma ti sei dimenticato di riattivare le interruzioni: quando il 6510 serve un'interruzione imposta lo status flag in modo da mascherare successivi IRQ.
In sostanza prima delle NOP devi inserire una CLI.
A quel punto il 2° interrupt verrà generato tra le NOP ma avrai comunque un'incertezza di 1 ciclo da correggere, hai già visto come fare? Tutto si gioca su un confronto ben mirato su D012.
Infine, importantissimo, dal momento che hai servito due interruzioni una dentro all'altra, lo stack avrà le informazioni di ritorno relative al primo e al secondo IRQ. Quelle al primo ci servono, quelle al secondo no pertanto possono scartate.
Tieni presente che un'interruzione gestita con l'appoggio del kernel ($0314) inserisce 6 byte nello stack: vanno tolti.
Se hai altri dubbi chiedi pure, forza con i fix!
 
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 18 Marzo 2011, 23:53:48
 Ho studiato un po' del tuo codice sul forum + la routine di fungus su
codebase (http://codebase64.org/doku.php?id=base:double_irq).

Credo che adesso il 2° interrupt sia ok (il break che ho inserito non viene mai eseguito!).

Inoltre ho salvato e ripristinato lo stato stack pointer usando la locazione $5f, copiando da te. hai scelto proprio quella locazione per un motivo?

Il raster è ancora ballerino, e ho notato che premendo tasti della tastiera va tutto a farsi friggere ancora di piu'! Forse devo disabilitare qualcosa nel set up iniziale dell'ambiente?

Grazie per tutte queste informazioni!! spero di essere riuscito a cogliere le dritte che mi hai dato :)

Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   tax
   stx $d020
   stx $d021

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
          sta $d01a  ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
   cli

hold
   jmp hold



irqpre  
   lsr $d019
   inc $d012;Vogliamo che il prossimo interrupt sia synchato a $35
  
   lda #<irq
   ldx #>irq
   sta $0314
   stx $0315

   tsx;Trasferisco lo stack pointer in x
   stx $5f;storo x in $5f

   cli
  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
          ;l'altro interrupt viene eseguito
   nop
   nop
   brk;questo brk non viene mai eseguito quindi andiamo un po' meglio!
    
irq
   asl $d019
  
   ldx $5f;carico quello che avevo salvato prima..
   txs;ripristino lo stack pointer

   lda #$35  ;Siamo a 35?
   cmp $d012
   beq start  ;se NO devo saltare un altro ciclo!
start

   nop
 
  
  
   jsr rasterbars
    
   lda #<irqpre;Punto di nuovo al primo interrupt
   ldx #>irqpre
  
   sta $0314
   stx $0315
    
      ;rimetto apposto anche il registro $d012
   lda $34
   sta $d012
  
   jmp $ea31
  

rasterbars    
   lda colors
   sta $d020
   sta $d021
  
   ldx #$03
   dex
   bne *-1
  
   lda #0
   sta $d020
   sta $d021
      
   rts
  


dir       .byte $0
offs      .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 19 Marzo 2011, 16:19:37
 L'impostazione generale é corretta, i problemi sono dovuti ai timing.
Punto 1
Nel 6502 (ed analogamente nel 6510 del nostro c64), quando si genera un'interruzione avvengono le seguenti cose:
- si attende che finisca l'eventuale istruzione in corso (X cicli)
- si esegue l'IRQ (salvataggio IP e status register, salto alla routine puntata da $FFFE/$FFFF) (7 cicli)

Citazione
Ora, se stai lavorando col c64 in modalità normale (con le ROM attive), agli indirizzi $FFFE ed $FFFF ci sono rispettivamente i valori $48 e $FF. Il processore, quindi, non farà altro che saltare alla routine all'indirizzo $FF48: questa routine é quella che ho già postato nella mia prima risposta a questo thread. Se lavorassi con le ROM inattive (non é il caso del tuo programma) potresti iniziare a servire l'interruzione dopo un ritardo di soli 7+X cicli.
- si esegue la routine in $FF48 che, come ultima istruzione, effettua un salto all'indirizzo puntato in $0314/$0315 (29 cicli)

Tirando le somme, quindi, in realtà l'istruzione "lsr $d019", la prima del tuo irqpre, viene eseguita dopo X+7+29 cicli da quando é stata generata l'interruzione (cioé da quando siamo nella riga $34!).
Questo 'X' dipende da quanto lunga era l'istruzione durante la quale é stato generato l'IRQ: può valere da 0 (interruzione avvenuta esattamente tra un'istruzione e l'altra) a 7 (interruzione avvenuta durante il primo ciclo di un'istruzione da 8 cicli).
Da ciò ne consegue che l'inizio di irqpre si attesta tra i 36 ed 43 cicli di ritardo rispetto all'inizio del raster.
Cosa comporta ciò? Che nel peggior caso hai solo 20 (63-43) cicli a disposizione per gestire la prima interruzione prima che sia triggerato l'interrupt per la seconda (quella relativa alla riga $35).
Tornando al tuo programma con un rapido conto puoi osservare che le istruzioni che, in irqpre, vanno dalla LSR $D019 alla CLI (compresa) superano abbondantemente i 20 cicli (sono già 20 con lo sta $0314).
Hai pochi cicli... come fare? C'é posto solo per l'essenziale: l'aknowledge dell'interrupt, l'impostazione della riga del secondo interrupt, l'aggiornamento dell'indirizzo della routine dell'handler.
Quest'ultima attività in particolare la puoi ridure al solo aggiornamento del LSB perché, se allinei bene il programma, é ragionevole pensare che il primo interrupt sia negli stessi 256 byte del secondo.
Quindi: 6 cicli per $D019, 6 per $D012,2+4 per $0314,2 per il CLI:20 cicli!
Fai quindi seguire almeno 4 NOP: noi abbiamo analizzato il caso peggiore, ma nel caso migliore avremmo 36+20=56 cicli e quindi dopo la CLI ci potrebbero essere ancora 7 cicli prima della seconda interruzione. Con 4 NOP siamo al sicuro.
Tutto questo cosa ci garantisce? Che la seconda interruzione cadrà:
- o tra una NOP e l'altra (Ritardo 0 cicli)
- o in mezzo ad una NOP (Ritardo 1 ciclo)
Il secondo interrupt ha lo scopo di sistemare questa incertezza: anche in questo caso i timing del tuo programma non sono corretti ma attendo la sistemazione di irqpre prima di chiarire il meccanismo (con quello che sarà il punto 2).
Perdona la logorrea, spero di averti chiarito un po' le idee! ;)
Attendo (attendiamo) nuove!

 
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 19 Marzo 2011, 21:43:40
 Logorrea?? Non so davvero come ringraziarti!! La tua spiegazione è chiara e tutte queste info valgono oro :)
 
Credo di aver sistemato irqpre, però ho notato che il tutto va in crash quando arriva il momento di ritornare dal secondo interrupt. Ho provato a spostare un po' le istruzioni, credo che il problema sia dato dal fatto che ripristino $0314 troppo presto :(

Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   tax
   stx $d020
   stx $d021

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
          sta $d01a   ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
   cli

hold
   jmp hold


;FINO A QUI 20 + X + 7 + 29 cicli.
;ricorda che 0<=X<=7 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 20+X+7
irqpre  
   lsr $d019; 6
   inc $d012  ; 6
  
   lda #<irq  ;2
   sta $0314  ;4
        
   cli  ;2

;---FINO A QUI MAX 20 CICLI (cosiderato caso peggiore)

   tsx;Trasferisco lo stack pointer in x
   stx $5f;storo x in $5f
  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
                       ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop;4 nop per totale di 8 cicli, sono sicuro in tutti i casi
   ;(considerando anche il caso migliore)

   brk
    
irq
   asl $d019
  
   ldx $5f;carico quello che avevo salvato prima..
   txs;ripristino lo stack pointer
  
   lda #$35   ;Siamo a 35?
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
  
   cmp $d012
   beq start  ;se NO devo saltare un altro ciclo!
start
   sty $0314
   nop
   jsr rasterbars
  
  
  ;rimetto apposto anche il registro $d012
   lda $34
   sta $d012
  
   jmp $ea31
  

rasterbars    
   lda colors
   sta $d020
   sta $d021
  
   ldx #$0b
   dex
   bne *-1
  
   lda #0
   sta $d020
   sta $d021
      
   rts
  


dir       .byte $0
offs      .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 19 Marzo 2011, 22:11:33
 Bene le prime 5 istruzioni di irqpre, bene i commenti, male le istruzioni che seguono le prime 5!!!!
Subito dopo la CLI ci sono 7 cicli (0<=x<=7) in uno qualsiasi dei quali può verificarsi il 2° IRQ: non devi mettere istruzioni che non siano delle NOP in quella zona!
Questo essenzialmente per due motivi:
- non avresti la certezza di eseguirle: se l'IRQ avviene prima di TSX, cosa perfettamente plausibile, quell'operazione non verrà mai eseguita.
- se le istruzioni hanno tempi di esecuzione diversi dai famosi due cicli (é il caso di STX che in 0 page vuole 3 cicli), finisce lo scopo del primo interrupt: ti ricordo che con il primo interrupt stiamo riducendo l'incertezza da 0-7 cicli a 0-1.
Quindi via assolutamente TSX e STX: devi trovare un altro modo di ripristinare lo stack alla fine del secondo interrupt.
Il modo più comodo é semplicemente eseguire 6 PLA di seguito.
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 19 Marzo 2011, 22:50:34
 
Citazione da: "Freshness79"
... in effetti il 2° interrupt non viene mai chiamato.
Nella routine preirq hai configurato correttamente il secondo IRQ ma ti sei dimenticato di riattivare le interruzioni: quando il 6510 serve un'interruzione imposta lo status flag in modo da mascherare successivi IRQ.
In sostanza prima delle NOP devi inserire una CLI.
A quel punto il 2° interrupt verrà generato tra le NOP ma avrai comunque un'incertezza di 1 ciclo da correggere, hai già visto come fare? Tutto si gioca su un confronto ben mirato su D012.
Infine, importantissimo, dal momento che hai servito due interruzioni una dentro all'altra, lo stack avrà le informazioni di ritorno relative al primo e al secondo IRQ. Quelle al primo ci servono, quelle al secondo no pertanto possono scartate.
Tieni presente che un'interruzione gestita con l'appoggio del kernel ($0314) inserisce 6 byte nello stack: vanno tolti.
Se hai altri dubbi chiedi pure, forza con i fix!
Chiaro il problema del post cli.

Citazione
Tieni presente che un'interruzione gestita con l'appoggio del kernel ($0314) inserisce 6 byte nello stack: vanno tolti.

Quindi la prima volta vengono pushati 6 bytes. La seconda volta altri 6.

Citazione
Infine, importantissimo, dal momento che hai servito due interruzioni una dentro all'altra, lo stack avrà le informazioni di ritorno relative al primo e al secondo IRQ. Quelle al primo ci servono, quelle al secondo no pertanto possono scartate.

Ok, dentro lo stack (che è LIFO) ci sono le info sui due interrupt. Facendo 6 volte PLA di fila tengo nell'accumulatore solo i valori del primo interrupt, e scarto gli altri.

Ho provato a inserire i 6 pla, ma continua a crashare. Se però fermo le interruzioni (sei) e le riabilito (cli) subito prima e subito dopo dei pla, il tutto funziona e sembra stabile!

Incollo la versione SENZA sei e cli prima e dopo i pla:


Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   tax
   stx $d020
   stx $d021

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
      sta $d01a   ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
   cli

hold
   jmp hold


;FINO A QUI 20 + X + 7 + 29 cicli.
;ricorda che 0<=X<=7 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 20+X+7
irqpre  
   lsr $d019; 6
   inc $d012  ; 6
  
   lda #<irq  ;2
   sta $0314  ;4
        
   cli  ;2

;---FINO A QUI MAX 20 CICLI (cosiderato caso peggiore)

  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
           ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop;4 nop per totale di 8 cicli, sono sicuro in tutti i casi
   ;(considerando anche il caso migliore)

   brk
    
irq
   asl $d019
  
  
      
   lda #$35   ;Siamo a 35?
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
  
   cmp $d012
   beq start  ;se NO devo saltare un altro ciclo!
start
  
   nop
   jsr rasterbars
  
  ;Tolgo i 6 bytes inseriti nello stack
  ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   sty $0314
  
  ;rimetto apposto anche il registro $d012
   lda $34
   sta $d012
  
   jmp $ea31
  

rasterbars    
   lda colors
   sta $d020
   sta $d021
  
   ldx #$0b
   dex
   bne *-1
  
   lda #0
   sta $d020
   sta $d021
      
   rts
  


dir       .byte $0
offs      .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 20 Marzo 2011, 00:46:22
 Il codice della prima interruzione é corretto.
Il programma può crashare ma in realtà va nella maggior parte dei casi. Questo comportamento "instabile" é dovuto al fatto che non hai messo degli acknoledge "di sicurezza" nella routine di inizializzazione.
Me ne sono accorto solo ora quindi chiedo venia!
Perché mettere degli acknowledge? Per lavorare a bocce ferme. Se viene generato un IRQ mentre stai inizializzando (le prime righe di codice "coperte" dalla mascheratura SEI) alla riattivazione degli interrupt (CLI) verrà eseguito irqpre ma l'interrupt in questione avrà accumulato un maggior ritardo a causa delle istruzioni nelle quali era rimasto mascherato.
Questo ha il probabile effetto di andare ad impostare il secondo IRQ quando il raster é già arrivato a quella linea: a quel punto il secondo IRQ non viene eseguito e la routine chiude con il BRK.
Ottimo debugger il break! ;)
La soluzione quindi é aggiungere queste tre righe prima della CLI di fine inizializzazione:

LDA $DC0D ; Acknowledge CIA IRQ
LDA $DD0D ; Acknowledge CIA NMI
LSR $D019 ; Acknowledge VIC IRQ

Ora puoi ragionare sulla seconda interruzione!
 
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 20 Marzo 2011, 11:22:50
 Ok, ora con le intestazioni corrette va tutto bene anche senza "incartare" con sei e cli i PLA.

Ho fatto un po' di spostamenti e conti nel secondo interrupt, ho pensato questo: se è tutto ok con il 1°interrupt, l'incertezza è 0/1 cicli. E questo si sistema aggiungendo il controllo su $d012. A questo punto, il conto riparte da capo, e ho di nuovo 63 cicli per disegnare la linea. Rifacendo i conti però, mi sono accorto che la mia funzione occupa molti piu cicli!

Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   tax
   stx $d020
   stx $d021

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
      sta $d01a   ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
  
   LDA $DC0D; Acknowledge CIA IRQ
   LDA $DD0D; Acknowledge CIA NMI
   LSR $D019; Acknowledge VIC IRQ
   cli

hold
   jmp hold


;FINO A QUI 20 + X + 7 + 29 cicli.
;ricorda che 0<=X<=7 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 20+X+7
irqpre  
   lsr $d019; 6
   inc $d012  ; 6
  
   lda #<irq  ;2
   sta $0314  ;4
        
   cli  ;2

;---FINO A QUI MAX 20 CICLI (cosiderato caso peggiore)

  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
           ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop;4 nop per totale di 8 cicli, sono sicuro in tutti i casi
   ;(considerando anche il caso migliore)

   brk

;Anche qui 20 + X + 7 + 29 cicli.
;Però grazie all'interrupt precedente 0<=X<=1
;In teoria dovrei far entrare la 1° linea bianca
;in 63 cicli  
irq
  ;nel caso peggiore qui siamo a 57 cicli
  ;20+1+7+29 = 57
  
  ;**************************************
  ;* Rientro: precisamente nei 63 cicli *
  ;* infatti 57+2+4 = 63
  ;**************************************
   lda #$35   ;2
   cmp $d012  ;4
   beq start  ;con questo branch allineo l'ultimo
start                  ;ciclo di insicurezza

   jsr rasterbars;6 cicli
        
   asl $d019;spostato  qui dall'inizio interrupt
    ; perchè altrimenti non rientro nei 63 cicli
  
  ;Tolgo i 6 bytes inseriti nello stack
  ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
   sty $0314
  
  ;rimetto apposto anche il registro $d012
   lda $34
   sta $d012
  
   jmp $ea31
  

rasterbars    
  
   lda colors;2
   sta $d020;4
   sta $d021;4
  
   ldx #$0b;3 + 11*4 = 47
   dex;2
   bne *-1;2
  ;fino a qui siamo a 6+2+4+4+47 = 63!    
  
   lda #0    ;2
   sta $d020 ;4
   sta $d021 ;4 come faccio con questi 10 cicli in piu'?
      
   rts
  


dir       .byte $0
offs      .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: Roberto - 20 Marzo 2011, 13:22:46
 
Citazione da: "Elder0010"
In riferimento al codice di Ian Coog:
http://ready64.org/smf/index.php?topic=1837.0 (http://ready64.org/smf/index.php?topic=1837.0)
(Breve) Nota di Servizio: ho aggiunto il link ad inizio discussione a favore di quanti, privi di facoltà extransesoriali quali preveggenza e divinazione, avessero incontrato problemi nel rintracciare la discussione di riferimento.
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 20 Marzo 2011, 13:35:12
 colpa mia, mi è sfuggito. grazie!
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 22 Marzo 2011, 01:00:17
 Bene... a conferma che l'argomento é di una certa complessità, sono qui a ritrattare le mie stesse dichiarazioni!
Ieri ti stavo per rispondere ma mi sono bloccato un attimo perché c'era qualcosa che non tornava: una delle affermazioni che avevo fatto non coincideva con la realtà.
Ho dovuto ravanare in rete e fare alcune prove prima di tornare a risponderti con ragionevole cognizione di causa, e ti ringrazio perché questo thread mi ha dato lo spunto per chiarire gli ultimi dubbi che avevo su questa tecnica.
Ho sbagliato a dirti che un IRQ richiamato tra un istruzione e l'altra sia immediatamente eseguito dalla cpu: non é assolutamente così.
La realtà é che perché un IRQ sia eseguito subito dopo una determinata istruzione, é necessario che sia segnalato almeno due cicli prima del termine della stessa (fonte: Stable Raster - Makela (http://www.antimon.org/dl/c64/code/stable.txt)).
Questo comporta che il tempo minimo di ritardo con il quale viene eseguito un IRQ é esattamente di 2 cicli (e non di 0 come ti avevo detto).
Faccio un esempio:
posso scomporre il seguente codice:

NOP    ;2 cicli (prima nop)
NOP    ;2 cicli (seconda nop)

nei 4 cicli di cui si compone
0 - NOP1
1 - NOP1
2 - NOP2
3 - NOP2
4... (fine del 2° NOP)

Se l'irq capita in 0, all'inizio della prima NOP, verrà servito in 2: esattamente 2 cicli più tardi.
Se l'irq capita in 1, cioé in mezzo alla prima NOP, manca solo 1 ciclo alla fine della stessa perciò l'IRQ non può essere eseguito in 2 ma sarà necessario attendere la fine della seconda NOP: l'IRQ verrà eseguito in 4 per un ritardo totale di 3 cicli di ritardo.
Il discorso si può estendere anche alle istruzioni più lunghe, alla fine si ottiene che il campo di variabilità del ritardo di esecuzione di un interrupt dovuto all'istruzione correntemente eseguita va dai 2 ai 9 cicli.
Alla luce di questo cambiano i timing delle routine di cui abbiamo parlato nel thread: in particolare quella del primo interrupt dev'essere ulteriormente accorciata perché il massimo ritardo accumulabile é 9 (max ritardo di istruzione)+7 (istruzione IRQ) + 29 (routine del kernel) = 45. La routine quindi ha al massimo 18 cicli (45+18=63) per fare l'acknowledge dell'irq, l'aggiornamento di $D012 e l'aggiornamento di $0314.
Può sembrare poco tempo ma é ancora possibile farci stare tutto con un semplice accorgimento, questa volta per semplicità ti propongo il codice:

Codice: [Seleziona]
...
...
irqpre
lda #<secirq;2 (36+2/9)  
sta $0314;4
sta $d019;4
inc $d012  ;6
cli  ;2
nop  ;2 gli IRQ inizieranno qua ma questo nop verrà sempre eseguito
nop  ;2
nop  ;2
nop  ;2
nop  ;2
brk  ; Qua non ci si arriva mai!

align 2
*=*+1; Mi assicuro che l'indirizzo sia dispari
; così posso usare il valore per l'ack
secirq
....
....

Ora per il secondo interrupt tieni presente che la routine verrà eseguita con un ritardo di 2/3+7+29=38/39 cicli.
Dovrai fare in modo di posizionare una LDA $d012 o una CMP $d012 (a seconda di come preferisci strutturare la cosa) in modo tale che il suo ultimo ciclo, il 4°, venga ad essere il 63° della 2° riga/1° della 3° riga.
A quel punto, se risulti essere ancora nella 2° riga, un semplice branch all'istruzione successiva ti permetterà di eliminare l'ultimo ciclo di incertezza.
Se hai bisogno "fai un fischio"!
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 22 Marzo 2011, 23:06:17
 
Citazione
*=*+1; Mi assicuro che l'indirizzo sia dispari
; così posso usare il valore per l'ack

Questo significa: prendi la locazione corrente di memoria e skip di 1 posizione? Se si, come fa a rendermi sicuro che l'indirizzo sia dispari? Se mi trovassi in un indirizzo pari + 1 = dispari. Se fossi in un dispari + 1 = di nuovo pari.

Perdona la mia (somma) ignoranza, non capisco che relazione ha con l'ack :(

Apparte questo, ho provato a sistemare il codice! Ora in teoria dovrebbe essere stabile. Ho pensato che al momento di eseguire il salto jsr rasterbars, il conto dei cicli si resetta, e mi trovo il raster allineato.

Però, per saltare, caricare l'accumulatore ecc ecc, servono altri cicli, e infatti la rasterline bianca non è allineata con il bordo sx dello schermo. Come fare? aspettare altri 63 cicli e eseguire gli sta $d020 / sta $d021 in modo da terminare esattamente al 63° ciclo successivo?

La situazione sarebbe quindi questa:

irqpre -> ci assicura il ritardo su irq
irq -> siamo sicuri sul ritardo, possiamo fare un conto sicuro: raster stabile.
raster stabile -> per avere una linea completa e allineata, bisogna fare in modo che l'ultimo sta $d021 termini esattamente al 63°esimo ciclo. Si tratta quindi di ritardare fino all'ultimo!

spero di averci capito qualcosa :) incollo solo la parte centrale del programma per non floodare


Codice: [Seleziona]
;FINO A QUI  X + 7 + 29 cicli.
;ricorda che 2<=X<=9 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 29+X+7
;caso peggiore 45 cicli, ne ho solo  18
irqpre  
   lda #<irq  ;2
   sta $0314  ;4
   sta $d019;4 rispetto ad una inc scendo di 2 cicli
   inc $d012  ;6    
   cli  ;2

;---FINO A QUI MAX 18 CICLI (cosiderato caso peggiore)

  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
                       ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop
   nop;5 nop per totale di 10 cicli, sono sicuro in tutti i casi
   ;(considerando anche il caso migliore)

   brk


   *=*+1;
  ;la routine verrà eseguita con un ritardo di 2/3+7+29=38/39 cicli.
irq
   nop ;41
   nop ;43
   nop ;45
   nop ;47
   nop ;49
   nop ;51
  
   asl $d019;6 = 57
   lda #$35   ;2 = 59
   cmp $d012  ;4 =63
  
   beq start  ;con questo branch allineo l'ultimo
start                  ;ciclo di insicurezza

  ;In teoria qui il conto si resetta a 0 cicli
  ;perche ho stabilizzato il tutto
   jsr rasterbars;6 cicli
        
  ;Tolgo i 6 bytes inseriti nello stack
  ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
   sty $0314
  
  ;rimetto apposto anche il registro $d012
   lda $34
   sta $d012
  
   jmp $ea31
  

rasterbars  
                      ;TODO: ritardare in modo da avere gli sta $d020 / 21
                      ;allineati al 63esimo ciclo (?)
   lda colors;2
   sta $d020;4
   sta $d021;4
  
   ldx #$0a
   dex
   bne *-1
  
    
  
   lda #0    
   sta $d020  
   sta $d021  
      
   rts

 
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 23 Marzo 2011, 00:38:58
 Rispondo per punti:
1)
*=*+1 significa in effetti "incrementa di uno l'attuale indirizzo". La garanzia che sia dispari ce l'ho perché ho fatto precedere un align 2 (allinea l'indirizzo a multipli di 2).
Perché serve dispari? Perché per effettuare l'acknowledge di interrupt generati dal raggiungimento di un raster é necessario scrivere un 1 nel bit 0 di $d019. Ti ricordo che $D019 é strutturato in questo modo:

Bit 0
RST (Interrupt generato dal raggiungimento di un raster)
Read: 1 se c'é un interrupt da servire
Write: 1 per dare l'ack
Bit 1
MBC (Interrupt generato da collisioni sprite/sfondo)
Read:  1 se c'é un interrupt da servire
Write: 1 per dare l'ack
Bit 2
MMC (Interrupt generato da collisioni sprite/sprite)
Read:  1 se c'é un interrupt da servire
Write: 1 per dare l'ack
Bit 3
LP (Interrupt triggerato da una lightpen)
Read:  1 se c'é un interrupt da servire
Write: 1 per dare l'ack

2)
Ho trovato una piccola svista nel tuo codice. Quando alla fine dell'interruzione vai a reimpostare il raster $34, l'istruzione giusta é LDA #$34!! L'hai indicato senza la "#" e quindi il processore va ad impostare l'accumulatore col valore letto nella posizione $34. ;)

3)
Dal momento che nel secondo interrupt sei partito a contare usando il worst case, dovresti arrivare al cmp #$d012 con 64, cioé col primo ciclo della riga successiva: solo in questo modo puoi usare quell'istruzione come discriminante. Se infatti il secondo irq verrà eseguito con un ritardo base di 38 la cmp sara ancora nella riga $35, il confronto andrà a buon fine e ti troverai in start che sei nel 3° ciclo della riga $36 (beq con salto = 3 cicli); se invece il secondo irq partirà con ritardo 39 la cmp sarà già nella riga successiva, il confronto andrà male ma ti troverai in start con lo stesso ritardo di 3 (1 dovuto al ritardo di base + 2 della beq senza salto).

4)
Ti consiglio di usare costantemente i debug border di vice per avere il polso della situazione: solo con quelli puoi avere un feedback visivo sull'effettiva stabilità della routine che stai scrivendo. Prova a vedere il programma così com'é adesso e dopo gli aggiustamenti necessari.

5)
Per il resto é sostanzialmente corretta la tua osservazione: una volta raggiunta la sincronizzazione della cpu con i raster, devi organizzare il tuo codice in modo da "far capitare le cose nel momento giusto"! Puoi ad esempio cambiare il colore del bordo al ciclo 63 di tutte le righe per creare delle linee orizzontali. E' chiaro che per arrivare al ciclo 63 di ciascuna riga dovrai far fare qualcosa al processore... al limite fargli perdere tempo!
In realtà si può cambiare il colore di sfondo anche più volte in una riga creando i famosi raster split; o ancora provare ad aprire i bordi laterali (cosa che si può fare unicamente con un raster stabile).

6)
Comincia a pensare alla maledizione delle badline...  :doh:  non sono sparite eh!
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 23 Marzo 2011, 23:51:21
Ok, grazie per l'ennesima spiegazione! é tutto chiaro. Ho aggiustato un po i timing, e ora mi sembra stabile!!

Ho visto il codice con il bordo in modalità debug, e ora è perfettamente fermo! è sparito anche il problema del flickering sui tasti premuti.

Ho contato i cicli in modo che il termine dell'istruzione sta $d021 (dentro la routine rasterbars) cada esattamente al 63°esimo ciclo.

Cosi facendo si avrà una linea che partirà precisamente alla successiva linea raster (quindi la #$36!). Inoltre poi ho "perso tempo" in modo da far terminare la rts al 63°esimo ciclo della linea #$36.

Che te ne pare? se non vedi errori comincio a lavorare un po sulle badlines :)


Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   tax
   stx $d020
   stx $d021

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
      sta $d01a  ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
  
   LDA $DC0D; Acknowledge CIA IRQ
   LDA $DD0D; Acknowledge CIA NMI
   LSR $D019; Acknowledge VIC IRQ
   cli

hold
   jmp hold


;FINO A QUI  X + 7 + 29 cicli.
;ricorda che 2<=X<=9 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 29+X+7
;caso peggiore 45 cicli, ne ho solo  18
irqpre  
   lda #<irq  ;2
   sta $0314  ;4
   sta $d019;4 rispetto ad una inc scendo di 2 cicli
   inc $d012  ;6    
   cli  ;2

;---FINO A QUI MAX 18 CICLI (cosiderato caso peggiore)

  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
          ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop
   nop;5 nop per totale di 10 cicli, sono sicuro in tutti i casi
  ;(considerando anche il caso migliore)

   brk

   align 2
   *=*+1;
  ;la routine verrà eseguita con un ritardo di 2/3+7+29=38/39 cicli.
irq
   nop;41
   nop;43
   nop;45
   nop;47
   nop;49
   bit $24;52
  
   asl $d019;6 = 58
   lda #$35  ;2 = 60
   cmp $d012  ;4 = 64 / 1° ciclo
  
   beq start  ;con questo branch allineo l'ultimo
start                  ;ciclo di insicurezza

  ;In teoria qui il conto si resetta a 0 cicli
  ;perche ho stabilizzato il tutto
   jsr rasterbars;6 cicli
        
  ;Tolgo i 6 bytes inseriti nello stack
  ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
   sty $0314
  
  ;rimetto apposto anche il registro $d012
   lda #$34
   sta $d012
  
   jmp $ea31
  

rasterbars  
   lda colors;2
  ;ora devo perdere tempo in modo da esaurire i 63-8 = 55 cicli
  
  ;**********************************
  ;*Questo blocco sono 4*12 + 2 = 50
  ;**********************************
   ldx #$0a;2
   dex;2
   bne *-1;2
  
   nop
   bit $24;55 !!
  
  ;Finisco di disegnare la riga proprio al 63°esimo ciclo
   sta $d020;4
   sta $d021;4
  
  ;Ora devo aspettare altri 63 cicli prima di
  ;resettare il colore del background
   ldx #$0a
   dex
   bne *-1
  
   nop
  
  ;e siamo a 47
    
   lda #$0;2    
   sta $d020;4
   sta $d021;4
      
   rts;6 - 63 tondi
  


dir       .byte $0
offs      .byte $90

colors
         .byte $01,$07,$05,$03,$07,$02
         .byte $09,$06,$03,$05,$03,$02
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 24 Marzo 2011, 00:56:43
 Ok, hai realizzato la tua prima raster routine perfettamente stabile!
Puoi anche levare il jmp hold e mettere un semplice rts: la stabilità rimane anche se lavori in basic e fai altre cose. Solo se premi restore noterai del movimento, perché viene generato un nmi. Ci sarebbe il modo di eliminare pure quello ma per il momento sorvoliamo.
Il raster adesso é stabile comunque, senza ombra di dubbio.
I conti che hai fatto per i cicli di ritardo, invece, sono un po' meno giusti, ti propongo lo spezzone di codice corretto. Dai un'occhiata e regolati per le eventuali righe successive.

Codice: [Seleziona]

cmp $d012 ;Qua o siamo a 0 o a 1
beq start ;Qua aggiungiamo 3 oppure 2 cicli
start        ;3 QUA SIAMO SEMPRE NEL 3° CICLO DELLA 3° RIGA

 ;(In teoria qui il conto si resetta a 0 cicli) ?? :) IN PRATICA NO!
 ;ho (stabilizzato)-> SINCRONIZZATO il tutto
   jsr rasterbars;9
        
 ;Tolgo i 6 bytes inseriti nello stack
 ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
   sty $0314
  
 ;rimetto apposto anche il registro $d012
   lda #$34
   sta $d012
  
   jmp $ea31
  

rasterbars  
   lda colors;13
 ;ora devo perdere tempo in modo da esaurire i 63-(13-4) = 46 cicli
    
   ldx #$09;2  2+2+(x-1)*5+2 => 4+8*5+2 = 46
   dex  ;2
   bne *-1 ;2/3
      
 ;Finisco di disegnare la riga proprio al 63°esimo ciclo
   sta $d020;(63) Fine riga
   sta $d021;4° ciclo riga successiva
  
 ;Ora devo aspettare altri 63-4 cicli prima di
 ;resettare il colore del background

   ldx #$0a;51 stessa formula di sopra
   dex
   bne *-1
  
   nop; 51+4+2=57
  
 ;e siamo a... 57
    
   lda #$0 ;59
   sta $d020;(63) fine riga
   sta $d021;4° ciclo nuova riga
      
   rts;6 - 10... comunque tondi ma non 63!;)
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 27 Marzo 2011, 03:37:28
 Ecco qua: chiedo scusa per la rozzezza del codice (sarebbe stato meglio mettere tutto in un loop e fare riferimento a una timing table per i delays..) però cosi' è stato piu' facile fare le prove. sono andato avanti finchè non ho incontrato una badline, e ho cambiato il timing value. poi ho disegnato un ulteriore riga "standard".

Codice: [Seleziona]
;prova doppio interrupt nested

    *=$0801
    include basicline.s

   sei  
   jsr $e544;screen clear

   lda #<irqpre
   ldx #>irqpre
   sta $0314
   stx $0315
  
   lda #$01
      sta $d01a   ; Turn on raster interrupts
  
   lda #$34    
   sta $d012
   lda #$1b    
   sta $d011
   lda #$7f
   sta $dc0d
   sta $dd0d
  
   LDA $DC0D; Acknowledge CIA IRQ
   LDA $DD0D; Acknowledge CIA NMI
   LSR $D019; Acknowledge VIC IRQ
   cli

hold
   jmp hold


;FINO A QUI  X + 7 + 29 cicli.
;ricorda che 2<=X<=9 e X è la
;durata dell'ultima istruzione eseguita
;prima dell'interrupt
;quindi lsr $d019 viene seguita dopo 29+X+7
;caso peggiore 45 cicli, ne ho solo  18
irqpre  
   lda #<irq  ;2
   sta $0314  ;4
   sta $d019;4 rispetto ad una inc scendo di 2 cicli
   inc $d012  ;6    
   cli  ;2

;---FINO A QUI MAX 18 CICLI (cosiderato caso peggiore)

  
  ;Aggiungo una serie di nop per "non fare nulla" intanto che
           ;l'altro interrupt viene eseguito
   nop
   nop
   nop
   nop
   nop;5 nop per totale di 10 cicli, sono sicuro in tutti i casi
   ;(considerando anche il caso migliore)

   brk

   align 2
   *=*+1;
  ;la routine verrà eseguita con un ritardo di 2/3+7+29=38/39 cicli.
irq
   nop ;41
   nop ;43
   nop ;45
   nop ;47
   nop ;49
   bit $24;52
  
   asl $d019;6 = 58
   lda #$35   ;2 = 60
   cmp $d012  ;4 =  64 - siamo a 0 o 1 cicli
  
   beq start  ;3 con questo branch allineo l'ultimo
start                  ;ciclo di insicurezza

  ;QUI SIAMO SICURAMENTE a 3.
   jsr rasterbars;9
        
  ;Tolgo i 6 bytes inseriti nello stack
  ;facendo push nell'accumulatore 6 volte
   pla
   pla
   pla
   pla
   pla
   pla
  
   ldy #<irqpre;Punto di nuovo al primo interrupt
   sty $0314
  
  ;rimetto apposto anche il registro $d012
   lda #$34
   sta $d012
  
   jmp $ea31
  

rasterbars  

    lda colors;13
;ora devo perdere tempo in modo da esaurire i 63-(13-4) = 46 cicli
    
    ldx #$09;2  2+2+(x-1)*5+2 => 4+8*5+2 = 46
    dex ;2
    bne *-1;2/3
      
   ;Finisco di disegnare la riga proprio al 63°esimo ciclo
    sta $d020;(63) Fine riga
    sta $d021;4° ciclo riga successiva
;NUOVA LINEA!  
   ;Ora devo aspettare altri 63-4 cicli prima di
   ;resettare il colore del background

    ldx #$0a;51 stessa formula di sopra
    dex
    bne *-1
  
   ; 51+4=55
  
   ;e siamo a... 55
    lda colors+2;59
    sta $d020;(63) fine riga
    sta $d021;4° ciclo nuova riga
;NUOVA LINEA!  - mancano 59 cicli
    ldx #$0a;51 stessa formula di sopra
    dex
    bne *-1
    
    lda colors+3
    sta $d020
    sta $d021
;NUOVA LINEA!  - mancano 59 cicli    
    
    ldx #$0a;51 stessa formula di sopra
    dex
    bne *-1
  
    lda colors+4;59
    sta $d020;(63) fine riga
    sta $d021;4° ciclo nuova riga
;NUOVA LINEA!  - mancano 59 cicli    
    
    ldx #$0a;51 stessa formula di sopra
    dex
    bne *-1
    
    lda colors+5
    sta $d020;
    sta $d021;4° ciclo nuova riga BADLINE
    
;NUOVA LINEA! BADLINE!! siccome l'ultima istruzione eseguita è una STA allora
; ho solo 22 cicli, di cui 4 ne ho gia consumati. ne restano 18      
    ldx #$01;6
    dex
    bne *-1
    nop
    lda colors+6;10
    sta $d020;14
    sta $d021;22
  
;NUOVA LINEA!  (non badline)  
    
    ldx #$0a
    dex
    bne *-1
    
    lda colors+5
    sta $d020
    sta $d021
    
    nop;allineo timings!
    
    ldx #$0a;51 stessa formula di sopra
    dex
    bne *-1
  
    lda #$0
    sta $d020
    sta $d021
  
    rts
  

colors
         .byte $06,$02,$03,$04,$05,$08
         .byte $07,$08,$04,$01,$00,$06
         .byte $0e,$03,$03,$0e,$03,$03
         .byte $03,$01,$03,$01,$01,$03
         .byte $01,$01,$01,$03,$01,$01
         .byte $03,$01,$03,$03,$03,$0e
         .byte $03,$03,$0e,$03,$0e,$0e
         .byte $0e,$06,$0e,$0e,$06,$0e
         .byte $06,$06,$06,$06,$06,$06
Titolo: Timing Rasters E Badline
Inserito da: antoniomauro - 31 Marzo 2011, 12:54:18
 Complimenti per il sorgente e per come ci sei arrivato!
Leggere la discussione è stato illuminante!
 
Titolo: Timing Rasters E Badline
Inserito da: Elder0010 - 31 Marzo 2011, 19:58:01
 il merito è tutto di freshness e delle sue spiegazioni!
Titolo: Timing Rasters E Badline
Inserito da: antoniomauro - 01 Aprile 2011, 11:01:34
 E' veramente preparatissimo!
Titolo: Timing Rasters E Badline
Inserito da: Freshness79 - 01 Aprile 2011, 15:24:37
 Vi ringrazio molto ma i meriti vanno tutti alle persone che, con notevole dovizia di particolari, hanno documentato l'hardware.
Io, come molti altri, mi sono limitato a leggere, ad applicare e a riportare.
Vi ricordo le due bibbie del 64:
- VIC-article
- 64DOC
Non metto i link ma basta una "googolata"... Il primo dei due in particolare consente di capire a fondo il comparto grafico del 64.
Non so se esistano documenti altrettanto dettagliati sul SID: magari iAN potrebbe conoscerne.
Ed ho sempre trovato informazioni spezzettate anche sui 2 CIA.
Forza Elder, attendo un raster più alto: almeno una 40ina di righe!
;)