Προγραμματίζοντας το WHDLoad

### Σχηματική ροή εκτέλεσης

Ο ακόλουθος πίνακας δείχνει τη ροή προγράμματος όταν θα εκτελεστεί μία εγκατάσταση του WHDLoad. Ελπίζω να σας βοηθήσει να καταλάβετε πως δουλεύει το WHDLoad και πως το WHDLoad, το Slave και το εγκατεστημένο πρόγραμμα συνεργάζονται.

Ο ΧΡΗΣΤΗΣ

- ξεκινάει το demo ή παιχνίδι κάνοντας κλικ στο εικονίδιο Icon ή ξεκινώντας το WHDLoad από τη γραμμή εντολών

Το Λειτουργικό Σύστημα

- φορτώνει το εκτελέσιμο του WHDLoad και το ξεκινάει

Το WHDLoad

- ελέγχει το περιβάλλον Software και Hardware
- φορτώνει και ελέγχει το Slave
- κατανέμει την απαιτούμενη memory για το εγκατεστημένο πρόγραμμα
- εάν η Preload/Sέχει ενεργοποιηθεί φορτώνει τα disk images και τα αρχεία στη RAM (εφόσον υπάρχει διαθέσιμη ελεύθερη μνήμη)
- κλείνει το OS (απενεργοποιεί το mutitasking και τα interrupts, υποβαθμίζει το hardware γραφικών σε OCS, ξεκινά όλο το hardware με ορισμένες τιμές)
- μεταπηδάει στο Slave

Slave

- φορτώνει το κυρίως εκτελέσιμο του εγκατεστημένου προγράμματος καλώντας μία συνάρτηση του WHDLoad (π.χ. resload_DiskLoad ή resload_LoadFile)
- διορθώνει το κυρίως εκτελέσιμο (ότι το πρόγραμμα θα φορτώσει τα δεδομένα του μέσω του Slave, να διορθώσει προβλήματα συμβατότητας, να ενεργοποιήσει μία έξοδος από το πρόγραμμα)
- καλεί το κυρίως εκτελέσιμο

Εγκατεστημένο πρόγραμμα

