Programmare WHDLoad

### Sequenza schematica di esecuzione

La seguente tabella mostra la sequenza di azioni compiute quando viene eseguito un programma installato con WHDLoad.Spero che vi possa aiutare a capire meglio come funziona WHDLoad e come avviene la sua cooperazione con lo Slave ed il programma installato.

L'UTENTE

- avvia il demo o il gioco cliccando un'icona o avviando WHDLoad dalla riga di comando

Il Sistema Operativo

- carica l'eseguibile di WHDLoad e lo avvia

WHDLoad

- controlla l'ambiente Software e Hardware
- carica e controlla lo Slave
- alloca la memoria necessaria per il programma installato
- se Preload/S è abilitata allora carica le immagini disco e i file nella RAM (se c'è abbastanza memoria disponibile)
- disabilita il SO (disabilita il multitasking e gli interrupt, degrada l'hardware grafico all'OCS, inizializza tutto l'hardware con i valori definiti)
- passa il controllo allo Slave

Slave

- carica l'eseguibile principale del programma installato mediante una chiamata ad una funzione di WHDLoad (ad esempio resload_DiskLoad o resload_LoadFile)
- patcha l'eseguibile principale (in modo che il programma carichi i suoi dati tramite lo Slave, per fissare problemi di compatibilità, per abilitare l'uscita dal programma)
- passa il controllo all'eseguibile principale

Il Programma Installato

- eseguirà le operazioni necessarie
- al caricamento di dati dal disco richiamerà lo Slave (poichè quest'ultimo in precedenza lo ha patchato in modo che lo faccia), e lo Slave richiamerà WHDLoad, e WHDLoad abiliterà parzialmente il SO per caricare i dati (solo se i dati non sono Preload'ed, precaricati), quindi ritornerà il controllo allo Slave, e quindi ancora al programma installato che procederà con l'esecuzione

L'UTENTE

- uscirà dal programma mediante pressione del QuitKey

Slave

- ripasserà il controllo a WHDLoad mediante chiamata a resload_Abort

WHDLoad

- riabiliterà il SO (ripristino dei registri hardware, del display e della memoria)
- libererà tutte le risorse allocate
- ritornerà al SO

### Come installare un semplice trackloader per disco singolo

Questa è una piccola e breve guida sulla creazione di un installatore per WHDLoad. La guida riflette un semplice caso ideale. Nella realtà questa eventualità probabilmente non si verificherà mai. Per situazioni speciali e problemi, leggi i capitoli che seguono questo.

1. Lavoro di preparazione
   - Crea un cassetto che contiene tutti i file.
   - Crea l'immagine del disco con DIC in questo cassetto.
   - Crea un file #?.info con "WHDLoad" come <Tool di Default> ed il Tooltype "SLAVE=#?" con il nome dello Slave (o più semplicemente copia l'icona da un installatore d'esempio, e disabilita tutti i tooltype eccetto "SLAVE=").
2. Lo Slave
   Per scrivere lo Slave abbiamo bisogno delle seguenti informazioni:
   1. Dov'è localizzato l'eseguibile principale nel disco?
   2. Dov'è localizzato il diskloader nell'eseguibile principale?
   Per ottenere queste informazioni prima di tutto analizziamo il bootblock. Il più delle volte l'eseguibile principale viene caricato da qui tramite exec.DoIO(). A volte nel bootblock c'è uno speciale trackloader. Adesso scriveremo uno Slave che simulerà il bootblock e caricherà l'eseguibile dall'immagine disco. A questo punto ripperemo l'eseguibile principale dall'immagine a da un memory dump. Dopodiche dobbiamo trovare il loader nell'eseguibile. Un metodo veloce è di cercare il pattern `$AAAAAAAA` (utilizzato dalla decodifica MFM) con un hex-editor. Quindi tagliamo l'area trovata (+/- `$1000` byte), disassembliamola, e cerchiamo l'inizio della routine. Bisogna capire la lista di parametri. Adesso creiamo il codice per lo Slave che patcherà questa routine di caricamento in maniera tale che tutte le chiamate al loader verranno redirezionate allo Slave. Lo Slave quindi aggiusterà i parametri e chiamerà la funzione di WHDLoad resload_DiskLoad.
3. In un caso ideale l'installatore ora sarà completo.
   L'unica cosa rimasta da fare è di creare una bella icona. Rippa due immagini con lo snoop di WHDLoad e SP oppure un freezer o ancora UAE e crea l'icona. Si raccomanda l'utilizzo della palette a 16 colori di RomIcon.

### Eventuali problemi e casi speciali

#### Trackloader non standard

Alcuni programmi utilizzano un formato disco proprietario. Questo significa che DIC non sarà capace di crearne l'immagine. Per creare i file o l'immagine di questo tipo di dischi si raccomanda l'utilizzo di RawDIC. Leggi la sua documentazione per maggiori informazioni.

#### Dischi multipli

Se il programma utilizza più di un disco lo slave deve redirezionare gli accessi disco al file immagine corretto. A volte questo non risulta essere semplice. Alcuni programmi supportano più di un drive, così puoi usare il numero del drive per selezionare il disco. Molti programmi fanno uso di un ID inserito in ogni disco per distinguerli. In questo caso usa una variabile che contiene il numero del disco, e ad ogni accesso all'ID del disco (determina questo tipo di accesso analizzando i parametri per il diskloader) incrementa la variabile (se si è arrivati all'ultimo disco, decrementala). Così si spera che il loader rileggerà l'ID fino a che il disco corretto non sarà inserito. Se vi fosse una richiesta da parte del programma che richieda all'utente di inserire il disco corretto, disabilitala.

