****     Virus Checker           ***
***   Checks for SCA virus, Byte Bandit Virus and Non-Standard Boot Blocks **
***   Based on the idea and code from Steve Tibbett on Fish #136    **
**    Only this is much smaller and done in assembly language     **
**    Please   send me any more viruses so I can update this      **
**    John Veldthuis
**    21 Ngatai Street
**    Manaia, Taranaki
**    New Zealand

**    Placed in the Public domain libraries to help all get rid of Viruses **
**    V1.0  was an arp.library version
**    V1.1  was an port to the normal libraries
**    V1.2  had the ByteBandit virus dectection added into it
**    V1.3  had detection of the 3 Viruses in memory and removal of them


**    Buffer is for block reads
**    Buff   is for window title


   include  "exec/types.i"
   include  "intuition/intuition.i"
   include  "devices/trackdisk.i"
   include  "exec/memory.i"
   include  "libraries/dosextens.i"

   xref     _LVOOpenLibrary
   xref     _LVOCloseLibrary
   xref     _LVOFindTask
   xref     _LVOSetTaskPri
   xref     _LVODoIO
   xref     _LVOOpenDevice
   xref     _LVOCloseDevice
   xref     _LVOEnable
   xref     _LVODisable
   xref     _LVOOpenWindow
   xref     _LVOCloseWindow
   xref     _LVOSetAPen
   xref     _LVOSetBPen
   xref     _LVOSetDrMd
   xref     _LVOSetWindowTitles
   xref     _LVORawDoFmt
   xref     _LVOWaitPort
   xref     _LVOWait
   xref     _LVOGetMsg
   xref     _LVOReplyMsg
   xref     _LVOAutoRequest
   xref     _LVOAllocEntry
   xref     _LVOFreeEntry
   xref     _LVOOpen
   xref     _LVOClose
   xref     _LVOWrite
   xref     _LVODelay
   xref     _LVOAllocSignal
   xref     _LVOFreeSignal
   xref     _LVORequest
   xref     _LVOEndRequest
   xref     _LVOSumKickData
   xref     _LVOFindName

Offsets     macro
\1          equ   soffset
soffset     set   soffset+\2
            endm
soffset     set   0

            Offsets  message,4
            Offsets  intuibase,4
            Offsets  gfxbase,4
            Offsets  dosbase,4
            Offsets  execbase,4
            Offsets  file,4
            Offsets  buff,4
            Offsets  port,4
            Offsets  signal,4
            Offsets  signal1,4
            Offsets  userport,4
            Offsets  userport1,4
            Offsets  rport,4
            Offsets  rport1,4
            Offsets  buffer,4
            Offsets  mywindow,4
            Offsets  mywindow1,4
            Offsets  diskreq,4
            Offsets  task,4
            Offsets  oldpri,4
            Offsets  mementry,4
            Offsets  text,4
            Offsets  unit,2

Start:
      lea      BASE(pc),a5
      move.l   4,a6
      move.l   a6,execbase(a5)
      moveq.l  #0,d7          ;zero flag for checkdisks
      moveq.l  #0,d6          ;zero no. viruses found
      moveq.l  #0,d5          ;zero no. disks installed
      moveq.l  #0,d4          ;zero no. disks checked
      sub.l    a1,a1
      jsr      _LVOFindTask(a6)
      move.l   d0,task(a5)
      move.l   d0,a4
      tst.l    pr_CLI(a4)     ;see if we  are CLI or Workbench
      bne.s    CLI
      lea      pr_MsgPort(a4),a0
      jsr      _LVOWaitPort(a6)
      lea      pr_MsgPort(a4),a0
      jsr      _LVOGetMsg(a6)
      move.l   d0,message(a5)
CLI   moveq.l  #33,d0         ;version 33 or greater
      lea      Dos(pc),a1
      jsr      _LVOOpenLibrary(a6) ;open dos.library
      tst.l    d0
      bne.s    Lib1
NoLib add.w    #8,sp
      move.l   #20,d0         ;no library, indicate error and stop
      rts
Lib1  move.l   d0,dosbase(a5)
      moveq.l  #33,d0         ;version 33 or greater
      lea      IntuiLib(pc),a1
      jsr      _LVOOpenLibrary(a6) ;open dos.library
      tst.l    d0
      bne.s    1$
      move.l   dosbase(a5),a1
      jsr      _LVOCloseLibrary(a6)
      bra.s    NoLib
1$    move.l   d0,intuibase(a5)
      moveq.l  #33,d0         ;version 33 or greater
      lea      Graphics(pc),a1
      jsr      _LVOOpenLibrary(a6) ;open dos.library
      tst.l    d0
      bne.s    13$
      move.l   dosbase(a5),a1
      jsr      _LVOCloseLibrary(a6)
      move.l   intuibase(a5),a1
      jsr      _LVOCloseLibrary(a6)
      bra.s    NoLib