- θα κάνει τα πράγματά του
- στο φόρτωμα δεδομένων από το δίσκο θα καλέσει το Slave (επειδή το Slave το έχει διορθώσει έτσι προηγουμένως), και το Slave θα καλέσει το WHDLoad, και το WHDLoad θα ενεργοποιήσει μερικώς το OS για να φορτώσει τα δεδομένα (μόνο αν τα δεδομένα δεν είναι ήδη με Preload'ed),μετά επιστρέφει, επιστρέφει και το εγκατεστημένο πρόγραμμα συνεχίζει

Ο ΧΡΗΣΤΗΣ

- βγαίνει από το πρόγραμμα πατώντας το QuitKey

το Slave

- επιστρέφει στο WHDLoad καλώντας την resload_Abort

το WHDLoad

- επανενεργοποιεί το OS (επαναφέρει τους καταχωρητές hardware, την οθόνη και τη μνήμη)
- απελευθερώνει όλους τους κατανεμημένους πόρους
- και επιστρέφει στο OS

### Πως να εγκαταστήσετε ένα απλό trackloader μίας δισκέτας

Αυτός είναι ένα πολύ μικρός και σύντομος οδηγός βήμα-βήμα για το πως να δημιουργήσετε μία εγκατάσταση χρησιμοποιώντας το WHDLoad. Ο οδηγός αντιπροσωπεύει μία ιδανική απλή περίπτωση. Στο πραγματικό κόσμο μία τέτοια περίπτωση μάλλον δεν θα υπάρχει ποτέ. Για ειδικές περιπτώσεις και προβλήματα, διαβάστε τα κεφάλαια που ακολουθούν.

1. Προεργασία
   - Δημιουργήστε ένα κατάλογο που θα κρατήσει όλα τα αρχεία.
   - Δημιουργήστε ένα disk image χρησιμοποιώντας το DIC σε αυτόν το κατάλογο.
   - Δημιουργήστε ένα αρχείο #?.info με το "WHDLoad" ως <Default Tool> και ένα Tooltype "SLAVE=#?" που περιέχει το όνομα του slave. (ή απλά αντιγράψτε το εικονίδιο από ένα Παράδειγμα Εγκατάστασης, και απενεργοποιήστε όλα τα tooltypes εκτός του "SLAVE=").
2. Το Slave
   Για την εγγραφή του slave χρειαζόμαστε τις παρακάτω πληροφορίες:
   1. Που στο δίσκο βρίσκεται το κυρίως εκτελέσιμο;
   2. Που μέσα στο κυρίως εκτελέσιμο βρίσκεται ο disk loader;
   Για να πάρουμε αυτές τις πληροφορίες πρώτα αναλύουμε το bootblock. Τις περισσότερες φορές το κυρίως εκτελέσιμο θα φορτωθεί από εδώ μέσω της exec.DoIO(). Μερικές φορές ένας ειδικός trackloader μπορεί να βρίσκεται στο bootblock. Τώρα γράφουμε ένα Slave που θα εξομοιώσει το bootblock και θα φορτώσει το κυρίως εκτελέσιμο από το disk image. Τώρα εξάγουμε το κυρίως εκτελέσιμο από το image ή από ένα dump μνήμης. Μετά από αυτό πρέπει να βρούμε το loader στο κυρίως εκτελέσιμο. Ένας γρήγορος τρόπος είναι να ψάξουμε για το μοτίβο `$AAAAAAAA` (χρησιμοποιείται από αποκωδικοποίηση MFM) με έναν hex-editor. Μετά αποκόβουμε τη περιοχή (+/- `$1000` bytes) που βρήκαμε, την κάνουμε disassemble, και ψάχνουμε την αρχή της ρουτίνας. Καταννοούμε τη λίστα παραμέτρων. Τώρα χρησιμοποιούμε κώδικα για το Slave που θα διορθώσει αυτή τη ρουτίνα του loader με τέτοιο τρόπο που όλες οι κλήσεις στο loader θα προωθούνται στο Slave. Το Slave τότε θα προσαρμόσει τις παραμέτρους και θα καλέσει τη συνάρτηση του WHDLoad resload_DiskLoad.
3. Στην ιδανική περίπτωση η εγκατάσταση είναι τώρα ολοκληρωμένη.
   Το μόνο πράγμα που απομένει είναι να δημιουργήσουμε ένα ωραίο Εικονίδιο. Εξάγετε δύο εικόνες χρησιμοποιώντας το χαρακτηριστικό snoop του WHDLoad και το SP ή ένα freezer ή το U.A.E. και φτιάξτε το εικονίδιο. Προτείνεται η παλέτα 16 χρωμάτων του RomIcon.

### Πιθανά προβλήματα και ειδικές περιπτώσεις

#### Non standard trackloader

Μερικά προγράμματα χρησιμοποιούν δικό τους disk format. Αυτό σημαίνει ότι το DIC δεν μπορεί να δημιουργήσει disk images. Για τη δημιουργία αρχείων ή images από τέτοια δισκέτα προτείνεται η χρήση του RawDIC. Δείτε τις οδηγίες του RawDIC για περισσότερες πληροφορίες.

#### Πολλαπλές δισκέτες

Εάν το πρόγραμμα χρησιμοποιεί περισσότερες από μία δισκέτες το slave πρέπει να προωθήσει τις προσβάσεις δισκετών στο κατάλληλο αρχείο image. Μερικές φορές αυτό δεν είναι εύκολο. Μερικά προγράμματα υποστηρίζουν περισσότερους από έναν οδηγούς δισκέτας, οπότε μπορείτε να χρησιμοποιήσετε τον αριθμό του οδηγού για την επιλογή της δισκέτας. Τα περισσότερα προγράμματα χρησιμοποιούν ένα ID σε κάθε δισκέτα για να τις ξεχωρίσουν. Σε αυτή τη περίπτωση, χρησιμοποιούμε μία μεταβλητή που κρατάει τον αριθμό της δισκέτας, και σε κάθε πρόσβαση στο ID της δισκέτας (καθορίζουμε τέτοια πρόσβαση αναλύοντας τις παραμέτρους για το disk loader) αυξάνουμε τη μεταβλητή (αν φτάσουμε στη τελευταία δισκέτα, το μειώνουμε). Οπότε ελπίζουμε ότι ο loader θα διαβάσει το ID ξανά και ξανά μέχρι να εισαχθεί η σωστή δισκέτα. Ίσως υπάρχει ένα αίτημα από το πρόγραμμα για να εισάγει ο χρήστης την κατάλληλη δισκέτα, απενεργοποιήστε το.

#### Αποθήκευση Highscore

Δεν υπάρχουν πολλά να πούμε εδώ. Χρησιμοποιούμε την resload_SaveFile για να γράψουμε στη κατάλληλη περιοχή μνήμης στη δισκέτα. Αν θέλετε, κρυπτογραφήστε τη ώστε οι χαμένοι να μην μπορούν να τη διορθώσουν πολύ εύκολα. Δεν προτείνεται να γράψετε απευθείας σε disk images (χρησιμοποιώντας resload_SaveFileOffset), γιατί αν μερικές φορές κάτι πάει στραβά (π.χ. crash) είναι πιθανόν τα images να πάθουν ζημιά.

#### Savegames

Ο χειρισμός Savegame είναι ο ίδιος με τα highscore.

#### Προσβάσεις στο λειτουργικό σύστημα

Στο χρόνο που εκτελούνται το slave και το εγκατεστημένο πρόγραμμα, απολύτως κανένα OS δεν υπάρχει ή είναι προσβάσιμο ούτε έχει νόημα να προσπελάσουμε! Συνεπώς όλες οι προσβάσεις που επιχειρούνται από το εγκατεστημένο πρόγραμμα πρέπει να απενεργοποιηθούν. Αν δεν υπάρχουν πολλές, και δεν έχουν νόημα στο περιβάλλον του WHDLoad (όπως η exec.Disable() ή exec.SuperState()) απλά κάντε τις NOP (`$4e71`). Αν οι προσβάσεις έχουν κάποια σημαντική λειτουργία (όπως exec.DoIO()), προωθήστε τις στο Slave και εξομοιώστε τις. Αν υπάρχουν πολλές, δημιουργήστε μία απλή simple exec.library σε μία μη χρησιμοποιούμενη περιοχή μνήμης (εκκινήστε τη longword στη διεύθυνση `$4`). Μπορείτε να ελέγξετε το πηγαίο κώδικα για το Oscar.slave, που εξομοιώνει την exec.AllocMem(). Για να εντοπίσετε προσβάσεις στο OS, η αρχική execbase έχει οριστεί σε `$f0000001` με την πρόθεση όλες οι ρουτίνες που χρησιμοποιούν την execbase να δημιουργήσουν μία εξαίρεση "Address Error".
Εάν υπάρχει βαριά χρήση λειτουργιών του OS, χρησιμοποιούμε ένα από τα πακέτα kickemu που μπορούν να βρεθούν στο πακέτο whdload-dev. Υπάρχει ένα πακέτο για Kick 1.3 ('src/sources/whdload/kick13.s') και ένα για Kick 3.1 ('src/sources/whdload/kick31.s'). Αυτά τα πακέτα απαιτούν ένα αυθεντικό kickstart image και θα δημιουργήσουν ένα πλήρες περιβάλλον OS μέσα στο χώρο του WHDLoad. Συμβουλευτείτε επίσης το κατάλληλο readme που δίνεται για περισσότερες πληροφορίες.

### Συχνά προβλήματα συμβατότητας

#### Περιορισμένος χώρος διευθύνσεων σε 68000/68010/68ec020

Σε αυτούς τους επεξεργαστές ο χώρος διευθύνσεων είναι περιορισμένος στα 16 MB (`$000000...$ffffff`) γιατί αυτοί οι CPU έχουν μόνο 24 γραμμές διευθύνσεων. Σαν αποτέλεσμα όλες οι προσβάσεις σε μεγαλύτερες διευθύνσεις γίνονται στα χαμηλότερα 16 MB αγνοώντας τα ποιό σημαντικά 8 bits. Μερικά προγράμματα χρησιμοποιούν αυτά τα bits για να αποθηκεύουν δεδομένα, ή απλά ξεχνούν να τα καθαρίσουν. Σε έναν επεξεργαστή με πλήρες 4 GB χώρο διευθύνσεων όπως οι 68020/680ec30/68030/68040/68060 αυτό δεν θα λειτουργήσει, γιατί θα προσπελαστεί ολόκληρη η διεύθυνση 32-bit.
Για να το λύσουμε αυτό πρέπει να διορθώσουμε αυτές τις προσβάσεις και να τις προωθήσουμε στις κατάλληλες διευθύσεις.
Μερικές φορές ο λόγος για προσβάσεις σε περίεργες διευθύνσεις μπορεί να είναι ένας uninitialized δείκτης. Σε τέτοια περίπτωση μπορεί να βοηθήσει να καθαρίσουμε την `$400` - ws_BaseMemSize.

#### Διαφορετικά stackframes σε κάθε επεξεργαστή

Τα stackframes που δημιουργούνται από τον επεξεργαστή στα interrupts και εξαιρέσεις είναι διαφορετικά για τα μέλη της οικογένειας των 68k. Σε έναν 68000 ένα stackframe είναι 6 bytes, εκτός από Σφάλματα Διαύλου και Διευθύνσεων. Το stackframe περιέχει το αποθηκευμένο SR στον (a7) και το αποθηκευμένο PC στον (2,a7). Σε όλους τους άλλους επεξεργαστές (68010+) το ελάχιστο stackframe είναι 8 bytes και επιπλέον περιέχει τον αριθμό vector σαν word στον (6,a7). Αυτό το Four-Word stackframe format `$0` δημιουργείται για την "Trap #xx" και τα Interrupts σε 68010-68060. Τα stackframes σε άλλες εξαιρέσεις είναι διαφορετικά σε κάθε επεξεργαστή. Η εντολή RTE λειτουργεί διαφορετικά στον 68000 αντίθετα με τον 68010+. Σε έναν 68000 απλά επαναφέρει τον SR και PC και συνεχίζει την εκτέλεση του προγράμματος στην διεύθυνση που είχε διακοπεί. Στον 68010+ θα απελευθερώσει επιπλέον το stackframe ανάλογα το stackframe format.
Μερικά προγράμματα σπρώχνουν μία διεύθυνση (PC) και ένα SR και μετά εκτελούν μία εντολή RTE. Αυτό δουλεύει μόνο σε έναν 68000, σε 68010+ αυτό θα έχει απροσδιόριστα αποτελέσματα.
Αν ένα πρόγραμμα το κάνει, θα πρέπει να το φτιάξουμε. Μερικές φορές ίσως είναι αρκετό να αντικατασταθεί η RTE με ένα RTR.

#### MOVEM.x RL,-(An) σε 68000/010 και 68020/030/040

Υπάρχει διαφορά αν ο καταχωρητής που θα χρησιμοποιηθεί σε predecrement mode (RL) περιέχεται επίσης στη λίστα καταχωρητών. Για τους 68020, 68030 και 68040 η τιμή που γράφεται στη μνήμη είναι η αρχική τιμή του καταχωρητή decremented από μέγεθος της εργασίας. Οι 68000 και 68010 γράφουν την αρχική τιμή του καταχωρητή (not decremented).
Επειδή μία τέτοια κατασκευή δεν είναι πολύ χρήσιμη, κανένα λογισμικό δεν είναι γνωστό να έχει προβλήματα με αυτή.

### Γενικές οδηγίες για εγγραφή εγκαταστάσεων

- Μην αλλάζετε τους καταχωρητές CPU που υπάρχουν σε μεγαλύτερους επεξεργαστές όπως ο VBR ή ο CACR. Ο VBR είναι πάντα 0 από την μεριά του προγραμματιστή του Slave, ακόμα και αν έχει μετακινηθεί γιατί τα Auto Vectors (και τα Traps αν το Flag WHDL_EmulTrap is set) έχει οριστεί) εξομοιώνονται. Τα bits στον CACR είναι διαφορετικά για κάθε επεξεργαστή. Υπάρχει μόνο ένας έγκυρος τρόπος για την τροποποίηση των caches, use resload_SetCACR/SetCPU και τα bitdef's από την 'exec/execbase.i' και 'whdload.i'. Επίσης όλα τα πράγματα που βρίσκονται στο πρόγραμμα προς εγκατάσταση που χτυπούν αυτούς τους καταχωρητές πρέπει να απενεργοποιηθούν ή να παρακαμφθούν, διαφορετικά το WHDLoad δεν μπορεί να λειτουργήσει κανονικά!
- Ποτέ μην τροποποιείτε disk images. Αυτό έχει το πλεονέκτημα ότι αν κάποιος θέλει να ξεκινήσει το πρόγραμμα από δισκέτα το μόνο που έχει να κάνει είναι να γράψει τα images πίσω σε δισκέτα (με την προϋπόθεση ότι το πρόγραμμα τρέχει χωρίς διάφορες διορθώσεις, σίγουρα όχι η ποιό συχνή περίπτωση).
- Ποτέ μην χρησιμοποιείτε αυθεντικά πράγματα από το πρόγραμμα απευθείας στο slave (πρόβλημα copyright).
- Ενεργοποιήστε τα Caches μόνο αν είστε βέβαιοι ότι τρέχει σε όλους τους επεξεργαστές.
- Χρησιμοποιήστε όσο το δυνατόν λιγότερη μνήμη για την ws_BaseMemSize. Μερικοί άνθρωποι έχουν resident tags στο τέλος της μνήμη Chip, οπότε βοηθάει να χρησιμοποιήσετε μόνο `$1f0000` αντί για `$200000` και το WHDLoad μπορεί να χρησιμοποιήσει απόλυτη κατανεμημένη μνήμη.

### Συμβουλές & και κόλπα

#### Τι είναι καλύτερο, η χρήση diskimages ή αρχείων;

Μερικές φορές θα έχετε την επιλογή να χρησιμοποιήσετε disk images ή πραγματικά αρχεία. Και τα δύο έχουν τα πλεονεκτήματά τους. Η χρήση των disk images είναι συνήθως ο ευκολότερος και γρηγορότερος τρόπος για τη δημιουργία του Slave. Αλλά τα πραγματικά αρχεία είναι ποιό εύκολα cached (αν υπάρχει πολύ λίγη μνήμη ή η μνήμη είναι κατακερματισμένη). Ο απαραίτητος χώρος στο δίσκο θα είναι επίσης μικρότερος με πραγματικά αρχεία αντί για images. Χρησιμοποιήστε disk images μόνο αν υπάρχουν πολλά αρχεία (περισσότερα από 30).