ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/rom_patches.cpp
Revision: 1.46
Committed: 2009-08-18T18:26:10Z (14 years, 8 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.45: +53 -53 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 * rom_patches.cpp - ROM 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 /*
22 * TODO:
23 * IRQ_NEST must be handled atomically
24 * Don't use r1 in extra routines
25 */
26
27 #include <string.h>
28
29 #include "sysdeps.h"
30 #include "rom_patches.h"
31 #include "main.h"
32 #include "prefs.h"
33 #include "cpu_emulation.h"
34 #include "emul_op.h"
35 #include "xlowmem.h"
36 #include "sony.h"
37 #include "disk.h"
38 #include "cdrom.h"
39 #include "audio.h"
40 #include "audio_defs.h"
41 #include "serial.h"
42 #include "macos_util.h"
43 #include "thunks.h"
44
45 #define DEBUG 0
46 #include "debug.h"
47
48
49 // 68k breakpoint address
50 //#define M68K_BREAK_POINT 0x29e0 // BootMe
51 //#define M68K_BREAK_POINT 0x2a1e // Boot block code returned
52 //#define M68K_BREAK_POINT 0x3150 // CritError
53 //#define M68K_BREAK_POINT 0x187ce // Unimplemented trap
54
55 // PowerPC breakpoint address
56 //#define POWERPC_BREAK_POINT 0x36e6c0 // 68k emulator start
57
58 #define DISABLE_SCSI 1
59
60
61 // Other ROM addresses
62 const uint32 CHECK_LOAD_PATCH_SPACE = 0x2fcf00;
63 const uint32 PUT_SCRAP_PATCH_SPACE = 0x2fcf80;
64 const uint32 GET_SCRAP_PATCH_SPACE = 0x2fcfc0;
65 const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd100;
66
67 // Global variables
68 int ROMType; // ROM type
69 static uint32 sony_offset; // Offset of .Sony driver resource
70
71 // Prototypes
72 static bool patch_nanokernel_boot(void);
73 static bool patch_68k_emul(void);
74 static bool patch_nanokernel(void);
75 static bool patch_68k(void);
76
77
78 // Decode LZSS data
79 static void decode_lzss(const uint8 *src, uint8 *dest, int size)
80 {
81 char dict[0x1000];
82 int run_mask = 0, dict_idx = 0xfee;
83 for (;;) {
84 if (run_mask < 0x100) {
85 // Start new run
86 if (--size < 0)
87 break;
88 run_mask = *src++ | 0xff00;
89 }
90 bool bit = run_mask & 1;
91 run_mask >>= 1;
92 if (bit) {
93 // Verbatim copy
94 if (--size < 0)
95 break;
96 int c = *src++;
97 dict[dict_idx++] = c;
98 *dest++ = c;
99 dict_idx &= 0xfff;
100 } else {
101 // Copy from dictionary
102 if (--size < 0)
103 break;
104 int idx = *src++;
105 if (--size < 0)
106 break;
107 int cnt = *src++;
108 idx |= (cnt << 4) & 0xf00;
109 cnt = (cnt & 0x0f) + 3;
110 while (cnt--) {
111 char c = dict[idx++];
112 dict[dict_idx++] = c;
113 *dest++ = c;
114 idx &= 0xfff;
115 dict_idx &= 0xfff;
116 }
117 }
118 }
119 }
120
121 // Decode parcels of ROM image (MacOS 9.X and even earlier)
122 void decode_parcels(const uint8 *src, uint8 *dest, int size)
123 {
124 uint32 parcel_offset = 0x14;
125 D(bug("Offset Type Name\n"));
126 while (parcel_offset != 0) {
127 const uint32 *parcel_data = (uint32 *)(src + parcel_offset);
128 uint32 next_offset = ntohl(parcel_data[0]);
129 uint32 parcel_type = ntohl(parcel_data[1]);
130 D(bug("%08x %c%c%c%c %s\n", parcel_offset,
131 (parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff,
132 (parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6]));
133 if (parcel_type == FOURCC('r','o','m',' ')) {
134 uint32 lzss_offset = ntohl(parcel_data[2]);
135 uint32 lzss_size = ((uintptr)src + next_offset) - ((uintptr)parcel_data + lzss_offset);
136 decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size);
137 }
138 parcel_offset = next_offset;
139 }
140 }
141
142
143 /*
144 * Decode ROM image, 4 MB plain images or NewWorld images
145 */
146
147 bool DecodeROM(uint8 *data, uint32 size)
148 {
149 if (size == ROM_SIZE) {
150 // Plain ROM image
151 memcpy(ROMBaseHost, data, ROM_SIZE);
152 return true;
153 }
154 else if (strncmp((char *)data, "<CHRP-BOOT>", 11) == 0) {
155 // CHRP compressed ROM image
156 uint32 image_offset, image_size;
157 bool decode_info_ok = false;
158
159 char *s = strstr((char *)data, "constant lzss-offset");
160 if (s != NULL) {
161 // Probably a plain LZSS compressed ROM image
162 if (sscanf(s - 7, "%06x", &image_offset) == 1) {
163 s = strstr((char *)data, "constant lzss-size");
164 if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1))
165 decode_info_ok = true;
166 }
167 }
168 else {
169 // Probably a MacOS 9.2.x ROM image
170 s = strstr((char *)data, "constant parcels-offset");
171 if (s != NULL) {
172 if (sscanf(s - 7, "%06x", &image_offset) == 1) {
173 s = strstr((char *)data, "constant parcels-size");
174 if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1))
175 decode_info_ok = true;
176 }
177 }
178 }
179
180 // No valid information to decode the ROM found?
181 if (!decode_info_ok)
182 return false;
183
184 // Check signature, this could be a parcels-based ROM image
185 uint32 rom_signature = ntohl(*(uint32 *)(data + image_offset));
186 if (rom_signature == FOURCC('p','r','c','l')) {
187 D(bug("Offset of parcels data: %08x\n", image_offset));
188 D(bug("Size of parcels data: %08x\n", image_size));
189 decode_parcels(data + image_offset, ROMBaseHost, image_size);
190 }
191 else {
192 D(bug("Offset of compressed data: %08x\n", image_offset));
193 D(bug("Size of compressed data: %08x\n", image_size));
194 decode_lzss(data + image_offset, ROMBaseHost, image_size);
195 }
196 return true;
197 }
198 return false;
199 }
200
201
202 /*
203 * Search ROM for byte string, return ROM offset (or 0)
204 */
205
206 static uint32 find_rom_data(uint32 start, uint32 end, const uint8 *data, uint32 data_len)
207 {
208 uint32 ofs = start;
209 while (ofs < end) {
210 if (!memcmp(ROMBaseHost + ofs, data, data_len))
211 return ofs;
212 ofs++;
213 }
214 return 0;
215 }
216
217
218 /*
219 * Search ROM resource by type/ID, return ROM offset of resource data
220 */
221
222 static uint32 rsrc_ptr = 0;
223
224 // id = 4711 means "find any ID"
225 static uint32 find_rom_resource(uint32 s_type, int16 s_id = 4711, bool cont = false)
226 {
227 uint32 lp = ROMBase + 0x1a;
228 uint32 x = ReadMacInt32(lp);
229 uint32 header_size = ReadMacInt8(ROMBase + x + 5);
230
231 if (!cont)
232 rsrc_ptr = x;
233 else if (rsrc_ptr == 0)
234 return 0;
235
236 for (;;) {
237 lp = ROMBase + rsrc_ptr;
238 rsrc_ptr = ReadMacInt32(lp);
239 if (rsrc_ptr == 0)
240 break;
241
242 rsrc_ptr += header_size;
243
244 lp = ROMBase + rsrc_ptr + 4;
245 uint32 data = ReadMacInt32(lp);
246 uint32 type = ReadMacInt32(lp + 4);
247 int16 id = ReadMacInt16(lp + 8);
248 if (type == s_type && (id == s_id || s_id == 4711))
249 return data;
250 }
251 return 0;
252 }
253
254
255 /*
256 * Search offset of A-Trap routine in ROM
257 */
258
259 static uint32 find_rom_trap(uint16 trap)
260 {
261 uint32 lp = ROMBase + ReadMacInt32(ROMBase + 0x22);
262
263 if (trap > 0xa800)
264 return ReadMacInt32(lp + 4 * (trap & 0x3ff));
265 else
266 return ReadMacInt32(lp + 4 * ((trap & 0xff) + 0x400));
267 }
268
269
270 /*
271 * Return target of branch instruction specified at ADDR, or 0 if
272 * there is no such instruction
273 */
274
275 static uint32 rom_powerpc_branch_target(uint32 addr)
276 {
277 uint32 opcode = ntohl(*(uint32 *)(ROMBaseHost + addr));
278 uint32 primop = opcode >> 26;
279 uint32 target = 0;
280
281 if (primop == 18) { // Branch
282 target = opcode & 0x3fffffc;
283 if (target & 0x2000000)
284 target |= 0xfc000000;
285 if ((opcode & 2) == 0)
286 target += addr;
287 }
288 else if (primop == 16) { // Branch Conditional
289 target = (int32)(int16)(opcode & 0xfffc);
290 if ((opcode & 2) == 0)
291 target += addr;
292 }
293 return target;
294 }
295
296
297 /*
298 * Search ROM for instruction branching to target address, return 0 if none found
299 */
300
301 static uint32 find_rom_powerpc_branch(uint32 start, uint32 end, uint32 target)
302 {
303 for (uint32 addr = start; addr < end; addr += 4) {
304 if (rom_powerpc_branch_target(addr) == target)
305 return addr;
306 }
307 return 0;
308 }
309
310
311 /*
312 * Check that requested ROM patch space is really available
313 */
314
315 static bool check_rom_patch_space(uint32 base, uint32 size)
316 {
317 size = (size + 3) & -4;
318 for (int i = 0; i < size; i += 4) {
319 uint32 x = ntohl(*(uint32 *)(ROMBaseHost + base + i));
320 if (x != 0x6b636b63 && x != 0)
321 return false;
322 }
323 return true;
324 }
325
326
327 /*
328 * List of audio sifters installed in ROM and System file
329 */
330
331 struct sift_entry {
332 uint32 type;
333 int16 id;
334 };
335 static sift_entry sifter_list[32];
336 static int num_sifters;
337
338 void AddSifter(uint32 type, int16 id)
339 {
340 if (FindSifter(type, id))
341 return;
342 D(bug(" adding sifter type %c%c%c%c (%08x), id %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, id));
343 sifter_list[num_sifters].type = type;
344 sifter_list[num_sifters].id = id;
345 num_sifters++;
346 }
347
348 bool FindSifter(uint32 type, int16 id)
349 {
350 for (int i=0; i<num_sifters; i++) {
351 if (sifter_list[i].type == type && sifter_list[i].id == id)
352 return true;
353 }
354 return false;
355 }
356
357
358 /*
359 * Driver stubs
360 */
361
362 static const uint8 sony_driver[] = { // Replacement for .Sony driver
363 // Driver header
364 SonyDriverFlags >> 8, SonyDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
365 0x00, 0x18, // Open() offset
366 0x00, 0x1c, // Prime() offset
367 0x00, 0x20, // Control() offset
368 0x00, 0x2c, // Status() offset
369 0x00, 0x52, // Close() offset
370 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79, // ".Sony"
371
372 // Open()
373 M68K_EMUL_OP_SONY_OPEN >> 8, M68K_EMUL_OP_SONY_OPEN & 0xff,
374 0x4e, 0x75, // rts
375
376 // Prime()
377 M68K_EMUL_OP_SONY_PRIME >> 8, M68K_EMUL_OP_SONY_PRIME & 0xff,
378 0x60, 0x0e, // bra IOReturn
379
380 // Control()
381 M68K_EMUL_OP_SONY_CONTROL >> 8, M68K_EMUL_OP_SONY_CONTROL & 0xff,
382 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
383 0x66, 0x04, // bne IOReturn
384 0x4e, 0x75, // rts
385
386 // Status()
387 M68K_EMUL_OP_SONY_STATUS >> 8, M68K_EMUL_OP_SONY_STATUS & 0xff,
388
389 // IOReturn
390 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
391 0x08, 0x01, 0x00, 0x09, // btst #9,d1
392 0x67, 0x0c, // beq 1
393 0x4a, 0x40, // tst.w d0
394 0x6f, 0x02, // ble 2
395 0x42, 0x40, // clr.w d0
396 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
397 0x4e, 0x75, // rts
398 0x4a, 0x40, //1 tst.w d0
399 0x6f, 0x04, // ble 3
400 0x42, 0x40, // clr.w d0
401 0x4e, 0x75, // rts
402 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
403 0x4e, 0x75, // rts
404
405 // Close()
406 0x70, 0xe8, // moveq #-24,d0
407 0x4e, 0x75 // rts
408 };
409
410 static const uint8 disk_driver[] = { // Generic disk driver
411 // Driver header
412 DiskDriverFlags >> 8, DiskDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
413 0x00, 0x18, // Open() offset
414 0x00, 0x1c, // Prime() offset
415 0x00, 0x20, // Control() offset
416 0x00, 0x2c, // Status() offset
417 0x00, 0x52, // Close() offset
418 0x05, 0x2e, 0x44, 0x69, 0x73, 0x6b, // ".Disk"
419
420 // Open()
421 M68K_EMUL_OP_DISK_OPEN >> 8, M68K_EMUL_OP_DISK_OPEN & 0xff,
422 0x4e, 0x75, // rts
423
424 // Prime()
425 M68K_EMUL_OP_DISK_PRIME >> 8, M68K_EMUL_OP_DISK_PRIME & 0xff,
426 0x60, 0x0e, // bra IOReturn
427
428 // Control()
429 M68K_EMUL_OP_DISK_CONTROL >> 8, M68K_EMUL_OP_DISK_CONTROL & 0xff,
430 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
431 0x66, 0x04, // bne IOReturn
432 0x4e, 0x75, // rts
433
434 // Status()
435 M68K_EMUL_OP_DISK_STATUS >> 8, M68K_EMUL_OP_DISK_STATUS & 0xff,
436
437 // IOReturn
438 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
439 0x08, 0x01, 0x00, 0x09, // btst #9,d1
440 0x67, 0x0c, // beq 1
441 0x4a, 0x40, // tst.w d0
442 0x6f, 0x02, // ble 2
443 0x42, 0x40, // clr.w d0
444 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
445 0x4e, 0x75, // rts
446 0x4a, 0x40, //1 tst.w d0
447 0x6f, 0x04, // ble 3
448 0x42, 0x40, // clr.w d0
449 0x4e, 0x75, // rts
450 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
451 0x4e, 0x75, // rts
452
453 // Close()
454 0x70, 0xe8, // moveq #-24,d0
455 0x4e, 0x75 // rts
456 };
457
458 static const uint8 cdrom_driver[] = { // CD-ROM driver
459 // Driver header
460 CDROMDriverFlags >> 8, CDROMDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
461 0x00, 0x1c, // Open() offset
462 0x00, 0x20, // Prime() offset
463 0x00, 0x24, // Control() offset
464 0x00, 0x30, // Status() offset
465 0x00, 0x56, // Close() offset
466 0x08, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x43, 0x44, 0x00, // ".AppleCD"
467
468 // Open()
469 M68K_EMUL_OP_CDROM_OPEN >> 8, M68K_EMUL_OP_CDROM_OPEN & 0xff,
470 0x4e, 0x75, // rts
471
472 // Prime()
473 M68K_EMUL_OP_CDROM_PRIME >> 8, M68K_EMUL_OP_CDROM_PRIME & 0xff,
474 0x60, 0x0e, // bra IOReturn
475
476 // Control()
477 M68K_EMUL_OP_CDROM_CONTROL >> 8, M68K_EMUL_OP_CDROM_CONTROL & 0xff,
478 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
479 0x66, 0x04, // bne IOReturn
480 0x4e, 0x75, // rts
481
482 // Status()
483 M68K_EMUL_OP_CDROM_STATUS >> 8, M68K_EMUL_OP_CDROM_STATUS & 0xff,
484
485 // IOReturn
486 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
487 0x08, 0x01, 0x00, 0x09, // btst #9,d1
488 0x67, 0x0c, // beq 1
489 0x4a, 0x40, // tst.w d0
490 0x6f, 0x02, // ble 2
491 0x42, 0x40, // clr.w d0
492 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
493 0x4e, 0x75, // rts
494 0x4a, 0x40, //1 tst.w d0
495 0x6f, 0x04, // ble 3
496 0x42, 0x40, // clr.w d0
497 0x4e, 0x75, // rts
498 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
499 0x4e, 0x75, // rts
500
501 // Close()
502 0x70, 0xe8, // moveq #-24,d0
503 0x4e, 0x75 // rts
504 };
505
506 static uint32 long_ptr;
507
508 static void SetLongBase(uint32 addr)
509 {
510 long_ptr = addr;
511 }
512
513 static void Long(uint32 value)
514 {
515 WriteMacInt32(long_ptr, value);
516 long_ptr += 4;
517 }
518
519 static void gen_ain_driver(uintptr addr)
520 {
521 SetLongBase(addr);
522
523 // .AIn driver header
524 Long(0x4d000000); Long(0x00000000);
525 Long(0x00200040); Long(0x00600080);
526 Long(0x00a0042e); Long(0x41496e00);
527 Long(0x00000000); Long(0x00000000);
528 Long(0xaafe0700); Long(0x00000000);
529 Long(0x00000000); Long(0x00179822);
530 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING));
531 Long(0x00000000); Long(0x00000000);
532 Long(0xaafe0700); Long(0x00000000);
533 Long(0x00000000); Long(0x00179822);
534 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN));
535 Long(0x00000000); Long(0x00000000);
536 Long(0xaafe0700); Long(0x00000000);
537 Long(0x00000000); Long(0x00179822);
538 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL));
539 Long(0x00000000); Long(0x00000000);
540 Long(0xaafe0700); Long(0x00000000);
541 Long(0x00000000); Long(0x00179822);
542 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS));
543 Long(0x00000000); Long(0x00000000);
544 Long(0xaafe0700); Long(0x00000000);
545 Long(0x00000000); Long(0x00179822);
546 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING));
547 Long(0x00000000); Long(0x00000000);
548 };
549
550 static void gen_aout_driver(uintptr addr)
551 {
552 SetLongBase(addr);
553
554 // .AOut driver header
555 Long(0x4d000000); Long(0x00000000);
556 Long(0x00200040); Long(0x00600080);
557 Long(0x00a0052e); Long(0x414f7574);
558 Long(0x00000000); Long(0x00000000);
559 Long(0xaafe0700); Long(0x00000000);
560 Long(0x00000000); Long(0x00179822);
561 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN));
562 Long(0x00000000); Long(0x00000000);
563 Long(0xaafe0700); Long(0x00000000);
564 Long(0x00000000); Long(0x00179822);
565 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT));
566 Long(0x00000000); Long(0x00000000);
567 Long(0xaafe0700); Long(0x00000000);
568 Long(0x00000000); Long(0x00179822);
569 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL));
570 Long(0x00000000); Long(0x00000000);
571 Long(0xaafe0700); Long(0x00000000);
572 Long(0x00000000); Long(0x00179822);
573 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS));
574 Long(0x00000000); Long(0x00000000);
575 Long(0xaafe0700); Long(0x00000000);
576 Long(0x00000000); Long(0x00179822);
577 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE));
578 Long(0x00000000); Long(0x00000000);
579 };
580
581 static void gen_bin_driver(uintptr addr)
582 {
583 SetLongBase(addr);
584
585 // .BIn driver header
586 Long(0x4d000000); Long(0x00000000);
587 Long(0x00200040); Long(0x00600080);
588 Long(0x00a0042e); Long(0x42496e00);
589 Long(0x00000000); Long(0x00000000);
590 Long(0xaafe0700); Long(0x00000000);
591 Long(0x00000000); Long(0x00179822);
592 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING));
593 Long(0x00000000); Long(0x00000000);
594 Long(0xaafe0700); Long(0x00000000);
595 Long(0x00000000); Long(0x00179822);
596 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN));
597 Long(0x00000000); Long(0x00000000);
598 Long(0xaafe0700); Long(0x00000000);
599 Long(0x00000000); Long(0x00179822);
600 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL));
601 Long(0x00000000); Long(0x00000000);
602 Long(0xaafe0700); Long(0x00000000);
603 Long(0x00000000); Long(0x00179822);
604 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS));
605 Long(0x00000000); Long(0x00000000);
606 Long(0xaafe0700); Long(0x00000000);
607 Long(0x00000000); Long(0x00179822);
608 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING));
609 Long(0x00000000); Long(0x00000000);
610 };
611
612 static void gen_bout_driver(uintptr addr)
613 {
614 SetLongBase(addr);
615
616 // .BOut driver header
617 Long(0x4d000000); Long(0x00000000);
618 Long(0x00200040); Long(0x00600080);
619 Long(0x00a0052e); Long(0x424f7574);
620 Long(0x00000000); Long(0x00000000);
621 Long(0xaafe0700); Long(0x00000000);
622 Long(0x00000000); Long(0x00179822);
623 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN));
624 Long(0x00000000); Long(0x00000000);
625 Long(0xaafe0700); Long(0x00000000);
626 Long(0x00000000); Long(0x00179822);
627 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT));
628 Long(0x00000000); Long(0x00000000);
629 Long(0xaafe0700); Long(0x00000000);
630 Long(0x00000000); Long(0x00179822);
631 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL));
632 Long(0x00000000); Long(0x00000000);
633 Long(0xaafe0700); Long(0x00000000);
634 Long(0x00000000); Long(0x00179822);
635 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS));
636 Long(0x00000000); Long(0x00000000);
637 Long(0xaafe0700); Long(0x00000000);
638 Long(0x00000000); Long(0x00179822);
639 Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE));
640 Long(0x00000000); Long(0x00000000);
641 };
642
643 static const uint8 adbop_patch[] = { // Call ADBOp() completion procedure
644 // The completion procedure may call ADBOp() again!
645 0x40, 0xe7, // move sr,-(sp)
646 0x00, 0x7c, 0x07, 0x00, // ori #$0700,sr
647 M68K_EMUL_OP_ADBOP >> 8, M68K_EMUL_OP_ADBOP & 0xff,
648 0x48, 0xe7, 0x70, 0xf0, // movem.l d1-d3/a0-a3,-(sp)
649 0x26, 0x48, // move.l a0,a3
650 0x4a, 0xab, 0x00, 0x04, // tst.l 4(a3)
651 0x67, 0x00, 0x00, 0x18, // beq 1
652 0x20, 0x53, // move.l (a3),a0
653 0x22, 0x6b, 0x00, 0x04, // move.l 4(a3),a1
654 0x24, 0x6b, 0x00, 0x08, // move.l 8(a3),a2
655 0x26, 0x78, 0x0c, 0xf8, // move.l $cf8,a3
656 0x4e, 0x91, // jsr (a1)
657 0x70, 0x00, // moveq #0,d0
658 0x60, 0x00, 0x00, 0x04, // bra 2
659 0x70, 0xff, //1 moveq #-1,d0
660 0x4c, 0xdf, 0x0f, 0x0e, //2 movem.l (sp)+,d1-d3/a0-a3
661 0x46, 0xdf, // move (sp)+,sr
662 0x4e, 0x75 // rts
663 };
664
665
666 /*
667 * Copy PowerPC code to ROM image and reverse bytes if necessary
668 */
669
670 static inline void memcpy_powerpc_code(void *dst, const void *src, size_t len)
671 {
672 #ifdef WORDS_BIGENDIAN
673 (void)memcpy(dst, src, len);
674 #else
675 uint32 *d = (uint32 *)dst;
676 uint32 *s = (uint32 *)src;
677 for (int i = 0; i < len/4; i++)
678 d[i] = htonl(s[i]);
679 #endif
680 }
681
682
683 /*
684 * Install ROM patches (RAMBase and KernelDataAddr must be set)
685 */
686
687 bool PatchROM(void)
688 {
689 // Print ROM info
690 D(bug("Checksum: %08lx\n", ntohl(*(uint32 *)ROMBaseHost)));
691 D(bug("Version: %04x\n", ntohs(*(uint16 *)(ROMBaseHost + 8))));
692 D(bug("Sub Version: %04x\n", ntohs(*(uint16 *)(ROMBaseHost + 18))));
693 D(bug("Nanokernel ID: %s\n", (char *)ROMBaseHost + 0x30d064));
694 D(bug("Resource Map at %08lx\n", ntohl(*(uint32 *)(ROMBaseHost + 26))));
695 D(bug("Trap Tables at %08lx\n\n", ntohl(*(uint32 *)(ROMBaseHost + 34))));
696
697 // Detect ROM type
698 if (!memcmp(ROMBaseHost + 0x30d064, "Boot TNT", 8))
699 ROMType = ROMTYPE_TNT;
700 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Alchemy", 12))
701 ROMType = ROMTYPE_ALCHEMY;
702 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Zanzibar", 13))
703 ROMType = ROMTYPE_ZANZIBAR;
704 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gazelle", 12))
705 ROMType = ROMTYPE_GAZELLE;
706 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gossamer", 13))
707 ROMType = ROMTYPE_GOSSAMER;
708 else if (!memcmp(ROMBaseHost + 0x30d064, "NewWorld", 8))
709 ROMType = ROMTYPE_NEWWORLD;
710 else
711 return false;
712
713 // Check that other ROM addresses point to really free regions
714 if (!check_rom_patch_space(CHECK_LOAD_PATCH_SPACE, 0x40))
715 return false;
716 if (!check_rom_patch_space(PUT_SCRAP_PATCH_SPACE, 0x40))
717 return false;
718 if (!check_rom_patch_space(GET_SCRAP_PATCH_SPACE, 0x40))
719 return false;
720 if (!check_rom_patch_space(ADDR_MAP_PATCH_SPACE - 10 * 4, 0x100))
721 return false;
722
723 // Apply patches
724 if (!patch_nanokernel_boot()) return false;
725 if (!patch_68k_emul()) return false;
726 if (!patch_nanokernel()) return false;
727 if (!patch_68k()) return false;
728
729 #ifdef M68K_BREAK_POINT
730 // Install 68k breakpoint
731 uint16 *wp = (uint16 *)(ROMBaseHost + M68K_BREAK_POINT);
732 *wp++ = htons(M68K_EMUL_BREAK);
733 *wp = htons(M68K_EMUL_RETURN);
734 #endif
735
736 #ifdef POWERPC_BREAK_POINT
737 // Install PowerPC breakpoint
738 uint32 *lp = (uint32 *)(ROMBaseHost + POWERPC_BREAK_POINT);
739 *lp = htonl(0);
740 #endif
741
742 // Copy 68k emulator to 2MB boundary
743 memcpy(ROMBaseHost + ROM_SIZE, ROMBaseHost + (ROM_SIZE - 0x100000), 0x100000);
744 return true;
745 }
746
747
748 /*
749 * Nanokernel boot routine patches
750 */
751
752 static bool patch_nanokernel_boot(void)
753 {
754 uint32 *lp;
755 uint32 base, loc;
756
757 // ROM boot structure patches
758 lp = (uint32 *)(ROMBaseHost + 0x30d000);
759 lp[0x9c >> 2] = htonl(KernelDataAddr); // LA_InfoRecord
760 lp[0xa0 >> 2] = htonl(KernelDataAddr); // LA_KernelData
761 lp[0xa4 >> 2] = htonl(KernelDataAddr + 0x1000); // LA_EmulatorData
762 lp[0xa8 >> 2] = htonl(ROMBase + 0x480000); // LA_DispatchTable
763 lp[0xac >> 2] = htonl(ROMBase + 0x460000); // LA_EmulatorCode
764 lp[0x360 >> 2] = htonl(0); // Physical RAM base (? on NewWorld ROM, this contains -1)
765 lp[0xfd8 >> 2] = htonl(ROMBase + 0x2a); // 68k reset vector
766
767 // Skip SR/BAT/SDR init
768 loc = 0x310000;
769 if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_GOSSAMER || ROMType == ROMTYPE_NEWWORLD) {
770 lp = (uint32 *)(ROMBaseHost + loc);
771 *lp++ = htonl(POWERPC_NOP);
772 *lp = htonl(0x38000000);
773 }
774 static const uint8 sr_init_dat[] = {0x35, 0x4a, 0xff, 0xfc, 0x7d, 0x86, 0x50, 0x2e};
775 if ((base = find_rom_data(0x3101b0, 0x3105b0, sr_init_dat, sizeof(sr_init_dat))) == 0) return false;
776 D(bug("sr_init %08lx\n", base));
777 lp = (uint32 *)(ROMBaseHost + loc + 8);
778 *lp = htonl(0x48000000 | ((base - loc - 8) & 0x3fffffc)); // b ROMBase+0x3101b0
779 lp = (uint32 *)(ROMBaseHost + base);
780 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA); // lwz r1,(pointer to Kernel Data)
781 *lp++ = htonl(0x3da0dead); // lis r13,0xdead (start of kernel memory)
782 *lp++ = htonl(0x3dc00010); // lis r14,0x0010 (size of page table)
783 *lp = htonl(0x3de00010); // lis r15,0x0010 (size of kernel memory)
784
785 // Don't read PVR
786 static const uint8 pvr_read_dat[] = {0x7d, 0x9f, 0x42, 0xa6};
787 if ((base = find_rom_data(0x3103b0, 0x3108b0, pvr_read_dat, sizeof(pvr_read_dat))) == 0) return false;
788 D(bug("pvr_read %08lx\n", base));
789 lp = (uint32 *)(ROMBaseHost + base);
790 *lp = htonl(0x81800000 + XLM_PVR); // lwz r12,(theoretical PVR)
791
792 // Set CPU specific data (even if ROM doesn't have support for that CPU)
793 if (ntohl(lp[6]) != 0x2c0c0001)
794 return false;
795 uint32 ofs = ntohl(lp[7]) & 0xffff;
796 D(bug("ofs %08lx\n", ofs));
797 lp[8] = htonl((ntohl(lp[8]) & 0xffff) | 0x48000000); // beq -> b
798 loc = (ntohl(lp[8]) & 0xffff) + (uintptr)(lp+8) - (uintptr)ROMBaseHost;
799 D(bug("loc %08lx\n", loc));
800 lp = (uint32 *)(ROMBaseHost + ofs + 0x310000);
801 switch (PVR >> 16) {
802 case 1: // 601
803 lp[0] = htonl(0x1000); // Page size
804 lp[1] = htonl(0x8000); // Data cache size
805 lp[2] = htonl(0x8000); // Inst cache size
806 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
807 lp[4] = htonl(0x00010040); // Unified caches/Inst cache line size
808 lp[5] = htonl(0x00400020); // Data cache line size/Data cache block size touch
809 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
810 lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
811 lp[8] = htonl(0x01000002); // TLB total size/TLB assoc
812 break;
813 case 3: // 603
814 lp[0] = htonl(0x1000); // Page size
815 lp[1] = htonl(0x2000); // Data cache size
816 lp[2] = htonl(0x2000); // Inst cache size
817 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
818 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
819 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
820 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
821 lp[7] = htonl(0x00020002); // Inst cache assoc/Data cache assoc
822 lp[8] = htonl(0x00400002); // TLB total size/TLB assoc
823 break;
824 case 4: // 604
825 lp[0] = htonl(0x1000); // Page size
826 lp[1] = htonl(0x4000); // Data cache size
827 lp[2] = htonl(0x4000); // Inst cache size
828 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
829 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
830 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
831 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
832 lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
833 lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
834 break;
835 // case 5: // 740?
836 case 6: // 603e
837 case 7: // 603ev
838 lp[0] = htonl(0x1000); // Page size
839 lp[1] = htonl(0x4000); // Data cache size
840 lp[2] = htonl(0x4000); // Inst cache size
841 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
842 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
843 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
844 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
845 lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
846 lp[8] = htonl(0x00400002); // TLB total size/TLB assoc
847 break;
848 case 8: // 750, 750FX
849 case 0x7000:
850 lp[0] = htonl(0x1000); // Page size
851 lp[1] = htonl(0x8000); // Data cache size
852 lp[2] = htonl(0x8000); // Inst cache size
853 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
854 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
855 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
856 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
857 lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
858 lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
859 break;
860 case 9: // 604e
861 case 10: // 604ev5
862 lp[0] = htonl(0x1000); // Page size
863 lp[1] = htonl(0x8000); // Data cache size
864 lp[2] = htonl(0x8000); // Inst cache size
865 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
866 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
867 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
868 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
869 lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
870 lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
871 break;
872 // case 11: // X704?
873 case 12: // 7400, 7410, 7450, 7455, 7457
874 case 0x800c:
875 case 0x8000:
876 case 0x8001:
877 case 0x8002:
878 lp[0] = htonl(0x1000); // Page size
879 lp[1] = htonl(0x8000); // Data cache size
880 lp[2] = htonl(0x8000); // Inst cache size
881 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
882 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
883 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
884 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
885 lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
886 lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
887 break;
888 case 13: // ???
889 lp[0] = htonl(0x1000); // Page size
890 lp[1] = htonl(0x8000); // Data cache size
891 lp[2] = htonl(0x8000); // Inst cache size
892 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
893 lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
894 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
895 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
896 lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
897 lp[8] = htonl(0x01000004); // TLB total size/TLB assoc
898 break;
899 // case 50: // 821
900 // case 80: // 860
901 case 96: // ???
902 lp[0] = htonl(0x1000); // Page size
903 lp[1] = htonl(0x8000); // Data cache size
904 lp[2] = htonl(0x8000); // Inst cache size
905 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
906 lp[4] = htonl(0x00010020); // Unified caches/Inst cache line size
907 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
908 lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
909 lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
910 lp[8] = htonl(0x00800004); // TLB total size/TLB assoc
911 break;
912 case 0x39: // 970
913 lp[0] = htonl(0x1000); // Page size
914 lp[1] = htonl(0x8000); // Data cache size
915 lp[2] = htonl(0x10000); // Inst cache size
916 lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
917 lp[4] = htonl(0x00010020); // Unified caches/Inst cache line size
918 lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
919 lp[6] = htonl(0x00800080); // Inst cache block size/Data cache block size
920 lp[7] = htonl(0x00020002); // Inst cache assoc/Data cache assoc
921 lp[8] = htonl(0x02000004); // TLB total size/TLB assoc
922 break;
923 default:
924 printf("WARNING: Unknown CPU type\n");
925 break;
926 }
927
928 // Don't set SPRG3, don't test MQ
929 static const uint8 sprg3_mq_dat[] = {0x7d, 0x13, 0x43, 0xa6, 0x3d, 0x00, 0x00, 0x04, 0x7d, 0x00, 0x03, 0xa6, 0x39, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0xa6};
930 if ((base = find_rom_data(loc + 0x20, loc + 0x60, sprg3_mq_dat, sizeof(sprg3_mq_dat))) == 0) return false;
931 D(bug("sprg3/mq %08lx\n", base));
932 lp = (uint32 *)(ROMBaseHost + base);
933 lp[0] = htonl(POWERPC_NOP);
934 lp[2] = htonl(POWERPC_NOP);
935 lp[4] = htonl(POWERPC_NOP);
936
937 // Don't read MSR
938 static const uint8 msr_dat[] = {0x7d, 0xc0, 0x00, 0xa6};
939 if ((base = find_rom_data(loc + 0x40, loc + 0x80, msr_dat, sizeof(msr_dat))) == 0) return false;
940 D(bug("msr %08lx\n", base));
941 lp = (uint32 *)(ROMBaseHost + base);
942 *lp = htonl(0x39c00000); // li r14,0
943
944 // Don't write to DEC
945 lp = (uint32 *)(ROMBaseHost + loc + 0x70);
946 *lp++ = htonl(POWERPC_NOP);
947 loc = (ntohl(lp[0]) & 0xffff) + (uintptr)lp - (uintptr)ROMBaseHost;
948 D(bug("loc %08lx\n", loc));
949
950 // Don't set SPRG3
951 static const uint8 sprg3_dat[] = {0x39, 0x21, 0x03, 0x60, 0x7d, 0x33, 0x43, 0xa6, 0x39, 0x01, 0x04, 0x20};
952 if ((base = find_rom_data(0x310000, 0x314000, sprg3_dat, sizeof(sprg3_dat))) == 0) return false;
953 D(bug("sprg3 %08lx\n", base + 4));
954 lp = (uint32 *)(ROMBaseHost + base + 4);
955 *lp = htonl(POWERPC_NOP);
956
957 // Don't read PVR
958 static const uint8 pvr_read2_dat[] = {0x7e, 0xff, 0x42, 0xa6, 0x56, 0xf7, 0x84, 0x3e};
959 if ((base = find_rom_data(0x310000, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) == 0) return false;
960 D(bug("pvr_read2 %08lx\n", base));
961 lp = (uint32 *)(ROMBaseHost + base);
962 *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
963 if ((base = find_rom_data(base + 4, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) != 0) {
964 D(bug("pvr_read2 %08lx\n", base));
965 lp = (uint32 *)(ROMBaseHost + base);
966 *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
967 }
968 static const uint8 pvr_read3_dat[] = {0x7e, 0x5f, 0x42, 0xa6, 0x56, 0x52, 0x84, 0x3e};
969 if ((base = find_rom_data(0x310000, 0x320000, pvr_read3_dat, sizeof(pvr_read3_dat))) != 0) {
970 D(bug("pvr_read3 %08lx\n", base));
971 lp = (uint32 *)(ROMBaseHost + base);
972 *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR)
973 }
974 static const uint8 pvr_read4_dat[] = {0x7d, 0x3f, 0x42, 0xa6, 0x55, 0x29, 0x84, 0x3e};
975 if ((base = find_rom_data(0x310000, 0x320000, pvr_read4_dat, sizeof(pvr_read4_dat))) != 0) {
976 D(bug("pvr_read4 %08lx\n", base));
977 lp = (uint32 *)(ROMBaseHost + base);
978 *lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR)
979 }
980
981 // Don't read SDR1
982 static const uint8 sdr1_read_dat[] = {0x7d, 0x19, 0x02, 0xa6, 0x55, 0x16, 0x81, 0xde};
983 if ((base = find_rom_data(0x310000, 0x320000, sdr1_read_dat, sizeof(sdr1_read_dat))) == 0) return false;
984 D(bug("sdr1_read %08lx\n", base));
985 lp = (uint32 *)(ROMBaseHost + base);
986 *lp++ = htonl(0x3d00dead); // lis r8,0xdead (pointer to page table)
987 *lp++ = htonl(0x3ec0001f); // lis r22,0x001f (size of page table)
988 *lp = htonl(POWERPC_NOP);
989
990 // Don't clear page table, don't invalidate TLB
991 static const uint8 pgtb_clear_dat[] = {0x36, 0xd6, 0xff, 0xfc, 0x7e, 0xe8, 0xb1, 0x2e, 0x41, 0x81, 0xff, 0xf8};
992 if ((base = find_rom_data(0x310000, 0x320000, pgtb_clear_dat, sizeof(pgtb_clear_dat))) == 0) return false;
993 D(bug("pgtb_clear %08lx\n", base + 4));
994 lp = (uint32 *)(ROMBaseHost + base + 4);
995 *lp = htonl(POWERPC_NOP);
996 D(bug("tblie %08lx\n", base + 12));
997 lp = (uint32 *)(ROMBaseHost + base + 12);
998 *lp = htonl(POWERPC_NOP);
999
1000 // Don't create RAM descriptor table
1001 static const uint8 desc_create_dat[] = {0x97, 0xfd, 0x00, 0x04, 0x3b, 0xff, 0x10, 0x00, 0x4b, 0xff, 0xff, 0xdc};
1002 if ((base = find_rom_data(0x310000, 0x320000, desc_create_dat, sizeof(desc_create_dat))) == 0) return false;
1003 D(bug("desc_create %08lx\n", base))
1004 lp = (uint32 *)(ROMBaseHost + base);
1005 *lp = htonl(POWERPC_NOP);
1006
1007 // Don't load SRs and BATs
1008 static const uint8 sr_load[] = {0x7c, 0x00, 0x04, 0xac, 0x83, 0x9d, 0x00, 0x00, 0x93, 0x81, 0x05, 0xe8};
1009 if ((loc = find_rom_data(0x310000, 0x320000, sr_load, sizeof(sr_load))) == 0) return false;
1010 static const uint8 sr_load_caller[] = {0x3e, 0xd6, 0xff, 0xff, 0x41, 0x81, 0xff, 0xdc, 0xb2, 0xc8, 0x00, 0x02};
1011 if ((base = find_rom_data(0x310000, 0x320000, sr_load_caller, sizeof(sr_load_caller))) == 0) return false;
1012 if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false;
1013 D(bug("sr_load %08lx, called from %08lx\n", loc, base));
1014 lp = (uint32 *)(ROMBaseHost + base);
1015 *lp = htonl(POWERPC_NOP);
1016
1017 // Don't mess with SRs
1018 static const uint8 sr_load2_dat[] = {0x83, 0xa1, 0x05, 0xe8, 0x57, 0x7c, 0x3e, 0x78, 0x7f, 0xbd, 0xe0, 0x2e};
1019 if ((base = find_rom_data(0x310000, 0x320000, sr_load2_dat, sizeof(sr_load2_dat))) == 0) return false;
1020 D(bug("sr_load2 %08lx\n", base));
1021 lp = (uint32 *)(ROMBaseHost + base);
1022 *lp = htonl(POWERPC_BLR);
1023
1024 // Don't check performance monitor
1025 static const uint8 pm_check_dat[] = {0x7e, 0x58, 0xeb, 0xa6, 0x7e, 0x53, 0x90, 0xf8, 0x7e, 0x78, 0xea, 0xa6};
1026 if ((base = find_rom_data(0x310000, 0x320000, pm_check_dat, sizeof(pm_check_dat))) == 0) return false;
1027 D(bug("pm_check %08lx\n", base));
1028 lp = (uint32 *)(ROMBaseHost + base);
1029
1030 static const int spr_check_list[] = {
1031 952 /* mmcr0 */, 953 /* pmc1 */, 954 /* pmc2 */, 955 /* sia */,
1032 956 /* mmcr1 */, 957 /* pmc3 */, 958 /* pmc4 */, 959 /* sda */
1033 };
1034
1035 for (int i = 0; i < sizeof(spr_check_list)/sizeof(spr_check_list[0]); i++) {
1036 int spr = spr_check_list[i];
1037 uint32 mtspr = 0x7e4003a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
1038 uint32 mfspr = 0x7e6002a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
1039 for (int ofs = 0; ofs < 64; ofs++) {
1040 if (ntohl(lp[ofs]) == mtspr) {
1041 if (ntohl(lp[ofs + 2]) != mfspr)
1042 return false;
1043 D(bug(" SPR%d %08lx\n", spr, base + 4*ofs));
1044 lp[ofs] = htonl(POWERPC_NOP);
1045 lp[ofs + 2] = htonl(POWERPC_NOP);
1046 }
1047 }
1048 }
1049
1050 // Jump to 68k emulator
1051 static const uint8 jump68k_dat[] = {0x7d, 0x92, 0x43, 0xa6, 0x7d, 0x5a, 0x03, 0xa6, 0x7d, 0x7b, 0x03, 0xa6};
1052 if ((loc = find_rom_data(0x310000, 0x320000, jump68k_dat, sizeof(jump68k_dat))) == 0) return false;
1053 static const uint8 jump68k_caller_dat[] = {0x85, 0x13, 0x00, 0x08, 0x56, 0xbf, 0x50, 0x3e, 0x63, 0xff, 0x0c, 0x00};
1054 if ((base = find_rom_data(0x310000, 0x320000, jump68k_caller_dat, sizeof(jump68k_caller_dat))) == 0) return false;
1055 if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false;
1056 D(bug("jump68k %08lx, called from %08lx\n", loc, base));
1057 lp = (uint32 *)(ROMBaseHost + base);
1058 *lp++ = htonl(0x80610634); // lwz r3,0x0634(r1) (pointer to Emulator Data)
1059 *lp++ = htonl(0x8081119c); // lwz r4,0x119c(r1) (pointer to opcode table)
1060 *lp++ = htonl(0x80011184); // lwz r0,0x1184(r1) (pointer to emulator init routine)
1061 *lp++ = htonl(0x7c0903a6); // mtctr r0
1062 *lp = htonl(POWERPC_BCTR);
1063 return true;
1064 }
1065
1066
1067 /*
1068 * 68k emulator patches
1069 */
1070
1071 static bool patch_68k_emul(void)
1072 {
1073 uint32 *lp;
1074 uint32 base, loc;
1075
1076 // Overwrite twi instructions
1077 static const uint8 twi_dat[] = {0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0x0f, 0xff, 0x00, 0x02};
1078 if ((base = find_rom_data(0x36e600, 0x36ea00, twi_dat, sizeof(twi_dat))) == 0) return false;
1079 D(bug("twi %08lx\n", base));
1080 lp = (uint32 *)(ROMBaseHost + base);
1081 *lp++ = htonl(0x48000000 + 0x36f900 - base); // b 0x36f900 (Emulator start)
1082 *lp++ = htonl(0x48000000 + 0x36fa00 - base - 4); // b 0x36fa00 (Mixed mode)
1083 *lp++ = htonl(0x48000000 + 0x36fb00 - base - 8); // b 0x36fb00 (Reset/FC1E opcode)
1084 *lp++ = htonl(0x48000000 + 0x36fc00 - base - 12); // FE0A opcode
1085 *lp++ = htonl(POWERPC_ILLEGAL); // Interrupt
1086 *lp++ = htonl(0x48000000 + 0x36fd00 - base - 20); // FE0F opcode
1087 *lp++ = htonl(POWERPC_ILLEGAL);
1088 *lp++ = htonl(POWERPC_ILLEGAL);
1089 *lp++ = htonl(POWERPC_ILLEGAL);
1090 *lp++ = htonl(POWERPC_ILLEGAL);
1091 *lp++ = htonl(POWERPC_ILLEGAL);
1092 *lp++ = htonl(POWERPC_ILLEGAL);
1093 *lp++ = htonl(POWERPC_ILLEGAL);
1094 *lp++ = htonl(POWERPC_ILLEGAL);
1095 *lp++ = htonl(POWERPC_ILLEGAL);
1096 *lp = htonl(POWERPC_ILLEGAL);
1097
1098 #if EMULATED_PPC
1099 // Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes
1100 lp = (uint32 *)(ROMBaseHost + 0x380000 + (M68K_EMUL_RETURN << 3));
1101 *lp++ = htonl(POWERPC_EMUL_OP);
1102 *lp++ = htonl(0x4bf66e80); // b 0x366084
1103 *lp++ = htonl(POWERPC_EMUL_OP | 1);
1104 *lp++ = htonl(0x4bf66e78); // b 0x366084
1105 *lp++ = htonl(POWERPC_EMUL_OP | 2);
1106 *lp++ = htonl(0x4bf66e70); // b 0x366084
1107 for (int i=0; i<OP_MAX; i++) {
1108 *lp++ = htonl(POWERPC_EMUL_OP | (i + 3));
1109 *lp++ = htonl(0x4bf66e68 - i*8); // b 0x366084
1110 }
1111 #else
1112 // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes
1113 lp = (uint32 *)(ROMBaseHost + 0x380000 + (M68K_EMUL_RETURN << 3));
1114 *lp++ = htonl(0x80000000 + XLM_EMUL_RETURN_PROC); // lwz r0,XLM_EMUL_RETURN_PROC
1115 *lp++ = htonl(0x4bf705fc); // b 0x36f800
1116 *lp++ = htonl(0x80000000 + XLM_EXEC_RETURN_PROC); // lwz r0,XLM_EXEC_RETURN_PROC
1117 *lp++ = htonl(0x4bf705f4); // b 0x36f800
1118 *lp++ = htonl(0x00dead00); // Let SheepShaver crash, since
1119 *lp++ = htonl(0x00beef00); // no native opcode is available
1120 for (int i=0; i<OP_MAX; i++) {
1121 *lp++ = htonl(0x38a00000 + i); // li r5,OP_*
1122 *lp++ = htonl(0x4bf705ec - i*8); // b 0x36f808
1123 }
1124
1125 // Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP
1126 lp = (uint32 *)(ROMBaseHost + 0x36f800);
1127 *lp++ = htonl(0x7c0803a6); // mtlr r0
1128 *lp++ = htonl(0x4e800020); // blr
1129
1130 *lp++ = htonl(0x80000000 + XLM_EMUL_OP_PROC); // lwz r0,XLM_EMUL_OP_PROC
1131 *lp++ = htonl(0x7c0803a6); // mtlr r0
1132 *lp = htonl(0x4e800020); // blr
1133 #endif
1134
1135 // Extra routine for 68k emulator start
1136 lp = (uint32 *)(ROMBaseHost + 0x36f900);
1137 *lp++ = htonl(0x7c2903a6); // mtctr r1
1138 *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1139 *lp++ = htonl(0x38210001); // addi r1,r1,1
1140 *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1141 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1142 *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1143 *lp++ = htonl(0x7cc902a6); // mfctr r6
1144 *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1145 *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1146 *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1147 *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1148 *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1149 *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1150 *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1151 *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1152 *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1153 *lp++ = htonl(0x7da00026); // mfcr r13
1154 *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1155 *lp++ = htonl(0x7d8802a6); // mflr r12
1156 *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1157 *lp++ = htonl(0x814105f0); // lwz r10,0x05f0(r1)
1158 *lp++ = htonl(0x7d4803a6); // mtlr r10
1159 *lp++ = htonl(0x7d8a6378); // mr r10,r12
1160 *lp++ = htonl(0x3d600002); // lis r11,0x0002
1161 *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1162 *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1163 *lp = htonl(0x4e800020); // blr
1164
1165 // Extra routine for Mixed Mode
1166 lp = (uint32 *)(ROMBaseHost + 0x36fa00);
1167 *lp++ = htonl(0x7c2903a6); // mtctr r1
1168 *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1169 *lp++ = htonl(0x38210001); // addi r1,r1,1
1170 *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1171 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1172 *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1173 *lp++ = htonl(0x7cc902a6); // mfctr r6
1174 *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1175 *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1176 *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1177 *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1178 *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1179 *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1180 *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1181 *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1182 *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1183 *lp++ = htonl(0x7da00026); // mfcr r13
1184 *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1185 *lp++ = htonl(0x7d8802a6); // mflr r12
1186 *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1187 *lp++ = htonl(0x814105f4); // lwz r10,0x05f4(r1)
1188 *lp++ = htonl(0x7d4803a6); // mtlr r10
1189 *lp++ = htonl(0x7d8a6378); // mr r10,r12
1190 *lp++ = htonl(0x3d600002); // lis r11,0x0002
1191 *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1192 *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1193 *lp = htonl(0x4e800020); // blr
1194
1195 // Extra routine for Reset/FC1E opcode
1196 lp = (uint32 *)(ROMBaseHost + 0x36fb00);
1197 *lp++ = htonl(0x7c2903a6); // mtctr r1
1198 *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1199 *lp++ = htonl(0x38210001); // addi r1,r1,1
1200 *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1201 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1202 *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1203 *lp++ = htonl(0x7cc902a6); // mfctr r6
1204 *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1205 *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1206 *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1207 *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1208 *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1209 *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1210 *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1211 *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1212 *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1213 *lp++ = htonl(0x7da00026); // mfcr r13
1214 *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1215 *lp++ = htonl(0x7d8802a6); // mflr r12
1216 *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1217 *lp++ = htonl(0x814105f8); // lwz r10,0x05f8(r1)
1218 *lp++ = htonl(0x7d4803a6); // mtlr r10
1219 *lp++ = htonl(0x7d8a6378); // mr r10,r12
1220 *lp++ = htonl(0x3d600002); // lis r11,0x0002
1221 *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1222 *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1223 *lp = htonl(0x4e800020); // blr
1224
1225 // Extra routine for FE0A opcode (QuickDraw 3D needs this)
1226 lp = (uint32 *)(ROMBaseHost + 0x36fc00);
1227 *lp++ = htonl(0x7c2903a6); // mtctr r1
1228 *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1229 *lp++ = htonl(0x38210001); // addi r1,r1,1
1230 *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1231 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1232 *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1233 *lp++ = htonl(0x7cc902a6); // mfctr r6
1234 *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1235 *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1236 *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1237 *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1238 *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1239 *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1240 *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1241 *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1242 *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1243 *lp++ = htonl(0x7da00026); // mfcr r13
1244 *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1245 *lp++ = htonl(0x7d8802a6); // mflr r12
1246 *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1247 *lp++ = htonl(0x814105fc); // lwz r10,0x05fc(r1)
1248 *lp++ = htonl(0x7d4803a6); // mtlr r10
1249 *lp++ = htonl(0x7d8a6378); // mr r10,r12
1250 *lp++ = htonl(0x3d600002); // lis r11,0x0002
1251 *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1252 *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1253 *lp = htonl(0x4e800020); // blr
1254
1255 // Extra routine for FE0F opcode (power management)
1256 lp = (uint32 *)(ROMBaseHost + 0x36fd00);
1257 *lp++ = htonl(0x7c2903a6); // mtctr r1
1258 *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1259 *lp++ = htonl(0x38210001); // addi r1,r1,1
1260 *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1261 *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1262 *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1263 *lp++ = htonl(0x7cc902a6); // mfctr r6
1264 *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1265 *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1266 *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1267 *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1268 *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1269 *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1270 *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1271 *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1272 *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1273 *lp++ = htonl(0x7da00026); // mfcr r13
1274 *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1275 *lp++ = htonl(0x7d8802a6); // mflr r12
1276 *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1277 *lp++ = htonl(0x81410604); // lwz r10,0x0604(r1)
1278 *lp++ = htonl(0x7d4803a6); // mtlr r10
1279 *lp++ = htonl(0x7d8a6378); // mr r10,r12
1280 *lp++ = htonl(0x3d600002); // lis r11,0x0002
1281 *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1282 *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1283 *lp = htonl(0x4e800020); // blr
1284
1285 // Patch DR emulator to jump to right address when an interrupt occurs
1286 lp = (uint32 *)(ROMBaseHost + 0x370000);
1287 while (lp < (uint32 *)(ROMBaseHost + 0x380000)) {
1288 if (ntohl(*lp) == 0x4ca80020) // bclr 5,8
1289 goto dr_found;
1290 lp++;
1291 }
1292 D(bug("DR emulator patch location not found\n"));
1293 return false;
1294 dr_found:
1295 lp++;
1296 loc = (uintptr)lp - (uintptr)ROMBaseHost;
1297 if ((base = rom_powerpc_branch_target(loc)) == 0) base = loc;
1298 static const uint8 dr_ret_dat[] = {0x80, 0xbf, 0x08, 0x14, 0x53, 0x19, 0x4d, 0xac, 0x7c, 0xa8, 0x03, 0xa6};
1299 if ((base = find_rom_data(base, 0x380000, dr_ret_dat, sizeof(dr_ret_dat))) == 0) return false;
1300 D(bug("dr_ret %08lx\n", base));
1301 if (base != loc) {
1302 // OldWorld ROMs contain an absolute branch
1303 D(bug(" patching absolute branch at %08x\n", loc));
1304 *lp = htonl(0x48000000 + 0xf000 - (loc & 0xffff)); // b DR_CACHE_BASE+0x1f000
1305 lp = (uint32 *)(ROMBaseHost + 0x37f000);
1306 *lp++ = htonl(0x3c000000 + ((ROMBase + base) >> 16)); // lis r0,xxx
1307 *lp++ = htonl(0x60000000 + ((ROMBase + base) & 0xffff)); // ori r0,r0,xxx
1308 *lp++ = htonl(0x7c0803a6); // mtlr r0
1309 *lp = htonl(POWERPC_BLR); // blr
1310 }
1311 return true;
1312 }
1313
1314
1315 /*
1316 * Nanokernel patches
1317 */
1318
1319 static bool patch_nanokernel(void)
1320 {
1321 uint32 *lp;
1322 uint32 base, loc;
1323
1324 // Patch Mixed Mode trap
1325 static const uint8 virt2phys_dat[] = {0x7d, 0x1b, 0x43, 0x78, 0x3b, 0xa1, 0x03, 0x20};
1326 if ((base = find_rom_data(0x313000, 0x314000, virt2phys_dat, sizeof(virt2phys_dat))) == 0) return false;
1327 D(bug("virt2phys %08lx\n", base + 8));
1328 lp = (uint32 *)(ROMBaseHost + base + 8); // Don't translate virtual->physical
1329 lp[0] = htonl(0x7f7fdb78); // mr r31,r27
1330 lp[2] = htonl(POWERPC_NOP);
1331
1332 static const uint8 ppc_excp_tbl_dat[] = {0x39, 0x01, 0x04, 0x20, 0x7d, 0x13, 0x43, 0xa6};
1333 if ((base = find_rom_data(0x313000, 0x314000, ppc_excp_tbl_dat, sizeof(ppc_excp_tbl_dat))) == 0) return false;
1334 D(bug("ppc_excp_tbl %08lx\n", base));
1335 lp = (uint32 *)(ROMBaseHost + base); // Don't activate PPC exception table
1336 *lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE
1337 *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE
1338
1339 static const uint8 save_fpu_dat[] = {0x7d, 0x00, 0x00, 0xa6, 0x61, 0x08, 0x20, 0x00, 0x7d, 0x00, 0x01, 0x24};
1340 if ((base = find_rom_data(0x310000, 0x314000, save_fpu_dat, sizeof(save_fpu_dat))) == 0) return false;
1341 D(bug("save_fpu %08lx\n", base));
1342 lp = (uint32 *)(ROMBaseHost + base); // Don't modify MSR to turn on FPU
1343 if (ntohl(lp[4]) != 0x556b04e2) return false;
1344 loc = base;
1345 #if 1
1346 // FIXME: is that really intended?
1347 *lp++ = htonl(POWERPC_NOP);
1348 lp++;
1349 *lp++ = htonl(POWERPC_NOP);
1350 lp++;
1351 *lp = htonl(POWERPC_NOP);
1352 #else
1353 lp[0] = htonl(POWERPC_NOP);
1354 lp[1] = htonl(POWERPC_NOP);
1355 lp[2] = htonl(POWERPC_NOP);
1356 lp[3] = htonl(POWERPC_NOP);
1357 #endif
1358
1359 static const uint8 save_fpu_caller_dat[] = {0x93, 0xa6, 0x01, 0xec, 0x93, 0xc6, 0x01, 0xf4, 0x93, 0xe6, 0x01, 0xfc, 0x40};
1360 if ((base = find_rom_data(0x310000, 0x314000, save_fpu_caller_dat, sizeof(save_fpu_caller_dat))) == 0) return false;
1361 D(bug("save_fpu_caller %08lx\n", base + 12));
1362 if (rom_powerpc_branch_target(base + 12) != loc) return false;
1363 lp = (uint32 *)(ROMBaseHost + base + 12); // Always save FPU state
1364 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88
1365
1366 static const uint8 mdec_dat[] = {0x7f, 0xf6, 0x02, 0xa6, 0x2c, 0x08, 0x00, 0x00, 0x93, 0xe1, 0x06, 0x68, 0x7d, 0x16, 0x03, 0xa6};
1367 if ((base = find_rom_data(0x310000, 0x314000, mdec_dat, sizeof(mdec_dat))) == 0) return false;
1368 D(bug("mdec %08lx\n", base));
1369 lp = (uint32 *)(ROMBaseHost + base); // Don't modify DEC
1370 lp[0] = htonl(0x3be00000); // li r31,0
1371 #if 1
1372 lp[3] = htonl(POWERPC_NOP);
1373 lp[4] = htonl(POWERPC_NOP);
1374 #else
1375 lp[3] = htonl(0x39000040); // li r8,0x40
1376 lp[4] = htonl(0x990600e4); // stb r8,0xe4(r6)
1377 #endif
1378
1379 static const uint8 restore_fpu_caller_dat[] = {0x81, 0x06, 0x00, 0xf4, 0x81, 0x46, 0x00, 0xfc, 0x7d, 0x09, 0x03, 0xa6, 0x40};
1380 if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller_dat, sizeof(restore_fpu_caller_dat))) == 0) return false;
1381 D(bug("restore_fpu_caller %08lx\n", base + 12));
1382 lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state
1383 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc
1384
1385 static const uint8 m68k_excp_tbl_dat[] = {0x81, 0x21, 0x06, 0x58, 0x39, 0x01, 0x03, 0x60, 0x7d, 0x13, 0x43, 0xa6};
1386 if ((base = find_rom_data(0x310000, 0x314000, m68k_excp_tbl_dat, sizeof(m68k_excp_tbl_dat))) == 0) return false;
1387 D(bug("m68k_excp %08lx\n", base + 4));
1388 lp = (uint32 *)(ROMBaseHost + base + 4); // Don't activate 68k exception table
1389 *lp++ = htonl(0x39000000 + MODE_68K); // li r8,MODE_68K
1390 *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE
1391
1392 // Patch 68k emulator trap routine
1393 static const uint8 restore_fpu_caller2_dat[] = {0x81, 0x86, 0x00, 0x8c, 0x80, 0x66, 0x00, 0x94, 0x80, 0x86, 0x00, 0x9c, 0x40};
1394 if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller2_dat, sizeof(restore_fpu_caller2_dat))) == 0) return false;
1395 D(bug("restore_fpu_caller2 %08lx\n", base + 12));
1396 loc = rom_powerpc_branch_target(base + 12);
1397 lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state
1398 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4
1399
1400 static const uint8 restore_fpu_dat[] = {0x55, 0x68, 0x04, 0xa5, 0x4c, 0x82, 0x00, 0x20, 0x81, 0x06, 0x00, 0xe4};
1401 if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_dat, sizeof(restore_fpu_dat))) == 0) return false;
1402 D(bug("restore_fpu %08lx\n", base));
1403 if (base != loc) return false;
1404 lp = (uint32 *)(ROMBaseHost + base + 4); // Don't modify MSR to turn on FPU
1405 *lp++ = htonl(POWERPC_NOP);
1406 lp += 2;
1407 *lp++ = htonl(POWERPC_NOP);
1408 lp++;
1409 *lp++ = htonl(POWERPC_NOP);
1410 *lp++ = htonl(POWERPC_NOP);
1411 *lp = htonl(POWERPC_NOP);
1412
1413 // Disable suspend (FE0F opcode)
1414 // TODO: really suspend SheepShaver?
1415 static const uint8 suspend_dat[] = {0x7c, 0x88, 0x68, 0x39, 0x41, 0x9d};
1416 if ((base = find_rom_data(0x315000, 0x316000, suspend_dat, sizeof(suspend_dat))) == 0) return false;
1417 D(bug("suspend %08lx\n", base));
1418 lp = (uint32 *)(ROMBaseHost + base + 4);
1419 *lp = htonl((ntohl(*lp) & 0xffff) | 0x48000000); // bgt -> b
1420
1421 // Patch trap return routine
1422 static const uint8 trap_return_dat[] = {0x80, 0xc1, 0x00, 0x18, 0x80, 0x21, 0x00, 0x04, 0x4c, 0x00, 0x00, 0x64};
1423 if ((base = find_rom_data(0x312000, 0x320000, trap_return_dat, sizeof(trap_return_dat))) == 0) return false;
1424 D(bug("trap_return %08lx\n", base + 8));
1425 lp = (uint32 *)(ROMBaseHost + base + 8); // Replace rfi
1426 *lp = htonl(POWERPC_BCTR);
1427
1428 while (ntohl(*lp) != 0x7d5a03a6) lp--;
1429 *lp++ = htonl(0x7d4903a6); // mtctr r10
1430 *lp++ = htonl(0x7daff120); // mtcr r13
1431 *lp = htonl(0x48000000 + ((0x318000 - ((uintptr)lp - (uintptr)ROMBaseHost)) & 0x03fffffc)); // b ROMBase+0x318000
1432 uint32 npc = (uintptr)(lp + 1) - (uintptr)ROMBaseHost;
1433
1434 lp = (uint32 *)(ROMBaseHost + 0x318000);
1435 *lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST
1436 *lp++ = htonl(0x394affff); // subi r10,r10,1
1437 *lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST
1438 *lp = htonl(0x48000000 + ((npc - 0x31800c) & 0x03fffffc)); // b ROMBase+0x312c2c
1439
1440 // Patch FEOA opcode, selector 0x0A (virtual->physical page index)
1441 static const uint8 fe0a_0a_dat[] = {0x55, 0x23, 0xa3, 0x3e, 0x4b};
1442 if ((base = find_rom_data(0x314000, 0x318000, fe0a_0a_dat, sizeof(fe0a_0a_dat))) == 0) return false;
1443 loc = rom_powerpc_branch_target(base - 8);
1444 static const uint8 fe0a_dat[] = {0x7e, 0x04, 0x48, 0x40, 0x81, 0xe1, 0x06, 0xb0, 0x54, 0x88, 0x10, 0x3a, 0x40, 0x90};
1445 if (find_rom_data(loc, 0x318000, fe0a_dat, sizeof(fe0a_dat)) != loc) return false;
1446 D(bug("fe0a_0a %08lx\n", base - 8));
1447 lp = (uint32 *)(ROMBaseHost + base - 8);
1448 *lp++ = htonl(0x7c832378); // mr r3,r4
1449 *lp++ = htonl(POWERPC_NOP);
1450 *lp = htonl(POWERPC_NOP);
1451
1452 // Disable FE0A opcode, selector 0x11 (init page tables?)
1453 static const uint8 fe0a_11_dat[] = {0x56, 0x07, 0x06, 0x74, 0x2c, 0x07, 0x00, 0x60, 0x40};
1454 if ((base = find_rom_data(0x314000, 0x318000, fe0a_11_dat, sizeof(fe0a_11_dat))) == 0) return false;
1455 loc = rom_powerpc_branch_target(base - 4);
1456 if (find_rom_data(0x314000, 0x318000, fe0a_dat, sizeof(fe0a_dat)) != loc) return false;
1457 D(bug("fe0a_11 %08lx\n", base - 4));
1458 lp = (uint32 *)(ROMBaseHost + base - 4);
1459 *lp++ = htonl(POWERPC_NOP);
1460 *lp++ = htonl(POWERPC_NOP);
1461 *lp++ = htonl(POWERPC_NOP);
1462 *lp = htonl(ntohl(*lp) | 0x02800000); // bf => ba
1463
1464 // Patch FE0A opcode to fake a page table entry so that V=P for RAM and ROM
1465 static const uint8 pg_lookup_dat[] = {0x7e, 0x0f, 0x40, 0x6e, 0x81, 0xc1, 0x06, 0xa4, 0x7e, 0x00, 0x71, 0x20};
1466 if ((base = find_rom_data(0x310000, 0x320000, pg_lookup_dat, sizeof(pg_lookup_dat))) == 0) return false;
1467 D(bug("fe0a_pgtb_lookup %08lx\n", base - 12));
1468 lp = (uint32 *)(ROMBaseHost + base - 12);
1469 if (ntohl(lp[0]) != 0x81e106b0) // lwz r15,$06b0(r1)
1470 return false;
1471 lp[0] = htonl(0x54906026); // slwi r16,r4,12
1472 lp[3] = htonl(0x62100121); // ori r16,r16,0x121
1473
1474 // Patch FE0A opcode to not write to kernel memory
1475 static const uint8 krnl_write_dat[] = {0x38, 0xe0, 0x00, 0x01, 0x7e, 0x10, 0x38, 0x78, 0x92, 0x0f, 0x00, 0x00};
1476 if ((base = find_rom_data(0x310000, 0x320000, krnl_write_dat, sizeof(krnl_write_dat))) == 0) return false;
1477 D(bug("fe0a_krnl_write %08lx\n", base));
1478 lp = (uint32 *)(ROMBaseHost + base);
1479 lp[2] = htonl(POWERPC_NOP);
1480
1481 /*
1482 // Disable FE0A/FE06 opcodes
1483 lp = (uint32 *)(ROMBase + 0x3144ac);
1484 *lp++ = htonl(POWERPC_NOP);
1485 *lp += 8;
1486 */
1487 return true;
1488 }
1489
1490
1491 /*
1492 * 68k boot routine patches
1493 */
1494
1495 static bool patch_68k(void)
1496 {
1497 uint32 *lp;
1498 uint16 *wp;
1499 uint8 *bp;
1500 uint32 base, loc;
1501
1502 // Remove 68k RESET instruction
1503 static const uint8 reset_dat[] = {0x4e, 0x70};
1504 if ((base = find_rom_data(0xc8, 0x120, reset_dat, sizeof(reset_dat))) == 0) return false;
1505 D(bug("reset %08lx\n", base));
1506 wp = (uint16 *)(ROMBaseHost + base);
1507 *wp = htons(M68K_NOP);
1508
1509 // Fake reading PowerMac ID (via Universal)
1510 static const uint8 powermac_id_dat[] = {0x45, 0xf9, 0x5f, 0xff, 0xff, 0xfc, 0x20, 0x12, 0x72, 0x00};
1511 if ((base = find_rom_data(0xe000, 0x15000, powermac_id_dat, sizeof(powermac_id_dat))) == 0) return false;
1512 D(bug("powermac_id %08lx\n", base));
1513 wp = (uint16 *)(ROMBaseHost + base);
1514 *wp++ = htons(0x203c); // move.l #id,d0
1515 *wp++ = htons(0);
1516 // if (ROMType == ROMTYPE_NEWWORLD)
1517 // *wp++ = htons(0x3035); // (PowerMac 9500 ID)
1518 // else
1519 *wp++ = htons(0x3020); // (PowerMac 9500 ID)
1520 *wp++ = htons(0xb040); // cmp.w d0,d0
1521 *wp = htons(0x4ed6); // jmp (a6)
1522
1523 // Patch UniversalInfo
1524 if (ROMType == ROMTYPE_NEWWORLD) {
1525 static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00};
1526 if ((base = find_rom_data(0x14000, 0x18000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false;
1527 D(bug("universal_info %08lx\n", base));
1528 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1529 lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14));
1530 lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo
1531 lp[0x14 >> 2] = htonl(0x3fff0401);
1532 lp[0x18 >> 2] = htonl(0x0300001c);
1533 lp[0x1c >> 2] = htonl(0x000108c4);
1534 lp[0x24 >> 2] = htonl(0xc301bf26);
1535 lp[0x28 >> 2] = htonl(0x00000861);
1536 lp[0x58 >> 2] = htonl(0x30200000);
1537 lp[0x60 >> 2] = htonl(0x0000003d);
1538 } else if (ROMType == ROMTYPE_ZANZIBAR) {
1539 base = 0x12b70;
1540 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1541 lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14));
1542 lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo
1543 lp[0x14 >> 2] = htonl(0x3fff0401);
1544 lp[0x18 >> 2] = htonl(0x0300001c);
1545 lp[0x1c >> 2] = htonl(0x000108c4);
1546 lp[0x24 >> 2] = htonl(0xc301bf26);
1547 lp[0x28 >> 2] = htonl(0x00000861);
1548 lp[0x58 >> 2] = htonl(0x30200000);
1549 lp[0x60 >> 2] = htonl(0x0000003d);
1550 } else if (ROMType == ROMTYPE_GOSSAMER) {
1551 base = 0x12d20;
1552 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1553 lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14));
1554 lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo
1555 lp[0x14 >> 2] = htonl(0x3fff0401);
1556 lp[0x18 >> 2] = htonl(0x0300001c);
1557 lp[0x1c >> 2] = htonl(0x000108c4);
1558 lp[0x24 >> 2] = htonl(0xc301bf26);
1559 lp[0x28 >> 2] = htonl(0x00000861);
1560 lp[0x58 >> 2] = htonl(0x30410000);
1561 lp[0x60 >> 2] = htonl(0x0000003d);
1562 }
1563
1564 // Construct AddrMap for NewWorld ROM
1565 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) {
1566 lp = (uint32 *)(ROMBaseHost + ADDR_MAP_PATCH_SPACE);
1567 memset(lp - 10, 0, 0x128);
1568 lp[-10] = htonl(0x0300001c);
1569 lp[-9] = htonl(0x000108c4);
1570 lp[-4] = htonl(0x00300000);
1571 lp[-2] = htonl(0x11010000);
1572 lp[-1] = htonl(0xf8000000);
1573 lp[0] = htonl(0xffc00000);
1574 lp[2] = htonl(0xf3016000);
1575 lp[3] = htonl(0xf3012000);
1576 lp[4] = htonl(0xf3012000);
1577 lp[24] = htonl(0xf3018000);
1578 lp[25] = htonl(0xf3010000);
1579 lp[34] = htonl(0xf3011000);
1580 lp[38] = htonl(0xf3015000);
1581 lp[39] = htonl(0xf3014000);
1582 lp[43] = htonl(0xf3000000);
1583 lp[48] = htonl(0xf8000000);
1584 }
1585
1586 // Don't initialize VIA (via Universal)
1587 static const uint8 via_init_dat[] = {0x08, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x2c, 0x24, 0x68, 0x00, 0x08};
1588 if ((base = find_rom_data(0xe000, 0x15000, via_init_dat, sizeof(via_init_dat))) == 0) return false;
1589 D(bug("via_init %08lx\n", base));
1590 wp = (uint16 *)(ROMBaseHost + base + 4);
1591 *wp = htons(0x6000); // bra
1592
1593 static const uint8 via_init2_dat[] = {0x24, 0x68, 0x00, 0x08, 0x00, 0x12, 0x00, 0x30, 0x4e, 0x71};
1594 if ((base = find_rom_data(0xa000, 0x10000, via_init2_dat, sizeof(via_init2_dat))) == 0) return false;
1595 D(bug("via_init2 %08lx\n", base));
1596 wp = (uint16 *)(ROMBaseHost + base);
1597 *wp = htons(0x4ed6); // jmp (a6)
1598
1599 static const uint8 via_init3_dat[] = {0x22, 0x68, 0x00, 0x08, 0x28, 0x3c, 0x20, 0x00, 0x01, 0x00};
1600 if ((base = find_rom_data(0xa000, 0x10000, via_init3_dat, sizeof(via_init3_dat))) == 0) return false;
1601 D(bug("via_init3 %08lx\n", base));
1602 wp = (uint16 *)(ROMBaseHost + base);
1603 *wp = htons(0x4ed6); // jmp (a6)
1604
1605 // Don't RunDiags, get BootGlobs pointer directly
1606 if (ROMType == ROMTYPE_NEWWORLD) {
1607 static const uint8 run_diags_dat[] = {0x60, 0xff, 0x00, 0x0c};
1608 if ((base = find_rom_data(0x110, 0x128, run_diags_dat, sizeof(run_diags_dat))) == 0) return false;
1609 D(bug("run_diags %08lx\n", base));
1610 wp = (uint16 *)(ROMBaseHost + base);
1611 *wp++ = htons(0x4df9); // lea xxx,a6
1612 *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16);
1613 *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff);
1614 } else {
1615 static const uint8 run_diags_dat[] = {0x74, 0x00, 0x2f, 0x0e};
1616 if ((base = find_rom_data(0xd0, 0xf0, run_diags_dat, sizeof(run_diags_dat))) == 0) return false;
1617 D(bug("run_diags %08lx\n", base));
1618 wp = (uint16 *)(ROMBaseHost + base - 6);
1619 *wp++ = htons(0x4df9); // lea xxx,a6
1620 *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16);
1621 *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff);
1622 }
1623
1624 // Replace NVRAM routines
1625 static const uint8 nvram1_dat[] = {0x48, 0xe7, 0x01, 0x0e, 0x24, 0x68, 0x00, 0x08, 0x08, 0x83, 0x00, 0x1f};
1626 if ((base = find_rom_data(0x7000, 0xc000, nvram1_dat, sizeof(nvram1_dat))) == 0) return false;
1627 D(bug("nvram1 %08lx\n", base));
1628 wp = (uint16 *)(ROMBaseHost + base);
1629 *wp++ = htons(M68K_EMUL_OP_XPRAM1);
1630 *wp = htons(M68K_RTS);
1631
1632 if (ROMType == ROMTYPE_NEWWORLD) {
1633 static const uint8 nvram2_dat[] = {0x48, 0xe7, 0x1c, 0xe0, 0x4f, 0xef, 0xff, 0xb4};
1634 if ((base = find_rom_data(0xa000, 0xd000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false;
1635 D(bug("nvram2 %08lx\n", base));
1636 wp = (uint16 *)(ROMBaseHost + base);
1637 *wp++ = htons(M68K_EMUL_OP_XPRAM2);
1638 *wp = htons(0x4ed3); // jmp (a3)
1639
1640 static const uint8 nvram3_dat[] = {0x48, 0xe7, 0xdc, 0xe0, 0x4f, 0xef, 0xff, 0xb4};
1641 if ((base = find_rom_data(0xa000, 0xd000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false;
1642 D(bug("nvram3 %08lx\n", base));
1643 wp = (uint16 *)(ROMBaseHost + base);
1644 *wp++ = htons(M68K_EMUL_OP_XPRAM3);
1645 *wp = htons(0x4ed3); // jmp (a3)
1646
1647 static const uint8 nvram4_dat[] = {0x4e, 0x56, 0xff, 0xa8, 0x48, 0xe7, 0x1f, 0x38, 0x16, 0x2e, 0x00, 0x13};
1648 if ((base = find_rom_data(0xa000, 0xd000, nvram4_dat, sizeof(nvram4_dat))) == 0) return false;
1649 D(bug("nvram4 %08lx\n", base));
1650 wp = (uint16 *)(ROMBaseHost + base + 16);
1651 *wp++ = htons(0x1a2e); // move.b ($000f,a6),d5
1652 *wp++ = htons(0x000f);
1653 *wp++ = htons(M68K_EMUL_OP_NVRAM3);
1654 *wp++ = htons(0x4cee); // movem.l ($ff88,a6),d3-d7/a2-a4
1655 *wp++ = htons(0x1cf8);
1656 *wp++ = htons(0xff88);
1657 *wp++ = htons(0x4e5e); // unlk a6
1658 *wp = htons(M68K_RTS);
1659
1660 static const uint8 nvram5_dat[] = {0x0c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0a, 0x70, 0x00, 0x21, 0xf8, 0x02, 0x0c, 0x01, 0xe4};
1661 if ((base = find_rom_data(0xa000, 0xd000, nvram5_dat, sizeof(nvram5_dat))) == 0) return false;
1662 D(bug("nvram5 %08lx\n", base));
1663 wp = (uint16 *)(ROMBaseHost + base + 6);
1664 *wp = htons(M68K_NOP);
1665
1666 static const uint8 nvram6_dat[] = {0x2f, 0x0a, 0x24, 0x48, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f};
1667 if ((base = find_rom_data(0x9000, 0xb000, nvram6_dat, sizeof(nvram6_dat))) == 0) return false;
1668 D(bug("nvram6 %08lx\n", base));
1669 wp = (uint16 *)(ROMBaseHost + base);
1670 *wp++ = htons(0x7000); // moveq #0,d0
1671 *wp++ = htons(0x2080); // move.l d0,(a0)
1672 *wp++ = htons(0x4228); // clr.b 4(a0)
1673 *wp++ = htons(0x0004);
1674 *wp = htons(M68K_RTS);
1675
1676 static const uint8 nvram7_dat[] = {0x42, 0x2a, 0x00, 0x04, 0x4f, 0xef, 0x00, 0x60, 0x24, 0x5f, 0x4e, 0x75, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f};
1677 base = find_rom_data(0x9000, 0xb000, nvram7_dat, sizeof(nvram7_dat));
1678 if (base) {
1679 D(bug("nvram7 %08lx\n", base));
1680 wp = (uint16 *)(ROMBaseHost + base + 12);
1681 *wp = htons(M68K_RTS);
1682 }
1683 } else {
1684 static const uint8 nvram2_dat[] = {0x4e, 0xd6, 0x06, 0x41, 0x13, 0x00};
1685 if ((base = find_rom_data(0x7000, 0xb000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false;
1686 D(bug("nvram2 %08lx\n", base));
1687 wp = (uint16 *)(ROMBaseHost + base + 2);
1688 *wp++ = htons(M68K_EMUL_OP_XPRAM2);
1689 *wp = htons(0x4ed3); // jmp (a3)
1690
1691 static const uint8 nvram3_dat[] = {0x4e, 0xd3, 0x06, 0x41, 0x13, 0x00};
1692 if ((base = find_rom_data(0x7000, 0xb000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false;
1693 D(bug("nvram3 %08lx\n", base));
1694 wp = (uint16 *)(ROMBaseHost + base + 2);
1695 *wp++ = htons(M68K_EMUL_OP_XPRAM3);
1696 *wp = htons(0x4ed3); // jmp (a3)
1697
1698 static const uint32 nvram4_loc[] = {0x582f0, 0xa0a0, 0x7e50, 0xa1d0, 0x538d0, 0};
1699 wp = (uint16 *)(ROMBaseHost + nvram4_loc[ROMType]);
1700 *wp++ = htons(0x202f); // move.l 4(sp),d0
1701 *wp++ = htons(0x0004);
1702 *wp++ = htons(M68K_EMUL_OP_NVRAM1);
1703 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE)
1704 *wp = htons(M68K_RTS);
1705 else {
1706 *wp++ = htons(0x1f40); // move.b d0,8(sp)
1707 *wp++ = htons(0x0008);
1708 *wp++ = htons(0x4e74); // rtd #4
1709 *wp = htons(0x0004);
1710 }
1711
1712 static const uint32 nvram5_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0x53a20, 0};
1713 wp = (uint16 *)(ROMBaseHost + nvram5_loc[ROMType]);
1714 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) {
1715 *wp++ = htons(0x202f); // move.l 4(sp),d0
1716 *wp++ = htons(0x0004);
1717 *wp++ = htons(0x122f); // move.b 11(sp),d1
1718 *wp++ = htons(0x000b);
1719 *wp++ = htons(M68K_EMUL_OP_NVRAM2);
1720 *wp = htons(M68K_RTS);
1721 } else {
1722 *wp++ = htons(0x202f); // move.l 6(sp),d0
1723 *wp++ = htons(0x0006);
1724 *wp++ = htons(0x122f); // move.b 4(sp),d1
1725 *wp++ = htons(0x0004);
1726 *wp++ = htons(M68K_EMUL_OP_NVRAM2);
1727 *wp++ = htons(0x4e74); // rtd #6
1728 *wp = htons(0x0006);
1729 }
1730 }
1731
1732 // Fix MemTop/BootGlobs during system startup
1733 static const uint8 mem_top_dat[] = {0x2c, 0x6c, 0xff, 0xec, 0x2a, 0x4c, 0xdb, 0xec, 0xff, 0xf4};
1734 if ((base = find_rom_data(0x120, 0x180, mem_top_dat, sizeof(mem_top_dat))) == 0) return false;
1735 D(bug("mem_top %08lx\n", base));
1736 wp = (uint16 *)(ROMBaseHost + base);
1737 *wp++ = htons(M68K_EMUL_OP_FIX_MEMTOP);
1738 *wp = htons(M68K_NOP);
1739
1740 // Don't initialize SCC (via 0x1ac)
1741 static const uint8 scc_init_caller_dat[] = {0x21, 0xce, 0x01, 0x08, 0x22, 0x78, 0x0d, 0xd8};
1742 if ((base = find_rom_data(0x180, 0x1f0, scc_init_caller_dat, sizeof(scc_init_caller_dat))) == 0) return false;
1743 D(bug("scc_init_caller %08lx\n", base + 12));
1744 wp = (uint16 *)(ROMBaseHost + base + 12);
1745 loc = ntohs(wp[1]) + ((uintptr)wp - (uintptr)ROMBaseHost) + 2;
1746 static const uint8 scc_init_dat[] = {0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8};
1747 if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) == 0) return false;
1748 D(bug("scc_init %08lx\n", base));
1749 wp = (uint16 *)(ROMBaseHost + base);
1750 *wp++ = htons(M68K_EMUL_OP_RESET);
1751 *wp = htons(M68K_RTS);
1752
1753 // Don't EnableExtCache (via 0x1f6) and don't DisableIntSources(via 0x1fc)
1754 static const uint8 ext_cache_dat[] = {0x4e, 0x7b, 0x00, 0x02};
1755 if ((base = find_rom_data(0x1d0, 0x230, ext_cache_dat, sizeof(ext_cache_dat))) == 0) return false;
1756 D(bug("ext_cache %08lx\n", base));
1757 loc = ReadMacInt32(ROMBase + base + 6);
1758 wp = (uint16 *)(ROMBaseHost + loc + base + 6);
1759 *wp = htons(M68K_RTS);
1760 loc = ReadMacInt32(ROMBase + base + 12);
1761 wp = (uint16 *)(ROMBaseHost + loc + base + 12);
1762 *wp = htons(M68K_RTS);
1763
1764 // Fake CPU speed test (SetupTimeK)
1765 static const uint8 timek_dat[] = {0x0c, 0x38, 0x00, 0x04, 0x01, 0x2f, 0x6d, 0x3c};
1766 if ((base = find_rom_data(0x400, 0x500, timek_dat, sizeof(timek_dat))) == 0) return false;
1767 D(bug("timek %08lx\n", base));
1768 wp = (uint16 *)(ROMBaseHost + base);
1769 *wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA
1770 *wp++ = htons(100);
1771 *wp++ = htons(0x0d00);
1772 *wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA
1773 *wp++ = htons(100);
1774 *wp++ = htons(0x0d02);
1775 *wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA
1776 *wp++ = htons(100);
1777 *wp++ = htons(0x0b24);
1778 *wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA
1779 *wp++ = htons(100);
1780 *wp++ = htons(0x0cea);
1781 *wp = htons(M68K_RTS);
1782
1783 // Relocate jump tables ($2000..)
1784 static const uint8 jump_tab_dat[] = {0x41, 0xfa, 0x00, 0x0e, 0x21, 0xc8, 0x20, 0x10, 0x4e, 0x75};
1785 if ((base = find_rom_data(0x3000, 0x6000, jump_tab_dat, sizeof(jump_tab_dat))) == 0) return false;
1786 D(bug("jump_tab %08lx\n", base));
1787 lp = (uint32 *)(ROMBaseHost + base + 16);
1788 for (;;) {
1789 D(bug(" %08lx\n", (uintptr)lp - (uintptr)ROMBaseHost));
1790 while ((ntohl(*lp) & 0xff000000) == 0xff000000) {
1791 *lp = htonl((ntohl(*lp) & (ROM_SIZE-1)) + ROMBase);
1792 lp++;
1793 }
1794 while (!ntohl(*lp)) lp++;
1795 if (ntohl(*lp) != 0x41fa000e)
1796 break;
1797 lp += 4;
1798 }
1799
1800 // Create SysZone at start of Mac RAM (SetSysAppZone, via 0x22a)
1801 static const uint8 sys_zone_dat[] = {0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x00};
1802 if ((base = find_rom_data(0x600, 0x900, sys_zone_dat, sizeof(sys_zone_dat))) == 0) return false;
1803 D(bug("sys_zone %08lx\n", base));
1804 lp = (uint32 *)(ROMBaseHost + base);
1805 *lp++ = htonl(RAMBase ? RAMBase : 0x3000);
1806 *lp = htonl(RAMBase ? RAMBase + 0x1800 : 0x4800);
1807
1808 // Set boot stack at RAMBase+4MB and fix logical/physical RAM size (CompBootStack)
1809 // The RAM size fix must be done after InitMemMgr!
1810 static const uint8 boot_stack_dat[] = {0x08, 0x38, 0x00, 0x06, 0x24, 0x0b};
1811 if ((base = find_rom_data(0x580, 0x800, boot_stack_dat, sizeof(boot_stack_dat))) == 0) return false;
1812 D(bug("boot_stack %08lx\n", base));
1813 wp = (uint16 *)(ROMBaseHost + base);
1814 *wp++ = htons(0x207c); // move.l #RAMBase+0x3ffffe,a0
1815 *wp++ = htons((RAMBase + 0x3ffffe) >> 16);
1816 *wp++ = htons((RAMBase + 0x3ffffe) & 0xffff);
1817 *wp++ = htons(M68K_EMUL_OP_FIX_MEMSIZE);
1818 *wp = htons(M68K_RTS);
1819
1820 // Get PowerPC page size (InitVMemMgr, via 0x240)
1821 static const uint8 page_size_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x10};
1822 if ((base = find_rom_data(0xb000, 0x12000, page_size_dat, sizeof(page_size_dat))) == 0) return false;
1823 D(bug("page_size %08lx\n", base));
1824 wp = (uint16 *)(ROMBaseHost + base);
1825 *wp++ = htons(0x203c); // move.l #$1000,d0
1826 *wp++ = htons(0);
1827 *wp++ = htons(0x1000);
1828 *wp++ = htons(M68K_NOP);
1829 *wp = htons(M68K_NOP);
1830
1831 // Gestalt PowerPC page size, CPU type, RAM size (InitGestalt, via 0x25c)
1832 static const uint8 page_size2_dat[] = {0x26, 0x79, 0x5f, 0xff, 0xef, 0xd8, 0x25, 0x6b, 0x00, 0x10, 0x00, 0x1e};
1833 if ((base = find_rom_data(0x50000, 0x70000, page_size2_dat, sizeof(page_size2_dat))) == 0) return false;
1834 D(bug("page_size2 %08lx\n", base));
1835 wp = (uint16 *)(ROMBaseHost + base);
1836 *wp++ = htons(0x257c); // move.l #$1000,$1e(a2)
1837 *wp++ = htons(0);
1838 *wp++ = htons(0x1000);
1839 *wp++ = htons(0x001e);
1840 *wp++ = htons(0x157c); // move.b #PVR,$1d(a2)
1841 uint32 cput = (PVR >> 16);
1842 if (cput == 0x7000)
1843 cput |= 0x20;
1844 else if (cput >= 0x8000 && cput <= 0x8002)
1845 cput |= 0x10;
1846 cput &= 0xff;
1847 *wp++ = htons(cput);
1848 *wp++ = htons(0x001d);
1849 *wp++ = htons(0x263c); // move.l #RAMSize,d3
1850 *wp++ = htons(RAMSize >> 16);
1851 *wp++ = htons(RAMSize & 0xffff);
1852 *wp++ = htons(M68K_NOP);
1853 *wp++ = htons(M68K_NOP);
1854 *wp = htons(M68K_NOP);
1855 if (ROMType == ROMTYPE_NEWWORLD)
1856 wp = (uint16 *)(ROMBaseHost + base + 0x4a);
1857 else
1858 wp = (uint16 *)(ROMBaseHost + base + 0x28);
1859 *wp++ = htons(M68K_NOP);
1860 *wp = htons(M68K_NOP);
1861
1862 // Gestalt CPU/bus clock speed (InitGestalt, via 0x25c)
1863 if (ROMType == ROMTYPE_ZANZIBAR) {
1864 wp = (uint16 *)(ROMBaseHost + 0x5d87a);
1865 *wp++ = htons(0x203c); // move.l #Hz,d0
1866 *wp++ = htons(BusClockSpeed >> 16);
1867 *wp++ = htons(BusClockSpeed & 0xffff);
1868 *wp++ = htons(M68K_NOP);
1869 *wp = htons(M68K_NOP);
1870 wp = (uint16 *)(ROMBaseHost + 0x5d888);
1871 *wp++ = htons(0x203c); // move.l #Hz,d0
1872 *wp++ = htons(CPUClockSpeed >> 16);
1873 *wp++ = htons(CPUClockSpeed & 0xffff);
1874 *wp++ = htons(M68K_NOP);
1875 *wp = htons(M68K_NOP);
1876 }
1877
1878 // Don't write to GC interrupt mask register (via 0x262)
1879 if (ROMType != ROMTYPE_NEWWORLD) {
1880 static const uint8 gc_mask_dat[] = {0x83, 0xa8, 0x00, 0x24, 0x4e, 0x71};
1881 if ((base = find_rom_data(0x13000, 0x20000, gc_mask_dat, sizeof(gc_mask_dat))) == 0) return false;
1882 D(bug("gc_mask %08lx\n", base));
1883 wp = (uint16 *)(ROMBaseHost + base);
1884 *wp++ = htons(M68K_NOP);
1885 *wp = htons(M68K_NOP);
1886 wp = (uint16 *)(ROMBaseHost + base + 0x40);
1887 *wp++ = htons(M68K_NOP);
1888 *wp = htons(M68K_NOP);
1889 wp = (uint16 *)(ROMBaseHost + base + 0x78);
1890 *wp++ = htons(M68K_NOP);
1891 *wp = htons(M68K_NOP);
1892 wp = (uint16 *)(ROMBaseHost + base + 0x96);
1893 *wp++ = htons(M68K_NOP);
1894 *wp = htons(M68K_NOP);
1895
1896 static const uint8 gc_mask2_dat[] = {0x02, 0xa8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x24};
1897 if ((base = find_rom_data(0x13000, 0x20000, gc_mask2_dat, sizeof(gc_mask2_dat))) == 0) return false;
1898 D(bug("gc_mask2 %08lx\n", base));
1899 wp = (uint16 *)(ROMBaseHost + base);
1900 if (ROMType == ROMTYPE_GOSSAMER) {
1901 *wp++ = htons(M68K_NOP);
1902 *wp++ = htons(M68K_NOP);
1903 *wp++ = htons(M68K_NOP);
1904 *wp++ = htons(M68K_NOP);
1905 }
1906 for (int i=0; i<5; i++) {
1907 *wp++ = htons(M68K_NOP);
1908 *wp++ = htons(M68K_NOP);
1909 *wp++ = htons(M68K_NOP);
1910 *wp++ = htons(M68K_NOP);
1911 wp += 2;
1912 }
1913 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) {
1914 for (int i=0; i<6; i++) {
1915 *wp++ = htons(M68K_NOP);
1916 *wp++ = htons(M68K_NOP);
1917 *wp++ = htons(M68K_NOP);
1918 *wp++ = htons(M68K_NOP);
1919 wp += 2;
1920 }
1921 }
1922 }
1923
1924 // Don't initialize Cuda (via 0x274)
1925 static const uint8 cuda_init_dat[] = {0x08, 0xa9, 0x00, 0x04, 0x16, 0x00, 0x4e, 0x71, 0x13, 0x7c, 0x00, 0x84, 0x1c, 0x00, 0x4e, 0x71};
1926 if ((base = find_rom_data(0xa000, 0x12000, cuda_init_dat, sizeof(cuda_init_dat))) == 0) return false;
1927 D(bug("cuda_init %08lx\n", base));
1928 wp = (uint16 *)(ROMBaseHost + base);
1929 *wp++ = htons(M68K_NOP);
1930 *wp++ = htons(M68K_NOP);
1931 *wp++ = htons(M68K_NOP);
1932 *wp++ = htons(M68K_NOP);
1933 *wp++ = htons(M68K_NOP);
1934 *wp++ = htons(M68K_NOP);
1935 *wp = htons(M68K_NOP);
1936
1937 // Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them)
1938 static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c};
1939 if ((base = find_rom_data(0x6000, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false;
1940 D(bug("cpu_speed %08lx\n", base));
1941 wp = (uint16 *)(ROMBaseHost + base);
1942 *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0
1943 *wp++ = htons(CPUClockSpeed / 1000000);
1944 *wp++ = htons(CPUClockSpeed / 1000000);
1945 *wp = htons(M68K_RTS);
1946 if ((base = find_rom_data(base, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) {
1947 D(bug("cpu_speed2 %08lx\n", base));
1948 wp = (uint16 *)(ROMBaseHost + base);
1949 *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0
1950 *wp++ = htons(CPUClockSpeed / 1000000);
1951 *wp++ = htons(CPUClockSpeed / 1000000);
1952 *wp = htons(M68K_RTS);
1953 }
1954
1955 // Don't poke VIA in InitTimeMgr (via 0x298)
1956 static const uint8 time_via_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x28, 0x78, 0x01, 0xd4, 0x43, 0xec, 0x10, 0x00};
1957 if ((base = find_rom_data(0x30000, 0x40000, time_via_dat, sizeof(time_via_dat))) == 0) return false;
1958 D(bug("time_via %08lx\n", base));
1959 wp = (uint16 *)(ROMBaseHost + base);
1960 *wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4
1961 *wp++ = htons(0x1f3f);
1962 *wp = htons(M68K_RTS);
1963
1964 // Don't read from 0xff800000 (Name Registry, Open Firmware?) (via 0x2a2)
1965 // Remove this if FE03 works!!
1966 static const uint8 open_firmware_dat[] = {0x2f, 0x79, 0xff, 0x80, 0x00, 0x00, 0x00, 0xfc};
1967 if ((base = find_rom_data(0x48000, 0x58000, open_firmware_dat, sizeof(open_firmware_dat))) == 0) return false;
1968 D(bug("open_firmware %08lx\n", base));
1969 wp = (uint16 *)(ROMBaseHost + base);
1970 *wp++ = htons(0x2f7c); // move.l #deadbeef,0xfc(a7)
1971 *wp++ = htons(0xdead);
1972 *wp++ = htons(0xbeef);
1973 *wp = htons(0x00fc);
1974 wp = (uint16 *)(ROMBaseHost + base + 0x1a);
1975 *wp++ = htons(M68K_NOP); // (FE03 opcode, tries to jump to 0xdeadbeef)
1976 *wp = htons(M68K_NOP);
1977
1978 // Don't EnableExtCache (via 0x2b2)
1979 static const uint8 ext_cache2_dat[] = {0x4f, 0xef, 0xff, 0xec, 0x20, 0x4f, 0x10, 0xbc, 0x00, 0x01, 0x11, 0x7c, 0x00, 0x1b};
1980 if ((base = find_rom_data(0x13000, 0x20000, ext_cache2_dat, sizeof(ext_cache2_dat))) == 0) return false;
1981 D(bug("ext_cache2 %08lx\n", base));
1982 wp = (uint16 *)(ROMBaseHost + base);
1983 *wp = htons(M68K_RTS);
1984
1985 // Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8)
1986 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
1987 static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9};
1988 if ((base = find_rom_data(0x2a0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false;
1989 D(bug("tm_task %08lx\n", base));
1990 wp = (uint16 *)(ROMBaseHost + base + 28);
1991 *wp++ = htons(M68K_NOP);
1992 *wp++ = htons(M68K_NOP);
1993 *wp++ = htons(M68K_NOP);
1994 *wp++ = htons(M68K_NOP);
1995 *wp++ = htons(M68K_NOP);
1996 *wp = htons(M68K_NOP);
1997 } else {
1998 static const uint8 tm_task_dat[] = {0x20, 0x3c, 0x73, 0x79, 0x73, 0x61};
1999 if ((base = find_rom_data(0x280, 0x300, tm_task_dat, sizeof(tm_task_dat))) == 0) return false;
2000 D(bug("tm_task %08lx\n", base));
2001 wp = (uint16 *)(ROMBaseHost + base - 6);
2002 *wp++ = htons(M68K_NOP);
2003 *wp++ = htons(M68K_NOP);
2004 *wp = htons(M68K_NOP);
2005 }
2006
2007 // Don't read PVR from 0x5fffef80 in DriverServicesLib (via 0x316)
2008 if (ROMType != ROMTYPE_NEWWORLD && ROMType != ROMTYPE_GOSSAMER) {
2009 uint32 dsl_offset = find_rom_resource(FOURCC('n','l','i','b'), -16401);
2010 if (ROMType == ROMTYPE_ZANZIBAR) {
2011 static const uint8 dsl_pvr_dat[] = {0x40, 0x82, 0x00, 0x40, 0x38, 0x60, 0xef, 0x80, 0x3c, 0x63, 0x60, 0x00, 0x80, 0x83, 0x00, 0x00, 0x54, 0x84, 0x84, 0x3e};
2012 if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false;
2013 } else {
2014 static const uint8 dsl_pvr_dat[] = {0x3b, 0xc3, 0x00, 0x00, 0x30, 0x84, 0xff, 0xa0, 0x40, 0x82, 0x00, 0x44, 0x80, 0x84, 0xef, 0xe0, 0x54, 0x84, 0x84, 0x3e};
2015 if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false;
2016 }
2017 D(bug("dsl_pvr %08lx\n", base));
2018 lp = (uint32 *)(ROMBaseHost + base + 12);
2019 *lp = htonl(0x3c800000 | (PVR >> 16)); // lis r4,PVR
2020
2021 // Don't read bus clock from 0x5fffef88 in DriverServicesLib (via 0x316)
2022 if (ROMType == ROMTYPE_ZANZIBAR) {
2023 static const uint8 dsl_bus_dat[] = {0x81, 0x07, 0x00, 0x00, 0x39, 0x20, 0x42, 0x40, 0x81, 0x62, 0xff, 0x20};
2024 if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false;
2025 D(bug("dsl_bus %08lx\n", base));
2026 lp = (uint32 *)(ROMBaseHost + base);
2027 *lp = htonl(0x81000000 + XLM_BUS_CLOCK); // lwz r8,(bus clock speed)
2028 } else {
2029 static const uint8 dsl_bus_dat[] = {0x80, 0x83, 0xef, 0xe8, 0x80, 0x62, 0x00, 0x10, 0x7c, 0x04, 0x03, 0x96};
2030 if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false;
2031 D(bug("dsl_bus %08lx\n", base));
2032 lp = (uint32 *)(ROMBaseHost + base);
2033 *lp = htonl(0x80800000 + XLM_BUS_CLOCK); // lwz r4,(bus clock speed)
2034 }
2035 }
2036
2037 // Don't open InterruptTreeTNT in MotherBoardHAL init in DriverServicesLib init
2038 if (ROMType == ROMTYPE_ZANZIBAR) {
2039 lp = (uint32 *)(ROMBaseHost + find_rom_resource(FOURCC('n','l','i','b'), -16408) + 0x16c);
2040 *lp = htonl(0x38600000); // li r3,0
2041 }
2042
2043 // Don't read from MacPgm in WipeOutMACPGMINFOProcPtrs (StdCLib)
2044 if (1) {
2045 uint32 hpchk_offset = find_rom_resource(FOURCC('n','l','i','b'), 10);
2046 static const uint8 hpchk_dat[] = {0x80, 0x80, 0x03, 0x16, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xc4, 0x00, 0x04};
2047 if ((base = find_rom_data(hpchk_offset, hpchk_offset + 0x3000, hpchk_dat, sizeof(hpchk_dat))) == 0) return false;
2048 D(bug("macpgm %08lx\n", base));
2049 lp = (uint32 *)(ROMBaseHost + base);
2050 *lp = htonl(0x80800000 + XLM_ZERO_PAGE); // lwz r4,(zero page)
2051 }
2052
2053 // Patch Name Registry
2054 static const uint8 name_reg_dat[] = {0x70, 0xff, 0xab, 0xeb};
2055 if ((base = find_rom_data(0x300, 0x380, name_reg_dat, sizeof(name_reg_dat))) == 0) return false;
2056 D(bug("name_reg %08lx\n", base));
2057 wp = (uint16 *)(ROMBaseHost + base);
2058 *wp = htons(M68K_EMUL_OP_NAME_REGISTRY);
2059
2060 #if DISABLE_SCSI
2061 // Fake SCSI Manager
2062 // Remove this if SCSI Manager works!!
2063 static const uint8 scsi_mgr_a_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e};
2064 static const uint8 scsi_mgr_b_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x2f, 0x0c, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e};
2065 if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_a_dat, sizeof(scsi_mgr_a_dat))) == 0) {
2066 if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_b_dat, sizeof(scsi_mgr_b_dat))) == 0) return false;
2067 }
2068 D(bug("scsi_mgr %08lx\n", base));
2069 wp = (uint16 *)(ROMBaseHost + base);
2070 *wp++ = htons(0x21fc); // move.l #xxx,0x624 (SCSIAtomic)
2071 *wp++ = htons((ROMBase + base + 18) >> 16);
2072 *wp++ = htons((ROMBase + base + 18) & 0xffff);
2073 *wp++ = htons(0x0624);
2074 *wp++ = htons(0x21fc); // move.l #xxx,0xe54 (SCSIDispatch)
2075 *wp++ = htons((ROMBase + base + 22) >> 16);
2076 *wp++ = htons((ROMBase + base + 22) & 0xffff);
2077 *wp++ = htons(0x0e54);
2078 *wp++ = htons(M68K_RTS);
2079 *wp++ = htons(M68K_EMUL_OP_SCSI_ATOMIC);
2080 *wp++ = htons(M68K_RTS);
2081 *wp++ = htons(M68K_EMUL_OP_SCSI_DISPATCH);
2082 *wp = htons(0x4ed0); // jmp (a0)
2083 wp = (uint16 *)(ROMBaseHost + base + 0x20);
2084 *wp++ = htons(0x7000); // moveq #0,d0
2085 *wp = htons(M68K_RTS);
2086 #endif
2087
2088 #if DISABLE_SCSI
2089 // Don't access SCSI variables
2090 // Remove this if SCSI Manager works!!
2091 if (ROMType == ROMTYPE_NEWWORLD) {
2092 static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00};
2093 if ((base = find_rom_data(0x1f500, 0x1f600, scsi_var_dat, sizeof(scsi_var_dat))) != 0) {
2094 D(bug("scsi_var %08lx\n", base));
2095 wp = (uint16 *)(ROMBaseHost + base + 12);
2096 *wp = htons(0x6000); // bra
2097 }
2098
2099 static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x58, 0x48, 0xe7, 0x1f, 0x38};
2100 if ((base = find_rom_data(0x1f700, 0x1f800, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) {
2101 D(bug("scsi_var2 %08lx\n", base));
2102 wp = (uint16 *)(ROMBaseHost + base);
2103 *wp++ = htons(0x7000); // moveq #0,d0
2104 *wp = htons(M68K_RTS);
2105 }
2106 }
2107 else if (ROMType == ROMTYPE_GOSSAMER) {
2108 static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00};
2109 if ((base = find_rom_data(0x1d700, 0x1d800, scsi_var_dat, sizeof(scsi_var_dat))) != 0) {
2110 D(bug("scsi_var %08lx\n", base));
2111 wp = (uint16 *)(ROMBaseHost + base + 12);
2112 *wp = htons(0x6000); // bra
2113 }
2114
2115 static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x5a, 0x48, 0xe7, 0x1f, 0x38};
2116 if ((base = find_rom_data(0x1d900, 0x1da00, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) {
2117 D(bug("scsi_var2 %08lx\n", base));
2118 wp = (uint16 *)(ROMBaseHost + base);
2119 *wp++ = htons(0x7000); // moveq #0,d0
2120 *wp = htons(M68K_RTS);
2121 }
2122 }
2123 #endif
2124
2125 // Don't wait in ADBInit (via 0x36c)
2126 static const uint8 adb_init_dat[] = {0x08, 0x2b, 0x00, 0x05, 0x01, 0x5d, 0x66, 0xf8};
2127 if ((base = find_rom_data(0x31000, 0x3d000, adb_init_dat, sizeof(adb_init_dat))) == 0) return false;
2128 D(bug("adb_init %08lx\n", base));
2129 wp = (uint16 *)(ROMBaseHost + base + 6);
2130 *wp = htons(M68K_NOP);
2131
2132 // Modify check in InitResources() so that addresses >0x80000000 work
2133 static const uint8 init_res_dat[] = {0x4a, 0xb8, 0x0a, 0x50, 0x6e, 0x20};
2134 if ((base = find_rom_data(0x78000, 0x8c000, init_res_dat, sizeof(init_res_dat))) == 0) return false;
2135 D(bug("init_res %08lx\n", base));
2136 bp = (uint8 *)(ROMBaseHost + base + 4);
2137 *bp = 0x66;
2138
2139 // Modify vCheckLoad() so that we can patch resources (68k Resource Manager)
2140 static const uint8 check_load_dat[] = {0x20, 0x78, 0x07, 0xf0, 0x4e, 0xd0};
2141 if ((base = find_rom_data(0x78000, 0x8c000, check_load_dat, sizeof(check_load_dat))) == 0) return false;
2142 D(bug("check_load %08lx\n", base));
2143 wp = (uint16 *)(ROMBaseHost + base);
2144 *wp++ = htons(M68K_JMP);
2145 *wp++ = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) >> 16);
2146 *wp = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) & 0xffff);
2147 wp = (uint16 *)(ROMBaseHost + CHECK_LOAD_PATCH_SPACE);
2148 *wp++ = htons(0x2f03); // move.l d3,-(a7)
2149 *wp++ = htons(0x2078); // move.l $07f0,a0
2150 *wp++ = htons(0x07f0);
2151 *wp++ = htons(M68K_JSR_A0);
2152 *wp++ = htons(M68K_EMUL_OP_CHECKLOAD);
2153 *wp = htons(M68K_RTS);
2154
2155 // Replace .Sony driver
2156 sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4);
2157 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD)
2158 sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4, true); // First DRVR 4 is .MFMFloppy
2159 if (sony_offset == 0) {
2160 sony_offset = find_rom_resource(FOURCC('n','d','r','v'), -20196); // NewWorld 1.6 has "PCFloppy" ndrv
2161 if (sony_offset == 0)
2162 return false;
2163 lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8);
2164 *lp = htonl(FOURCC('D','R','V','R'));
2165 wp = (uint16 *)(ROMBaseHost + rsrc_ptr + 12);
2166 *wp = htons(4);
2167 }
2168 D(bug("sony_offset %08lx\n", sony_offset));
2169 memcpy((void *)(ROMBaseHost + sony_offset), sony_driver, sizeof(sony_driver));
2170
2171 // Install .Disk and .AppleCD drivers
2172 memcpy((void *)(ROMBaseHost + sony_offset + 0x100), disk_driver, sizeof(disk_driver));
2173 memcpy((void *)(ROMBaseHost + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver));
2174
2175 // Install serial drivers
2176 gen_ain_driver( ROMBase + sony_offset + 0x300);
2177 gen_aout_driver(ROMBase + sony_offset + 0x400);
2178 gen_bin_driver( ROMBase + sony_offset + 0x500);
2179 gen_bout_driver(ROMBase + sony_offset + 0x600);
2180
2181 // Copy icons to ROM
2182 SonyDiskIconAddr = ROMBase + sony_offset + 0x800;
2183 memcpy(ROMBaseHost + sony_offset + 0x800, SonyDiskIcon, sizeof(SonyDiskIcon));
2184 SonyDriveIconAddr = ROMBase + sony_offset + 0xa00;
2185 memcpy(ROMBaseHost + sony_offset + 0xa00, SonyDriveIcon, sizeof(SonyDriveIcon));
2186 DiskIconAddr = ROMBase + sony_offset + 0xc00;
2187 memcpy(ROMBaseHost + sony_offset + 0xc00, DiskIcon, sizeof(DiskIcon));
2188 CDROMIconAddr = ROMBase + sony_offset + 0xe00;
2189 memcpy(ROMBaseHost + sony_offset + 0xe00, CDROMIcon, sizeof(CDROMIcon));
2190
2191 // Patch driver install routine
2192 static const uint8 drvr_install_dat[] = {0xa7, 0x1e, 0x21, 0xc8, 0x01, 0x1c, 0x4e, 0x75};
2193 if ((base = find_rom_data(0xb00, 0xd00, drvr_install_dat, sizeof(drvr_install_dat))) == 0) return false;
2194 D(bug("drvr_install %08lx\n", base));
2195 wp = (uint16 *)(ROMBaseHost + base + 8);
2196 *wp++ = htons(M68K_EMUL_OP_INSTALL_DRIVERS);
2197 *wp = htons(M68K_RTS);
2198
2199 // Don't install serial drivers from ROM
2200 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
2201 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('S','E','R','D'), 0));
2202 *wp = htons(M68K_RTS);
2203 } else {
2204 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0xc4);
2205 *wp++ = htons(M68K_NOP);
2206 *wp++ = htons(M68K_NOP);
2207 *wp++ = htons(M68K_NOP);
2208 *wp++ = htons(M68K_NOP);
2209 *wp = htons(0x7000); // moveq #0,d0
2210 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0x8ee);
2211 *wp = htons(M68K_NOP);
2212 }
2213 uint32 nsrd_offset = find_rom_resource(FOURCC('n','s','r','d'), 1);
2214 if (nsrd_offset) {
2215 lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8);
2216 *lp = htonl(FOURCC('x','s','r','d'));
2217 }
2218
2219 // Replace ADBOp()
2220 memcpy(ROMBaseHost + find_rom_trap(0xa07c), adbop_patch, sizeof(adbop_patch));
2221
2222 // Replace Time Manager
2223 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa058));
2224 *wp++ = htons(M68K_EMUL_OP_INSTIME);
2225 *wp = htons(M68K_RTS);
2226 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa059));
2227 *wp++ = htons(0x40e7); // move sr,-(sp)
2228 *wp++ = htons(0x007c); // ori #$0700,sr
2229 *wp++ = htons(0x0700);
2230 *wp++ = htons(M68K_EMUL_OP_RMVTIME);
2231 *wp++ = htons(0x46df); // move (sp)+,sr
2232 *wp = htons(M68K_RTS);
2233 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05a));
2234 *wp++ = htons(0x40e7); // move sr,-(sp)
2235 *wp++ = htons(0x007c); // ori #$0700,sr
2236 *wp++ = htons(0x0700);
2237 *wp++ = htons(M68K_EMUL_OP_PRIMETIME);
2238 *wp++ = htons(0x46df); // move (sp)+,sr
2239 *wp = htons(M68K_RTS);
2240 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa093));
2241 *wp++ = htons(M68K_EMUL_OP_MICROSECONDS);
2242 *wp = htons(M68K_RTS);
2243
2244 // Disable Egret Manager
2245 static const uint8 egret_dat[] = {0x2f, 0x30, 0x81, 0xe2, 0x20, 0x10, 0x00, 0x18};
2246 if ((base = find_rom_data(0xa000, 0x10000, egret_dat, sizeof(egret_dat))) == 0) return false;
2247 D(bug("egret %08lx\n", base));
2248 wp = (uint16 *)(ROMBaseHost + base);
2249 *wp++ = htons(0x7000);
2250 *wp = htons(M68K_RTS);
2251
2252 // Don't call FE0A opcode in Shutdown Manager
2253 static const uint8 shutdown_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x48, 0xe7, 0x3f, 0x00, 0x2c, 0x00, 0x2e, 0x01};
2254 if ((base = find_rom_data(0x30000, 0x40000, shutdown_dat, sizeof(shutdown_dat))) == 0) return false;
2255 D(bug("shutdown %08lx\n", base));
2256 wp = (uint16 *)(ROMBaseHost + base);
2257 if (ROMType == ROMTYPE_ZANZIBAR)
2258 *wp = htons(M68K_RTS);
2259 else if (ntohs(wp[-4]) == 0x61ff)
2260 *wp = htons(M68K_RTS);
2261 else if (ntohs(wp[-2]) == 0x6700)
2262 wp[-2] = htons(0x6000); // bra
2263
2264 // Patch PowerOff()
2265 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05b)); // PowerOff()
2266 *wp = htons(M68K_EMUL_RETURN);
2267
2268 // Patch VIA interrupt handler
2269 static const uint8 via_int_dat[] = {0x70, 0x7f, 0xc0, 0x29, 0x1a, 0x00, 0xc0, 0x29, 0x1c, 0x00};
2270 if ((base = find_rom_data(0x13000, 0x1c000, via_int_dat, sizeof(via_int_dat))) == 0) return false;
2271 D(bug("via_int %08lx\n", base));
2272 uint32 level1_int = ROMBase + base;
2273 wp = (uint16 *)(ROMBaseHost + base); // Level 1 handler
2274 *wp++ = htons(0x7002); // moveq #2,d0 (60Hz interrupt)
2275 *wp++ = htons(M68K_NOP);
2276 *wp++ = htons(M68K_NOP);
2277 *wp++ = htons(M68K_NOP);
2278 *wp = htons(M68K_NOP);
2279
2280 static const uint8 via_int2_dat[] = {0x13, 0x7c, 0x00, 0x02, 0x1a, 0x00, 0x4e, 0x71, 0x52, 0xb8, 0x01, 0x6a};
2281 if ((base = find_rom_data(0x10000, 0x18000, via_int2_dat, sizeof(via_int2_dat))) == 0) return false;
2282 D(bug("via_int2 %08lx\n", base));
2283 wp = (uint16 *)(ROMBaseHost + base); // 60Hz handler
2284 *wp++ = htons(M68K_EMUL_OP_IRQ);
2285 *wp++ = htons(0x4a80); // tst.l d0
2286 *wp++ = htons(0x6700); // beq xxx
2287 *wp = htons(0xffe8);
2288
2289 if (ROMType == ROMTYPE_NEWWORLD) {
2290 static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26};
2291 if ((base = find_rom_data(0x15000, 0x19000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false;
2292 D(bug("via_int3 %08lx\n", base));
2293 wp = (uint16 *)(ROMBaseHost + base); // CHRP level 1 handler
2294 *wp++ = htons(M68K_JMP);
2295 *wp++ = htons((level1_int - 12) >> 16);
2296 *wp = htons((level1_int - 12) & 0xffff);
2297 }
2298
2299 // Patch PutScrap() for clipboard exchange with host OS
2300 uint32 put_scrap = find_rom_trap(0xa9fe); // PutScrap()
2301 wp = (uint16 *)(ROMBaseHost + PUT_SCRAP_PATCH_SPACE);
2302 *wp++ = htons(M68K_EMUL_OP_PUT_SCRAP);
2303 *wp++ = htons(M68K_JMP);
2304 *wp++ = htons((ROMBase + put_scrap) >> 16);
2305 *wp++ = htons((ROMBase + put_scrap) & 0xffff);
2306 base = ROMBase + ReadMacInt32(ROMBase + 0x22);
2307 WriteMacInt32(base + 4 * (0xa9fe & 0x3ff), PUT_SCRAP_PATCH_SPACE);
2308
2309 // Patch GetScrap() for clipboard exchange with host OS
2310 uint32 get_scrap = find_rom_trap(0xa9fd); // GetScrap()
2311 wp = (uint16 *)(ROMBaseHost + GET_SCRAP_PATCH_SPACE);
2312 *wp++ = htons(M68K_EMUL_OP_GET_SCRAP);
2313 *wp++ = htons(M68K_JMP);
2314 *wp++ = htons((ROMBase + get_scrap) >> 16);
2315 *wp++ = htons((ROMBase + get_scrap) & 0xffff);
2316 base = ROMBase + ReadMacInt32(ROMBase + 0x22);
2317 WriteMacInt32(base + 4 * (0xa9fd & 0x3ff), GET_SCRAP_PATCH_SPACE);
2318
2319 // Patch SynchIdleTime()
2320 if (PrefsFindBool("idlewait")) {
2321 base = find_rom_trap(0xabf7) + 4; // SynchIdleTime()
2322 wp = (uint16 *)(ROMBaseHost + base);
2323 D(bug("SynchIdleTime at %08lx\n", base));
2324 if (ntohs(*wp) == 0x2078) { // movea.l ExpandMem,a0
2325 *wp++ = htons(M68K_EMUL_OP_IDLE_TIME);
2326 *wp = htons(M68K_NOP);
2327 }
2328 else if (ntohs(*wp) == 0x70fe) // moveq #-2,d0
2329 *wp++ = htons(M68K_EMUL_OP_IDLE_TIME_2);
2330 else {
2331 D(bug("SynchIdleTime patch not installed\n"));
2332 }
2333 }
2334
2335 // Construct list of all sifters used by sound components in ROM
2336 D(bug("Searching for sound components with type sdev in ROM\n"));
2337 uint32 thing = find_rom_resource(FOURCC('t','h','n','g'));
2338 while (thing) {
2339 thing += ROMBase;
2340 D(bug(" found %c%c%c%c %c%c%c%c\n", ReadMacInt8(thing), ReadMacInt8(thing + 1), ReadMacInt8(thing + 2), ReadMacInt8(thing + 3), ReadMacInt8(thing + 4), ReadMacInt8(thing + 5), ReadMacInt8(thing + 6), ReadMacInt8(thing + 7)));
2341 if (ReadMacInt32(thing) == FOURCC('s','d','e','v') && ReadMacInt32(thing + 4) == FOURCC('s','i','n','g')) {
2342 WriteMacInt32(thing + 4, FOURCC('a','w','g','c'));
2343 D(bug(" found sdev component at offset %08x in ROM\n", thing));
2344 AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID));
2345 if (ReadMacInt32(thing + componentPFCount))
2346 AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID));
2347 }
2348 thing = find_rom_resource(FOURCC('t','h','n','g'), 4711, true);
2349 }
2350
2351 // Patch component code
2352 D(bug("Patching sifters in ROM\n"));
2353 for (int i=0; i<num_sifters; i++) {
2354 if ((thing = find_rom_resource(sifter_list[i].type, sifter_list[i].id)) != 0) {
2355 D(bug(" patching type %08x, id %d\n", sifter_list[i].type, sifter_list[i].id));
2356 // Install 68k glue code
2357 uint16 *wp = (uint16 *)(ROMBaseHost + thing);
2358 *wp++ = htons(0x4e56); *wp++ = htons(0x0000); // link a6,#0
2359 *wp++ = htons(0x48e7); *wp++ = htons(0x8018); // movem.l d0/a3-a4,-(a7)
2360 *wp++ = htons(0x266e); *wp++ = htons(0x000c); // movea.l $c(a6),a3
2361 *wp++ = htons(0x286e); *wp++ = htons(0x0008); // movea.l $8(a6),a4
2362 *wp++ = htons(M68K_EMUL_OP_AUDIO_DISPATCH);
2363 *wp++ = htons(0x2d40); *wp++ = htons(0x0010); // move.l d0,$10(a6)
2364 *wp++ = htons(0x4cdf); *wp++ = htons(0x1801); // movem.l (a7)+,d0/a3-a4
2365 *wp++ = htons(0x4e5e); // unlk a6
2366 *wp++ = htons(0x4e74); *wp++ = htons(0x0008); // rtd #8
2367 }
2368 }
2369 return true;
2370 }
2371
2372
2373 /*
2374 * Install .Sony, disk and CD-ROM drivers
2375 */
2376
2377 void InstallDrivers(void)
2378 {
2379 D(bug("Installing drivers...\n"));
2380 M68kRegisters r;
2381 SheepArray<SIZEOF_IOParam> pb_var;
2382 const uintptr pb = pb_var.addr();
2383
2384 #if DISABLE_SCSI
2385 // Setup fake SCSI Globals
2386 r.d[0] = 0x1000;
2387 Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
2388 uint32 scsi_globals = r.a[0];
2389 D(bug("Fake SCSI globals at %08lx\n", scsi_globals));
2390 WriteMacInt32(0xc0c, scsi_globals); // Set SCSIGlobals
2391 #endif
2392
2393 // Install floppy driver
2394 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
2395
2396 // Force installation of floppy driver with NewWorld and Gossamer ROMs
2397 r.a[0] = ROMBase + sony_offset;
2398 r.d[0] = (uint32)SonyRefNum;
2399 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2400 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~SonyRefNum * 4); // Get driver handle from Unit Table
2401 Execute68kTrap(0xa029, &r); // HLock()
2402 uint32 dce = ReadMacInt32(r.a[0]);
2403 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset);
2404 WriteMacInt16(dce + dCtlFlags, SonyDriverFlags);
2405 }
2406
2407 // Open .Sony driver
2408 SheepString sony_str("\005.Sony");
2409 WriteMacInt8(pb + ioPermssn, 0);
2410 WriteMacInt32(pb + ioNamePtr, sony_str.addr());
2411 r.a[0] = pb;
2412 Execute68kTrap(0xa000, &r); // Open()
2413
2414 // Install disk driver
2415 r.a[0] = ROMBase + sony_offset + 0x100;
2416 r.d[0] = (uint32)DiskRefNum;
2417 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2418 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~DiskRefNum * 4); // Get driver handle from Unit Table
2419 Execute68kTrap(0xa029, &r); // HLock()
2420 uint32 dce = ReadMacInt32(r.a[0]);
2421 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x100);
2422 WriteMacInt16(dce + dCtlFlags, DiskDriverFlags);
2423
2424 // Open disk driver
2425 SheepString disk_str("\005.Disk");
2426 WriteMacInt32(pb + ioNamePtr, disk_str.addr());
2427 r.a[0] = pb;
2428 Execute68kTrap(0xa000, &r); // Open()
2429
2430 // Install CD-ROM driver unless nocdrom option given
2431 if (!PrefsFindBool("nocdrom")) {
2432
2433 // Install CD-ROM driver
2434 r.a[0] = ROMBase + sony_offset + 0x200;
2435 r.d[0] = (uint32)CDROMRefNum;
2436 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2437 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~CDROMRefNum * 4); // Get driver handle from Unit Table
2438 Execute68kTrap(0xa029, &r); // HLock()
2439 dce = ReadMacInt32(r.a[0]);
2440 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x200);
2441 WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags);
2442
2443 // Open CD-ROM driver
2444 SheepString apple_cd("\010.AppleCD");
2445 WriteMacInt32(pb + ioNamePtr, apple_cd.addr());
2446 r.a[0] = pb;
2447 Execute68kTrap(0xa000, &r); // Open()
2448 }
2449
2450 // Install serial drivers
2451 r.a[0] = ROMBase + sony_offset + 0x300;
2452 r.d[0] = (uint32)-6;
2453 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2454 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-6) * 4); // Get driver handle from Unit Table
2455 Execute68kTrap(0xa029, &r); // HLock()
2456 dce = ReadMacInt32(r.a[0]);
2457 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x300);
2458 WriteMacInt16(dce + dCtlFlags, 0x4d00);
2459
2460 r.a[0] = ROMBase + sony_offset + 0x400;
2461 r.d[0] = (uint32)-7;
2462 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2463 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-7) * 4); // Get driver handle from Unit Table
2464 Execute68kTrap(0xa029, &r); // HLock()
2465 dce = ReadMacInt32(r.a[0]);
2466 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x400);
2467 WriteMacInt16(dce + dCtlFlags, 0x4e00);
2468
2469 r.a[0] = ROMBase + sony_offset + 0x500;
2470 r.d[0] = (uint32)-8;
2471 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2472 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-8) * 4); // Get driver handle from Unit Table
2473 Execute68kTrap(0xa029, &r); // HLock()
2474 dce = ReadMacInt32(r.a[0]);
2475 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x500);
2476 WriteMacInt16(dce + dCtlFlags, 0x4d00);
2477
2478 r.a[0] = ROMBase + sony_offset + 0x600;
2479 r.d[0] = (uint32)-9;
2480 Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2481 r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-9) * 4); // Get driver handle from Unit Table
2482 Execute68kTrap(0xa029, &r); // HLock()
2483 dce = ReadMacInt32(r.a[0]);
2484 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x600);
2485 WriteMacInt16(dce + dCtlFlags, 0x4e00);
2486 }