#### Salvataggio dell'Highscore

Non molto da dire. Usa resload_SaveFile per scrivere su disco l'appropriata area di memoria. Se preferisci, puoi crittare i dati così i lamer non potranno modificarli tanto facilmente. Non raccomandiamo di scrivere direttamente nelle immagini disco (tramite resload_SaveFileOffset), perché se qualcosa va storto (ad esempio un crash) è possibile che l'immagine venga corrotta.

#### Salvataggi

La gestione dei salvataggi è identica a quella degli highscore.

#### Accessi al sistema operativo

Nel momento in cui vengono eseguiti lo slave ed il programma installato, il sistema operativo non è disponibile e non vi si può accedere! Perciò tutti i tentativi di accesso da parte del programma installato devono essere disabilitati. Se non ce ne sono molti e non hanno nessun senso nell'ambiente di WHDLoad (come exec.Disable() o exec.SuperState()) sostituiscili con un NOP (`$4e71`). Se gli accessi svolgono un'azione importante (come exec.DoIO()), redirezionali allo Slave ed emulali. Se ce ne sono molti, crea una semplice exec.library in un'area non utilizzata di memoria (inizializza la longword all'indirizzo `$4`). Puoi dare uno sguardo al sorgente di Oscar.slave, che emula exec.AllocMem(). Per scovare gli accessi al SO, l'execbase viene impostato inizialmente a `$f0000001` con l'intenzione che tutte le routine che utilizzeranno l'execbase causeranno un'eccezione "Address Error".
Se c'è un pesante uso di funzioni del SO, usa uno dei pacchetti kickemu che possono essere trovati nel pacchetto whdload-dev. C'è un pacchetto per il Kick 1.3 ('src/sources/whdload/kick13.s') ed uno per il Kick 3.1 ('src/sources/whdload/kick31.s'). Questi richiedono un'immagine originale del Kickstart e creeranno un ambiente SO completo all'interno dello spazio di WHDLoad. Cunsulta anche l'appropriato readme fornito per ulteriori informazioni.

### Problemi comuni di compatibilità

#### Spazio di indirizzamento limitato con 68000/68010/68ec020

In questi processori lo spazio di indirizzamento è limitato a 16Mb (`$000000...$ffffff`) perché queste CPU possiedono solo 24 linee di indirizzo. Come risultato si ha che tutti gli accessi ad indirizzi superiori vengono effettuati nei 16Mb inferiori tramite ignoramento degli 8 bit più significativi. Alcuni programmi utilizzano questi bit per immagazzinare dei dati, o semplicemente dimenticano di azzerarli. Con una CPU con 4Gb di spazio di indirizzamento come 68020/68ec030/68030/68040/68060 questo non funzionerà, perché verrà acceduto l'intero spazio di indirizzamento a 32-bit.
Per risolvere questo problema devi patchare questi accessi e redirezionarli agli indirizzi appropriati.
A volte la ragione di accessi a strani indirizzi può essere un puntatore non inizializzato. In questo caso può aiutare l'azzeramento di `$400` - ws_BaseMemSize.

