;****** Auto-Revision Header (do not edit) *******************************
;*
;* © Copyright by PetiWare - freely distributyble software
;*
;* Filename         : SerialPatch.asm
;* Created on       : 24-Aug-92
;* Created by       : Peter Simons
;* Current revision : V2.000
;*
;*
;* Purpose: Patches the OpenDevice()-Routine to use any device instead
;*          of the serial.
;*
;*
;* V2.000 : Released:                           Peter Simons (24-Aug-92)
;*
;* V1.003 : added a delay before releasing the memory of NewOpenDev(),
;*          because this could cause problems, when the routine is in
;*          use, while the patch is removed.
;*
;* V1.002 : NewUnit-switch added
;*
;* V1.001 : PatchOnlyUnit-switch added
;*
;* V1.000 : released:                           Peter Simons (24-Aug-92)
;*
;* V0.300 : Argument-Parsing implemented
;*
;* V0.200 : Main patch-routine works
;*
;* V0.100 : Patch based on my CPUClear V2.011
;*
;* V0.000 : --- Initial release ---
;*
;*************************************************************************
;
;

;***************************************************************************
;*                                                                         *
;* SEKTION: Labels, Macros, Switches, Structures                           *
;*                                                                         *
;***************************************************************************

;-------------------------------------- Switches -----------
                MC68000
                EXEOBJ
                OBJFILE "RAM:SerialPatch"
                NEWSYNTAX
                MULTIPASS

;-------------------------------------- Exec ---------------
MEMF_PUBLIC     equ     1<<0

;-------------------------------------- Labels -------------
                MACLIB  "DATAS:Offsets.preass"
KICKVERSION     equ     37

_DOSBase        equr    A5
_NewOpenDev     equr    A3
_OutputHandle   equr    D7
_RDArgsStruct   equr    D6

;-------------------------------------- Macros -------------
REVISION        MACRO
                dc.b "2.000"
                ENDM
REVDATE         MACRO
                dc.b "24-Aug-92"
                ENDM



;***************************************************************************
;*                                                                         *
;* SEKTION: Program                                                        *
;*                                                                         *
;***************************************************************************

START:          lea     (DATA,PC),a4
                BASEREG A4,DATA
                OPTIMON BASEREG

                move.l  ($4).W,a6
                lea     (dosname,PC),a1
                moveq   #KICKVERSION,d0
                jsr     (_LVOOpenLibrary,a6)            ; open Dos-Library
                tst.l   d0
                beq     .ErrorExit
                move.l  d0,_DOSBase

                move.l  _DOSBase,a6
                lea     (Template,PC),a0
                move.l  a0,d1
                lea     (_NewDeviceName,PC),a2
                move.l  a2,d2
                moveq   #0,d3
                jsr     (_LVOReadArgs,a6)
                move.l  d0,_RDArgsStruct
                bne.b   .ArgsOkay
                pea     (.CloseDosLib,PC)
                bra     _ErrorHandle

.ArgsOkay       move.l  _DOSBase,a6
                jsr     (_LVOOutput,a6)                 ; get standard-
                move.l  d0,_OutputHandle                ; outputhandle

                move.l  _OutputHandle,d1
                beq.b   .SkipWrite
                lea     (Header,PC),a0                  ; write standard-
                move.l  a0,d2                           ; header
                moveq   #Header_len,d3
                jsr     (_LVOWrite,a6)

.SkipWrite      move.l  ($4).w,a6
                move.l  (_LVOOpenDevice+2,a6),_NewOpenDev ; is the patch
                cmp.l   #'SPAT',(new_ID,_NewOpenDev)    ; already installed?
                beq     .RemovePatch                    ; Yep->remove

;-------------------------------------- install patch ------

                lea     (_NewDeviceName,PC),a0
                tst.l   (a0)
                bne.b   .ArgOkay
                moveq   #116,d0         ; REQUIRED_AGUMENT_MISSING
                pea     (.FreeArgs,PC)
                bra     _PrintError

.ArgOkay        move.l  (a0),a0
                bsr     _Len
                add.l   #NewOpenDev_len,d0
                moveq   #MEMF_PUBLIC,d1
                move.l  ($4).W,a6
                jsr     (_LVOAllocVec,a6)
                tst.l   d0
                bne.b   .BufferOkay
                pea     (.FreeArgs,PC)
                moveq   #103,d0                 ; NO_FREE_STORE
                bra     _PrintError

.BufferOkay     move.l  d0,_NewOpenDev
                lea     (NewOpenDev,PC),a0
                move.l  _NewOpenDev,a1          ; copy patch into
                moveq   #NewOpenDev_len,d0      ; reserved buffer
                jsr     (_LVOCopyMem,a6)

                tst.l   (_PatchOnlyUnit)
                beq.b   .NoOnlyUnit
                move.l  (_PatchOnlyUnit,PC),a0
                move.l  (a0),(new_PatchOnlyUnit,_NewOpenDev)

.NoOnlyUnit     tst.l   (_NewUnit)
                beq.b   .NoNewUnit
                move.l  (_NewUnit,PC),a0
                move.l  (a0),(new_NewUnit,_NewOpenDev)

.NoNewUnit      move.l  (_NewDeviceName,PC),a0
                bsr     _Len
                lea     (new_NewDevName,_NewOpenDev),a1 ; copy new device-
                jsr     (_LVOCopyMem,a6)                ; name into reserved
                                                        ; buffer
                jsr     (_LVOForbid,a6)
                move.l  ($4).w,a1
                move.w  #_LVOOpenDevice,a0              ; patch OS-function
                move.l  _NewOpenDev,d0
                jsr     (_LVOSetFunction,a6)
                move.l  d0,(new_OldOpenDev,_NewOpenDev) ; save old vector
                jsr     (_LVOCacheClearU,a6)            ; flush caches for
                jsr     (_LVOPermit,a6)                 ; '40 compatiblity

                lea     (Install,PC),a0                 ; give feedback :-)
                moveq   #Install_len,d3
                bra.b   .exit

