home *** CD-ROM | disk | FTP | other *** search
- *****************************************************************************
- *
- * SNOOPGLUE.S vi:ts=8
- *
- * Assembly support routines for snoopdos.c
- *
- * This file contains routines to patch/unpatch dos library to point
- * to a C routine, and to call the old routines.
- *
- * Does some special tricks to patch into dos.library, in such a way
- * as to work properly under both 1.3 and 2.0.
- *
- * Also includes a tiny sprintf function.
- *
- *****************************************************************************
-
- INCLUDE "exec/types.i"
- INCLUDE "exec/libraries.i"
- INCLUDE "libraries/dosextens.i"
-
- XDEF _installdospatch
- XDEF _uninstalldospatch
- XDEF _CallLock
- XDEF _CallOpen
- XDEF _CallLoadSeg
- XDEF _CallExecute
- XDEF _CallCurrentDir
- XDEF _CallDeleteFile
- XDEF _sprintf
-
- XREF _DOSBase
- XREF _SysBase
-
- XREF _New_Open
- XREF _New_Lock
- XREF _New_LoadSeg
- XREF _New_Execute
- XREF _New_CurrentDir
- XREF _New_DeleteFile
-
- XREF _LVOOpen
- XREF _LVOLock
- XREF _LVOLoadSeg
- XREF _LVOExecute
- XREF _LVOCurrentDir
- XREF _LVODeleteFile
- XREF _LVORawDoFmt
-
- CALL MACRO
- XREF _LVO\1
- JSR _LVO\1(A6)
- ENDM
-
- SECTION SnoopDos,CODE
-
- *
- * Modify DOS library to call our functions for Open() and Lock();
- * We can't just use SetFunction() because DOS library is non-standard.
- * Instead of using JMP $123456 type instructions, it uses (mostly)
- * MOVEQ #funcnum,D0; BRA.L Dispatch. So, we replace this entire
- * sequence with a standard JMP instruction, steal the number from
- * the MOVEQ instruction and use it when we want to call the real
- * DOS library later on.
- *
- _installdospatch:
- MOVEM.L A0-A3/A6,-(A7) * Save regs
- MOVE.L 4,A6 * Get ExecBase
- MOVE.L _DOSBase,A0 * Get DOSbase
- BSET #LIBB_CHANGED,LIB_FLAGS(A0) * Indicate changing DOS library
-
- SetFunc MACRO
- MOVEM.W _LVO\1(A0),A1-A3 * Read in current value for func
- MOVEM.W A1-A3,\1Save * Save the appropriate data
- MOVEM.W CallOur\1,A1-A3 * Read in replacement code
- MOVEM.W A1-A3,_LVO\1(A0) * And modify library
- ENDM
-
- SetFunc Open
- SetFunc Lock
- SetFunc LoadSeg
- SetFunc Execute
- SetFunc CurrentDir
- SetFunc DeleteFile
-
- MOVE.L A0,A1 * Finally,
- CALL SumLibrary * Recalculate library checksum
- MOVEM.L (A7)+,A0-A3/A6 * Save regs
- RTS
-
- *
- * Reinstall previous DOS patch. If someone has already altered the
- * function, we can't actually exit immediately so return a FALSE
- * result. While there is a very small window which could cause
- * problems (if someone is in the middle of a SetFunction() when
- * this is called), but we'll ignore this mostly.
- *
- _uninstalldospatch:
- MOVEM.L A0-A3/A6,-(A7) * Save regs
- MOVE.L 4,A6 * Get sysbase
- MOVE.L _DOSBase,A0 * Get DOSBase
-
- TestFunc MACRO
- MOVE.L CallOur\1+2,D0 * Get old address of function
- CMP.L _LVO\1+2(A0),D0 * See if changed
- BNE changed * If it has, exit with no action
- ENDM
-
- TestFunc Open
- TestFunc Lock
- TestFunc LoadSeg
- TestFunc Execute
- TestFunc CurrentDir
- TestFunc DeleteFile
-
- BSET #LIBB_CHANGED,LIB_FLAGS(A0) * Indicate changing DOS library
-
- RestFunc MACRO
- MOVEM.W \1Save,A1-A3 * Read in prev. value of vec.
- MOVEM.W A1-A3,_LVO\1(A0) * Atomically restore it
- ENDM
-
- RestFunc Open
- RestFunc Lock
- RestFunc LoadSeg
- RestFunc Execute
- RestFunc CurrentDir
- RestFunc DeleteFile
-
- MOVE.L A0,A1 * Finally,
- CALL SumLibrary * Update library checksum
- MOVEQ #1,D0 * Indicate success
- BRA.S unexit * And exit
-
- changed:
- MOVEQ #0,D0 * Indicate failure to uninstall
- unexit:
- MOVEM.L (A7)+,A0-A3/A6 * Restore regs
- RTS * And exit with return in D0
-
- *
- * This code is the code that gets moved directly into the DOS
- * library vectors
- *
- CallOurOpen: JMP _New_Open
- CallOurLock: JMP _New_Lock
- CallOurLoadSeg: JMP _New_LoadSeg
- CallOurExecute: JMP _New_Execute
- CallOurCurrentDir: JMP _New_CurrentDir
- CallOurDeleteFile: JMP _New_DeleteFile
-
- *
- * These are the replacement DOS routines.
- *
- NewFunc MACRO
- MOVEM.L A2-A6/D2-D7,-(A7) * Save all registers (to be safe)
- JSR _New_\1 * Call C version with params in D1-D3
- MOVEM.L (A7)+,A2-A6/D2-D7 * Restore registers
- MOVE.L D0,D1 * Copy return value into D1
- * * [some routines expect this :-( ]
- RTS * Return to caller, exit value in D0
- ENDM
-
- NewOpen: NewFunc Open
- NewLock: NewFunc Lock
- NewLoadSeg: NewFunc LoadSeg
- NewExecute: NewFunc Execute
- NewCurrentDir: NewFunc CurrentDir
- NewDeleteFile: NewFunc DeleteFile
-
- *
- * Allow's C to call the old DOS functions. If we're running Kikstart 2.0
- * then just call the original function directly. Otherwise, calculate
- * where to go from the code stored in the vector.
- *
- OldDosCall MACRO
- LEA.L \1Save,A0 * Get pointer to func save vector
- MOVE.W #_LVO\1,D0 * Get library offset vector
- BRA.S CallDos * Skip to execute it
- ENDM
-
- _CallOpen: OldDosCall Open
- _CallLock: OldDosCall Lock
- _CallLoadSeg: OldDosCall LoadSeg
- _CallExecute: OldDosCall Execute
- _CallCurrentDir: OldDosCall CurrentDir
- _CallDeleteFile: OldDosCall DeleteFile
-
- NOP * Stop Lattice messing up final branch
- CallDos:
- MOVEM.L D1-D3/D6/D7/A6,-(A7) * Save registers
- MOVE.W (A0),D6 * Get previous instruction
- CMP.W #$4ef9,D6 * Is it a JMP instruction?
- BNE dos_exec * If not, then call using special code
- MOVE.L 2(A0),A0 * Else it's 2.0 or SetFunction()
- MOVE.L _DOSBase,A6 * Put DOSBase into A6 as expected
- JSR (A0) * Call original function
- BRA.S callexit * And exit
-
- dos_exec:
- MOVE.W (A0),D6 * Get MOVEQ instruction
- EXT.W D6 * Convert data to word
- EXT.L D6 * and then longword
- EXG.L D0,D6 * Swap with library vector offset
- MOVE.W 4(A0),D7 * Get offset to DOS routine from LVO
- MOVE.L _DOSBase,A6 * Get DOSBase
- ADD.W D6,D7 * Calculate offset value
- JSR 4(A6,D7.W) * Call DOS function dispatcher
-
- callexit:
- MOVEM.L (A7)+,D1-D3/D6/D7/A6 * Restore registers
- RTS * And return to C caller
-
- *****************************************************************************
- *
- * Taken straight from the Rom Kernel Manuals (V1.3 ed.)
- *
- * Simple version of the C sprintf() function. Assumes C-style
- * stack-based function conventions.
- *
- * long eyecount;
- * eyecount=2;
- * sprintf(string, "%s have %ld eyes.", "Fish", eyecount);
- *
- * would produce "Fish have 2 eyes." in the string buffer. Note that
- * integer arguments must be explicitly given as long, otherwise they
- * default to 16 bits.
- *
- *****************************************************************************
-
- stuffChar:
- move.b d0,(a3)+ ; Store data in output string
- rts
-
- _sprintf:
- movem.l a2-a3/a6,-(sp) ; Save registers
- move.l 4*4(sp),a3 ; Get the output string pointer
- move.l 5*4(sp),a0 ; Get the FormatString pointer
- lea.l 6*4(sp),a1 ; Get the pointer to the DataStream
- lea.l stuffChar(pc),a2 ; Get pointer to char stuff routine
- move.l _SysBase,a6 ; Get ExecBase
- jsr _LVORawDoFmt(a6) ; Format string
- movem.l (sp)+,a2-a3/a6 ; Restore registers
- rts
-
- *****************************************************************************
- *
- * Globals used by SnoopDos
- *
- *****************************************************************************
-
- SECTION SnoopData,DATA
-
- OpenSave DS.W 3
- LockSave DS.W 3
- LoadSegSave DS.W 3
- ExecuteSave DS.W 3
- CurrentDirSave DS.W 3
- DeleteFileSave DS.W 3
-
- END
-