 ;AskFirst.By Kamran Karimi.It is a software disk protection mechanism
 ;and when asked by the user prevents writes on a write-enabled disk
 ;assembled with Cape Assembler



ExecBase equ 4
FindTask equ -294
OpenLib equ -408
CloseLib equ -414
OpenWindow equ -204
CloseWindow equ -72
WaitPort equ -384
GetMsg equ -372
ReplyMsg equ -378
PrintIText equ -216
Allocmem equ -198
FreeMem equ -210
Forbid equ -132
Permit equ -138
Delay equ -198
DoIO equ -454
SendIO equ -460

          


Start:
 movem.l d0/a0,-(a7)       ;save command line parameters
 move.l  #20,d6         ;possible return code to DOS
 move.l  ExecBase,a6
 movea.l #0,a1
 jsr     FindTask(a6)
 move.l  d0,a4
 tst.l   $ac(a4)
 bne     FromCLI

FromWorkBench:        ;get workbench message
 lea     $5c(a4),a0
 jsr     WaitPort(a6)
 lea     $5c(a4),a0
 jsr     GetMsg(a6)
 bra     StackAdjust

FromCLI:
 movem.l (a7)+,d0/a0  ;command line parameters
 subq    #1,d0
 beq     NoParam

LoopParam1:
 cmpi.b  #' ',(a0)+
 bne     Found
 dbra    d0,LoopParam1
 bra     NoParam
Found:
 suba.l  #1,a0
 cmpi.b  #'n',(a0)
 beq     FoundN
 cmpi.b  #'N',(a0)
 bne     NoParam
FoundN:
 adda.l  #1,a0
 cmpi.b  #'o',(a0)
 beq     FoundO
 cmpi.b  #'O',(a0)
 bne     NoParam
FoundO:
 move.w  #$86,SelAddr
 move.l  #0,AllowedD    ;found no in the command line so don't allow
 move.l  #0,AllowedS
 bra     NoParam

StackAdjust:
 movem.l (a7)+,d0/a0
NoParam:
 moveq   #0,d5          ;flag for In Effect/Not In Effect determination
 lea     DOSName,a1
 jsr     OpenLib(a6)
 move.l  d0,DOSBase
 beq     NoDOS
 lea     IntuitionName,a1
 jsr     OpenLib(a6)
 move.l  d0,IntBase
 beq     NoIntuition
 move.l  d0,a6
 lea     WindowParam,a0
 jsr     OpenWindow(a6)
 move.l  d0,WindowHandler
 beq     NoWindow
 move.l  WindowHandler,a0
 move.l  50(a0),a0
 lea     MyName,a1
 move.l  #4,d0
 move.l  #12,d1
 jsr     PrintIText(a6)
 move.l  DOSBase,a6
 move.l  #100,d1
 jsr     Delay(a6)
 move.l  IntBase,a6
 move.l  WindowHandler,a0
 jsr     CloseWindow(a6)
 move.l  #MyGadget,GadAddr
 lea     WindowParam,a0
 jsr     OpenWindow(a6)
 move.l  d0,WindowHandler
 beq     NoWindow
 move.l  WindowHandler,a0
 move.l  50(a0),a0
 lea     MyText,a1
 move.l  #4,d0
 move.l  #12,d1
 jsr     PrintIText(a6)
 move.l  ExecBase,a6
 move.l  #EndeDoIO-BeginDoIO,d0
 move.l  #$10000,d1
 jsr     Allocmem(a6)
 move.l  d0,ReservedDoIO   ;the address where we will copy the DoIO routine
 beq     NoMem
 move.l  #EndeSendIO-BeginSendIO,d0
 jsr     Allocmem(a6)
 move.l  d0,ReservedSendIO    ;same as above for SendIO
 beq     FreeDoIO

 move.l  DoIO(a6),SaveDoIO      ;save original vectors
 move.l  DoIO(a6),MySaveDoIO
 move.l  SendIO(a6),SaveSendIO
 move.l  SendIO(a6),MySaveSendIO

 move.l  #BeginDoIO,a0
 move.l  ReservedDoIO,a1
 move.l  #EndeDoIO-BeginDoIO,d0
 subi.l  #1,d0
loop1:                          ;copy the routines to the allocated mem
 move.b  (a0)+,(a1)+
 dbra    d0,loop1
 move.l  #BeginSendIO,a0
 move.l  ReservedSendIO,a1
 move.l  #EndeSendIO-BeginSendIO,d0
 subi.l  #1,d0
loop2:
 move.b  (a0)+,(a1)+
 dbra    d0,loop2

 jsr     Forbid(a6)                ;change vectors with ours
 move.l  ReservedSendIO,SendIO(a6)
 move.l  ReservedDoIO,DoIO(a6) 
 jsr     Permit(a6)
 moveq   #0,d7      ; flag to show that no diskchange has occured
         ;so that befor the first diskchange nothing is written(In Eff...)