13$   move.l   d0,gfxbase(a5)
      lea      MemDisc(pc),a0
      jsr      _LVOAllocEntry(a6)   ;allocate all memory in one go
      btst     #31,d0
      bne      MemErr
      move.l   d0,mementry(a5)
      move.l   d0,a0
      move.l   a0,a1
      add.w    #LN_SIZE+2,a1
      move.l   (a1),buffer(a5)
      move.l   a0,a1
      add.w    #LN_SIZE+10,a1
      move.l   (a1),buff(a5)
      move.l   task(a5),a1
      move.l   #19,d0
      jsr      _LVOSetTaskPri(a6)   ;set our task to priorty 19
      move.l   d0,oldpri(a5)         ;save old priority
      bsr      CreatePort        ;create a reply port
      tst.l    d0
      beq      Error
      move.l   d0,d3
      move.l   d0,port(a5)           ;save for closing later
      move.l   mementry(a5),a0
      add.w    #$20,a0
      move.l   (a0),a0
      move.b   #NT_MESSAGE,LN_TYPE(a0)
      move.w   #IOSTD_SIZE,MN_LENGTH(a0)
      move.l   d3,MN_REPLYPORT(a0)
      move.l   a0,diskreq(a5)        ;save IO block address
      bsr      CheckMemory           ;check for viruses in memory first
      moveq.l  #3,d3
Loop  lea      TrackName(pc),a0
      move.l   d3,d0
      move.l   diskreq(a5),a1
      moveq.l  #0,d1
      jsr      _LVOOpenDevice(a6);open up trackdisk.device
      tst.l    d0
      bgt.s    Cont
      move.w   #TD_CHANGENUM,IO_COMMAND(a1)
      jsr      _LVODoIO(a6)      ;find out change count for all drives
      move.l   IO_ACTUAL(a1),d0
      lea     ChangeCount(pc),a0
      move.l   d3,d1
      lsl.l    #2,d1
      add.l    d1,a0
      move.l   d0,(a0)           ;set current change count
      jsr      _LVOCloseDevice(a6)
Cont  dbra     d3,Loop           ;do 4 drives
      lea      MyNewWindow(pc),a0
      move.l   intuibase(a5),a6
      jsr      _LVOOpenWindow(a6);open up our window
      move.l   execbase(a5),a6              ;restore ExecBase
      tst.l    d0
      beq      Error
      move.l   d0,mywindow(a5)       ;save for later
      move.l   d0,a0
      move.l   wd_RPort(a0),rport(a5);get window rastport, saves time later
      move.l   wd_UserPort(a0),a0
      move.l   a0,userport(a5)       ;also get userport
      moveq.l  #0,d0
      move.b   MP_SIGBIT(a0),d0 ;get this ports signal number
      moveq.l  #1,d1
      lsl.l    d0,d1            ;convert into a mask
      move.l   d1,signal(a5)        ;and save
      moveq.l  #3,d3
      lea      ChangeCount(pc),a0
4$    move.l   (a0),d0
      cmp.l    #-1,d0             ;is current count -1
      bne.s    11$
      addq.w   #4,a0              ;yes, then no drive here
      bra.s    12$
11$   move.l   #1000,(a0)+        ;otherwise set count to 1000
12$   dbra     d3,4$              ;do all drives attached
      bsr      CheckBlock         ;and check disks
      move.l   rport(a5),a1           ;get our rast port
      moveq.l  #1,d0
      move.l   gfxbase(a5),a6
      jsr      _LVOSetAPen(a6)
      moveq.l  #0,d0
      jsr      _LVOSetBPen(a6)
      moveq.l  #RP_JAM2,d0
      jsr      _LVOSetDrMd(a6)
MainLoop:                         ;where the work is done
      move.l   execbase(a5),a6
      lea      FmtString(pc),a0
      move.l   d6,-(sp)
      move.l   d5,-(sp)
      move.l   d4,-(sp)
      move.l   sp,a1
      lea      Format1(pc),a2
      move.l   buff(a5),a3
      jsr      _LVORawDoFmt(a6)   ;format screen title string
      add.w    #12,sp
      move.l   intuibase(a5),a6
      move.l   mywindow(a5),a0           ;pointer to window
      moveq.l  #-1,d0
      move.l   d0,a1             ;don't change window title
      move.l   buff(a5),a2
      jsr      _LVOSetWindowTitles(a6)
      move.l   execbase(a5),a6
Lp    move.l   userport(a5),a0
      jsr      _LVOGetMsg(a6)    ;see if any messages at our port
      tst.l    d0
      bne.s    Act
      move.l   signal(a5),d0         ;no then we will wait for one
      jsr      _LVOWait(a6)
      bra.s    Lp
Act   move.l   d0,a1             ;yes, lets see what it is
      move.l   im_Class(a1),d3   ;copy class
      jsr      _LVOReplyMsg(a6)  ;reply to these fast
      cmp.l    #CLOSEWINDOW,d3   ;shall we close down
      beq.s    EndofLoop
      cmp.l    #DISKINSERTED,d3  ;or has someone put a disk in
      bne.s    MainLoop          ;no, well thats all we want
      bsr.s    CheckBlock        ;yes lets check it out
      bra      MainLoop
