; Pius Nippgen, Bergstr.12, 6657 Gersheim 8, Tel. 06843/781 (abends 06843/1522)

; VIRUS-CONTROL V1.3  -  Sourcecode:
; ---------------------------------
; assembliert mit SEKA-Assembler.
start:
 move.l  $4.w,a6
 movem.l d0/a0,Parameter   ; eventuelle zusätzliche Parameter retten
 sub.l   a1,a1             ; FindTask() bzw. Prozeß
 jsr     -294(a6)
 move.l  d0,a1
 tst.l   $ac(a1)           ; wenn Pointer to ConsoleLineInterpreter = 0 ->
 bne.s   clistart          ; Workbenchstart -> muß Workbench-StartupMessage
 move.l  d0,-(sp)          ; ahholen, da andernfalls Absturz !
 lea     $5c(a1),a0
 jsr     -384(a6)          ; WaitPort()
 move.l  (sp)+,a1
 lea     $5c(a1),a0
 jsr     -372(a6)          ; GetMsg()
 move.l  d0,-(sp)
 lea     NOBOOTRtext(pc),a0
 add.l   #reset,-8(a0)
 add.l   #reset,-12(a0)
 lea     NoWBStart(pc),a1
 lea     NOBOOTR(pc),a2
 lea     NOBOOTR(pc),a3    ; mittels Requester auf CLI-Start hinweisen
 bsr     autorequest
 sub.l   #reset,-8(a0)
 sub.l   #reset,-12(a0)
 move.l  (sp)+,a1
 jmp     -378(a6)          ; ReplyMsg() + Ende
clistart:
 move.l  #end-reset+9000,d0; eigentliche VIRUS-CONTROL-Routine + Task-stack
 move.l  #$10002,d1        ; Chip-Memory, da auf jedem Rechner vorhanden, und
 jsr     -198(a6)          ; bereits in Cool-Vektor-Routine belegt werden kann.
 move.l  d0,pointer        ; Speicher löschen, damit definiert vorbelegt
 beq     weiter-2          ; error -> rts -> keine Installationsmeldung
 move.l  -454(a6),oldDOIO  ; oldDOIO retten, wird dann mitkopiert
 tst.l   546(a6)
 bne.s   kickchanged
 tst.l   550(a6)        ; wenn KICK-Vektoren verändert, nur Warnmeldung aus-
 bne.s   kickchanged    ; geben, da Änderung auch durch seriöses Programm
 tst.l   554(a6)        ; denkbar
 beq.s   testBeginIO
kickchanged:
 move.l  #MeldungVektorEnde-MeldungVektor,textlaenge
 move.l  #MeldungVektor,textadresse
 bsr     meldungout
testBeginIO:
 lea     350(a6),a0     ; DeviceListStruktur
 lea     trackdisk(pc),a1
 jsr     -276(a6)       ; Adresse der Trackdisk-Node = trackdisk.device-Base
 move.l  d0,a0
 lea     -28(a0),a0
 move.l  a0,BeginIOAdr  ; Adresse des BeginIO-Vektors holen
 cmp.l   #$00fc0000,(a0); wird auch durch seriöse Programme (z.B.FACC) verbogen
 bhs.s   testDOIO       ; deshalb nur Warnmeldung ausgeben
 move.l  #MeldungVektorEnde-MeldungVektor,textlaenge
 move.l  #MeldungVektor,textadresse
 move.l  #"Begi",MeldungVektor+4
 move.l  #"nIO-",MeldungVektor+8
 bsr     meldungout
testDOIO:
 lea     newDOIO(pc),a0 ; prüfen, ob DOIO-Vektor bereits auf VIRUS-CONTROL
 move.l  oldDOIO(pc),a3 ; verbogen ist,
 moveq   #127,d0        ; wenn nicht, VIRUS-CONTROL installieren, aber nur
aaaa:                   ; wenn DOIO noch nicht anderweitig verbogen wurde
 cmpm.l  (a3)+,(a0)+
 bne.s   install
 dbra    d0,aaaa        ; VIRUS-CONTROL wurde schon installiert, da DOIO okay

 lea     reset(pc),a0   ; prüfen, ob COOL-Vektor auch noch auf VIRUS-CONTROL
 move.l  46(a6),a3      ; verbogen ist
 moveq   #127,d0        ; 127 Bytes vergleichen reicht aus
bbbb:                   ; (127, weil größter Pluswert für moveq)
 cmpm.l  (a3)+,(a0)+
 bne     COOLchanged    ; Cool-Vektor auf anderes Programm (Virus?) verbogen
 dbra    d0,bbbb
 bra     isinstalled    ; alles okay, da beide Vektoren richtig verbogen
install:
 cmp.l   #$00fc0000,oldDOIO; prüfen, ob der DOIO-Vektor noch auf ROM zeigt,
 ; prüfe allgemein auf ROM-Adresse, damit ROM-Version unahhängig.
 ; wenn nicht, wurde er bereits von einem anderen Programm (Virus?) verbogen,
 ; bra jmpoldDOIO würde dann in Virus springen.
 blo     DOIOchanged
 movem.l d1-d7/a0-a6,-(sp)
 lea     taskname(pc),a1; es könnte Vektor-Kontroll-Task noch aktiv sein,
 jsr     -294(a6)       ; da ein Window oder Requester noch in Arbeit,
 tst.l   d0             ; DOIO, COOL-Vektor bereits zurückgesetzt.
 movem.l (sp)+,d1-d7/a0-a6
 bne     freemem
 move.l  pointer(pc),a1 ; a1 wird bei copy verwendet
 move.l  a1,d0
 lea     Kennung(pc),a0 ; damit die Kennung nicht in virus-control steht
 addq.b  #1,8(a0)       ; virus-control kann somit auch geschützt werden
 lea     NOBOOT(pc),a0
 add.l   d0,lastDOIO       -NOBOOT(a0)    ; absolute Adressen mit minus reset
 add.l   d0,lastCOOL       -NOBOOT(a0)    ; assemblieren.
 add.l   d0,NOBOOTtext     -NOBOOT-8(a0)  ; Diese absoluten Adressen nun an
 add.l   d0,NOBOOTtext     -NOBOOT-12(a0) ; die aktuelle Speicheradresse
 add.l   d0,NOBOOTRtext    -NOBOOT-8(a0)  ; anpassen.
 add.l   d0,NOBOOTRtext    -NOBOOT-12(a0)
 add.l   d0,OPENERRtext    -NOBOOT-8(a0)
 add.l   d0,OPENERRtext    -NOBOOT-12(a0)
 add.l   d0,NAME0text      -NOBOOT-8(a0)
 add.l   d0,NAME0text      -NOBOOT-12(a0)
 add.l   d0,NAME1text      -NOBOOT-8(a0)
 add.l   d0,NAME1text      -NOBOOT-12(a0)
 add.l   d0,NAME2text      -NOBOOT-8(a0)
 add.l   d0,NAME2text      -NOBOOT-12(a0)
 add.l   d0,NAME3text      -NOBOOT-8(a0)
 add.l   d0,NAME3text      -NOBOOT-12(a0)
 add.l   d0,ONEDIFFtext    -NOBOOT-8(a0)
 add.l   d0,ONEDIFFtext    -NOBOOT-12(a0)
 add.l   d0,CORRECTtext    -NOBOOT-8(a0)
 add.l   d0,CORRECTtext    -NOBOOT-12(a0)
 add.l   d0,PROTECTtext    -NOBOOT-8(a0)
 add.l   d0,PROTECTLtext   -NOBOOT-8(a0)
 add.l   d0,ALREADYNOtext  -NOBOOT-8(a0)
 add.l   d0,ALREADYNOdeltext-NOBOOT-8(a0)
 add.l   d0,ALREADYVItext  -NOBOOT-8(a0)
 add.l   d0,ALREADYVItext  -NOBOOT-12(a0)
 add.l   d0,ALREADYWORKtext-NOBOOT-8(a0)
 add.l   d0,ALREADYNOnamtext-NOBOOT-8(a0)
 add.l   d0,ALREADYNOnamtext-NOBOOT-12(a0)
 add.l   d0,OPENFILEnamtext-NOBOOT-8(a0)
 add.l   d0,OPENFILEnamtext-NOBOOT-12(a0)
 add.l   d0,EXITtext       -NOBOOT-8(a0)
 add.l   d0,linktext       -NOBOOT-8(a0)
 add.l   d0,linktext       -NOBOOT-12(a0)
 add.l   d0,neuschtext     -NOBOOT-8(a0)
 add.l   d0,okktext        -NOBOOT-8(a0)
 add.l   d0,noloadftext    -NOBOOT-8(a0)
 add.l   d0,FILESCHUTZtext -NOBOOT-8(a0)
 add.l   d0,WRITEBBtext    -NOBOOT-8(a0)
 add.l   d0,WRITEBBtext    -NOBOOT-12(a0)
 add.l   d0,OVERWRITEtext  -NOBOOT-8(a0)
 add.l   d0,OVERWRITELtext -NOBOOT-8(a0)
 add.l   d0,OVERWRITERtext -NOBOOT-8(a0)
 add.l   d0,BOOTL          -NOBOOT-8(a0)
 add.l   d0,BOOTLtext      -NOBOOT-8(a0)
 add.l   d0,BOOTRtext      -NOBOOT-8(a0)
 add.l   d0,REALLYBOOTtext -NOBOOT-8(a0)
 add.l   d0,vektor0text    -NOBOOT-8(a0)
 add.l   d0,VEKTORLtext    -NOBOOT-8(a0)
 add.l   d0,VEKTORLtext    -NOBOOT-12(a0)
 add.l   d0,gadtext16text  -NOBOOT-8(a0)
 add.l   d0,gadtext16text  -NOBOOT-12(a0)
 add.l   d0,gadtext15text  -NOBOOT-8(a0)
 add.l   d0,gadtext15text  -NOBOOT-12(a0)
 add.l   d0,gadtext14text  -NOBOOT-8(a0)
 add.l   d0,gadtext14text  -NOBOOT-12(a0)
 add.l   d0,gadtext13text  -NOBOOT-8(a0)
 add.l   d0,gadtext13text  -NOBOOT-12(a0)
 add.l   d0,gadtext12text  -NOBOOT-8(a0)
 add.l   d0,gadtext12text  -NOBOOT-12(a0)
 add.l   d0,gadtext11text  -NOBOOT-8(a0)
 add.l   d0,gadtext11text  -NOBOOT-12(a0)
 add.l   d0,gadtext8text   -NOBOOT-8(a0)
 add.l   d0,gadtext8text   -NOBOOT-12(a0)
 add.l   d0,gadtext7text   -NOBOOT-8(a0)
 add.l   d0,gadtext7text   -NOBOOT-12(a0)
 add.l   d0,gadtext6text   -NOBOOT-8(a0)
 add.l   d0,gadtext6text   -NOBOOT-12(a0)
 add.l   d0,gadtext5text   -NOBOOT-8(a0)
 add.l   d0,gadtext5text   -NOBOOT-12(a0)
 add.l   d0,gadtext4text   -NOBOOT-8(a0)
 add.l   d0,gadtext4text   -NOBOOT-12(a0)
 add.l   d0,gadtext3text   -NOBOOT-8(a0)
 add.l   d0,gadtext3text   -NOBOOT-12(a0)
 add.l   d0,gadtext2text   -NOBOOT-8(a0)
 add.l   d0,gadtext2text   -NOBOOT-12(a0)
 add.l   d0,gadtext1text   -NOBOOT-8(a0)
 add.l   d0,gadtext1text   -NOBOOT-12(a0)
 add.l   d0,gadtext0text   -NOBOOT-8(a0)
 add.l   d0,gadtext0text   -NOBOOT-12(a0)
 add.l   d0,gad90          -NOBOOT(a0)
 add.l   d0,gad90          -NOBOOT+18(a0)
 add.l   d0,gad90          -NOBOOT+34(a0)
 add.l   d0,string0        -NOBOOT(a0)
 add.l   d0,string0        -NOBOOT+4(a0)
 add.l   d0,gad91          -NOBOOT(a0)
 add.l   d0,gad91          -NOBOOT+18(a0)
 add.l   d0,gad91          -NOBOOT+34(a0)
 add.l   d0,string1        -NOBOOT(a0)
 add.l   d0,string1        -NOBOOT+4(a0)
 add.l   d0,gad92          -NOBOOT(a0)
 add.l   d0,gad92          -NOBOOT+18(a0)
 add.l   d0,gad92          -NOBOOT+34(a0)
 add.l   d0,string2        -NOBOOT(a0)
 add.l   d0,string2        -NOBOOT+4(a0)
 add.l   d0,gad93          -NOBOOT(a0)
 add.l   d0,gad93          -NOBOOT+18(a0)
 add.l   d0,gad93          -NOBOOT+34(a0)
 add.l   d0,string3        -NOBOOT(a0)
 add.l   d0,string3        -NOBOOT+4(a0)
 add.l   d0,gad0           -NOBOOT(a0)
 add.l   d0,gad0           -NOBOOT+18(a0)
 add.l   d0,gad0           -NOBOOT+26(a0)
 add.l   d0,gad1           -NOBOOT(a0)
 add.l   d0,gad1           -NOBOOT+18(a0)
 add.l   d0,gad1           -NOBOOT+26(a0)
 add.l   d0,gad2           -NOBOOT(a0)
 add.l   d0,gad2           -NOBOOT+18(a0)
 add.l   d0,gad2           -NOBOOT+26(a0)
 add.l   d0,gad3           -NOBOOT(a0)
 add.l   d0,gad3           -NOBOOT+18(a0)
 add.l   d0,gad3           -NOBOOT+26(a0)
 add.l   d0,gad4           -NOBOOT(a0)
 add.l   d0,gad4           -NOBOOT+18(a0)
 add.l   d0,gad4           -NOBOOT+26(a0)
 add.l   d0,gad5           -NOBOOT(a0)
 add.l   d0,gad5           -NOBOOT+18(a0)
 add.l   d0,gad5           -NOBOOT+26(a0)
 add.l   d0,gad6           -NOBOOT(a0)
 add.l   d0,gad6           -NOBOOT+18(a0)
 add.l   d0,gad6           -NOBOOT+26(a0)
 add.l   d0,gad7           -NOBOOT(a0)
 add.l   d0,gad7           -NOBOOT+18(a0)
 add.l   d0,gad7           -NOBOOT+26(a0)
 add.l   d0,gad8           -NOBOOT(a0)
 add.l   d0,gad8           -NOBOOT+18(a0)
 add.l   d0,gad8           -NOBOOT+26(a0)
 add.l   d0,gad10          -NOBOOT(a0)
 add.l   d0,gad10          -NOBOOT+18(a0)
 add.l   d0,gad10          -NOBOOT+26(a0)
 add.l   d0,gad11          -NOBOOT(a0)
 add.l   d0,gad11          -NOBOOT+18(a0)
 add.l   d0,gad11          -NOBOOT+26(a0)
 add.l   d0,gad12          -NOBOOT(a0)
 add.l   d0,gad12          -NOBOOT+18(a0)
 add.l   d0,gad12          -NOBOOT+26(a0)
 add.l   d0,gad13          -NOBOOT(a0)
 add.l   d0,gad13          -NOBOOT+18(a0)
 add.l   d0,gad13          -NOBOOT+26(a0)
 add.l   d0,gad14          -NOBOOT(a0)
 add.l   d0,gad14          -NOBOOT+18(a0)
 add.l   d0,gad14          -NOBOOT+26(a0)
 add.l   d0,gad15          -NOBOOT(a0)
 add.l   d0,gad15          -NOBOOT+18(a0)
 add.l   d0,gad15          -NOBOOT+26(a0)
 add.l   d0,gad16          -NOBOOT+18(a0)
 add.l   d0,gad16          -NOBOOT+26(a0)
 add.l   d0,gadborders     -NOBOOT-8(a0)
 add.l   d0,gadborder1     -NOBOOT-8(a0)
 add.l   d0,pairs          -NOBOOT-8(a0)
 add.l   d0,font           -NOBOOT(a0)
 add.l   d0,window         -NOBOOT+26(a0)
 add.l   d0,structtask     -NOBOOT+10(a0)
 add.l   d0,end            -NOBOOT-30(a0)
 add.l   d0,end            -NOBOOT-34(a0)
 add.l   d0,end            -NOBOOT-38(a0)
 lea     reset(pc),a0   ; pc-relativ adressieren, da kürzer
 move.w  #end-reset-1,d0; da erst bei -1 (ffff) dbcc ende
