2 #include <aros/asmcall.h>
4 #include <exec/libraries.h>
5 #include <dos/dosextens.h>
7 #include <proto/arossupport.h>
8 #include <proto/exec.h>
13 /* CallGlobVec lives in the private function (4) */
14 AROS_UFP5(LONG
, CallGlobVec
,
15 AROS_UFPA(LONG
, function
, D0
),
16 AROS_UFPA(LONG
, d1
, D1
),
17 AROS_UFPA(LONG
, d2
, D2
),
18 AROS_UFPA(LONG
, d3
, D3
),
19 AROS_UFPA(LONG
, d4
, D4
));
22 /* LoadSeg() needs D1-D3 parameters for overlay hunk support */
23 AROS_UFP4(BPTR
, LoadSeg_Overlay
,
24 AROS_UFPA(UBYTE
*, name
, D1
),
25 AROS_UFPA(BPTR
, hunktable
, D2
),
26 AROS_UFPA(BPTR
, fh
, D3
),
27 AROS_UFPA(struct DosLibrary
*, DosBase
, A6
));
29 static AROS_ENTRY(LONG
, SetPatch_noop
,
30 AROS_UFHA(char *, argstr
, A0
),
31 AROS_UFHA(ULONG
, argsize
, D0
),
32 struct ExecBase
*, SysBase
)
36 APTR DOSBase
= TaggedOpenLibrary(TAGGEDOPEN_DOS
);
39 struct CommandLineInterface
*cli
= Cli();
40 if (cli
&& cli
->cli_Interactive
) {
41 Printf("Only AROS m68k SetPatch is supported.\n");
43 CloseLibrary(DOSBase
);
52 static CONST_STRPTR
FindSegmentVER(BPTR Segment
, LONG
*length
)
57 CONST_STRPTR MyBuffer
;
59 CONST_STRPTR EndBuffer
;
60 CONST_STRPTR SegmentEnd
;
62 MySegment
= BADDR(Segment
);
63 MyBuffer
= (CONST_STRPTR
) (MySegment
+ sizeof(BPTR
));
64 BufferLen
= *(ULONG
*)(MySegment
- sizeof(ULONG
));
65 SegmentEnd
= (CONST_STRPTR
) (MySegment
+ (BufferLen
- 1) * 4);
66 EndBuffer
= SegmentEnd
- 5;
68 while (MyBuffer
< EndBuffer
)
70 if (MyBuffer
[0] == '$' &&
79 /* Required because some smartass could end his $VER: tag
80 * without '\0' in the segment to save space. - Piru
82 for (EndPtr
= MyBuffer
; EndPtr
< SegmentEnd
&& *EndPtr
; EndPtr
++)
84 if (EndPtr
- MyBuffer
)
86 *length
= EndPtr
- MyBuffer
;
94 Segment
=*(BPTR
*)MySegment
;
99 /* Check if SetPatch includes magic $VER: string */
100 static BSTR
LoadSeg_Check_SetPatch(BSTR segs
, struct DosLibrary
*DOSBase
)
103 CONST_STRPTR ver
= FindSegmentVER(segs
, &len
);
104 if (ver
&& len
>= 18 + 1) {
105 if (!memcmp (ver
+ 1, "SetPatch AROS-m68k", 18))
109 return CreateSegList(SetPatch_noop
);
112 AROS_UFH5(BPTR
, LoadSeg_Check
,
113 AROS_UFPA(UBYTE
*, name
, D1
),
114 AROS_UFPA(BPTR
, hunktable
, D2
),
115 AROS_UFPA(BPTR
, fh
, D3
),
116 AROS_UFPA(APTR
, LoadSeg_Original
, A0
),
117 AROS_UFPA(struct DosLibrary
*, DOSBase
, A6
))
123 /* name == NULL: Overlay LoadSeg */
125 return AROS_UFC4(BPTR
, LoadSeg_Overlay
,
126 AROS_UFCA(UBYTE
*, name
, D1
),
127 AROS_UFCA(BPTR
, hunktable
, D2
),
128 AROS_UFCA(BPTR
, fh
, D3
),
129 AROS_UFCA(struct DosLibrary
*, DOSBase
, A6
));
131 filename
= FilePart(name
);
132 /* On m68k, we map AOS SetPatch to a no-op seglist,
133 * due to the fact that OS 3.x and higher's SetPatch
134 * blindly patches without checking OS versions.
136 if (stricmp(filename
,"setpatch") == 0) {
137 BSTR segs
= AROS_UFC2(BPTR
, LoadSeg_Original
,
138 AROS_UFCA(UBYTE
*, name
, D1
),
139 AROS_UFCA(struct DosLibrary
*, DOSBase
, A6
));
142 return LoadSeg_Check_SetPatch (segs
, DOSBase
);
144 /* Do not allow Picasso96 to load, it is not
145 * compatible with built-in AROS RTG system */
146 if (stricmp(filename
,"rtg.library") == 0)
149 /* Call original LoadSeg function */
150 return AROS_UFC2(BPTR
, LoadSeg_Original
,
151 AROS_UFCA(UBYTE
*, name
, D1
),
152 AROS_UFCA(struct DosLibrary
*, DOSBase
, A6
));
157 extern void *BCPL_jsr
, *BCPL_rts
;
158 extern const ULONG BCPL_GlobVec
[(BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
) >> 2];
160 const UWORD highfunc
= 37, lowfunc
= 5, skipfuncs
= 2;
162 #define PATCHMEM_SIZE (10 * (highfunc - lowfunc + 1 - skipfuncs) * sizeof(UWORD) + 13 * sizeof(UWORD))
164 /* This patches two compatibility problems with badly written programs:
165 * 1) Return value in both D0 and D1.
166 * 2) 1.x original DOS functions can be called without DOSBase in A6.
167 * Both "features" are original BCPL DOS side-effects.
170 static int PatchDOS(struct DosLibrary
*dosbase
)
173 UWORD
*asmcall
, *asmmem
;
177 GlobVec
= AllocMem(BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
, MEMF_PUBLIC
);
181 CopyMem(BCPL_GlobVec
, GlobVec
, BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
);
182 GlobVec
+= BCPL_GlobVec_NegSize
;
183 *(APTR
*)(GlobVec
+ GV_DOSBase
) = dosbase
;
187 /* Use this private slot for the C-to-BCPL thunk */
188 __AROS_INITVEC(dosbase
, 4);
189 __AROS_SETVECADDR(dosbase
, 4, CallGlobVec
);
191 asmmem
= asmcall
= AllocMem(PATCHMEM_SIZE
, MEMF_PUBLIC
);
193 for (i
= lowfunc
; i
<= highfunc
; i
++)
195 if (i
== 24 || i
== 25)
197 func
= (IPTR
)__AROS_GETJUMPVEC(dosbase
, i
)->vec
;
198 __AROS_SETVECADDR(dosbase
, i
, asmcall
);
199 *asmcall
++ = 0x2f0e; // MOVE.L A6,-(SP)
200 *asmcall
++ = 0x4df9; // LEA dosbase,A6
201 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 16);
202 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 0);
203 *asmcall
++ = 0x4eb9; // JSR func
204 *asmcall
++ = (UWORD
)(func
>> 16);
205 *asmcall
++ = (UWORD
)(func
>> 0);
206 *asmcall
++ = 0x2C5F; // MOVE.L (SP)+,A6
207 *asmcall
++ = 0x2200; // MOVE.L D0,D1
208 *asmcall
++ = 0x4e75; // RTS
211 /* LoadSeg() patch */
212 func
= (IPTR
)__AROS_GETJUMPVEC(dosbase
, 25)->vec
;
213 __AROS_SETVECADDR(dosbase
, 25, asmcall
);
214 *asmcall
++ = 0x2f0e; // MOVE.L A6,-(SP)
215 *asmcall
++ = 0x4df9; // LEA dosbase,A6
216 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 16);
217 *asmcall
++ = (UWORD
)((ULONG
)dosbase
>> 0);
218 *asmcall
++ = 0x41f9; // LEA func,A0
219 *asmcall
++ = (UWORD
)(func
>> 16);
220 *asmcall
++ = (UWORD
)(func
>> 0);
221 *asmcall
++ = 0x4eb9; // jsr func
222 *asmcall
++ = (UWORD
)((ULONG
)LoadSeg_Check
>> 16);
223 *asmcall
++ = (UWORD
)((ULONG
)LoadSeg_Check
>> 0);
224 *asmcall
++ = 0x2C5F; // MOVE.L (SP)+,A6
225 *asmcall
++ = 0x2200; // MOVE.L D0,D1
226 *asmcall
++ = 0x4e75; // RTS
228 CacheClearE(asmmem
, PATCHMEM_SIZE
, CACRF_ClearI
|CACRF_ClearD
);
230 dosbase
->dl_A5
= (LONG
)&BCPL_jsr
;
231 dosbase
->dl_A6
= (LONG
)&BCPL_rts
;
232 dosbase
->dl_GV
= (APTR
)GlobVec
;
239 ADD2INITLIB(PatchDOS
, 0)
241 static int UnPatchDOS(struct DosLibrary
*dosbase
)
245 asmcall
= __AROS_GETJUMPVEC(dosbase
, lowfunc
)->vec
;
246 FreeMem(asmcall
, PATCHMEM_SIZE
);
247 FreeMem(dosbase
->dl_GV
- BCPL_GlobVec_NegSize
, BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
);
252 ADD2EXPUNGELIB(UnPatchDOS
, 0)