;=====================
;  BootLetter  V 1.0
;---------------------
; Assembler-Quelltext
;     (PROFIMAT)
;---------------------
;(c) B.van Rüschen
;    Norderstr. 34
;    2910 Westerstede
;=====================

;### MACROS ###

_LVOForbid   = -132          ;Offsets für
_LVOFindTask = -294          ;Systemroutinen
_LVOGetMsg   = -372
_LVOReplyMsg = -378 
_LVOWaitPort = -384 

PR_CLI     = 172
PR_MsgPort = 92
ExecBase   = 4

CALL:MACRO $\1               ;CALL  Systemroutine
 jsr _LVO\1(a6)              ;----  aufrufen
 ENDM

INIT_AMIGA:MACRO             ;INIT_AMIGA
 move.l ExecBase,a6          ;----------
 sub.l a1,a1                 ;eigenen Task holen
 CALL FindTask
 move.l d0,MyTask            ;und Pointer ablegen
 move.l d0,a4
 tst.l PR_CLI(a4)
 bne.s \1
 lea PR_MsgPort(a4),a0       ;Start von Workbench
 CALL WaitPort
 lea PR_MsgPort(a4),a0       ;Startup-Message
 CALL GetMsg                 ;holen
 move.l d0,WBenchMsg
\1:                          ;Start von CLI
 ENDM

EXIT_AMIGA:MACRO             ;EXIT_AMIGA
 tst.l WBenchMsg             ;----------
 beq.s \1                    ;bei Start
 CALL Forbid                 ;von Workbench
 move.l WBenchMsg,a1         ;Message abmelden
 CALL ReplyMsg
\1:
 moveq #0,d0                 ;Return-Code löschen
 rts
 ENDM

 BSS
WBenchMsg: DC.L 0
MyTask:    DC.L 0
 TEXT


;### HAUPTPROGRAMM ###

_LVOFindResident   = -96     ;Offsets für
_LVODisable        = -120    ;Systemroutinen
_LVOEnable         = -126
_LVOAllocMem       = -198
_LVOFreeMem        = -210
_LVOAddPort        = -354
_LVORemPort        = -360
_LVOOldOpenLibrary = -408 
_LVOCloseLibrary   = -414
_LVOOpenDevice     = -444
_LVOCloseDevice    = -450
_LVODoIO           = -456
_LVOOpen           = -30
_LVOClose          = -36
_LVORead           = -42
_LVOWrite          = -48
_LVODeleteFile     = -72
_LVOExecute        = -222
_LVOText           = -60
_LVOOpenFont       = -72
_LVOMove           = -240
_LVOSetRGB4        = -288
_LVOSetAPen        = -342
_LVOSetDrMd        = -354
_LVOCloseWindow    = -72
_LVODisplayAlert   = -90
_LVOOpenWindow     = -204
_LVORectFill       = -306
_LVORefreshGList   = -432

MEMF_CHIP     = 1<<1         ;Definitionen
MEMF_CLEAR    = 1<<16
MODE_OLDFILE  = 1005
MODE_NEWFILE  = 1006
CMD_WRITE     = 3
CMD_UPDATE    = 4
TD_MOTOR      = 9
TD_PROTSTATUS = 15
RP_COMPLEMENT = 2
ScreenSize    = 40*17*16
GadgetSize    = 6*74+16*80+36+42
BfSize        = 20000
FileName   EQUR Gadgets+GadgetSize-42
BootTxName EQUR RunEd+7

 jmp Startup(pc)             ;Libs,Ed,Window,
                             ;Gadgets,Text

;                        ===> HAUPTSCHLEIFE
Main:
 lea Gadgets,a5              ;Prop-Gadgets
 moveq #1,d7
SetCol:
 asl.l #8,d6
 move.l WbViewPort(pc),a0
 move d7,d0
 eor #1,d0
 move.b 48(a5),d1            ;Werte der
 lsr.b #4,d1                 ;Prop-Gadgets
 or.b d1,d6                  ;lesen und
 asl.l #4,d6                 ;zu Farbwerten
 move.b 74+48(a5),d2         ;umwandeln
 lsr.b #4,d2
 or.b d2,d6
 asl.l #4,d6
 move.b 148+48(a5),d3
 lsr.b #4,d3
 or.b d3,d6
 move.l GfxBase(pc),a6
 CALL SetRGB4                ;Farben setzen
 add #222,a5
 dbra d7,SetCol
 move.l d6,ActualCol         ;Farben sichern
 btst #0,ParFlags(pc)
 bne.s StoreCol
 swap d6
StoreCol:                    ;Farben umformen
 move ColMask(pc),d0         ;und in
 or d0,d6                    ;Interrupt-Routine
 move d6,ColValue1+2         ;schreiben
 swap d6
 move d6,ColValue2
 and #$111,d0                ;Abstufungs-Wert
 move d0,ColSub+2            ;setzen

 move.l MyWindow(pc),a0      ;IntuiMessage
 move.l 86(a0),a0            ;holen und
 move.l ExecBase,a6          ;auswerten
 CALL GetMsg
 tst.l d0
 beq Main
 move.l d0,a1
 move.l d0,a5                ;Message abmelden
 CALL ReplyMsg
 move 22(a5),d0              ;IDCMP-Flags
 cmp.l #$100,$6c             ;Interrupt-Routine
 bne.s AskFlag                    ;angeschaltet?
 move #$4e71,IntOnOff-IntPrg+$100 ;Ja, dann aus
 clr.l d0                         ;$4e71 = NOP
AskFlag:
 cmp #$200,d0                ;Close-Gadget?
 beq ExitMain
 cmp #$40,d0                 ;sonstiges Gadget
 bne Main                    ;angewählt?
 move.l 28(a5),a5            ;Ja, dann Gadget-
 move 38(a5),d0              ;Nummer holen
 cmp #15,d0                  ;Parameter oder Text
 bcc.s NoChange              ;geändert?
 clr.b SaveFlag              ;Ja, merken
