*
* BootBlockWriter - put your own programs into the bootblock!
*
* created on 2/12/89  16:59:19  by Holger Gzella
*

                incdir "asm:"
                include "exec/exec_lib.i"
                include "libraries/dos_lib.i"
                include "intuition/intuition_lib.i"
                include "intuition/intuition.i"

Flags           EQU     WINDOWDRAG|WINDOWDEPTH|ACTIVATE
AFlags          EQU     GADGIMMEDIATE|RELVERIFY
SFlags          EQU     AFlags|TOGGLESELECT|STRINGCENTER

                lea     DosName,a1
                CALLEXEC OldOpenLibrary         * DOS öffnen
                move.l  d0,DosBase              * Zeiger sichern
                beq     DosLibFault             * Abbruch bei Fehler

                lea     IntuiName,a1
                CALLEXEC OldOpenLibrary         * Intuition öffnen
                move.l  d0,IntuiBase            * Zeiger sichern
                beq     MemFault                * Abbruch bei Fehler

                move.l  #1048,d0                * 1048 Bytes für den
                                                * Bootblock
                moveq.l #2,d1                   * CHIP-Memory!
                CALLEXEC AllocMem               * reservieren
                move.l  d0,Data                 * Zeiger sichern
                beq     MemFault                * Abbruch bei Fehler

                move.l  IntuiBase,a6
                lea     WindowData,a0
                jsr     _LVOOpenWindow(a6)      * Fenster öffnen
                move.l  d0,WindowPtr            * Zeiger sichern
                beq     FileFault               * oder Abbruch

*
* Hier wird über IDCMP gewartet, bis der Anwender
* irgendein Gadget angeklickt hat.
*

MessageLoop:    move.l  WindowPtr,a0
                move.l  $56(a0),a0
                move.l  a0,a5
                move.b  $0f(a0),d1
                moveq   #0,d0
                bset    d1,d0
                CALLEXEC Wait                   * auf Nachricht
                                                * warten

                move.l  a5,a0
                CALLEXEC GetMsg                 * Nachricht holen
                move.l  d0,a1
                move.l  $14(a1),d4              * diverse
                move.l  $18(a1),d5              * Parameter
                move.l  $1c(a1),a4              * sichern
                CALLEXEC ReplyMsg               * Nachricht beantworten

                cmpi.l  #GADGETUP,d4            * Gadget angeklickt?
                beq.s   ParseGadgets            * auswerten!

                bra.s   MessageLoop             * war wohl was anderes

*
* Diese Routine dient zur Feststellung
* des angeklickten Gadgets!
*

ParseGadgets:   move.l  $24(a4),d0              * Gadget-ID laden
                cmpi.w  #1,d0                   * Gadget Nr. 1?
                beq.s   Info                    * Version anzeigen

                cmpi.w  #2,d0                   * Gadget Nr. 2?
                beq     InstallDf0              * Bootblock auf DF0:

                cmpi.w  #3,d0                   * Gadget Nr. 3?
                beq     InstallDf1              * Bootblock auf DF1:
                cmpi.w  #4,d0                   * Gadget Nr. 4?
                beq     FileFault               * ENDE!

                bra.s   MessageLoop             * zurück

*
* Version anzeigen (mit einem Intuition-Automatik-Requester) ...
*

Info:           move.l  WindowPtr,a0
                lea     BodyText,a1             * Versionstext
                lea     LeftText,a2             * Text des linken
                                                * Gadgets
                lea     RightText,a3            * Text des rechten
                                                * Gadgets
                moveq.l #0,d0                   * nur anklicken
                moveq.l #0,d1                   *       "
                move.w  #350,d2                 * 350 Pixel breit
                moveq.w #100,d3                 * 100 Pixel hoch
                move.l  IntuiBase,a6
                jsr     _LVOAutoRequest(a6)     * und anzeigen

                bra     MessageLoop             * zurück

*
* Bootblock auf die Disk in DF0: schreiben ...
*

InstallDf0:     move.l  #0,Drive                * Drive=DF0:
                bra.s   LoadFile                * Datei laden
                                                * und schreiben

*
* Bootblock auf die Disk in DF1: schreiben ...
*

InstallDf1:     move.l  #1,Drive                * Drive=DF1:

*
* Im String-Gadget angegebene Datei laden ...
*

