****     A Privilige Violation handler for the 68010 CPU               ****
****     To use for traping those MOVE SR,ea instructions I went to use ***
****     Decigel but found it would not survive a reboot. I needed this ***
****     for those copy protected programs that run from boot. The idea ***
****     for the Violation code is from Scott Turner's Decigel program. I *
****     added the code that will allow it to survive a warm boot.     ****
****     To remove the handler press the left mouse button while       ****
****     rebooting. The screen will flash red to let you know the code ****
****     has gone. It allocates a port so that if you try to install   ****
****     it again it will tell you it is already there.                ****
****     The port also allows the PrivligeHandler -q to find the code  ****
****     so it can deallocate the Memory                               ****
****     The other way to get rid of it is to type PrivligeHandler -q  ****
****     I am placing this into the public domain for use by anyone    ****
****     John Veldthuis
****     21 Ngatai Street
****     Manaia, Taranaki
****     New Zealand

****     Revision 1  03/04/88
****     Added code to remove handler from Cli

	ifd	CAPE
	EXEOBJ
	OBJFILE	'ram:Priv'
	endc

PrivVect          EQU   $20      ; Address of Privlege error vector
_LVOOpenLibrary   EQU   -$228
_LVOCloseLibrary  EQU   -$19E
_LVOFindPort      EQU   -$186
_LVOAddPort       EQU   -$162
_LVORemovePort    EQU   -$168
_LVOAllocMem      EQU   -$C6
_LVOAllocAbs      EQU   -$CC
_LVOFreeMem       EQU   -$D2

_LVOOutput        EQU   -$3C
_LVOWrite         EQU   -$30

Start:
         movem.l  d0/a0,-(sp)       ;save command line
         move.l   4,a6
         lea      DosName(pc),a1
         moveq.l  #0,d0
         jsr      _LVOOpenLibrary(a6)         ;open dos library
         tst.l    d0
         bne.s    1$
         moveq.l  #20,d0            ;error if no Dos
         rts
1$       move.l   d0,DosBase
         move.l   d0,a6
         jsr      _LVOOutput(a6)
         move.l   d0,StdOut
         movem.l  (sp)+,d0/a0       ;restore command line
         move.b   #0,0(a0,d0.w)   ;zero end of line
         move.l   4,a6
Loop     move.b   (a0)+,d0
         tst.b    d0
         beq      NoQuit            ;if no command install handler
         cmp.b    #'-',d0
         bne.s    Loop              ;look for -q
         move.b   (a0),d0           ;should now be a 'q'
         cmp.b    #'q',d0
         bne.s    Loop
         lea      PortName(pc),a1
         jsr      _LVOFindPort(a6)
         tst.l    d0
         bne.s    PortHere
         lea      NoHandler(pc),a1
         move.l   a1,d2
         move.l   StdOut,d1
         move.l   #23,d3
         move.l   DosBase,a6
         jsr      _LVOWrite(a6)
         bra      Quit
PortHere move.l   d0,a4             ;a4 = pointer to port
         move.l   -4(a4),d0         ;d0 = old exception handler
         move.l   d0,$20            ;restore old handler
         clr.l    $2e(a6)           ;reset coolcapture vector
         bsr      CheckSum          ;redo exec checksum
         move.l   a4,a1
         jsr      _LVORemovePort(a6) ;remove port
         move.l   a4,a0
         move.l   #Port1-Install,d0
         sub.l    d0,a0
         move.l   a0,a1
         move.l   #CodeEnd-MoveMe,d0
         jsr      _LVOFreeMem(a6)  ;freeMem
         lea      Remove(pc),a0
         move.l   a0,d2
         move.l   StdOut,d1
         move.l   #17,d3
         move.l   DosBase,a6
         jsr      _LVOWrite(a6)
         bra      Quit
NoQuit   move.l   4,a6
         lea      PortName(pc),a1
         jsr      _LVOFindPort(a6)         ;find port
         tst.l    d0
         beq.s    10$               ;if no port then go install handler
         move.l   DosBase,a6        ;otherwise print that handler installed
         move.l   StdOut,d1
         lea      Mess3(pc),a0
         move.l   a0,d2
         move.l   #27,d3
         jsr      _LVOWrite(a6)
         bra.s    Quit

10$      move.l   #CodeEnd-MoveMe,d0
         moveq.l  #0,d1
         jsr      _LVOAllocMem(a6)   ;allocate memory for handler
         tst.l    d0
         bne.s    2$
         move.l   DosBase,a6        ;if not enough then print message
         move.l   StdOut,d1
         lea      Mess1(pc),a0
         move.l   a0,d2
         move.l   #34,d3
         jsr      _LVOWrite(a6)
         moveq.l  #20,d0
         rts