NoChange:
 clr.l Error                 ;Fehler-Var. löschen
 move.b ParFlags(pc),OldFlags;Gadget-Flags retten

;                        ===> GADGETS ABFRAGEN

 cmp #6,d0                   ;R-Gadget angeklickt?
 bne.s Gadget2               ;Ja, dann Maske für
 eor #$f00,ColMask           ;Abstufung ändern
Gadget2:
 cmp #7,d0                   ;G-Gadget angeklickt?
 bne.s Gadget3               ;Ja, dann Maske für
 eor #$0f0,ColMask           ;Abstufung ändern
Gadget3:
 cmp #8,d0                   ;B-Gadget angeklickt?
 bne.s Gadget4               ;Ja, dann Maske für
 eor #$00f,ColMask           ;Abstufung ändern

Gadget4:
 cmp #9,d0                   ;"Abstufung auf"
 bne.s Gadget5               ;angeklickt?
 bchg #0,ParFlags            ;Ja, merken
Gadget5:
 cmp #10,d0                  ;Abschaltungs-Gadget
 bne.s Gadget6               ;angeklickt?
 bchg #1,ParFlags            ;Ja, merken
Gadget6:
 cmp #11,d0                  ;Scrolling-Gadget
 bne.s Gadget7               ;angeklickt?
 bchg #7,ParFlags            ;Ja, merken

Gadget7:
 cmp #12,d0                  ;"<->" angeklickt?
 bne.s Gadget8
 move.l ActualCol(pc),d6     ;Aktuelle Farbe
 jsr SetProp2(pc)            ;Props vertauschen
 jsr RefreshProp(pc)         ;und refreshen
 clr.l d0

Gadget8:
 cmp #15,d0            ;"Boot-Text ansehen"
 bne.s Gadget9         ;angeklickt?
 jsr TestTx(pc)        ;Text vorhanden?
 bne.s Gadget9         ;Nein, verzweigen!
 lea IntOnOff(pc),a5   ;Abschaltungs-Befehl retten
 move.b (a5),d7        ;"bra"($60) = Boot-Text ein
 move.b #$60,(a5)      ;Abschaltung dann mit "nop"
 jsr BootPrg(pc)       ;Boot-Programm starten
 move.b d7,(a5)        ;Befehl zurücksetzen

Gadget9:
 cmp #16,d0                  ;"BootBlock auf df0:"
 bne Gadget10                ;angeklickt?
 jsr TestTx(pc)              ;Text vorhanden?
 bne Gadget10
 lea BootStat1(pc),a4
 jsr PrintStat(pc)           ;Status ausgeben
 clr.l ChkSum
 clr.l d0
 move #255,d1
 lea BootBlock(pc),a0        ;Checksumme
MakeChkSum:                  ;berechnen...
 add.l (a0)+,d0
 bcc.s NoSumAdd
 addq.l #1,d0
NoSumAdd:
 dbra d1,MakeChkSum
 moveq #-1,d1
 sub.l d0,d1
 move.l d1,ChkSum            ;...und ablegen
 lea ReplyPort,a1
 move.l MyTask,16(a1)        ;Port
 CALL AddPort                ;installieren
 lea IOExtTD,a1
 moveq #0,d0                 ;df0:
 clr.l d1
 lea TD_NAME(pc),a0          ;Trackdisk-Device
 CALL OpenDevice             ;öffnen
 tst.l d0                    ;Fehler?
 bne SetTDErr                ;Dann verzweigen!
 lea IOExtTD,a1
 move.l #ReplyPort,14(a1)    ;Schreibschutz
 move #TD_PROTSTATUS,28(a1)  ;testen...
 clr.l 36(a1)
 CALL DoIO
 lea IOExtTD,a1
 moveq #28,d6
 tst.l 32(a1)                ;gesetzt?
 bne.s MotorOff              ;Dann verzweigen!
 move #CMD_WRITE,28(a1)
 move.l #BootBlock,40(a1)
 move.l #2*512,36(a1)        ;BootBlock in
 clr.l 44(a1)                ;Trackdisk-Buffer
 CALL DoIO                   ;schreiben
 lea IOExtTD,a1
 move.b 31(a1),d6            ;Fehler?
 bne.s MotorOff              ;Dann verzweigen!
 move #CMD_UPDATE,28(a1)
 clr.l 36(a1)                ;BootBlock auf
 CALL DoIO                   ;Disk schreiben
 lea IOExtTD,a1
 move.b 31(a1),d6
MotorOff:
 move #TD_MOTOR,28(a1)       ;Motor aus
 clr.l 36(a1)
 CALL DoIO
 lea ReplyPort,a1
 CALL RemPort                ;Port löschen
 lea IOExtTD,a1
 CALL CloseDevice            ;Device schließen
 tst.b d6                    ;Fehler vorgefallen?
 beq.s NoTDError
 move.l #WriteProt,Error     ;Schreibschutz
 cmp.b #28,d6                ;war gesetzt
 beq SetGad
SetTDErr:
 move.l #DiskErr,Error       ;sonstiger Fehler
 bra SetGad
NoTDError:                   ;Muß CLI-Befehl
 btst #1,ParFlags(pc)        ;zur Abschaltung
 beq SetOK                   ;geschrieben werden?
 lea BootStat2(pc),a4
 jsr PrintStat(pc)           ;Ja, Status ausgeben
 move.l #BootOffName,d1
 lea BootOff(pc),a5          ;"BootOff" auf
 moveq #60,d6                ;Disk schreiben
 jsr CopyMemToFile(pc)
 beq SetOK                   ;Fehler?

Gadget10:
 cmp #13,d0                  ;"Text editieren"
 bne.s Gadget11              ;angeklickt?
 jsr ClrStat(pc)             ;Statuszeile löschen
 lea RunEd(pc),a5
 jsr MyEx(pc)                ;Ed aufrufen
 beq.s SetBootTx             ;Boot-Text setzen