EndofLoop:
      move.l   task(a5),a0
      move.l   oldpri(a5),d0
      jsr      _LVOSetTaskPri(a6) ;restore old priority
      move.l   intuibase(a5),a6
      move.l   mywindow(a5),a0
      jsr      _LVOCloseWindow(a6) ;close our window
      move.l   execbase(a5),a6
      move.l   port(a5),a1
      bsr      DeletePort         ;delete our port
      move.l   mementry(a5),a0
      jsr      _LVOFreeEntry(a6)
      bsr      CloseLibrary
      moveq.l  #0,d0
      rts                          ;indicate a clean return

CheckBlock:
      bsr      WhoChanged          ;find out which drive is involved
      cmp.l    #-1,d0              ;no more drives to check
      beq      Return
      move.b   d0,unit(a5)             ;save drive number
      addq.l   #1,d4                ;add one to number checked
      lea      TrackName(pc),a0
      move.l   diskreq(a5),a1
      moveq.l  #0,d1
      jsr      _LVOOpenDevice(a6)  ;open trackdisk on unit
      tst.l    d0
      bgt.s    CheckBlock          ;won't open, try next drive
      move.l   diskreq(a5),a1
      move.w   #CMD_READ,IO_COMMAND(a1)
      move.l   buffer(a5),IO_DATA(a1)
      move.l   #1536,IO_LENGTH(a1)
      move.l   #0,IO_OFFSET(a1)
      jsr      _LVODoIO(a6)        ;read boot block into buffer
      move.l   diskreq(a5),a1
      move.w   #TD_MOTOR,IO_COMMAND(a1)
      move.l   #0,IO_LENGTH(a1)
      jsr      _LVODoIO(a6)        ;turn motor off
      move.l   diskreq(a5),a1
      move.b   IO_ERROR(a1),d3     ;see what error there was
      jsr      _LVOCloseDevice(a6)
      cmp.b    #19,d3
      bgt.s    CheckBlock           ;if an error try next drive
      move.w   #$FF,d1
      moveq.l  #0,d2
      move.l   buffer(a5),a0
1$    add.l    (a0)+,d2
      bcc.s    2$
      addq.l   #1,d2
2$    dbra     d1,1$             ; compute checksum on block
      not.l    d2                ;if not zero then this will not boot
      bne      CheckBlock        ;not a booting disk, then check next one
      move.l   buffer(a5),a1
      move.l   12(a1),d0
      cmp.l    #$41FAFFF2,d0     ;check for SCA virus
      bne.s    NextCheck
      addq.l   #1,d6             ;another SCA virus found
      bra.s    DisplaySCA        ;display message
NextCheck:
      move.l   32(a1),d0
      cmp.l    #'Band',d0        ;check for Byte Bandit virus
      bne.s    NextCheck2
      addq.l   #1,d6             ;found one
      bra      DisplayBYT        ;display message
NextCheck2:
      move.w   14(a1),d0
      cmp.w    'ID',d0           ;check for revenge virus
      bne.s    NextCheck3
      move.b   16(a1),d0
      cmp.b    #'9',d0
      bne.s    NextCheck3
      addq     #1,d6
      bra      DisplayREV
NextCheck3:
      move.l   $C0(a1),d0
      cmp.l    #'DASA',d0
      bne.s    CheckBoot
      addq     #1,d6
      bra      DisplayWAR
CheckBoot:
      addq.w   #8,a1
      lea      BootBlock+8(pc),a2
      moveq.l  #10,d3
1$    move.l   (a1)+,d0          ;otherwise see if the block is a 
      move.l   (a2)+,d1          ;standard booting disk
      cmp.l    d0,d1
      bne      DisplayNstd       ;it isn't, then display message
      dbra     d3,1$             ;okay it is, next disk
      bra      CheckBlock        ;see it any more disks changed
DisplaySCA:
      lea      SCABody(pc),a1
Disp2 move.b   unit(a5),d0
      add.b    #'0',d0           ;set unit number on message
      lea      TEXTPTR+23(pc),a0
      move.b   d0,(a0)
Disp3 bsr      GetInput           ;see what user wants to do with it
      bra      CheckBlock
DisplayBYT:
      lea      BYTBody(pc),a1
      bra.s    Disp2         ;same here but why use the same code twice
DisplayREV:
      lea      REVBody(pc),a1
      bra.s    Disp2
DisplayWAR:
      lea      WARBody(pc),a1
      bra.s    Disp2
DisplayNstd:
      lea      NBCTEXT(pc),a0
      add.w    #23,a0
      move.b   unit(a5),d0
      add.b    #'0',d0
      move.b   d0,(a0)
      lea      Body1(pc),a1
      bra.s    Disp3


DisplayIt
      move.l   dosbase(a5),a6
      lea      FileName(pc),a0
      move.l   a0,d1
      move.l   #MODE_NEWFILE,d2
      jsr      _LVOOpen(a6)         ;open up a console window
      move.l   execbase(a5),a6
      tst.l    d0
      beq      Cont3           ;error open window goto next requester
      move.l   d0,file(a5)         ;save for later
      move.l   #1023,d2        ;1024 chars
      move.l   buffer(a5),a2
