revert between 56095 -> 55830 in arch
[AROS.git] / arch / m68k-all / dos / bcpl_patches.c
blob1e9e22d18a953fae518eb4d9dd9659a022863809
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/asmcall.h>
7 #include <string.h>
8 #include <exec/libraries.h>
9 #include <dos/dosextens.h>
10 #include <dos/dos.h>
11 #include <proto/arossupport.h>
12 #include <proto/exec.h>
13 #include <proto/dos.h>
15 #include "bcpl.h"
17 /* CallGlobVec lives in the private function (4) */
18 AROS_UFP5(LONG, CallGlobVec,
19 AROS_UFPA(LONG, function, D0),
20 AROS_UFPA(LONG, d1, D1),
21 AROS_UFPA(LONG, d2, D2),
22 AROS_UFPA(LONG, d3, D3),
23 AROS_UFPA(LONG, d4, D4));
26 /* LoadSeg() needs D1-D3 parameters for overlay hunk support */
27 AROS_UFP4(BPTR, LoadSeg_Overlay,
28 AROS_UFPA(UBYTE*, name, D1),
29 AROS_UFPA(BPTR, hunktable, D2),
30 AROS_UFPA(BPTR, fh, D3),
31 AROS_UFPA(struct DosLibrary *, DosBase, A6));
33 static AROS_UFH2(BPTR, NoReqLoadSeg,
34 AROS_UFPA(BSTR, name, D1),
35 AROS_UFPA(struct DosLibrary *, DOSBase, A6))
37 AROS_USERFUNC_INIT
39 BPTR ret = BNULL;
41 if (name != BNULL) {
42 struct Process *me = (struct Process *)FindTask(NULL);
43 int len = AROS_BSTR_strlen(name);
44 TEXT buff[len+1];
45 APTR oldWindowPtr;
47 CopyMem(buff, AROS_BSTR_ADDR(name), len);
48 buff[len] = 0;
50 oldWindowPtr = me->pr_WindowPtr;
51 me->pr_WindowPtr = (APTR)-1;
52 ret = LoadSeg(buff);
53 me->pr_WindowPtr = oldWindowPtr;
54 } else {
55 SetIoErr(ERROR_OBJECT_NOT_FOUND);
58 return ret;
60 AROS_USERFUNC_EXIT
63 AROS_UFH5(BPTR, LoadSeg_Check,
64 AROS_UFPA(UBYTE*, name, D1),
65 AROS_UFPA(BPTR, hunktable, D2),
66 AROS_UFPA(BPTR, fh, D3),
67 AROS_UFPA(APTR, LoadSeg_Original, A0),
68 AROS_UFPA(struct DosLibrary *, DOSBase, A6))
70 AROS_USERFUNC_INIT
72 UBYTE *filename;
74 /* name == NULL: Overlay LoadSeg */
75 if (name == NULL)
76 return AROS_UFC4(BPTR, LoadSeg_Overlay,
77 AROS_UFCA(UBYTE*, name, D1),
78 AROS_UFCA(BPTR, hunktable, D2),
79 AROS_UFCA(BPTR, fh, D3),
80 AROS_UFCA(struct DosLibrary *, DOSBase, A6));
82 filename = FilePart(name);
84 /* Do not allow Picasso96 to load, it is not
85 * compatible with built-in AROS RTG system */
86 if (stricmp(filename,"rtg.library") == 0)
87 return BNULL;
89 /* Call original LoadSeg function */
90 return AROS_UFC2(BPTR, LoadSeg_Original,
91 AROS_UFCA(UBYTE*, name, D1),
92 AROS_UFCA(struct DosLibrary *, DOSBase, A6));
94 AROS_USERFUNC_EXIT
97 extern void *BCPL_jsr, *BCPL_rts;
98 extern const ULONG BCPL_GlobVec[(BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize) >> 2];
100 const UWORD highfunc = 37, lowfunc = 5, skipfuncs = 2;
102 #define PATCHMEM_SIZE (10 * (highfunc - lowfunc + 1 - skipfuncs) * sizeof(UWORD) + 13 * sizeof(UWORD))
104 /* This patches two compatibility problems with badly written programs:
105 * 1) Return value in both D0 and D1.
106 * 2) 1.x original DOS functions can be called without DOSBase in A6.
107 * Both "features" are original BCPL DOS side-effects.
110 static int PatchDOS(struct DosLibrary *dosbase)
112 UWORD i;
113 UWORD *asmcall, *asmmem;
114 IPTR func;
115 APTR GlobVec;
117 GlobVec = AllocMem(BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize, MEMF_PUBLIC);
118 if (GlobVec == NULL)
119 return FALSE;
121 CopyMem(BCPL_GlobVec, GlobVec, BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize);
122 GlobVec += BCPL_GlobVec_NegSize;
123 *(APTR *)(GlobVec + GV_DOSBase) = dosbase;
125 Forbid();
127 /* Use this private slot for the C-to-BCPL thunk */
128 __AROS_INITVEC(dosbase, 4);
129 __AROS_SETVECADDR(dosbase, 4, CallGlobVec);
131 asmmem = asmcall = AllocMem(PATCHMEM_SIZE, MEMF_PUBLIC);
133 for (i = lowfunc; i <= highfunc; i++)
135 if (i == 24 || i == 25)
136 continue;
137 func = (IPTR)__AROS_GETJUMPVEC(dosbase, i)->vec;
138 __AROS_SETVECADDR(dosbase, i, asmcall);
139 *asmcall++ = 0x2f0e; // MOVE.L A6,-(SP)
140 *asmcall++ = 0x4df9; // LEA dosbase,A6
141 *asmcall++ = (UWORD)((ULONG)dosbase >> 16);
142 *asmcall++ = (UWORD)((ULONG)dosbase >> 0);
143 *asmcall++ = 0x4eb9; // JSR func
144 *asmcall++ = (UWORD)(func >> 16);
145 *asmcall++ = (UWORD)(func >> 0);
146 *asmcall++ = 0x2C5F; // MOVE.L (SP)+,A6
147 *asmcall++ = 0x2200; // MOVE.L D0,D1
148 *asmcall++ = 0x4e75; // RTS
151 /* NoReqLoadSeg() patch */
152 SetFunction((struct Library *)dosbase, 28, NoReqLoadSeg);
154 /* LoadSeg() patch */
155 func = (IPTR)__AROS_GETJUMPVEC(dosbase, 25)->vec;
156 __AROS_SETVECADDR(dosbase, 25, asmcall);
157 *asmcall++ = 0x2f0e; // MOVE.L A6,-(SP)
158 *asmcall++ = 0x4df9; // LEA dosbase,A6
159 *asmcall++ = (UWORD)((ULONG)dosbase >> 16);
160 *asmcall++ = (UWORD)((ULONG)dosbase >> 0);
161 *asmcall++ = 0x41f9; // LEA func,A0
162 *asmcall++ = (UWORD)(func >> 16);
163 *asmcall++ = (UWORD)(func >> 0);
164 *asmcall++ = 0x4eb9; // jsr LoadSeg_Check
165 *asmcall++ = (UWORD)((ULONG)LoadSeg_Check >> 16);
166 *asmcall++ = (UWORD)((ULONG)LoadSeg_Check >> 0);
167 *asmcall++ = 0x2C5F; // MOVE.L (SP)+,A6
168 *asmcall++ = 0x2200; // MOVE.L D0,D1
169 *asmcall++ = 0x4e75; // RTS
171 CacheClearE(asmmem, PATCHMEM_SIZE, CACRF_ClearI|CACRF_ClearD);
173 dosbase->dl_A5 = (LONG)&BCPL_jsr;
174 dosbase->dl_A6 = (LONG)&BCPL_rts;
175 dosbase->dl_GV = (APTR)GlobVec;
177 Permit();
179 return TRUE;
182 ADD2INITLIB(PatchDOS, 0)
184 static int UnPatchDOS(struct DosLibrary *dosbase)
186 APTR asmcall;
188 asmcall = __AROS_GETJUMPVEC(dosbase, lowfunc)->vec;
189 FreeMem(asmcall, PATCHMEM_SIZE);
190 FreeMem(dosbase->dl_GV - BCPL_GlobVec_NegSize, BCPL_GlobVec_NegSize + BCPL_GlobVec_PosSize);
192 return TRUE;
195 ADD2EXPUNGELIB(UnPatchDOS, 0)