Gadget11:
 cmp #14,d0                  ;"Text löschen"
 bne.s Gadget12              ;angeklickt?
 jsr Sure(pc)                ;Sicherheitsabfrage
 beq.s Gadget12
 jsr DeleteTx(pc)            ;Text löschen
 st.b TxClrFlag              ;Kein Text vorhanden!
 bra SetOK                   ;OK ausgeben

Gadget12:
 cmp #17,d0                  ;"Text laden"
 bne Gadget13                ;angeklickt?
 jsr ClrStat(pc)             ;Statuszeile löschen
 move.l #FileName,d1
 move.l #BootTxName,d7       ;File ins RAM
 jsr FileCopy(pc)            ;kopieren
 bne Gadget13                ;Fehler?
 jsr SetParName(pc)
 jsr CopyFileToMem(pc)       ;Parameter-File laden
 clr.b (a4)                  ;alter Filename
 move.l ActualCol(pc),d6
 jsr SetProp(pc)             ;Props setzen
 jsr RefreshProp(pc)         ;und refreshen
 st.b SaveFlag               ;keine Text-Änderung
SetBootTx:
 move.l #BootTxName,d1
 jsr OpenOld(pc)             ;BootText öffnen
 clr.l Error
 tst.l d0
 beq.s Gadget13              ;Fehler?
 clr.b TxClrFlag             ;Text vorhanden!
 move.l d0,d7
 lea BootTx(pc),a5           ;BootText Startadr.
 move #600-1,d0
ClrBootTx:
 clr.b (a5,d0)               ;BootText löschen
 dbra d0,ClrBootTx
ReadTx:
 moveq #0,d6                 ;Zeichen-Pos.in Zeile
ReadTxLoop:
 move.l d7,d1
 move.l #CharBf,d2
 moveq #1,d3
 CALL Read                   ;1 Zeichen lesen
 tst.l d0                    ;File-Ende?
 beq.s ExitRead              ;Dann verzweigen!
 not.l d0                    ;Fehler?
 beq.s ExitRead              ;Dann verzweigen!
 move.b CharBf(pc),d1        ;Zeichen auswerten
 cmp #$a,d1                  ;CR? Dann neue Zeile
 beq.s NextLine
 addq.b #1,d6
 bmi.s NextLine              ;Kein Zeilenende?
 cmp #41,d6                  ;unter 41 Zeichen?
 bcs.s StoreChar             ;Ja, dann ablegen
 move.l #CutTx,Error         ;Nein, "Schnipp!"
 bra.s ReadTxLoop            ;nicht ablegen
StoreChar:
 sub.b #32,d1                ;Zeichencode
 bpl.s CharOK                ;umformen
 sub.b #32,d1
CharOK:
 move.b d1,-1(a5,d6)         ;Zeichen ablegen
 bra.s ReadTxLoop
NextLine:
 add #40,a5                  ;Neue Zeile
 cmp.l #BootTx+600,a5        ;BootText-Ende
 bne.s ReadTx                ;erreicht?
ExitRead:
 move.l #"©bvr",BootBlock+1020
 jsr MyClose(pc)             ;Schließen
 beq.s SetOK                 ;OK ausgebn

Gadget13:
 cmp #18,d0                  ;"Text speichern"
 bne.s Gadget14              ;angeklickt?
 jsr TestTx(pc)              ;Text vorhanden?
 bne.s Gadget14
 jsr ClrStat(pc)             ;Statuszeile löschen
 move.l #BootTxName,d1
 move.l #FileName,d7         ;File auf Disk
 jsr FileCopy(pc)            ;speichern
 bne.s Gadget14              ;Fehler?
 jsr SetParName(pc)          ;Parameter-File
 jsr CopyMemToFile(pc)       ;speichern
 clr.b (a4)                  ;alter File-Name
 tst.l Error                 ;Fehler?
 bne.s Gadget14              ;Ja, verzweigen
 st.b SaveFlag               ;keine Text-Änderung
 bra.s SetOK                 ;OK ausgeben

Gadget14:
 cmp #19,d0                  ;"CLI" angeklickt?
 bne.s Gadget15
 lea NewCli(pc),a5           ;Dann "NewCli"
 jsr MyEx(pc)                ;starten
 beq.s SetOK                 ;und OK ausgeben

Gadget15:
 cmp #20,d0                  ;"Info" angeklickt?
 bne.s SetGad
 lea Info(pc),a0             ;Dann Info-Alert
 jsr Alert(pc)               ;ausgeben

;                        ===> GADGETS SETZEN
SetOK:
 move.l #OK,Error            ;Error auf OK
SetGad:
 move ColMask(pc),d6         ;RGB-Abstufung holen
 move RGB(pc),d5             ;und mit bisheriger
 eor d5,d6                   ;Einstellung der RGB-
 btst #8,d6                  ;Schalter verknüpfen
 beq.s TstGad2
 moveq #111-2,d7             ;Wenn Flag gesetzt
 jsr Rect(pc)                ;ist, dann Zustand
 bchg #8,d5                  ;des "R" ändern
TstGad2:
 btst #4,d6
 beq.s TstGad3
 move #111+24-2,d7           ;Wenn Flag gesetzt
 jsr Rect(pc)                ;ist, dann Zustand
 bchg #4,d5                  ;des "G" ändern
TstGad3:
 btst #0,d6
 beq.s TstGad4
 move #111+48-2,d7           ;Wenn Flag gesetzt
 jsr Rect(pc)                ;ist, dann Zustand
 bchg #0,d5                  ;des "B" ändern
TstGad4:
 move d5,RGB                 ;RGB-Zustand merken
 move.b OldFlags(pc),d6      ;alter Zustand
 move.b ParFlags(pc),d5      ;neuer Zustand
 eor.b d5,d6                 ;Gad-Flags verknüpfen
 btst #0,d6                  ;Flag geändert?
 beq.s TstGad5               ;Nein, verzweigen!
 move.l #$1820180,d0
 lea ShadeBack(pc),a5        ;Testen, ob Hinter-
 btst #0,d5                  ;grund oder Textfarbe
 beq.s SetGad4               ;für Abstufung ange-
 swap d0                     ;wählt ist, und dem-
 lea ShadeText(pc),a5        ;entsprechend Gadget-
