ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/rsrc_patches.cpp
Revision: 1.16
Committed: 2005-07-02T17:51:43Z (19 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.15: +6 -0 lines
Log Message:
Issue a SysError(dsOldSystem) if we are trying to use MacOS < 8.1.0 with a
NewWorld ROM. That may be 8.1.0 included but original iMac had a NewWorld
ROM compatible system.

Otherwise we will crash because the boot routine is trying to execute code
through unitialized descriptor that points to 0x13ff, which is obviously
wrong (and unaligned on word-boundaries for 68k code).

File Contents

# Content
1 /*
2 * rsrc_patches.cpp - Resource patches
3 *
4 * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "sysdeps.h"
26 #include "rsrc_patches.h"
27 #include "cpu_emulation.h"
28 #include "emul_op.h"
29 #include "xlowmem.h"
30 #include "macos_util.h"
31 #include "rom_patches.h"
32 #include "main.h"
33 #include "audio.h"
34 #include "audio_defs.h"
35 #include "thunks.h"
36
37 #define DEBUG 0
38 #include "debug.h"
39
40
41 // Sound input driver
42 static const uint8 sound_input_driver[] = { // .AppleSoundInput driver header
43 // Driver header
44 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x24, // Open() offset
46 0x00, 0x28, // Prime() offset
47 0x00, 0x2c, // Control() offset
48 0x00, 0x38, // Status() offset
49 0x00, 0x5e, // Close() offset
50 0x10, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x00, // ".AppleSoundInput"
51
52 // Open()
53 M68K_EMUL_OP_SOUNDIN_OPEN >> 8, M68K_EMUL_OP_SOUNDIN_OPEN & 0xff,
54 0x4e, 0x75, // rts
55
56 // Prime()
57 M68K_EMUL_OP_SOUNDIN_PRIME >> 8, M68K_EMUL_OP_SOUNDIN_PRIME & 0xff,
58 0x60, 0x0e, // bra IOReturn
59
60 // Control()
61 M68K_EMUL_OP_SOUNDIN_CONTROL >> 8, M68K_EMUL_OP_SOUNDIN_CONTROL & 0xff,
62 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
63 0x66, 0x04, // bne IOReturn
64 0x4e, 0x75, // rts
65
66 // Status()
67 M68K_EMUL_OP_SOUNDIN_STATUS >> 8, M68K_EMUL_OP_SOUNDIN_STATUS & 0xff,
68
69 // IOReturn
70 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
71 0x08, 0x01, 0x00, 0x09, // btst #9,d1
72 0x67, 0x0c, // beq 1
73 0x4a, 0x40, // tst.w d0
74 0x6f, 0x02, // ble 2
75 0x42, 0x40, // clr.w d0
76 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
77 0x4e, 0x75, // rts
78 0x4a, 0x40, //1 tst.w d0
79 0x6f, 0x04, // ble 3
80 0x42, 0x40, // clr.w d0
81 0x4e, 0x75, // rts
82 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
83 0x4e, 0x75, // rts
84
85 // Close()
86 M68K_EMUL_OP_SOUNDIN_CLOSE >> 8, M68K_EMUL_OP_SOUNDIN_CLOSE & 0xff,
87 0x4e, 0x75, // rts
88 };
89
90
91 /*
92 * Search resource for byte string, return offset (or 0)
93 */
94
95 static uint32 find_rsrc_data(const uint8 *rsrc, uint32 max, const uint8 *search, uint32 search_len, uint32 ofs = 0)
96 {
97 while (ofs < max - search_len) {
98 if (!memcmp(rsrc + ofs, search, search_len))
99 return ofs;
100 ofs++;
101 }
102 return 0;
103 }
104
105
106 /*
107 * Resource patches via vCheckLoad
108 */
109
110 // 680x0 code pattern matching helper
111 #define PM(N, V) (p[N] == htons(V))
112
113 void CheckLoad(uint32 type, int16 id, uint16 *p, uint32 size)
114 {
115 uint16 *p16;
116 uint32 base;
117 D(bug("vCheckLoad %c%c%c%c (%08x) ID %d, data %p, size %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, id, p, size));
118
119 // Don't modify resources in ROM
120 if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE))
121 return;
122
123 if (type == FOURCC('b','o','o','t') && id == 3) {
124 D(bug("boot 3 found\n"));
125 size >>= 1;
126 while (size--) {
127 if (PM(0,0x2e49)) {
128 // Set boot stack pointer (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6)
129 p[0] = htons(M68K_EMUL_OP_FIX_BOOTSTACK);
130 D(bug(" patch 1 applied\n"));
131 } else if (PM(0,0x4267) && PM(1,0x3f01) && PM(2,0x3f2a) && PM(3,0x0006) && PM(4,0x6100)) {
132 // Check when ntrb 17 is installed (for native Resource Manager patch) (7.5.3, 7.5.5)
133 p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH3);
134 D(bug(" patch 2 applied\n"));
135 } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x6100)) {
136 // Check when ntrb 17 is installed (for native Resource Manager patch) (7.6, 7.6.1, 8.0, 8.1)
137 p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH);
138 D(bug(" patch 3 applied\n"));
139 } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x61ff) && PM(8,0x245f)) {
140 // Check when ntrb 17 is installed (for native Resource Manager patch) (8.5, 8.6)
141 p[8] = htons(M68K_EMUL_OP_NTRB_17_PATCH);
142 D(bug(" patch 4 applied\n"));
143 } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x61ff) && PM(7,0x301f)) {
144 // Check when ntrb 17 is installed (for native Resource Manager patch) (9.0)
145 p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH4);
146 p[8] = htons(ntohs(p[8]) & 0xf0ff); // bra
147 D(bug(" patch 8 applied\n"));
148 } else if (PM(0,0x0c39) && PM(1,0x0001) && PM(2,0xf800) && PM(3,0x0008) && PM(4,0x6f00)) {
149 // Don't read from 0xf8000008 (8.5 with Zanzibar ROM, 8.6)
150 p[0] = htons(M68K_NOP);
151 p[1] = htons(M68K_NOP);
152 p[2] = htons(M68K_NOP);
153 p[3] = htons(M68K_NOP);
154 p[4] = htons(0x6000); // bra
155 D(bug(" patch 5 applied\n"));
156 } else if (PM(0,0x2f3c) && PM(1,0x6b72) && PM(2,0x6e6c) && PM(3,0x4267) && PM(4,0xa9a0) && PM(5,0x265f) && PM(6,0x200b) && PM(7,0x6700)) {
157 // Don't replace nanokernel ("krnl" resource) (8.6)
158 p[0] = htons(M68K_NOP);
159 p[1] = htons(M68K_NOP);
160 p[2] = htons(M68K_NOP);
161 p[3] = htons(M68K_NOP);
162 p[4] = htons(M68K_NOP);
163 p[7] = htons(0x6000); // bra
164 D(bug(" patch 6 applied\n"));
165 } else if (PM(0,0xa8fe) && PM(1,0x3038) && PM(2,0x017a) && PM(3,0x0c40) && PM(4,0x8805) && PM(5,0x6710)) {
166 // No SCSI (calls via 0x205c jump vector which is not initialized in NewWorld ROM 1.6) (8.6)
167 if (ROMType == ROMTYPE_NEWWORLD) {
168 p[5] = htons(0x6010); // bra
169 D(bug(" patch 7 applied\n"));
170 }
171 } else if (PM(0,0x2f3c) && PM(1,0x7665) && PM(2,0x7273) && PM(3,0x3f3c) && PM(4,0x0001) && PM(10,0x2041) && PM(11,0x2248) && PM(12,0x2050) && PM(20,0x7066) && PM(21,0xa9c9)) {
172 // Check when vers 1 is installed (for safe abort if MacOS < 8.1 is used with a NewWorld ROM)
173 p[10] = htons(M68K_EMUL_OP_CHECK_SYSV);
174 p[11] = htons(0x4a81); // tst.l d1
175 p[12] = htons(0x670e); // beq.s <SysError #dsOldSystem>
176 D(bug(" patch 9 applied\n"));
177 }
178 p++;
179 }
180
181 } else if (type == FOURCC('g','n','l','d') && id == 0) {
182 D(bug("gnld 0 found\n"));
183
184 // Patch native Resource Manager after ntrbs are installed (7.5.2)
185 static const uint8 dat[] = {0x4e, 0xba, 0x00, 0x9e, 0x3e, 0x00, 0x50, 0x4f, 0x67, 0x04};
186 base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat));
187 if (base) {
188 p16 = (uint16 *)((uintptr)p + base + 6);
189 *p16 = htons(M68K_EMUL_OP_NTRB_17_PATCH2);
190 D(bug(" patch 1 applied\n"));
191 }
192
193 } else if (type == FOURCC('p','t','c','h') && id == 156) {
194 D(bug("ptch 156 found\n"));
195 size >>= 1;
196 while (size--) {
197 if (PM(0,0x4e56) && PM(1,0xfffa) && PM(2,0x48e7) && PM(3,0x1f18) && PM(4,0x7800) && PM(5,0x267c) && PM(6,0x6900) && PM(7,0x0000)) {
198 // Don't call FE0A opcode (9.0)
199 p[0] = htons(0x7000); // moveq #0,d0
200 p[1] = htons(M68K_RTS);
201 D(bug(" patch 1 applied\n"));
202 break;
203 }
204 p++;
205 }
206
207 } else if (type == FOURCC('p','t','c','h') && id == 420) {
208 D(bug("ptch 420 found\n"));
209 size >>= 1;
210 while (size--) {
211 if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x303c) && PM(3,0x0100) && PM(4,0xc06e) && PM(5,0xfef6)) {
212 // Disable VM (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1)
213 p[1] = htons(M68K_NOP);
214 p[2] = htons(M68K_NOP);
215 p[3] = htons(M68K_NOP);
216 p[4] = htons(M68K_NOP);
217 p[5] = htons(M68K_NOP);
218 p[6] = htons(M68K_NOP);
219 p[7] = htons(M68K_NOP);
220 p[8] = htons(M68K_NOP);
221 p[9] = htons(M68K_NOP);
222 p[10] = htons(M68K_NOP);
223 p[11] = htons(M68K_NOP);
224 D(bug(" patch 1 applied\n"));
225 break;
226 } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfef6) && PM(5,0x323c) && PM(6,0x0100)) {
227 // Disable VM (8.0, 8.1)
228 p[8] = htons(M68K_NOP);
229 p[15] = htons(M68K_NOP);
230 D(bug(" patch 2 applied\n"));
231 break;
232 } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfecc) && PM(5,0x323c) && PM(6,0x0100)) {
233 // Disable VM (8.5, 8.6)
234 p[8] = htons(M68K_NOP);
235 p[15] = htons(M68K_NOP);
236 D(bug(" patch 3 applied\n"));
237 break;
238 }
239 p++;
240 }
241
242 } else if (type == FOURCC('g','p','c','h') && id == 16) {
243 D(bug("gpch 16 found\n"));
244 size >>= 1;
245 while (size--) {
246 if (PM(0,0x6700) && PM(13,0x7013) && PM(14,0xfe0a)) {
247 // Don't call FE0A in Shutdown Manager (7.6.1, 8.0, 8.1, 8.5)
248 p[0] = htons(0x6000);
249 D(bug(" patch 1 applied\n"));
250 break;
251 }
252 p++;
253 }
254
255 } else if (type == FOURCC('g','p','c','h') && id == 650) {
256 D(bug("gpch 650 found\n"));
257 size >>= 1;
258 while (size--) {
259 if (PM(0,0x6600) && PM(1,0x001a) && PM(2,0x2278) && PM(3,0x0134)) {
260 // We don't have SonyVars (7.5.2)
261 p[0] = htons(0x6000);
262 D(bug(" patch 1 applied\n"));
263 } else if (PM(0,0x6618) && PM(1,0x2278) && PM(2,0x0134)) {
264 // We don't have SonyVars (7.5.3)
265 p[-6] = htons(M68K_NOP);
266 p[-3] = htons(M68K_NOP);
267 p[0] = htons(0x6018);
268 D(bug(" patch 2 applied\n"));
269 } else if (PM(0,0x666e) && PM(1,0x2278) && PM(2,0x0134)) {
270 // We don't have SonyVars (7.5.5)
271 p[-6] = htons(M68K_NOP);
272 p[-3] = htons(M68K_NOP);
273 p[0] = htons(0x606e);
274 D(bug(" patch 3 applied\n"));
275 } else if (PM(0,0x6400) && PM(1,0x011c) && PM(2,0x2278) && PM(3,0x0134)) {
276 // We don't have SonyVars (7.6.1, 8.0, 8.1, 8.5, 8.6)
277 p[0] = htons(0x6000);
278 D(bug(" patch 4 applied\n"));
279 } else if (PM(0,0x6400) && PM(1,0x00e6) && PM(2,0x2278) && PM(3,0x0134)) {
280 // We don't have SonyVars (7.6)
281 p[0] = htons(0x6000);
282 D(bug(" patch 5 applied\n"));
283 }
284 p++;
285 }
286
287 } else if (type == FOURCC('g','p','c','h') && id == 655) {
288 D(bug("gpch 655 found\n"));
289 size >>= 1;
290 while (size--) {
291 if (PM(0,0x83a8) && PM(1,0x0024) && PM(2,0x4e71)) {
292 // Don't write to GC interrupt mask (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
293 p[0] = htons(M68K_NOP);
294 p[1] = htons(M68K_NOP);
295 D(bug(" patch 1 applied\n"));
296 } else if (PM(0,0x207c) && PM(1,0xf300) && PM(2,0x0034)) {
297 // Don't read PowerMac ID (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
298 p[0] = htons(0x303c); // move.w #id,d0
299 p[1] = htons(0x3020);
300 p[2] = htons(M68K_RTS);
301 D(bug(" patch 2 applied\n"));
302 } else if (PM(0,0x13fc) && PM(1,0x0081) && PM(2,0xf130) && PM(3,0xa030)) {
303 // Don't write to hardware (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
304 p[0] = htons(M68K_NOP);
305 p[1] = htons(M68K_NOP);
306 p[2] = htons(M68K_NOP);
307 p[3] = htons(M68K_NOP);
308 D(bug(" patch 3 applied\n"));
309 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf800) && PM(4,0x0000)) {
310 // OpenFirmare? (7.6.1, 8.0, 8.1 with Zanzibar ROM)
311 p[0] = htons(M68K_RTS);
312 D(bug(" patch 4 applied\n"));
313 } else if (PM(0,0x4e56) && PM(1,0xfffc) && PM(2,0x48e7) && PM(3,0x0300) && PM(4,0x598f) && PM(5,0x2eb8) && PM(6,0x01dc)) {
314 // Don't write to SCC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
315 p[0] = htons(M68K_RTS);
316 D(bug(" patch 5 applied\n"));
317 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf300) && PM(4,0x0034)) {
318 // Don't write to GC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
319 p[0] = htons(M68K_RTS);
320 D(bug(" patch 6 applied\n"));
321 } else if (PM(0,0x40e7) && PM(1,0x007c) && PM(2,0x0700) && PM(3,0x48e7) && PM(4,0x00c0) && PM(5,0x2078) && PM(6,0x0dd8) && PM(7,0xd1e8) && PM(8,0x0044) && PM(9,0x8005) && PM(11,0x93c8) && PM(12,0x2149) && PM(13,0x0024)) {
322 // Don't replace NVRAM routines (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
323 p[0] = htons(M68K_RTS);
324 D(bug(" patch 7 applied\n"));
325 } else if (PM(0,0x207c) && PM(1,0x50f1) && PM(2,0xa101) && (PM(3,0x08d0) || PM(3,0x0890))) {
326 // Don't write to 0x50f1a101 (8.1 with Zanzibar ROM)
327 p[3] = htons(M68K_NOP);
328 p[4] = htons(M68K_NOP);
329 D(bug(" patch 8 applied\n"));
330 }
331 p++;
332 }
333
334 } else if (type == FOURCC('g','p','c','h') && id == 750) {
335 D(bug("gpch 750 found\n"));
336 size >>= 1;
337 while (size--) {
338 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
339 // Don't read from 0xf3019100 (MACE ENET) (7.6, 7.6.1, 8.0, 8.1)
340 p[2] = htons(M68K_NOP);
341 p[3] = htons(M68K_NOP);
342 p[4] = htons(0x6026);
343 D(bug(" patch 1 applied\n"));
344 } else if (PM(0,0x41e8) && PM(1,0x0374) && PM(2,0xfc1e)) {
345 // Don't call FC1E opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6)
346 p[2] = htons(M68K_NOP);
347 D(bug(" patch 2 applied\n"));
348 } else if (PM(0,0x700a) && PM(1,0xfe0a)) {
349 // Don't call FE0A opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6)
350 p[1] = htons(0x7000);
351 D(bug(" patch 3 applied\n"));
352 } else if (PM(0,0x6c00) && PM(1,0x016a) && PM(2,0x2278) && PM(3,0x0134)) {
353 // We don't have SonyVars (8.6)
354 p[-4] = htons(0x21fc); // move.l $40810000,($0000)
355 p[-3] = htons(0x4081);
356 p[-2] = htons(0x0000);
357 p[-1] = htons(0x0000);
358 p[0] = htons(0x6000);
359 D(bug(" patch 4 applied\n"));
360 }
361 p++;
362 }
363
364 } else if (type == FOURCC('g','p','c','h') && id == 999) {
365 D(bug("gpch 999 found\n"));
366 size >>= 1;
367 while (size--) {
368 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
369 // Don't read from 0xf3019100 (MACE ENET) (8.5, 8.6)
370 p[2] = htons(M68K_NOP);
371 p[3] = htons(M68K_NOP);
372 p[4] = htons(0x6026);
373 D(bug(" patch 1 applied\n"));
374 }
375 p++;
376 }
377
378 } else if (type == FOURCC('g','p','c','h') && id == 3000) {
379 D(bug("gpch 3000 found\n"));
380 size >>= 1;
381 while (size--) {
382 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
383 // Don't read from 0xf3019100 (MACE ENET) (8.1 with NewWorld ROM)
384 p[2] = htons(M68K_NOP);
385 p[3] = htons(M68K_NOP);
386 p[4] = htons(0x6026);
387 D(bug(" patch 1 applied\n"));
388 }
389 p++;
390 }
391
392 } else if (type == FOURCC('l','t','l','k') && id == 0) {
393 D(bug("ltlk 0 found\n"));
394 #if 1
395 size >>= 1;
396 while (size--) {
397 if (PM(0,0xc2fc) && PM(1,0x0fa0) && PM(2,0x82c5)) {
398 // Prevent division by 0 in speed test (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
399 p[2] = htons(0x7200);
400 WriteMacInt32(0x1d8, 0x2c00);
401 WriteMacInt32(0x1dc, 0x2c00);
402 D(bug(" patch 1 applied\n"));
403 } else if (PM(0,0x1418) && PM(1,0x84c1)) {
404 // Prevent division by 0 (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
405 p[1] = htons(0x7400);
406 D(bug(" patch 2 applied\n"));
407 } else if (PM(0,0x2678) && PM(1,0x01dc) && PM(2,0x3018) && PM(3,0x6708) && PM(4,0x1680) && PM(5,0xe058) && PM(6,0x1680)) {
408 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
409 p[4] = htons(M68K_NOP);
410 p[6] = htons(M68K_NOP);
411 D(bug(" patch 3 applied\n"));
412 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0006) && PM(4,0x4e71) && PM(5,0x1292)) {
413 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
414 p[2] = htons(M68K_NOP);
415 p[3] = htons(M68K_NOP);
416 p[5] = htons(M68K_NOP);
417 D(bug(" patch 4 applied\n"));
418 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0003) && PM(4,0x4e71) && PM(5,0x1281)) {
419 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
420 p[2] = htons(M68K_NOP);
421 p[3] = htons(M68K_NOP);
422 p[5] = htons(M68K_NOP);
423 D(bug(" patch 5 applied\n"));
424 } else if (PM(0,0x0811) && PM(1,0x0000) && PM(2,0x51c8) && PM(3,0xfffa)) {
425 // Don't test SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
426 p[0] = htons(M68K_NOP);
427 p[1] = htons(M68K_NOP);
428 D(bug(" patch 6 applied\n"));
429 } else if (PM(0,0x4a2a) && PM(1,0x063e) && PM(2,0x66fa)) {
430 // Don't wait for SCC (7.5.2, 7.5.3, 7.5.5)
431 p[2] = htons(M68K_NOP);
432 D(bug(" patch 7 applied\n"));
433 } else if (PM(0,0x4a2a) && PM(1,0x03a6) && PM(2,0x66fa)) {
434 // Don't wait for SCC (7.6, 7.6.1, 8.0, 8.1)
435 p[2] = htons(M68K_NOP);
436 D(bug(" patch 8 applied\n"));
437 }
438 p++;
439 }
440 #else
441 // Disable LocalTalk
442 p[0] = htons(M68K_JMP_A0);
443 p[1] = htons(0x7000); // moveq #0,d0
444 p[2] = htons(M68K_RTS);
445 D(bug(" patch 1 applied\n"));
446 #endif
447
448 } else if (type == FOURCC('n','s','r','d') && id == 1) {
449 D(bug("nsrd 1 found\n"));
450 if (p[(0x378 + 0x570) >> 1] == htons(0x7c08) && p[(0x37a + 0x570) >> 1] == htons(0x02a6)) {
451 // Don't overwrite our serial drivers (8.0, 8.1)
452 p[(0x378 + 0x570) >> 1] = htons(0x4e80); // blr
453 p[(0x37a + 0x570) >> 1] = htons(0x0020);
454 D(bug(" patch 1 applied\n"));
455 } else if (p[(0x378 + 0x6c0) >> 1] == htons(0x7c08) && p[(0x37a + 0x6c0) >> 1] == htons(0x02a6)) {
456 // Don't overwrite our serial drivers (8.5, 8.6)
457 p[(0x378 + 0x6c0) >> 1] = htons(0x4e80); // blr
458 p[(0x37a + 0x6c0) >> 1] = htons(0x0020);
459 D(bug(" patch 2 applied\n"));
460 } else if (p[(0x374 + 0x510) >> 1] == htons(0x7c08) && p[(0x376 + 0x510) >> 1] == htons(0x02a6)) {
461 // Don't overwrite our serial drivers (9.0)
462 p[(0x374 + 0x510) >> 1] = htons(0x4e80); // blr
463 p[(0x376 + 0x510) >> 1] = htons(0x0020);
464 D(bug(" patch 3 applied\n"));
465 }
466
467 } else if (type == FOURCC('c','i','t','t') && id == 45) {
468 D(bug("citt 45 found\n"));
469 size >>= 1;
470 while (size--) {
471 if (PM(0,0x203c) && PM(1,0x0100) && PM(2,0x0000) && PM(3,0xc0ae) && PM(4,0xfffc)) {
472 // Don't replace SCSI Manager (8.1, 8.5, 8.6)
473 p[5] = htons((ntohs(p[5]) & 0xff) | 0x6000); // beq
474 D(bug(" patch 1 applied\n"));
475 break;
476 }
477 p++;
478 }
479
480 } else if (type == FOURCC('t','h','n','g')) {
481 // Collect info about used audio sifters
482 uint32 thing = Host2MacAddr((uint8 *)p);
483 uint32 c_type = ReadMacInt32(thing);
484 uint32 sub_type = ReadMacInt32(thing + 4);
485 if (c_type == FOURCC('s','d','e','v') && sub_type == FOURCC('s','i','n','g')) {
486 WriteMacInt32(thing + 4, FOURCC('a','w','g','c'));
487 D(bug("thng %d, type %c%c%c%c (%08x), sub type %c%c%c%c (%08x), data %p\n", id, c_type >> 24, (c_type >> 16) & 0xff, (c_type >> 8) & 0xff, c_type & 0xff, c_type, sub_type >> 24, (sub_type >> 16) & 0xff, (sub_type >> 8) & 0xff, sub_type & 0xff, sub_type, p));
488 AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID));
489 if (ReadMacInt32(thing + componentPFCount))
490 AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID));
491 }
492
493 } else if (type == FOURCC('s','i','f','t') || type == FOURCC('n','i','f','t')) {
494 // Patch audio sifters
495 if (FindSifter(type, id)) {
496 D(bug("sifter found\n"));
497 p[0] = htons(0x4e56); p[1] = htons(0x0000); // link a6,#0
498 p[2] = htons(0x48e7); p[3] = htons(0x8018); // movem.l d0/a3-a4,-(a7)
499 p[4] = htons(0x266e); p[5] = htons(0x000c); // movea.l $c(a6),a3
500 p[6] = htons(0x286e); p[7] = htons(0x0008); // movea.l $8(a6),a4
501 p[8] = htons(M68K_EMUL_OP_AUDIO_DISPATCH);
502 p[9] = htons(0x2d40); p[10] = htons(0x0010); // move.l d0,$10(a6)
503 p[11] = htons(0x4cdf); p[12] = htons(0x1801); // movem.l (a7)+,d0/a3-a4
504 p[13] = htons(0x4e5e); // unlk a6
505 p[14] = htons(0x4e74); p[15] = htons(0x0008); // rtd #8
506 D(bug(" patch applied\n"));
507 }
508
509 } else if (type == FOURCC('D','R','V','R') && (id == -16501 || id == -16500)) {
510 D(bug("DRVR -16501/-16500 found\n"));
511 // Install sound input driver
512 memcpy(p, sound_input_driver, sizeof(sound_input_driver));
513 D(bug(" patch 1 applied\n"));
514
515 } else if (type == FOURCC('I','N','I','T') && id == 1 && size == (2416 >> 1)) {
516 D(bug("INIT 1 (size 2416) found\n"));
517 size >>= 1;
518 while (size--) {
519 if (PM(0,0x247c) && PM(1,0xf301) && PM(2,0x9000)) {
520 // Prevent "MacOS Licensing Extension" from accessing hardware (7.6)
521 p[22] = htons(0x6028);
522 D(bug(" patch 1 applied\n"));
523 break;
524 }
525 p++;
526 }
527
528 } else if (type == FOURCC('s','c','o','d') && id == -16465) {
529 D(bug("scod -16465 found\n"));
530
531 // Don't crash in Process Manager on reset/shutdown (8.6)
532 static const uint8 dat[] = {0x4e, 0x56, 0x00, 0x00, 0x48, 0xe7, 0x03, 0x18, 0x2c, 0x2e, 0x00, 0x10};
533 base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat));
534 if (base) {
535 p16 = (uint16 *)((uintptr)p + base);
536 p16[0] = htons(0x7000); // moveq #0,d0
537 p16[1] = htons(M68K_RTS);
538 D(bug(" patch 1 applied\n"));
539 }
540
541 } else if (type == FOURCC('N','O','b','j') && id == 100) {
542 D(bug("NObj 100 found\n"));
543
544 // Don't access VIA registers in MacBench 5.0
545 static const uint8 dat1[] = {0x7c, 0x08, 0x02, 0xa6, 0xbf, 0x01, 0xff, 0xe0, 0x90, 0x01, 0x00, 0x08};
546 base = find_rsrc_data((uint8 *)p, size, dat1, sizeof(dat1));
547 if (base) {
548 p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0
549 p[(base + 0x02) >> 1] = htons(0x0000);
550 p[(base + 0x04) >> 1] = htons(0x4e80); // blr
551 p[(base + 0x06) >> 1] = htons(0x0020);
552 D(bug(" patch 1 applied\n"));
553 }
554 static const uint8 dat2[] = {0x7c, 0x6c, 0x1b, 0x78, 0x7c, 0x8b, 0x23, 0x78, 0x38, 0xc0, 0x3f, 0xfd};
555 base = find_rsrc_data((uint8 *)p, size, dat2, sizeof(dat2));
556 if (base) {
557 p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0
558 p[(base + 0x02) >> 1] = htons(0x0000);
559 p[(base + 0x04) >> 1] = htons(0x4e80); // blr
560 p[(base + 0x06) >> 1] = htons(0x0020);
561 D(bug(" patch 2 applied\n"));
562 }
563
564 } else if (type == FOURCC('C','O','D','E') && id == 27 && size == 25024) {
565 D(bug("CODE 27 found [Apple Personal Diagnostics]\n"));
566
567 // Don't access FCBs directly in Apple Personal Diagnostics (MacOS 9)
568 // FIXME: this should not be called in the first place, use UTResolveFCB?
569 static const uint8 dat[] = {0x2d, 0x78, 0x03, 0x4e, 0xff, 0xf8, 0x20, 0x6e, 0xff, 0xf8};
570 base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat));
571 if (base
572 && ReadMacInt16(0x3f6) == 4 /* FSFCBLen */
573 && p[(base + 0x1a) >> 1] == htons(0x605e)
574 && p[(base + 0x80) >> 1] == htons(0x7000))
575 {
576 p[(base + 0x1a) >> 1] = htons(0x6064);
577 D(bug(" patch1 applied\n"));
578 }
579 }
580 }
581
582
583 /*
584 * Native Resource Manager patches
585 */
586
587 #ifdef __BEOS__
588 static
589 #else
590 extern "C"
591 #endif
592 void check_load_invoc(uint32 type, int16 id, uint32 h)
593 {
594 if (h == 0)
595 return;
596 uint32 p = ReadMacInt32(h);
597 if (p == 0)
598 return;
599 uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff;
600
601 CheckLoad(type, id, (uint16 *)Mac2HostAddr(p), size);
602 }
603
604 #ifdef __BEOS__
605 static asm void **get_resource(register uint32 type, register int16 id)
606 {
607 // Create stack frame
608 mflr r0
609 stw r0,8(r1)
610 stwu r1,-(56+12)(r1)
611
612 // Save type/ID
613 stw r3,56(r1)
614 stw r4,56+4(r1)
615
616 // Call old routine
617 lwz r0,XLM_GET_RESOURCE
618 lwz r2,XLM_RES_LIB_TOC
619 mtctr r0
620 bctrl
621 lwz r2,XLM_TOC // Get TOC
622 stw r3,56+8(r1) // Save handle
623
624 // Call CheckLoad
625 lwz r3,56(r1)
626 lwz r4,56+4(r1)
627 lwz r5,56+8(r1)
628 bl check_load_invoc
629 lwz r3,56+8(r1) // Restore handle
630
631 // Return to caller
632 lwz r0,56+12+8(r1)
633 mtlr r0
634 addi r1,r1,56+12
635 blr
636 }
637
638 static asm void **get_1_resource(register uint32 type, register int16 id)
639 {
640 // Create stack frame
641 mflr r0
642 stw r0,8(r1)
643 stwu r1,-(56+12)(r1)
644
645 // Save type/ID
646 stw r3,56(r1)
647 stw r4,56+4(r1)
648
649 // Call old routine
650 lwz r0,XLM_GET_1_RESOURCE
651 lwz r2,XLM_RES_LIB_TOC
652 mtctr r0
653 bctrl
654 lwz r2,XLM_TOC // Get TOC
655 stw r3,56+8(r1) // Save handle
656
657 // Call CheckLoad
658 lwz r3,56(r1)
659 lwz r4,56+4(r1)
660 lwz r5,56+8(r1)
661 bl check_load_invoc
662 lwz r3,56+8(r1) // Restore handle
663
664 // Return to caller
665 lwz r0,56+12+8(r1)
666 mtlr r0
667 addi r1,r1,56+12
668 blr
669 }
670
671 static asm void **get_ind_resource(register uint32 type, register int16 index)
672 {
673 // Create stack frame
674 mflr r0
675 stw r0,8(r1)
676 stwu r1,-(56+12)(r1)
677
678 // Save type/index
679 stw r3,56(r1)
680 stw r4,56+4(r1)
681
682 // Call old routine
683 lwz r0,XLM_GET_IND_RESOURCE
684 lwz r2,XLM_RES_LIB_TOC
685 mtctr r0
686 bctrl
687 lwz r2,XLM_TOC // Get TOC
688 stw r3,56+8(r1) // Save handle
689
690 // Call CheckLoad
691 lwz r3,56(r1)
692 lwz r4,56+4(r1)
693 lwz r5,56+8(r1)
694 bl check_load_invoc
695 lwz r3,56+8(r1) // Restore handle
696
697 // Return to caller
698 lwz r0,56+12+8(r1)
699 mtlr r0
700 addi r1,r1,56+12
701 blr
702 }
703
704 static asm void **get_1_ind_resource(register uint32 type, register int16 index)
705 {
706 // Create stack frame
707 mflr r0
708 stw r0,8(r1)
709 stwu r1,-(56+12)(r1)
710
711 // Save type/index
712 stw r3,56(r1)
713 stw r4,56+4(r1)
714
715 // Call old routine
716 lwz r0,XLM_GET_1_IND_RESOURCE
717 lwz r2,XLM_RES_LIB_TOC
718 mtctr r0
719 bctrl
720 lwz r2,XLM_TOC // Get TOC
721 stw r3,56+8(r1) // Save handle
722
723 // Call CheckLoad
724 lwz r3,56(r1)
725 lwz r4,56+4(r1)
726 lwz r5,56+8(r1)
727 bl check_load_invoc
728 lwz r3,56+8(r1) // Restore handle
729
730 // Return to caller
731 lwz r0,56+12+8(r1)
732 mtlr r0
733 addi r1,r1,56+12
734 blr
735 }
736
737 static asm void **r_get_resource(register uint32 type, register int16 id)
738 {
739 // Create stack frame
740 mflr r0
741 stw r0,8(r1)
742 stwu r1,-(56+12)(r1)
743
744 // Save type/ID
745 stw r3,56(r1)
746 stw r4,56+4(r1)
747
748 // Call old routine
749 lwz r0,XLM_R_GET_RESOURCE
750 lwz r2,XLM_RES_LIB_TOC
751 mtctr r0
752 bctrl
753 lwz r2,XLM_TOC // Get TOC
754 stw r3,56+8(r1) // Save handle
755
756 // Call CheckLoad
757 lwz r3,56(r1)
758 lwz r4,56+4(r1)
759 lwz r5,56+8(r1)
760 bl check_load_invoc
761 lwz r3,56+8(r1) // Restore handle
762
763 // Return to caller
764 lwz r0,56+12+8(r1)
765 mtlr r0
766 addi r1,r1,56+12
767 blr
768 }
769 #else
770 // Routines in asm_linux.S
771 extern "C" void get_resource(void);
772 extern "C" void get_1_resource(void);
773 extern "C" void get_ind_resource(void);
774 extern "C" void get_1_ind_resource(void);
775 extern "C" void r_get_resource(void);
776 #endif
777
778 void PatchNativeResourceManager(void)
779 {
780 D(bug("PatchNativeResourceManager\n"));
781
782 // Patch native GetResource()
783 uint32 upp = ReadMacInt32(0x1480);
784 if ((upp & 0xffc00000) == ROM_BASE)
785 return;
786 uint32 tvec = ReadMacInt32(upp + 5 * 4);
787 D(bug(" GetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
788 WriteMacInt32(XLM_RES_LIB_TOC, ReadMacInt32(tvec + 4));
789 WriteMacInt32(XLM_GET_RESOURCE, ReadMacInt32(tvec));
790 #if EMULATED_PPC
791 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_RESOURCE));
792 #else
793 #ifdef __BEOS__
794 uint32 *tvec2 = (uint32 *)get_resource;
795 WriteMacInt32(tvec, tvec2[0]);
796 WriteMacInt32(tvec + 4, tvec2[1]);
797 #else
798 WriteMacInt32(tvec, (uint32)get_resource);
799 #endif
800 #endif
801
802 // Patch native Get1Resource()
803 upp = ReadMacInt32(0x0e7c);
804 tvec = ReadMacInt32(upp + 5 * 4);
805 D(bug(" Get1Resource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
806 WriteMacInt32(XLM_GET_1_RESOURCE, ReadMacInt32(tvec));
807 #if EMULATED_PPC
808 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_RESOURCE));
809 #else
810 #ifdef __BEOS__
811 tvec2 = (uint32 *)get_1_resource;
812 WriteMacInt32(tvec, tvec2[0]);
813 WriteMacInt32(tvec + 4, tvec2[1]);
814 #else
815 WriteMacInt32(tvec, (uint32)get_1_resource);
816 #endif
817 #endif
818
819 // Patch native GetIndResource()
820 upp = ReadMacInt32(0x1474);
821 tvec = ReadMacInt32(upp + 5 * 4);
822 D(bug(" GetIndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
823 WriteMacInt32(XLM_GET_IND_RESOURCE, ReadMacInt32(tvec));
824 #if EMULATED_PPC
825 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_IND_RESOURCE));
826 #else
827 #ifdef __BEOS__
828 tvec2 = (uint32 *)get_ind_resource;
829 WriteMacInt32(tvec, tvec2[0]);
830 WriteMacInt32(tvec + 4, tvec2[1]);
831 #else
832 WriteMacInt32(tvec, (uint32)get_ind_resource);
833 #endif
834 #endif
835
836 // Patch native Get1IndResource()
837 upp = ReadMacInt32(0x0e38);
838 tvec = ReadMacInt32(upp + 5 * 4);
839 D(bug(" Get1IndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
840 WriteMacInt32(XLM_GET_1_IND_RESOURCE, ReadMacInt32(tvec));
841 #if EMULATED_PPC
842 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_IND_RESOURCE));
843 #else
844 #ifdef __BEOS__
845 tvec2 = (uint32 *)get_1_ind_resource;
846 WriteMacInt32(tvec, tvec2[0]);
847 WriteMacInt32(tvec + 4, tvec2[1]);
848 #else
849 WriteMacInt32(tvec, (uint32)get_1_ind_resource);
850 #endif
851 #endif
852
853 // Patch native RGetResource()
854 upp = ReadMacInt32(0x0e30);
855 tvec = ReadMacInt32(upp + 5 * 4);
856 D(bug(" RGetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
857 WriteMacInt32(XLM_R_GET_RESOURCE, ReadMacInt32(tvec));
858 #if EMULATED_PPC
859 WriteMacInt32(tvec, NativeFunction(NATIVE_R_GET_RESOURCE));
860 #else
861 #ifdef __BEOS__
862 tvec2 = (uint32 *)r_get_resource;
863 WriteMacInt32(tvec, tvec2[0]);
864 WriteMacInt32(tvec + 4, tvec2[1]);
865 #else
866 WriteMacInt32(tvec, (uint32)r_get_resource);
867 #endif
868 #endif
869 }