copy:
 move.b  (a0)+,(a1)+    ; eigentliche VIRUS-CONTROL-Routine (reset: bis end:)
 dbra    d0,copy        ; in den angeforderten Speicherbereich kopieren
 move.l  pointer(pc),a1
 add.l   #newDOIO-reset,a1
 move.l  a1,-454(a6)    ; DOIO-Vektor auf VIRUS-CONTROL verbiegen
 bsr     execchecksum   ; COOL-Vektor auf VIRUS-CONTROL verbiegen
 move.l  pointer(pc),a1
 move.l  a1,a2
 add.l   #structtask-reset,a1  ; addtask
 add.l   #task-reset,a2
 sub.l   a3,a3          ; 2 Bytes statt  6 Bytes(move.l #0,a3)
 jsr     -282(a6)
 move.l  #MeldungEnde-Meldung,textlaenge
 move.l  #Meldung,textadresse
 bsr.s   meldungout
 bra.s   checkdrive     ; eingelegte Disks prüfen
DOIOchanged:
 move.l  #"DOIO",vektorchanged
COOLchanged:
 bsr     freemem
 move.l  #MeldungDangerEnde-MeldungDanger,textlaenge
 move.l  #MeldungDanger,textadresse
 bra.s   meldungout
isinstalled:
 bsr     freemem
 move.l  #MeldungEnde-Meldung,textlaenge
 move.l  #Meldung,textadresse
 move.l  #"  be",Meldungmodify    ; Meldung modifizieren kürzer
 move.l  #"reit",Meldungmodify+4  ; wie extra eigene Meldung
 move.l  #"s   ",Meldungmodify+8
 bsr.s   meldungout
 bra.s   checkdrive         ; eingelegte Disks prüfen
meldungout:
 bsr     OpenDOS            ; OpenLibrary("dos.library",0);
 jsr     -60(a6)            ; outputhandle holen
 move.l  d0,d1
 movem.l textadresse(pc),d2-d3 ; Adresse + Länge der Meldung
 jsr     -48(a6)            ; write
 bra     CloseDOS           ; CloseLibrary("dos.library") + rts

checkdrive:                 ; zuerst eventuelle zusätzliche Parameter auswerten
 move.l  46(a6),a1
 move.l  a1,VCreset
 move.b  #$ff,openflag-reset(a1)    ; Open() nicht verbiegen als default
 move.l  #"AUS ",gadtext15text-reset+14(a1)
 move.w  #$ffff,colorflag-reset(a1) ; colorflag, searchfiles als default
 move.l  #" AN ",gadtext0text-reset+14(a1)
 move.l  #" AN ",gadtext16text-reset+14(a1)
 movem.l Parameter(pc),d0/a0; zusätzliche Parameter
 subq.l  #1,d0              ; d0 = Zeichenanzahl der zusätzlichen Parameter
 beq.s   noparameter        ; wenn nur Programmname -> d0=1, da nur $0a(Return)
testline:
 cmp.b   #$20,(a0)
 bne.s   testn
 addq.l  #1,a0
 bra.s   testline
testn:
 cmp.b   #"-",(a0)+         ; in a0 Adresse der zusätzlichen Parameter
 bne.s   noparameter
 cmp.b   #"c",(a0)          ; -c = kein Farbsignal bei Disk-Einlegen
 bne.s   testt
 clr.b   colorflag-reset(a1)
 move.l  #"AUS ",gadtext0text-reset+14(a1)
 addq.l  #1,a0
 bra.s   testline
testt:
 cmp.b   #"t",(a0)          ; -t = eingelegte Disks nicht testen
 bne.s   testo
 clr.b   checkflag
 addq.l  #1,a0
 bra.s   testline
testo:
 cmp.b   #"o",(a0)          ; -o = Open() verbiegen
 bne.s   testf
 clr.b   openflag-reset(a1)
 move.l  #" AN ",gadtext15text-reset+14(a1)
 addq.l  #1,a0
 bra.s   testline
testf:
 cmp.b   #"f",(a0)+         ; -f = S:NoWarning S:VirusName nicht durchsuchen
 bne.s   noparameter
 clr.b   searchfiles-reset(a1)
 move.l  #"AUS ",gadtext16text-reset+14(a1)
 bra.s   testline

noparameter:                ; Routine zum Prüfen der eingelegten Disks
 moveq   #0,d0              ; df0: (ist auch eventueller Returncode)
 tst.b   checkflag
 beq     weiter-2
 bsr     OpenDOS
 moveq   #50,d1             ; 1 Sekunde warten, damit Vektor-Kontroll-Task
 jsr     -198(a6)           ; Openflag entsprechend setzen kann
 bsr     CloseDOS
 bsr.s   check
 moveq   #1,d0              ; df1:
 bsr.s   check
 moveq   #2,d0              ; df2:
 bsr.s   check
 moveq   #3,d0              ; df3:
 bra.s   check
check:
 move.l  d0,-(sp)
 sub.l   a1,a1                       ; FindTask()
 jsr     -294(a6)
 move.l  VCreset(pc),a1
 lea     trackport-reset(a1),a1
 move.l  d0,16(a1)
 jsr     -354(a6)                    ; AddPort()
 move.l  VCreset(pc),a1
 lea     trackreq-reset(a1),a1
 lea     trackdisk(pc),a0
 moveq   #0,d1                       ; keine Flags
 move.l  (sp)+,d0                    ; Laufwerk
 jsr     -444(a6)                    ; OpenDevice()
 tst.l   d0
 bne.s   OpenDeviceError             ; d0 <> 0 -> Laufwerk nicht vorhanden
 move.l  VCreset(pc),a0
 lea     trackreq-reset(a0),a1
 lea     trackport-reset(a0),a3
 move.l  a3,14(a1)
 lea     blockbuff-reset(a0),a3
 move.l  a3,40(a1)
 moveq   #2,d0
 move.w  d0,28(a1)                   ; CMD_READ
 lsl.l   #8,d0                       ; 512 Bytes ab 0 -> VIRUS-CONTROL
 move.l  d0,36(a1)                   ; prüft zuerst, ob Disk eingelegt ist,
 clr.l   44(a1)                      ; wenn nicht weiter mit alterDOIO-Routine
 jsr     -456(a6)                    ; DOIO -> springt in VIRUSCONTROL
 ; darf statt VCreset nicht 46(a6) benutzen, da in der auf VIRUS-CONTROL ver-
 ; bogenen DOIO-Routine 'Beende Virus-Control' möglich ist, wodurch 46(a6) = 0
 ; Vektor-Kontroll-Task wartet 5 Sekunden mit Speicherfreigabe -> genug Zeit
 ; für Motor aus, CloseDevice() RemPort(), welche ja den Speicher noch benutzen
 move.l  VCreset(pc),a1
 lea     trackreq-reset(a1),a1
 move.w  #9,28(a1)                   ; Motor
 clr.l   36(a1)                      ; aus
 jsr     -456(a6)                    ; DOIO
 move.l  VCreset(pc),a1
 lea     trackreq-reset(a1),a1
 jsr     -450(a6)                    ; CloseDevice()
OpenDeviceError:
 move.l  VCreset(pc),a1
 lea     trackport-reset(a1),a1
 jsr     -360(a6)                    ; RemovePort()
 bra     returncode

textadresse:  dc.l 0     ; Adresse der auszugebenden Meldung
textlaenge:   dc.l 0     ; Länge der auszugebenden Meldung
Parameter:    dc.l 0     ; Zeichenanzahl der zusätzlichen Eingabeparameter
Parameteradr: dc.l 0     ; Adresse der zusätzlichen Eingabeparameter
VCreset:      dc.l 0     ; Adresse des installierten VIRUS-CONTROL
checkflag:    dc.b $ff
frei:         dc.b 0
trackdisk:    dc.b "trackdisk.device",0
 even
Meldung:
 dc.b $9b,"33mVIRUS-CONTROL V1.3 von PIUS NIPPGEN "
Meldungmodify: dc.b                       "erfolgreich installiert !",10,$9b,"31m"
 dc.b "100% Assembler!   resetfest!   für alle Amigas!  sekündl.System-Vektorentest!",10
 dc.b "Kill-Virus durch Vektoren-Restauration!   Bootblock-Schreibzugriff-Kontrolle!",10
 dc.b "Reset+linke M.taste->entfernt VIRUSCONTROL!  Reset+rechte M.taste->NoFastMem!",10
 dc.b "verdächtige Disk einlegen->WarnWindow! +L-ALT->immer WarnWindow! +R-ALT->nie!",10
 dc.b "Bootblock auf Schirm od. in File!  Standard,NoFastMem od. File auf Bootblock!",10
 dc.b "Bootblockchecksum falsch->k.(Virus-)Boot mehr, richtig->(Virus-)Boot möglich!",10
 dc.b "gefahrloses Booten  von Virus-Diskette  durch Bootsimulation!",10
 dc.b "Bootblock    nach   S:NoWarning     -> nur rotes Warn-Signal!",10
 dc.b "Bootblock mit Namen nach S:VirusName-> namentliche   Warnung!",10
 dc.b "Link-Viren-Schutz    durch   File-Schutz-Kennung!",10
 dc.b "-f  S:NoWarning, S:VirusName  nicht  durchsuchen!",10
 dc.b "-c  kein  grünes  Farb-Signal  bei Disk-Einlegen!",10
 dc.b "-t  bei Programmstart  eingelegte Disks n.testen!",10
 dc.b "-o  File-Zugriff mittels Requester kontrollieren!",10
 dc.b "Kontakte und Mitteilungen  aller  Art  erwünscht!",10
MeldungEnde: even
MeldungDanger:
 dc.b $9b,"33mVIRUS-CONTROL V1.3 von P.NIPPGEN  nicht installiert,",10,
 dc.b $9b,"31mda "
vektorchanged: ; vektorchanged-Adresse muß gerade sein, da .l daraufzugreife
 dc.b    "COOL-Vektor schon verbogen -> durch  ein VIRUS ?",10
 dc.b "die einzig 100 % sichere Virus-Entfern-Methode ist:",10
 dc.b "AMIGA AUS, Warten, Amiga an, VIRUS-CONTROL starten!",10
MeldungDangerEnde: even
MeldungVektor: dc.b $9b,"33mKICK   -Vektor verändert -> Virus ?",10,$9b,"31m"
MeldungVektorEnde: even
NoWBStart:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,NoWBStarttext,0
NoWBStarttext:
 dc.b "VIRUS-CONTROL V1.3 von P.NIPPGEN nur im CLI startbar !",0
 even

; in der eigentlichen VIRUS-CONTROL-Routine (reset: bis end:), welche in
; den angeforderten Speicherbereich kopiert wurde, darf ich nicht absolut
; adressieren, da nach dem Kopieren die absoluten Adressen ja nicht mehr
; stimmen, deshalb nur relativ adressieren:
; z.B. move adresse(pc),lea(pc),bsr,bra  statt  move adresse,lea,jsr,jmp
reset:                 ; RESET-Routine, wird über Cool-Vektor bei Reset
 btst    #6,$bfe001    ; angesprungen, wenn execchecksum korrekt.
 bne.s   weiter        ; wenn linke Maustaste während Reset gedrückt,
 clr.l   $2e(a6)       ; wird VIRUS-CONTROL entfernt.
 rts
weiter:
 movem.l d0-d7/a0-a6,-(sp); alle Register retten
 move.l  pointer(pc),a1
 move.l  #end-reset+9000,d0
 jsr     -204(a6)      ; mit AllocAbs den früheren Speicherbereich, worin sich
 tst.l   d0            ; VIRUS-CONTROL befindet, wieder belegen,
 bne.s   AllocAbsOkay  ; in der COOL-Routine sind noch keine Libraries, außer
showend:               ; der Exec-Library installiert. Auch ist noch kein
 bsr     optzeichen    ; eventuelles Expansion-Ram eingebunden. Deshalb
 bra.s   showend       ; Chip-Memory für VIRUS-CONTROL brnutzen.
AllocAbsOkay:          ; AllocAbs klappt, da es sehr früh aufgerufen wird.
 lea     taskflag(pc),a0  ; taskflag, resetflag, exitflag, exitcount löschen
 clr.l   (a0)+            ; inuse-flags löschen,
 clr.l   (a0)             ; taskflag, exitcount, inuse-flags löschen reicht
 bsr     VCrestore        ; Vektoren auf VIRUS-CONTROL verbiegen
 bsr     optzeichen       ; grünes Farbsignal -> VIRUS-CONTROL noch aktiv
 movem.l (sp)+,d0-d7/a0-a6; coolvektor, execchecksum bleibt bei reset erhalten
 rts                      ; reicht also 1* bei CLI-aufruf

newDOIO: ; neuer Einsprung der DOIO-Routine. Code, der bei jedem DOIO-Aufruf
         ; durchlaufen wird, möglichst kurz halten, um Absturz durch
         ; DOIO-Aufruf-Stau zu verhindern !!
 cmp.l   #$400,36(a1)   ; 1024 Bytes bei reset
 beq.s   test
 cmp.l   #$200,36(a1)   ; 512 Bytes bei Disk einlegen und loadwb
 beq.s   test
 bra     jmpoldDOIO     ; in alte DOIO-Routine einspringen
; Der Code der neuen DOIO-Routine muß reentrant sein, da ja bis zu 4 Mal
; (=für jedes Laufwerk) aufgerufen werden kann. Daher darf ich nicht eine
; absolute Speicherstelle als Speicher für gadgetID, windowpointer o.ä.
; benutzen, da ja alle 4 möglichen Tasks auf diese eine Speicherstelle
; zugreifen würden -> Fehler. Deshalb diese Werte einfach in unbenutzten
; Register ablegen, denn diese werden ja mit Taskwechsel umgeladen,
; so daß automatisch immer die jeweils richtigen Werte in den Registern
; vorhanden sind. Da die Betriebssystemroutinen des öftern zumindest
; a0,a1,d0,d1 ändern, sicherheitshalber immer vor Aufruf Register retten.
; die Register werden folgendermaßen zur Speicherung benutzt:
; d6 = Laufwerknummer des jeweiligen DOIO-Aufrufs (um Texte zu modifizieren)
; d4 = IDCMPclass, d5 LowWord=gadgetID, d5 HiWord= 1Unterschied ausgeben
; d7 = Windowpointer, a5 = bootblockpuffer
; Um Speicherplatz zu sparen werden die Textmeldungen vor der Textausgabe
; jeweils für das aktuelle Laufwerk modifiziert. Ich muß deshalb vor der
; Textmodifizierung das Multitasking abschalten und erst nach der Textausgabe
; wieder einschalten. Dadurch wird das Umschalten auf einen andreren Task
; verhindert, welcher einen nicht für ihn modifizierten Text ausgeben könnte.
test:
 movem.l d0-d7/a0-a6,-(sp); alle Register retten
 move.l  $4.w,a6        ; kann auch DOIO mit execbase in z.B. a5 aufrufen
 move.l  20(a1),a0      ; in a1 Zeiger auf I/O-Request-Struktur
 move.l  10(a0),a0      ; in 20(a1) Adresse der Device-Struktur, diese beginnt
 cmp.l   #"trac",(a0)+  ; mit einer Node-struktur, deren Namen prüfen
 bne.s   shorter4       ; DOIO-Zugriff auf Trackdisk.device ?
 cmp.l   #"kdis",(a0)+
 bne.s   shorter4
 cmp.l   #"k.de",(a0)
 bne.s   shorter4
 tst.l   44(a1)         ; ab Block 0 ?
 bne.s   shorter4
 cmp.w   #$02,28(a1)    ; wird gelesen ?
 beq.s   read3
 cmp.w   #$03,28(a1)    ; wird geschrieben ? -> Gefahrmeldung in bootblockread
shorter4:               ; bne.s shorter4 = 2 Byte, bne.l DOIOweiter = 4 Byte
 bne     DOIOweiter1
read3:
 move.l  24(a1),a0      ; OpenDevice() trug in IO_UNIT die Adresse des
 move.b  67(a0),d0      ; MsgPort des Laufwerks ein.
 move.b  d0,d6          ; Laufwerknummer in d6 ablegen
 btst    #1,64(a0)      ; wenn Laufwerk leer, da ja DOIO auf leeres Laufwerk
 bne     shorter4       ; machen kann, siehe check:
 lea     inuse0(pc),a0
 ext.w   d6             ; da in d6 nur Byte abgespeichert wurde, dieses Byte
 ext.l   d6             ; auf Wordbreite, und dann auf Longwordbreite bringen,
 add.l   d6,a0          ; wegen add.l
 tst.b   (a0)           ; inuse-Flag des Laufwerkes testen
 bne     shorter4       ; Ende, wenn schon Warn-Window für Laufwerk aufgerufen
 move.b  #$ff,(a0)      ; inuse-Flag setzen
 lea     exitcount(pc),a0 ; exitcount +1 wenn Diskette bearbeitet wird
 addq.b  #1,(a0)
 moveq   #0,d5          ; damit bei -f nichts in Window ausgegeben wird
 bsr     bootblockread  ; bootblock einlesen, und auf Schreibzugriff prüfen
 bsr     nameunknown    ; alter virusname mit unknown überschreiben
 cmp.l   #$400,36(a1)   ; 1024 Bytes bei reset, setzt resetflag, wenn aus ROM
 beq.s   checkiton
 lea     resetflag(pc),a0
 move.b  (a0),d0        ; den ersten DOIO-Zugriff 512 Bytes ab 0 ignorieren,
 clr.b   (a0)           ; da die meisten dos.library-Funktionen noch nicht
 tst.b   d0             ; benutzbar sind, z.B. Open() führt zu Task-Held
 bne     DOIOweiter
 cmp.b   #$35,$bfec01   ; rechte Alt-Taste gedrückt ?
 beq     DOIOweiter     ; R-ALT -> kein VIRUS-CONTROL-Test
 lea     colorflag(pc),a0
 tst.b   (a0)
 beq.s   nocolor        ; kein optisches Zeichen wenn Colorflag = 0
 bsr     optzeichen
nocolor:
 cmp.b   #$37,$bfec01   ; linke Alt-Taste gedrückt ?
 beq     VirusNameFile  ; L-ALT -> immer Warn-Window
checkiton:
 move.l  a5,a0          ; in bootblockread wurde Pufferadresse in a5 abgelegt
 cmp.l   #$444f5300,(a0); "DOS",0 ?
 bne     DOIOweiter     ; keine DOS-Disk
 bsr     bootchecksum   ; Bootblockchecksum falsch, keine Gefahr, da kein Boot
 bne     DOIOweiter     ; in oldDOIO wird wieder erster Block gelesen
 ; es liegt DOS-Kennung vor und CHECKSUM stimmt, d.h. Bootroutine würde aus-
 ; geführt werden, daher jetzt noch prüfen, ob womöglich VIRUS-code.
 ; dieses zusätzliche Lesen stört nicht weiter, da Amiga ja immer ganzen Track
 ; in einen TrackPuffer liest. Es wird also schnell aus Trackpuffer gelesen.
 move.l  a5,a0
 add.l   #12,a0
 cmp.l   #$43fa0018,(a0)+ ; (a0)+ kürzer wie z.B. 12(a0)
 bne.s   testreset      ; und prüfen, ob es sich um den ungefährlichen
 cmp.l   #$4eaeffa0,(a0)+
 bne.s   testreset      ; Standard-Bootcode handelt
 cmp.l   #$4a80670a,(a0)+
 bne.s   testreset
 cmp.l   #$20402068,(a0)+
 bne.s   testreset
 cmp.l   #$00167000,(a0)+
 bne.s   testreset
 cmp.l   #$4e7570ff,(a0)+
 bne.s   testreset
 cmp.l   #$60fa646f,(a0)
testreset:
 jsr     -528(a6)        ; getcc() damit Prozessor-aufwärtskompatibel
 move.w  d0,-(sp)        ; Flags retten, beq=kein virus  bne=virus
 cmp.l   #$400,36(a1)    ; 1024 Bytes=reset. bei Disk einlegen + loadwb = 512
 bne     nobootroutine
 move.l  62(sp),a0       ; RTS-Adresse prüfen, ob DOIO-Aufruf aus ROM.
 cmp.l   #$00fc0000,a0   ; in ROM wird nur 1* DOIO mit $400 aufgerufen,
 blo     nobootroutine   ; und zwar in Bootroutine. Da aber auch jmp DOIO
 cmp.w   #$4a80,(a0)     ; durch ein Programm denkbar, könnte auf Stack
 bne     nobootroutine   ; zufällig ROM-Adresse liegen, deshalb noch Code
 cmp.l   #$2014b0ba,4(a0); vergleichen. Um möglichst ROM-Version-unabhängig
 bne     nobootroutine   ; zu sein, ist dieser umständliche Weg nötig.
 ; hier in der Bootroutine sind bereits alle Libraries benutzbar, außer der
 ; dos.library, da die Vorbereitungen zum Öffnen der dos.library erst durch
 ; das Ausführen des Bootblockcodes getätigt werden. Die intuition.library
 ; (z.B. Autorequester) ist also voll benutzbar, man muß nur bedenken, daß
 ; die 'system-configuration' noch nicht ausgewertet wurde, daß also noch die
 ; Standardwerte eingestellt sind, so z.B. Topaz 9 -> 60 Zeichen-Zeilenbreite
 ; die Requesterstrukturen also auf 60 Zeichen-Zeilenbreite auslegen bzw.
 ; als font topaz80 einsetzen.
 lea     resetflag(pc),a3
 move.b  #$ff,(a3)      ; resetflag setzen
 cmp.w   #$100,$dff016  ; rechte Maustaste gedrückt ?
 bne.s   memokay
fastaway:
 move.l  #$20004,d1     ; größter Fastmem-Speicherbereich ermitteln
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -216(a6)       ; availmem()
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 beq.s   memokay
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -198(a6)       ; diesen Bereich mittels allocmem() belegen
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0             ; da ich die Anfangsadressen der belegten Speicher-
 bne.s   fastaway       ; bereiche nicht rette, bleibt Fastmem bis zum
memokay:                ; nächsten Reset belegt
 move.w  (sp)+,ccr
 beq.s   bootsimul      ; geht schneller als nochmal laden
 movem.l a0-a3,-(sp)    ; a0 wegen modifyunit retten, a1,a2,a3 retten, weil
 jsr     -132(a6)       ; hierin Requesterparameter übergebe
 bsr     modifyunit
 lea     NOBOOTtext(pc),a0
 clr.b   26(a0)         ; 'String' kürzen
 lea     BOOT(pc) ,a1
 lea     BOOTL(pc),a2
 lea     BOOTR(pc),a3
 bsr     autorequest
 move.b  #" ",26(a0)    ; 'String' wiederherstellen, da ganz für Window brauche
 jsr     -138(a6)
 movem.l (sp)+,a0-a3    ; true  1  retry  = linkes  Gadget
 tst.l   d0             ; false 0  cancel = rechtes Gadget
 beq.s   bootsimul      ; links -> Bootsimulation
 movem.l a0-a3,-(sp)
 jsr     -132(a6)
 bsr     modifyunit
 lea     REALLYBOOT(pc),a1
 lea     BOOTL(pc),a2
 lea     BOOTR(pc),a3   ; wirklich echte Disk-Boot-Routine ?
 bsr     autorequest    ; gefährlich, da so Viren aktiviert werden können!
 jsr     -138(a6)
 movem.l (sp)+,a0-a3
 tst.l   d0
 beq.s   bootsimul
 movem.l d0-d7/a0-a6,-(sp); da beim Booten dos.library noch nicht benutzbar,
 bsr     settimer         ; anstatt Delay()  timer.device direkt mittels DOIO
 bsr     wait1            ; ansprechen -> 2 sec. warten, in dieser Zeit können
 bsr     wait1            ; Screen,Windowlisten usw. aktualisiert werden.
 bsr     remreqport       ; allerdings ist diese Wartezeit nur bei ganz wenigen
 bsr     addtask          ; unsauber programmierten BootIntros erforderlich.
 movem.l (sp)+,d0-d7/a0-a6
 bra     DOIOweiter ; echte Bootblockdaten von Disk lesen, welche AmigaDOS
                    ; dann ausführt, und dadurch womöglich Virus aktiviert
bootsimul:
 bsr     addtask
 move.l  40(a1),a0
 move.l  a0,a2
 bsr     clear1024
 lea     bootblock(pc),a0
 moveq   #bootblockend-bootblock-1,d0
loop6:
 move.b  (a0)+,(a2)+
 dbra    d0,loop6
 bsr     clearflags
 movem.l (sp)+,d0-d7/a0-a6
 moveq   #$0,d0 ; rts nach $fea806(V1.2) mit d0=0 -> DOIO okay, also anstatt
 rts     ; mittels jmp oldDOIO Daten von Disk in Puffer zu lesen, gefahrloser
         ; Bootcode in Puffer kopieren, den AmigaDOS dann ruhig ausführen kann
nobootroutine:
 move.w  (sp)+,ccr
 beq     DOIOweiter        ; kein Virus
 lea     searchfiles(pc),a0
 tst.b   (a0)              ; S:NoWarning, S:VirusName nicht durchsuchen,
 beq     openwindow        ; wenn searchfiles = 0
 ; prüfen, ob Bootblock in NoWarning-File enthalten, wenn ja nur rotes Signal
 movem.l d0-d7/a0-a6,-(sp)
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 lea     NoWarning(pc),a0
 move.l  a0,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, um bestehendes S:NoWarning-File
 bsr     checkdevicename   ; zu öffnen,EXCLUSIVE_LOCK nötig, um Schreibzugriffe
 tst.l   d0                ; durch andere 'Laufwerk-Aufrufe' auszuschließen,
 beq     NoWarnError       ; denn dadurch könnten falsche Daten gelesen werden.
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6 ; OpenError,weil z.B. nicht existiert
 tst.l   d0                ; oder weil z.B. schon von anderem 'Laufwerk-Aufruf'
 beq     NoWarnError       ; EXKLUSIVE geöffnet wurde
 move.l  d0,d1             ; filehandle
nextbootblock:
 move.l  a5,a2
 lea     Nobuff(pc),a0
 move.l  a0,d2             ; Vektor-Kontroll-Task-Stackboden
 move.l  #1024,d3          ; als 1024-Puffer benutzen
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -42(a6)           ; ersten Bootblock aus S:NoWarning lesen
 movem.l (sp)+,d1-d7/a0-a6
 cmp.l   #1024,d0          ; kein Bootblock mehr zu lesen -> Fileende
 bne.s   fileende
 move.w  #$ff,d0
NoWarningloop:
 cmpm.l  (a0)+,(a2)+
 bne.s   nextbootblock
 dbra    d0,NoWarningloop
 bsr     CloseFile         ; 1024 Bytes gleich -> gefunden !
 move.l  #$0f000f00,d0     ; rotes Signal für gefunden
 bsr     optzeichen2
 movem.l (sp)+,d0-d7/a0-a6
 bra     DOIOweiter
fileende:                  ; nicht gefunden !
 bsr     CloseFile         ; Close File + Close dos.library
 bra.s   allclosed
NoWarnError:
 bsr     CloseDOS          ; Close dos.library
allclosed:
 movem.l (sp)+,d0-d7/a0-a6

VirusNameFile:
 ; bevor Warn-Window öffne, prüfen, ob Bootblock in VirusName-File enthalten,
 ; wenn ja VirusName entsprechend setzen
 lea     searchfiles(pc),a0 ; wenn -f auch bei L-ALT nicht durchsuchen
 tst.b   (a0)               ; wenn searchfiles = 0
 beq     openwindow
 movem.l d0-d7/a0-a6,-(sp)
 bsr     nameunknown       ; als Name unbekannt vorbelegen
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 lea     VirusName(pc),a0
 move.l  a0,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, um bestehendes S:VirusName-File
 bsr     checkdevicename   ; zu öffnen,EXCLUSIVE_LOCK nötig, um Schreibzugriffe
 tst.l   d0                ; durch andere 'Laufwerk-Aufrufe' auszuschließen,
 beq     OpenFailed        ; denn dadurch könnten falsche Daten gelesen werden.
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6 ; OpenError,weil z.B. nicht existiert
 tst.l   d0                ; oder weil z.B. schon von anderem 'Laufwerk-Aufruf'
 beq     OpenFailed        ; EXKLUSIVE geöffnet wurde
 move.l  d0,d1             ; filehandle
nextbootblock1:
 clr.b   20(sp)               ; 20(sp) = d5 nach movem, GadgetID erst später
 lea     Vibuff(pc),a0
 move.l  a0,d2                ; Vektor-Kontroll-Task-Stackboden
 move.l  #1024+buff1-buff0,d3 ; als 1024+32-Puffer benutzen
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -42(a6)              ; 1 Virusname+Bootblock aus S:VirusName lesen
 movem.l (sp)+,d1-d7/a0-a6
 cmp.l   #1024+buff1-buff0,d0
 bne.s   fileende1            ; Fileende
 lea     NAME0text(pc),a2
 moveq   #buff1-buff0+20,d0   ; Virusname in entsprechende Intuitext-struktur
 mulu    d6,d0                ; kopieren, wird später in geöffnetes Window
 add.l   d0,a2                ; geprintet
 bsr     copyname
 move.w  #$ff,d0
 move.l  a5,a2
VirusNameloop:
 cmpm.l  (a0)+,(a2)+
 beq.s   issame
 cmp.l   #"FREE",-4(a0)
 beq.s   nextbootblock1
 tst.b   20(sp)
 bne.s   nextbootblock1
countit:                   ; 1 Longword-Unterschied erlauben
 move.b  #$ff,20(sp)       ; Flag für 1 Longword-Unterschied
issame:
 dbra    d0,VirusNameloop  ; 1024 Bytes gleich -> gefunden !
 bra.s   CloseFileDOS
fileende1:                 ; nicht gefunden !
 bsr     nameunknown       ; als Name unbekannt setzen
CloseFileDOS:
 bsr     CloseFile         ; Close File + Close dos.library
 bra.s   allclosed1
OpenFailed:
 bsr     CloseDOS          ; Close dos.library
allclosed1:
 movem.l (sp)+,d0-d7/a0-a6
 bra     openwindow

Checksumfalsch:
 move.l  24(a1),a0      ; falsche Bootblock-Checksum schreiben -> inaktiviert
 btst    #4,64(a0)      ; Bootblock-Virus, da kein Boot mehr möglich.
 ; zuvor prüfen, ob Disk schreibgeschützt, OpenDevice() trug in IO_UNIT die
 ; Adresse des MsgPort des Laufwerks ein. In Byte 64 des MsgPort steht ein
 ; gesetztes Bit 4 für eine schreibgeschützte Disk.
 beq.s   noprotect
 bsr.s   writeprotected ; schreibgeschützt -> Requester ausgeben
 bne.s   Checksumfalsch ; neuer Versuch
 rts
noprotect:
 bsr     setchecksum    ; richtige Bootblockchecksum setzen
 addq.l  #1,4(a0)       ; richtige checksum durch +1 falsch machen
writecheck:
 bra     bootblockwrite ; auf Disk schreiben

Checksumrichtig:
 move.l  24(a1),a0
 btst    #4,64(a0)
 beq.s   noprotect1
 bsr.s   writeprotected
 bne.s   Checksumrichtig
 rts
noprotect1:
 bsr     setchecksum    ; richtige Checksum setzen
 bra.s   writecheck

writeprotected:
 movem.l a0-a3,-(sp)    ; Requester, der erscheint,
 jsr     -132(a6)       ; wenn Disk schreibgeschützt
 bsr     modifyunit
 lea     PROTECT(pc) ,a1; mit forbid() permit() umschließen, damit der
 lea     PROTECTL(pc),a2; modifizierte Text auch vom dem richtigen Task
 lea     NOBOOTR(pc) ,a3; ausgegeben wird.
 bra     shorter2

showbootblock:             ; Bootblock-ASCII-Dump, wenn a4(=Filename) mit RAW:
 movem.l d0-d7/a0-a6,-(sp) ; beginnt, andernfalls abspeichern in File
 jsr     -132(a6)
 bsr     modifyunit
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 move.l  a4,d1             ; showbootblock wird mit filename in a4 aufgerufen
 move.l  #1006,d2          ; newmode, da u.U. auch richtiges File öffnen muß
 bsr     checkdevicename   ; oldmode würde dann Absturz bewirken
 tst.l   d0
 bne.s   deviceokay
 movem.l d1-d7/a0-a6,-(sp)
 bra.s   deviceunknown
deviceokay:
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -30(a6)           ; Open()
deviceunknown:
 move.l  $4.w,a6           ; Open() (wenn RAW:-Window->modifizierter Titel)
 jsr     -138(a6)
 movem.l (sp)+,d1-d7/a0-a6 ; DOIO->writeprotect->eigener requester
 tst.l   d0                ; DOSfunctions->writeprotect->AmigaDOSAutorequester
 bne.s   NoErrorShow       ; OpenError(falscher filename)->eigener requester
 bsr     openerror
 bra     OpenFailed
NoErrorShow:
 move.l  d0,d1             ; filehandle für späteres write() und close() retten
 bsr     WriteInFile       ; Puffer, welcher ersten Block enthält ausgeben
 cmp.l   #"RAW:",(a4)
 bne     CloseFileDOS
 lea     unit2(pc),a0      ; z.B. unit2 als Puffer für das eingegebene Zeichen
 move.l  a0,d2             ; benutzen, da ja wieder restauriert wird
 moveq   #1,d3             ; 1 Zeichen holen
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -42(a6)           ; Read  aus RAW:  wartet auf Eingabe,
 movem.l (sp)+,d0-d7/a0-a6
 bsr     CloseFile
 movem.l (sp)+,d0-d7/a0-a6; a1-IORequest restaurieren
 bsr     bootblockread    ; da durch ASCII-Ausgabe Daten verändert wurden
 bra     openwindow

autorequest:              ; in a6 muß exec.base stehen
 movem.l d1-d7/a0-a6,-(sp)
 movem.l a1-a3,-(sp)      ; Haupttext, linker Text, rechter Text
 bsr     OpenIntuition
 jsr     -342(a6)         ; WBenchToFront()
 sub.l   a0,a0            ; 2 Bytes statt  6 Bytes(move.l #0,a3)
 movem.l (sp)+,a1-a3      ; Haupttext, linker Text, rechter Text
 moveq   #0,d0            ; keine IDCMP-Flags für linken Knopf
 moveq   #0,d1            ; keine IDCMP-Flags für rechten Knopf
 move.l  #640,d2          ; Autorequester-Breite
 moveq   #100,d3          ; Autorequester-Höhe
 jsr     -348(a6)         ; AutoRequest()
 move.l  a6,a1            ; intuitionbase
 move.l  $4.w,a6
 move.l  d0,-(sp)         ; BOOL retten
 jsr     -414(a6)         ; CloseLibrary("intuition.library");
 move.l  (sp)+,d0         ; BOOL-Wert
 movem.l (sp)+,d1-d7/a0-a6; d0-Rückgabewert darf durch movem nicht
 rts                      ; überschrieben werden

optzeichen:
 move.l  #$00f000f0,d0 ; green green -> VirusControl arbeitet korrekt
optZeichen2:           ; Farb-Signal-Routine erwartet Farbwert in d0
 movem.l d0-d7/a0-a6,-(sp)
 move.l  $4.w,a6       ; Disable(), damit permanent Register beschreiben kann,
 jsr     -120(a6)      ; -> Copperlist wird praktisch nicht wirksam
 move.w  #40,d1        ; als 'Timer' vertikale Strahlenposition benutzen,
red:                   ; da Prozessor-unabhängig und bereits in Cool-Routine
 move.b  $dff005,d2    ; abfragbar, im Gegensatz zu CIA-Timer, welche erst in
waittick:              ; folgender initcode()-Funktion initialisiert werden
 move.l  d0,$dff180
 move.l  d0,$dff184    ; alle 4 Workbenchfarben mit Farbe überschreiben
 cmp.b   $dff005,d2
 beq.s   waittick
 dbra    d1,red
 jsr     -126(a6)      ; Enable()
 movem.l (sp)+,d0-d7/a0-a6
 rts
                       ; erwartet in a6 exec.base in a1 IO-Request
bootblockread:         ; verändert a0,d0, setzt a5
 moveq   #0,d0         ; Requester bei Schreibzugriff ausgeben
bb:
 move.l  36(a1),-(sp)  ; ursprüngliche Byte-anzahl retten
 move.l  40(a1),-(sp)  ; ursprünglichen Puffer retten
 tst.l   d0
 bne.s   readaccess    ; write ohne Requester
 cmp.w   #$02,28(a1)   ; wird gelesen ?
 beq.s   readaccess
 bsr     writebbzugriff
 bne.s   changetoread
 add.l   #12,sp        ; Stack korrigieren
 bra     DOIOweiter    ; schreiben -> weiter in alter DOIO-routine
changetoread:
 move.w  #$02,28(a1)   ; in Lesen wandeln
readaccess:
 lea     bootblock0(pc),a0
 move.l  #bootblock1-bootblock0,d0
 mulu    d6,d0
 add.l   d0,a0
 move.l  a0,a5         ; aktueller bootblockpuffer in a5 abspeichern
 move.l  a0,40(a1)     ; je nach Laufwerk entsprechenden Puffer setzen
 move.l  #1024,36(a1)  ; 1024(=ganzer Bootblock) lesen
 movem.l d1-d7/a0-a6,-(sp)
 bsr     jmpoldDOIO
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 beq.s   bootblockreadokay
 bsr     openerror
bootblockreadokay:
 move.l  (sp)+,40(a1)  ; ursprünglichen Puffer restaurieren
 move.l  (sp)+,36(a1)  ; ursprüngliche Byte-anzahl restaurieren
 rts

bootblockwrite:        ; erwartet in a6 exec.base in a1 IO-Request
 move.l  24(a1),a0     ; verändert a0,d0, setzt a5
 btst    #4,64(a0)
 beq.s   noprotect3
 bsr     writeprotected; wenn Disk schreibgeschützt oder aus Laufwerk entnommen
 bne.s   bootblockwrite
 rts
noprotect3:
 moveq   #-1,d0        ; write ohne Requester
 move.w  #3,28(a1)     ; 3 = CMD_WRITE
 bsr     bb
 move.w  #2,28(a1)     ; 2 = CMD_READ
 rts
; Wenn ich mittels DOIO schreibend auf Disk zugreifen will, dann muß ich
; selber vorher prüfen, ob Disk schreibgeschützt ist. Wenn ja eigener
; Autorequester ausgeben, denn AmigaDOS prüft dies nur bei Open()-Funktion

bootchecksum:          ; erwartet in a0 Adresse des Datenpuffers
 move.w  #$ff,d1       ; ändert a0, d0,d1
 moveq   #$0,d0        ; rts mit bootblockchecksum in d0
loop:
 add.l   (a0)+,d0
 bcc.s   jump
 addq.l  #1,d0
jump:
 dbra d1,loop
 not.l   d0
 rts

setchecksum:
 move.l  a5,a0
 clr.l   4(a0)         ; alte Bootblockchecksum löschen
 bsr.s   bootchecksum  ; neue richtige Bootblockchecksum berechnen
 move.l  a5,a0
 move.l  d0,4(a0)      ; und die richtige Bootblockchecksum eintragen
 rts

WriteInFile:           ; verändert a0, d0,d1,d2,d3
 move.l  a5,d2         ; d2 = Adresse des Puffers der auszugebenden Bytes
 move.l  #1024,d3      ; d3 = Anzahl der auszugebenden Bytes
 move.w  #1023,d0      ; 1024-1 Zähler für dbra modifybuffer
 move.l  d2,a0
modifybuffer:
 cmp.l   #"RAW:",(a4)  ; wenn Filename nicht mit "RAW:" anfängt, also wenn
 bne.s   writeokay     ; keine Ausgabe auf Schirm, dann nicht wandeln
 cmp.b   #$20,(a0)
 blo.s   writedefault
 cmp.b   #127,(a0)
 blo.s   writeokay
writedefault:          ; wenn Byte < 32  oder Byte > 126, dann . ausgeben
 move.b  #".",(a0)
writeokay:
 addq.l  #1,a0
 dbra    d0,modifybuffer
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -48(a6)       ; Write
 movem.l (sp)+,d0-d7/a0-a6
 rts

modifyunit:            ; modifiziert auszugebende Texte für aktuelles Laufwerk
 move.b  d6,d0         ; in d6 wird ganz am Anfang die Laufwerksnummer abgelegt
 add.b   #48,d0
 lea     unit0(pc),a0
 move.b  d0,(a0)
 lea     unit1(pc),a0
 move.b  d0,(a0)
 lea     unit2(pc),a0
 move.b  d0,(a0)
 lea     unit3(pc),a0
 move.b  d0,(a0)
 lea     unit4(pc),a0
 move.b  d0,(a0)
 lea     unit5(pc),a0
 move.b  d0,(a0)
 lea     unit6(pc),a0
 move.b  d0,(a0)
 lea     unit7(pc),a0
 move.b  d0,(a0)
 lea     unit8(pc),a0
 move.b  d0,(a0)
 rts

DOIOweiter:
 bsr     clearflags
DOIOweiter1:
 movem.l (sp)+,d0-d7/a0-a6
jmpoldDOIO: dc.w $4ef9 ; Opcode für jmp, also in die
oldDOIO:    dc.l 0     ; Original-DOIO-Routine einspringen

bootblock:             ; harmloser Original-Bootblock für die Boot-Simulation
 dc.b    "DOS",0       ; wenn Bootblock ändere -> muß Bootblock-Checksum
 dc.l    $c0200f19     ; korrigieren
 dc.l    $00000370
 lea     dosname(pc),a1
 jsr     -96(a6)
 tst.l   d0
 beq.s   error
 move.l  d0,a0
 move.l  22(a0),a0
returncode:
 moveq   #0,d0
ende0:
 rts
error:
 moveq   #-1,d0
 bra.s ende0
dosname: dc.b "dos.library",0
bootblockend: even

nofastbootblock:       ; NoFastMem-Bootblock
 dc.b    "DOS",0
 dc.l    $9f780e84
 dc.l    $00000370
 movem.l d0-d7/a0-a6,-(sp)
 btst    #6,$bfe001
 beq.s   memokay1      ; wenn linke Maustaste während Reset drücke,
fastaway1:             ; wird kein FastMem belegt
 move.l  #$20004,d1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -216(a6)      ; availmem()
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 beq.s   optzeichen1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -198(a6)      ; allocmem()
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   fastaway1
optZeichen1:           ; NoFastMem -> blaues Farb-Signal
 jsr     -132(a6)      ; Forbid(), damit permanent Register beschreiben kann,
 move.l  #$000f000f,d0 ; -> Copperlist wird praktisch nicht wirksam
 move.w  #40,d1
farbe:
 move.b  $dff005,d2
waittick1:
 move.l  d0,$dff180
 move.l  d0,$dff184    ; alle 4 Workbenchfarben mit blau überschreiben
 cmp.b   $dff005,d2
 beq.s   waittick1
 dbra    d1,farbe
 jsr     -138(a6)      ; Permit()
memokay1:
 movem.l (sp)+,d0-d7/a0-a6
 lea     dosname1(pc),a1; ab hier der eigentliche Standard-Bootblock
 jsr     -96(a6)
 tst.l   d0
 beq.s   error1
 move.l  d0,a0
 move.l  22(a0),a0
 moveq   #0,d0
ende1:
 rts
error1:
 moveq   #-1,d0
 bra.s   ende1
dosname1:dc.b "dos.library",0
 even
taskname:dc.b " VIRUS-CONTROL V1.3 von PIUS NIPPGEN, 6657 Gersheim 8,"
         dc.b " 06843/1522",0
; Bedienungsanleitung
dc.b "wenn linke Maustaste nicht gedrueckt, wird beim Booten automatisch "
dc.b "FASTMEM abgeschaltet"
nofastbootblockend: even

openfile:
 cmp.b   #$39,$bfec01   ; CTRL-Taste gedrückt ?
 beq.s   jmpoldopen     ; wenn ja gleich Original-Open
 movem.l a0-a1,-(sp)
 move.l  d1,a0
 cmp.b   #"*",(a0)      ; Open "*" ignorieren
 movem.l (sp)+,a0-a1
 beq.s   jmpoldopen
 movem.l d1-d7/a0-a6,-(sp)
 moveq   #-2,d2         ; ACCESS_READ
 move.l  dosbase(pc),a6 ; da theoretisch Dosbase nicht in a6 stehen muß
 jsr     -84(a6)        ; Lock() (wenn auf RAW:Window->kurzzeitig RAW:Window)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 beq.s   jmpoldopen     ; da File noch nicht existiert -> keine Gefahr
 movem.l d1-d7/a0-a6,-(sp)
 move.l  d0,d1
 move.l  dosbase(pc),a6 ; da theoretisch Dosbase nicht in a6 stehen muß
 jsr     -90(a6)        ; Unlock()
 movem.l (sp)+,d1-d7/a0-a6
 movem.l d1-d7/a0-a6,-(sp)
 lea     opencount(pc),a0
 addq.b  #1,(a0)
 bsr     allowaccess   ; kann ewig lang dauern
 subq.b  #1,(a0)       ; VIRUS-CONTROL kann beendet werden, wenn opencount=0
 movem.l (sp)+,d1-d7/a0-a6 ; a6=execbase wieder mit dosbase belegen
 tst.l   d0
 bne.s   jmpoldopen    ; kann mittlerweile ruhig restauriert worden sein
 bra     returncode

jmpoldopen: dc.w 0     ; wird 'moveq #$ff,d1' reinkopiert
jmp:        dc.w $4ef9 ; Opcode für jmp
oldopen:    dc.l 0     ; in Original-Open-Routine einspringen
savebra:    dc.l 0     ; Original bra offset retten

; Taskcode, welcher Systemvektoren-kontrolliert, der Task muß möglichst
; frühzeitig und automatisch installiert werden. Dieses wird von der
; Bootroutine gemacht. Da nur Prozesse dos.library benutzen können, muß
; Task-waiting mittels timer.device realisieren, es werden 1* pro Sekunde
; Vektoren überprüft, Wait wichtig, damit Systemleistung erhalten bleibt.
task:
 move.l  $4.w,a6
 bsr     settimer          ; timerdevice setzen
 lea     taskflag(pc),a0   ; bei CLI-Start nicht warten
 tst.b   (a0)              ; nach Reset mehrere Sekunden warten, damit
 bne.s   ttt               ; WorkBenchScreen offen. Wenn nicht warte, wird
 move.l  #10,32(a1)        ; ein StandardScreen geöffnet. Dadurch wird später
 bsr     wait              ; die system-configuration nicht voll ausgewertet
ttt:                       ; (Breite>640, Interlace wird nicht berücksichtigt)
 bsr     opendos           ; auch dos.library ist jetzt eingerichtet
 lea     dosbase(pc),a0
 move.l  d0,(a0)
taskweiter:
 lea     openflag(pc),a0   ; durch CLI-start oder Window-Gadget setzen
 tst.b   (a0)
 bne.s   tt
 move.l  dosbase(pc),a6
 cmp.w   #$4ef9,-30(a6)
 beq.s   tt                ; schon verbogen
 lea     jmpoldopen(pc),a0
 move.w  -30(a6),(a0)      ; moveq #$ff,d1
 lea     -26(a6),a4        ; relative Adresse in
 add.w   -26(a6),a4        ; absolute Adresse umrechnen
 move.l  a4,4(a0)
 move.l  -28(a6),8(a0)
 move.l  $4.w,a4
 exg     a4,a6
 jsr     -120(a6)          ; Disable(), da theoretisch Taskswitch nach 1 Befehl
 exg     a4,a6
 lea     openfile(pc),a0
 move.w  #$4ef9,-30(a6)    ; Open() verbiegen
 move.l  a0,-28(a6)
 exg     a4,a6
 jsr     -126(a6)          ; Enable()
tt:
 move.l  $4.w,a6
 lea     openflag(pc),a0   ; durch CLI-start oder Window-Gadget setzen
 tst.b   (a0)
 beq.s   tttt
 bsr     restoreopen       ; Open() wiederherstellen
tttt:
 bsr     wait1             ; 1 sec warten
 lea     exitflag(pc),a0   ; soll VIRUS-CONTROL entfernt werden
 tst.b   (a0)
 beq.s   noexitflag
 clr.l   $2e(a6)           ; VIRUSCONTROL wird bei nächsten Reset n.m.aktiviert
 move.l  oldDOIO(pc),-454(a6) ; DOIO-Vektor zurücksetzen -> kein Diskcheck mehr
 bsr     restoreopen       ; Open() wiederherstellen
 lea     exitcount(pc),a0
 tst.b   (a0)              ; ist noch ein Warn-Window in Arbeit ?
 bne.s   tttt              ; warten bis alle Arbeits-Windows beendet sind
 lea     opencount(pc),a0  ; sind auch alle Open()-Requester bearbeitet ?
 tst.b   (a0)              ; muß dies prüfen, da diese Routinen den
 bne.s   tttt              ; freizugebenden Speicher als Code benutzen
 move.l  #5,32(a1)         ; vor der Speicherfreigabe 5 sec. warten, damit alle
 bsr     wait              ; Routinen beendet, die den Speicherbereich benutzen
 bsr     remreqport        ; Device schließen + Port entfernen
 bra     freemem           ; Speicherfreigabe + rts->EndTask
noexitflag:
 move.l  BeginIOAdr(pc),a0
 lea     lastBeginIO(pc),a1; wenn VIRUS-CONTROL neu installiert wird,
 tst.l   (a1)              ; nach CLI-Start oder reset = 0
 bne.s   alreadyset        ; mit dem momentanen BeginIO-Vektor-Wert belegen
 move.l  (a0),(a1)+        ; momentaner BeginIO-Vektor nach lastBeginIO
 move.l  (a0),(a1)         ; momentaner BeginIO-Vektor nach restoreIO
alreadyset:
 cmp.l   #$00fc0000,(a0)   ; wenn BeginIO auf ROM zeigt (z.B. nach Reset),
 bhs.s   restoreIOROM      ; dann diesen Wert als restoreIO benutzen
 move.l  lastBeginIO(pc),a2
 lea     lastBeginIO(pc),a3
 move.l  (a0),(a3)         ; momentanen Vektor für nächsten Vergleich retten
 cmp.l   (a0),a2           ; wurde BeginIO-Vektor in letzter Sekunde verändert
 beq.s   testKICK1         ; nein, weiter mit KICK-Vektoren-Test
 lea     vektor0text(pc),a0; weil verändert, Warn-Requester ausgeben
 move.l  #"Begi",(a0)+
 move.l  #"nIO-",(a0)      ; Warn-Text an BeginIO-Vektor anpassen
 bsr     vektoropenwindow
 bra     taskweiter
restoreIOROM:              ; Original-BeginIO-Vektor wird in der deletevirus-
 lea     restoreIO(pc),a1  ; routineist benötigt. BeginIO-Vektor-Handlung etwas
 move.l  (a0),(a1)         ; aufwendiger, um ROM-Version-unabhängig zu sein
 move.l  (a0),-4(a1)
testKICK1:
 tst.l   546(a6)           ; wenn Kick-Vektor auf Null geändert wurde -> okay
 bne.s   testKICK2
 tst.l   550(a6)
 bne.s   testKICK2
 tst.l   554(a6)
 beq.s   testCool1
testKICK2:
 move.l  546(a6),a0
 move.l  lastKickMem(pc),a2
 lea     lastKickMem(pc),a3
 move.l  a0,(a3)           ; momentanen Pointer für nächsten Vergleich retten
 cmp.l   a0,a2             ; wurde KickMem-Ptr in letzten Sekunde verändert
 bne.s   kickchanged1
 move.l  550(a6),a0
 move.l  lastKickTag(pc),a2
 lea     lastKickTag(pc),a3
 move.l  a0,(a3)           ; momentanen Pointer für nächsten Vergleich retten
 cmp.l   a0,a2             ; wurde KickTag-Pointer in letzter Sekunde verändert
 bne.s   kickchanged1
 move.l  554(a6),a0
 move.l  lastKickCheck(pc),a2
 lea     lastKickCheck(pc),a3
 move.l  a0,(a3)           ; momentanen Checksum für nächsten Vergleich retten
 cmp.l   a0,a2             ; wurde KickChecksun in letzter Sekunde verändert
 beq.s   testcool1
kickchanged1:
 lea     vektor0text(pc),a0
 move.l  #"KICK",(a0)+
 move.l  #" -  ",(a0)
 bsr.s   vektoropenwindow
 bra     taskweiter
testcool1:
 move.l  pointer(pc),a2    ; Adresse von VIRUS-CONTROL nach a2
 move.l  46(a6),a0
 cmp.l   a0,a2             ; zeigt CoolVektor auf VIRUS-CONTROL ?
 beq.s   testDOIO1
 move.l  lastCOOL(pc),a2
 lea     lastCOOL(pc),a3
 move.l  a0,(a3)
 cmp.l   a0,a2             ; COOL-Vektor in letzter Sekunde verändert ?
 beq.s   testDOIO1
 lea     vektor0text(pc),a0
 move.l  #"COOL",(a0)+
 move.l  #" -  ",(a0)
 bsr.s   vektoropenwindow
 bra     taskweiter
testDOIO1:
 lea     newDOIO(pc),a2
 move.l  -454(a6),a0
 cmp.l   a0,a2             ; zeigt DOIO-Vektor auf meine (newDOIO-)Routine ?
 beq     taskweiter
 move.l  lastDOIO(pc),a2
 lea     lastDOIO(pc),a3
 move.l  a0,(a3)
 cmp.l   a0,a2             ; DOIO-Vektor in letzter Sekunde verändert ?
 beq     taskweiter
 lea     vektor0text(pc),a0
 move.l  #"DOIO",(a0)+
 move.l  #" -  ",(a0)
 bsr.s   vektoropenwindow
 bra     taskweiter

; Warn-Requester ausgeben, da BeginIO-Vektor, KICK-Vektor, COOL-Vektor oder
; DOIO-Vektor verändert, wahrscheinlich durch ein Virus.
; Rechner ausschalten ist die beste und einfachste Heilmethode.
vektoropenwindow:
 lea     VEKTOR0(pc),a1
kill:
 lea     VEKTORL(pc),a2
 lea     NOBOOTR(pc),a3
 bsr     autorequest
 tst.l   d0
 beq.s   vektortested
 bsr     deletevirus       ; kill Virus
vektortested:
 rts

wait1:
 lea     timereq(pc),a1
 move.l  #1,32(a1)         ; 1 sec warten
wait:
 move.w  #9,28(a1)
 jmp     -456(a6)

openwindow:
 movem.l d1-d7/a0-a6,-(sp) ; a1 = IO-Request usw. retten
nopush:
 move.l  $4.w,a6          ; Forbid() -> kann ungestört entsprechendes
 jsr     -132(a6)         ; StringGadget setzen, und Gadgettext des rechten
 bsr     OpenIntuition    ; Gadgets modifizieren. Nach OpenWindow() wieder
 movem.l d1-d7/a0-a6,-(sp); permit(), da bei OpenWindow ja Ausgabe erfolgte.
 jsr     -342(a6)         ; WBenchToFront(),da bei OpenWindow nicht automatisch
 movem.l (sp)+,d1-d7/a0-a6
 lea     window(pc),a2
 tst.b   d6
 bne.s   test1
 lea     gad90(pc),a1   ; für df0:  entsprechendes Stringgadget
 move.l  a1,18(a2)      ; mit eigenem Puffer setzen
test1:
 cmp.b   #1,d6
 bne.s   test2
 lea     gad91(pc),a1   ; für df1:  entsprechendes Stringgadget
 move.l  a1,18(a2)      ; mit eigenem Puffer setzen
test2:
 cmp.b   #2,d6
 bne.s   test3
 lea     gad92(pc),a1   ; für df2:  entsprechendes Stringgadget
 move.l  a1,18(a2)      ; mit eigenem Puffer setzen
test3:
 cmp.b   #3,d6
 bne.s   testende
 lea     gad93(pc),a1   ; für df3:  entsprechendes Stringgadget
 move.l  a1,18(a2)      ; mit eigenem Puffer setzen
testende:
 move.l  34(a1),a4      ; Adresse des StringInfo
 move.l  (a4),a4        ; Adresse des Puffers(=Filename) nach a4
 bsr     modifyunit     ; modifiziert u.a. Gadgettext des rechten Gadgets
 lea     window(pc),a0
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -204(a6)       ; OpenWindow(), wodurch auch Gadgets angezeigt werden
 movem.l (sp)+,d1-d7/a0-a6
 move.l  d0,d7          ; aktueller Windowpointer nach d7
 bne.s   openok
 moveq   #0,d0          ; Bildschirm schwarz als Zeichen für verdächtige Disk
 bsr     optzeichen2    ; Notersatz für nicht zu öffnendes WarnWindow
 bra     openwindowerror
openok:
 move.l  d7,a0
 move.l  50(a0),a0      ; RastPort des Windows
 lea     NAME0(pc),a1   ; Name des Virus ausgeben
 moveq   #buff1-buff0+20,d0
 mulu    d6,d0
 add.l   d0,a1
 moveq   #38,d0         ; x-Wert
 moveq   #40,d1         ; y-Wert
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -216(a6)       ; PrintIText
 movem.l (sp)+,d0-d7/a0-a6
 movem.l d0-d7/a0-a6,-(sp)
 btst    #31,d5         ; ein Bit aus 24-31 testen, z.B. 31
 beq.s   noonediff      ; wird durch GadgetID nicht überschrieben
 movem.l (sp)+,d0-d7/a0-a6
 moveq   #56,d1         ; y-Wert
 lea     ONEDIFF(pc),a1
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -216(a6)       ; PrintIText
noonediff:
 move.l  $4.w,a6
 jsr     -138(a6)       ; Permit()
 movem.l (sp)+,d0-d7/a0-a6
 move.l  a6,-(sp)       ; intuitionbase retten
 move.l  $4.w,a6
waitmessage:
 move.l  d7,a0
 move.l  86(a0),a0      ; UserPort des Windows
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -384(a6)       ; WaitPort(UserPort)
 movem.l (sp)+,d1-d7/a0-a6
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -372(a6)       ; GetMsg(UserPort)
 movem.l (sp)+,d1-d7/a0-a6
 move.l  d0,a0
 move.l  d0,a1          ; für ReplyMsg nach a1
 move.l  20(a0),d4      ; Class = IDCMP-Flags nach d4
 cmp.l   #$200,d4
 beq.s   closegadget    ; da bei Systemgadgets Intuition-Objekt-Adresse nicht
 move.l  28(a0),a0      ; gesetzt wird, kann hier zufälliger Weise ungerade
 move.w  38(a0),d5      ; Adresse stehen, wodurch bei move.w TaskHeld
closegadget:            ; also nur bei User-Gadgets auswerten !
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -378(a6)       ; ReplyMsg(a1=intuimessage), nachdem ausgewertet habe
 movem.l (sp)+,d1-d7/a0-a6
 cmp.w   #9,d5          ; Stringadget -> weiter warten
 beq.s   itis9          ; großes Gadget rechts dient nur der Information,
 cmp.w   #10,d5         ; deshalb weiter warten
 bne.s   portleeren
itis9:
 clr.w   d5             ; d5 löschen, damit wenn closegadget gedrückt, nicht
 bra.s   waitmessage    ; Endlosschleife, weil d5 ja noch erhalten !
portleeren:             ; sicherheitshalber nochmal Port abfragen bzw. leeren
 move.l  d7,a0          ; bevor Closewindow()
 move.l  86(a0),a0      ; UserPort des Windows
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -372(a6)       ; GetMsg(UserPort)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0             ; sicherheitshalber Port leeren
 beq.s   leerende
 move.l  d0,a1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -378(a6)       ; ReplyMsg(a1=intuimessage)
 movem.l (sp)+,d1-d7/a0-a6
 bra.s   portleeren
leerende:
 move.l  (sp)+,a6
 move.l  d7,a0
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -72(a6)        ; CloseWindow()
 movem.l (sp)+,d1-d7/a0-a6
 move.l  a6,a1
 move.l  $4.w,a6
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -414(a6)       ; CloseLibrary("intuition.library")
 movem.l (sp)+,d1-d7/a0-a6

 cmp.l   #$200,d4       ; CloseWindow-Gadget gedrückt -> Ende
 bne.s   testgad0
openwindowerror:
 movem.l (sp)+,d1-d7/a0-a6
 bra     DOIOweiter

; Endlosschleife, also immer wieder Warn-Window
; öffnen, bis closewindow oder ende gedrückt
testgad0:
 tst.w   d5
 bne.s   testgad1          ; FarbSignal
 jsr     -132(a6)
 lea     colorflag(pc),a0
 not.b   (a0)
 lea     gadtext0text(pc),a1
 move.l  #"AUS ",14(a1)
 tst.b   (a0)
 beq.s   aus
 move.l  #" AN ",14(a1)
aus:
 jsr     -138(a6)
 bra     nopush
testgad1:                  ; Bootblock -> Schirm
 cmp.w   #1,d5
 bne.s   testgad2
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 lea     filename(pc),a4
 bra     showbootblock

testgad2:
 cmp.w   #2,d5
 bne.s   testgad3          ; Bootblock -> File
 move.l  a4,d0             ; a4 vor überschreiben durch movem retten
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 move.l  d0,a4
 bsr     namecorrect
 beq     openwindow
 bra     showbootblock

testgad3:
 cmp.w   #3,d5
 bne     testgad4          ; File -> Bootblock
 move.l  a4,d0             ; a4 vor überschreiben durch movem retten
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 move.l  d0,a4
 bsr     namecorrect
 beq     openwindow
 bsr     reallyoverwrite
 beq     openwindow
 movem.l d0-d7/a0-a6,-(sp)
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 move.l  a4,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, da existierendes File lesen will,
 bsr     checkdevicename   ; sicherheitshalber kein MODE_OLDFILE, damit
 tst.l   d0                ; kein anderes Programm durch Schreiben stört
 beq.s   deviceunknown1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0                ; Device schreibgeschützt
 bne.s   noErrorFile       ; -> Amiga-DOS-Autorequester
deviceunknown1:
 bsr     openerror         ; OpenError wegen z.B verbotenem Filenamen
 bra     OpenFailed        ; -> eigener Requester erforderlich
noErrorFile:
 move.l  d0,d1             ; filehandle für späteres read() und close() retten
 move.l  a5,d2             ; d2 = Puffer, in den die Bytes eingelesen werden
 move.l  #1024,d3          ; d3 = Anzahl der zu lesenden Bytes
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -42(a6)           ; Read()  1024 Bytes aus File lesen
 movem.l (sp)+,d0-d7/a0-a6
 move.l  $4.w,a3
 exg     a3,a6
 bsr     bootblockwrite    ; und als Bootblock schreiben
 exg     a3,a6
 bra     CloseFileDOS

testgad4:
 cmp.w   #4,d5
 bne.s   testgad5          ; Standard-Bootblock
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 bsr     reallyoverwrite
 beq     openwindow
 bsr     bootblockclear    ; bootblock mit Null belegen
 lea     bootblock(pc),a0
 moveq   #bootblockend-bootblock-1,d0
loop7:
 move.b  (a0)+,(a2)+
 dbra    d0,loop7          ; StandardBootblock in Puffer kopieren
 bsr     bootblockwrite
 bra     openwindow

testgad5:
 cmp.w   #5,d5
 bne.s   testgad6          ; NoFastMem-Bootblock
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 bsr     reallyoverwrite
 beq     openwindow
 bsr     bootblockclear    ; bootblock mit Null belegen
 lea     nofastbootblock(pc),a0
 move.l  #nofastbootblockend-nofastbootblock-1,d0
 bra.s   loop7             ; NoFastMemBootblock schreiben

testgad6:
 cmp.w   #6,d5
 bne.s   testgad7          ; falsche Checksum -> Boot nicht möglich
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 bsr     Checksumfalsch
 bra     openwindow

testgad7:
 cmp.w   #7,d5
 bne.s   testgad8          ; richtige Checksum -> Boot möglich
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 bsr     Checksumrichtig
 bra     openwindow

testgad8:                  ; Beende Virus-Control
 cmp.w   #8,d5
 bne.s   testgad11         ; bei ID = 9,10 wird oben ja weiter gewartet
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 bsr     reallyexit        ; Sicherheitsabfrage
 beq     openwindow
 lea     exitflag(pc),a0
 move.b  #$ff,(a0)         ; exitflag für Vektor-Control-Task setzen
 bra     DOIOweiter

testgad11:
 cmp.w   #11,d5
 bne     testgad12         ; in NoWarning-File
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 movem.l d0-d7/a0-a6,-(sp)
 lea     freeposition(pc),a0
 clr.l   (a0)
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 lea     NoWarning(pc),a0
 move.l  a0,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, um altes S:NoWarning-File
 bsr     checkdevicename   ; zu öffnen, EXCLUSIVE_LOCK nötig, da schreibend
 tst.l   d0                ; zugreife, denn wenn kein EXCLUSIVE-LOCK, könnte
 beq.s   unknowndevice2    ; ein anderer 'Laufwerk-Aufruf' ebenfalls gleich-
 movem.l d1-d7/a0-a6,-(sp) ; zeitig schreibend zugreifen -> falsche Daten
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   noErrorNoWarning
 move.l  #1006,d2          ; MODE_NEWFILE, um S:NoWarning-File neu anzulegen
 movem.l d1-d7/a0-a6,-(sp) ; -> EXCLUSIVE_LOCK
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   noErrorNoWarning  ; immer noch Error, z.B. weil S:NoWarning-File
unknowndevice2:
 bsr     openerror         ; bereits von anderem 'Laufwerk-Aufruf' EXKLUSIVE
 bra     OpenFailed        ; geöffnet wurde
noErrorNoWarning:
 move.l  d0,d1             ; filehandle
nextbootblock2:
 move.l  a5,a2
 lea     Nobuff(pc),a0
 move.l  a0,d2             ; Vektor-Kontroll-Task-Stackboden
 move.l  #1024,d3          ; als 1024-Puffer benutzen
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -42(a6)           ; ersten Bootblock aus S:NoWarning lesen
 movem.l (sp)+,d1-d7/a0-a6
 cmp.l   #1024,d0          ; kein Bootblock mehr zu lesen -> Fileende
 bne     appendnext        ; File nach Eintrag durchsuchen, hierbei eventueller
 move.w  #$ff,d0           ; freier Block merken, wird mit Eintrag beschrieben
NoWarningloop2:            ; wenn kein Eintrag vorhanden war. wenn nichts frei
 cmp.l   #"FREE",(a0)      ; wird File verlängert. Wenn Eintrag vorhanden, wird
 bne.s   notfree           ; der Block lediglich als FREE markiert zurückge-
 bsr     getposition       ; schrieben wird, deshalb auch völlig egal wenn File
notfree:                   ; nicht ganz durchsuche.
 cmpm.l  (a0)+,(a2)+
 bne.s   nextbootblock2
 dbra    d0,NoWarningloop2
 bsr     alreadynoset      ; Bootblock bereits in S:NoWarning enthalten
 beq     CloseFileDOS      ; Bootblock in S:NoWarning belassen
 bsr     getposition       ; um jetzige Position zu erhalten, freeposition egal
 sub.l   #1024,d0          ; da ja nur FREE markiere
 move.l  d0,d2
 bsr     seekback1
 move.l  (a5),-(sp)        ; da für Weiterarbeit wiederherstellen muß
 move.l  #"FREE",(a5)
 move.l  a5,d2             ; d2 = bootblockpuffer
 move.l  #1024,d3          ; d3 = Anzahl der zu schreibenden Bytes
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -48(a6)           ; Bootblock als FREE schreiben,
 movem.l (sp)+,d1-d7/a0-a6
 move.l  (sp)+,(a5)
 bra     CloseFileDOS

testgad12:                 ; in VirusName-File
 cmp.w   #12,d5
 bne     testgad13
 move.l  a4,d0             ; a4 vor überschreiben durch movem retten
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 move.l  d0,a4
 bsr     namecorrect
 beq     openwindow
 movem.l d0-d7/a0-a6,-(sp)
 lea     freeposition(pc),a0
 clr.l   (a0)
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 lea     VirusName(pc),a0
 move.l  a0,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, um altes S:VirusName-File
 bsr     checkdevicename   ; zu öffnen, EXCLUSIVE_LOCK nötig, da schreibend
 tst.l   d0                ; zugreife, denn wenn kein EXCLUSIVE-LOCK, könnte
 beq.s   unknowndevice3    ; ein anderer 'Laufwerk-Aufruf' ebenfalls gleich-
 movem.l d1-d7/a0-a6,-(sp) ; zeitig schreibend zugreifen -> falsche Daten
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   noErrorVirusName
 move.l  #1006,d2          ; MODE_NEWFILE, um S:VirusName-File neu anzulegen
 movem.l d1-d7/a0-a6,-(sp) ; -> EXCLUSIVE_LOCK
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   noErrorVirusName  ; immer noch Error, z.B. weil S:VirusName-File
unknowndevice3:
 bsr     openerror         ; bereits von anderem 'Laufwerk-Aufruf' EXKLUSIVE
 bra     OpenFailed        ; geöffnet wurde
noErrorVirusName:
 move.l  d0,d1             ; filehandle
nextbootblock3:
 lea     onediff1(pc),a0
 clr.b   (a0)
 lea     Vibuff(pc),a0
 move.l  a0,d2                ; Vektor-Kontroll-Task-Stackboden
 move.l  #1024+buff1-buff0,d3 ; als 1024+32-Puffer benutzen
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -42(a6)             ; ersten Virusname+Bootblock aus S:VirusName lesen
 movem.l (sp)+,d1-d7/a0-a6
 cmp.l   #1024+buff1-buff0,d0
 bne.s   fileende2
 lea     oldname(pc),a2
 bsr     copyname
 move.w  #$ff,d0
 move.l  a5,a2
VirusNameloop1:
 cmp.l   #"FREE",(a0)
 bne.s   notfree1
 bsr     getposition       ; während ich notfalls ganzes File nach Eintrag
notfree1:                  ; absuche, freeposition schon mal merken
 cmpm.l  (a0)+,(a2)+
 beq.s   issame1
 movem.l a0/a1,-(sp)
 lea     onediff1(pc),a0
 tst.b   (a0)
 movem.l (sp)+,a0/a1
 bne.s   nextbootblock3
countit1:
 movem.l a0/a1,-(sp)
 lea     onediff1(pc),a0   ; 1 Longword-Unterschied erfassen
 move.b  #$ff,(a0)         ; Flag für 1 Longword-Unterschied
 movem.l (sp)+,a0/a1
issame1:
 dbra    d0,VirusNameloop1
 bsr     alreadyviset      ; gefunden !
 beq     CloseFileDOS
 bsr     getposition
 sub.l   #1024+buff1-buff0,d0 ; minus 1 Eintrag
 move.l  d0,d2
 bsr     seekback1
 move.l  a4,a0
 lea     nameoverwrite(pc),a2
 bsr     copyname
 bsr     alreadyviwork
 beq.s   nixfrei3          ; mit neuem Namen überschreiben
 move.l  #"FREE",(a5)
 bra.s   nixfrei3          ; als FREE markieren
fileende2:                 ; nicht gefunden !
 move.l  freeposition(pc),d2
 beq.s   nixfrei3          ; wenn freier Eintrag, dann diesen setzen
 sub.l   #1024+buff1-buff0,d2
 bsr     seekback1
nixfrei3:
 move.l  a4,d2             ; 32-Byte-VirusName
 moveq   #buff1-buff0,d3
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -48(a6)           ; VirusName an S:VirusName hängen
 movem.l (sp)+,d1-d7/a0-a6
 bra.s   nixfrei
appendnext:
 move.l  freeposition(pc),d2
 beq.s   nixfrei
 sub.l   #1024,d2          ; wenn freier Eintrag, dann diesen setzen
 bsr     seekback1
nixfrei:
 move.l  a5,d2             ; d2 = bootblockpuffer
 move.l  #1024,d3          ; d3 = Anzahl der zu schreibenden Bytes
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -48(a6)           ; bootblock an File hängen
 movem.l (sp)+,d1-d7/a0-a6 ; Stackebene wird erst in CloseFileDos restauriert
 move.l  $4.w,a3           ; dennoch bootblockread, da a1=IORequest unverändert
 exg     a3,a6             ; bootblockread verändert d1=filehandle nicht
 bsr     bootblockread     ; FREE-Markirung überschreiben, damit korrekt
 exg     a3,a6             ; weiterarbeiten kann, hier immer CMD_READ
 bra     CloseFileDOS

testgad13:                 ; deletevirus
 cmp.w   #13,d5
 bne.s   testgad14
 lea     gadtext13(pc),a1  ; in Autorequester wegen Farben 'unsichtbar',
 bsr     kill              ; in a6 steht exec.base
 bra     nopush

testgad14:                 ; File - Schutz
 cmp.w   #14,d5
 bne     testgad15
 move.l  a4,d0
 movem.l (sp)+,d1-d7/a0-a6 ; a1=IORequest
 move.l  d0,a4
 moveq   #0,d4             ; Flag für check directory (noloadfi:) löschen
 movem.l d0-d7/a0-a6,-(sp)
 bsr     OpenDOS           ; OpenLibrary("dos.library",0);
 move.l  a4,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, da existierendes File lesen will,
 bsr     checkdevicename   ; sicherheitshalber kein MODE_OLDFILE, damit
 tst.l   d0                ; kein anderes Programm durch Schreiben stört
 beq     nodirectory
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -30(a6)
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne     noErrorFile1
 move.l  a4,d1             ; Directory eingetragen ?
 moveq   #-2,d2            ; ACCESS_READ
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -84(a6)           ; Lock()
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 beq     nodirectory       ; auch kein Directory eingetragen
 move.l  d0,-(sp)          ; für Unlock()     RETTEN
 move.l  d0,d1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -126(a6)          ; cd auf eingetragenes directory
 movem.l (sp)+,d1-d7/a0-a6
 move.l  d0,-(sp)          ; für restaurieren RETTEN
 movem.l d1-d7/a0-a6,-(sp)
 move.l  #260,d0           ; Speicher für struct FileInfoBlock belegen
 moveq   #1,d1
 move.l  $4.w,a6           ; entsprechend Speicher anfordern
 jsr     -198(a6)
 movem.l (sp)+,d1-d7/a0-a6
 move.l  d0,d2
 beq.s   mmm
 move.l  d0,-(sp)          ; Speicheradresse  RETTEN
 move.l  8(sp),d1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -102(a6)          ; Examine()
 movem.l (sp)+,d1-d7/a0-a6
 moveq   #-1,d4            ; Flag für check directory (noloadfi:)
exnext:
 move.l  8(sp),d1          ; Lock
 move.l  (sp),d2           ; Speicher für FileInfoBlock
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -108(a6)          ; ExNext()
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0                ; d0=0 wenn keine Files mehr vorhanden
 beq.s   kkk
 move.l  d2,a0
 lea     8(a0),a4
 move.l  a4,d1             ; Filename-Adresse nach d1
 move.l  #1004,d2          ; MODE_READWRITE, da existierendes File lesen will,
 movem.l d1-d7/a0-a6,-(sp) ; sicherheitshalber kein MODE_OLDFILE, damit
 jsr     -30(a6)           ; kein anderes Programm durch Schreiben stört
 movem.l (sp)+,d1-d7/a0-a6
 tst.l   d0
 bne.s   noErrorFile1
 bra.s   exnext            ; wenn Directory
kkk:
 move.l  a1,a0             ; IORequest retten
 move.l  (sp)+,a1
 move.l  #260,d0
 movem.l d1-d7/a0-a6,-(sp)
 move.l  $4.w,a6
 jsr     -210(a6)          ; FreeMem
 movem.l (sp)+,d1-d7/a0-a6
 move.l  a0,a1
mmm:
 move.l  (sp)+,d1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -126(a6)          ; cd wiederherstellen
 movem.l (sp)+,d1-d7/a0-a6
 move.l  (sp)+,d1
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -90(a6)           ; Unlock()
 movem.l (sp)+,d1-d7/a0-a6
 move.l  $4.w,a3           ; Stackebene wird erst in CloseFileDos restauriert
 exg     a3,a6             ; dennoch bootblockread, da a1=IORequest unverändert
 bsr     bootblockread     ; bootblockread verändert d1=filehandle nicht
 exg     a3,a6             ; Bootblockpuffer wiederherstellen
 bra     Openfailed
nodirectory:
 bsr     openerror         ; OpenError wegen z.B verbotenem Filenamen
 bra     OpenFailed        ; -> eigener Requester erforderlich
noErrorFile1:
 move.l  d0,d1             ; filehandle für späteres read() und close() retten
nextbootblock4:
 move.l  a5,a0             ; mit 0 vorbelegen, damit nicht zufällig Kennung in
 bsr     clear1024         ; Puffer steht, wenn nur < 1024 aus File lesen kann
 bsr     testfile          ; erste 1024 Bytes aus File in Bootblockpuffer lesen
 cmp.l   #$000003f3,(a5)
 beq.s   isloadfile
 bsr     noloadfile
 bra     noloadfi
isloadfile:
 move.w  #$ff,d0
 move.l  a5,a2             ; d0 und a2 als Zähler
piusloop:
 cmp.l   #$000003e8,(a2)+
 bne.s   cvb
 subq.l  #1,d0
 bpl.s   yyx
 bsr     testfile          ; nächste 1024 Bytes lesen
 tst.l   d0                ; Fileende ?
 beq.s   bbn
 move.w  #$ff,d0
 move.l  a5,a2             ; d0 und a2 als Zähler
yyx:
 cmp.l   #$00000002,(a2)+
 bne.s   cvb
 subq.l  #1,d0
 bpl.s   yyy
 bsr     testfile          ; nächste 1024 Bytes lesen
 tst.l   d0                ; Fileende ?
 beq.s   bbn
 move.w  #$ff,d0
 move.l  a5,a2             ; d0 und a2 als Zähler
yyy:
 cmp.l   #"PIUS",(a2)+
 beq.s   marked
cvb:
 dbra    d0,piusloop
 bsr     testfile          ; nächste 1024 Bytes lesen
 tst.l   d0                ; Fileende ?
 bne.s   isloadfile
bbn:
 bsr     schuetzenodweiter
 beq     noloadfi
 bsr     setend            ; Filelänge holen
 lea     Kennung(pc),a0
 move.l  d0,Kennzahl-Kennung(a0)
 move.l  a0,d2
 moveq   #20,d3
 movem.l d0-d7/a0-a6,-(sp)
 jsr     -48(a6)           ; an das File die Kennung anhängen
 movem.l (sp)+,d0-d7/a0-a6
 bra     noloadfi
marked:
 tst.l   d0                ; muß nächster 1024-Block gelesen werden ?,
 bne.s   notblockend       ; da ich ja ursprüngliche Filelänge brauche
 bsr     testfile
 move.l  a5,a2
notblockend:
 bsr     setend            ; setend gibt in d0 aktuelle Filelänge zurück
 sub.l   #20,d0            ; Kennung von Filelänge abziehen
 move.l  d0,d7             ; Filelänge retten
 cmp.l   (a2),d0           ; d0=aktuelle Filelänge  a2=ursprüngliche Filelänge
 beq.s   fileokay
 bsr     filedanger
 bra     noloadfi
fileokay:
 bsr     FileIsOkay
noloadfi:
 tst.l   d4
 beq.s   onlyfile
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -36(a6)           ; Close() file
 movem.l (sp)+,d1-d7/a0-a6
 bra     exnext
onlyfile:
 move.l  $4.w,a3           ; Stackebene wird erst in CloseFileDos restauriert
 exg     a3,a6             ; dennoch bootblockread, da a1=IORequest unverändert
 bsr     bootblockread     ; bootblockread verändert d1=filehandle nicht
 exg     a3,a6             ; Bootblockpuffer wiederherstellen
 bra     CloseFileDOS      ; da ja durch Filebytes überschrieben wurde

testgad15:                 ; CheckOpen
 cmp.w   #15,d5
 bne.s   testgad16
 jsr     -132(a6)
 lea     openflag(pc),a0
 not.b   (a0)
 lea     gadtext15text(pc),a1
 move.l  #"AUS ",14(a1)
 tst.b   (a0)
 bne.s   aus1
 move.l  #" AN ",14(a1)
aus1:
 jsr     -138(a6)
 bra     nopush

testgad16:                 ; Files durchsuchen
; cmp.w   #16,d5
; bne.s   testgad17
 jsr     -132(a6)
 lea     searchfiles(pc),a0
 not.b   (a0)
 lea     gadtext16text(pc),a1
 move.l  #"AUS ",14(a1)
 tst.b   (a0)
 beq.s   aus2
 move.l  #" AN ",14(a1)
aus2:
 jsr     -138(a6)
 bra     nopush

; testgad17:

namecorrect:
 movem.l a0-a3,-(sp)
 jsr     -132(a6)
 move.l  a4,a0
 lea     correctname(pc),a2; den aktuellen Stringadget-Puffer-Inhalt
 bsr     copyname          ; in Intuitext-Struktur kopieren
 bsr     modifyunit        ; und anzeigen, ob okay
 lea     CORRECT(pc) ,a1
 bra.s   shorter1

reallyexit:
 movem.l a0-a3,-(sp)       ; Sicherheitsabfrage, ob VirusControl wirklich
 jsr     -132(a6)          ; verlassen werden soll
 lea     EXIT(pc) ,a1
 bra.s   shorter1

writebbzugriff:
 movem.l a0-a3,-(sp)       ; Schreibzugriff auf Bootblock in Lesen wandeln ?
 jsr     -132(a6)
 bsr     modifyunit
 lea     WRITEBB(pc) ,a1
 bra.s   shorter1

reallyoverwrite:
 movem.l a0-a3,-(sp)       ; Sicherheitsabfrage, ob Bootblock wirklich
 jsr     -132(a6)          ; überschrieben werden soll
 bsr     modifyunit
 lea     OVERWRITE(pc) ,a1
shorter1:
 lea     OVERWRITEL(pc),a2
 lea     OVERWRITER(pc),a3
shorter2:
 bsr     autorequest
 jsr     -138(a6)
 movem.l (sp)+,a0-a3
 tst.l   d0                ; rts verändert keine Flags
 rts

fileprotect:
 movem.l a0-a3,-(sp)
 jsr     -132(a6)
 move.l  a4,a0
 lea     checkfilename(pc),a2
 bsr     copyname
 lea     FILESCHUTZ(pc),a1
 bra.s   shorter1

openerror:                 ; zeigt Open-Error an
 movem.l a0-a6,-(sp)       ; da in a6 dosbase steht
 move.l  $4.w,a6           ; aber autorequest in a6 exec.base erwartet
 jsr     -132(a6)
 bsr     modifyunit
 lea     OPENERR(pc),a1
shorter7:
 lea     NOBOOTR(pc),a2
shorter5:
 lea     NOBOOTR(pc),a3
shorter6:
 bsr     autorequest
 jsr     -138(a6)
 movem.l (sp)+,a0-a6
 tst.l   d0
 rts

alreadynoset:              ; Requester, welcher erscheint, wenn Bootblock
 movem.l a0-a6,-(sp)       ; bereits in S:NoWarning vorhanden ist.
 move.l  $4.w,a6
 jsr     -132(a6)
 bsr     modifyunit
 lea     ALREADYNO(pc),a1
 lea     ALREADYNOdel(pc),a2
 bra.s   shorter5

alreadyviset:              ; Requester, welcher erscheint, wenn Bootblock
 movem.l a0-a6,-(sp)       ; bereits in S:VirusName vorhanden ist.
 move.l  $4.w,a6
 jsr     -132(a6)
 bsr     modifyunit
 lea     ALREADYVI(pc),a1
 lea     ALREADYWORK(pc),a2
 bra.s   shorter5

alreadyviwork:             ; Requester, welcher folgendes anbietet
 movem.l a0-a6,-(sp)       ; Bootblock+Name aus S:VirusName entfernen oder
 move.l  $4.w,a6           ; alten Namen durch neuen Namen ersetzen
 jsr     -132(a6)
 bsr     modifyunit
 lea     ALREADYVI(pc),a1
 lea     ALREADYNOdel(pc),a2
 lea     ALREADYNOnam(pc),a3
 bra.s   shorter6

noloadfile:
 movem.l a0-a6,-(sp)       ; da in a6 dosbase steht
 move.l  $4.w,a6           ; aber forbid und autorequest exec.base erwartet
 jsr     -132(a6)
 move.l  a4,a0
 lea     keinloadfile(pc),a2
 bsr     copyname
 lea     noloadf(pc),a1
 bra     shorter7

filedanger:
 movem.l a0-a6,-(sp)       ; da in a6 dosbase steht
 move.l  $4.w,a6           ; aber forbid und autorequest exec.base erwartet
 jsr     -132(a6)
 move.l  a4,a0
 lea     linkname(pc),a2
 bsr     copyname
 lea     link(pc),a1
 bra     shorter7

FileIsOkay:
 movem.l a0-a6,-(sp)       ; da in a6 dosbase steht
 move.l  $4.w,a6           ; aber forbid und autorequest exec.base erwartet
 jsr     -132(a6)
 move.l  a4,a0
 lea     checkfilename(pc),a2
 bsr     copyname
 lea     FILESCHUTZ(pc),a1
 lea     okk(pc),a2
 lea     okk(pc),a3
 bra     shorter6

schuetzenodweiter:
 movem.l a0-a6,-(sp)       ; da in a6 dosbase steht
 move.l  $4.w,a6           ; aber forbid und autorequest exec.base erwartet
 jsr     -132(a6)
 move.l  a4,a0
 lea     checkfilename(pc),a2
 bsr     copyname
 lea     FILESCHUTZ(pc),a1
 lea     neusch(pc),a2
 bra     shorter5

allowaccess:
 movem.l a0-a3,-(sp)   ; Zugriff auf File erlauben ?
 move.l  $4.w,a6
 jsr     -132(a6)
 move.l  d1,a0
 lea     filewrite(pc),a2
 bsr     copyname
 lea     OPENFILEnam(pc) ,a1
 bra     shorter1

getposition:
 moveq   #0,d2
 moveq   #0,d3
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -66(a6)           ; Seek() -> aktuelle Fileposition holen
 lea     freeposition(pc),a0
 move.l  d0,(a0)           ; position merken
 movem.l (sp)+,d1-d7/a0-a6
 rts

seekback1:
 moveq   #-1,d3
seekit:
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -66(a6)
 movem.l (sp)+,d1-d7/a0-a6
 rts

addtask:
 ; mittels addtask task einbinden, welcher die Systemvektoren 1* pro Sekunde
 ; überprüft, in coolroutine kann man addtask noch nicht aufrufen->Absturz
 ; in coolroutine sind nur einige exec-routinen aufrufbar.
 movem.l d0-d7/a0-a6,-(sp); alle Register retten
 lea     structtask(pc),a1
 lea     task(pc),a2
 sub.l   a3,a3  ; 2 Bytes statt  6 Bytes(move.l #0,a3)
 jsr     -282(a6)       ; addtask
 movem.l (sp)+,d0-d7/a0-a6
 rts

deletevirus:
 bsr     optzeichen
 clr.l   546(a6)           ; KickMemPtr löschen
 clr.l   550(a6)           ; KickTagPtr löschen
 clr.l   554(a6)           ; KickCheckSum löschen
 clr.l   42(a6)            ; COLD-Vektor löschen
 move.l  58(a6),a0         ; 1024 Bytes am Supervisorstackboden löschen,
 bsr.s   clear1024         ; da sich dort oft Viren einnisten
 move.l  BeginIOAdr(pc),a0 ; Original-BeginIO-Vektor setzen
 move.l  restoreIO(pc),(a0); und zwar ROM-version-unabhängig
VCrestore:
 lea     lastBeginIO(pc),a0; letzten BeginIO-Wert löschen
 clr.l   (a0)
 lea     lastKickMem(pc),a0
 clr.l   (a0)+             ; lastKickMem löschen
 clr.l   (a0)+             ; lastKickTag löschen
 clr.l   (a0)              ; lastKickCheck löschen
 lea     newDOIO(pc),a0    ; muß DOIO bei jedem reset wieder neu auf newDOIO
 move.l  a0,-454(a6)       ; verbiegen, da auf Originalwert zurückgesetzt wurde
 move.l  a0,-(sp)
 lea     lastDOIO(pc),a0   ; VIRUS-CONTROL-DOIO-Wert als lastDOIO setzen
 move.l  (sp)+,(a0)
execchecksum:
 lea     lastCOOL(pc),a0
 move.l  pointer(pc),(a0)   ; VIRUS-CONTROL-COOL-Wert als lastCOOL setzen
 move.l  pointer(pc),$2e(a6); Cool-Vektor auf VIRUS-CONTROL verbiegen
 lea     $22(a6),a0         ; Execchecksumme neu berechnen
 clr.w   d0                 ; Cool-Vektor und Execchecksum bleibt bei
 moveq   #$17,d1            ; Reset erhalten
execcheck:
 add.w   (a0)+,d0
 dbra    d1,execcheck
 not.w   d0
 move.w  d0,(a0)
 rts

clear1024:
 move.w   #$00ff,d0     ; dbra arbeitet nur mit Word-breite
clearloop:              ; Einsprung mit d0=$007f löscht 128 * 4 = 512 Bytes
 clr.l   (a0)+
 dbra    d0,clearloop   ; 256 * 4 = 1024 Bytes löschen
 rts

Bootblockclear:
 move.l  a5,a0
 move.l  a0,a2
 bra.s   clear1024

nameunknown:
 movem.l d0-d7/a0-a6,-(sp)
 lea     NAME0text(pc),a2
 moveq   #buff1-buff0+20,d0
 mulu    d6,d0
 add.l   d0,a2          ; Virusname mit unbekannt überschreiben
 lea     unknown(pc),a0
 bsr.s   copyname
 movem.l (sp)+,d0-d7/a0-a6
 rts

copyname:
 moveq   #buff1-buff0-1,d0
copyvirusname:
 move.b  (a0)+,(a2)+
 dbra    d0,copyvirusname
 rts

checkdevicename:           ; df0:-trackdisk.device-task oft task-held, wenn
 movem.l d1-d7/a0-a6,-(sp) ; versucht wird, nicht vorhandenes Device zu öffnen
 move.l  d1,a4             ; bei df1: df2: df3:-trackdisk.device-task kein
 move.l  d1,a0             ; task-held, sondern es erscheint Systemrequester
 move.l  $4.w,a3           ; warum stürzt nur df0: ab ???
 exg     a3,a6             ; Um df0:-task-held zu verhindern, vorher prüfen,
 jsr     -132(a6)          ; ob Devicename angegeben ist, und wenn ja, ob das
 exg     a3,a6             ; angegebene Device vorhanden ist
 moveq   #-1,d0
isitdevice:
 tst.b   (a0)              ; Filename
 beq.s   searchend         ; ende mit d0=$ffffffff, wenn kein Device angegeben
 cmp.b   #":",(a0)+
 bne.s   isitdevice
 move.l  34(a6),a0         ; RootNode
 move.l  24(a0),d0         ; DosInfo
 lsl.l   #2,d0             ; BPTR * 4 = APTR
 move.l  d0,a0
 move.l  4(a0),d0          ; DevInfo
nextdevice:
 move.l  a4,a3             ; a3 mit Filename-Adresse laden
 lsl.l   #2,d0             ; BPTR * 4 = APTR
 move.l  d0,a0
 move.l  40(a0),d0         ; DeviceName
 lsl.l   #2,d0             ; BPTR * 4 = APTR
 move.l  d0,a2
 move.b  (a2)+,d1          ; erstes Byte = Stringlänge (BSTR)
 ext.w   d1                ; wegen dbra auf wordbreite bringen
 subq.w  #1,d1             ; da dbra bis -1 zählt
testdevice:
 cmpm.b  (a2)+,(a3)+
 bne.s   testgrossklein
teston:
 dbra    d1,testdevice
 cmp.b   #":",(a3)
 beq.s   isdevice
 moveq   #0,d0
 bra.s   searchend         ; z.B. RAMM: statt RAM: eingegeben
isdevice:
 moveq   #-1,d0            ; Device existiert -> d0 = $ffffffff
 bra.s   searchend
testgrossklein:            ; da AmigaDOS Groß/Klein nicht unterscheidet,
 add.b   #32,-(a3)         ; muß ich ebenso verfahren
 subq.l  #1,a2
 cmpm.b  (a2)+,(a3)+       ; klappt der Vergleich als Groß-Buchstabe ?
 beq.s   teston
 sub.b   #64,-(a3)
 subq.l  #1,a2
 cmpm.b  (a2)+,(a3)+       ; klappt der Vergleich als Klein-Buchstabe ?
 beq.s   teston
 add.b   #32,-(a3)         ; wieder Original-Wert restaurieren
 move.l  (a0),d0           ; wenn kein Device mehr -> d0 = 0
 bne.s   nextdevice        ; NextDevice
searchend:
 move.l  $4.w,a6
 jsr     -138(a6)          ; okay wenn d0=$ffffffff, der Fall, wenn kein Device
 movem.l (sp)+,d1-d7/a0-a6 ; angegeben oder wenn angegebenes  Device existiert.
 rts                       ; d0=0, wenn ein angegebenes Device nicht existiert

OpenIntuition:             ; OpenLibrary("intuition.library",0);
 movem.l d1-d7/a0-a6,-(sp) ; verändert d0,a6
 lea     intuition(pc),a1
 bra.s   shorter3

OpenDOS:                   ; OpenLibrary("dos.library",0);
 movem.l d1-d7/a0-a6,-(sp) ; verändert d0,a6
 lea     dosname(pc),a1
shorter3:
 moveq   #0,d0             ; Version >= 0
 jsr     -552(a6)          ; OpenLibrary("intuition.library",0)
 movem.l (sp)+,d1-d7/a0-a6
 move.l  d0,a6             ; base nach a6
 rts                       ; da in ROM, testen praktisch überflüssig

CloseFile:
 jsr     -36(a6)           ; Close() file
CloseDOS:
 move.l  a6,a1
 move.l  $4.w,a6
 jmp     -414(a6)          ; CloseLibrary("dos.library",0) + rts

clearflags:
 lea     exitcount(pc),a0
 subq.b  #1,(a0)           ; exitcount -1 wenn Arbeit mit Diskette beendet ist
 lea     inuse0(pc),a0
 add.l   d6,a0
 clr.b   (a0)              ; inuse-Flag des Laufwerks löschen
 rts

settimer:
 sub.l   a1,a1
 jsr     -294(a6)
 lea     timeport(pc),a1
 move.l  d0,16(a1)
 jsr     -354(a6)
 lea     timerdev(pc),a0
 lea     timereq(pc),a1    ; Task schickt Message(=request) an den task des
 moveq   #1,d0             ; timer.devices, wenn Zeit um, schickt der task des
 moveq   #0,d1             ; timer.devices Message an den Port meines Tasks,
 jsr     -444(a6)          ; da ja meine Port-Adresse in request eingetragen.
 lea     timeport(pc),a3   ; Das Eintreffen der Message am Port erkennt mein
 lea     timereq(pc),a1    ; Task, da in dem Port meine Task-Adresse als der
 move.l  a3,14(a1)         ; zu benachrichtigende Task steht
 rts

freemem:
 move.l  #end-reset+9000,d0 ; Bytesize
 move.l  pointer(pc),a1
 jmp     -210(a6)           ; FreeMem + rts

remreqport:
 lea     timereq(pc),a1
 jsr     -450(a6)          ; CloseDevice()
 lea     timeport(pc),a1
 jmp     -360(a6)          ; RemPort()

restoreopen:
 lea     jmpoldopen(pc),a0
 move.l  dosbase(pc),a4
 cmp.w   #$4ef9,-30(a4)
 bne.s   notchanged
 jsr     -120(a6)          ; Disable(), da theoretisch Taskswitch nach 1 Befehl
 move.w  (a0),-30(a4)      ; Open() restaurieren
 move.l  8(a0),-28(a4)
 jsr     -126(a6)          ; Enable()
notchanged:
 rts

testfile:
 move.l  a5,d2             ; d2 = Puffer, in den die Bytes eingelesen werden
 move.l  #1024,d3          ; d3 = Anzahl der zu lesenden Bytes
 movem.l d1-d7/a0-a6,-(sp)
 jsr     -42(a6)           ; Read()
 movem.l (sp)+,d1-d7/a0-a6
 rts

setend:                    ; in d0 wird Filelänge zurückgegeben
 moveq   #0,d2
 moveq   #1,d3             ;  END
 bra     seekit

openflag:      dc.b $ff ; $ff -> Open() wird von Kontroll-Task nicht verbogen
opencount:     dc.b 0   ; OpenRequester-Anzahl, ENDE erst wenn = 0
colorflag:     dc.b $ff ; grünes Farb-Signal bei Disk-Einlegen
searchfiles:   dc.b $ff ; durchsuche eventuelles S:NoWarning, S:VirusName-File
taskflag:      dc.b $ff ; $ff -> Task beginnt sofort mit Vektorenkontrolle
resetflag:     dc.b 0   ; um den ersten Disk-DOIO-Zugriff zu ignorieren
exitflag:      dc.b 0   ; wird gesetzt, wenn VIRUS-CONTROL entfernt werden soll
exitcount:     dc.b 0   ; exitcount = Warn-Window-Anzahl, ENDE erst wenn = 0
inuse0:        dc.b 0   ; wenn inuse-Flag des Laufwerkes gesetzt ist, wird
inuse1:        dc.b 0   ; kein weiteres Warn-Window aufgerufen
inuse2:        dc.b 0
inuse3:        dc.b 0
pointer:       dc.l 0   ; Zeiger auf Speicherbereich für VIRUS-CONTROL
BeginIOAdr:    dc.l 0   ; Adresse des BeginIO-Vektors des trackdisk-devices
lastBeginIO:   dc.l 0   ; letzter BeginIO-Vektor-Wert
restoreIO:     dc.l 0   ; BeginIO-Wert für Virus-Entfern-Versuch, kann je nach
; Betriebssystem-Version verschieden sein, daher etwas aufwendiger programmiert
lastKickMem:   dc.l 0
lastKickTag:   dc.l 0
lastKickCheck: dc.l 0
lastDOIO:      dc.l newdoio-reset ; für CLI-Start setzen
lastCOOL:      dc.l reset-reset   ; für CLI-Start setzen
freeposition:  dc.l 0
dosbase:       dc.l 0
onediff1:      dc.b 0
nochfrei:      dc.b 0
intuition:     dc.b "intuition.library",0
 even
timerdev:      dc.b "timer.device",0
 even
unknown:       dc.b "Name nicht bekannt !           ",0
unknownend:    even
NoWarning:     dc.b "S:NoWarning",0
 even
VirusName:     dc.b "S:VirusName",0
 even
Kennung:       dc.l $000003e8  ; Modul-Name-Kennung
               dc.l $00000002  ; Name 2 Longword lang
               dc.b  "OIUS"    ; Markierung (wird bei Start zu PIUS)
Kennzahl:      dc.l $00000000  ; ursprüngliche Filelänge
               dc.l $000003f2  ; Modul-Ende-Kennung
filename:
 dc.b "RAW:0/0/640/170/BOOTBLOCK-DF"
unit4:                       dc.b "0:  weiter mit Taste ",0
 even
; Bei Booten ist der Standardzeichensatz Topaz 9 eingestellt ist, wodurch
; 60 Zeichen in Zeile dargestellt werden. Deshalb RAW: mit y=170 öffnen,
; damit der gesamte Bootblock ohne Wegscrollen dargestellt wird.
; RAW: statt CON:, damit auch mit z.B. F-tasten oder Cursor-tasten weiter.
; Die Systemconfiguration wird erst am Ende der Bootroutine ausgewertet.

NOBOOT:       ; topaz80, da topaz60 zu lang,
 dc.b 1,0,0,0 ; weil rechts neben Gadgets ausgegeben wird
 dc.w 7,8
 dc.l font-reset,NOBOOTtext-reset,0
NOBOOTtext:
 dc.b "Bootblock-Virus in DF"
unit0:         dc.b "0: ?       PUBLIC DOMAIN !! CONTACTS WELCOMED !!",0
 even
NAME0:
 dc.b 1,0,0,0
 dc.w 0,0
 dc.l font-reset,NAME0text-reset,0
NAME0text:
 dc.b "                               ",0
 even
NAME1:
 dc.b 1,0,0,0
 dc.w 0,0
 dc.l font-reset,NAME1text-reset,0
NAME1text:
 dc.b "                               ",0
 even
NAME2:
 dc.b 1,0,0,0
 dc.w 0,0
 dc.l font-reset,NAME2text-reset,0
NAME2text:
 dc.b "                               ",0
 even
NAME3:
 dc.b 1,0,0,0
 dc.w 0,0
 dc.l font-reset,NAME3text-reset,0
NAME3text:
 dc.b "                               ",0
 even
ONEDIFF:
 dc.b 1,0,0,0
 dc.w 0,0
 dc.l font-reset,ONEDIFFtext-reset,0
ONEDIFFtext:
 dc.b "1 Longword-Unterschied",0
 even
OPENERR:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,OPENERRtext-reset,0
OPENERRtext:
 dc.b "Warn-Window-DF"
unit3:         dc.b "0: Open-Error",0
 even
CORRECT:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,CORRECTtext-reset,0
CORRECTtext:
 dc.b "String-Gadget-Inhalt-DF"
unit5: dc.b "0: richtig ? "
correctname:        dc.b "                                  ",0
 even
NOBOOTR:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l font-reset,NOBOOTRtext-reset,0
NOBOOTRtext: dc.b " ENDE ",0
 even
PROTECT:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,PROTECTtext-reset,0
PROTECTtext:
 dc.b "Disk in DF"
unit2:     dc.b "0: ist schreibgeschützt !",0
 even
PROTECTL:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,PROTECTLtext-reset,0
PROTECTLtext: dc.b " NEUER VERSUCH ",0
 even
ALREADYNO:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,ALREADYNOtext-reset,0
ALREADYNOtext:
 dc.b "Bootblock DF"
unit6:       dc.b "0: schon in S:NoWarning !",0
 even
ALREADYNOdel:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,ALREADYNOdeltext-reset,0
ALREADYNOdeltext:
 dc.b " ENTFERNEN ",0
 even
ALREADYVI:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,ALREADYVItext-reset,0
ALREADYVItext:
 dc.b "Bootblock DF"
unit7:       dc.b "0: schon in S:VirusName: "
oldname:                              dc.b "                               ",0
 even
ALREADYWORK:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,ALREADYWORKtext-reset,0
ALREADYWORKtext:
 dc.b " ENTFERNEN oder UEBERSCHREIBEN ",0
 even
ALREADYNOnam:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l font-reset,ALREADYNOnamtext-reset,0
ALREADYNOnamtext:
 dc.b " UEBERSCHREIBEN mit "
nameoverwrite:       dc.b "                               ",0
 even
OPENFILEnam:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,OPENFILEnamtext-reset,0
OPENFILEnamtext:
 dc.b "ACHTUNG: ZUGRIFF auf "
filewrite:           dc.b "                               ",0
 even
EXIT:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,EXITtext-reset,0
EXITtext:
 dc.b "VIRUS-CONTROL wirklich entfernen ?",0
 even
neusch:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,neuschtext-reset,0
neuschtext:
 dc.b " Schützen ",0
 even
okk:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,okktext-reset,0
okktext:
 dc.b " File okay ",0
 even
noloadf:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,noloadftext-reset,0
noloadftext:
 dc.b "kein load-file: "
keinloadfile:        dc.b "                               ",0
 even
FILESCHUTZ:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,FILESCHUTZtext-reset,0
FILESCHUTZtext:
 dc.b "File-Schutz: "
checkfilename:       dc.b "                               ",0
 even
link:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,linktext-reset,0
linktext:
 dc.b "Filelänge verändert !! -> LINK-VIRUS ?? -> "
linkname: dc.b "                               ",0
 even
WRITEBB:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l font-reset,WRITEBBtext-reset,0
WRITEBBtext:
 dc.b "ACHTUNG: SCHREIBZUGRIFF auf Bootblock DF"
unit8:                                   dc.b "0:  in Lesen wandeln ?",0
 even
OVERWRITE:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,OVERWRITEtext-reset,0
OVERWRITEtext:
 dc.b "Bootblock  in DF"
unit1:          dc.b "0: wirklich überschreiben ?",0
 even
OVERWRITEL:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,OVERWRITELtext-reset,0
OVERWRITELtext: dc.b "  JA  ",0
 even
OVERWRITER:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,OVERWRITERtext-reset,0
OVERWRITERtext: dc.b " NEIN ",0
 even
BOOT:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,NOBOOTtext-reset,0
BOOTL:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,BOOTLtext-reset,0
BOOTLtext: dc.b " Disk-Boot-Routine ",0
 even
BOOTR:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l 0,BOOTRtext-reset,0
BOOTRtext: dc.b " Boot-Simulation ",0
 even
REALLYBOOT:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,REALLYBOOTtext-reset,0
REALLYBOOTtext:
 dc.b "links: startet eventuellen Disk-Boot-VIRUS !!",0
 even

vektor0:
 dc.b 0,1,0,0
 dc.w 15,30
 dc.l 0,vektor0text-reset,0
vektor0text: dc.b "       -Vektor verändert -> VIRUS ? - AMIGA AUS !!",0
 even
VEKTORL:
 dc.b 0,1,0,0
 dc.w 7,4
 dc.l font-reset,VEKTORLtext-reset,0  ; Topaz80 da > 60 Zeichen
VEKTORLtext:
 dc.b " VIRUS-ENTFERN-VERSUCH -> Absturzgefahr -> besser AMIGA AUS !! ",0
 even

gadtext16:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext16text-reset,0
gadtext16text: dc.b "  FileSuche    AN ",0
 even
gadtext15:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext15text-reset,0
gadtext15text: dc.b "  CheckOpen   AUS ",0
 even
gadtext14:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext14text-reset,0
gadtext14text:dc.b "   File - Schutz",0
 even
gadtext13:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext13text-reset,0
gadtext13text:dc.b " Kill System-Virus",0
 even
gadtext12:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext12text-reset,0
gadtext12text:dc.b "in S:VirusName-File",0
 even
gadtext11:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext11text-reset,0
gadtext11text:dc.b "in S:NoWarning-File",0
 even
gadtext8:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext8text-reset,0
gadtext8text: dc.b "Beende VirusControl",0
 even
gadtext7:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext7text-reset,0
gadtext7text: dc.b "r.Checksum ->  Boot",0
 even
gadtext6:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext6text-reset,0
gadtext6text: dc.b "f.Checksum ->NoBoot",0
 even
gadtext5:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext5text-reset,0
gadtext5text: dc.b "NoFastMem-BootBlock",0
 even
gadtext4:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext4text-reset,0
gadtext4text: dc.b "Standard -BootBlock",0
 even
gadtext3:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext3text-reset,0
gadtext3text: dc.b "File   -> BootBlock",0
 even
gadtext2:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext2text-reset,0
gadtext2text: dc.b "Bootblock ->   File",0
 even
gadtext1:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext1text-reset,0
gadtext1text: dc.b "BootBlock -> Schirm",0
 even
gadtext0:
 dc.b 1,0,0,0
 dc.w 7,3
 dc.l font-reset,gadtext0text-reset,0
gadtext0text: dc.b  "  FarbSignal   AN ",0
 even

gad16:            ;   Files durchsuchen
 dc.l 0
 dc.w 430,6*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext16-reset,0,0
 dc.w 16
 dc.l 0
gad15:            ;   Check Open
 dc.l gad16-reset
 dc.w 430,5*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext15-reset,0,0
 dc.w 15
 dc.l 0
gad14:            ; File - Schutz
 dc.l gad15-reset
 dc.w 430,3*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext14-reset,0,0
 dc.w 14
 dc.l 0
gad13:            ; Kill System-Virus
 dc.l gad14-reset
 dc.w 230,6*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext13-reset,0,0
 dc.w 13
 dc.l 0
gad12:           ; in S:VirusName-File
 dc.l gad13-reset
 dc.w 230,3*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext12-reset,0,0
 dc.w 12
 dc.l 0
gad11:           ; in S:NoWarning-File
 dc.l gad12-reset
 dc.w 230,2*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext11-reset,0,0
 dc.w 11
 dc.l 0
gad10:
 dc.l gad11-reset
 dc.w 30,1*18-3,566,53,3,1,1  ; GADGHNONE, damit völlig unauffällig bleibt
 dc.l gadborder1-reset,0,NOBOOT-reset,0,0
 dc.w 10
 dc.l 0
gad8:            ; Beende VirusControl
 dc.l gad10-reset
 dc.w 430,2*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext8-reset,0,0
 dc.w 8
 dc.l 0
gad7:            ; (Virus)DiskBoot  AN
 dc.l gad8-reset
 dc.w 230,5*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext7-reset,0,0
 dc.w 7
 dc.l 0
gad6:            ; (Virus)DiskBoot AUS
 dc.l gad7-reset
 dc.w 230,4*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext6-reset,0,0
 dc.w 6
 dc.l 0
gad5:            ; NoFastMem-BootBlock
 dc.l gad6-reset
 dc.w 30,6*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext5-reset,0,0
 dc.w 5
 dc.l 0
gad4:            ; Standard -BootBlock
 dc.l gad5-reset
 dc.w 30,5*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext4-reset,0,0
 dc.w 4
 dc.l 0
gad3:            ; File   -> BootBlock
 dc.l gad4-reset
 dc.w 30,4*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext3-reset,0,0
 dc.w 3
 dc.l 0
gad2:            ; Bootblock ->   File
 dc.l gad3-reset
 dc.w 30,3*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext2-reset,0,0
 dc.w 2
 dc.l 0
gad1:            ; BootBlock -> Schirm
 dc.l gad2-reset
 dc.w 30,2*18+43,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext1-reset,0,0
 dc.w 1
 dc.l 0
gad0:            ;   FarbSignal
 dc.l gad1-reset
 dc.w 430,4*18+48,166,12,0,1,1
 dc.l gadborder-reset,0,gadtext0-reset,0,0
 dc.w 0
 dc.l 0

gad90:                                     ; je nach Laufwerk entsprechendes
 dc.l gad0-reset                           ; Stringgadget als FirstGadget
 dc.w 37,8*18+38,566,12,0,1,4              ; setzen, als nächstes Gadget ist
 dc.l gadborders-reset,0,0,0,string0-reset ; gad0,gad1,gad2 usw. bereits
 dc.w 9                                    ; gesetzt
 dc.l 0
string0:
 dc.l buff0-reset,undo0-reset
 dc.w 0,buff1-buff0,0,0,0,0,0,0
 dc.l 0,0,0
gad91:
 dc.l gad0-reset
 dc.w 37,8*18+38,566,12,0,1,4
 dc.l gadborders-reset,0,0,0,string1-reset
 dc.w 9
 dc.l 0
string1:
 dc.l buff1-reset,undo1-reset
 dc.w 0,buff1-buff0,0,0,0,0,0,0
 dc.l 0,0,0
gad92:
 dc.l gad0-reset
 dc.w 37,8*18+38,566,12,0,1,4
 dc.l gadborders-reset,0,0,0,string2-reset
 dc.w 9
 dc.l 0
string2:
 dc.l buff2-reset,undo2-reset
 dc.w 0,buff1-buff0,0,0,0,0,0,0
 dc.l 0,0,0
gad93:
 dc.l gad0-reset
 dc.w 37,8*18+38,566,12,0,1,4
 dc.l gadborders-reset,0,0,0,string3-reset
 dc.w 9
 dc.l 0
string3:
 dc.l buff3-reset,undo3-reset
 dc.w 0,buff1-buff0,0,0,0,0,0,0
 dc.l 0,0,0

gadborder:           ; für alle Gadgets, außer Stringgadget und oberes Gadget
 dc.w -1,-1
 dc.b 2,1,0,18
 dc.l pairs-reset,0
gadborders:          ; für das Stringgadget
 dc.w -8,-4          ; GadgetID = 9
 dc.b 2,1,0,18
 dc.l pairss-reset,0
gadborder1:          ; für das große obere Informations-Gadget
 dc.w -1,-1          ; GadgetID = 10
 dc.b 2,1,0,18
 dc.l pairs1-reset,0

pairs:               ; der Schatteneffekt wird durch die Borderlinien erzielt
 dc.w 0,13, 0,0, 167,0, 167,13, 0,13, 1,14, 168,14, 168,0, 169,1,
 dc.w 169,15, 170,15, 170,2, 171,3, 171,15, 2,15, 3,16, 172,16, 172,4
pairss:
 dc.w 0,13, 0,0, 567,0, 567,13, 0,13, 1,14, 568,14, 568,0, 569,1,
 dc.w 569,15, 570,15, 570,2, 571,3, 571,15, 2,15, 3,16, 572,16, 572,4
pairs1:
 dc.w 0,54, 0,0, 567,0, 567,54, 0,54, 1,55, 568,55, 568,0, 569,1,
 dc.w 569,56, 570,56, 570,2, 571,3, 571,56, 2,56, 3,57, 572,57, 572,4

font:
 dc.l topazfont-reset
 dc.w 8
 dc.b 0,1
topazfont: dc.b "topaz.font",0
 even

; 4 Stringgadget-Puffer, da bis zu 4 Laufwerks-Aufrufe gleichzeitig möglich
buff0: dc.b "ram:filename",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; kein even
buff1: dc.b "ram:filename",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; da je
buff2: dc.b "ram:filename",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 32 Bytes
buff3: dc.b "ram:filename",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

window:            ; New-Window-Struktur des Warn-Windows
 dc.w 0,0,640,200
 dc.b 0,1          ; CLOSEWINDOW|GADGETUP
 dc.l $240,$100f,0 ; ACTIVATE|W.DEPTH|W.DRAG|W.CLOSE|W.SIZING|SMART_REFRESH
 dc.l 0,taskname-reset,0,0 ; Windowtitellänge egal
 dc.w 290,68,640,200,1     ; WBENCHSCREEN
 ; WINDOWSIZING -> kann Titel ganz lesen, aber wegen PrintIText einschränken
structtask: dc.l 0,0
            dc.b 1,0
            dc.l taskname-reset
            dc.b 0,0,0,0
            dc.l 0,0,0,0
            dc.w 0,0
            dc.l 0,0,0,0
            dc.l end-reset+9000,end-reset,end-reset+9000
            dc.l 0,0,0,0,0
            dc.w 0,0,0
end:
; +9000 Bytes duch AllocMem belegen.
; end       bis end+1024             Bootblock-Puffer für NoWarning-Funktion
; end+1024  bis end+2*1024+32        Bootblock-Puffer für VirusName-Funktion
; end+2080  bis end+2080+128         4 * 32-Byte-String-Gadget-Undo-Puffer
; end+2208  bis end+2208+40+48+2*34  2*Request-Struktur,2*Port-Struktur
; end+2364  bis end+2364+512         512-Byte-Sektor-Puffer für -t Option
; end+2876  bis end+2876+1024        1024-Byte-Bootblock-Puffer für df0:
; end+3900  bis end+3900+1024        1024-Byte-Bootblock-Puffer für df1:
; end+4924  bis end+4924+1024        1024-Byte-Bootblock-Puffer für df2:
; end+5948  bis end+5948+1024        1024-Byte-Bootblock-Puffer für df3:
; end+6972  bis end+9000             Vektor-Kontroll-Task-Stack
; Autorequester-Aufruf des Vektor-Kontroll-Tasks belegt circa 1.2 KB Stack,
; 9000-6972 = 2028  Stack reicht aus.
Nobuff      = end
Vibuff      = Nobuff+1024
undo0       = Vibuff+1024+32
undo1       = undo0+32
undo2       = undo1+32
undo3       = undo2+32
timereq     = undo3+32         ; IORequest(32)+timeval(8) -> da AllocMem mit
timeport    = timereq+40       ; MsgPort(34)              -> MEMF_CLEAR mit 0
trackreq    = timeport+34      ; IOStdRequest(48)         -> vorbelegt
trackport   = trackreq+48      ; MsgPort(34)
blockbuff   = trackport+34
bootblock0  = blockbuff+512;
bootblock1  = bootblock0+1024
bootblock2  = bootblock1+1024
bootblock3  = bootblock2+1024