SetGad4:                     ;Text und Farb-
 move d0,ColReg1+4           ;register setzen
 swap d0
 move d0,ColReg2
 jsr Print(pc)
TstGad5:
 btst #1,d6                  ;Flag geändert?
 beq.s TstGad6               ;Nein, verzweigen!
 moveq #$67,d0
 lea IntOff1(pc),a5          ;Testen,ob Auto- oder
 btst #1,d5                  ;CLI-Abschaltung an-
 beq.s SetGad5               ;gewählt ist, und
 moveq #$60,d0               ;dementsprechend
 lea IntOff2(pc),a5          ;Gadget-Text setzen
SetGad5:                     ;und Interrupt-
 move.b d0,IntOnOff          ;Routine anpassen
 jsr Print(pc)               ;$60=bra; $67=beq
TstGad6:
 tst.b d6                    ;Flag geändert?
 bpl.s ChkErr                ;Nein, verzweigen!
 moveq #$65,d0
 moveq #-1,d1                ;Testen, ob Scrolling
 lea ScrollOn(pc),a5         ;ein- oder ausge-
 tst.b d5                    ;schaltet ist, und
 bpl.s SetGad6               ;dementsprechend
 moveq #$60,d0               ;Gadget-Text setzen
 moveq #$2f,d1               ;und Interrupt-
 lea ScrollOff(pc),a5        ;Routine anpassen
SetGad6:                     ;$60=bra; $65=bcs
 move.b d0,ScrollOnOff
 move.b d1,VertPos
 jsr Print(pc)
ChkErr:
 move.l Error(pc),d0         ;Fehler?
 beq.s GoMain                ;Nein, Hauptschleife
 move.l d0,a4
 jsr PrintStat(pc)           ;Fehler ausgeben
GoMain:
 bra Main

;                        ===> PROGRAMM BEENDEN
ExitMain:
 jsr Sure(pc)                ;Sicherheitsabfrage
 beq Main
 move.l GfxBase(pc),a6
 moveq #1,d7
 move.l ColBf(pc),d6
RestoreCol:                  ;Alte Farben
 move.l WbViewPort(pc),a0    ;wiederherstellen
 move d7,d0
 move d6,d3
 and #$f,d3
 lsr #4,d6
 move d6,d2
 and #$f,d2
 lsr #4,d6
 move d6,d1
 and #$f,d1
 swap d6
 CALL SetRGB4
 dbra d7,RestoreCol

 move.l IntuitionBase(pc),a6
 move.l MyWindow(pc),a0      ;Window schließen
 CALL CloseWindow

DeleteFiles:
 jsr DeleteTx(pc)
 move.l #MyEdName,d1
 CALL DeleteFile             ;Ed löschen

 move.l ExecBase,a6
 move.l IntuitionBase(pc),a1
 CALL CloseLibrary           ;Librarys schließen
 move.l GfxBase(pc),a1
 CALL CloseLibrary
 move.l DosBase(pc),a1
 CALL CloseLibrary

 EXIT_AMIGA


;### UNTERPROGRAMME ###

;                        ===> PROPS EINSTELLEN
SetProp:
 swap d6                     ;Farben in d6
SetProp2:
 lea Gadgets,a0
 moveq #5,d0
 moveq #17,d1
 moveq #0,d7
SetPropLoop:
 move d1,4(a0)               ;LeftEdge
 move #22,6(a0)              ;TopEdge
 move #14,8(a0)              ;Width
 move #64,10(a0)             ;Height
 move #3,14(a0)              ;Activation
 move #3,16(a0)              ;GadgetType
 move d7,38(a0)              ;GadgetID
 rol.l #4,d6
 move d6,48(a0)
 and #$f000,48(a0)
 or #$0800,48(a0)
 move #$fff,52(a0)           ;VertBody
 add #44,a0
 move #5,(a0)                ;Flags
 move.l a0,-10(a0)           ;SpecialInfo
 add #22,a0
 move.l a0,-48(a0)           ;GadgetRender
 addq #8,a0
 move.l a0,-74(a0)           ;NextGadget
 addq #1,d7
 add #24,d1
 cmp #3,d0                   ;3 Gadgets ge-
 bne.s NextProp              ;setzt?
 add #110,d1                 ;dann Pos. ändern
 rol.l #4,d6                 ;Nächste Farbe
NextProp:
 dbra d0,SetPropLoop         ;Nächstes Gadget
 rts

;                        ===> PROPS REFRESHEN
RefreshProp:
 lea Gadgets,a0              ;Prop-Gadgets
 move.l MyWindow(pc),a1
 sub.l a2,a2
 moveq #6,d0                 ;6 Gadgets refreshen
 move.l IntuitionBase(pc),a6
 jmp _LVORefreshGList(a6)

;                        ===> STATUSZEILE LÖSCHEN
ClrStat:
 lea Clear(pc),a5            ;Spaces
 jmp Print(pc)               ;ausgeben

;                        ===> STATUS AUSGEBEN
PrintStat:
 jsr ClrStat(pc)             ;Statuszeile löschen
 move.l a4,a5                ;Status ausgeben

;                        ===> TEXT AUSGEBEN
Print:
 movem.l d0-d7/a0-a4/a6,-(sp);Register ablegen
 moveq #1,d7                 ;Schrift + Schatten
PrintLoop:
 move.l a5,a4                ;Zeiger auf Text
 move.l d7,d0                ;JAM1 / JAM2
 move.l MyRastPort(pc),a1
 move.l GfxBase(pc),a6
 CALL SetDrMd                ;Zeichenmodus
 move.l d7,d0                ;weiß / schwarz
 addq #1,d0
 CALL SetAPen                ;Zeichenfarbe
 clr.l d0
 clr.l d1                    ;Position setzen
 move.b (a4)+,d0
 move.b (a4)+,d1
 add.b d7,d0                 ;Schrift verschieben
 CALL Move                   ;Position setzen
 moveq #-1,d0
 move.l a4,a0                ;Anzahl der aus-