4$    moveq.l  #0,d0
      move.b   (a2),d0
      cmp.b    #' ',d0         ;if < space print a '.'
      blt.s    1$
      cmp.b    #'~',d0         'if > '~'  print a '.'
      ble.s    2$
1$    move.b   #'.',(a2)+
      bra.s    3$
2$    move.b   d0,(a2)+
3$    dbra     d2,4$
      move.l   dosbase(a5),a6
      move.l   #1024,d3
      move.l   file(a5),d1
      move.l   buffer(a5),d2
      jsr      _LVOWrite(a6)
      move.l   execbase(a5),a6
Cont3 lea      NBCTEXT(pc),a0
      add.w    #23,a0
      move.b   unit(a5),d0
      add.b    #'0',d0
      move.b   d0,(a0)
      move.l   mywindow(a5),a0
      move.l   text(a5),a1
      lea      Pos(pc),a2
      lea      Neg1(pc),a3
      moveq.l  #0,d0
      moveq.l  #0,d1
      move.l   #340,d2
      move.l   #75,d3
      move.l   intuibase(a5),a6
      jsr      _LVOAutoRequest(a6) ;get more input from user
      move.l   execbase(a5),a6
      move.l   d0,-(sp)
      move.l   dosbase(a5),a6
      move.l   file(a5),d1
      jsr      _LVOClose(a6)       ;close console device
      move.l   execbase(a5),a6
      move.l   (sp)+,d0
      tst.l    d0
      beq.s    1$
      bsr.s    DoInstall          ;clear block if user wants to
1$    rts

DoInstall:
      move.l   intuibase(a5),a6
      move.l   mywindow(a5),a0
      lea      REWBody(pc),a1
      lea      REWPos(pc),a2
      lea      REWNeg(pc),a3
      moveq.l  #0,d0
      moveq.l  #0,d1
      move.l   #320,d2
      move.l   #75,d3
      jsr      _LVOAutoRequest(a6) ;last warning
      move.l   execbase(a5),a6
      tst.l    d0
      beq      Return              ;no, make up your mind
      move.l   buffer(a5),a0
      move.l   #256,d3
      moveq.l  #0,d0
1$    move.l   d0,(a0)+          ;zero buffer
      dbra     d3,1$
      move.l   buffer(a5),a0
      lea      BootBlock(pc),a1
      moveq.l  #12,d3
2$    move.l   (a1)+,(a0)+         ;copy standard boot block to buffer
      dbra     d3,2$
      lea      TrackName(pc),a0
      move.l   diskreq(a5),a1
      move.b   unit(a5),d0
      ext.w    d0
      ext.l    d0
      moveq.l  #0,d1
      jsr      _LVOOpenDevice(a6) ;open correct drive
      tst.l    d0
      bgt      Return
4$    move.l   diskreq(a5),a1
      move.w   #TD_PROTSTATUS,IO_COMMAND(a1)
      jsr      _LVODoIO(a6)       ;check write protect tab
      move.l   diskreq(a5),a1
      move.l   IO_ACTUAL(a1),d0
      tst.l    d0
      beq.s    3$
      move.l   intuibase(a5),a6
      move.l   mywindow(a5),a0
      lea      ERRBody(pc),a1
      lea      ERRPos(pc),a2
      lea      ERRNeg(pc),a3
      moveq.l  #0,d0
      moveq.l  #0,d1
      move.l   #320,d2
      move.l   #75,d3
      jsr      _LVOAutoRequest(a6) ;ask user to take protect off
      move.l   execbase(a5),a6
      tst.l    d0
      bne.s    4$
      move.l   diskreq(a5),a1
      jsr      _LVOCloseDevice(a6) ;or ignore the block again
      bra      Return
3$    move.l   diskreq(a5),a1
      move.l   #1024,IO_LENGTH(a1)
      move.l   buffer(a5),IO_DATA(a1)
      move.w   #CMD_WRITE,IO_COMMAND(A1)
      move.l   #0,IO_OFFSET(A1)
      jsr      _LVODoIO(a6)        ;write block out to disk
      move.l   diskreq(a5),a1
      move.w   #CMD_UPDATE,IO_COMMAND(A1)
      jsr      _LVODoIO(a6)        ;flush data to disk
      move.l   diskreq(a5),a1
      move.b   IO_ERROR(a1),d3     ;get error condition
      move.w   #TD_MOTOR,IO_COMMAND(A1)
      move.l   #0,IO_LENGTH(a1)
      jsr      _LVODoIO(a6)        ;turn off drive
      move.l   diskreq(a5),a1
      jsr      _LVOCloseDevice(a6) ;shut down device
      cmp.b    #19,d3
      ble.s    5$
      lea      ErrorND(pc),a1      ;if error > 19 then nothing done
      bra.s    6$
