;
; UnixDir.asm             (c) 1988  Software Dimensions.
;          ______
;         /     /\        All Rights Reserved
;        /_____/ |\       Written by Murray Bennett and Mark Cyster
;       |\    |\  /|      Software Dimensions
;       | \/__|_\/ |      6th Floor, 239 Adelaide Tce
;       |__|     | |      Perth WA 6000
;        \ |  4  | /      Australia
;         \|_____|/
;                         BBS:(In Australia !??)
;
;----------------------------------------------------------------------------
; This material is Copyright (C) 1988 and 1989 Software Dimensions.
; It may be distributed freely as long as the following restrictions are met:
;
;    1.  All files present in the distribution package must be redistributed
;        with the package.  If you distribute on diskette, all files must be
;        on a single diskette.
;        Files in this distribution are listed in FILES.LIST
;
;    2.  The distributor agrees to cease distributing the programs and data
;        involved if requested to do so by authors or any member of The
;        Software Distillery.
;
; DISCLAIMER
;
; Neither Software Dimensions nor any of its members will be liable for
; any damage arising from the failure of this program to perform as described,
; or any destruction of other programs or data residing on a system
; attempting to run the program.  While we know of no damaging errors, the
; user of this program uses it at his or her own risk.
;
; DONATIONS
;
; Welcome (but we realise it's a long way to Australia).
;
;----------------------------------------------------------------------------
;
;  Date 27-2-89
;
;  This is the loader part of UnixDirs
;
;  This stub simply loads L:UnixDirs-Handler into
;  memory and modifies the appropriate DOS calls
;  so we get called
;
;  Note: It makes assumptions about the format of the loaded segment
;
;
;  This program SetFunction's the following DOS library vectors :
;
;     CreateDir
;     DeleteFile
;     LoadSeg
;     Lock
;     Open
;     Rename
;     SetComment
;     SetProtection
;
;  Note: The DOS library jump table is not in the statndard EXEC library
;        format.
;        moveq    FunctionNum,d0  $70   'FunctionNum'(8 Bit)  total = 2 Bytes
;        bra.l    DOSFunction     $6000 'DosFunction'(16 Bit) total = 4 Bytes
;
;----------------------------------------------------------------------------

            NOLIST
            INCLUDE     "UnixDirs.i"
            LIST

            xref        _LVOAlert
            xref        _LVOCloseLibrary
            xref        _LVOForbid
            xref        _LVOLoadSeg
            xref        _LVOOpenLibrary
            xref        _LVOOutput
            xref        _LVOPermit
            xref        _LVOSetFunction
            xref        _LVOUnLoadSeg
            xref        _LVOWrite

            ; replaced functions
            xref        _LVOCreateDir
            xref        _LVODeleteFile
            xref        _LVOLoadSeg
            xref        _LVOLock
            xref        _LVOOpen
            xref        _LVORename
            xref        _LVOSetComment
            xref        _LVOSetProtection

MoveqNumD0  equ         $70

;
; Places the old DOS function number in UnixTable (the passed parameters)
; or jumps to ErrorBadDOSFormat if library not in DOS format
;
GET_OLD_NUM MACRO
            move.l      #_LVO\1,d0
            bsr         GetDOSNum
            bne         ErrorBadDOSFormat
            move.l      d0,\1Num(TableBase)
            ENDM

;
; Replaces the old DOS jump vector with a jump to the new routine
;
REPL_OLD_FUNC MACRO
            ; Replaces DOS function \1
            move.l      #_LVO\1,d1
;            DBPrint     <'Replacing dos function \1'>
            lea.l       \1JumpInst+UnixTable_Sizeof(TableBase),a0
            bsr         ReplaceDOSFunction
            ENDM

; ******
; start
; ******

ArpBase     equr         a5
TableBase   equr         a3         ; Points to top of Passed Parameters
                                    ;

;            RESIDENT    2000
            STARTUP

            ;
            ; open arp library
            lea.l       ArpLibrary,a1
            move.l      #ArpVersion,d0
            move.l      AbsExecBase,a6
            LINKEXEC    OpenLibrary
            tst.l       d0
            beq         NoArpExit
            move.l      d0,ArpBase              ; arp library open - everything OK

            ;
            ; load 'handler'
            lea.l       handler,a0
            move.l      a0,d1
            move.l      DosBase(ArpBase),a6
            LINKDOS     LoadSeg
            BTOC        d0
            beq         LoadHandlerError
            add.l       #SegmentStart_Sizeof,d0       ; Handler loaded successfully
            move.l      d0,TableBase

            move.l      ArpBase,SaveArpBase(TableBase) ; Save ArpBase
            ;
            ; Forbid -  as we don't want anyone changing the DOS jump table
            ;           or using it while we change it
            move.l      AbsExecBase,a6
            LINKEXEC    Forbid

            ;
            ; All DOS functions jump to the same function so first we
            ; get a pointer to this function and keep it
            ;
            ; The DOS table doesn't have the standard format jump table
            ; but it's own peculiar format :
            ;  moveq    FunctionNum,d0     $70   'FunctionNum'(8 Bit)  total = 2 Bytes
            ;  bra.l    DOSFunction        $6000 'DosFunction'(16 Bit) total = 4 Bytes
            ;

            ;
            ; Get and Pass (to 'handler')  pointer to the 'DOSFunction'
            move.l      DosBase(ArpBase),a0
            add.l       #_LVOLoadSeg,a0       ; Any dos function will do
            move.w      4(a0),d0              ; Get 'DOSFunction'
            lea.l       4(a0,d0.w),a0         ; jmp val - jumps from end of jump instruction (before val)
            move.l      a0,DOSFunction(TableBase)

            ;
            ; Save DOS function call numbers in UnixTable
            ; Don't modify yet - first check all are in DOS format
            ;                    if not exit -> allows for easier cleanup
            move.l      DosBase(ArpBase),a0
            GET_OLD_NUM CreateDir
            GET_OLD_NUM DeleteFile
            GET_OLD_NUM LoadSeg
            GET_OLD_NUM Lock
            GET_OLD_NUM Open
            GET_OLD_NUM Rename
            GET_OLD_NUM SetComment
            GET_OLD_NUM SetProtection

            REPL_OLD_FUNC CreateDir
            REPL_OLD_FUNC DeleteFile
            REPL_OLD_FUNC LoadSeg
            REPL_OLD_FUNC Lock
            REPL_OLD_FUNC Open
            REPL_OLD_FUNC Rename
            REPL_OLD_FUNC SetComment
            REPL_OLD_FUNC SetProtection

            ;
            ; Permit
CleanUp1
            move.l      AbsExecBase,a6
            LINKEXEC    Permit

            ; Display a message to say that everything went OK

            lea.l       InstalledOKMessage,a1
            move.l      ArpBase,a6
            LINKARP     Puts

            ;
            ; Exit with return code 0
            move.l      #0,d0

            ;
            ; end - with arp
            ;
exit
            move.l      ArpBase,a6
            move.l      #0,d1
            move.l      #0,d2
            LINKARP     ArpExit
            rts


            ;
            ; Dos Library already modified
ErrorBadDOSFormat
            lea.l       BadLibraryFormat,a1
            move.l      ArpBase,a6
            LINKARP     Puts
            bsr         UnloadSegment
            move.l      #5,d0
            bra         exit

            ;
            ; Unload the loaded handler because of an error
            ; condition.
            ; CPTR to handler is TableBase - SegmentStart_Sizeof
            ;
UnloadSegment
            move.l      TableBase,d1
            sub.l       #SegmentStart_Sizeof,d1
            CTOB        d1
            move.l      DosBase(ArpBase),a6
            LINKDOS     UnLoadSeg
            rts

            ;
            ; unable to load 'handler'
            ;
LoadHandlerError
            lea.l      LoadError,a1
            move.l     ArpBase,a6
            LINKARP    Puts
            move.l     #10,d0
            bra        exit

            ;
            ; end - without arp
            ;
NoArpExit
            ;exec base is still in a6
            lea.l       DOSLibrary,a1
            moveq       #0,d0                   ;version unimportant
            LINKEXEC    OpenLibrary
            tst.l       d0
            beq         BadExit

            move.l      d0,a6                   ;DOSBase
            LINKDOS     Output
            move.l      d0,d1
            lea.l       NoArp,a0
            move.l      a0,d2
            move.l      #(NoArpEnd-NoArp),d3
            LINKDOS     Write

            move.l      a6,a1                   ;Closing dos.library
            move.l      AbsExecBase,a6
            LINKEXEC    CloseLibrary
DosExit
            move.l      #20,d0
            rts

            ;
            ; couldn't even find DOS
            ;
BadExit
            ALERT       (AG_OpenLib|AO_DOSLib)
            bra         DosExit

; ******
; OldNum = GetDOSNum(_LVOffset,DosBase)
;  d0                   d0       a0
;
; Where OldNum is the value passed in d0 to the 'DosFunction'
;              when you call the specific DOS routine at the
;              '_LVOffset' you pass
;            - if the jump table is in non DOS format we fail
;              and return with the Z-flag set
;              (which it will be if we are already implemented)
; ******
GetDOSNum
            move.b      (a0,d0),d1
            move.b      1(a0,d0),d0
            ext.w       d0
            ext.l        d0
            cmp.b       #MoveqNumD0,d1
            rts


; ******
; OldBranchInstruction = ReplaceDOSFunction(_LVOffset,NewFunction)
;              d0                              d1        a0
;
; ******
ReplaceDOSFunction
            move.l      DosBase(ArpBase),a1         ; library = DosBase
            move.l      a0,d0                       ; New function
            move.l      d1,a0                       ; offset
            move.l      AbsExecBase,a6              ; Exec call
            LINKEXEC    SetFunction
            rts

;
;
            DSEG

DOSLibrary  DOSNAME

NoArp       dc.b        'Can',$27,'t open '
ArpLibrary  ArpName
            dc.b        10,13
NoArpEnd

LoadError   dc.b        'Unable to load '
handler     dc.b        'L:UnixDirs-Handler',0

OutOfMem    dc.b        'Out of memory',0

BadLibraryFormat
            dc.b        'The DOS library jump table has already been modified',0

InstalledOKMessage
            dc.b        'UnixDirs Installed',0
            end