GetTxEnd:                    ;zugebenden Zeichen
 addq #1,d0                  ;ermitteln
 tst.b (a4)+
 bne.s GetTxEnd
 CALL Text                   ;Text ausgeben
 dbra d7,PrintLoop           ;auch Schatten setzen
 move.l a4,a5                ;neuer Zeiger nach a5
 movem.l (sp)+,d0-d7/a0-a4/a6;Register holen
 rts

;                        ===> RECHTECK INVERTIEREN
Rect:
 moveq #RP_COMPLEMENT,d0     ;invertieren
 move.l MyRastPort(pc),a1
 move.l GfxBase(pc),a6
 CALL SetDrMd                ;Zeichenmodus
 move.l d7,d0
 moveq #23+60-8,d1
 moveq #11,d2                ;Positionen setzen
 add.l d7,d2                 ;und
 moveq #23+60-8+10,d3
 jmp _LVORectFill(a6)        ;Rechteck invertieren

;                        ===> SICHERHEITSABFRAGE
Sure:
 move.b SaveFlag(pc),d0      ;Text nicht geändert?
 bne.s ExitSure              ;Dann kein Alert
 move.b TxClrFlag(pc),d0     ;Kein Text?
 bne.s ExitSure              ;Dann kein Alert!
 lea SureTx(pc),a0
 jsr Alert(pc)               ;Alert ausgeben
ExitSure:
 tst.b d0                    ;Taste prüfen
 rts

;                        ===> ALERT DARSTELLEN
Alert:
 move.l ExecBase,a6
 CALL Disable                ;Interrupts aus
 moveq #0,d0                 ;Recovery
 moveq #33,d1                ;Höhe: 33
 move.l IntuitionBase(pc),a6
 CALL DisplayAlert           ;Alert darstellen
 move.l ExecBase,a6
 jmp _LVOEnable(a6)          ;Interrupts ein

;                        ===> FILES KOPIEREN
FileCopy:
 tst.b FileName              ;Filename vorhanden?
 bne.s NoNameErr
 move.l #AskTxName,Error     ;Nein, Fehler
 bra.s NoClose
NoNameErr:
 jsr OpenOld(pc)             ;Quelle öffnen
 beq.s NoClose
 move.l d7,d1
 move.l d0,d7                ;Handle nach d7
 jsr OpenNew(pc)             ;Ziel öffnen
 beq.s MyClose
 move.l d0,d6                ;Handle nach d6
FileCopyLoop:
 move.l d7,d1                ;Quell-Handle
 move.l #FileBf,d2           ;Startadresse
 move.l #BfSize,d3           ;max. 20000 Bytes
 CALL Read
 move.l d0,d3                ;Länge = neue Länge
 beq.s ExitFileCopy2         ;Ende?
 not.l d0
 beq.s ExitFileCopy          ;Fehler?
 move.l d6,d1                ;Ziel-Handle
 move.l #FileBf,d2           ;Startadresse
 CALL Write
 not.l d0
 bne.s FileCopyLoop          ;Fehler? Nein, weiter
ExitFileCopy:
 jsr TestDosErr(pc)          ;Fehler prüfen
ExitFileCopy2:
 move.l d6,d1
 CALL Close                  ;Ziel schließen
 bra.s MyClose               ;Quelle schließen

;                        ===> FILE EINLESEN
CopyFileToMem:
 jsr OpenOld(pc)             ;Öffnen
 beq.s NoClose               ;Fehler?
 move.l a5,d2
 move.l d6,d3                ;Parameter setzen
 move.l d0,d7
 move.l d0,d1
 CALL Read
 bra.s ExitCopy              ;Schließen

;                        ===> FILE SCHREIBEN
CopyMemToFile:
 jsr OpenNew(pc)             ;Öffnen
 beq.s NoClose               ;Fehler?
 move.l a5,d2
 move.l d6,d3                ;Parameter setzen
 move.l d0,d7
 move.l d0,d1
 CALL Write
ExitCopy:
 move.l d0,d6                ;Länge nach d6
 not.l d0
 jsr TestDosErr(pc)          ;Fehler?

;                        ===> CLOSE
MyClose:
 move.l d7,d1                ;Filehandle aus d7
 CALL Close                  ;Schließen
NoClose:
 clr.l d0                    ;für Abfrage löschen
 tst.l Error                 ;Fehler prüfen
 rts

;                        ===> OPEN
OpenNew:
 move.l #MODE_NEWFILE,d2     ;Neues File öffnen
 bra.s OpenNewJmp
OpenOld:
 move.l #MODE_OLDFILE,d2     ;Altes File öffnen
OpenNewJmp:
 move.l DosBase(pc),a6
 CALL Open
TestDosErr:
 tst.l d0                    ;Fehler?
 bne.s NoDosErr              ;Nein, verzweigen
SetDosErr:
 move.l #DosErr,Error        ;Ja, "DOS-Fehler"
NoDosErr:
 tst.l d0                    ;Fehler prüfen
 rts

;                        ===> TEXT VORHANDEN?
TestTx:
 tst.b TxClrFlag
 beq.s NoClose
 move.l #NoTx,Error          ;Nein, dann Error
 bra.s NoClose

;                        ===> TEXT LÖSCHEN
DeleteTx:
 move.l #BootTxName,d1
 move.l DosBase(pc),a6
 jmp _LVODeleteFile(a6)      ;File löschen

;                        ===> EXECUTE
MyEx:
 move.l #NIL,d1
 jsr OpenOld(pc)             ;Filehandle erzeugen
 beq.s NoClose               ;Fehler?
 move.l d0,d7                ;Handle retten
 move.l a5,d1
 clr.l d2                    ;Parameter setzen
 move.l d0,d3
 CALL Execute
 jsr TestDosErr(pc)
 bra.s MyClose               ;Schließen