;-------------------------------------- remove patch -------
.RemovePatch    move.l  ($4).w,a1
                move.w  #_LVOOpenDevice,a0
                move.l  (new_OldOpenDev,_NewOpenDev),d0
                move.l  ($4).W,a6
                jsr     (_LVOSetFunction,a6)            ; replace old
                move.l  d0,a2                           ; function and
                                                        ; release memory
                move.l  _DOSBase,a6                     ; after a delay
                moveq   #100,d1
                jsr     (_LVODelay,a6)

                move.l  a2,a1
                move.l  ($4).W,a6
                jsr     (_LVOFreeVec,a6)

                move.l  _DOSBase,a6
                lea     (Remove,PC),a0
                moveq   #Remove_len,d3

;-------------------------------------- exit gracefully ----

.exit           move.l  _OutputHandle,d1
                beq.b   .FreeArgs
                move.l  a0,d2
                move.l  _DOSBase,a6
                jsr     (_LVOWrite,a6)

                move.l  _OutputHandle,d1
                lea     (Returns,PC),a0
                move.l  a0,d2
                moveq   #Returns_len,d3
                jsr     (_LVOWrite,a6)

.FreeArgs       move.l  _RDArgsStruct,d1
                move.l  _DOSBase,a6
                jsr     (_LVOFreeArgs,a6)

.CloseDosLib    move.l  ($4).W,a6               ; close resources
                move.l  _DOSBase,a1
                jsr     (_LVOCloseLibrary,a6)

.ErrorExit      moveq   #0,d0
                rts

;***************************************************************************
;*                                                                         *
;* SEKTION: Subroutines                                                    *
;*                                                                         *
;***************************************************************************
_ErrorHandle:   move.l  _DOSBase,a6
                jsr     (_LVOIoErr,a6)
_PrintError:    move.l  d0,d1
                moveq   #0,d2
                move.l  _DOSBase,a6
                jmp     (_LVOPrintFault,a6)


_Len:           pea     (a0)            ; save register
.loop           tst.b   (a0)+
                bne.b   .loop           ; currect char equal zero?
                move.l  a0,d0
                move.l  (SP)+,a0
                sub.l   a0,d0           ; return string-length INCLUDING
                rts                     ; the ZERO-byte


;***************************************************************************
;*                                                                         *
;* SEKTION: new OpenDev()-Routine                                          *
;*                                                                         *
;***************************************************************************
NewOpenDev:
saveregs        setrl   a0-a1
                movem.l saveregs,-(SP)

                lea     (.PatchOnlyUnit,PC),a1
                cmp.w   #-1,(a1)
                beq.b   .Cmp
                cmp.l   (a1),d0
                bne.b   .OpenNormal

.Cmp            lea     (.SerDeviceName,PC),a1
.CmpLoop        tst.b   (a0)                    ; compare device-name with
                beq.b   .PatchIt                ; the specified one (default
                cmpm.b  (a0)+,(a1)+             ; is serial.device) and
                bne.b   .OpenNormal             ; replace it if it's the
                bra.b   .CmpLoop                ; same

.PatchIt        lea     (.NewUnit,PC),a0
                cmp.l   #-1,(a0)
                beq.b   .NoNewUnit

                movem.l (SP)+,saveregs
                lea     (.NewDeviceName,PC),a0
                move.l  (.NewUnit,PC),d0
                bra.b   .OldOpenDev

.NoNewUnit      movem.l (SP)+,saveregs
                lea     (.NewDeviceName,PC),a0
                bra.b   .OldOpenDev

.OpenNormal     movem.l (SP)+,saveregs

new_OldOpenDev  equ     (*-NewOpenDev+2)
.OldOpenDev     jmp     ($00000000).L
new_ID          equ     (*-NewOpenDev)
                dc.b    "SPAT"
new_PatchOnlyUnit       equ     (*-NewOpenDev)
.PatchOnlyUnit  dc.l    -1
new_NewUnit     equ     (*-NewOpenDev)
.NewUnit        dc.l    -1
.SerDeviceName  dc.b    "serial.device",0
new_NewDevName  equ     (*-NewOpenDev)
.NewDeviceName

NewOpenDev_len  equ     (*-NewOpenDev)          ; length of routine

;***************************************************************************
;*                                                                         *
;* SEKTION: Daten, Zeiger                                                  *
;*                                                                         *
;***************************************************************************
DATA:

dosname         dc.b    "dos.library",0
Header          dc.b    $9B,"1;33",$6D
                dc.b    "$VER: SerialPatch "
                REVISION
                dc.b    " ("
                REVDATE
                dc.b    ")"
                dc.b    $9B,$6D
                dc.b    " coding by Peter Simons",$0A
Header_len      equ     (*-Header)

Install         dc.b    "Installed"
Install_len     equ     (*-Install)
Remove          dc.b    "Removed"
Remove_len      equ     (*-Remove)
Returns         dc.b    "...",$0A,$0A
Returns_len     equ     (*-Returns)

Template        dc.b    "NewDevice,POU=PatchOnlyUnit/N,NewUnit/N",0

_NewDeviceName  ds.l    1
_PatchOnlyUnit  ds.l    1
_NewUnit        ds.l    1

                END