2$       move.l   d0,a4       ;save local copy of memory allocation
         move.l   d0,a1
         lea      MoveMe(pc),a0
         move.l   CodeSize,d0
3$       move.l   (a0)+,(a1)+ ;copy code to allocated memory
         dbf      d0,3$
         jsr      (a4)        ;install handler
         move.l   DosBase,a6
         lea      Mess2(pc),a0
         move.l   a0,d2
         move.l   StdOut,d1
         move.l   #29,d3
         jsr      _LVOWrite(a6)    ;print installed message
Quit     move.l   a6,a1
         move.l   4,a6
         jsr      _LVOCloseLibrary(a6)      ;close dos.library
         moveq.l  #0,d0
         rts



StdOut   dc.l  0
DosBase  dc.l  0
DosName  dc.b  'dos.library',0
Mess1    dc.b  'Can''t Allocate memory for Handler',10,0
Mess2    dc.b  'Privilege Handler Installed',10,0
Mess3    dc.b  'Handler already Installed',10,0
NoHandler dc.b 'Handler not Installed',10,0
Remove   dc.b  'Handler Removed',10,0

         cnop  0,4

MoveMe:
Install:
         move.l   4,a6
         btst     #6,$BFE001        ;Test left mouse button
         bne.s    2$
         clr.l    $2E(a6)           ;if button down reset vector
         bsr      CheckSum
         lea      $DFF000,a5
         move.w   #$F00,$180(a5)
         moveq    #$64,d0
4$       cmpi.b   #0,6(a5)          ;flash screen to indicate
         bne.s    4$                ;handler removed
5$       cmpi.b   #0,6(a5)
         bne.s    5$
         dbf      d0,4$
         moveq.l  #0,d0
         rts
2$       lea      Install(pc),a1    ;memory allocation will fail the first
         move.l   #CodeEnd-MoveMe,d0 ;time we do this but we dont care
         jsr      _LVOAllocAbs(a6)  ;Allocate Mem so No-one else gets it
         lea      Port1(pc),a0
         moveq.l  #0,d0
         move.l   d0,(a0)
         move.l   d0,4(a0)
         move.w   #$0400,8(a0)
         move.w   d0,14(a0)
         move.l   d0,16(a0)
         lea      PortName(pc),a1
         move.l   a1,10(a0)
         lea      Port1(pc),a1
         jsr      _LVOAddPort(a6)   ;addport to let every know we are here
         lea      Install(pc),a0
         Move.l   a0,$2e(a6)        ;install handler into warm boot
         bsr.s    CheckSum          ;recompute exec checksum
         lea      OpCode+2(pc),a0
         move.l   PrivVect,(A0)    ; Patch old vector into our handler
         lea      PivVi(pc),a2
         move.l   A2,PrivVect       ; Patch us into the vector
         moveq    #0,D0             ; Good return code
         rts                        ; Back to AmigaDOS, no error
CheckSum:
         lea      $22(a6),a0       ;recompute exec checksum
         clr.w    d0
         moveq    #$17,d1
3$       add.w    (a0)+,d0
         dbf      d1,3$
         not.w    d0
         move.w   d0,(a0)
         rts

PivVi    movem.l  D0/A0,-(SP)       ; Save registers
         move.l   8+2(SP),A0        ; Pointer to opcode
         move.w   (A0),D0           ; Pickup opcode
         andi.w   #~%111111,D0      ; Mask out EA field
         cmpi.w   #$40C0,D0         ; Is it a MOVE SR,ea?
         bne.s    NotOne
         bset     #1,(A0)           ; Convert it to MOVE CCR,ea
         movem.l  (SP)+,D0/A0       ; Restore regs
         rte                        ; Rerun new opcode

NotOne   movem.l  (SP)+,D0/A0       ; Restore regs
OpCode   jmp      $FC0000   ; To previous handler, patched by our install
Port1    dc.l     0
         dc.l     0
         dc.b     4              ;port type
         dc.b     0
         dc.l     0              ;port name
         dc.b     0
         dc.b     0
         dc.l     0
         ds.b     14
PortName dc.b     'PrivHandler',0
         cnop 0,4                   ; installation of this routine
CodeEnd
CodeSize DC.L     (CodeEnd-MoveMe)/4    ; Size of routine
         end