LoadFile:       move.l  DosBase,a6
                move.l  d0,d1
                move.l  FileName,d1             * aktueller Filename
                move.l  #1005,d2                * Datei existiert
                jsr     _LVOOpen(a6)            * öffnen!
                move.l  d0,FileHandle           * Handle sichern
                beq     MessageLoop             * Fehler!

                move.l  d0,d1                   * Handle nach d1
                move.l  Data,d2                 * Bootblock-Zeiger nach d2
                move.l  #1048,d3                * Größe nach d3
                jsr     _LVORead(a6)            * Datei lesen
                move.l  FileHandle,d1           * und
                jsr     _LVOClose(a6)           * schließen

                move.l  #BootHeader,a0          * Zeiger auf Boot-Header
                move.l  Data,a1                 * und Datenblock laden
                add.l   #24,a1                  * Offset 24
                move.l  #2,d0                   * 3 Longwords schreiben

*
* Nun wird der Bootblock-Header vor die Datei gesetzt ...
*

CopyBootHeader: move.l  (a0)+,(a1)+             * Header kopieren
                dbra    d0,CopyBootHeader       * bis alles kopiert

*
* Jetzt müssen wir die Bootblock-Checksumme berechnen ...
*

CompCheckSum:   move.l  Data,a0                 * Bootblock-Zeiger nach a0
                add.l   #24,a0                  * Offset addieren
                move.l  (a0),d0                 * Adresse nach d0
                add.l   #8,a0                   * 8 addieren
                move.l  #1016/4-1,d7            * Anzahl Longwords nach d7

AddLoop:        add.l   (a0)+,d0                * Longwords addieren
                bcs.s   Overflow                * Übertrag?

EndOverflow:    dbra    d7,AddLoop              * bis alle addiert

                addq.l  #1,d0                   * Zähler erhöhen
                neg.l   d0                      * negieren
                bra.s   GoForIt                 * und schreiben!

*
* Diese Stelle wird bei einem Übertrag
* aufgerufen. Bei jedem Übertrag wird die
* Checksumme um 1 erhöht.
*

Overflow:       add.l   #1,d0                   * Zähler erhöhen und
                bra.s   EndOverflow             * Übertrag ignorieren

*
* Jetzt wird der Bootblock auf die Diskette geschrieben!
*

GoForIt:        move.l  Data,a0                 * Zeiger auf Block suchen
                add.l   #28,a0                  * Zeiger auf Checksumme
                                                * richten
                move.l  d0,(a0)                 * Checksumme speichern

*
* Erstmal müssen wir einen MsgPort installieren ...
*

                sub.l   a1,a1
                CALLEXEC FindTask               * Task suchen

                move.l  d0,ReplyPort+$10        * MsgPort
                lea     ReplyPort,a1            * initialisieren und
                CALLEXEC AddPort                * einfügen

*
* Dann können wir das "trackdisk.device" öffnen ...
*

                lea     DiskIO,a1               * IOTrackDisk laden
                move.l  Drive,d0                * Laufwerks-Unit laden
                moveq   #0,d1                   * keine Spezial-Flags
                lea     DevName,a0              * Name des Devices
                CALLEXEC OpenDevice             * Device öffnen
                tst.l   d0                      * hat's geklappt?
                bne.s   Abort                   * nein ... zurück!

*
* Alles klar - der Bootblock kann nun mit
* unserem eigenen überschrieben werden!
*

                lea     DiskIO,a1               * IOTrackDisk laden
                move.l  #ReplyPort,14(a1)       * Nachrichten-Port laden
                move    #3,28(a1)               * Kommando: schreiben
                move.l  Data,a0                 * Daten: Bootblock
                add.l   #24,a0                  * plus 24
                move.l  a0,40(a1)               * Adresse setzen
                move.l  #1024,36(a1)            * Größe
                move.l  #0,44(a1)               * sonstiges
                CALLEXEC DoIO                   * ausführen

                lea     DiskIO,a1               * IOTrackDisk laden
                move    #4,28(a1)               * Kommando: update
                CALLEXEC DoIO                   * ausführen

                lea     DiskIO,a1               * IOTrackDisk laden
                move    #9,28(a1)               * Kommando: Motor
                move.l  #0,36(a1)               * ausschalten
                CALLEXEC DoIO                   * ausführen!

