1 #include <aros/asmcall.h>
2 #include <dos/dosextens.h>
3 #include <exec/libraries.h>
4 #include <proto/exec.h>
8 /* CallGlobVec lives in the private function (4) */
9 AROS_UFP5(LONG
, CallGlobVec
,
10 AROS_UFPA(LONG
, function
, D0
),
11 AROS_UFPA(LONG
, d1
, D1
),
12 AROS_UFPA(LONG
, d2
, D2
),
13 AROS_UFPA(LONG
, d3
, D3
),
14 AROS_UFPA(LONG
, d4
, D4
));
17 /* LoadSeg() needs D1-D3 parameters for overlay hunk support */
18 AROS_UFP4(BPTR
, LoadSeg_Overlay
,
19 AROS_UFPA(UBYTE
*, name
, D1
),
20 AROS_UFPA(BPTR
, hunktable
, D2
),
21 AROS_UFPA(BPTR
, fh
, D3
),
22 AROS_UFPA(struct DosLibrary
*, DosBase
, A6
));
24 extern void *BCPL_jsr
, *BCPL_rts
;
25 extern const ULONG BCPL_GlobVec
[(BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
) >> 2];
27 const UWORD highfunc
= 37, lowfunc
= 5, skipfuncs
= 2;
29 #define PATCHMEM_SIZE (10 * (highfunc - lowfunc + 1 - skipfuncs) * sizeof(UWORD) + 16 * sizeof(UWORD))
31 /* This patches two compatibility problems with badly written programs:
32 * 1) Return value in both D0 and D1.
33 * 2) 1.x original DOS functions can be called without DOSBase in A6.
34 * Both "features" are original BCPL DOS side-effects.
37 static int PatchDOS(struct DosLibrary
*dosbase
)
40 UWORD
*asmcall
, *asmmem
;
44 GlobVec
= AllocMem(BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
, MEMF_PUBLIC
);
48 CopyMem(BCPL_GlobVec
, GlobVec
, BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
);
49 GlobVec
+= BCPL_GlobVec_NegSize
;
50 *(APTR
*)(GlobVec
+ GV_DOSBase
) = dosbase
;
54 /* Use this private slot for the C-to-BCPL thunk */
55 __AROS_INITVEC(dosbase
, 4);
56 __AROS_SETVECADDR(dosbase
, 4, CallGlobVec
);
58 asmmem
= asmcall
= AllocMem(PATCHMEM_SIZE
, MEMF_PUBLIC
);
60 for (i
= lowfunc
; i
<= highfunc
; i
++)
62 if (i
== 24 || i
== 25)
64 func
= (IPTR
)__AROS_GETJUMPVEC(dosbase
, i
)->vec
;
65 __AROS_SETVECADDR(dosbase
, i
, asmcall
);
66 *asmcall
++ = 0x2f0e; // MOVE.L A6,-(SP)
67 *asmcall
++ = 0x4df9; // LEA dosbase,A6
68 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 16);
69 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 0);
70 *asmcall
++ = 0x4eb9; // JSR func
71 *asmcall
++ = (UWORD
)(func
>> 16);
72 *asmcall
++ = (UWORD
)(func
>> 0);
73 *asmcall
++ = 0x2C5F; // MOVE.L (SP)+,A6
74 *asmcall
++ = 0x2200; // MOVE.L D0,D1
75 *asmcall
++ = 0x4e75; // RTS
78 /* Redirect LoadSeg() to LoadSeg_Overlay() if D1 == NULL */
79 func
= (IPTR
)__AROS_GETJUMPVEC(dosbase
, 25)->vec
;
80 __AROS_SETVECADDR(dosbase
, 25, asmcall
);
81 *asmcall
++ = 0x2f0e; // MOVE.L A6,-(SP)
82 *asmcall
++ = 0x4df9; // LEA dosbase,A6
83 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 16);
84 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 0);
85 *asmcall
++ = 0x41f9; // LEA func,A0
86 *asmcall
++ = (UWORD
)(func
>> 16);
87 *asmcall
++ = (UWORD
)(func
>> 0);
88 *asmcall
++ = 0x4a81; // TST.L D1
89 *asmcall
++ = 0x6606; // BNE.B +6 (D1 not NULL = normal LoadSeg)
90 *asmcall
++ = 0x41f9; // LEA LoadSeg_Overlay,A0
91 *asmcall
++ = (UWORD
)((ULONG
)LoadSeg_Overlay
>> 16);
92 *asmcall
++ = (UWORD
)((ULONG
)LoadSeg_Overlay
>> 0);
93 *asmcall
++ = 0x4e90; // JSR (A0)
94 *asmcall
++ = 0x2C5F; // MOVE.L (SP)+,A6
95 *asmcall
++ = 0x2200; // MOVE.L D0,D1
96 *asmcall
++ = 0x4e75; // RTS
98 CacheClearE(asmmem
, PATCHMEM_SIZE
, CACRF_ClearI
|CACRF_ClearD
);
100 dosbase
->dl_A5
= (LONG
)&BCPL_jsr
;
101 dosbase
->dl_A6
= (LONG
)&BCPL_rts
;
102 dosbase
->dl_GV
= (APTR
)GlobVec
;
109 ADD2INITLIB(PatchDOS
, 0)
111 static int UnPatchDOS(struct DosLibrary
*dosbase
)
115 asmcall
= __AROS_GETJUMPVEC(dosbase
, lowfunc
)->vec
;
116 FreeMem(asmcall
, PATCHMEM_SIZE
);
117 FreeMem(dosbase
->dl_GV
- BCPL_GlobVec_NegSize
, BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
);
122 ADD2EXPUNGELIB(UnPatchDOS
, 0)