;                        ===> PARAMETERFILE
SetParName:
 lea FileName,a4
 move.l a4,d1
ParNameLoop:
 tst.b (a4)+                 ;"&" an den aktuellen
 bne.s ParNameLoop           ;Filenamen anhängen
 clr.b (a4)
 move.b #"&",-(a4)
 lea ActualCol(pc),a5        ;Startadresse
 moveq #OldFlags-ActualCol,d6;Länge des Files
 rts


;### BOOTPROGRAMM ###

BootBlock:
 DC.B "DOS",0
ChkSum:
 DC.L 0,$0370

BootPrg:
 lea IntPrg(pc),a0
 lea $100,a1                 ;Interrupt-Routine
 move #BootTx-IntPrg-1,d0    ;nach $100
CopyIntPrg:                  ;kopieren
 move.b (a0)+,(a1)+
 dbra d0,CopyIntPrg

 lea GfxName(pc),a1          ;Library öffnen
 CALL OldOpenLibrary
 move.l d0,a6                      ;alten Copper-
 move.l 38(a6),GfxName-IntPrg+$100 ;Zeiger retten
 lea TextAttr-IntPrg+$100,a0
 CALL OpenFont               ;Font öffnen
 move.l d0,a0                ;Zeiger auf Font-
 move.l 34(a0),d6            ;Daten nach d6
 move.l ExecBase,a6
 move.l #ScreenSize,d0           ;Speicher
 move.l #MEMF_CHIP|MEMF_CLEAR,d1 ;für Screen
 CALL AllocMem                   ;reservieren
 move.l d0,GfxName-IntPrg+$104   ;Zeiger ablegen
 move.l d0,a0
 move d0,ScreenPtLo-IntPrg+$100  ;Zeiger in
 swap d0                         ;Copper-Liste
 move d0,ScreenPtHi-IntPrg+$100  ;einbauen

 lea BootTx(pc),a1           ;Textanfang
 moveq #14,d2                ;15 Zeilen
LineOut:
 moveq #39,d1                ;40 Zeichen/Zeile
CharOut:
 clr.l d0                    ;d0 löschen
 move.b (a1)+,d0             ;Zeichen in d0
 add.l d6,d0                 ;+ Zeiger auf Font
 move.l d0,a2                ;d0 nach a2
 moveq #7,d0
SetChar:
 move.b (a2),(a0)            ;Zeichendaten auf
 move.b (a2),40(a0)          ;den Screen bringen
 add #80,a0                  ;nächstes Screenbyte
 add #$c0,a2                 ;nächstes Datenbyte
 dbra d0,SetChar
 sub #639,a0
 dbra d1,CharOut             ;nächstes Zeichen
 add #600,a0
 dbra d2,LineOut             ;nächste Zeile

 lea BootTx-IntPrg+$100,a0   ;Ende der CopperListe
 moveq #15,d0                ;ab Rasterzeile 15
ColValue1:
 move #$000,d1               ;Anfangsfarbwert
 moveq #15,d2                ;16 Abstufungen
MakeCol:
 move.b d0,(a0)+             ;Rasterzeile ablegen
 move.b #9,(a0)+             ;x-Rasterpositon
ColReg1:
 move.l #$fffe0180,(a0)+     ;Farbregister
 move d1,(a0)+               ;Farbwert ablegen
 add.b #16,d0
ColSub:
 sub #0,d1                   ;nächste Abstufung
 dbra d2,MakeCol
 move.l #$fffffffe,(a0)      ;CopList-Ende: warten

 move.l $6c,Font-IntPrg+$100 ;Int-Vektor retten
 move.l #$100,$6c            ;und neu setzen
 move.l #CopList-IntPrg+$100,$dff080 ;neue CopList
 lea DosName(pc),a1
 CALL FindResident           ;DOS-Library
 move.l d0,a0                ;initialisieren
 move.l 22(a0),a0
 moveq #0,d0
 rts

DosName:
 DC.B "dos.library",0

;                        ===> INTERRUPT-ROUTINE
IntPrg:
 movem.l d0-d7/a0-a6,-(a7)   ;Register ablegen
 btst #5,$dff01f             ;Vertical-Blanking?
 beq.s ExitInt
 cmp.b #$30,VertPos-IntPrg+$100 ;Text noch nicht
ScrollOnOff:                    ;oberste Zeile
 bcs.s NoScroll                 ;erreicht?
 subq.b #1,VertPos-IntPrg+$100  ;Dann scrollen!
NoScroll:
 move.l ExecBase,a6
 lea ConTask(pc),a1          ;Task für CLI-Fenster
 CALL FindTask               ;vorhanden?
 tst.l d0
IntOnOff:
 beq.s ExitInt
 move.l Font(pc),$6c             ;alte Int-Routine
 move.l GfxName(pc),$dff080      ;alte Cop-List
 move #%1000000000100000,$dff096 ;Sprites ein
 move.l #ScreenSize,d0
 move.l GfxName+4(pc),a1         ;Speicher für
 CALL FreeMem                    ;Screen abmelden
ExitInt:
 movem.l (a7)+,d0-d7/a0-a6   ;Register holen
 DC.W $4ef9                  ;Code für "jmp";
                             ;springt zur alten
Font:                        ;Interrupt-Routine
 DC.B "topaz.font"           ;mit Adr. in Font
TextAttr:
 DC.L Font-IntPrg+$100       ;ta_Name
 DC.W 8                      ;ta_YSize
 DC.B 0                      ;ta_Style
 DC.B 0                      ;ta_Flags
ConTask:
 DC.B "CON",0
GfxName:
 DC.B "graphics.library"

CopList:
 DC.B 0
 DC.B $096                   ;dmacon
 DC.W %1000000110000000
 DC.W $096                   ;dmacon
 DC.W %0000000000100000
ColReg2:
 DC.W $182                   ;color0x
ColValue2:
 DC.W $0000
 DC.W $08e                   ;diwstrt