5$    lea      Healed(pc),a1       ;otherwise it was healed
6$    move.l   mywindow(a5),a0
      moveq.l  #-1,d0
      move.l   d0,a3
      move.l   intuibase(a5),a6
      jsr      _LVOSetWindowTitles(a6);set window title
      move.l   dosbase(a5),a6
      moveq.l  #100,d1
      jsr      _LVODelay(a6)       ;delay for 2 seconds
      move.l   intuibase(a5),a6
      move.l   mywindow(a5),a0
      lea      TITLETEXT(pc),a1
      moveq.l  #-1,d0
      move.l   d0,a3
      jsr      _LVOSetWindowTitles(a6) ;restore window title
      move.l   execbase(a5),a6
      addq.l   #1,d5                   ;add 1 to disks installed
Return:
      rts




WhoChanged:
      moveq.l  #3,d3
Loop1 move.l   d3,d0
      lsl.l    #2,d0
      lea      ChangeCount(pc),a0
      add.l    d0,a0
      move.l   (a0),d0
      cmp.l    #-1,d0
      beq      Cont2
      lea      TrackName(pc),a0
      move.l   d3,d0
      move.l   diskreq(a5),a1
      moveq.l  #0,d1
      jsr      _LVOOpenDevice(a6)
      tst.l    d0
      bgt.s    Cont2
      move.l   diskreq(a5),a1
      move.w   #TD_CHANGESTATE,IO_COMMAND(a1)
      jsr      _LVODoIO(a6)
      move.l   diskreq(a5),a1
      tst.l    IO_ACTUAL(a1)
      bne.s    Cont1
      move.w   #TD_CHANGENUM,IO_COMMAND(a1)
      jsr      _LVODoIO(a6)
      move.l   diskreq(a5),a1
      lea      ChangeCount(pc),a2
      move.l   d3,d0
      lsl.l    #2,d0
      add.l    d0,a2
      move.l   IO_ACTUAL(a1),d0
      move.l   (a2),d1
      cmp.l    d0,d1
      beq.s    Cont1
      move.l   d0,(a2)
      jsr      _LVOCloseDevice(a6)
      move.l   d3,d0
      rts
Cont1 jsr      _LVOCloseDevice(a6)
Cont2 dbra     d3,Loop1
      move.l   #-1,d0         ;return noone changed
      rts

CloseLibrary:
      tst.l    message(a5)
      beq.s    4$
      move.l   message(a5),a1
      jsr      _LVOReplyMsg(a6)  ;reply to workbench message
4$    tst.l    dosbase(a5)
      beq.s    1$
      move.l   dosbase(a5),a1
      jsr      _LVOCloseLibrary(a6)
1$    tst.l    intuibase(a5)
      beq.s    2$
      move.l   intuibase(a5),a1
      jsr      _LVOCloseLibrary(a6)
2$    tst.l    gfxbase(a5)
      beq.s    3$
      move.l   Intuibase,a1
      jsr      _LVOCloseLibrary(a6)
3$    rts

MemErr:
Error:
         move.l   execbase(a5),a6
         bsr      CloseLibrary
         move.l   task(a5),a0
         move.l   pr_CLI(a0),d0
         lsl.l    #2,d0
         move.l   d0,a0
         move.l   #103,(a0)   ;put out of memory into CLI result
         moveq.l  #20,d0      ;indicate error
         rts

Format1  move.b   d0,(a3)+    ;this is used by _LVORawDoFmt
         rts

GetInput:                              ;a1 holds text to print in requester
      move.l   a1,text(a5)
      lea      MNewWindow(pc),a0
      move.l   intuibase(a5),a6
      jsr      _LVOOpenWindow(a6);open up our window
      move.l   execbase(a5),a6              ;restore ExecBase
      move.l   text(a5),a1
      tst.l    d0
      beq      5$                ;if window wont open display block
      move.l   d0,mywindow1(a5)      ;save for later
      move.l   d0,a0
      move.l   wd_RPort(a0),d0   ;get window rastport, saves time later
      move.l   d0,rport1(a5)
      move.l   wd_UserPort(a0),d0
      move.l   d0,userport1(a5)       ;also get userport
      move.l   d0,a0
      moveq.l  #0,d0
      move.b   MP_SIGBIT(a0),d0 ;get this ports signal number
      moveq.l  #1,d1
      lsl.l    d0,d1            ;convert into a mask
      move.l   d1,signal1(a5)        ;and save
      lea      MyRequester(pc),a0
      move.l   a1,rq_ReqText(a0)       ;put in text
      move.l   #0,(a0)              ;zero out link
6$    move.l   intuibase(a5),a6
      move.l   mywindow1(a5),a1
      jsr      _LVORequest(a6)      ;put requester up
      move.l   execbase(a5),a6
1$    move.l   userport1(a5),a0
      jsr      _LVOGetMsg(a6)
      tst.l    d0
      bne.s    2$
      move.l   signal1(a5),d0
      jsr      _LVOWait(a6)
      bra.s    1$
2$    move.l   d0,a1
      move.l   im_Class(a1),d3
      cmp.l    #GADGETUP,d3
      beq.s    7$
      jsr      _LVOReplyMsg(a6)
      bra.s    6$                   ;do the requester again
