Hallo!
Ich habe mich in den letzten paar Tagen viel mit C64-Assembler auseinandergesetzt, da ich SID-Musik einfach klasse finde und mal gucken wollte, wie schwer es eigentlich ist, einen nicht-blockierenden Player zu schreiben. Damit hatte ich schon auf dem ESP32 Erfolg. Aber der 64'er ist nochmal was ganz anderes. Ich habe mich mit dem IRQ beschäftigt und es geschafft, diesen IRQ anzuzapfen und "Alle meine Entchen" mit einer Frequenztabelle zu spielen. Man könnte auch einfach nur die tiefsten 12 Töne speichern und dann ROL nutzen, aber das wollte ich nicht direkt am Anfang ausprobieren. "Alle meine Entchen" spielte zwar, aber es spielte aus dem Takt. Nicht extrem schlimm, aber mich nervt sowas ganz besonders, darum versuchte ich, da was gegen zu tun. Ich habe mir diesen Rasterzeilen-IRQ angeguckt und dafür ein Beispielprogramm, welches den Hintergrund und Rahmen zur Deutschlandflagge (welche übrigens nur ganz schlecht mit der hellblauen Schrift harmoniert) macht. Ich dachte mir, dass ein IRQ, der so exakt ist, dass der Hintergrund fast garnicht flackert, unmöglich aus dem Takt sein kann, darum habe ich das Abspielprogramm mit dem Flaggenprogramm verschmolzen und zusätzlich noch diesen 60 Mal pro Sekunde gehenden IRQ abgestellt - ich hänge eh BASIC mit jmp * auf - und es spielte immernoch aus dem Takt. Ich habe auch die Rasterzeile in die Mitte gepackt, vollkommen ohne Effekt. Langsam habe ich keine Ahnung mehr, was ich tun könnte, daher frage ich euch: Wisst ihr, wie man dem C64 ein bisschen mehr Taktgefühl verpassen kann? Hier ist mein Programm:
- OCTAVE1 = 0
- OCTAVE2 = 12
- OCTAVE3 = 24
- OCTAVE4 = 36
- OCTAVE5 = 48
- OCTAVE6 = 60
- NC1 = OCTAVE1+1
- NCs1 = OCTAVE1+2
- ND1 = OCTAVE1+3
- NDs1 = OCTAVE1+4
- NE1 = OCTAVE1+5
- NF1 = OCTAVE1+6
- NFs1 = OCTAVE1+7
- NG1 = OCTAVE1+8
- NGs1 = OCTAVE1+9
- NA1 = OCTAVE1+10
- NB1 = OCTAVE1+11
- NH1 = OCTAVE1+12
- NC2 = OCTAVE2+1
- NCs2 = OCTAVE2+2
- ND2 = OCTAVE2+3
- NDs2 = OCTAVE2+4
- NE2 = OCTAVE2+5
- NF2 = OCTAVE2+6
- NFs2 = OCTAVE2+7
- NG2 = OCTAVE2+8
- NGs2 = OCTAVE2+9
- NA2 = OCTAVE2+10
- NB2 = OCTAVE2+11
- NH2 = OCTAVE2+12
- NC3 = OCTAVE3+1
- NCs3 = OCTAVE3+2
- ND3 = OCTAVE3+3
- NDs3 = OCTAVE3+4
- NE3 = OCTAVE3+5
- NF3 = OCTAVE3+6
- NFs3 = OCTAVE3+7
- NG3 = OCTAVE3+8
- NGs3 = OCTAVE3+9
- NA3 = OCTAVE3+10
- NB3 = OCTAVE3+11
- NH3 = OCTAVE3+12
- NC4 = OCTAVE4+1
- NCs4 = OCTAVE4+2
- ND4 = OCTAVE4+3
- NDs4 = OCTAVE4+4
- NE4 = OCTAVE4+5
- NF4 = OCTAVE4+6
- NFs4 = OCTAVE4+7
- NG4 = OCTAVE4+8
- NGs4 = OCTAVE4+9
- NA4 = OCTAVE4+10
- NB4 = OCTAVE4+11
- NH4 = OCTAVE4+12
- NC5 = OCTAVE5+1
- NCs5 = OCTAVE5+2
- ND5 = OCTAVE5+3
- NDs5 = OCTAVE5+4
- NE5 = OCTAVE5+5
- NF5 = OCTAVE5+6
- NFs5 = OCTAVE5+7
- NG5 = OCTAVE5+8
- NGs5 = OCTAVE5+9
- NA5 = OCTAVE5+10
- NB5 = OCTAVE5+11
- NH5 = OCTAVE5+12
- NC6 = OCTAVE6+1
- NCs6 = OCTAVE6+2
- ND6 = OCTAVE6+3
- NDs6 = OCTAVE6+4
- NE6 = OCTAVE6+5
- NF6 = OCTAVE6+6
- NFs6 = OCTAVE6+7
- NG6 = OCTAVE6+8
- NGs6 = OCTAVE6+9
- NA6 = OCTAVE6+10
- NB6 = OCTAVE6+11
- NH6 = OCTAVE6+12
- TIMELEFT = $FF
- MUSICPOS = $FE
- BUFFERFQL = $FD
- BUFFERFQH = $FC
- BUFFERCNT = $FB
- BUFFERFLT = $FA
- *=$0801
- ;*** Startadresse BASIC-Zeile: 2018 SYS 2064:NEW
- !word main-2, 2018
- !byte $9e
- !text " 2064:"
- !byte $a2,$00,$00,$00
- lda #$36
- sta $D405
- lda #$39
- sta $D406
- lda #$41
- sta $D404
- lda #$08
- sta $D403
- lda #$00
- sta $D402
- ;lda #$41
- ;sta $D404
- lda #$1F
- sta $D418
- lda #$81
- sta $D417
- lda #$80
- sta $D416
- lda #$01
- sta $FF
- lda #$00
- sta $FE
- main
- sei ;Interrupts sperren
- lda #<irq ;unsere Interrupt-Routine
- sta $0314 ;in den IRQ-Vector eingtragen
- lda #>irq ;auch das MSB
- sta $0315
- lda #%01111111 ;Ohne KERNAL-ROM gibt es auch
- sta $DC0D ;kein $EA31 mehr, also Timer-IRQ aus!
- lda #$80 ;Bei STARTBLACK soll ein
- sta $d012 ;Raster-IRQ ausgelöst werden
- lda $d011 ;Zur Sicherheit auch noch
- and #%01111111 ;das höhste Bit für den
- sta $d011 ;gewünschten Raster-IRQ löschen
- lda $d01a ;IRQs vom
- ora #%00000001 ;VIC-II aktivieren
- sta $d01a
- cli ;Interrupts wieder erlauben
- jmp *
- ;rts ;zurück zum BASIC
- ;*=$1000
- ;*** unsere eigene Interrupt-Routine
- irq
- lda $d019
- sta $d019
- ;lda $d019
- ;bmi doRasterIrq ;wenn ja -> Raster IRQ
- ;lda $dc0d ;sonst, CIA-IRQ bestätigen
- ;cli ;IRQs erlauben
- ;jmp $ea31 ;und zur ROM-Routine springen
- ;doRasterIrq
- ;sta $d019 ;IRQ bestätigen
- dec TIMELEFT
- bne skip
- readnote
- ldx MUSICPOS
- lda music+1,x
- sta TIMELEFT
- lda music,x
- cmp #$00
- beq skipnote
- pha
- and #%11110000
- cmp #%11100000
- bne skipcmdf
- pla
- asl
- asl
- asl
- asl
- ora #%00001111
- sta BUFFERFLT
- inc MUSICPOS
- jmp readnote
- skipcmdf
- pla
- asl
- tax
- lda notes-2,x
- sta BUFFERFQL
- lda notes-1,x
- sta BUFFERFQH
- lda #$41
- sta BUFFERCNT
- skipnote
- inc MUSICPOS
- inc MUSICPOS
- ;lda $FE
- ;cmp #80
- ;bne skip
- ;lda #$00
- ;sta $FE
- ldx MUSICPOS
- lda music,x
- cmp #$FF
- bne skip
- lda #$00
- sta MUSICPOS
- skip
- lda BUFFERCNT
- beq nocnt
- ldx #$00
- stx $D404
- sta $D404
- lda #$00
- sta BUFFERCNT
- nocnt
- lda BUFFERFQL
- sta $D400
- lda BUFFERFQH
- sta $D401
- lda BUFFERFLT
- sta $D416
- pla ;Y vom Stack
- tay
- pla ;X vom Stack
- tax
- pla ;Akku vom Stack
- rti ;Interrupt verlassen
- *=$1000
- notes
- !word 1024,1084,1149,1217,1290,1366,1448,1534,1625,1722,1824,1933
- !word 2048,2169,2298,2435,2580,2733,2896,3068,3250,3444,3649,3866
- !word 4096,4339,4597,4870,5160,5467,5792,6137,6501,6888,7298,7732
- !word 8192,8679,9195,9741,10321,10935,11585,12274,13003,13777,14596,15464
- !word 16384,17358,18390,19483,20642,21870,23170,24548,26007,27554,29192,30928
- !word 32768,34716,36780,38967,41285,43740,46340,49096,52015,55108,58385,61857
- music
- ;!byte $E0, ND1,12, ND1,12, ND2,12, ND1,12, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E1, ND1,12, ND1,12, ND2,12, ND1,12, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E2, ND1,12, ND1,12, ND2,12, ND1,12, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E3, ND1,12, ND1,12, ND2,12, ND1,12, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E4, ND1,12, ND1,12, ND2,12, ND1,12, $E5, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E6, ND1,12, ND1,12, ND2,12, ND1,12, $E7, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E8, ND1,12, ND1,12, ND2,12, ND1,12, $E9, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $EA, ND1,12, ND1,12, ND2,12, ND1,12, $EB, ND2,12, ND1,12, NA1,12, NC2,12
- ;!byte $E9, ND3,2,NF3,2,NA3,2,ND3,2,NF3,2,NA3,2,0,12
- ;!byte $ED, ND3,2,NF3,2,NA3,2,ND3,2,NF3,2,NA3,2,0,12
- ;!byte $E9, ND3,2,NF3,2,NA3,2,ND3,2,NF3,2,NA3,2,0,6
- ;!byte $ED, ND3,2,NF3,2,NA3,2,ND3,2,NF3,2,NA3,2,0,6
- ;!byte $EF, ND3,2,NF3,2,NA3,2,ND3,2,NF3,2,NA3,2
- ;
- ;!byte $E9, ND3,2,NG3,2,NH3,2,ND3,2,NG3,2,NH3,2,0,12
- ;!byte $ED, ND3,2,NG3,2,NH3,2,ND3,2,NG3,2,NH3,2,0,12
- ;!byte $E9, ND3,2,NG3,2,NH3,2,ND3,2,NG3,2,NH3,2,0,6
- ;!byte $ED, ND3,2,NG3,2,NC4,2,ND3,2,NG3,2,NC4,2,0,6
- ;!byte $EF, ND3,2,NG3,2,NH3,2,ND3,2,NG3,2,NH3,2
- !byte $E9,NC4,12
- !byte $EB,NC4,12
- !byte $ED,NC4,12
- !byte $EF,NC4,12
- !byte $FF
Da das Programm aus mehreren Programmen zusammengestückelt ist, machen die Kommentare größtenteils keinen Sinn.
Gruß
NoobTracker