VertPos:
 DC.W $ff81
 DC.W $090                   ;diwstop
 DC.W $3fc1
 DC.W $092                   ;ddfstrt
 DC.W $0038
 DC.W $094                   ;ddfstop
 DC.W $00d0
 DC.W $108                   ;bpl1mod
 DC.W $0000
 DC.W $102                   ;bplcon1
 DC.W $0000
 DC.W $104                   ;bplcon2
 DC.W %100100
 DC.W $0e0                   ;bplpt[0]
ScreenPtHi:
 DC.W $0000
 DC.W $0e2
ScreenPtLo:
 DC.W $0000
 DC.W $100                   ;bplcon0
 DC.W %0001001000000000
BootTx:


;### INITALISIERUNG ###

Startup:
 INIT_AMIGA
;                        ===> LIBRARYS ÖFFNEN

 lea DosName(pc),a1          ;Dos-Library
 CALL OldOpenLibrary         ;öffnen
 move.l d0,DosBase
 lea GfxName(pc),a1          ;Graphics-Library
 CALL OldOpenLibrary         ;öffnen
 move.l d0,GfxBase
 lea IntuitionName(pc),a1    ;Intuition-Library
 CALL OldOpenLibrary         ;öffnen
 move.l d0,IntuitionBase
;                        ===> ED LADEN UND ÄNDERN

 clr.l Error                 ;Fehler-Var. löschen
 move.l #EdName,d1
 lea FileBf,a5
 move.l #BfSize,d6           ;Ed laden
 jsr CopyFileToMem(pc)
 bne.s DoEdAlert             ;Fehler? Dann Alert!
ModifyEd:
 moveq #2,d0                 ;Angaben für
 lea MyEdRAW(pc),a0          ;RAW-Fenster suchen
GotOldRAW:
 move.b (a5)+,d1
 cmp.l #FileBf+BfSize,a5     ;Kein "RAW" gefunden?
 beq.s DoEdAlert             ;Dann Alert!
 bclr #5,d1                  ;Groß-/Kleinschr. aus
 cmp.b (a0)+,d1
 bne.s ModifyEd
 dbra d0,GotOldRAW           ;Neue RAW-Angaben
 moveq #EdName-MyEdRaw-4,d0  ;kopieren
CopyNewRAW:
 move.b (a0)+,(a5)+
 dbra d0,CopyNewRAW
 move.l #MyEdName,d1         ;Ed ins RAM kopieren
 lea FileBf,a5
 jsr CopyMemToFile(pc)
 beq.s MakeGad
DoEdAlert:
 lea EdAlert(pc),a0          ;Ed macht Probleme
 jsr Alert(pc)               ;Alert ausgeben
 bra DeleteFiles             ;und aussteigen

;                        ===> GADGET-STRUCT SETZEN
MakeGad:
 move.l IntuitionBase(pc),a6
 move.l 56(a6),a5
 lea 44(a5),a5               ;Zeiger auf
 move.l a5,WbViewPort        ;View-Port holen
 move.l 4(a5),a5
 move.l 4(a5),a5             ;Workbench-Farben
 move.l (a5),d6              ;retten
 move.l d6,ColBf             ;Prop-Einstellung
 jsr SetProp(pc)             ;Props setzen
 moveq #15,d0                ;16 Bool-Gadgets
 lea GadgetData(pc),a1       ;Zeiger auf Daten
SetBool:
 move.b (a1)+,5(a0)          ;LeftEdge
 move.b (a1)+,7(a0)          ;TopEdge
 clr.l d1
 move.b (a1)+,d1
 move d1,8(a0)               ;Width
 subq #1,d1
 move d1,64(a0)              ;xy
 move d1,68(a0)              ;xy
 move #11,10(a0)             ;Height
 move #10,70(a0)             ;xy
 move #10,74(a0)             ;xy
 addq #3,14(a0)              ;Activation
 cmp #10,d0
 bcs.s NoInv
 addq #3,12(a0)              ;Invertierung aus
NoInv:
 addq #1,16(a0)              ;GadgetType
 move d7,38(a0)              ;GadgetID
 move.l #$1000005,48(a0)     ;Front/Back, Count
 add #44,a0
 move.l a0,-26(a0)           ;GadgetRender
 add #16,a0
 move.l a0,-8(a0)            ;Border-Data
 add #20,a0
 move.l a0,-80(a0)           ;Next Gadget
 addq #1,d7
 dbra d0,SetBool             ;nächstes Gadget
 clr.l -80(a0)
 addq #2,-74(a0)             ;Position des
 subq #2,-34(a0)             ;String-Gadgets
 addq #2,-76(a0)             ;korrigieren
 subq #2,-36(a0)
 addq #3,-64(a0)             ;Typ = String
 move.l a0,-46(a0)
 move #41,10(a0)             ;MaxChars
 add #36,a0
 move.l a0,-36(a0)           ;Buffer

;                        ===> WINDOW ÖFFNEN
 lea NewWindow(pc),a0
 CALL OpenWindow             ;Fenster öffnen
 move.l d0,MyWindow          ;und Zeiger retten
 beq DeleteFiles             ;Nicht zu öffnen?
 move.l d0,a0
 move.l 50(a0),MyRastPort    ;RastPort holen
 lea GadgetTx(pc),a5
 moveq #30,d0
PrintGadTx:
 jsr Print(pc)               ;Gadget-Beschriftung
 dbra d0,PrintGadTx          ;ausgeben
 bra Main


;### DATEN ###

IntuitionName:
 DC.B "intuition.library",0

NewWindow:
 DC.W 180,0      ;LeftEdge, TopEdge
 DC.W 280,200    ;Width, Height
 DC.B 0,1        ;DetailPen, BlockPen
 DC.L $80748     ;IDCMPFlags
 DC.L $1100e     ;Flags
 DC.L Gadgets    ;FirstGadget
 DC.L 0          ;Checkmark
 DC.L WindowName ;Title
 DC.L 0          ;Screen
 DC.L 0          ;BitMap
 DC.W 100,100    ;MinWidth, MinHeight
 DC.W 100,100    ;MaxWidth, MaxHeight
 DC.W 1          ;Type