WaitOn:                     ;this is the main loop
 move.l  WindowHandler,a0
 move.l  86(a0),d4
 move.l  d4,a0
 jsr     WaitPort(a6)
 move.l  d4,a0
 jsr     GetMsg(a6)
 move.l  d0,a0
 move.l  20(a0),d6
 move.l  d0,a1
 jsr     ReplyMsg(a6)
 cmpi.l  #$200,d6        ;Windowclose
 beq     Quit
 cmpi.l  #$8000,d6       ;diskinserted
 beq     DiskInserted

GadgetChosen:
 move.w  SelAddr,d6
 andi.w  #$80,d6       ;SELECTED?
 beq     Allow
 moveq   #0,d2      ;value in d2 is used to enable/disable writing
 bra     Enforce
Allow:
 moveq   #1,d2

Enforce:
 jsr     Forbid(a6)
 movea.l ReservedDoIO,a0
 move.l  #AllowedD-BeginDoIO,d1
 adda.l  d1,a0               ;a0 contains the address of the Allowedx
 movem.l d2,(a0)
 movea.l ReservedSendIO,a0
 move.l  #AllowedS-BeginSendIO,d1
 adda.l  d1,a0
 movem.l d2,(a0)
 jsr     Permit(a6)
 move.l  IntBase,a6
 tst.l   d7
 beq     L1
 tst.l   d5
 bne     NEffe
 subi.l  #1,d3
 bne     L1
 moveq   #2,d3
 move.l  WindowHandler,a0
 move.l  50(a0),a0
 lea     InEffect,a1
 move.l  #0,d0
 move.l  #0,d1
 jsr     PrintIText(a6)
L1:
 move.l  Execbase,a6
 moveq   #1,d5
 Bra     WaitOn
NEffe:
 sub.l   #1,d3
 move.l  WindowHandler,a0
 move.l  50(a0),a0
 lea     NotInEffect,a1
 move.l  #0,d0
 move.l  #0,d1
 jsr     PrintIText(a6)
 move.l  Execbase,a6
 moveq   #0,d5
 bra    WaitOn

DiskInserted:
 moveq   #1,d7
 move.l  IntBase,a6
 move.l  WindowHandler,a0
 move.l  50(a0),a0
 lea     InEffect,a1
 move.l  #0,d0
 move.l  #0,d1
 jsr     PrintIText(a6)
 move.l  Execbase,a6
 moveq   #1,d5
 moveq   #2,d3
 bra     WaitOn

Quit:
 moveq  #0,d6
 move.l ExecBase,a6
 move.l MySaveDoIO,DoIO(a6)
 move.l MySaveSendIO,SendIO(a6) 
 move.l ReservedSendIO,a1
 move.l #EndeSendIO-BeginSendIO,d0
 jsr    FreeMem(a6)

FreeDoIO:
 move.l ReservedDoIO,a1
 move.l #EndeDoIO-BeginDoIO,d0
 jsr    FreeMem(a6)  

NoMem:
 move.l IntBase,a6
 move.l WindowHandler,a0
 jsr    CloseWindow(a6)

NoWindow:
 move.l ExecBase,a6
 move.l IntBase,a1
 jsr    CloseLib(a6)

NoIntuition:
 move.l ExecBase,a6
 move.l DOSBase,a1
 jsr    CloseLib(a6)
NoDOS:
 move.l d6,d0
 rts


IntuitionName:  dc.b 'intuition.library',0
DOSName:        dc.b 'dos.library',0
ReservedDoIO:   dc.l 0
ReservedSendIO: dc.l 0
WindowHandler:  dc.l 0
IntBase:        dc.l 0
DOSBase:        dc.l 0
MySaveDoIO:     dc.l 0
MySaveSendIO:   dc.l 0

MyText:         dc.b 1,0,1,0
                dc.w 1,0
                dc.l 0
                dc.l Texte
                dc.l 0
Texte:          dc.b 'Allow Floppy Writes?',0,0

InEffect:       dc.b 3,0,1,0
                dc.w 20,27
                dc.l 0
                dc.l IEText
                dc.l 0
IEText:         dc.b 'In Effect:    ',0,0

NotInEffect:    dc.b 3,0,1,0
                dc.w 20,27
                dc.l 0
                dc.l NIEText
                dc.l 0
NIEText:        dc.b 'Not In Effect!',0,0


MyName:         dc.b 2,0,1,0
                dc.w 35,4
                dc.l 0
                dc.l Name1
                dc.l MyName2
Name1:          dc.b '   Ask First!',0

MyName2:        dc.b 1,0,1,0
                dc.w 35,16
                dc.l 0
                dc.l Name2
                dc.l 0
Name2:         dc.b 'By Kamran Karimi',0,0


WindowParam:
 dc.w 10
 dc.w 5
 dc.w 200
 dc.w 40
 dc.b -1
 dc.b -1
 dc.l $8220
 dc.l $e
GadAddr:
 dc.l 0
 dc.l 0
 dc.l WindowName
 dc.l 0
 dc.l 0
 dc.w 0
 dc.w 0
 dc.w 0
 dc.w 0
 dc.w 1
 
