Ready64 Forum
Commodore 64 => Programmazione, Grafica e Musica => Topic aperto da: mssmsoft - 27 Giugno 2009, 17:55:33
-
Ho "portato" in C i primi due esempi del capitolo 4 della Guida del Programmatore.
Potrebbero essere utili a qualcuno, almeno spero :D .
Per compilare, salvate il sorgente da qualche parte, andate nel direttorio e usate:
cl65 -O1 -t c64 -o sound.prg *.c
-
Trovati *BUG* nel listato riportato dalla versione italiana del Manuale del programmatore e *BUG* nel mio listato.
Questo nuovo suona esattamente come la versione BASIC.
-
Ecco l'ultima versione del file, con tutti e 10 i programmi del capitolo 4 del manuale del programmatore.
Il sorgente e` (parzialmente) commentato.
-
Archivio con:
sound.c
sound.prg
make.bat
-
Dover rilanciare dopo ogni scelta e' un po' noioso.
Nell'opzione J hai usato un delay decisamente lungo, 25000 e' troppo.
for(t=0; t<delay(250); t++);
SID.v1.ctrl = 20;
for(t=0; t<delay(100); t++);
e' fin che mai adeguato.
E in C l'acapo nelle stringhe e' \r\n, a meno che CC65 non abbia qualche controindicazione :P
-
Dover rilanciare dopo ogni scelta e' un po' noioso
Concordo
Nell'opzione J hai usato un delay decisamente lungo, 25000 e' troppo.
Ho cercato di mantenere la stessa durata dei suoni delle versioni BASIC. Ho scritto una nuova delay() che mi permette di "regolare" meglio la durata.
* delay - attende per il tempo indicato (in 1/60 di secondo)
*
* Parametri:
* unsigned long t; 1/60 di secondo da attendere
* Ritorno: void
* Nessuno
* Side Effects:
* Nessuno
*/
void delay(unsigned long t)
{
unsigned char *tt = (unsigned char *)0x00A0;
unsigned long l, f;
l = (unsigned long)(tt[2]+tt[1]*256+tt[0]*256*256);
f = l + t;
while(l < f) {
l = (unsigned long)(tt[2]+tt[1]*256+tt[0]*256*256);
}
}
E in C l'acapo nelle stringhe e' \r\n
Pignolo! :D
-
Nuova versione di delay() che gestisce anche il fatto che l'orogio di sistema potrebbe arrivare a fine corsa e ripartire da zero
#define DELAY_LIMIT 0xFFFFFFUL
#define TREBYTE(x) (unsigned long)((x)[2]+(x)[1]*256+(x)[0]*256*256)
void delay(unsigned long t)
{
unsigned char *tt = (unsigned char *)0x00A0;
unsigned long l, f;
l = TREBYTE(tt);
if((l + t) > DELAY_LIMIT) {
t -= DELAY_LIMIT - l;
while(l < DELAY_LIMIT) {
l = TREBYTE(tt);
}
}
f = l + t;
while(l < f) {
l = TREBYTE(tt);
}
}
-
Nella delay() c'e` un problema: l'orologio del C64 e` su 3 byte e viene aggiornato ogni 1/60 di secondo. Capita che la routine NON riesca a leggere i 3 byte prima che uno dei tre venga nuovamente modificato e quindi si prendono fischi per fiaschi. :doh:
Domanda: come posso leggere l'orologio altrimenti? :confused:
-
Quei byte ($a0-a2) sono aggiornati solo mentre usi il basic e non hai nulla in irq. Un programma in cc65 non e' detto che abbia il basic attivo anzi, che io sappia vedi tutta la memoria fino a $cfff quindi niente basic ROM attiva.
Prova a utilizzare il CIA clock, che non e' affetto da alcun ritardo.
Alternativamente c'e' una routine in Kernal che consente di aspettare esattamente un microsecondo
$EEB3/61107: Delay 1 ms
Jump from $ED3D:
EEB3: 8A TXA
EEB4: A2 B8 LDX #$B8
Jump from $EEB7:
EEB6: CA DEX
EEB7: D0 FD BNE $EEB6
EEB9: AA TAX
EEBA: 60 RTS