GadgetData:
 DC.B 111-2,83-8,8+4    ;R
 DC.B 111+24-2,83-8,8+4 ;G
 DC.B 111+48-2,83-8,8+4 ;B
 DC.B 95-2,47-8,11*8+4  ;Abstufung
 DC.B 172-2,105-8,5*8+4 ;Abschaltung
 DC.B 172-2,117-8,5*8+4 ;Scrolling
 DC.B 127-2,19-8,3*8+4  ;<->
 DC.B 16-2,156-8,124    ;editieren
 DC.B 144-2,156-8,124   ;löschen
 DC.B 16-2,132-8,31*8+4 ;ansehen
 DC.B 16-2,144-8,31*8+4 ;Boot-Block
 DC.B 16-2,168-8,124    ;laden
 DC.B 144-2,168-8,124   ;speichern
 DC.B 232-2,183-8,4*8+4 ;CLI
 DC.B 232-2,195-8,4*8+4 ;Info
 DC.B 96-2,183-8,16*8+4 ;Filename

GadgetTx:
 DC.B 4,19,"Hintergrund",0
 DC.B 127,19,"<->",0
 DC.B 186,19," Textfarbe ",0
 DC.B 20,93,"R",0
 DC.B 20+24,93,"G",0
 DC.B 20+48,93,"B",0
 DC.B 203,93,"R",0
 DC.B 203+24,93,"G",0
 DC.B 203+48,93,"B",0
 DC.B 87,36,"Abstufung auf",0
 DC.B 95,64,"RGB-Auswahl",0
 DC.B 87,72,"für Abstufung",0
 DC.B 111,83,"R",0
 DC.B 111+24,83,"G",0
 DC.B 111+48,83,"B",0
 DC.B 66,105,"Abschaltung:",0
 DC.B 66,117,"Scrolling:",0
 DC.B 140-68,132,"Boot-Text ansehen",0
 DC.B 140-116,144,"Boot-Block auf df0: schreiben",0
 DC.B 76-56,156,"Text editieren",0
 DC.B 204-48,156,"Text löschen",0
 DC.B 76-40,168,"Text laden",0
 DC.B 204-56,168,"Text speichern",0
 DC.B 16,183,"Textname:",0
 DC.B 236,183,"CLI",0
 DC.B 232,195,"Info",0
 DC.B 32,195,"Status:",0

OK:        DC.B 96,195,"OK!",0
ShadeBack: DC.B 95,47,"Hintergrund",0
IntOff1:   DC.B 176,105,"auto",0
ScrollOn:  DC.B 180,117,"ein",0
ShadeText: DC.B 95,47," Textfarbe ",0
IntOff2:   DC.B 172,105," CLI ",0
ScrollOff: DC.B 180,117,"aus",0
Clear:     DC.B 95,195,"              ",0
DosErr:    DC.B 96,195,"DOS-Fehler!",0
AskTxName: DC.B 96,195,"Textname?",0
NoTx:      DC.B 96,195,"Kein Text!",0
CutTx:     DC.B 96,195,"Schnipp!",0
BootStat1: DC.B 96,195,"BootBlock...",0
BootStat2: DC.B 96,195,"c/BootOff...",0
DiskErr:   DC.B 96,195,"Disk-Fehler!",0
WriteProt: DC.B 96,195,"Schreibschutz?",0

WindowName:  DC.B "BootLetter 1.0   ©bvr",0
TD_NAME:     DC.B "trackdisk.device",0
NIL:         DC.B "NIL:",0
NewCli:      DC.B "newcli con:0/0/640/159/CLI",0
MyEdRAW:     DC.B "RAW:145/0/350/141/Ed",0
EdName:      DC.B "SYS:c/ed",0
BootOffName: DC.B "c/BootOff",0
MyEdName:    DC.B "ram:ed",0
RunEd:       DC.B "ram:ed ram:boot.tx",0

EdAlert:
 DC.B 0,248,18,"Ed macht Probleme! ",0,0
SureTx:
 DC.B 0,252,14,"Text gespeichert?",0,1
 DC.B 0,16,22,"linke Maustaste: JA",0,1
 DC.B 1,168,22,"rechte Maustaste: ABBRUCH",0,0
Info:
 DC.B 0,108,18,"© 1988  B.van Rüschen, "
 DC.B "Norderstr.34, 2910 Westerstede",0,0

BootOff:
 DC.B $00,$00,$03,$F3,$00,$00,$00,$00
 DC.B $00,$00,$00,$01,$00,$00,$00,$00
 DC.B $00,$00,$00,$00,$00,$00,$00,$05
 DC.B $00,$00,$03,$E9,$00,$00,$00,$05
 DC.B $31,$FC,$4E,$71,$01,$28,$0C,$B8
 DC.B $00,$00,$01,$00,$00,$6C,$67,$F6
 DC.B $4E,$75,$00,$00,$00,$00,$03,$F2
 DC.B $00,$00,$03,$F2

 ALIGN


;### VARIABLEN UND FLAGS ###

ActualCol:     DC.L 0
ColMask:       DC.W 0
ParFlags:      DC.B 0

OldFlags:      DC.B 0
CharBf:        DC.B 0
TxClrFlag:     DC.B -1
RGB:           DC.W 0
ColBf:         DC.L 0
WbViewPort:    DC.L 0
MyWindow:      DC.L 0
MyRastPort:    DC.L 0
DosBase:       DC.L 0
GfxBase:       DC.L 0
IntuitionBase: DC.L 0
Error:         DC.L 0
SaveFlag:      DC.B 0


;### RESERVIERTER SPEICHER ###

 BSS
ReplyPort: DS.B 34
IOExtTD:   DS.B 56
Gadgets:   DS.B GadgetSize
FileBf:    DS.B BfSize
 END

