Nell’ottica di usare i programmi originariamente su cassetta in emulatori o con dispositivi SDI2EC che simulano i dischetti (ovvero file .d64) ci si trova nella necessità di trasferire giochi con caricamento a più parti da cassetta a disco. Ecco una ricetta utile in molti casi
Il caso di esempio
Useremo come caso di esempio il gioco “ATTACCO ALIENO” preso da una vecchia cassetta della collana Program. Il gioco si carica in due parti:
- Una prima parte, breve, che mostra un titolo grafico e carica la seconda (questo primo programma è anche detta loader)
- Una seconda parte contiene il gioco vero e proprio
E’ facile trasferire da cassetta a disco i due programmi:
- Carico il primo programma con LOAD, salvo su disco con SAVE”ATTACCO ALIENO”,8,1
- Resetto la macchina, quindi carico il secondo programma con LOAD””,1,1 e lo salvo con SAVE”ATT2.CHN”,8,1
- Eseguo LIST per verificare che nel secondo programma non c’è una istruzione SYS che fa partire il gioco da un indirizzo specificato. Evidentemente il primo programma “sa” già a quale indirizzo si trovi l’inizio del programma quindi a caricamento ultimato lo fa partire con una SYS diretta. Un tempo si usavano questi stratagemmi sia per sfruttare tutta la poca memoria disponibile, sia per impedire copie non autorizzate dei giochi creando difficoltà in più.
Alcune note fino qui:
- Il secondo programma l’ho caricato con il parametro Secondary Address = 1 (è il secondo ,1 dell’istruzione LOAD) per accertarmi che venga caricato all’indirizzo di memoria originario. In assenza di questo parametro infatti il VIC potrebbe pure rilocare il codice dove gli fa comodo. I programmi in linguaggio macchina, se spostati altrove in memoria, spesso non funzionano e non vogliamo correre rischi di alterare nulla.
- Il secondo programma l’ho salvato con Secondary Address = 1 (notare ,8,1) in modo da evitare che venga rilocato quando lo caricherò di nuovo. Sono piccoli dettagli spesso non critici, ma se non si fa attenzione in questa fase si può alterare il programma rendendolo inutilizzabile.
- Il nome su disco del secondo programma “ATT2.CHN” è stato dato con questa parte finale .CHN per fare in modo che il programma MENU che usiamo non lo mostri nella lista, ci basta il primo programma che avvia il caricamento del gioco.
Ora, si nota che caricando da disco il primo programma e facendolo partire con RUN, questo tenta di caricare il secondo pezzo da nastro. Questo comportamento è perfettamente normale ma rappresenta il problema che dobbiamo risolvere.
Dobbiamo evidentemente modificare il primo programma per:
- Caricare il secondo programma da disco (device 8) invece che nastro (device 1). Questo può essere relativamente facile da fare.
- Caricando da nastro non era necessario sapere il nome del file, ma usando il disco sì dovremo specificarlo. Il primo programma che funge da loader dunque dovrà essere istruito su come si chiama la seconda parte da caricare, e spesso inserire questa informazione non è banale. Per capire come mai, diamo un’occhiata al primo programma…
Il programma loader (per nastro)
Segue il programma loader originale (ho tolto qualche print inutile per brevità)
200 FOR X=0 TO 24:READ Y:POKE256+X,Y:NEXT
210 SYS256 : REM SOSTITUIRE CON END
220 DATA 162,1,160,255,32,186,255,169,0,32,189,255,162,255
230 DATA 160,255,32,213,255,76,4,16,0,0,0,0,0,0,0,0
Il programma legge nelle DATA una lista di numeri che vengono memorizzati con la POKE a partire dalla locazione di memoria 256. Si tratta evidentemente di un programma in linguaggio macchina che viene poi eseguito con la SYS256.
A questo punto, dopo il ciclo di linea 200 va fatta una ispezione del programma con il monitor per il Linguaggio Macchina per capire cosa fa veramente questo loader. Io ho sostituito la SYS256 a riga 210 con una END, con lo scopo di usare VICMON dopo l’esecuzione per vedere il codice caricato. Se non si ha la cartuccia di VICMON si usa questo dump che prima di iniziare va caricato con l’espansione di memoria settata col blocco 3 attivo. Appena il programma incontra linea 210 e termina si avvia quindi VICMON con:
SYS 24576
Ora, la locazione 256 in esadecimale corrisponde a 0100 quindi, una volta nel monitor, ho disassemblato il programma linguaggi macchina appena caricato con il seguente comando VICMON:
D 0100
da qui (per capirlo serve un pò di esperienza e qualche ricerca su google) si vede che il loader carica il successivo programma dal nastro (Chiamate alle routine Kernel FFBA, FFBD e FFD5) ed esegue il gioco con una JMP $1004, equivalente a una SYS 4100.
Non è un loader particolarmente complicato. Non fa delle POKE di valori speciali in locazioni segrete, né altre raffinatezze, semplicemente carica e avvia il gioco.
Tuttavia per caricare da disco lo dobbiamo modificare e, risparmiandovi i ragionamenti intermedi, vi mostro il codice modificato che andremo a commentare per capirne i punti salienti. Questo codice può essere riutilizzato e adattato in moltissimi altri casi simili.
Il programma loader per disco
Segue il listato:
200 READ Y:IFY=-1THEN210
203 POKE673+X,Y:X=X+1:GOTO200
210 SYS673
220 DATA 162,8,160,1,32,186,255,169,8,162,191,160,02,32,189,255,162,255
230 DATA 160,255,169,0,32,213,255,76,4,16,0,0,65,84,84,50,46,67,72,78,0,0
240 DATA-1
Da un primo sguardo vediamo che il codice linguaggio macchina è più corposo. Ora infatti contiene pure i dati necessari a specificare il nome del file da caricare (ATT2.CHN).
Dal momento che l’area di memoria 256 e seguenti è estremamente piccola e delicata, ho pensato di usare un’altra area un pò più grandicella e meno delicata, quella cioè che parte dalla locazione 673 (esadecimale 02A1), che ho visto usare da altri programmi simili.
Ho modificato il ciclo di lettura dei dati in modo che si fermi quando incontra un dato -1, il che mi ha dato possibilità di modificare il programma facendo via via diverse prove, fino a raggiungere la versione che si vede qui.
La sequenza di dati che compone il caricamento e l’avvio del gioco è quindi data dai numeri che si vedono nelle istruzioni DATA. Li commentiamo qui sotto:
Numeri DATA | Assembler | Cosa fa |
162,8 160,1 32,186,255 |
LDX #$08 LDY #$01 JSR $FFBA |
Device=8 Caricamento con SA=1 chiama routine SETLFS |
169,8 162,191 160,2 32,189,255 |
LDA #$08 LDX #$BF LDY #$02 JSR $FFBD |
Nome file lungo 8 chars Si trova a $02BF chiama routine SETNAM (imposta nome file da cercare) |
162,255 160,255 169,0 32,213,255 |
LDX #$FF LDY #$FF LDA #$00 JSR $FFD5 |
Chiama la routine LOAD che userà i parametri impostati dalle due chiamate precedenti |
76,4,16 0 0 |
JMP $1004 BRK BRK |
SYS 4100 |
65,84,84,50,46,67,72,78 0,0 |
Nome file (8 caratteri) a partire da $02BF Due zeri finali (così disassemblando vedo dove finisce… 0 corrisponde a BRK) |
ATT2.CHN |
…e il gioco è fatto. Attacco alieno si carica da disco!
Se vuoi vedere il risultato:
[Scarica il disco .d64 completo qui]
Include anche VICMON. Il file loader originale è presente sotto il nome “ATTACCO.ORI”.
Ricorda che per eseguire VICMON devi avere una espansione di memoria di 8k su Block 3 (è necessaria una espansione switchabile su un VIC fisico, oppure l’emulatore opportunamente settato) e caricare VICMON con LOAD”VICMON*”,8,1 prima di tutto il resto. Se ti serve il manuale di VICMON lo trovi qui in formato PDF: [Manuale VICMON]
Per riutilizzare il codice
Il codice di sopra può essere utilizzato per altri casi. Ricorda:
- Ispeziona sempre il codice linguaggio macchina del loader originale e fanne una copia e uno screen shot (=foto col cellulare) prima di iniziare a fare modifiche. Cerca di capire cosa fa prima di modificare.
- Salva il file da caricare con un nome lungo 8 caratteri così la LDA #$ 08 non hai bisogno di modificarla.
- Metti il nome file come sequenza di codici ASCII nei dati dopo i due zeri (gli zeri sono i BRK dell’assembler). Con VICMON prendi nota della locazione di memoria dopo i due BRK e sostituisci a 02BF il valore attuale. Byte basso prima, byte alto dopo. Per i codici ASCII dei caratteri puoi usare PRINT ASC(“C”) cambiando il carattere tra virgolette. Per convertire da decimale a esadecimale e viceversa puoi usare la calcolatrice di Windows settata in modo Programmatore, altrimenti trovi siti online con cui fare la conversione.
- Cambia la JMP 1004 con la JMP all’indirizzo giusto per il TUO gioco.
Conclusioni
Adattare un programma multi load da nastro a disco non è banale e richiede un pò di esperienza e di accortezza. Generalmente la seconda parte del programma viene caricata e avviata da un piccolo programma in linguaggio macchina. Dal momento che il caricamento di un programma ha sempre più o meno la stessa sequenza di operazioni e chiamate, con l’aiuto di VICMON è possibile capire cosa il programma loader fa, e modificarlo in modo di caricare da disco invece che da nastro.
Se hai trovato questo tutorial utile, per favore fai un commento qui sotto e dai un rating con le stelline.
E comunque adesso puoi farti una bella partita ad Attacco Alieno!
Grazie, ottima lezione, utile anche per gli ignoranti come me. Adesso mi sento un po’ uno smanettone anch’io 🙂
grazie ci giocavo nell’84 l’ho ritrovato in soffitta e mi hai fatto tornare la voglia di smanettare . carlo