ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/rsrc_patches.cpp
Revision: 1.24
Committed: 2009-08-18T18:26:10Z (15 years, 3 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.23: +1 -1 lines
Log Message:
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.


Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".

SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.

The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.

On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.


Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.

This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.

Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.

A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.


Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.

The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.

This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.


Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.

2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.

3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.

4. Changed and rearranged the allocation of RAM and ROM areas.

Before it worked like this:

  - Allocate ROM area
  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0, allocate at fixed address

We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:

  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0
      if REAL addressing
         allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
      else (direct addressing)
         allocate RAM at fixed address
  - If ROM hasn't been allocated yet, allocate at fixed address

5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.

6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.

7. Change subsequent code from using constant ROM_BASE to variable ROMBase.


Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.

ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.

ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.

main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.

cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.

user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.

File Contents

# Content
1 /*
2 * rsrc_patches.cpp - Resource patches
3 *
4 * SheepShaver (C) 1997-2008 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,0x51c9) && PM(2,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, 9.0)
129 p[2] = 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 5 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, 9.0)
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 6 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, 9.0)
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 7 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 8 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, 9.0)
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,0x6660) && PM(1,0x2278) && PM(2,0x0134)) {
270 // We don't have SonyVars (7.5.3 Revision 2.2)
271 p[-6] = htons(M68K_NOP);
272 p[-3] = htons(M68K_NOP);
273 p[0] = htons(0x6060);
274 D(bug(" patch 3 applied\n"));
275 } else if (PM(0,0x666e) && PM(1,0x2278) && PM(2,0x0134)) {
276 // We don't have SonyVars (7.5.5)
277 p[-6] = htons(M68K_NOP);
278 p[-3] = htons(M68K_NOP);
279 p[0] = htons(0x606e);
280 D(bug(" patch 4 applied\n"));
281 } else if (PM(0,0x6400) && PM(1,0x011c) && PM(2,0x2278) && PM(3,0x0134)) {
282 // We don't have SonyVars (7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0)
283 p[0] = htons(0x6000);
284 D(bug(" patch 5 applied\n"));
285 } else if (PM(0,0x6400) && PM(1,0x00e6) && PM(2,0x2278) && PM(3,0x0134)) {
286 // We don't have SonyVars (7.6)
287 p[0] = htons(0x6000);
288 D(bug(" patch 6 applied\n"));
289 }
290 p++;
291 }
292
293 } else if (type == FOURCC('g','p','c','h') && id == 655) {
294 D(bug("gpch 655 found\n"));
295 size >>= 1;
296 while (size--) {
297 if (PM(0,0x83a8) && PM(1,0x0024) && PM(2,0x4e71)) {
298 // Don't write to GC interrupt mask (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
299 p[0] = htons(M68K_NOP);
300 p[1] = htons(M68K_NOP);
301 D(bug(" patch 1 applied\n"));
302 } else if (PM(0,0x207c) && PM(1,0xf300) && PM(2,0x0034)) {
303 // Don't read PowerMac ID (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
304 p[0] = htons(0x303c); // move.w #id,d0
305 p[1] = htons(0x3020);
306 p[2] = htons(M68K_RTS);
307 D(bug(" patch 2 applied\n"));
308 } else if (PM(0,0x13fc) && PM(1,0x0081) && PM(2,0xf130) && PM(3,0xa030)) {
309 // Don't write to hardware (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
310 p[0] = htons(M68K_NOP);
311 p[1] = htons(M68K_NOP);
312 p[2] = htons(M68K_NOP);
313 p[3] = htons(M68K_NOP);
314 D(bug(" patch 3 applied\n"));
315 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf800) && PM(4,0x0000)) {
316 // OpenFirmare? (7.6.1, 8.0, 8.1 with Zanzibar ROM)
317 p[0] = htons(M68K_RTS);
318 D(bug(" patch 4 applied\n"));
319 } else if (PM(0,0x4e56) && PM(1,0xfffc) && PM(2,0x48e7) && PM(3,0x0300) && PM(4,0x598f) && PM(5,0x2eb8) && PM(6,0x01dc)) {
320 // Don't write to SCC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
321 p[0] = htons(M68K_RTS);
322 D(bug(" patch 5 applied\n"));
323 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf300) && PM(4,0x0034)) {
324 // Don't write to GC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
325 p[0] = htons(M68K_RTS);
326 D(bug(" patch 6 applied\n"));
327 } 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)) {
328 // Don't replace NVRAM routines (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
329 p[0] = htons(M68K_RTS);
330 D(bug(" patch 7 applied\n"));
331 } else if (PM(0,0x207c) && PM(1,0x50f1) && PM(2,0xa101) && (PM(3,0x08d0) || PM(3,0x0890))) {
332 // Don't write to 0x50f1a101 (8.1 with Zanzibar ROM)
333 p[3] = htons(M68K_NOP);
334 p[4] = htons(M68K_NOP);
335 D(bug(" patch 8 applied\n"));
336 }
337 p++;
338 }
339
340 } else if (type == FOURCC('g','p','c','h') && id == 750) {
341 D(bug("gpch 750 found\n"));
342 size >>= 1;
343 while (size--) {
344 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
345 // Don't read from 0xf3019100 (MACE ENET) (7.6, 7.6.1, 8.0, 8.1)
346 p[2] = htons(M68K_NOP);
347 p[3] = htons(M68K_NOP);
348 p[4] = htons(0x6026);
349 D(bug(" patch 1 applied\n"));
350 } else if (PM(0,0x41e8) && PM(1,0x0374) && PM(2,0xfc1e)) {
351 // Don't call FC1E opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6)
352 p[2] = htons(M68K_NOP);
353 D(bug(" patch 2 applied\n"));
354 } else if (PM(0,0x700a) && PM(1,0xfe0a)) {
355 // Don't call FE0A opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0)
356 p[1] = htons(0x2008); // move.l a0,d0
357 D(bug(" patch 3 applied\n"));
358 } else if (PM(0,0x6c00) && PM(1,0x016a) && PM(2,0x2278) && PM(3,0x0134)) {
359 // We don't have SonyVars (8.6)
360 p[-4] = htons(0x21fc); // move.l $40810000,($0000)
361 p[-3] = htons(0x4081);
362 p[-2] = htons(0x0000);
363 p[-1] = htons(0x0000);
364 p[0] = htons(0x6000);
365 D(bug(" patch 4 applied\n"));
366 }
367 p++;
368 }
369
370 } else if (type == FOURCC('g','p','c','h') && id == 999) {
371 D(bug("gpch 999 found\n"));
372 size >>= 1;
373 while (size--) {
374 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
375 // Don't read from 0xf3019100 (MACE ENET) (8.5, 8.6)
376 p[2] = htons(M68K_NOP);
377 p[3] = htons(M68K_NOP);
378 p[4] = htons(0x6026);
379 D(bug(" patch 1 applied\n"));
380 }
381 p++;
382 }
383
384 } else if (type == FOURCC('g','p','c','h') && id == 3000) {
385 D(bug("gpch 3000 found\n"));
386 size >>= 1;
387 while (size--) {
388 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
389 // Don't read from 0xf3019100 (MACE ENET) (8.1 with NewWorld ROM)
390 p[2] = htons(M68K_NOP);
391 p[3] = htons(M68K_NOP);
392 p[4] = htons(0x6026);
393 D(bug(" patch 1 applied\n"));
394 }
395 p++;
396 }
397
398 } else if (type == FOURCC('l','t','l','k') && id == 0) {
399 D(bug("ltlk 0 found\n"));
400 #if 1
401 size >>= 1;
402 while (size--) {
403 if (PM(0,0xc2fc) && PM(1,0x0fa0) && PM(2,0x82c5)) {
404 // 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)
405 p[2] = htons(0x7200);
406 WriteMacInt32(0x1d8, 0x2c00);
407 WriteMacInt32(0x1dc, 0x2c00);
408 D(bug(" patch 1 applied\n"));
409 } else if (PM(0,0x1418) && PM(1,0x84c1)) {
410 // Prevent division by 0 (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
411 p[1] = htons(0x7400);
412 D(bug(" patch 2 applied\n"));
413 } else if (PM(0,0x2678) && PM(1,0x01dc) && PM(2,0x3018) && PM(3,0x6708) && PM(4,0x1680) && PM(5,0xe058) && PM(6,0x1680)) {
414 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
415 p[4] = htons(M68K_NOP);
416 p[6] = htons(M68K_NOP);
417 D(bug(" patch 3 applied\n"));
418 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0006) && PM(4,0x4e71) && PM(5,0x1292)) {
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 4 applied\n"));
424 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0003) && PM(4,0x4e71) && PM(5,0x1281)) {
425 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
426 p[2] = htons(M68K_NOP);
427 p[3] = htons(M68K_NOP);
428 p[5] = htons(M68K_NOP);
429 D(bug(" patch 5 applied\n"));
430 } else if (PM(0,0x0811) && PM(1,0x0000) && PM(2,0x51c8) && PM(3,0xfffa)) {
431 // Don't test SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
432 p[0] = htons(M68K_NOP);
433 p[1] = htons(M68K_NOP);
434 D(bug(" patch 6 applied\n"));
435 } else if (PM(0,0x4a2a) && PM(1,0x063e) && PM(2,0x66fa)) {
436 // Don't wait for SCC (7.5.2, 7.5.3, 7.5.5)
437 p[2] = htons(M68K_NOP);
438 D(bug(" patch 7 applied\n"));
439 } else if (PM(0,0x4a2a) && PM(1,0x03a6) && PM(2,0x66fa)) {
440 // Don't wait for SCC (7.6, 7.6.1, 8.0, 8.1)
441 p[2] = htons(M68K_NOP);
442 D(bug(" patch 8 applied\n"));
443 }
444 p++;
445 }
446 #else
447 // Disable LocalTalk
448 p[0] = htons(M68K_JMP_A0);
449 p[1] = htons(0x7000); // moveq #0,d0
450 p[2] = htons(M68K_RTS);
451 D(bug(" patch 1 applied\n"));
452 #endif
453
454 } else if (type == FOURCC('n','s','r','d') && id == 1) {
455 D(bug("nsrd 1 found\n"));
456 if (p[(0x378 + 0x460) >> 1] == htons(0x7c08) && p[(0x37a + 0x460) >> 1] == htons(0x02a6)) {
457 // Don't overwrite our serial drivers (7.5.3 Revision 2.2)
458 p[(0x378 + 0x460) >> 1] = htons(0x4e80); // blr
459 p[(0x37a + 0x460) >> 1] = htons(0x0020);
460 D(bug(" patch 1 applied\n"));
461 } else if (p[(0x378 + 0x570) >> 1] == htons(0x7c08) && p[(0x37a + 0x570) >> 1] == htons(0x02a6)) {
462 // Don't overwrite our serial drivers (8.0, 8.1)
463 p[(0x378 + 0x570) >> 1] = htons(0x4e80); // blr
464 p[(0x37a + 0x570) >> 1] = htons(0x0020);
465 D(bug(" patch 2 applied\n"));
466 } else if (p[(0x378 + 0x6c0) >> 1] == htons(0x7c08) && p[(0x37a + 0x6c0) >> 1] == htons(0x02a6)) {
467 // Don't overwrite our serial drivers (8.5, 8.6)
468 p[(0x378 + 0x6c0) >> 1] = htons(0x4e80); // blr
469 p[(0x37a + 0x6c0) >> 1] = htons(0x0020);
470 D(bug(" patch 3 applied\n"));
471 } else if (p[(0x374 + 0x510) >> 1] == htons(0x7c08) && p[(0x376 + 0x510) >> 1] == htons(0x02a6)) {
472 // Don't overwrite our serial drivers (9.0)
473 p[(0x374 + 0x510) >> 1] = htons(0x4e80); // blr
474 p[(0x376 + 0x510) >> 1] = htons(0x0020);
475 D(bug(" patch 4 applied\n"));
476 }
477
478 } else if (type == FOURCC('c','i','t','t') && id == 45) {
479 D(bug("citt 45 found\n"));
480 size >>= 1;
481 while (size--) {
482 if (PM(0,0x203c) && PM(1,0x0100) && PM(2,0x0000) && PM(3,0xc0ae) && PM(4,0xfffc)) {
483 // Don't replace SCSI Manager (8.1, 8.5, 8.6, 9.0)
484 p[5] = htons((ntohs(p[5]) & 0xff) | 0x6000); // beq
485 D(bug(" patch 1 applied\n"));
486 break;
487 }
488 p++;
489 }
490
491 } else if (type == FOURCC('t','h','n','g')) {
492 // Collect info about used audio sifters
493 uint32 thing = Host2MacAddr((uint8 *)p);
494 uint32 c_type = ReadMacInt32(thing);
495 uint32 sub_type = ReadMacInt32(thing + 4);
496 if (c_type == FOURCC('s','d','e','v') && sub_type == FOURCC('s','i','n','g')) {
497 WriteMacInt32(thing + 4, FOURCC('a','w','g','c'));
498 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));
499 AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID));
500 if (ReadMacInt32(thing + componentPFCount))
501 AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID));
502 }
503
504 } else if (type == FOURCC('s','i','f','t') || type == FOURCC('n','i','f','t')) {
505 // Patch audio sifters
506 if (FindSifter(type, id)) {
507 D(bug("sifter found\n"));
508 p[0] = htons(0x4e56); p[1] = htons(0x0000); // link a6,#0
509 p[2] = htons(0x48e7); p[3] = htons(0x8018); // movem.l d0/a3-a4,-(a7)
510 p[4] = htons(0x266e); p[5] = htons(0x000c); // movea.l $c(a6),a3
511 p[6] = htons(0x286e); p[7] = htons(0x0008); // movea.l $8(a6),a4
512 p[8] = htons(M68K_EMUL_OP_AUDIO_DISPATCH);
513 p[9] = htons(0x2d40); p[10] = htons(0x0010); // move.l d0,$10(a6)
514 p[11] = htons(0x4cdf); p[12] = htons(0x1801); // movem.l (a7)+,d0/a3-a4
515 p[13] = htons(0x4e5e); // unlk a6
516 p[14] = htons(0x4e74); p[15] = htons(0x0008); // rtd #8
517 D(bug(" patch applied\n"));
518 }
519
520 } else if (type == FOURCC('D','R','V','R') && (id == -16501 || id == -16500)) {
521 D(bug("DRVR -16501/-16500 found\n"));
522 // Install sound input driver
523 memcpy(p, sound_input_driver, sizeof(sound_input_driver));
524 D(bug(" patch 1 applied\n"));
525
526 } else if (type == FOURCC('I','N','I','T') && id == 1 && size == (2416 >> 1)) {
527 D(bug("INIT 1 (size 2416) found\n"));
528 size >>= 1;
529 while (size--) {
530 if (PM(0,0x247c) && PM(1,0xf301) && PM(2,0x9000)) {
531 // Prevent "MacOS Licensing Extension" from accessing hardware (7.6)
532 p[22] = htons(0x6028);
533 D(bug(" patch 1 applied\n"));
534 break;
535 }
536 p++;
537 }
538
539 } else if (type == FOURCC('s','c','o','d') && id == -16465) {
540 D(bug("scod -16465 found\n"));
541
542 // Don't crash in Process Manager on reset/shutdown (8.6, 9.0)
543 static const uint8 dat[] = {0x4e, 0x56, 0x00, 0x00, 0x48, 0xe7, 0x03, 0x18, 0x2c, 0x2e, 0x00, 0x10};
544 base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat));
545 if (base) {
546 p16 = (uint16 *)((uintptr)p + base);
547 p16[0] = htons(0x7000); // moveq #0,d0
548 p16[1] = htons(M68K_RTS);
549 D(bug(" patch 1 applied\n"));
550 }
551
552 } else if (type == FOURCC('N','O','b','j') && id == 100) {
553 D(bug("NObj 100 found\n"));
554
555 // Don't access VIA registers in MacBench 5.0
556 static const uint8 dat1[] = {0x7c, 0x08, 0x02, 0xa6, 0xbf, 0x01, 0xff, 0xe0, 0x90, 0x01, 0x00, 0x08};
557 base = find_rsrc_data((uint8 *)p, size, dat1, sizeof(dat1));
558 if (base) {
559 p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0
560 p[(base + 0x02) >> 1] = htons(0x0000);
561 p[(base + 0x04) >> 1] = htons(0x4e80); // blr
562 p[(base + 0x06) >> 1] = htons(0x0020);
563 D(bug(" patch 1 applied\n"));
564 }
565 static const uint8 dat2[] = {0x7c, 0x6c, 0x1b, 0x78, 0x7c, 0x8b, 0x23, 0x78, 0x38, 0xc0, 0x3f, 0xfd};
566 base = find_rsrc_data((uint8 *)p, size, dat2, sizeof(dat2));
567 if (base) {
568 p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0
569 p[(base + 0x02) >> 1] = htons(0x0000);
570 p[(base + 0x04) >> 1] = htons(0x4e80); // blr
571 p[(base + 0x06) >> 1] = htons(0x0020);
572 D(bug(" patch 2 applied\n"));
573 }
574
575 } else if (type == FOURCC('C','O','D','E') && id == 27 && size == 25024) {
576 D(bug("CODE 27 found [Apple Personal Diagnostics]\n"));
577
578 // Don't access FCBs directly in Apple Personal Diagnostics (MacOS 9)
579 // FIXME: this should not be called in the first place, use UTResolveFCB?
580 static const uint8 dat[] = {0x2d, 0x78, 0x03, 0x4e, 0xff, 0xf8, 0x20, 0x6e, 0xff, 0xf8};
581 base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat));
582 if (base
583 && ReadMacInt16(0x3f6) == 4 /* FSFCBLen */
584 && p[(base + 0x1a) >> 1] == htons(0x605e)
585 && p[(base + 0x80) >> 1] == htons(0x7000))
586 {
587 p[(base + 0x1a) >> 1] = htons(0x6064);
588 D(bug(" patch1 applied\n"));
589 }
590
591 } else if (type == FOURCC('i','n','f','n') && (id == 129 || id == 200)) {
592 D(bug("infn %d found\n", id));
593 size >>= 1;
594 while (size--) {
595 if (PM(0,0x203c) && PM(1,0xf800) && PM(2,0x0000) && PM(4,0x2040) && PM(5,0x1028) && PM(6,0x0090)) {
596 // Don't read from 0xf8000090 during MacOS (8.5, 9.0) installation
597 p[0] = htons(M68K_NOP);
598 p[1] = htons(M68K_NOP);
599 p[2] = htons(M68K_NOP);
600 p[3] = htons(M68K_NOP);
601 p[4] = htons(M68K_NOP);
602 p[5] = htons(M68K_NOP);
603 p[6] = htons(0x7000); // moveq #0,d0
604 D(bug(" patch 1 applied\n"));
605 break;
606 }
607 p++;
608 }
609
610 }
611 }
612
613
614 /*
615 * Resource patches via GetNamedResource() and Get1NamedResource()
616 */
617
618 void CheckLoad(uint32 type, const char *name, uint8 *p, uint32 size)
619 {
620 uint16 *p16;
621 uint32 base;
622 D(bug("vCheckLoad %c%c%c%c (%08x) name \"%*s\", data %p, size %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, name[0], &name[1], p, size));
623
624 // Don't modify resources in ROM
625 if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE))
626 return;
627
628 if (type == FOURCC('D','R','V','R') && strncmp(&name[1], ".AFPTranslator", name[0]) == 0) {
629 D(bug(" DRVR .AFPTranslator found\n"));
630
631 // Don't access ROM85 as it it was a pointer to a ROM version number (8.0, 8.1)
632 static const uint8 dat[] = {0x3a, 0x2e, 0x00, 0x0a, 0x55, 0x4f, 0x3e, 0xb8, 0x02, 0x8e, 0x30, 0x1f, 0x48, 0xc0, 0x24, 0x40, 0x20, 0x40};
633 base = find_rsrc_data(p, size, dat, sizeof(dat));
634 if (base) {
635 p16 = (uint16 *)(p + base + 4);
636 *p16++ = htons(0x303c); // move.l #ROM85,%d0
637 *p16++ = htons(0x028e);
638 *p16++ = htons(M68K_NOP);
639 *p16++ = htons(M68K_NOP);
640 D(bug(" patch 1 applied\n"));
641 }
642 }
643 }
644
645
646 /*
647 * Native Resource Manager patches
648 */
649
650 #ifdef __BEOS__
651 static
652 #else
653 extern "C"
654 #endif
655 void check_load_invoc(uint32 type, int16 id, uint32 h)
656 {
657 if (h == 0)
658 return;
659 uint32 p = ReadMacInt32(h);
660 if (p == 0)
661 return;
662 uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff;
663
664 CheckLoad(type, id, (uint16 *)Mac2HostAddr(p), size);
665 }
666
667 #ifdef __BEOS__
668 static
669 #else
670 extern "C"
671 #endif
672 void named_check_load_invoc(uint32 type, uint32 name, uint32 h)
673 {
674 if (h == 0)
675 return;
676 uint32 p = ReadMacInt32(h);
677 if (p == 0)
678 return;
679 uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff;
680
681 CheckLoad(type, (char *)Mac2HostAddr(name), Mac2HostAddr(p), size);
682 }
683
684 #ifdef __BEOS__
685 static asm void **get_resource(register uint32 type, register int16 id)
686 {
687 // Create stack frame
688 mflr r0
689 stw r0,8(r1)
690 stwu r1,-(56+12)(r1)
691
692 // Save type/ID
693 stw r3,56(r1)
694 stw r4,56+4(r1)
695
696 // Call old routine
697 lwz r0,XLM_GET_RESOURCE
698 lwz r2,XLM_RES_LIB_TOC
699 mtctr r0
700 bctrl
701 lwz r2,XLM_TOC // Get TOC
702 stw r3,56+8(r1) // Save handle
703
704 // Call CheckLoad
705 lwz r3,56(r1)
706 lwz r4,56+4(r1)
707 lwz r5,56+8(r1)
708 bl check_load_invoc
709 lwz r3,56+8(r1) // Restore handle
710
711 // Return to caller
712 lwz r0,56+12+8(r1)
713 mtlr r0
714 addi r1,r1,56+12
715 blr
716 }
717
718 static asm void **get_1_resource(register uint32 type, register int16 id)
719 {
720 // Create stack frame
721 mflr r0
722 stw r0,8(r1)
723 stwu r1,-(56+12)(r1)
724
725 // Save type/ID
726 stw r3,56(r1)
727 stw r4,56+4(r1)
728
729 // Call old routine
730 lwz r0,XLM_GET_1_RESOURCE
731 lwz r2,XLM_RES_LIB_TOC
732 mtctr r0
733 bctrl
734 lwz r2,XLM_TOC // Get TOC
735 stw r3,56+8(r1) // Save handle
736
737 // Call CheckLoad
738 lwz r3,56(r1)
739 lwz r4,56+4(r1)
740 lwz r5,56+8(r1)
741 bl check_load_invoc
742 lwz r3,56+8(r1) // Restore handle
743
744 // Return to caller
745 lwz r0,56+12+8(r1)
746 mtlr r0
747 addi r1,r1,56+12
748 blr
749 }
750
751 static asm void **get_ind_resource(register uint32 type, register int16 index)
752 {
753 // Create stack frame
754 mflr r0
755 stw r0,8(r1)
756 stwu r1,-(56+12)(r1)
757
758 // Save type/index
759 stw r3,56(r1)
760 stw r4,56+4(r1)
761
762 // Call old routine
763 lwz r0,XLM_GET_IND_RESOURCE
764 lwz r2,XLM_RES_LIB_TOC
765 mtctr r0
766 bctrl
767 lwz r2,XLM_TOC // Get TOC
768 stw r3,56+8(r1) // Save handle
769
770 // Call CheckLoad
771 lwz r3,56(r1)
772 lwz r4,56+4(r1)
773 lwz r5,56+8(r1)
774 bl check_load_invoc
775 lwz r3,56+8(r1) // Restore handle
776
777 // Return to caller
778 lwz r0,56+12+8(r1)
779 mtlr r0
780 addi r1,r1,56+12
781 blr
782 }
783
784 static asm void **get_1_ind_resource(register uint32 type, register int16 index)
785 {
786 // Create stack frame
787 mflr r0
788 stw r0,8(r1)
789 stwu r1,-(56+12)(r1)
790
791 // Save type/index
792 stw r3,56(r1)
793 stw r4,56+4(r1)
794
795 // Call old routine
796 lwz r0,XLM_GET_1_IND_RESOURCE
797 lwz r2,XLM_RES_LIB_TOC
798 mtctr r0
799 bctrl
800 lwz r2,XLM_TOC // Get TOC
801 stw r3,56+8(r1) // Save handle
802
803 // Call CheckLoad
804 lwz r3,56(r1)
805 lwz r4,56+4(r1)
806 lwz r5,56+8(r1)
807 bl check_load_invoc
808 lwz r3,56+8(r1) // Restore handle
809
810 // Return to caller
811 lwz r0,56+12+8(r1)
812 mtlr r0
813 addi r1,r1,56+12
814 blr
815 }
816
817 static asm void **r_get_resource(register uint32 type, register int16 id)
818 {
819 // Create stack frame
820 mflr r0
821 stw r0,8(r1)
822 stwu r1,-(56+12)(r1)
823
824 // Save type/ID
825 stw r3,56(r1)
826 stw r4,56+4(r1)
827
828 // Call old routine
829 lwz r0,XLM_R_GET_RESOURCE
830 lwz r2,XLM_RES_LIB_TOC
831 mtctr r0
832 bctrl
833 lwz r2,XLM_TOC // Get TOC
834 stw r3,56+8(r1) // Save handle
835
836 // Call CheckLoad
837 lwz r3,56(r1)
838 lwz r4,56+4(r1)
839 lwz r5,56+8(r1)
840 bl check_load_invoc
841 lwz r3,56+8(r1) // Restore handle
842
843 // Return to caller
844 lwz r0,56+12+8(r1)
845 mtlr r0
846 addi r1,r1,56+12
847 blr
848 }
849
850 static asm void **get_named_resource(register uint32 type, register uint32 name)
851 {
852 // Create stack frame
853 mflr r0
854 stw r0,8(r1)
855 stwu r1,-(56+12)(r1)
856
857 // Save type/ID
858 stw r3,56(r1)
859 stw r4,56+4(r1)
860
861 // Call old routine
862 lwz r0,XLM_GET_NAMED_RESOURCE
863 lwz r2,XLM_RES_LIB_TOC
864 mtctr r0
865 bctrl
866 lwz r2,XLM_TOC // Get TOC
867 stw r3,56+8(r1) // Save handle
868
869 // Call CheckLoad
870 lwz r3,56(r1)
871 lwz r4,56+4(r1)
872 lwz r5,56+8(r1)
873 bl named_check_load_invoc
874 lwz r3,56+8(r1) // Restore handle
875
876 // Return to caller
877 lwz r0,56+12+8(r1)
878 mtlr r0
879 addi r1,r1,56+12
880 blr
881 }
882
883 static asm void **get_1_named_resource(register uint32 type, register uint32 name)
884 {
885 // Create stack frame
886 mflr r0
887 stw r0,8(r1)
888 stwu r1,-(56+12)(r1)
889
890 // Save type/ID
891 stw r3,56(r1)
892 stw r4,56+4(r1)
893
894 // Call old routine
895 lwz r0,XLM_GET_1_NAMED_RESOURCE
896 lwz r2,XLM_RES_LIB_TOC
897 mtctr r0
898 bctrl
899 lwz r2,XLM_TOC // Get TOC
900 stw r3,56+8(r1) // Save handle
901
902 // Call CheckLoad
903 lwz r3,56(r1)
904 lwz r4,56+4(r1)
905 lwz r5,56+8(r1)
906 bl named_check_load_invoc
907 lwz r3,56+8(r1) // Restore handle
908
909 // Return to caller
910 lwz r0,56+12+8(r1)
911 mtlr r0
912 addi r1,r1,56+12
913 blr
914 }
915 #else
916 // Routines in asm_linux.S
917 extern "C" void get_resource(void);
918 extern "C" void get_1_resource(void);
919 extern "C" void get_ind_resource(void);
920 extern "C" void get_1_ind_resource(void);
921 extern "C" void r_get_resource(void);
922 extern "C" void get_named_resource(void);
923 extern "C" void get_1_named_resource(void);
924 #endif
925
926 void PatchNativeResourceManager(void)
927 {
928 D(bug("PatchNativeResourceManager\n"));
929
930 // Patch native GetResource()
931 uint32 upp = ReadMacInt32(0x1480);
932 if ((upp & 0xffc00000) == ROMBase)
933 return;
934 uint32 tvec = ReadMacInt32(upp + 5 * 4);
935 D(bug(" GetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
936 WriteMacInt32(XLM_RES_LIB_TOC, ReadMacInt32(tvec + 4));
937 WriteMacInt32(XLM_GET_RESOURCE, ReadMacInt32(tvec));
938 #if EMULATED_PPC
939 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_RESOURCE));
940 #else
941 #ifdef __BEOS__
942 uint32 *tvec2 = (uint32 *)get_resource;
943 WriteMacInt32(tvec, tvec2[0]);
944 WriteMacInt32(tvec + 4, tvec2[1]);
945 #else
946 WriteMacInt32(tvec, (uint32)get_resource);
947 #endif
948 #endif
949
950 // Patch native Get1Resource()
951 upp = ReadMacInt32(0x0e7c);
952 tvec = ReadMacInt32(upp + 5 * 4);
953 D(bug(" Get1Resource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
954 WriteMacInt32(XLM_GET_1_RESOURCE, ReadMacInt32(tvec));
955 #if EMULATED_PPC
956 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_RESOURCE));
957 #else
958 #ifdef __BEOS__
959 tvec2 = (uint32 *)get_1_resource;
960 WriteMacInt32(tvec, tvec2[0]);
961 WriteMacInt32(tvec + 4, tvec2[1]);
962 #else
963 WriteMacInt32(tvec, (uint32)get_1_resource);
964 #endif
965 #endif
966
967 // Patch native GetIndResource()
968 upp = ReadMacInt32(0x1474);
969 tvec = ReadMacInt32(upp + 5 * 4);
970 D(bug(" GetIndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
971 WriteMacInt32(XLM_GET_IND_RESOURCE, ReadMacInt32(tvec));
972 #if EMULATED_PPC
973 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_IND_RESOURCE));
974 #else
975 #ifdef __BEOS__
976 tvec2 = (uint32 *)get_ind_resource;
977 WriteMacInt32(tvec, tvec2[0]);
978 WriteMacInt32(tvec + 4, tvec2[1]);
979 #else
980 WriteMacInt32(tvec, (uint32)get_ind_resource);
981 #endif
982 #endif
983
984 // Patch native Get1IndResource()
985 upp = ReadMacInt32(0x0e38);
986 tvec = ReadMacInt32(upp + 5 * 4);
987 D(bug(" Get1IndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
988 WriteMacInt32(XLM_GET_1_IND_RESOURCE, ReadMacInt32(tvec));
989 #if EMULATED_PPC
990 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_IND_RESOURCE));
991 #else
992 #ifdef __BEOS__
993 tvec2 = (uint32 *)get_1_ind_resource;
994 WriteMacInt32(tvec, tvec2[0]);
995 WriteMacInt32(tvec + 4, tvec2[1]);
996 #else
997 WriteMacInt32(tvec, (uint32)get_1_ind_resource);
998 #endif
999 #endif
1000
1001 // Patch native RGetResource()
1002 upp = ReadMacInt32(0x0e30);
1003 tvec = ReadMacInt32(upp + 5 * 4);
1004 D(bug(" RGetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
1005 WriteMacInt32(XLM_R_GET_RESOURCE, ReadMacInt32(tvec));
1006 #if EMULATED_PPC
1007 WriteMacInt32(tvec, NativeFunction(NATIVE_R_GET_RESOURCE));
1008 #else
1009 #ifdef __BEOS__
1010 tvec2 = (uint32 *)r_get_resource;
1011 WriteMacInt32(tvec, tvec2[0]);
1012 WriteMacInt32(tvec + 4, tvec2[1]);
1013 #else
1014 WriteMacInt32(tvec, (uint32)r_get_resource);
1015 #endif
1016 #endif
1017
1018 // Patch native GetNamedResource()
1019 upp = ReadMacInt32(0x1484);
1020 tvec = ReadMacInt32(upp + 5 * 4);
1021 D(bug(" GetNamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
1022 WriteMacInt32(XLM_GET_NAMED_RESOURCE, ReadMacInt32(tvec));
1023 #if EMULATED_PPC
1024 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_NAMED_RESOURCE));
1025 #else
1026 #ifdef __BEOS__
1027 tvec2 = (uint32 *)get_named_resource;
1028 WriteMacInt32(tvec, tvec2[0]);
1029 WriteMacInt32(tvec + 4, tvec2[1]);
1030 #else
1031 WriteMacInt32(tvec, (uint32)get_named_resource);
1032 #endif
1033 #endif
1034
1035 // Patch native Get1NamedResource()
1036 upp = ReadMacInt32(0x0e80);
1037 tvec = ReadMacInt32(upp + 5 * 4);
1038 D(bug(" Get1NamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4)));
1039 WriteMacInt32(XLM_GET_1_NAMED_RESOURCE, ReadMacInt32(tvec));
1040 #if EMULATED_PPC
1041 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_NAMED_RESOURCE));
1042 #else
1043 #ifdef __BEOS__
1044 tvec2 = (uint32 *)get_1_named_resource;
1045 WriteMacInt32(tvec, tvec2[0]);
1046 WriteMacInt32(tvec + 4, tvec2[1]);
1047 #else
1048 WriteMacInt32(tvec, (uint32)get_1_named_resource);
1049 #endif
1050 #endif
1051 }