*
* Es müßte soweit alles klar sein. Wenn nicht
* (z.B. Disk schreibgeschützt), können wir an
* dieser Stelle auch nichts mehr ändern!
*

                lea     DiskIO,a1
                CALLEXEC CloseDevice            * Device schließen
Abort:          lea     ReplyPort,a1
                CALLEXEC RemPort                * Port entfernen

                bra     MessageLoop             * zurück!

*
* Ab hier steht der Rückkehr-Code ...
*

FileFault:      move.l  Data,a1                 * Bootblock-Daten
                move.l  #1048,d0                * 1048 Bytes
                CALLEXEC FreeMem                * freigeben

MemFault:       move.l  DosBase,a1
                CALLEXEC CloseLibrary           * Dos schließen

                move.l  IntuiBase,d0            * konnte Intuition
                tst.l   d0                      * geöffnet werden?
                beq.s   GoHome                  * nein!

DosLibFault:    move.l  WindowPtr,d0            * konnte das Window
                tst.l   d0                      * geöffnet werden?
                beq.s   IntuiFault              * nein!

                move.l  d0,a0
                move.l  IntuiBase,a6
                jsr     _LVOCloseWindow(a6)     * Window schließen

IntuiFault:     move.l   IntuiBase,a1
                CALLEXEC CloseLibrary           * Intuition schließen

GoHome:         moveq    #0,d0
                rts

*
* Datenteil ...
*

DosName:        dc.b "dos.library",0
 even
IntuiName:      dc.b "intuition.library",0
 even
DevName:        dc.b "trackdisk.device",0
 even

*
* Das ist der Kopf des Bootblocks
*

 even
BootHeader:     dc.b "DOS",0                    * bootfähige Diskette
                dc.l $00000000,$00000370        * Feld für Checksummme
                                                * und Rootblock
 even

FileName:       dc.l StrBuffer                  * Zeiger auf Dateinamen

FileHandle:     dc.l 0                          * Zeiger auf Dateihandle
WindowPtr:      dc.l 0                          * Zeiger auf Fenster

DosBase:        dc.l 0                          * Zeiger auf DOS
IntuiBase:      dc.l 0                          * Zeiger auf Intuition

Data:           dc.l 0                          * Zeiger auf Dateidaten

DiskIO:         ds.l 20                         * IOTrackDisk-Record
ReplyPort:      ds.l 8                          * MsgPort-Record

StrBuffer:      ds.b 60                         * 60 Zeichen für Filenamen
StrUndo:        ds.b 60                         * 60 Zeichen Undo-Speicher

Drive:          dc.l 0                          * Laufwerksnummer f. Install

*
* Jetzt kommt die Definition des Intuition-Windows
*

 even
WindowData:     dc.w 99,98,442,60               * Position, Breite, Höhe
                dc.b 0,1                        * Farben
                dc.l GADGETUP                   * IDCMP-Flag
                dc.l Flags                      * Window-Flags
                dc.l Gadget1                    * Zeiger auf 1. Gadget
                dc.l 0                          * Standard-Checkmark
                dc.l Titel                      * Zeiger auf Window-Titel
                dc.l 0,0                        * kein eigener Screen/Bitmap
                dc.w 0,0,0,0                    * keine Mindest-/Max.-Größen
                dc.w WBENCHSCREEN               * Workbench-Screen

Titel:          dc.b "BootBlockWriter -- done by Holger Gzella",0
 even                                           * Window-Titel

*
* Nun folgen die Gadget-Definitionen ...
*

Gadget1:        dc.l Gadget2                    * nächstes Gadget
                dc.w 10,20,98,10                * Position und Ausmaße
                dc.w 0,AFlags,1                 * keine Special-Flags
                                                * und BoolGadget
                dc.l GBorder                    * Gadget-Rahmen
                dc.l 0                          * kein Select-Image
                dc.l Text1                      * Zeiger auf Gadget-Text
                dc.l 0,0                        * weder Exclude noch
                                                * Special-Info
                dc.w 1                          * Gadget-ID
                dc.l 0                          * keine Special-Daten

Gadget2:        dc.l Gadget3                    * siehe oben
                dc.w 118,20,98,10
                dc.w 0,AFlags,1
                dc.l GBorder
                dc.l 0
                dc.l Text2
                dc.l 0,0
                dc.w 2
                dc.l 0