7$    move.l   im_IAddress(a1),a0
      move.w   gg_GadgetID(a0),d3   ;get gadget number
      jsr      _LVOReplyMsg(a6)
      move.l   intuibase(a5),a6
      move.l   mywindow1(a5),a0
      jsr      _LVOCloseWindow(a6)
      move.l   execbase(a5),a6
      cmp.w    #0,d3
      bne.s    3$
      bsr      DoInstall
      rts
3$    cmp.w    #1,d3
      bne.s    4$                    ;ignore it
5$    bsr      DisplayIt
4$    rts


CreatePort:
      move.l   a2,-(a7)
      move.l   mementry(a5),a2
      add.w    #LN_SIZE+26,a2
      move.l   (a2),a2
      moveq   #-1,d0
      jsr     _LVOAllocSignal(a6)
      moveq   #-1,d1
      cmp.l   d0,d1   ;-1 indicates bad signal
      bne.s   cp_sigok
      move.l   (a7)+,a2
      moveq   #0,d0        ;otherwise indicate no port
      rts
cp_sigok   move.b   d0,MP_SIGBIT(a2)
      move.b   #PA_SIGNAL,MP_FLAGS(a2)
      move.b   #NT_MSGPORT,LN_TYPE(a2)
      clr.b   LN_PRI(a2)
      suba.l   a1,a1         ;a1=0/Find this task
      move.l   task(a5),d0
      move.l   d0,MP_SIGTASK(a2)
      lea.l   MP_MSGLIST(a2),a0  ;Point to list header
      NEWLIST a0      ;Init new list macro
      move.l   a2,d0
      move.l   (a7)+,a2   ;cc's NOT affected
      rts

DeletePort:
      moveq    #-1,d0
      move.b   d0,LN_TYPE(a1)
      move.l   d0,MP_MSGLIST+LH_HEAD(a1)
      moveq    #0,d0
      move.b   MP_SIGBIT(a1),d0
      jsr      _LVOFreeSignal(a6)
      rts

CheckMemory:
         lea      $142(a6),a0    ;get pointer to MemList Struct
         move.l   (a0),a0        ;get first available memory
         move.l   $18(a0),a1     ;get upper part of memory
                                 ;not used by system????
         move.l   (a1),d0        ;get copy of mem contents
         cmp.l    #$444F5300,d0  ;DOS,0
         bne.s    NextMemCheck
         move.l   $10(a1),d0
         cmp.l    #'Viru',d0     ;make sure it is a byte bandit virus
         bne.s    NextMemCheck
         lea      $3DA(a1),a4    ;A4 now points to VertBlank vector save
         jsr      _LVODisable(a6);disable interupts
         move.l   (a4),$94(a6)  ;restore vertical blank routine
         move.l   #$6000010A,$1B8(a1)  ;change trackdisk routine to
                                       ;bra.l   *+$10C
                                       ;this skips virus code
         lea      $3E2(a1),a0          ;find start of RomTag structure
         moveq    #12,d1               ;12 long words to clear
         moveq    #0,d0
1$       move.l   d0,(a0)+             ;remove RomTag structure
         dbra     d1,1$
         moveq    #18,d1
2$       move.l   d0,(a1)+             ;wipe out start of virus so we
         dbra     d1,2$                ;dont find it again
         bsr      FixRomTag
         jsr      _LVOEnable(a6)
         lea      Text1(pc),a1
         bsr      DisplayReq
NextMemCheck:
         lea      $7EC00,a0         ;SCA virus hiding place
         move.l   $3E4(a0),d0       ;part of the message
         cmp.l    #'SCA!',d0
         bne.s    NextMemCheck2
         move.l   $2E(a6),d0        ;cool capture vector
         cmp.l    #$7EC3E,d0        ;is SCA virus in coolcapture vector
         bne.s    NextMemCheck2
         move.l   #0,$3E4(a0)       ;clear out SCA! so we dont find it again
         move.l   $3DE(a0),-$1C6(a6);restore DoIO vector
         bsr      FixCoolCapture
         lea      SCAGone(pc),a1
         bsr      DisplayReq
NextMemCheck2:
         move.l   $2e(a6),d0
         cmp.l    #$7E060,d0
         bne.s    NextMemCheck3
         bsr.s    FixCoolCapture
         jsr      _LVODisable(a6)
         lea      $7E000,a0         ;revenge virus lives here
         clr.l    (a0)              ;get rid of DOS\0
         lea      $7E1E0,a0         ;patch DoIO routine to skip virus
         move.l   #$4EF90007,(a0)+
         move.w   #$E066,(a0)
         lea      $7E2DA,a0         ;patch vertical interupt wedge
         move.l   #$4EF90007,(a0)+
         move.w   #$E06C,(a0)
         jsr      _LVOEnable(a6)
         lea      RevGone(pc),a1
         bsr.s    DisplayReq
