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 (14 years, 8 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

# User Rev Content
1 cebix 1.1 /*
2     * rsrc_patches.cpp - Resource patches
3     *
4 gbeauche 1.23 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
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 gbeauche 1.8 #include "audio_defs.h"
35 gbeauche 1.7 #include "thunks.h"
36 cebix 1.1
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 gbeauche 1.4 // 680x0 code pattern matching helper
111     #define PM(N, V) (p[N] == htons(V))
112    
113 cebix 1.1 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 gbeauche 1.12 if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE))
121 cebix 1.1 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 gbeauche 1.19 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 cebix 1.1 D(bug(" patch 1 applied\n"));
131 gbeauche 1.4 } else if (PM(0,0x4267) && PM(1,0x3f01) && PM(2,0x3f2a) && PM(3,0x0006) && PM(4,0x6100)) {
132 cebix 1.1 // Check when ntrb 17 is installed (for native Resource Manager patch) (7.5.3, 7.5.5)
133 gbeauche 1.4 p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH3);
134 cebix 1.1 D(bug(" patch 2 applied\n"));
135 gbeauche 1.4 } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x6100)) {
136 cebix 1.1 // Check when ntrb 17 is installed (for native Resource Manager patch) (7.6, 7.6.1, 8.0, 8.1)
137 gbeauche 1.4 p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH);
138 cebix 1.1 D(bug(" patch 3 applied\n"));
139 gbeauche 1.11 } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x61ff) && PM(8,0x245f)) {
140 cebix 1.1 // Check when ntrb 17 is installed (for native Resource Manager patch) (8.5, 8.6)
141 gbeauche 1.4 p[8] = htons(M68K_EMUL_OP_NTRB_17_PATCH);
142 cebix 1.1 D(bug(" patch 4 applied\n"));
143 gbeauche 1.11 } 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 gbeauche 1.19 D(bug(" patch 5 applied\n"));
148 gbeauche 1.4 } else if (PM(0,0x0c39) && PM(1,0x0001) && PM(2,0xf800) && PM(3,0x0008) && PM(4,0x6f00)) {
149 gbeauche 1.19 // Don't read from 0xf8000008 (8.5 with Zanzibar ROM, 8.6, 9.0)
150 gbeauche 1.4 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 gbeauche 1.19 D(bug(" patch 6 applied\n"));
156 gbeauche 1.4 } 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 gbeauche 1.19 // Don't replace nanokernel ("krnl" resource) (8.6, 9.0)
158 gbeauche 1.4 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 gbeauche 1.19 D(bug(" patch 7 applied\n"));
165 gbeauche 1.4 } else if (PM(0,0xa8fe) && PM(1,0x3038) && PM(2,0x017a) && PM(3,0x0c40) && PM(4,0x8805) && PM(5,0x6710)) {
166 cebix 1.1 // No SCSI (calls via 0x205c jump vector which is not initialized in NewWorld ROM 1.6) (8.6)
167     if (ROMType == ROMTYPE_NEWWORLD) {
168 gbeauche 1.4 p[5] = htons(0x6010); // bra
169 gbeauche 1.19 D(bug(" patch 8 applied\n"));
170 cebix 1.1 }
171 gbeauche 1.16 } 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 cebix 1.1 }
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 gbeauche 1.4 p16 = (uint16 *)((uintptr)p + base + 6);
189 cebix 1.1 *p16 = htons(M68K_EMUL_OP_NTRB_17_PATCH2);
190     D(bug(" patch 1 applied\n"));
191     }
192    
193 gbeauche 1.11 } 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 cebix 1.1 } else if (type == FOURCC('p','t','c','h') && id == 420) {
208     D(bug("ptch 420 found\n"));
209     size >>= 1;
210     while (size--) {
211 gbeauche 1.4 if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x303c) && PM(3,0x0100) && PM(4,0xc06e) && PM(5,0xfef6)) {
212 cebix 1.1 // Disable VM (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1)
213 gbeauche 1.4 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 cebix 1.1 D(bug(" patch 1 applied\n"));
225     break;
226 gbeauche 1.4 } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfef6) && PM(5,0x323c) && PM(6,0x0100)) {
227 cebix 1.1 // Disable VM (8.0, 8.1)
228 gbeauche 1.4 p[8] = htons(M68K_NOP);
229     p[15] = htons(M68K_NOP);
230 cebix 1.1 D(bug(" patch 2 applied\n"));
231     break;
232 gbeauche 1.4 } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfecc) && PM(5,0x323c) && PM(6,0x0100)) {
233 gbeauche 1.19 // Disable VM (8.5, 8.6, 9.0)
234 gbeauche 1.4 p[8] = htons(M68K_NOP);
235     p[15] = htons(M68K_NOP);
236 cebix 1.1 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 gbeauche 1.4 if (PM(0,0x6700) && PM(13,0x7013) && PM(14,0xfe0a)) {
247 cebix 1.1 // Don't call FE0A in Shutdown Manager (7.6.1, 8.0, 8.1, 8.5)
248 gbeauche 1.4 p[0] = htons(0x6000);
249 cebix 1.1 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 gbeauche 1.4 if (PM(0,0x6600) && PM(1,0x001a) && PM(2,0x2278) && PM(3,0x0134)) {
260 cebix 1.1 // We don't have SonyVars (7.5.2)
261 gbeauche 1.4 p[0] = htons(0x6000);
262 cebix 1.1 D(bug(" patch 1 applied\n"));
263 gbeauche 1.4 } else if (PM(0,0x6618) && PM(1,0x2278) && PM(2,0x0134)) {
264 cebix 1.1 // We don't have SonyVars (7.5.3)
265 gbeauche 1.4 p[-6] = htons(M68K_NOP);
266     p[-3] = htons(M68K_NOP);
267     p[0] = htons(0x6018);
268 cebix 1.1 D(bug(" patch 2 applied\n"));
269 gbeauche 1.20 } 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 gbeauche 1.4 } else if (PM(0,0x666e) && PM(1,0x2278) && PM(2,0x0134)) {
276 cebix 1.1 // We don't have SonyVars (7.5.5)
277 gbeauche 1.4 p[-6] = htons(M68K_NOP);
278     p[-3] = htons(M68K_NOP);
279     p[0] = htons(0x606e);
280 gbeauche 1.20 D(bug(" patch 4 applied\n"));
281 gbeauche 1.4 } else if (PM(0,0x6400) && PM(1,0x011c) && PM(2,0x2278) && PM(3,0x0134)) {
282 gbeauche 1.19 // We don't have SonyVars (7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0)
283 gbeauche 1.4 p[0] = htons(0x6000);
284 gbeauche 1.20 D(bug(" patch 5 applied\n"));
285 gbeauche 1.4 } else if (PM(0,0x6400) && PM(1,0x00e6) && PM(2,0x2278) && PM(3,0x0134)) {
286 cebix 1.1 // We don't have SonyVars (7.6)
287 gbeauche 1.4 p[0] = htons(0x6000);
288 gbeauche 1.20 D(bug(" patch 6 applied\n"));
289 cebix 1.1 }
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 gbeauche 1.4 if (PM(0,0x83a8) && PM(1,0x0024) && PM(2,0x4e71)) {
298 cebix 1.1 // Don't write to GC interrupt mask (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
299 gbeauche 1.4 p[0] = htons(M68K_NOP);
300     p[1] = htons(M68K_NOP);
301 cebix 1.1 D(bug(" patch 1 applied\n"));
302 gbeauche 1.4 } else if (PM(0,0x207c) && PM(1,0xf300) && PM(2,0x0034)) {
303 cebix 1.1 // Don't read PowerMac ID (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
304 gbeauche 1.4 p[0] = htons(0x303c); // move.w #id,d0
305     p[1] = htons(0x3020);
306     p[2] = htons(M68K_RTS);
307 cebix 1.1 D(bug(" patch 2 applied\n"));
308 gbeauche 1.4 } else if (PM(0,0x13fc) && PM(1,0x0081) && PM(2,0xf130) && PM(3,0xa030)) {
309 cebix 1.1 // Don't write to hardware (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
310 gbeauche 1.4 p[0] = htons(M68K_NOP);
311     p[1] = htons(M68K_NOP);
312     p[2] = htons(M68K_NOP);
313     p[3] = htons(M68K_NOP);
314 cebix 1.1 D(bug(" patch 3 applied\n"));
315 gbeauche 1.4 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf800) && PM(4,0x0000)) {
316 cebix 1.1 // OpenFirmare? (7.6.1, 8.0, 8.1 with Zanzibar ROM)
317 gbeauche 1.4 p[0] = htons(M68K_RTS);
318 cebix 1.1 D(bug(" patch 4 applied\n"));
319 gbeauche 1.4 } else if (PM(0,0x4e56) && PM(1,0xfffc) && PM(2,0x48e7) && PM(3,0x0300) && PM(4,0x598f) && PM(5,0x2eb8) && PM(6,0x01dc)) {
320 cebix 1.1 // Don't write to SCC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
321 gbeauche 1.4 p[0] = htons(M68K_RTS);
322 cebix 1.1 D(bug(" patch 5 applied\n"));
323 gbeauche 1.4 } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf300) && PM(4,0x0034)) {
324 cebix 1.1 // Don't write to GC (7.6.1, 8.0, 8.1 with Zanzibar ROM)
325 gbeauche 1.4 p[0] = htons(M68K_RTS);
326 cebix 1.1 D(bug(" patch 6 applied\n"));
327 gbeauche 1.4 } 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 cebix 1.1 // Don't replace NVRAM routines (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM)
329 gbeauche 1.4 p[0] = htons(M68K_RTS);
330 cebix 1.1 D(bug(" patch 7 applied\n"));
331 gbeauche 1.4 } else if (PM(0,0x207c) && PM(1,0x50f1) && PM(2,0xa101) && (PM(3,0x08d0) || PM(3,0x0890))) {
332 cebix 1.1 // Don't write to 0x50f1a101 (8.1 with Zanzibar ROM)
333 gbeauche 1.4 p[3] = htons(M68K_NOP);
334     p[4] = htons(M68K_NOP);
335 cebix 1.1 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 gbeauche 1.4 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
345 cebix 1.1 // Don't read from 0xf3019100 (MACE ENET) (7.6, 7.6.1, 8.0, 8.1)
346 gbeauche 1.4 p[2] = htons(M68K_NOP);
347     p[3] = htons(M68K_NOP);
348     p[4] = htons(0x6026);
349 cebix 1.1 D(bug(" patch 1 applied\n"));
350 gbeauche 1.4 } else if (PM(0,0x41e8) && PM(1,0x0374) && PM(2,0xfc1e)) {
351 cebix 1.1 // Don't call FC1E opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6)
352 gbeauche 1.4 p[2] = htons(M68K_NOP);
353 cebix 1.1 D(bug(" patch 2 applied\n"));
354 gbeauche 1.4 } else if (PM(0,0x700a) && PM(1,0xfe0a)) {
355 gbeauche 1.19 // 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 cebix 1.1 D(bug(" patch 3 applied\n"));
358 asvitkine 1.22 } 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 cebix 1.1 }
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 gbeauche 1.4 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
375 cebix 1.1 // Don't read from 0xf3019100 (MACE ENET) (8.5, 8.6)
376 gbeauche 1.4 p[2] = htons(M68K_NOP);
377     p[3] = htons(M68K_NOP);
378     p[4] = htons(0x6026);
379 cebix 1.1 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 gbeauche 1.4 if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) {
389 cebix 1.1 // Don't read from 0xf3019100 (MACE ENET) (8.1 with NewWorld ROM)
390 gbeauche 1.4 p[2] = htons(M68K_NOP);
391     p[3] = htons(M68K_NOP);
392     p[4] = htons(0x6026);
393 cebix 1.1 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 gbeauche 1.4 if (PM(0,0xc2fc) && PM(1,0x0fa0) && PM(2,0x82c5)) {
404 cebix 1.1 // 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 gbeauche 1.4 p[2] = htons(0x7200);
406 cebix 1.1 WriteMacInt32(0x1d8, 0x2c00);
407     WriteMacInt32(0x1dc, 0x2c00);
408     D(bug(" patch 1 applied\n"));
409 gbeauche 1.4 } else if (PM(0,0x1418) && PM(1,0x84c1)) {
410 cebix 1.1 // Prevent division by 0 (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
411 gbeauche 1.4 p[1] = htons(0x7400);
412 cebix 1.1 D(bug(" patch 2 applied\n"));
413 gbeauche 1.4 } else if (PM(0,0x2678) && PM(1,0x01dc) && PM(2,0x3018) && PM(3,0x6708) && PM(4,0x1680) && PM(5,0xe058) && PM(6,0x1680)) {
414 cebix 1.1 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
415 gbeauche 1.4 p[4] = htons(M68K_NOP);
416     p[6] = htons(M68K_NOP);
417 cebix 1.1 D(bug(" patch 3 applied\n"));
418 gbeauche 1.4 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0006) && PM(4,0x4e71) && PM(5,0x1292)) {
419 cebix 1.1 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
420 gbeauche 1.4 p[2] = htons(M68K_NOP);
421     p[3] = htons(M68K_NOP);
422     p[5] = htons(M68K_NOP);
423 cebix 1.1 D(bug(" patch 4 applied\n"));
424 gbeauche 1.4 } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0003) && PM(4,0x4e71) && PM(5,0x1281)) {
425 cebix 1.1 // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
426 gbeauche 1.4 p[2] = htons(M68K_NOP);
427     p[3] = htons(M68K_NOP);
428     p[5] = htons(M68K_NOP);
429 cebix 1.1 D(bug(" patch 5 applied\n"));
430 gbeauche 1.4 } else if (PM(0,0x0811) && PM(1,0x0000) && PM(2,0x51c8) && PM(3,0xfffa)) {
431 cebix 1.1 // Don't test SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1)
432 gbeauche 1.4 p[0] = htons(M68K_NOP);
433     p[1] = htons(M68K_NOP);
434 cebix 1.1 D(bug(" patch 6 applied\n"));
435 gbeauche 1.4 } else if (PM(0,0x4a2a) && PM(1,0x063e) && PM(2,0x66fa)) {
436 cebix 1.1 // Don't wait for SCC (7.5.2, 7.5.3, 7.5.5)
437 gbeauche 1.4 p[2] = htons(M68K_NOP);
438 cebix 1.1 D(bug(" patch 7 applied\n"));
439 gbeauche 1.4 } else if (PM(0,0x4a2a) && PM(1,0x03a6) && PM(2,0x66fa)) {
440 cebix 1.1 // Don't wait for SCC (7.6, 7.6.1, 8.0, 8.1)
441 gbeauche 1.4 p[2] = htons(M68K_NOP);
442 cebix 1.1 D(bug(" patch 8 applied\n"));
443     }
444     p++;
445     }
446     #else
447     // Disable LocalTalk
448 gbeauche 1.4 p[0] = htons(M68K_JMP_A0);
449     p[1] = htons(0x7000); // moveq #0,d0
450     p[2] = htons(M68K_RTS);
451 cebix 1.1 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 gbeauche 1.20 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 cebix 1.1 // Don't overwrite our serial drivers (8.0, 8.1)
463 gbeauche 1.6 p[(0x378 + 0x570) >> 1] = htons(0x4e80); // blr
464     p[(0x37a + 0x570) >> 1] = htons(0x0020);
465 gbeauche 1.20 D(bug(" patch 2 applied\n"));
466 gbeauche 1.6 } else if (p[(0x378 + 0x6c0) >> 1] == htons(0x7c08) && p[(0x37a + 0x6c0) >> 1] == htons(0x02a6)) {
467 cebix 1.1 // Don't overwrite our serial drivers (8.5, 8.6)
468 gbeauche 1.6 p[(0x378 + 0x6c0) >> 1] = htons(0x4e80); // blr
469     p[(0x37a + 0x6c0) >> 1] = htons(0x0020);
470 gbeauche 1.20 D(bug(" patch 3 applied\n"));
471 gbeauche 1.13 } 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 gbeauche 1.20 D(bug(" patch 4 applied\n"));
476 cebix 1.1 }
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 gbeauche 1.4 if (PM(0,0x203c) && PM(1,0x0100) && PM(2,0x0000) && PM(3,0xc0ae) && PM(4,0xfffc)) {
483 gbeauche 1.19 // Don't replace SCSI Manager (8.1, 8.5, 8.6, 9.0)
484 gbeauche 1.6 p[5] = htons((ntohs(p[5]) & 0xff) | 0x6000); // beq
485 cebix 1.1 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 gbeauche 1.12 uint32 thing = Host2MacAddr((uint8 *)p);
494 gbeauche 1.8 uint32 c_type = ReadMacInt32(thing);
495     uint32 sub_type = ReadMacInt32(thing + 4);
496 cebix 1.1 if (c_type == FOURCC('s','d','e','v') && sub_type == FOURCC('s','i','n','g')) {
497 gbeauche 1.8 WriteMacInt32(thing + 4, FOURCC('a','w','g','c'));
498 cebix 1.1 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 gbeauche 1.8 AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID));
500     if (ReadMacInt32(thing + componentPFCount))
501     AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID));
502 cebix 1.1 }
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 gbeauche 1.4 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 cebix 1.1 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 gbeauche 1.4 if (PM(0,0x247c) && PM(1,0xf301) && PM(2,0x9000)) {
531 cebix 1.1 // Prevent "MacOS Licensing Extension" from accessing hardware (7.6)
532 gbeauche 1.4 p[22] = htons(0x6028);
533 cebix 1.1 D(bug(" patch 1 applied\n"));
534     break;
535     }
536     p++;
537     }
538 gbeauche 1.3
539     } else if (type == FOURCC('s','c','o','d') && id == -16465) {
540     D(bug("scod -16465 found\n"));
541    
542 gbeauche 1.19 // Don't crash in Process Manager on reset/shutdown (8.6, 9.0)
543 gbeauche 1.3 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 gbeauche 1.4 p16 = (uint16 *)((uintptr)p + base);
547     p16[0] = htons(0x7000); // moveq #0,d0
548     p16[1] = htons(M68K_RTS);
549 gbeauche 1.3 D(bug(" patch 1 applied\n"));
550     }
551 gbeauche 1.10
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 gbeauche 1.14
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 gbeauche 1.21
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 cebix 1.1 }
611     }
612    
613    
614     /*
615 gbeauche 1.17 * 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 gbeauche 1.18
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 gbeauche 1.17 }
644    
645    
646     /*
647 cebix 1.1 * Native Resource Manager patches
648     */
649    
650     #ifdef __BEOS__
651     static
652 gbeauche 1.2 #else
653     extern "C"
654 cebix 1.1 #endif
655 gbeauche 1.5 void check_load_invoc(uint32 type, int16 id, uint32 h)
656 cebix 1.1 {
657 gbeauche 1.5 if (h == 0)
658 cebix 1.1 return;
659 gbeauche 1.5 uint32 p = ReadMacInt32(h);
660     if (p == 0)
661 cebix 1.1 return;
662 gbeauche 1.5 uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff;
663 cebix 1.1
664 gbeauche 1.12 CheckLoad(type, id, (uint16 *)Mac2HostAddr(p), size);
665 cebix 1.1 }
666    
667     #ifdef __BEOS__
668 gbeauche 1.17 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 cebix 1.1 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 gbeauche 1.17
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 cebix 1.1 #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 gbeauche 1.17 extern "C" void get_named_resource(void);
923     extern "C" void get_1_named_resource(void);
924 cebix 1.1 #endif
925    
926     void PatchNativeResourceManager(void)
927     {
928     D(bug("PatchNativeResourceManager\n"));
929    
930     // Patch native GetResource()
931 gbeauche 1.5 uint32 upp = ReadMacInt32(0x1480);
932 asvitkine 1.24 if ((upp & 0xffc00000) == ROMBase)
933 cebix 1.1 return;
934 gbeauche 1.12 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 gbeauche 1.3 #if EMULATED_PPC
939 gbeauche 1.12 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_RESOURCE));
940 gbeauche 1.3 #else
941 cebix 1.1 #ifdef __BEOS__
942     uint32 *tvec2 = (uint32 *)get_resource;
943 gbeauche 1.12 WriteMacInt32(tvec, tvec2[0]);
944     WriteMacInt32(tvec + 4, tvec2[1]);
945 cebix 1.1 #else
946 gbeauche 1.12 WriteMacInt32(tvec, (uint32)get_resource);
947 cebix 1.1 #endif
948 gbeauche 1.3 #endif
949 cebix 1.1
950     // Patch native Get1Resource()
951 gbeauche 1.5 upp = ReadMacInt32(0x0e7c);
952 gbeauche 1.12 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 gbeauche 1.3 #if EMULATED_PPC
956 gbeauche 1.12 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_RESOURCE));
957 gbeauche 1.3 #else
958 cebix 1.1 #ifdef __BEOS__
959     tvec2 = (uint32 *)get_1_resource;
960 gbeauche 1.12 WriteMacInt32(tvec, tvec2[0]);
961     WriteMacInt32(tvec + 4, tvec2[1]);
962 cebix 1.1 #else
963 gbeauche 1.12 WriteMacInt32(tvec, (uint32)get_1_resource);
964 cebix 1.1 #endif
965 gbeauche 1.3 #endif
966 cebix 1.1
967     // Patch native GetIndResource()
968 gbeauche 1.5 upp = ReadMacInt32(0x1474);
969 gbeauche 1.12 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 gbeauche 1.3 #if EMULATED_PPC
973 gbeauche 1.12 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_IND_RESOURCE));
974 gbeauche 1.3 #else
975 cebix 1.1 #ifdef __BEOS__
976     tvec2 = (uint32 *)get_ind_resource;
977 gbeauche 1.12 WriteMacInt32(tvec, tvec2[0]);
978     WriteMacInt32(tvec + 4, tvec2[1]);
979 cebix 1.1 #else
980 gbeauche 1.12 WriteMacInt32(tvec, (uint32)get_ind_resource);
981 cebix 1.1 #endif
982 gbeauche 1.3 #endif
983 cebix 1.1
984     // Patch native Get1IndResource()
985 gbeauche 1.5 upp = ReadMacInt32(0x0e38);
986 gbeauche 1.12 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 gbeauche 1.3 #if EMULATED_PPC
990 gbeauche 1.12 WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_IND_RESOURCE));
991 gbeauche 1.3 #else
992 cebix 1.1 #ifdef __BEOS__
993     tvec2 = (uint32 *)get_1_ind_resource;
994 gbeauche 1.12 WriteMacInt32(tvec, tvec2[0]);
995     WriteMacInt32(tvec + 4, tvec2[1]);
996 cebix 1.1 #else
997 gbeauche 1.12 WriteMacInt32(tvec, (uint32)get_1_ind_resource);
998 cebix 1.1 #endif
999 gbeauche 1.3 #endif
1000 cebix 1.1
1001     // Patch native RGetResource()
1002 gbeauche 1.5 upp = ReadMacInt32(0x0e30);
1003 gbeauche 1.12 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 gbeauche 1.3 #if EMULATED_PPC
1007 gbeauche 1.12 WriteMacInt32(tvec, NativeFunction(NATIVE_R_GET_RESOURCE));
1008 gbeauche 1.3 #else
1009 cebix 1.1 #ifdef __BEOS__
1010     tvec2 = (uint32 *)r_get_resource;
1011 gbeauche 1.12 WriteMacInt32(tvec, tvec2[0]);
1012     WriteMacInt32(tvec + 4, tvec2[1]);
1013 cebix 1.1 #else
1014 gbeauche 1.12 WriteMacInt32(tvec, (uint32)r_get_resource);
1015 gbeauche 1.3 #endif
1016 cebix 1.1 #endif
1017 gbeauche 1.17
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 cebix 1.1 }