Gadget3:        dc.l Gadget4
                dc.w 226,20,98,10
                dc.w 0,AFlags,1
                dc.l GBorder
                dc.l 0
                dc.l Text3
                dc.l 0,0
                dc.w 3
                dc.l 0

Gadget4:        dc.l Gadget5
                dc.w 334,20,98,10
                dc.w 0,AFlags,1
                dc.l GBorder
                dc.l 0
                dc.l Text4
                dc.l 0,0
                dc.w 4
                dc.l 0

Gadget5:        dc.l 0
                dc.w 10,40,423,10
                dc.w 0,SFlags,4                 * String-Gadget!
                dc.l SBorder
                dc.l 0
                dc.l 0
                dc.l 0,Special                  * kriegt ein Special-Info
                dc.w 5
                dc.l 0

Special:        dc.l StrBuffer                  * Speicher für Filenamen
                dc.l StrUndo                    * Speicher für Undo-Option
                dc.w 0,60                       * Cursor bei 0 u. 60 Zeichen
                dc.w 0,0,0,0,0,0                * Infos für Cursor und so
                dc.l 0                          * kein LONGINT-Gadget!
                dc.l 0                          * Standard-Keymap

*
* Ab hier stehen die ganzen Intui-Texte für die Gadgets u. Requester ...
*

Text1:          dc.b 1,0,0                      * Farben und Draw-Modus JAM1
 even
                dc.w 1,2,0,0                    * Position u. Standard-Font
                dc.l Text1Text                  * Zeiger auf eigentliche Text
                dc.l 0                          * kein folgender Intui-Text
Text1Text:      dc.b "  VERSION!  ",0           * Gadget-Text
 even

Text2:          dc.b 1,0,0                      * siehe oben
 even
                dc.w 1,2,0,0
                dc.l Text2Text
                dc.l 0
Text2Text:      dc.b "Install DF0:",0
 even

Text3:          dc.b 1,0,0
 even
                dc.w 1,2,0,0
                dc.l Text3Text
                dc.l 0
Text3Text:      dc.b "Install DF1:",0
 even

Text4:          dc.b 1,0,0
 even
                dc.w 1,2,0,0
                dc.l Text4Text
                dc.l 0
Text4Text:      dc.b "    EXIT    ",0
 even

BodyText:       dc.b 0,1,0
 even
                dc.w 10,10,0,0
                dc.l BodyTextText
                dc.l BodyText2
BodyTextText:   dc.b "BootBlockWriter v1.00 by Holger Gzella",0
 even

BodyText2:      dc.b 0,1,0
 even
                dc.w 22,30,0,0
                dc.l BodyTextText2
                dc.l BodyText3
BodyTextText2:  dc.b "Put your own programs into a disk's",0
 even

BodyText3:      dc.b 0,1,0
 even
                dc.w 24,40,0,0
                dc.l BodyTextText3
                dc.l BodyText4
BodyTextText3:  dc.b "bootblock, but remember that they",0
 even

BodyText4:      dc.b 0,1,0
 even
                dc.w 24,50,0,0
                dc.l BodyTextText4
                dc.l 0
BodyTextText4:  dc.b "have to be assembled PC-relative!",0
 even

LeftText:       dc.b 0,1,0
 even
                dc.w 5,3,0,0
                dc.l LeftTextText
                dc.l 0
LeftTextText:   dc.b "  Logo!  ",0
 even

RightText:      dc.b 0,1,0
 even
                dc.w 5,3,0,0
                dc.l RightTextText
                dc.l 0
RightTextText:  dc.b "  Klar!  ",0
 even

*
* Es folgen die Daten für die Gadget-Rahmen ...
*

GBorder:        dc.w -1,-1                      * Position
                dc.b 1,0,0                      * Farben und JAM1
                dc.b 5                          * 5 Koordinatenpaare
                dc.l BordTable                  * Zeiger auf Koordinaten
                dc.l 0                          * kein weiterer Border

SBorder:        dc.w -1,-1                      * siehe oben
                dc.b 1,0,0
                dc.b 5
                dc.l SBordTable
                dc.l 0

BordTable:      dc.w 0,0,99,0,99,11,0,11,0,0    * Koordinaten
SBordTable:     dc.w 0,0,424,0,424,11,0,11,0,0

                END