WindowName: dc.b 'AskFirst',0,0

MyGadget:
 dc.l 0
 dc.w 150
 dc.w 23
 dc.w 32
 dc.w 13
SelAddr:
 dc.w $6       ;Flags
 dc.w $102     ;activation
 dc.w 1
 dc.l ImOK
 dc.l ImNO
 dc.l 0
 dc.l 0
 dc.l 0
 dc.w 1
 dc.l 0

ImOK:
 dc.w 0,0,32,13
 dc.w 1
 dc.l ImOKData
 dc.b 2,1
 dc.l 0

ImOKData:
 dc.l %00000000000000000000000000000000
 dc.l %00001111111000000111100011100000
 dc.l %00111000001110000011100011100000
 dc.l %00111000001110000011100111000000
 dc.l %00111000001110000011101110000000
 dc.l %00111000001110000011111100000000
 dc.l %00111000001110000011111100000000
 dc.l %00111000001110000011100111000000
 dc.l %00111000001110000011100011100000
 dc.l %00111000001110000011100001110000
 dc.l %00111000001110000011100001110000
 dc.l %00001111111000000111100001110000
 dc.l %00000000000000000000000000000000

ImNO:
 dc.w 0,0,32,13
 dc.w 1
 dc.l ImNOData
 dc.b 2,1
 dc.l 0

ImNOData:
 dc.l %00000000000000000000000000000000
 dc.l %00111000000011100000111111100000
 dc.l %00111100000011100011100000111000
 dc.l %00111111000011100011100000111000
 dc.l %00111011100011100011100000111000
 dc.l %00111001110011100011100000111000
 dc.l %00111000111011100011100000111000
 dc.l %00111000011111100011100000111000
 dc.l %00111000001111100011100000111000
 dc.l %00111000000111100011100000111000
 dc.l %00111000000011100011100000111000
 dc.l %00111000000011100000111111100000
 dc.l %00000000000000000000000000000000


BeginDoIO:
 movem.l d0/a0/a1/a2/a3/a4,-(a7)
 move.l  20(a1),a2      ;device
 move.l  10(a2),a3       ;device name
 move.l  #15,d0
 lea     TrackNameD(pc),a4
lop2D:
 cmpm.b  (a3)+,(a4)+
 bne     EnditD          ;is it trackdisk.sevice
 dbra    d0,lop2D
 move.w  28(a1),d0         ;d0 has command
 andi.w  #$00ff,d0
 cmpi.w  #15,d0       ;ask for protection?
 beq     WriteD
 bra     EnditD

WriteD:
 move.l  AllowedD(pc),d0
 tst.l   d0                          ;allow write?
 beq     NoWriteD

EnditD:
 movem.l (a7)+,d0/a0/a1/a2/a3/a4
 move.l  SaveDoIO(pc),-(a7)          ;cintinue normally
 rts

NoWriteD:
 movem.l (a7)+,d0/a0/a1/a2/a3/a4
 suba.l  #4,a7
 move.l  a1,-(a7)
 lea     AddressD(pc),a1
 move.l  a1,4(a7)
 move.l  (a7)+,a1
 move.l  SaveDoIO(pc),-(a7)      ;continue routine
 rts
AddressD:
 move.b  #$ff,32(a1)        ;back from DoIO,now change the result!
 rts                      ;return to main program

SaveDoIO:   dc.l 0
AllowedD:   dc.l 1
TrackNameD: dc.b 'trackdisk.device',0,0
EndeDoIO:



BeginSendIO:
 movem.l d0/a0/a1/a2/a3/a4,-(a7)
 move.l  20(a1),a2    ;device pointer
 move.l  10(a2),a3    ;device name
 move.l  #15,d0
 lea     TrackNameS(pc),a4
lop2S:
 cmpm.b  (a3)+,(a4)+
 bne     EnditS            ;is it trackdisk.device?
 dbra    d0,lop2S
 move.w  28(a1),d0         ;d0 has command
 andi.w  #$00ff,d0
 cmpi.w  #15,d0
 beq     WriteS
 bra     EnditS

WriteS:
 move.l  AllowedS(pc),d0
 tst.l   d0
 beq     NoWriteS

EnditS:
 movem.l (a7)+,d0/a0/a1/a2/a3/a4
 move.l  SaveSendIO(pc),-(a7)
 rts

NoWriteS:
 movem.l (a7)+,d0/a0/a1/a2/a3/a4
 suba.l  #4,a7
 move.l  a1,-(a7)
 lea     AddressS(pc),a1
 move.l  a1,4(a7)
 move.l  (a7)+,a1
 move.l  SaveSendIO(pc),-(a7)
 rts
AddressS:
 move.b  #$ff,32(a1)
 rts

SaveSendIO:   dc.l 0
AllowedS:     dc.l 1
TrackNameS:   dc.b 'trackdisk.device',0,0
EndeSendIO:

 end

