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 (15 years, 3 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

# User Rev Content
1 cebix 1.1 /*
2     * rom_patches.cpp - ROM patches
3     *
4 gbeauche 1.45 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
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 gbeauche 1.18 #include "thunks.h"
44 cebix 1.1
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 gbeauche 1.17 const uint32 CHECK_LOAD_PATCH_SPACE = 0x2fcf00;
63     const uint32 PUT_SCRAP_PATCH_SPACE = 0x2fcf80;
64     const uint32 GET_SCRAP_PATCH_SPACE = 0x2fcfc0;
65 gbeauche 1.21 const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd100;
66 cebix 1.1
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 gbeauche 1.2 // 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 gbeauche 1.3 uint32 next_offset = ntohl(parcel_data[0]);
129 gbeauche 1.2 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 gbeauche 1.16 uint32 lzss_size = ((uintptr)src + next_offset) - ((uintptr)parcel_data + lzss_offset);
136 gbeauche 1.2 decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size);
137     }
138 gbeauche 1.3 parcel_offset = next_offset;
139 gbeauche 1.2 }
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 gbeauche 1.36 memcpy(ROMBaseHost, data, ROM_SIZE);
152 gbeauche 1.2 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 gbeauche 1.36 decode_parcels(data + image_offset, ROMBaseHost, image_size);
190 gbeauche 1.2 }
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 gbeauche 1.36 decode_lzss(data + image_offset, ROMBaseHost, image_size);
195 gbeauche 1.2 }
196     return true;
197     }
198     return false;
199     }
200    
201    
202 cebix 1.1 /*
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 gbeauche 1.36 if (!memcmp(ROMBaseHost + ofs, data, data_len))
211 cebix 1.1 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 asvitkine 1.46 uint32 lp = ROMBase + 0x1a;
228 gbeauche 1.42 uint32 x = ReadMacInt32(lp);
229 asvitkine 1.46 uint32 header_size = ReadMacInt8(ROMBase + x + 5);
230 cebix 1.1
231     if (!cont)
232     rsrc_ptr = x;
233     else if (rsrc_ptr == 0)
234     return 0;
235    
236     for (;;) {
237 asvitkine 1.46 lp = ROMBase + rsrc_ptr;
238 gbeauche 1.42 rsrc_ptr = ReadMacInt32(lp);
239 cebix 1.1 if (rsrc_ptr == 0)
240     break;
241    
242     rsrc_ptr += header_size;
243    
244 asvitkine 1.46 lp = ROMBase + rsrc_ptr + 4;
245 gbeauche 1.42 uint32 data = ReadMacInt32(lp);
246     uint32 type = ReadMacInt32(lp + 4);
247     int16 id = ReadMacInt16(lp + 8);
248 cebix 1.1 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 asvitkine 1.46 uint32 lp = ROMBase + ReadMacInt32(ROMBase + 0x22);
262 cebix 1.1
263     if (trap > 0xa800)
264 gbeauche 1.42 return ReadMacInt32(lp + 4 * (trap & 0x3ff));
265 cebix 1.1 else
266 gbeauche 1.42 return ReadMacInt32(lp + 4 * ((trap & 0xff) + 0x400));
267 cebix 1.1 }
268    
269    
270     /*
271 gbeauche 1.20 * Return target of branch instruction specified at ADDR, or 0 if
272     * there is no such instruction
273     */
274    
275 gbeauche 1.36 static uint32 rom_powerpc_branch_target(uint32 addr)
276 gbeauche 1.20 {
277 gbeauche 1.36 uint32 opcode = ntohl(*(uint32 *)(ROMBaseHost + addr));
278 gbeauche 1.20 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 gbeauche 1.36 if (rom_powerpc_branch_target(addr) == target)
305 gbeauche 1.20 return addr;
306     }
307     return 0;
308     }
309    
310    
311     /*
312 gbeauche 1.21 * 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 gbeauche 1.36 uint32 x = ntohl(*(uint32 *)(ROMBaseHost + base + i));
320 gbeauche 1.21 if (x != 0x6b636b63 && x != 0)
321     return false;
322     }
323     return true;
324     }
325    
326    
327     /*
328 cebix 1.1 * 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 gbeauche 1.18 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 cebix 1.1
523 gbeauche 1.18 // .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 cebix 1.1 };
549    
550 gbeauche 1.18 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 cebix 1.1 };
580    
581 gbeauche 1.18 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 cebix 1.1 };
611    
612 gbeauche 1.18 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 cebix 1.1 };
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 gbeauche 1.9 * 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 cebix 1.1 * Install ROM patches (RAMBase and KernelDataAddr must be set)
685     */
686    
687     bool PatchROM(void)
688     {
689     // Print ROM info
690 gbeauche 1.36 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 cebix 1.1
697     // Detect ROM type
698 gbeauche 1.36 if (!memcmp(ROMBaseHost + 0x30d064, "Boot TNT", 8))
699 cebix 1.1 ROMType = ROMTYPE_TNT;
700 gbeauche 1.36 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Alchemy", 12))
701 cebix 1.1 ROMType = ROMTYPE_ALCHEMY;
702 gbeauche 1.36 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Zanzibar", 13))
703 cebix 1.1 ROMType = ROMTYPE_ZANZIBAR;
704 gbeauche 1.36 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gazelle", 12))
705 cebix 1.1 ROMType = ROMTYPE_GAZELLE;
706 gbeauche 1.36 else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gossamer", 13))
707 gbeauche 1.11 ROMType = ROMTYPE_GOSSAMER;
708 gbeauche 1.36 else if (!memcmp(ROMBaseHost + 0x30d064, "NewWorld", 8))
709 cebix 1.1 ROMType = ROMTYPE_NEWWORLD;
710     else
711     return false;
712    
713 gbeauche 1.14 // Check that other ROM addresses point to really free regions
714 gbeauche 1.21 if (!check_rom_patch_space(CHECK_LOAD_PATCH_SPACE, 0x40))
715 gbeauche 1.14 return false;
716 gbeauche 1.21 if (!check_rom_patch_space(PUT_SCRAP_PATCH_SPACE, 0x40))
717 gbeauche 1.14 return false;
718 gbeauche 1.21 if (!check_rom_patch_space(GET_SCRAP_PATCH_SPACE, 0x40))
719 gbeauche 1.14 return false;
720 gbeauche 1.21 if (!check_rom_patch_space(ADDR_MAP_PATCH_SPACE - 10 * 4, 0x100))
721 gbeauche 1.14 return false;
722    
723 cebix 1.1 // 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 gbeauche 1.36 uint16 *wp = (uint16 *)(ROMBaseHost + M68K_BREAK_POINT);
732 cebix 1.1 *wp++ = htons(M68K_EMUL_BREAK);
733     *wp = htons(M68K_EMUL_RETURN);
734     #endif
735    
736     #ifdef POWERPC_BREAK_POINT
737     // Install PowerPC breakpoint
738 gbeauche 1.36 uint32 *lp = (uint32 *)(ROMBaseHost + POWERPC_BREAK_POINT);
739 cebix 1.1 *lp = htonl(0);
740     #endif
741    
742     // Copy 68k emulator to 2MB boundary
743 gbeauche 1.36 memcpy(ROMBaseHost + ROM_SIZE, ROMBaseHost + (ROM_SIZE - 0x100000), 0x100000);
744 cebix 1.1 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 gbeauche 1.20 uint32 base, loc;
756 cebix 1.1
757     // ROM boot structure patches
758 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x30d000);
759 cebix 1.1 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 asvitkine 1.46 lp[0xa8 >> 2] = htonl(ROMBase + 0x480000); // LA_DispatchTable
763     lp[0xac >> 2] = htonl(ROMBase + 0x460000); // LA_EmulatorCode
764 cebix 1.1 lp[0x360 >> 2] = htonl(0); // Physical RAM base (? on NewWorld ROM, this contains -1)
765 asvitkine 1.46 lp[0xfd8 >> 2] = htonl(ROMBase + 0x2a); // 68k reset vector
766 cebix 1.1
767     // Skip SR/BAT/SDR init
768 gbeauche 1.20 loc = 0x310000;
769 gbeauche 1.11 if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_GOSSAMER || ROMType == ROMTYPE_NEWWORLD) {
770 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + loc);
771 cebix 1.1 *lp++ = htonl(POWERPC_NOP);
772     *lp = htonl(0x38000000);
773     }
774 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + loc + 8);
778 asvitkine 1.46 *lp = htonl(0x48000000 | ((base - loc - 8) & 0x3fffffc)); // b ROMBase+0x3101b0
779 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
780 cebix 1.1 *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 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
790 cebix 1.1 *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 gbeauche 1.36 loc = (ntohl(lp[8]) & 0xffff) + (uintptr)(lp+8) - (uintptr)ROMBaseHost;
799 cebix 1.1 D(bug("loc %08lx\n", loc));
800 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + ofs + 0x310000);
801 cebix 1.1 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 gbeauche 1.31 case 8: // 750, 750FX
849     case 0x7000:
850 cebix 1.1 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 gbeauche 1.31 case 12: // 7400, 7410, 7450, 7455, 7457
874 gbeauche 1.26 case 0x800c:
875 gbeauche 1.31 case 0x8000:
876     case 0x8001:
877     case 0x8002:
878 cebix 1.1 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 gbeauche 1.25 break;
912 gbeauche 1.33 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 cebix 1.1 default:
924     printf("WARNING: Unknown CPU type\n");
925     break;
926     }
927    
928     // Don't set SPRG3, don't test MQ
929 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
933 gbeauche 1.20 lp[0] = htonl(POWERPC_NOP);
934     lp[2] = htonl(POWERPC_NOP);
935     lp[4] = htonl(POWERPC_NOP);
936 cebix 1.1
937     // Don't read MSR
938 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
942 cebix 1.1 *lp = htonl(0x39c00000); // li r14,0
943    
944     // Don't write to DEC
945 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + loc + 0x70);
946 cebix 1.1 *lp++ = htonl(POWERPC_NOP);
947 gbeauche 1.36 loc = (ntohl(lp[0]) & 0xffff) + (uintptr)lp - (uintptr)ROMBaseHost;
948 cebix 1.1 D(bug("loc %08lx\n", loc));
949    
950     // Don't set SPRG3
951 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 4);
955 cebix 1.1 *lp = htonl(POWERPC_NOP);
956    
957     // Don't read PVR
958 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
962 cebix 1.1 *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
963 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
966 cebix 1.1 *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
967 gbeauche 1.20 }
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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
972 cebix 1.1 *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR)
973 gbeauche 1.20 }
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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
978 gbeauche 1.4 *lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR)
979 gbeauche 1.20 }
980 cebix 1.1
981     // Don't read SDR1
982 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
986 cebix 1.1 *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 gbeauche 1.20 // 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 4);
995 cebix 1.1 *lp = htonl(POWERPC_NOP);
996 gbeauche 1.20 D(bug("tblie %08lx\n", base + 12));
997 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 12);
998 cebix 1.1 *lp = htonl(POWERPC_NOP);
999    
1000     // Don't create RAM descriptor table
1001 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1005 cebix 1.1 *lp = htonl(POWERPC_NOP);
1006    
1007     // Don't load SRs and BATs
1008 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1015 cebix 1.1 *lp = htonl(POWERPC_NOP);
1016    
1017     // Don't mess with SRs
1018 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1022 cebix 1.1 *lp = htonl(POWERPC_BLR);
1023    
1024     // Don't check performance monitor
1025 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1029 gbeauche 1.20
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 cebix 1.1
1050     // Jump to 68k emulator
1051 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1058 cebix 1.1 *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 gbeauche 1.29 uint32 base, loc;
1075 cebix 1.1
1076     // Overwrite twi instructions
1077 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1081 cebix 1.1 *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 gbeauche 1.38 *lp++ = htonl(0x48000000 + 0x36fd00 - base - 20); // FE0F opcode
1087 cebix 1.1 *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 gbeauche 1.7 // Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes
1100 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x380000 + (M68K_EMUL_RETURN << 3));
1101 cebix 1.1 *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 gbeauche 1.7 *lp++ = htonl(POWERPC_EMUL_OP | 2);
1106     *lp++ = htonl(0x4bf66e70); // b 0x366084
1107 cebix 1.1 for (int i=0; i<OP_MAX; i++) {
1108 gbeauche 1.7 *lp++ = htonl(POWERPC_EMUL_OP | (i + 3));
1109     *lp++ = htonl(0x4bf66e68 - i*8); // b 0x366084
1110 cebix 1.1 }
1111     #else
1112     // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes
1113 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x380000 + (M68K_EMUL_RETURN << 3));
1114 cebix 1.1 *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 gbeauche 1.7 *lp++ = htonl(0x00dead00); // Let SheepShaver crash, since
1119     *lp++ = htonl(0x00beef00); // no native opcode is available
1120 cebix 1.1 for (int i=0; i<OP_MAX; i++) {
1121     *lp++ = htonl(0x38a00000 + i); // li r5,OP_*
1122 gbeauche 1.7 *lp++ = htonl(0x4bf705ec - i*8); // b 0x36f808
1123 cebix 1.1 }
1124    
1125     // Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP
1126 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x36f800);
1127 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x36f900);
1137 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x36fa00);
1167 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x36fb00);
1197 cebix 1.1 *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 gbeauche 1.4 *lp++ = htonl(0x814105f8); // lwz r10,0x05f8(r1)
1218 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x36fc00);
1227 cebix 1.1 *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 gbeauche 1.4 *lp++ = htonl(0x814105fc); // lwz r10,0x05fc(r1)
1248 cebix 1.1 *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 gbeauche 1.38 // 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 cebix 1.1 // Patch DR emulator to jump to right address when an interrupt occurs
1286 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x370000);
1287     while (lp < (uint32 *)(ROMBaseHost + 0x380000)) {
1288 cebix 1.1 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 gbeauche 1.36 loc = (uintptr)lp - (uintptr)ROMBaseHost;
1297 gbeauche 1.37 if ((base = rom_powerpc_branch_target(loc)) == 0) base = loc;
1298 gbeauche 1.29 static const uint8 dr_ret_dat[] = {0x80, 0xbf, 0x08, 0x14, 0x53, 0x19, 0x4d, 0xac, 0x7c, 0xa8, 0x03, 0xa6};
1299 gbeauche 1.37 if ((base = find_rom_data(base, 0x380000, dr_ret_dat, sizeof(dr_ret_dat))) == 0) return false;
1300 gbeauche 1.29 D(bug("dr_ret %08lx\n", base));
1301     if (base != loc) {
1302     // OldWorld ROMs contain an absolute branch
1303 gbeauche 1.36 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 asvitkine 1.46 *lp++ = htonl(0x3c000000 + ((ROMBase + base) >> 16)); // lis r0,xxx
1307     *lp++ = htonl(0x60000000 + ((ROMBase + base) & 0xffff)); // ori r0,r0,xxx
1308 gbeauche 1.29 *lp++ = htonl(0x7c0803a6); // mtlr r0
1309     *lp = htonl(POWERPC_BLR); // blr
1310     }
1311 cebix 1.1 return true;
1312     }
1313    
1314    
1315     /*
1316     * Nanokernel patches
1317     */
1318    
1319     static bool patch_nanokernel(void)
1320     {
1321     uint32 *lp;
1322 gbeauche 1.20 uint32 base, loc;
1323 cebix 1.1
1324     // Patch Mixed Mode trap
1325 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 8); // Don't translate virtual->physical
1329 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base); // Don't activate PPC exception table
1336 cebix 1.1 *lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE
1337 gbeauche 1.20 *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE
1338 cebix 1.1
1339 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base); // Don't modify MSR to turn on FPU
1343 gbeauche 1.20 if (ntohl(lp[4]) != 0x556b04e2) return false;
1344 gbeauche 1.36 loc = base;
1345 gbeauche 1.20 #if 1
1346     // FIXME: is that really intended?
1347 cebix 1.1 *lp++ = htonl(POWERPC_NOP);
1348     lp++;
1349     *lp++ = htonl(POWERPC_NOP);
1350     lp++;
1351     *lp = htonl(POWERPC_NOP);
1352 gbeauche 1.20 #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 cebix 1.1
1359 gbeauche 1.20 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 gbeauche 1.36 if (rom_powerpc_branch_target(base + 12) != loc) return false;
1363     lp = (uint32 *)(ROMBaseHost + base + 12); // Always save FPU state
1364 cebix 1.1 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88
1365    
1366 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base); // Don't modify DEC
1370 gbeauche 1.20 lp[0] = htonl(0x3be00000); // li r31,0
1371 cebix 1.1 #if 1
1372 gbeauche 1.20 lp[3] = htonl(POWERPC_NOP);
1373     lp[4] = htonl(POWERPC_NOP);
1374 cebix 1.1 #else
1375 gbeauche 1.20 lp[3] = htonl(0x39000040); // li r8,0x40
1376     lp[4] = htonl(0x990600e4); // stb r8,0xe4(r6)
1377 cebix 1.1 #endif
1378    
1379 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state
1383 cebix 1.1 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc
1384    
1385 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 4); // Don't activate 68k exception table
1389 cebix 1.1 *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 gbeauche 1.20 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 gbeauche 1.36 loc = rom_powerpc_branch_target(base + 12);
1397     lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state
1398 cebix 1.1 *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4
1399    
1400 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 4); // Don't modify MSR to turn on FPU
1405 cebix 1.1 *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 gbeauche 1.38 // Disable suspend (FE0F opcode)
1414 gbeauche 1.39 // TODO: really suspend SheepShaver?
1415 gbeauche 1.38 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 gbeauche 1.39 lp = (uint32 *)(ROMBaseHost + base + 4);
1419 gbeauche 1.38 *lp = htonl((ntohl(*lp) & 0xffff) | 0x48000000); // bgt -> b
1420    
1421 cebix 1.1 // Patch trap return routine
1422 gbeauche 1.20 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 8); // Replace rfi
1426 gbeauche 1.20 *lp = htonl(POWERPC_BCTR);
1427    
1428     while (ntohl(*lp) != 0x7d5a03a6) lp--;
1429 cebix 1.1 *lp++ = htonl(0x7d4903a6); // mtctr r10
1430     *lp++ = htonl(0x7daff120); // mtcr r13
1431 asvitkine 1.46 *lp = htonl(0x48000000 + ((0x318000 - ((uintptr)lp - (uintptr)ROMBaseHost)) & 0x03fffffc)); // b ROMBase+0x318000
1432 gbeauche 1.36 uint32 npc = (uintptr)(lp + 1) - (uintptr)ROMBaseHost;
1433 cebix 1.1
1434 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + 0x318000);
1435 cebix 1.1 *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 asvitkine 1.46 *lp = htonl(0x48000000 + ((npc - 0x31800c) & 0x03fffffc)); // b ROMBase+0x312c2c
1439 gbeauche 1.8
1440 gbeauche 1.43 // 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 gbeauche 1.44 lp = (uint32 *)(ROMBaseHost + base - 12);
1469 gbeauche 1.43 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 gbeauche 1.44 lp = (uint32 *)(ROMBaseHost + base);
1479 gbeauche 1.43 lp[2] = htonl(POWERPC_NOP);
1480    
1481 cebix 1.1 /*
1482     // Disable FE0A/FE06 opcodes
1483 asvitkine 1.46 lp = (uint32 *)(ROMBase + 0x3144ac);
1484 cebix 1.1 *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 gbeauche 1.20 uint32 base, loc;
1501 cebix 1.1
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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1507 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1514 cebix 1.1 *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 gbeauche 1.4 if ((base = find_rom_data(0x14000, 0x18000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false;
1527 cebix 1.1 D(bug("universal_info %08lx\n", base));
1528 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1529 cebix 1.1 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1541 cebix 1.1 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 gbeauche 1.11 } else if (ROMType == ROMTYPE_GOSSAMER) {
1551     base = 0x12d20;
1552 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base - 0x14);
1553 gbeauche 1.11 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 cebix 1.1 }
1563    
1564     // Construct AddrMap for NewWorld ROM
1565 gbeauche 1.11 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) {
1566 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + ADDR_MAP_PATCH_SPACE);
1567 cebix 1.1 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 4);
1591 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1597 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1603 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1611 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base - 6);
1619 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1629 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1637 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1644 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 16);
1651 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 6);
1664 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1670 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 12);
1681 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 2);
1688 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_XPRAM2);
1689     *wp = htons(0x4ed3); // jmp (a3)
1690    
1691 gbeauche 1.11 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 2);
1695 gbeauche 1.11 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + nvram4_loc[ROMType]);
1700 cebix 1.1 *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 gbeauche 1.11 static const uint32 nvram5_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0x53a20, 0};
1713 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + nvram5_loc[ROMType]);
1714 cebix 1.1 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1737 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_FIX_MEMTOP);
1738     *wp = htons(M68K_NOP);
1739    
1740     // Don't initialize SCC (via 0x1ac)
1741 gbeauche 1.20 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 12);
1745     loc = ntohs(wp[1]) + ((uintptr)wp - (uintptr)ROMBaseHost) + 2;
1746 gbeauche 1.21 static const uint8 scc_init_dat[] = {0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8};
1747 gbeauche 1.22 if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) == 0) return false;
1748 cebix 1.1 D(bug("scc_init %08lx\n", base));
1749 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1750 cebix 1.1 *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 asvitkine 1.46 loc = ReadMacInt32(ROMBase + base + 6);
1758 gbeauche 1.42 wp = (uint16 *)(ROMBaseHost + loc + base + 6);
1759 cebix 1.1 *wp = htons(M68K_RTS);
1760 asvitkine 1.46 loc = ReadMacInt32(ROMBase + base + 12);
1761 gbeauche 1.42 wp = (uint16 *)(ROMBaseHost + loc + base + 12);
1762 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1769 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 16);
1788 cebix 1.1 for (;;) {
1789 gbeauche 1.36 D(bug(" %08lx\n", (uintptr)lp - (uintptr)ROMBaseHost));
1790 cebix 1.1 while ((ntohl(*lp) & 0xff000000) == 0xff000000) {
1791 asvitkine 1.46 *lp = htonl((ntohl(*lp) & (ROM_SIZE-1)) + ROMBase);
1792 cebix 1.1 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
1805 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1814 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1825 cebix 1.1 *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 gbeauche 1.34 // Gestalt PowerPC page size, CPU type, RAM size (InitGestalt, via 0x25c)
1832 cebix 1.1 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1836 cebix 1.1 *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 gbeauche 1.34 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 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x4a);
1857 cebix 1.1 else
1858 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x28);
1859 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + 0x5d87a);
1865 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + 0x5d888);
1871 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1884 cebix 1.1 *wp++ = htons(M68K_NOP);
1885     *wp = htons(M68K_NOP);
1886 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x40);
1887 cebix 1.1 *wp++ = htons(M68K_NOP);
1888     *wp = htons(M68K_NOP);
1889 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x78);
1890 cebix 1.1 *wp++ = htons(M68K_NOP);
1891     *wp = htons(M68K_NOP);
1892 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x96);
1893 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1900 gbeauche 1.35 if (ROMType == ROMTYPE_GOSSAMER) {
1901 gbeauche 1.11 *wp++ = htons(M68K_NOP);
1902 gbeauche 1.35 *wp++ = htons(M68K_NOP);
1903     *wp++ = htons(M68K_NOP);
1904     *wp++ = htons(M68K_NOP);
1905     }
1906 cebix 1.1 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 gbeauche 1.11 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) {
1914 cebix 1.1 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1929 cebix 1.1 *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 gbeauche 1.4 if ((base = find_rom_data(0x6000, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false;
1940 cebix 1.1 D(bug("cpu_speed %08lx\n", base));
1941 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1942 cebix 1.1 *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 gbeauche 1.4 if ((base = find_rom_data(base, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) {
1947 cebix 1.1 D(bug("cpu_speed2 %08lx\n", base));
1948 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1949 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1960 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1970 cebix 1.1 *wp++ = htons(0x2f7c); // move.l #deadbeef,0xfc(a7)
1971     *wp++ = htons(0xdead);
1972     *wp++ = htons(0xbeef);
1973     *wp = htons(0x00fc);
1974 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x1a);
1975 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
1983 cebix 1.1 *wp = htons(M68K_RTS);
1984    
1985     // Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8)
1986 gbeauche 1.13 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
1987 cebix 1.1 static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9};
1988 gbeauche 1.13 if ((base = find_rom_data(0x2a0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false;
1989 cebix 1.1 D(bug("tm_task %08lx\n", base));
1990 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 28);
1991 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base - 6);
2002 cebix 1.1 *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 gbeauche 1.11 if (ROMType != ROMTYPE_NEWWORLD && ROMType != ROMTYPE_GOSSAMER) {
2009 cebix 1.1 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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base + 12);
2019 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
2027 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
2033 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + find_rom_resource(FOURCC('n','l','i','b'), -16408) + 0x16c);
2040 cebix 1.1 *lp = htonl(0x38600000); // li r3,0
2041     }
2042    
2043 gbeauche 1.43 // Don't read from MacPgm in WipeOutMACPGMINFOProcPtrs (StdCLib)
2044 gbeauche 1.19 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 gbeauche 1.43 D(bug("macpgm %08lx\n", base));
2049 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + base);
2050 gbeauche 1.19 *lp = htonl(0x80800000 + XLM_ZERO_PAGE); // lwz r4,(zero page)
2051     }
2052    
2053 cebix 1.1 // 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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2058 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2070 cebix 1.1 *wp++ = htons(0x21fc); // move.l #xxx,0x624 (SCSIAtomic)
2071 asvitkine 1.46 *wp++ = htons((ROMBase + base + 18) >> 16);
2072     *wp++ = htons((ROMBase + base + 18) & 0xffff);
2073 cebix 1.1 *wp++ = htons(0x0624);
2074     *wp++ = htons(0x21fc); // move.l #xxx,0xe54 (SCSIDispatch)
2075 asvitkine 1.46 *wp++ = htons((ROMBase + base + 22) >> 16);
2076     *wp++ = htons((ROMBase + base + 22) & 0xffff);
2077 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 0x20);
2084 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 12);
2096 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2103 cebix 1.1 *wp++ = htons(0x7000); // moveq #0,d0
2104 gbeauche 1.11 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 12);
2112 gbeauche 1.11 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2119 gbeauche 1.11 *wp++ = htons(0x7000); // moveq #0,d0
2120     *wp = htons(M68K_RTS);
2121 cebix 1.1 }
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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 6);
2130 cebix 1.1 *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 gbeauche 1.36 bp = (uint8 *)(ROMBaseHost + base + 4);
2137 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2144 cebix 1.1 *wp++ = htons(M68K_JMP);
2145 asvitkine 1.46 *wp++ = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) >> 16);
2146     *wp = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) & 0xffff);
2147 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + CHECK_LOAD_PATCH_SPACE);
2148 cebix 1.1 *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 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8);
2164 cebix 1.1 *lp = htonl(FOURCC('D','R','V','R'));
2165 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + rsrc_ptr + 12);
2166 cebix 1.1 *wp = htons(4);
2167     }
2168     D(bug("sony_offset %08lx\n", sony_offset));
2169 gbeauche 1.36 memcpy((void *)(ROMBaseHost + sony_offset), sony_driver, sizeof(sony_driver));
2170 cebix 1.1
2171     // Install .Disk and .AppleCD drivers
2172 gbeauche 1.36 memcpy((void *)(ROMBaseHost + sony_offset + 0x100), disk_driver, sizeof(disk_driver));
2173     memcpy((void *)(ROMBaseHost + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver));
2174 cebix 1.1
2175     // Install serial drivers
2176 asvitkine 1.46 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 cebix 1.1
2181     // Copy icons to ROM
2182 asvitkine 1.46 SonyDiskIconAddr = ROMBase + sony_offset + 0x800;
2183 gbeauche 1.36 memcpy(ROMBaseHost + sony_offset + 0x800, SonyDiskIcon, sizeof(SonyDiskIcon));
2184 asvitkine 1.46 SonyDriveIconAddr = ROMBase + sony_offset + 0xa00;
2185 gbeauche 1.36 memcpy(ROMBaseHost + sony_offset + 0xa00, SonyDriveIcon, sizeof(SonyDriveIcon));
2186 asvitkine 1.46 DiskIconAddr = ROMBase + sony_offset + 0xc00;
2187 gbeauche 1.36 memcpy(ROMBaseHost + sony_offset + 0xc00, DiskIcon, sizeof(DiskIcon));
2188 asvitkine 1.46 CDROMIconAddr = ROMBase + sony_offset + 0xe00;
2189 gbeauche 1.36 memcpy(ROMBaseHost + sony_offset + 0xe00, CDROMIcon, sizeof(CDROMIcon));
2190 cebix 1.1
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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base + 8);
2196 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_INSTALL_DRIVERS);
2197     *wp = htons(M68K_RTS);
2198    
2199     // Don't install serial drivers from ROM
2200 gbeauche 1.11 if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
2201 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('S','E','R','D'), 0));
2202 cebix 1.1 *wp = htons(M68K_RTS);
2203     } else {
2204 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0xc4);
2205 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0x8ee);
2211 cebix 1.1 *wp = htons(M68K_NOP);
2212     }
2213     uint32 nsrd_offset = find_rom_resource(FOURCC('n','s','r','d'), 1);
2214     if (nsrd_offset) {
2215 gbeauche 1.36 lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8);
2216 cebix 1.1 *lp = htonl(FOURCC('x','s','r','d'));
2217     }
2218    
2219     // Replace ADBOp()
2220 gbeauche 1.36 memcpy(ROMBaseHost + find_rom_trap(0xa07c), adbop_patch, sizeof(adbop_patch));
2221 cebix 1.1
2222     // Replace Time Manager
2223 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa058));
2224 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_INSTIME);
2225     *wp = htons(M68K_RTS);
2226 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa059));
2227 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05a));
2234 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa093));
2241 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2249 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base);
2257 cebix 1.1 if (ROMType == ROMTYPE_ZANZIBAR)
2258     *wp = htons(M68K_RTS);
2259 gbeauche 1.6 else if (ntohs(wp[-4]) == 0x61ff)
2260     *wp = htons(M68K_RTS);
2261     else if (ntohs(wp[-2]) == 0x6700)
2262 cebix 1.1 wp[-2] = htons(0x6000); // bra
2263    
2264     // Patch PowerOff()
2265 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05b)); // PowerOff()
2266 cebix 1.1 *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 asvitkine 1.46 uint32 level1_int = ROMBase + base;
2273 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base); // Level 1 handler
2274 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base); // 60Hz handler
2284 cebix 1.1 *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 gbeauche 1.4 if ((base = find_rom_data(0x15000, 0x19000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false;
2292 cebix 1.1 D(bug("via_int3 %08lx\n", base));
2293 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + base); // CHRP level 1 handler
2294 cebix 1.1 *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 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + PUT_SCRAP_PATCH_SPACE);
2302 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_PUT_SCRAP);
2303     *wp++ = htons(M68K_JMP);
2304 asvitkine 1.46 *wp++ = htons((ROMBase + put_scrap) >> 16);
2305     *wp++ = htons((ROMBase + put_scrap) & 0xffff);
2306     base = ROMBase + ReadMacInt32(ROMBase + 0x22);
2307 gbeauche 1.42 WriteMacInt32(base + 4 * (0xa9fe & 0x3ff), PUT_SCRAP_PATCH_SPACE);
2308 cebix 1.1
2309     // Patch GetScrap() for clipboard exchange with host OS
2310     uint32 get_scrap = find_rom_trap(0xa9fd); // GetScrap()
2311 gbeauche 1.36 wp = (uint16 *)(ROMBaseHost + GET_SCRAP_PATCH_SPACE);
2312 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_GET_SCRAP);
2313     *wp++ = htons(M68K_JMP);
2314 asvitkine 1.46 *wp++ = htons((ROMBase + get_scrap) >> 16);
2315     *wp++ = htons((ROMBase + get_scrap) & 0xffff);
2316     base = ROMBase + ReadMacInt32(ROMBase + 0x22);
2317 gbeauche 1.42 WriteMacInt32(base + 4 * (0xa9fd & 0x3ff), GET_SCRAP_PATCH_SPACE);
2318 cebix 1.1
2319     // Patch SynchIdleTime()
2320     if (PrefsFindBool("idlewait")) {
2321 gbeauche 1.36 base = find_rom_trap(0xabf7) + 4; // SynchIdleTime()
2322     wp = (uint16 *)(ROMBaseHost + base);
2323     D(bug("SynchIdleTime at %08lx\n", base));
2324 gbeauche 1.28 if (ntohs(*wp) == 0x2078) { // movea.l ExpandMem,a0
2325 cebix 1.1 *wp++ = htons(M68K_EMUL_OP_IDLE_TIME);
2326     *wp = htons(M68K_NOP);
2327 gbeauche 1.28 }
2328     else if (ntohs(*wp) == 0x70fe) // moveq #-2,d0
2329     *wp++ = htons(M68K_EMUL_OP_IDLE_TIME_2);
2330     else {
2331 cebix 1.1 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 asvitkine 1.46 thing += ROMBase;
2340 cebix 1.1 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 gbeauche 1.36 uint16 *wp = (uint16 *)(ROMBaseHost + thing);
2358 cebix 1.1 *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 gbeauche 1.18 SheepArray<SIZEOF_IOParam> pb_var;
2382     const uintptr pb = pb_var.addr();
2383 gbeauche 1.7
2384 gbeauche 1.41 #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 gbeauche 1.5 // Install floppy driver
2394 gbeauche 1.14 if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) {
2395 gbeauche 1.5
2396 gbeauche 1.14 // Force installation of floppy driver with NewWorld and Gossamer ROMs
2397 asvitkine 1.46 r.a[0] = ROMBase + sony_offset;
2398 gbeauche 1.5 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset);
2404 gbeauche 1.5 WriteMacInt16(dce + dCtlFlags, SonyDriverFlags);
2405     }
2406 gbeauche 1.8
2407 cebix 1.1 // Open .Sony driver
2408 gbeauche 1.18 SheepString sony_str("\005.Sony");
2409     WriteMacInt8(pb + ioPermssn, 0);
2410     WriteMacInt32(pb + ioNamePtr, sony_str.addr());
2411     r.a[0] = pb;
2412 cebix 1.1 Execute68kTrap(0xa000, &r); // Open()
2413    
2414     // Install disk driver
2415 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x100;
2416 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x100);
2422 cebix 1.1 WriteMacInt16(dce + dCtlFlags, DiskDriverFlags);
2423    
2424     // Open disk driver
2425 gbeauche 1.18 SheepString disk_str("\005.Disk");
2426     WriteMacInt32(pb + ioNamePtr, disk_str.addr());
2427     r.a[0] = pb;
2428 cebix 1.1 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 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x200;
2435 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x200);
2441 cebix 1.1 WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags);
2442    
2443     // Open CD-ROM driver
2444 gbeauche 1.18 SheepString apple_cd("\010.AppleCD");
2445     WriteMacInt32(pb + ioNamePtr, apple_cd.addr());
2446     r.a[0] = pb;
2447 cebix 1.1 Execute68kTrap(0xa000, &r); // Open()
2448     }
2449    
2450     // Install serial drivers
2451 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x300;
2452 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x300);
2458 cebix 1.1 WriteMacInt16(dce + dCtlFlags, 0x4d00);
2459    
2460 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x400;
2461 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x400);
2467 cebix 1.1 WriteMacInt16(dce + dCtlFlags, 0x4e00);
2468    
2469 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x500;
2470 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x500);
2476 cebix 1.1 WriteMacInt16(dce + dCtlFlags, 0x4d00);
2477    
2478 asvitkine 1.46 r.a[0] = ROMBase + sony_offset + 0x600;
2479 cebix 1.1 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 asvitkine 1.46 WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x600);
2485 cebix 1.1 WriteMacInt16(dce + dCtlFlags, 0x4e00);
2486     }