NextMemCheck3:
         lea      $7F800,a0         ;address where the Warrior hangs out
         move.l   $14C(a0),d0       ;pointer to RomTAG
         cmp.l    #$0007F954,d0     ;is the romtag here
         bne.s    NextMemCheck4
         move.l   #$FC06DC,-$1C6(a6);restore DoIO vector to V1.2 DoIO
                                    ;wont work under V1.3 but then
                                    ;neither will the virus
         move.w   #$FF,d1            ;256 longs to clear
         moveq    #0,d0
1$       move.l   d0,(a0)+          ;zero out this rodent
         dbra     d1,1$
         bsr.s    FixRomTag
         lea      WarGone(pc),a1
         bsr.s    DisplayReq
NextMemCheck4:
         rts


FixRomTag:
         move.l   d0,$222(a6)    ;clear out KickMemPtr
         move.l   d0,$226(a6)    ;clear out KickTagPtr
                                 ;virus uses this to reinstall itself at
                                 ;boot time
         move.l   d0,$22A(a6)    ;reset checksum to zero
         rts

FixCoolCapture:
            clr.l    $2e(a6)
            lea      $22(a6),a0
            moveq    #0,d0
            moveq    #$17,d1
1$          add.w    (a0)+,d0
            dbf      d1,1$
            not.w    d0
            move.w   d0,(a0)
            rts

DisplayReq:
         move.l   mywindow(a5),a0
         lea      Okay(pc),a2
         lea      Okay(pc),a3
         moveq.l  #0,d0
         moveq.l  #0,d1
         move.l   #340,d2
         move.l   #75,d3
         move.l   intuibase(a5),a6
         jsr      _LVOAutoRequest(a6) ;get more input from user
         move.l   execbase(a5),a6
         rts

ChangeCount dc.l  $ffffffff
            dc.l  $ffffffff
            dc.l  $ffffffff
            dc.l  $ffffffff
BASE:
Message     dc.l  0
Intuibase   dc.l  0
Gfxbase     dc.l  0
Dosbase     dc.l  0
Execbase    dc.l  0
File        dc.l  0
Buff        dc.l  0
Port        dc.l  0
Signal      dc.l  0
Signal1     dc.l  0
UserPort    dc.l  0
UserPort1   dc.l  0
RPort       dc.l  0
RPort1      dc.l  0
Buffer      dc.l  0
MyWindow    dc.l  0
MyWindow1   dc.l  0
DiskReq     dc.l  0
Task        dc.l  0
OldPri      dc.l  0
MemEntry    dc.l  0
Text        dc.l  0
Unit        dc.w  0
MemDisc     ds.b  LN_SIZE
            dc.w  4
            dc.l  MEMF_CHIP!MEMF_CLEAR
            dc.l  1536
            dc.l  MEMF_PUBLIC!MEMF_CLEAR
            dc.l  100
            dc.l  MEMF_PUBLIC!MEMF_CLEAR
            dc.l  IOSTD_SIZE
            dc.l  MEMF_PUBLIC!MEMF_CLEAR
            dc.l  MP_SIZE

MyNewWindow dc.w  128,0,300,10
            dc.b  0,1
            dc.l  DISKINSERTED!CLOSEWINDOW!VANILLAKEY!MOUSEBUTTONS
            dc.l  WINDOWDRAG!WINDOWDEPTH!RMBTRAP!WINDOWCLOSE!NOCAREREFRESH
            dc.l  0,0,TITLETEXT,0,0
            dc.w  0,0,0,0,WBENCHSCREEN
BootBlock   dc.b  'DOS',0,$c0,$20,$0f,$19,0,0,3,$70,$43,$fa,0,$18
            dc.b  $4e,$ae,$ff,$a0,$4a,$80,$67,$0a,$20,$40,$20,$68
            dc.b  0,$16,$70,0,$4e,$75,$70,$ff,$60,$fa,$64
            dc.b  $6f,$73,$2e,$6c,$69,$62,$72,$61,$72,$79,0,0,0,0,0
TITLETEXT   dc.b  'Virus Checker (V1.4)',0
TITLETEXT1  dc.b  'Virus Checker Requester',0
FmtString   dc.b  'Virus Checker: Disks Checked: %ld Disks Installed: %ld Viruses Found: %ld',0
FileName    dc.b  'CON:0/70/640/130/Ascii Dump of Boot Block',0
NAME        dc.b  'Virus Checker:',10,'By John Veldthuis',10
            dc.b  '21 Ngatai Street',10
            dc.b  'Manaia, Taranaki',10
            dc.b  'New Zealand',10,0