#### Stackframe differenti in ogni processore

Gli stackframe creati dal processore per interrupt ed eccezioni sono diversi per ogni membro della famiglia 68k. In un 68000 uno stackframe è di 6 byte, eccetto in caso di errori di Bus o Indirizzo. Lo stackframe contiene lo SR salvato all'indirizzo (a7) ed il PC salvato a (2,a7). In tutti gli altri processori (68010+) lo stackframe minimo è di 8 byte ed in aggiunta contiene il numero del vettore come word all'indirizzo (6,a7). Questo formato a 4-word dello stackframe `$0` viene creato per "Trap #xx" e gli interrupt nei 68010-68060. Gli stackframe nel caso di altre eccezioni sono diversi per ogni processore. L'istruzione RTE lavora in modo diverso su un 68000 rispetto che su 68010+. In un 68000 ripristina solamente lo SR ed il PC e continua l'esecuzione del programma all'indirizzo da cui è stata interrotta. Nei 68010+ in aggiunta a questo libererà lo stackframe dipendentemente dal suo formato.
Alcuni programmi eseguono un push di un indirizzo (PC) e uno SR e quindi eseguono una istruzione RTE. Questo funziona solo con un 68000, su 68010+ produrrà risultati indefinibili.
Se un programma lo fa, devi fissarlo. A volte può essere sufficente sostituire la RTE con una RTR.

#### MOVEM.x RL,-(An) su 68000/010 e 68020/030/040

C'è una differenza se il registro utilizzato in modalità predecremento (RL) è contenuto anche nella lista dei registri. Per il 68020, 68030 e 68040 il valore scritto nella memoria è il valore iniziale del registro decrementato della dimensione dell'operazione. I 68000 e 68010 scrivono il valore iniziale del registro (non decrementato).
Poiché questa caratteristica non è per niente utile, non si ha notizia di software che ha problemi per questo motivo.

### Linee guida generali per la scrittura degli installatori

- Non modificare i registri della CPU presenti in processori più evoluti come VBR o CACR. Il VBR è sempre 0 dal punto di vista del programmatore dello Slave, anche se viene spostato a causa dell'emulazione degli Auto Vectors (e Traps se il Flag WHDL_EmulTrap è impostato). I bit nel CACR sono diversi in ogni processore. C'è solo un modo corretto di modificare le cache, usa resload_SetCACR/SetCPU e i bitdef da 'exec/execbase.i' e 'whdload.i'. Anche tutte le parti del programma da installare che interagiscono con questi registri devono essere disabilitate o saltate, altrimenti WHDLoad non potrà funzionare correttamente!
- Non modificare mai le immagini disco. Questo ha il vantaggio che chiunque voglia avviare il programma da un floppy dovrà solo riscrivere l'immagine in un floppy (a condizione che il programma giri senza molti fix, di certo non un caso molto frequente).
- Non usare mai parti originali del programma nello Slave (problemi di copyright).
- Abilita le Cache solo se sei sicuro che in questo modo giri su tutti i processori.
- Utilizza il minor quantitativo di memoria possibile per ws_BaseMemSize. Alcune persone hanno tag residenti alla fine della memoria Chip, quindi aiuterà l'utilizzo di `$1f0000` invece che `$200000` e WHDLoad può usare memoria allocata in modo assoluto.

### Tips & tricks

#### Cos'è meglio, usare immagini disco o file?

A volte avrai la possibilità di scegliere fra l'utilizzo di immagini disco o file. Entrambi hanno i loro vantaggi. L'utilizzo di immagini disco è normalmente il modo più semplice e veloce di creare lo Slave. Ma il caching funziona meglio con i file (se c'è poca memoria o è frammentata). Anche lo spazio necessario nell'harddisk è inferiore per i file che con le immagini. Dovresti usare le immagini disco solo se ci sono molti file (più di 30).