Forgotten BCPL_GlobVec size fix.
[AROS.git] / arch / m68k-all / dos / bcpl_patches.c
blob0bad0987c711e9768d8cd7ca6f77c21ccbbc1ad2
1 #include <aros/asmcall.h>
2 #include <dos/dosextens.h>
3 #include <exec/libraries.h>
4 #include <proto/exec.h>
6 #include "bcpl.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)
39 UWORD i;
40 UWORD *asmcall, *asmmem;
41 IPTR func;
42 APTR GlobVec;
44 GlobVec = AllocMem(BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize, MEMF_PUBLIC);
45 if (GlobVec == NULL)
46 return FALSE;
48 CopyMem(BCPL_GlobVec, GlobVec, BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize);
49 GlobVec += BCPL_GlobVec_NegSize;
50 *(APTR *)(GlobVec + GV_DOSBase) = dosbase;
52 Forbid();
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)
63 continue;
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;
104 Permit();
106 return TRUE;
109 ADD2INITLIB(PatchDOS, 0)
111 static int UnPatchDOS(struct DosLibrary *dosbase)
113 APTR asmcall;
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);
119 return TRUE;
122 ADD2EXPUNGELIB(UnPatchDOS, 0)