Dos         dc.b  'dos.library',0
IntuiLib    dc.b  'intuition.library',0
Graphics    dc.b  'graphics.library',0
TrackName   dc.b  'trackdisk.device',0
NonStd      dc.b  'Nonstandard Boot Code!',0
OKAY1       dc.b  'Okay',0
Display     dc.b  'Display It',0
Ignore      dc.b  'Ignore  It',0
Remove      dc.b  'Remove  It',0
Retry       dc.b  'Retry',0
Yes         dc.b  'Yes',0
No          dc.b  'No',0
Cancel      dc.b  'Cancel',0
Bytmess     dc.b  'Your Memory was',0
Bytmess2    dc.b  'But it has been disabled',0
SCAV        dc.b  'infected with an SCA Virus!!',0
BYTV        dc.b  'infected with the Byte Bandit Virus!',0
REVV        dc.b  'infected with the Revenge Virus!',0
WARV        dc.b  'infected with the Byte Warrior Virus',0
WrtPro      dc.b  'Write Protected.',0
DiskERR     dc.b  'DISK ERROR: Disk is',0
Bootsec     dc.b  'Rewrite the boot sectors?',0
Rewrite     dc.b  'Are you sure you want to',0
NBCTEXT     dc.b  'Danger:  The disk in DF9: has',0
TEXTPTR     dc.b  'Danger:  The disk in DF9: is',0
ErrorND     dc.b  'Error,  Nothing Done.',0
Healed      dc.b  'Disk Healed.',0

def_font    dc.b  'topaz.font',0


            cnop  0,2

TxtAt_Plain dc.l  def_font
            dc.w  8
            dc.b  FS_NORMAL,FPF_ROMFONT
Body2       dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  NonStd
            dc.l  0
Body1       dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  NBCTEXT
            dc.l  Body2
PosD        dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Display
            dc.l  0
Neg1        dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Ignore
            dc.l  0
Pos         dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Remove
            dc.l  0
SCABody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  SCAV
            dc.l  0
SCABody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  TEXTPTR
            dc.l  SCABody2
BYTBody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  BYTV
            dc.l  0
BYTBody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  TEXTPTR
            dc.l  BYTBody2
REVBody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  TEXTPTR
            dc.l  REVBody2
REVBody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  REVV
            dc.l  0
WARBody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  TEXTPTR
            dc.l  WARBody2
WARBody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  WARV
            dc.l  0
ERRBody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  WrtPro
            dc.l  0
ERRBody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  DiskERR
            dc.l  ERRBody2
ERRPos      dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Retry
            dc.l  0
ERRNeg      dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Cancel
            dc.l  0
REWBody2    dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  Bootsec
            dc.l  0
REWBody     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  Rewrite
            dc.l  REWBody2
REWPos      dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  Yes
            dc.l  0
REWNeg      dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  No
            dc.l  0
Okay        dc.b  0,1,RP_JAM2,0
            dc.w  7,3
            dc.l  TxtAt_Plain
            dc.l  OKAY1
            dc.l  0
Text3       dc.b  0,1,RP_JAM2,0
            dc.w  20,28
            dc.l  TxtAt_Plain
            dc.l  Bytmess2
            dc.l  0
Text2       dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  BYTV
            dc.l  Text3
Text1       dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  Bytmess
            dc.l  Text2
SCAGone     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  Bytmess
            dc.l  SCA2
SCA2        dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  SCAV
            dc.l  Text3
RevGone     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  Bytmess
            dc.l  REV
REV         dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  REVV
            dc.l  Text3
WarGone     dc.b  0,1,RP_JAM2,0
            dc.w  20,8
            dc.l  TxtAt_Plain
            dc.l  Bytmess
            dc.l  WAR
WAR         dc.b  0,1,RP_JAM2,0
            dc.w  20,18
            dc.l  TxtAt_Plain
            dc.l  WARV
            dc.l  Text3






MyRequester:
         dc.l  0
         dc.w  4,12
         dc.w  320,120
         dc.w  0,0
         dc.l  Gad1
         dc.l  0
         dc.l  0                 ;filled in later
         dc.w  0
         dc.b  1
         dc.b  0
         dc.l  0
         ds.b  32
         dc.l  0
         dc.l  0
         ds.b  36

Gad1     dc.l  Gad2
         dc.w  40,45,95,12
         dc.w  GADGHCOMP,RELVERIFY!ENDGADGET,BOOLGADGET!REQGADGET
         dc.l  MyBorder
         dc.l  0,Pos
         dc.l  0,0
         dc.w  0
         dc.l  0
Gad2     dc.l  Gad3
         dc.w  92,70,95,12
         dc.w  GADGHCOMP,RELVERIFY!ENDGADGET,BOOLGADGET!REQGADGET
         dc.l  MyBorder
         dc.l  0,PosD
         dc.l  0,0
         dc.w  1
         dc.l  0
Gad3     dc.l  0
         dc.w  145,45,95,12
         dc.w  GADGHCOMP,RELVERIFY!ENDGADGET,BOOLGADGET!REQGADGET
         dc.l  MyBorder
         dc.l  0,Neg1
         dc.l  0,0
         dc.w  2
         dc.l  0
MyBorder dc.w  -1,-1
         dc.b  2,0,RP_JAM1,5
         dc.l  Pairs
         dc.l  0

Pairs    dc.w  0,0,95,0,95,12,0,12,0,0
MNewWindow  dc.w  0,0,324,133
            dc.b  0,1
            dc.l  VANILLAKEY!MOUSEBUTTONS!GADGETUP
            dc.l  WINDOWDRAG!WINDOWDEPTH!RMBTRAP!NOCAREREFRESH
            dc.l  0,0,TITLETEXT1,0,0
            dc.w  0,0,0,0,WBENCHSCREEN

      end
