ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/rom_patches.cpp
Revision: 1.1
Committed: 2002-02-04T16:58:13Z (22 years, 9 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * rom_patches.cpp - ROM patches
3     *
4     * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
22     * TODO:
23     * IRQ_NEST must be handled atomically
24     * Don't use r1 in extra routines
25     */
26    
27     #include <string.h>
28    
29     #include "sysdeps.h"
30     #include "rom_patches.h"
31     #include "main.h"
32     #include "prefs.h"
33     #include "cpu_emulation.h"
34     #include "emul_op.h"
35     #include "xlowmem.h"
36     #include "sony.h"
37     #include "disk.h"
38     #include "cdrom.h"
39     #include "audio.h"
40     #include "audio_defs.h"
41     #include "serial.h"
42     #include "macos_util.h"
43    
44     #define DEBUG 0
45     #include "debug.h"
46    
47    
48     // 68k breakpoint address
49     //#define M68K_BREAK_POINT 0x29e0 // BootMe
50     //#define M68K_BREAK_POINT 0x2a1e // Boot block code returned
51     //#define M68K_BREAK_POINT 0x3150 // CritError
52     //#define M68K_BREAK_POINT 0x187ce // Unimplemented trap
53    
54     // PowerPC breakpoint address
55     //#define POWERPC_BREAK_POINT 0x36e6c0 // 68k emulator start
56    
57     #define DISABLE_SCSI 1
58    
59    
60     // Other ROM addresses
61     const uint32 CHECK_LOAD_PATCH_SPACE = 0x2f7f00;
62     const uint32 PUT_SCRAP_PATCH_SPACE = 0x2f7f80;
63     const uint32 GET_SCRAP_PATCH_SPACE = 0x2f7fc0;
64     const uint32 ADDR_MAP_PATCH_SPACE = 0x2f8000;
65    
66     // Global variables
67     int ROMType; // ROM type
68     static uint32 sony_offset; // Offset of .Sony driver resource
69    
70     // Prototypes
71     static bool patch_nanokernel_boot(void);
72     static bool patch_68k_emul(void);
73     static bool patch_nanokernel(void);
74     static bool patch_68k(void);
75    
76    
77     /*
78     * Search ROM for byte string, return ROM offset (or 0)
79     */
80    
81     static uint32 find_rom_data(uint32 start, uint32 end, const uint8 *data, uint32 data_len)
82     {
83     uint32 ofs = start;
84     while (ofs < end) {
85     if (!memcmp((void *)(ROM_BASE + ofs), data, data_len))
86     return ofs;
87     ofs++;
88     }
89     return 0;
90     }
91    
92    
93     /*
94     * Search ROM resource by type/ID, return ROM offset of resource data
95     */
96    
97     static uint32 rsrc_ptr = 0;
98    
99     // id = 4711 means "find any ID"
100     static uint32 find_rom_resource(uint32 s_type, int16 s_id = 4711, bool cont = false)
101     {
102     uint32 *lp = (uint32 *)(ROM_BASE + 0x1a);
103     uint32 x = ntohl(*lp);
104     uint8 *bp = (uint8 *)(ROM_BASE + x + 5);
105     uint32 header_size = *bp;
106    
107     if (!cont)
108     rsrc_ptr = x;
109     else if (rsrc_ptr == 0)
110     return 0;
111    
112     for (;;) {
113     lp = (uint32 *)(ROM_BASE + rsrc_ptr);
114     rsrc_ptr = ntohl(*lp);
115     if (rsrc_ptr == 0)
116     break;
117    
118     rsrc_ptr += header_size;
119    
120     lp = (uint32 *)(ROM_BASE + rsrc_ptr + 4);
121     uint32 data = ntohl(*lp); lp++;
122     uint32 type = ntohl(*lp); lp++;
123     int16 id = ntohs(*(int16 *)lp);
124     if (type == s_type && (id == s_id || s_id == 4711))
125     return data;
126     }
127     return 0;
128     }
129    
130    
131     /*
132     * Search offset of A-Trap routine in ROM
133     */
134    
135     static uint32 find_rom_trap(uint16 trap)
136     {
137     uint32 *lp = (uint32 *)(ROM_BASE + 0x22);
138     lp = (uint32 *)(ROM_BASE + ntohl(*lp));
139    
140     if (trap > 0xa800)
141     return ntohl(lp[trap & 0x3ff]);
142     else
143     return ntohl(lp[(trap & 0xff) + 0x400]);
144     }
145    
146    
147     /*
148     * List of audio sifters installed in ROM and System file
149     */
150    
151     struct sift_entry {
152     uint32 type;
153     int16 id;
154     };
155     static sift_entry sifter_list[32];
156     static int num_sifters;
157    
158     void AddSifter(uint32 type, int16 id)
159     {
160     if (FindSifter(type, id))
161     return;
162     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));
163     sifter_list[num_sifters].type = type;
164     sifter_list[num_sifters].id = id;
165     num_sifters++;
166     }
167    
168     bool FindSifter(uint32 type, int16 id)
169     {
170     for (int i=0; i<num_sifters; i++) {
171     if (sifter_list[i].type == type && sifter_list[i].id == id)
172     return true;
173     }
174     return false;
175     }
176    
177    
178     /*
179     * Driver stubs
180     */
181    
182     static const uint8 sony_driver[] = { // Replacement for .Sony driver
183     // Driver header
184     SonyDriverFlags >> 8, SonyDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
185     0x00, 0x18, // Open() offset
186     0x00, 0x1c, // Prime() offset
187     0x00, 0x20, // Control() offset
188     0x00, 0x2c, // Status() offset
189     0x00, 0x52, // Close() offset
190     0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79, // ".Sony"
191    
192     // Open()
193     M68K_EMUL_OP_SONY_OPEN >> 8, M68K_EMUL_OP_SONY_OPEN & 0xff,
194     0x4e, 0x75, // rts
195    
196     // Prime()
197     M68K_EMUL_OP_SONY_PRIME >> 8, M68K_EMUL_OP_SONY_PRIME & 0xff,
198     0x60, 0x0e, // bra IOReturn
199    
200     // Control()
201     M68K_EMUL_OP_SONY_CONTROL >> 8, M68K_EMUL_OP_SONY_CONTROL & 0xff,
202     0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
203     0x66, 0x04, // bne IOReturn
204     0x4e, 0x75, // rts
205    
206     // Status()
207     M68K_EMUL_OP_SONY_STATUS >> 8, M68K_EMUL_OP_SONY_STATUS & 0xff,
208    
209     // IOReturn
210     0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
211     0x08, 0x01, 0x00, 0x09, // btst #9,d1
212     0x67, 0x0c, // beq 1
213     0x4a, 0x40, // tst.w d0
214     0x6f, 0x02, // ble 2
215     0x42, 0x40, // clr.w d0
216     0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
217     0x4e, 0x75, // rts
218     0x4a, 0x40, //1 tst.w d0
219     0x6f, 0x04, // ble 3
220     0x42, 0x40, // clr.w d0
221     0x4e, 0x75, // rts
222     0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
223     0x4e, 0x75, // rts
224    
225     // Close()
226     0x70, 0xe8, // moveq #-24,d0
227     0x4e, 0x75 // rts
228     };
229    
230     static const uint8 disk_driver[] = { // Generic disk driver
231     // Driver header
232     DiskDriverFlags >> 8, DiskDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
233     0x00, 0x18, // Open() offset
234     0x00, 0x1c, // Prime() offset
235     0x00, 0x20, // Control() offset
236     0x00, 0x2c, // Status() offset
237     0x00, 0x52, // Close() offset
238     0x05, 0x2e, 0x44, 0x69, 0x73, 0x6b, // ".Disk"
239    
240     // Open()
241     M68K_EMUL_OP_DISK_OPEN >> 8, M68K_EMUL_OP_DISK_OPEN & 0xff,
242     0x4e, 0x75, // rts
243    
244     // Prime()
245     M68K_EMUL_OP_DISK_PRIME >> 8, M68K_EMUL_OP_DISK_PRIME & 0xff,
246     0x60, 0x0e, // bra IOReturn
247    
248     // Control()
249     M68K_EMUL_OP_DISK_CONTROL >> 8, M68K_EMUL_OP_DISK_CONTROL & 0xff,
250     0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
251     0x66, 0x04, // bne IOReturn
252     0x4e, 0x75, // rts
253    
254     // Status()
255     M68K_EMUL_OP_DISK_STATUS >> 8, M68K_EMUL_OP_DISK_STATUS & 0xff,
256    
257     // IOReturn
258     0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
259     0x08, 0x01, 0x00, 0x09, // btst #9,d1
260     0x67, 0x0c, // beq 1
261     0x4a, 0x40, // tst.w d0
262     0x6f, 0x02, // ble 2
263     0x42, 0x40, // clr.w d0
264     0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
265     0x4e, 0x75, // rts
266     0x4a, 0x40, //1 tst.w d0
267     0x6f, 0x04, // ble 3
268     0x42, 0x40, // clr.w d0
269     0x4e, 0x75, // rts
270     0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
271     0x4e, 0x75, // rts
272    
273     // Close()
274     0x70, 0xe8, // moveq #-24,d0
275     0x4e, 0x75 // rts
276     };
277    
278     static const uint8 cdrom_driver[] = { // CD-ROM driver
279     // Driver header
280     CDROMDriverFlags >> 8, CDROMDriverFlags & 0xff, 0, 0, 0, 0, 0, 0,
281     0x00, 0x1c, // Open() offset
282     0x00, 0x20, // Prime() offset
283     0x00, 0x24, // Control() offset
284     0x00, 0x30, // Status() offset
285     0x00, 0x56, // Close() offset
286     0x08, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x43, 0x44, 0x00, // ".AppleCD"
287    
288     // Open()
289     M68K_EMUL_OP_CDROM_OPEN >> 8, M68K_EMUL_OP_CDROM_OPEN & 0xff,
290     0x4e, 0x75, // rts
291    
292     // Prime()
293     M68K_EMUL_OP_CDROM_PRIME >> 8, M68K_EMUL_OP_CDROM_PRIME & 0xff,
294     0x60, 0x0e, // bra IOReturn
295    
296     // Control()
297     M68K_EMUL_OP_CDROM_CONTROL >> 8, M68K_EMUL_OP_CDROM_CONTROL & 0xff,
298     0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0)
299     0x66, 0x04, // bne IOReturn
300     0x4e, 0x75, // rts
301    
302     // Status()
303     M68K_EMUL_OP_CDROM_STATUS >> 8, M68K_EMUL_OP_CDROM_STATUS & 0xff,
304    
305     // IOReturn
306     0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1
307     0x08, 0x01, 0x00, 0x09, // btst #9,d1
308     0x67, 0x0c, // beq 1
309     0x4a, 0x40, // tst.w d0
310     0x6f, 0x02, // ble 2
311     0x42, 0x40, // clr.w d0
312     0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0)
313     0x4e, 0x75, // rts
314     0x4a, 0x40, //1 tst.w d0
315     0x6f, 0x04, // ble 3
316     0x42, 0x40, // clr.w d0
317     0x4e, 0x75, // rts
318     0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp)
319     0x4e, 0x75, // rts
320    
321     // Close()
322     0x70, 0xe8, // moveq #-24,d0
323     0x4e, 0x75 // rts
324     };
325    
326     #ifdef __linux__
327     static uint32 serial_nothing_tvect[2] = {(uint32)SerialNothing, 0};
328     static uint32 serial_open_tvect[2] = {(uint32)SerialOpen, 0};
329     static uint32 serial_prime_in_tvect[2] = {(uint32)SerialPrimeIn, 0};
330     static uint32 serial_prime_out_tvect[2] = {(uint32)SerialPrimeOut, 0};
331     static uint32 serial_control_tvect[2] = {(uint32)SerialControl, 0};
332     static uint32 serial_status_tvect[2] = {(uint32)SerialStatus, 0};
333     static uint32 serial_close_tvect[2] = {(uint32)SerialClose, 0};
334     #endif
335    
336     static const uint32 ain_driver[] = { // .AIn driver header
337     0x4d000000, 0x00000000,
338     0x00200040, 0x00600080,
339     0x00a0042e, 0x41496e00,
340     0x00000000, 0x00000000,
341     0xaafe0700, 0x00000000,
342     0x00000000, 0x00179822,
343     #ifdef __linux__
344     0x00010004, (uint32)serial_nothing_tvect,
345     #else
346     0x00010004, (uint32)SerialNothing,
347     #endif
348     0x00000000, 0x00000000,
349     0xaafe0700, 0x00000000,
350     0x00000000, 0x00179822,
351     #ifdef __linux__
352     0x00010004, (uint32)serial_prime_in_tvect,
353     #else
354     0x00010004, (uint32)SerialPrimeIn,
355     #endif
356     0x00000000, 0x00000000,
357     0xaafe0700, 0x00000000,
358     0x00000000, 0x00179822,
359     #ifdef __linux__
360     0x00010004, (uint32)serial_control_tvect,
361     #else
362     0x00010004, (uint32)SerialControl,
363     #endif
364     0x00000000, 0x00000000,
365     0xaafe0700, 0x00000000,
366     0x00000000, 0x00179822,
367     #ifdef __linux__
368     0x00010004, (uint32)serial_status_tvect,
369     #else
370     0x00010004, (uint32)SerialStatus,
371     #endif
372     0x00000000, 0x00000000,
373     0xaafe0700, 0x00000000,
374     0x00000000, 0x00179822,
375     #ifdef __linux__
376     0x00010004, (uint32)serial_nothing_tvect,
377     #else
378     0x00010004, (uint32)SerialNothing,
379     #endif
380     0x00000000, 0x00000000,
381     };
382    
383     static const uint32 aout_driver[] = { // .AOut driver header
384     0x4d000000, 0x00000000,
385     0x00200040, 0x00600080,
386     0x00a0052e, 0x414f7574,
387     0x00000000, 0x00000000,
388     0xaafe0700, 0x00000000,
389     0x00000000, 0x00179822,
390     #ifdef __linux__
391     0x00010004, (uint32)serial_open_tvect,
392     #else
393     0x00010004, (uint32)SerialOpen,
394     #endif
395     0x00000000, 0x00000000,
396     0xaafe0700, 0x00000000,
397     0x00000000, 0x00179822,
398     #ifdef __linux__
399     0x00010004, (uint32)serial_prime_out_tvect,
400     #else
401     0x00010004, (uint32)SerialPrimeOut,
402     #endif
403     0x00000000, 0x00000000,
404     0xaafe0700, 0x00000000,
405     0x00000000, 0x00179822,
406     #ifdef __linux__
407     0x00010004, (uint32)serial_control_tvect,
408     #else
409     0x00010004, (uint32)SerialControl,
410     #endif
411     0x00000000, 0x00000000,
412     0xaafe0700, 0x00000000,
413     0x00000000, 0x00179822,
414     #ifdef __linux__
415     0x00010004, (uint32)serial_status_tvect,
416     #else
417     0x00010004, (uint32)SerialStatus,
418     #endif
419     0x00000000, 0x00000000,
420     0xaafe0700, 0x00000000,
421     0x00000000, 0x00179822,
422     #ifdef __linux__
423     0x00010004, (uint32)serial_close_tvect,
424     #else
425     0x00010004, (uint32)SerialClose,
426     #endif
427     0x00000000, 0x00000000,
428     };
429    
430     static const uint32 bin_driver[] = { // .BIn driver header
431     0x4d000000, 0x00000000,
432     0x00200040, 0x00600080,
433     0x00a0042e, 0x42496e00,
434     0x00000000, 0x00000000,
435     0xaafe0700, 0x00000000,
436     0x00000000, 0x00179822,
437     #ifdef __linux__
438     0x00010004, (uint32)serial_nothing_tvect,
439     #else
440     0x00010004, (uint32)SerialNothing,
441     #endif
442     0x00000000, 0x00000000,
443     0xaafe0700, 0x00000000,
444     0x00000000, 0x00179822,
445     #ifdef __linux__
446     0x00010004, (uint32)serial_prime_in_tvect,
447     #else
448     0x00010004, (uint32)SerialPrimeIn,
449     #endif
450     0x00000000, 0x00000000,
451     0xaafe0700, 0x00000000,
452     0x00000000, 0x00179822,
453     #ifdef __linux__
454     0x00010004, (uint32)serial_control_tvect,
455     #else
456     0x00010004, (uint32)SerialControl,
457     #endif
458     0x00000000, 0x00000000,
459     0xaafe0700, 0x00000000,
460     0x00000000, 0x00179822,
461     #ifdef __linux__
462     0x00010004, (uint32)serial_status_tvect,
463     #else
464     0x00010004, (uint32)SerialStatus,
465     #endif
466     0x00000000, 0x00000000,
467     0xaafe0700, 0x00000000,
468     0x00000000, 0x00179822,
469     #ifdef __linux__
470     0x00010004, (uint32)serial_nothing_tvect,
471     #else
472     0x00010004, (uint32)SerialNothing,
473     #endif
474     0x00000000, 0x00000000,
475     };
476    
477     static const uint32 bout_driver[] = { // .BOut driver header
478     0x4d000000, 0x00000000,
479     0x00200040, 0x00600080,
480     0x00a0052e, 0x424f7574,
481     0x00000000, 0x00000000,
482     0xaafe0700, 0x00000000,
483     0x00000000, 0x00179822,
484     #ifdef __linux__
485     0x00010004, (uint32)serial_open_tvect,
486     #else
487     0x00010004, (uint32)SerialOpen,
488     #endif
489     0x00000000, 0x00000000,
490     0xaafe0700, 0x00000000,
491     0x00000000, 0x00179822,
492     #ifdef __linux__
493     0x00010004, (uint32)serial_prime_out_tvect,
494     #else
495     0x00010004, (uint32)SerialPrimeOut,
496     #endif
497     0x00000000, 0x00000000,
498     0xaafe0700, 0x00000000,
499     0x00000000, 0x00179822,
500     #ifdef __linux__
501     0x00010004, (uint32)serial_control_tvect,
502     #else
503     0x00010004, (uint32)SerialControl,
504     #endif
505     0x00000000, 0x00000000,
506     0xaafe0700, 0x00000000,
507     0x00000000, 0x00179822,
508     #ifdef __linux__
509     0x00010004, (uint32)serial_status_tvect,
510     #else
511     0x00010004, (uint32)SerialStatus,
512     #endif
513     0x00000000, 0x00000000,
514     0xaafe0700, 0x00000000,
515     0x00000000, 0x00179822,
516     #ifdef __linux__
517     0x00010004, (uint32)serial_close_tvect,
518     #else
519     0x00010004, (uint32)SerialClose,
520     #endif
521     0x00000000, 0x00000000,
522     };
523    
524     static const uint8 adbop_patch[] = { // Call ADBOp() completion procedure
525     // The completion procedure may call ADBOp() again!
526     0x40, 0xe7, // move sr,-(sp)
527     0x00, 0x7c, 0x07, 0x00, // ori #$0700,sr
528     M68K_EMUL_OP_ADBOP >> 8, M68K_EMUL_OP_ADBOP & 0xff,
529     0x48, 0xe7, 0x70, 0xf0, // movem.l d1-d3/a0-a3,-(sp)
530     0x26, 0x48, // move.l a0,a3
531     0x4a, 0xab, 0x00, 0x04, // tst.l 4(a3)
532     0x67, 0x00, 0x00, 0x18, // beq 1
533     0x20, 0x53, // move.l (a3),a0
534     0x22, 0x6b, 0x00, 0x04, // move.l 4(a3),a1
535     0x24, 0x6b, 0x00, 0x08, // move.l 8(a3),a2
536     0x26, 0x78, 0x0c, 0xf8, // move.l $cf8,a3
537     0x4e, 0x91, // jsr (a1)
538     0x70, 0x00, // moveq #0,d0
539     0x60, 0x00, 0x00, 0x04, // bra 2
540     0x70, 0xff, //1 moveq #-1,d0
541     0x4c, 0xdf, 0x0f, 0x0e, //2 movem.l (sp)+,d1-d3/a0-a3
542     0x46, 0xdf, // move (sp)+,sr
543     0x4e, 0x75 // rts
544     };
545    
546    
547     /*
548     * Install ROM patches (RAMBase and KernelDataAddr must be set)
549     */
550    
551     bool PatchROM(void)
552     {
553     // Print ROM info
554     D(bug("Checksum: %08lx\n", ntohl(*(uint32 *)ROM_BASE)));
555     D(bug("Version: %04x\n", ntohs(*(uint16 *)(ROM_BASE + 8))));
556     D(bug("Sub Version: %04x\n", ntohs(*(uint16 *)(ROM_BASE + 18))));
557     D(bug("Nanokernel ID: %s\n", (char *)ROM_BASE + 0x30d064));
558     D(bug("Resource Map at %08lx\n", ntohl(*(uint32 *)(ROM_BASE + 26))));
559     D(bug("Trap Tables at %08lx\n\n", ntohl(*(uint32 *)(ROM_BASE + 34))));
560    
561     // Detect ROM type
562     if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot TNT", 8))
563     ROMType = ROMTYPE_TNT;
564     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Alchemy", 12))
565     ROMType = ROMTYPE_ALCHEMY;
566     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Zanzibar", 13))
567     ROMType = ROMTYPE_ZANZIBAR;
568     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12))
569     ROMType = ROMTYPE_GAZELLE;
570     else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8))
571     ROMType = ROMTYPE_NEWWORLD;
572     else
573     return false;
574    
575     // Apply patches
576     if (!patch_nanokernel_boot()) return false;
577     if (!patch_68k_emul()) return false;
578     if (!patch_nanokernel()) return false;
579     if (!patch_68k()) return false;
580    
581     #ifdef M68K_BREAK_POINT
582     // Install 68k breakpoint
583     uint16 *wp = (uint16 *)(ROM_BASE + M68K_BREAK_POINT);
584     *wp++ = htons(M68K_EMUL_BREAK);
585     *wp = htons(M68K_EMUL_RETURN);
586     #endif
587    
588     #ifdef POWERPC_BREAK_POINT
589     // Install PowerPC breakpoint
590     uint32 *lp = (uint32 *)(ROM_BASE + POWERPC_BREAK_POINT);
591     *lp = htonl(0);
592     #endif
593    
594     // Copy 68k emulator to 2MB boundary
595     memcpy((void *)(ROM_BASE + ROM_SIZE), (void *)(ROM_BASE + ROM_SIZE - 0x100000), 0x100000);
596     return true;
597     }
598    
599    
600     /*
601     * Nanokernel boot routine patches
602     */
603    
604     static bool patch_nanokernel_boot(void)
605     {
606     uint32 *lp;
607    
608     // ROM boot structure patches
609     lp = (uint32 *)(ROM_BASE + 0x30d000);
610     lp[0x9c >> 2] = htonl(KernelDataAddr); // LA_InfoRecord
611     lp[0xa0 >> 2] = htonl(KernelDataAddr); // LA_KernelData
612     lp[0xa4 >> 2] = htonl(KernelDataAddr + 0x1000); // LA_EmulatorData
613     lp[0xa8 >> 2] = htonl(ROM_BASE + 0x480000); // LA_DispatchTable
614     lp[0xac >> 2] = htonl(ROM_BASE + 0x460000); // LA_EmulatorCode
615     lp[0x360 >> 2] = htonl(0); // Physical RAM base (? on NewWorld ROM, this contains -1)
616     lp[0xfd8 >> 2] = htonl(ROM_BASE + 0x2a); // 68k reset vector
617    
618     // Skip SR/BAT/SDR init
619     if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_NEWWORLD) {
620     lp = (uint32 *)(ROM_BASE + 0x310000);
621     *lp++ = htonl(POWERPC_NOP);
622     *lp = htonl(0x38000000);
623     }
624     static const uint32 sr_init_loc[] = {0x3101b0, 0x3101b0, 0x3101b0, 0x3101ec, 0x310200};
625     lp = (uint32 *)(ROM_BASE + 0x310008);
626     *lp = htonl(0x48000000 | (sr_init_loc[ROMType] - 8) & 0xffff); // b ROM_BASE+0x3101b0
627     lp = (uint32 *)(ROM_BASE + sr_init_loc[ROMType]);
628     *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA); // lwz r1,(pointer to Kernel Data)
629     *lp++ = htonl(0x3da0dead); // lis r13,0xdead (start of kernel memory)
630     *lp++ = htonl(0x3dc00010); // lis r14,0x0010 (size of page table)
631     *lp = htonl(0x3de00010); // lis r15,0x0010 (size of kernel memory)
632    
633     // Don't read PVR
634     static const uint32 pvr_loc[] = {0x3103b0, 0x3103b4, 0x3103b4, 0x310400, 0x310438};
635     lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
636     *lp = htonl(0x81800000 + XLM_PVR); // lwz r12,(theoretical PVR)
637    
638     // Set CPU specific data (even if ROM doesn't have support for that CPU)
639     lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
640     if (ntohl(lp[6]) != 0x2c0c0001)
641     return false;
642     uint32 ofs = ntohl(lp[7]) & 0xffff;
643     D(bug("ofs %08lx\n", ofs));
644     lp[8] = htonl((ntohl(lp[8]) & 0xffff) | 0x48000000); // beq -> b
645     uint32 loc = (ntohl(lp[8]) & 0xffff) + (uint32)(lp+8) - ROM_BASE;
646     D(bug("loc %08lx\n", loc));
647     lp = (uint32 *)(ROM_BASE + ofs + 0x310000);
648     switch (PVR >> 16) {
649     case 1: // 601
650     lp[0] = htonl(0x1000); // Page size
651     lp[1] = htonl(0x8000); // Data cache size
652     lp[2] = htonl(0x8000); // Inst cache size
653     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
654     lp[4] = htonl(0x00010040); // Unified caches/Inst cache line size
655     lp[5] = htonl(0x00400020); // Data cache line size/Data cache block size touch
656     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
657     lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
658     lp[8] = htonl(0x01000002); // TLB total size/TLB assoc
659     break;
660     case 3: // 603
661     lp[0] = htonl(0x1000); // Page size
662     lp[1] = htonl(0x2000); // Data cache size
663     lp[2] = htonl(0x2000); // Inst cache size
664     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
665     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
666     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
667     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
668     lp[7] = htonl(0x00020002); // Inst cache assoc/Data cache assoc
669     lp[8] = htonl(0x00400002); // TLB total size/TLB assoc
670     break;
671     case 4: // 604
672     lp[0] = htonl(0x1000); // Page size
673     lp[1] = htonl(0x4000); // Data cache size
674     lp[2] = htonl(0x4000); // Inst cache size
675     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
676     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
677     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
678     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
679     lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
680     lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
681     break;
682     // case 5: // 740?
683     case 6: // 603e
684     case 7: // 603ev
685     lp[0] = htonl(0x1000); // Page size
686     lp[1] = htonl(0x4000); // Data cache size
687     lp[2] = htonl(0x4000); // Inst cache size
688     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
689     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
690     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
691     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
692     lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
693     lp[8] = htonl(0x00400002); // TLB total size/TLB assoc
694     break;
695     case 8: // 750
696     lp[0] = htonl(0x1000); // Page size
697     lp[1] = htonl(0x8000); // Data cache size
698     lp[2] = htonl(0x8000); // Inst cache size
699     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
700     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
701     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
702     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
703     lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
704     lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
705     break;
706     case 9: // 604e
707     case 10: // 604ev5
708     lp[0] = htonl(0x1000); // Page size
709     lp[1] = htonl(0x8000); // Data cache size
710     lp[2] = htonl(0x8000); // Inst cache size
711     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
712     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
713     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
714     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
715     lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc
716     lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
717     break;
718     // case 11: // X704?
719     case 12: // ???
720     lp[0] = htonl(0x1000); // Page size
721     lp[1] = htonl(0x8000); // Data cache size
722     lp[2] = htonl(0x8000); // Inst cache size
723     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
724     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
725     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
726     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
727     lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
728     lp[8] = htonl(0x00800002); // TLB total size/TLB assoc
729     break;
730     case 13: // ???
731     lp[0] = htonl(0x1000); // Page size
732     lp[1] = htonl(0x8000); // Data cache size
733     lp[2] = htonl(0x8000); // Inst cache size
734     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
735     lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size
736     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
737     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
738     lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
739     lp[8] = htonl(0x01000004); // TLB total size/TLB assoc
740     break;
741     // case 50: // 821
742     // case 80: // 860
743     case 96: // ???
744     lp[0] = htonl(0x1000); // Page size
745     lp[1] = htonl(0x8000); // Data cache size
746     lp[2] = htonl(0x8000); // Inst cache size
747     lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size
748     lp[4] = htonl(0x00010020); // Unified caches/Inst cache line size
749     lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch
750     lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size
751     lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc
752     lp[8] = htonl(0x00800004); // TLB total size/TLB assoc
753     break;
754     default:
755     printf("WARNING: Unknown CPU type\n");
756     break;
757     }
758    
759     // Don't set SPRG3, don't test MQ
760     lp = (uint32 *)(ROM_BASE + loc + 0x20);
761     *lp++ = htonl(POWERPC_NOP);
762     lp++;
763     *lp++ = htonl(POWERPC_NOP);
764     lp++;
765     *lp = htonl(POWERPC_NOP);
766    
767     // Don't read MSR
768     lp = (uint32 *)(ROM_BASE + loc + 0x40);
769     *lp = htonl(0x39c00000); // li r14,0
770    
771     // Don't write to DEC
772     lp = (uint32 *)(ROM_BASE + loc + 0x70);
773     *lp++ = htonl(POWERPC_NOP);
774     loc = (ntohl(lp[0]) & 0xffff) + (uint32)lp - ROM_BASE;
775     D(bug("loc %08lx\n", loc));
776    
777     // Don't set SPRG3
778     lp = (uint32 *)(ROM_BASE + loc + 0x2c);
779     *lp = htonl(POWERPC_NOP);
780    
781     // Don't read PVR
782     static const uint32 pvr_ofs[] = {0x138, 0x138, 0x138, 0x140, 0x148};
783     lp = (uint32 *)(ROM_BASE + loc + pvr_ofs[ROMType]);
784     *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
785     lp = (uint32 *)(ROM_BASE + loc + 0x170);
786     if (ntohl(*lp) == 0x7eff42a6) // NewWorld ROM
787     *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR)
788     lp = (uint32 *)(ROM_BASE + 0x313134);
789     if (ntohl(*lp) == 0x7e5f42a6)
790     *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR)
791     lp = (uint32 *)(ROM_BASE + 0x3131f4);
792     if (ntohl(*lp) == 0x7e5f42a6) // NewWorld ROM
793     *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR)
794    
795     // Don't read SDR1
796     static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c};
797     lp = (uint32 *)(ROM_BASE + loc + sdr1_ofs[ROMType]);
798     *lp++ = htonl(0x3d00dead); // lis r8,0xdead (pointer to page table)
799     *lp++ = htonl(0x3ec0001f); // lis r22,0x001f (size of page table)
800     *lp = htonl(POWERPC_NOP);
801    
802     // Don't clear page table
803     static const uint32 pgtb_ofs[] = {0x198, 0x198, 0x198, 0x1a0, 0x1c4};
804     lp = (uint32 *)(ROM_BASE + loc + pgtb_ofs[ROMType]);
805     *lp = htonl(POWERPC_NOP);
806    
807     // Don't invalidate TLB
808     static const uint32 tlb_ofs[] = {0x1a0, 0x1a0, 0x1a0, 0x1a8, 0x1cc};
809     lp = (uint32 *)(ROM_BASE + loc + tlb_ofs[ROMType]);
810     *lp = htonl(POWERPC_NOP);
811    
812     // Don't create RAM descriptor table
813     static const uint32 desc_ofs[] = {0x350, 0x350, 0x350, 0x358, 0x37c};
814     lp = (uint32 *)(ROM_BASE + loc + desc_ofs[ROMType]);
815     *lp = htonl(POWERPC_NOP);
816    
817     // Don't load SRs and BATs
818     static const uint32 sr_ofs[] = {0x3d8, 0x3d8, 0x3d8, 0x3e0, 0x404};
819     lp = (uint32 *)(ROM_BASE + loc + sr_ofs[ROMType]);
820     *lp = htonl(POWERPC_NOP);
821    
822     // Don't mess with SRs
823     static const uint32 sr2_ofs[] = {0x312118, 0x312118, 0x312118, 0x312118, 0x3121b4};
824     lp = (uint32 *)(ROM_BASE + sr2_ofs[ROMType]);
825     *lp = htonl(POWERPC_BLR);
826    
827     // Don't check performance monitor
828     static const uint32 pm_ofs[] = {0x313148, 0x313148, 0x313148, 0x313148, 0x313218};
829     lp = (uint32 *)(ROM_BASE + pm_ofs[ROMType]);
830     while (ntohl(*lp) != 0x7e58eba6) lp++;
831     *lp++ = htonl(POWERPC_NOP);
832     while (ntohl(*lp) != 0x7e78eaa6) lp++;
833     *lp++ = htonl(POWERPC_NOP);
834     while (ntohl(*lp) != 0x7e59eba6) lp++;
835     *lp++ = htonl(POWERPC_NOP);
836     while (ntohl(*lp) != 0x7e79eaa6) lp++;
837     *lp++ = htonl(POWERPC_NOP);
838     while (ntohl(*lp) != 0x7e5aeba6) lp++;
839     *lp++ = htonl(POWERPC_NOP);
840     while (ntohl(*lp) != 0x7e7aeaa6) lp++;
841     *lp++ = htonl(POWERPC_NOP);
842     while (ntohl(*lp) != 0x7e5beba6) lp++;
843     *lp++ = htonl(POWERPC_NOP);
844     while (ntohl(*lp) != 0x7e7beaa6) lp++;
845     *lp++ = htonl(POWERPC_NOP);
846     while (ntohl(*lp) != 0x7e5feba6) lp++;
847     *lp++ = htonl(POWERPC_NOP);
848     while (ntohl(*lp) != 0x7e7feaa6) lp++;
849     *lp++ = htonl(POWERPC_NOP);
850     while (ntohl(*lp) != 0x7e5ceba6) lp++;
851     *lp++ = htonl(POWERPC_NOP);
852     while (ntohl(*lp) != 0x7e7ceaa6) lp++;
853     *lp++ = htonl(POWERPC_NOP);
854     while (ntohl(*lp) != 0x7e5deba6) lp++;
855     *lp++ = htonl(POWERPC_NOP);
856     while (ntohl(*lp) != 0x7e7deaa6) lp++;
857     *lp++ = htonl(POWERPC_NOP);
858     while (ntohl(*lp) != 0x7e5eeba6) lp++;
859     *lp++ = htonl(POWERPC_NOP);
860     while (ntohl(*lp) != 0x7e7eeaa6) lp++;
861     *lp++ = htonl(POWERPC_NOP);
862    
863     // Jump to 68k emulator
864     static const uint32 jump68k_ofs[] = {0x40c, 0x40c, 0x40c, 0x414, 0x438};
865     lp = (uint32 *)(ROM_BASE + loc + jump68k_ofs[ROMType]);
866     *lp++ = htonl(0x80610634); // lwz r3,0x0634(r1) (pointer to Emulator Data)
867     *lp++ = htonl(0x8081119c); // lwz r4,0x119c(r1) (pointer to opcode table)
868     *lp++ = htonl(0x80011184); // lwz r0,0x1184(r1) (pointer to emulator init routine)
869     *lp++ = htonl(0x7c0903a6); // mtctr r0
870     *lp = htonl(POWERPC_BCTR);
871     return true;
872     }
873    
874    
875     /*
876     * 68k emulator patches
877     */
878    
879     static bool patch_68k_emul(void)
880     {
881     uint32 *lp;
882     uint32 base;
883    
884     // Overwrite twi instructions
885     static const uint32 twi_loc[] = {0x36e680, 0x36e6c0, 0x36e6c0, 0x36e6c0, 0x36e740};
886     base = twi_loc[ROMType];
887     lp = (uint32 *)(ROM_BASE + base);
888     *lp++ = htonl(0x48000000 + 0x36f900 - base); // b 0x36f900 (Emulator start)
889     *lp++ = htonl(0x48000000 + 0x36fa00 - base - 4); // b 0x36fa00 (Mixed mode)
890     *lp++ = htonl(0x48000000 + 0x36fb00 - base - 8); // b 0x36fb00 (Reset/FC1E opcode)
891     *lp++ = htonl(0x48000000 + 0x36fc00 - base - 12); // FE0A opcode
892     *lp++ = htonl(POWERPC_ILLEGAL); // Interrupt
893     *lp++ = htonl(POWERPC_ILLEGAL); // ?
894     *lp++ = htonl(POWERPC_ILLEGAL);
895     *lp++ = htonl(POWERPC_ILLEGAL);
896     *lp++ = htonl(POWERPC_ILLEGAL);
897     *lp++ = htonl(POWERPC_ILLEGAL);
898     *lp++ = htonl(POWERPC_ILLEGAL);
899     *lp++ = htonl(POWERPC_ILLEGAL);
900     *lp++ = htonl(POWERPC_ILLEGAL);
901     *lp++ = htonl(POWERPC_ILLEGAL);
902     *lp++ = htonl(POWERPC_ILLEGAL);
903     *lp = htonl(POWERPC_ILLEGAL);
904    
905     #if EMULATED_PPC
906     // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes
907     lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3));
908     *lp++ = htonl(POWERPC_EMUL_OP);
909     *lp++ = htonl(0x4bf66e80); // b 0x366084
910     *lp++ = htonl(POWERPC_EMUL_OP | 1);
911     *lp++ = htonl(0x4bf66e78); // b 0x366084
912     for (int i=0; i<OP_MAX; i++) {
913     *lp++ = htonl(POWERPC_EMUL_OP | (i + 2));
914     *lp++ = htonl(0x4bf66e70 - i*8); // b 0x366084
915     }
916     #else
917     // Install EMUL_RETURN, EXEC_RETURN and EMUL_OP opcodes
918     lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_RETURN << 3));
919     *lp++ = htonl(0x80000000 + XLM_EMUL_RETURN_PROC); // lwz r0,XLM_EMUL_RETURN_PROC
920     *lp++ = htonl(0x4bf705fc); // b 0x36f800
921     *lp++ = htonl(0x80000000 + XLM_EXEC_RETURN_PROC); // lwz r0,XLM_EXEC_RETURN_PROC
922     *lp++ = htonl(0x4bf705f4); // b 0x36f800
923     for (int i=0; i<OP_MAX; i++) {
924     *lp++ = htonl(0x38a00000 + i); // li r5,OP_*
925     *lp++ = htonl(0x4bf705f4 - i*8); // b 0x36f808
926     }
927    
928     // Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP
929     lp = (uint32 *)(ROM_BASE + 0x36f800);
930     *lp++ = htonl(0x7c0803a6); // mtlr r0
931     *lp++ = htonl(0x4e800020); // blr
932    
933     *lp++ = htonl(0x80000000 + XLM_EMUL_OP_PROC); // lwz r0,XLM_EMUL_OP_PROC
934     *lp++ = htonl(0x7c0803a6); // mtlr r0
935     *lp = htonl(0x4e800020); // blr
936     #endif
937    
938     // Extra routine for 68k emulator start
939     lp = (uint32 *)(ROM_BASE + 0x36f900);
940     *lp++ = htonl(0x7c2903a6); // mtctr r1
941     *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
942     *lp++ = htonl(0x38210001); // addi r1,r1,1
943     *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
944     *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
945     *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
946     *lp++ = htonl(0x7cc902a6); // mfctr r6
947     *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
948     *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
949     *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
950     *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
951     *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
952     *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
953     *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
954     *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
955     *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
956     *lp++ = htonl(0x7da00026); // mfcr r13
957     *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
958     *lp++ = htonl(0x7d8802a6); // mflr r12
959     *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
960     *lp++ = htonl(0x814105f0); // lwz r10,0x05f0(r1)
961     *lp++ = htonl(0x7d4803a6); // mtlr r10
962     *lp++ = htonl(0x7d8a6378); // mr r10,r12
963     *lp++ = htonl(0x3d600002); // lis r11,0x0002
964     *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
965     *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
966     *lp = htonl(0x4e800020); // blr
967    
968     // Extra routine for Mixed Mode
969     lp = (uint32 *)(ROM_BASE + 0x36fa00);
970     *lp++ = htonl(0x7c2903a6); // mtctr r1
971     *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
972     *lp++ = htonl(0x38210001); // addi r1,r1,1
973     *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
974     *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
975     *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
976     *lp++ = htonl(0x7cc902a6); // mfctr r6
977     *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
978     *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
979     *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
980     *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
981     *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
982     *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
983     *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
984     *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
985     *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
986     *lp++ = htonl(0x7da00026); // mfcr r13
987     *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
988     *lp++ = htonl(0x7d8802a6); // mflr r12
989     *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
990     *lp++ = htonl(0x814105f4); // lwz r10,0x05f4(r1)
991     *lp++ = htonl(0x7d4803a6); // mtlr r10
992     *lp++ = htonl(0x7d8a6378); // mr r10,r12
993     *lp++ = htonl(0x3d600002); // lis r11,0x0002
994     *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
995     *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
996     *lp = htonl(0x4e800020); // blr
997    
998     // Extra routine for Reset/FC1E opcode
999     lp = (uint32 *)(ROM_BASE + 0x36fc00);
1000     *lp++ = htonl(0x7c2903a6); // mtctr r1
1001     *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1002     *lp++ = htonl(0x38210001); // addi r1,r1,1
1003     *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1004     *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1005     *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1006     *lp++ = htonl(0x7cc902a6); // mfctr r6
1007     *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1008     *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1009     *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1010     *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1011     *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1012     *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1013     *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1014     *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1015     *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1016     *lp++ = htonl(0x7da00026); // mfcr r13
1017     *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1018     *lp++ = htonl(0x7d8802a6); // mflr r12
1019     *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1020     *lp++ = htonl(0x814105f4); // lwz r10,0x05f8(r1)
1021     *lp++ = htonl(0x7d4803a6); // mtlr r10
1022     *lp++ = htonl(0x7d8a6378); // mr r10,r12
1023     *lp++ = htonl(0x3d600002); // lis r11,0x0002
1024     *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1025     *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1026     *lp = htonl(0x4e800020); // blr
1027    
1028     // Extra routine for FE0A opcode (QuickDraw 3D needs this)
1029     lp = (uint32 *)(ROM_BASE + 0x36fc00);
1030     *lp++ = htonl(0x7c2903a6); // mtctr r1
1031     *lp++ = htonl(0x80200000 + XLM_IRQ_NEST); // lwz r1,XLM_IRQ_NEST
1032     *lp++ = htonl(0x38210001); // addi r1,r1,1
1033     *lp++ = htonl(0x90200000 + XLM_IRQ_NEST); // stw r1,XLM_IRQ_NEST
1034     *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA);// lwz r1,XLM_KERNEL_DATA
1035     *lp++ = htonl(0x90c10018); // stw r6,0x18(r1)
1036     *lp++ = htonl(0x7cc902a6); // mfctr r6
1037     *lp++ = htonl(0x90c10004); // stw r6,$0004(r1)
1038     *lp++ = htonl(0x80c1065c); // lwz r6,$065c(r1)
1039     *lp++ = htonl(0x90e6013c); // stw r7,$013c(r6)
1040     *lp++ = htonl(0x91060144); // stw r8,$0144(r6)
1041     *lp++ = htonl(0x9126014c); // stw r9,$014c(r6)
1042     *lp++ = htonl(0x91460154); // stw r10,$0154(r6)
1043     *lp++ = htonl(0x9166015c); // stw r11,$015c(r6)
1044     *lp++ = htonl(0x91860164); // stw r12,$0164(r6)
1045     *lp++ = htonl(0x91a6016c); // stw r13,$016c(r6)
1046     *lp++ = htonl(0x7da00026); // mfcr r13
1047     *lp++ = htonl(0x80e10660); // lwz r7,$0660(r1)
1048     *lp++ = htonl(0x7d8802a6); // mflr r12
1049     *lp++ = htonl(0x50e74001); // rlwimi. r7,r7,8,$80000000
1050     *lp++ = htonl(0x814105f4); // lwz r10,0x05fc(r1)
1051     *lp++ = htonl(0x7d4803a6); // mtlr r10
1052     *lp++ = htonl(0x7d8a6378); // mr r10,r12
1053     *lp++ = htonl(0x3d600002); // lis r11,0x0002
1054     *lp++ = htonl(0x616bf072); // ori r11,r11,0xf072 (MSR)
1055     *lp++ = htonl(0x50e7deb4); // rlwimi r7,r7,27,$00000020
1056     *lp = htonl(0x4e800020); // blr
1057    
1058     // Patch DR emulator to jump to right address when an interrupt occurs
1059     lp = (uint32 *)(ROM_BASE + 0x370000);
1060     while (lp < (uint32 *)(ROM_BASE + 0x380000)) {
1061     if (ntohl(*lp) == 0x4ca80020) // bclr 5,8
1062     goto dr_found;
1063     lp++;
1064     }
1065     D(bug("DR emulator patch location not found\n"));
1066     return false;
1067     dr_found:
1068     lp++;
1069     *lp = htonl(0x48000000 + 0xf000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b DR_CACHE_BASE+0x1f000
1070     lp = (uint32 *)(ROM_BASE + 0x37f000);
1071     *lp++ = htonl(0x3c000000 + ((ROM_BASE + 0x46d0a4) >> 16)); // lis r0,xxx
1072     *lp++ = htonl(0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff)); // ori r0,r0,xxx
1073     *lp++ = htonl(0x7c0903a6); // mtctr r0
1074     *lp = htonl(POWERPC_BCTR); // bctr
1075     return true;
1076     }
1077    
1078    
1079     /*
1080     * Nanokernel patches
1081     */
1082    
1083     static bool patch_nanokernel(void)
1084     {
1085     uint32 *lp;
1086    
1087     // Patch Mixed Mode trap
1088     lp = (uint32 *)(ROM_BASE + 0x313c90); // Don't translate virtual->physical
1089     while (ntohl(*lp) != 0x3ba10320) lp++;
1090     lp++;
1091     *lp++ = htonl(0x7f7fdb78); // mr r31,r27
1092     lp++;
1093     *lp = htonl(POWERPC_NOP);
1094    
1095     lp = (uint32 *)(ROM_BASE + 0x313c3c); // Don't activate PPC exception table
1096     while (ntohl(*lp) != 0x39010420) lp++;
1097     *lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE
1098     *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE
1099    
1100     lp = (uint32 *)(ROM_BASE + 0x312e88); // Don't modify MSR to turn on FPU
1101     while (ntohl(*lp) != 0x556b04e2) lp++;
1102     lp -= 4;
1103     *lp++ = htonl(POWERPC_NOP);
1104     lp++;
1105     *lp++ = htonl(POWERPC_NOP);
1106     lp++;
1107     *lp = htonl(POWERPC_NOP);
1108    
1109     lp = (uint32 *)(ROM_BASE + 0x312b3c); // Always save FPU state
1110     while (ntohl(*lp) != 0x81010668) lp++;
1111     lp--;
1112     *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88
1113    
1114     lp = (uint32 *)(ROM_BASE + 0x312b44); // Don't read DEC
1115     while (ntohl(*lp) != 0x7ff602a6) lp++;
1116     *lp = htonl(0x3be00000); // li r31,0
1117    
1118     lp = (uint32 *)(ROM_BASE + 0x312b50); // Don't write DEC
1119     while (ntohl(*lp) != 0x7d1603a6) lp++;
1120     #if 1
1121     *lp++ = htonl(POWERPC_NOP);
1122     *lp = htonl(POWERPC_NOP);
1123     #else
1124     *lp++ = htonl(0x39000040); // li r8,0x40
1125     *lp = htonl(0x990600e4); // stb r8,0xe4(r6)
1126     #endif
1127    
1128     lp = (uint32 *)(ROM_BASE + 0x312b9c); // Always restore FPU state
1129     while (ntohl(*lp) != 0x7c00092d) lp++;
1130     lp--;
1131     *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc
1132    
1133     lp = (uint32 *)(ROM_BASE + 0x312a68); // Don't activate 68k exception table
1134     while (ntohl(*lp) != 0x39010360) lp++;
1135     *lp++ = htonl(0x39000000 + MODE_68K); // li r8,MODE_68K
1136     *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE
1137    
1138     // Patch 68k emulator trap routine
1139     lp = (uint32 *)(ROM_BASE + 0x312994); // Always restore FPU state
1140     while (ntohl(*lp) != 0x39260040) lp++;
1141     lp--;
1142     *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4
1143    
1144     lp = (uint32 *)(ROM_BASE + 0x312dd8); // Don't modify MSR to turn on FPU
1145     while (ntohl(*lp) != 0x810600e4) lp++;
1146     lp--;
1147     *lp++ = htonl(POWERPC_NOP);
1148     lp += 2;
1149     *lp++ = htonl(POWERPC_NOP);
1150     lp++;
1151     *lp++ = htonl(POWERPC_NOP);
1152     *lp++ = htonl(POWERPC_NOP);
1153     *lp = htonl(POWERPC_NOP);
1154    
1155     // Patch trap return routine
1156     lp = (uint32 *)(ROM_BASE + 0x312c20);
1157     while (ntohl(*lp) != 0x7d5a03a6) lp++;
1158     *lp++ = htonl(0x7d4903a6); // mtctr r10
1159     *lp++ = htonl(0x7daff120); // mtcr r13
1160     *lp = htonl(0x48000000 + 0x8000 - (((uint32)lp - ROM_BASE) & 0xffff)); // b ROM_BASE+0x318000
1161     uint32 xlp = ((uint32)(lp+1) - ROM_BASE) & 0xffff;
1162    
1163     lp = (uint32 *)(ROM_BASE + 0x312c50); // Replace rfi
1164     while (ntohl(*lp) != 0x4c000064) lp++;
1165     *lp = htonl(POWERPC_BCTR);
1166    
1167     lp = (uint32 *)(ROM_BASE + 0x318000);
1168     *lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST
1169     *lp++ = htonl(0x394affff); // subi r10,r10,1
1170     *lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST
1171     *lp = htonl(0x48000000 + ((xlp - 0x800c) & 0x03fffffc)); // b ROM_BASE+0x312c2c
1172     /*
1173     // Disable FE0A/FE06 opcodes
1174     lp = (uint32 *)(ROM_BASE + 0x3144ac);
1175     *lp++ = htonl(POWERPC_NOP);
1176     *lp += 8;
1177     */
1178     return true;
1179     }
1180    
1181    
1182     /*
1183     * 68k boot routine patches
1184     */
1185    
1186     static bool patch_68k(void)
1187     {
1188     uint32 *lp;
1189     uint16 *wp;
1190     uint8 *bp;
1191     uint32 base;
1192    
1193     // Remove 68k RESET instruction
1194     static const uint8 reset_dat[] = {0x4e, 0x70};
1195     if ((base = find_rom_data(0xc8, 0x120, reset_dat, sizeof(reset_dat))) == 0) return false;
1196     D(bug("reset %08lx\n", base));
1197     wp = (uint16 *)(ROM_BASE + base);
1198     *wp = htons(M68K_NOP);
1199    
1200     // Fake reading PowerMac ID (via Universal)
1201     static const uint8 powermac_id_dat[] = {0x45, 0xf9, 0x5f, 0xff, 0xff, 0xfc, 0x20, 0x12, 0x72, 0x00};
1202     if ((base = find_rom_data(0xe000, 0x15000, powermac_id_dat, sizeof(powermac_id_dat))) == 0) return false;
1203     D(bug("powermac_id %08lx\n", base));
1204     wp = (uint16 *)(ROM_BASE + base);
1205     *wp++ = htons(0x203c); // move.l #id,d0
1206     *wp++ = htons(0);
1207     // if (ROMType == ROMTYPE_NEWWORLD)
1208     // *wp++ = htons(0x3035); // (PowerMac 9500 ID)
1209     // else
1210     *wp++ = htons(0x3020); // (PowerMac 9500 ID)
1211     *wp++ = htons(0xb040); // cmp.w d0,d0
1212     *wp = htons(0x4ed6); // jmp (a6)
1213    
1214     // Patch UniversalInfo
1215     if (ROMType == ROMTYPE_NEWWORLD) {
1216     static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00};
1217     if ((base = find_rom_data(0x14000, 0x16000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false;
1218     D(bug("universal_info %08lx\n", base));
1219     lp = (uint32 *)(ROM_BASE + base - 0x14);
1220     lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14));
1221     lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo
1222     lp[0x14 >> 2] = htonl(0x3fff0401);
1223     lp[0x18 >> 2] = htonl(0x0300001c);
1224     lp[0x1c >> 2] = htonl(0x000108c4);
1225     lp[0x24 >> 2] = htonl(0xc301bf26);
1226     lp[0x28 >> 2] = htonl(0x00000861);
1227     lp[0x58 >> 2] = htonl(0x30200000);
1228     lp[0x60 >> 2] = htonl(0x0000003d);
1229     } else if (ROMType == ROMTYPE_ZANZIBAR) {
1230     base = 0x12b70;
1231     lp = (uint32 *)(ROM_BASE + base - 0x14);
1232     lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14));
1233     lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo
1234     lp[0x14 >> 2] = htonl(0x3fff0401);
1235     lp[0x18 >> 2] = htonl(0x0300001c);
1236     lp[0x1c >> 2] = htonl(0x000108c4);
1237     lp[0x24 >> 2] = htonl(0xc301bf26);
1238     lp[0x28 >> 2] = htonl(0x00000861);
1239     lp[0x58 >> 2] = htonl(0x30200000);
1240     lp[0x60 >> 2] = htonl(0x0000003d);
1241     }
1242    
1243     // Construct AddrMap for NewWorld ROM
1244     if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR) {
1245     lp = (uint32 *)(ROM_BASE + ADDR_MAP_PATCH_SPACE);
1246     memset(lp - 10, 0, 0x128);
1247     lp[-10] = htonl(0x0300001c);
1248     lp[-9] = htonl(0x000108c4);
1249     lp[-4] = htonl(0x00300000);
1250     lp[-2] = htonl(0x11010000);
1251     lp[-1] = htonl(0xf8000000);
1252     lp[0] = htonl(0xffc00000);
1253     lp[2] = htonl(0xf3016000);
1254     lp[3] = htonl(0xf3012000);
1255     lp[4] = htonl(0xf3012000);
1256     lp[24] = htonl(0xf3018000);
1257     lp[25] = htonl(0xf3010000);
1258     lp[34] = htonl(0xf3011000);
1259     lp[38] = htonl(0xf3015000);
1260     lp[39] = htonl(0xf3014000);
1261     lp[43] = htonl(0xf3000000);
1262     lp[48] = htonl(0xf8000000);
1263     }
1264    
1265     // Don't initialize VIA (via Universal)
1266     static const uint8 via_init_dat[] = {0x08, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x2c, 0x24, 0x68, 0x00, 0x08};
1267     if ((base = find_rom_data(0xe000, 0x15000, via_init_dat, sizeof(via_init_dat))) == 0) return false;
1268     D(bug("via_init %08lx\n", base));
1269     wp = (uint16 *)(ROM_BASE + base + 4);
1270     *wp = htons(0x6000); // bra
1271    
1272     static const uint8 via_init2_dat[] = {0x24, 0x68, 0x00, 0x08, 0x00, 0x12, 0x00, 0x30, 0x4e, 0x71};
1273     if ((base = find_rom_data(0xa000, 0x10000, via_init2_dat, sizeof(via_init2_dat))) == 0) return false;
1274     D(bug("via_init2 %08lx\n", base));
1275     wp = (uint16 *)(ROM_BASE + base);
1276     *wp = htons(0x4ed6); // jmp (a6)
1277    
1278     static const uint8 via_init3_dat[] = {0x22, 0x68, 0x00, 0x08, 0x28, 0x3c, 0x20, 0x00, 0x01, 0x00};
1279     if ((base = find_rom_data(0xa000, 0x10000, via_init3_dat, sizeof(via_init3_dat))) == 0) return false;
1280     D(bug("via_init3 %08lx\n", base));
1281     wp = (uint16 *)(ROM_BASE + base);
1282     *wp = htons(0x4ed6); // jmp (a6)
1283    
1284     // Don't RunDiags, get BootGlobs pointer directly
1285     if (ROMType == ROMTYPE_NEWWORLD) {
1286     static const uint8 run_diags_dat[] = {0x60, 0xff, 0x00, 0x0c};
1287     if ((base = find_rom_data(0x110, 0x128, run_diags_dat, sizeof(run_diags_dat))) == 0) return false;
1288     D(bug("run_diags %08lx\n", base));
1289     wp = (uint16 *)(ROM_BASE + base);
1290     *wp++ = htons(0x4df9); // lea xxx,a6
1291     *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16);
1292     *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff);
1293     } else {
1294     static const uint8 run_diags_dat[] = {0x74, 0x00, 0x2f, 0x0e};
1295     if ((base = find_rom_data(0xd0, 0xf0, run_diags_dat, sizeof(run_diags_dat))) == 0) return false;
1296     D(bug("run_diags %08lx\n", base));
1297     wp = (uint16 *)(ROM_BASE + base - 6);
1298     *wp++ = htons(0x4df9); // lea xxx,a6
1299     *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16);
1300     *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff);
1301     }
1302    
1303     // Replace NVRAM routines
1304     static const uint8 nvram1_dat[] = {0x48, 0xe7, 0x01, 0x0e, 0x24, 0x68, 0x00, 0x08, 0x08, 0x83, 0x00, 0x1f};
1305     if ((base = find_rom_data(0x7000, 0xc000, nvram1_dat, sizeof(nvram1_dat))) == 0) return false;
1306     D(bug("nvram1 %08lx\n", base));
1307     wp = (uint16 *)(ROM_BASE + base);
1308     *wp++ = htons(M68K_EMUL_OP_XPRAM1);
1309     *wp = htons(M68K_RTS);
1310    
1311     if (ROMType == ROMTYPE_NEWWORLD) {
1312     static const uint8 nvram2_dat[] = {0x48, 0xe7, 0x1c, 0xe0, 0x4f, 0xef, 0xff, 0xb4};
1313     if ((base = find_rom_data(0xa000, 0xd000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false;
1314     D(bug("nvram2 %08lx\n", base));
1315     wp = (uint16 *)(ROM_BASE + base);
1316     *wp++ = htons(M68K_EMUL_OP_XPRAM2);
1317     *wp = htons(0x4ed3); // jmp (a3)
1318    
1319     static const uint8 nvram3_dat[] = {0x48, 0xe7, 0xdc, 0xe0, 0x4f, 0xef, 0xff, 0xb4};
1320     if ((base = find_rom_data(0xa000, 0xd000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false;
1321     D(bug("nvram3 %08lx\n", base));
1322     wp = (uint16 *)(ROM_BASE + base);
1323     *wp++ = htons(M68K_EMUL_OP_XPRAM3);
1324     *wp = htons(0x4ed3); // jmp (a3)
1325    
1326     static const uint8 nvram4_dat[] = {0x4e, 0x56, 0xff, 0xa8, 0x48, 0xe7, 0x1f, 0x38, 0x16, 0x2e, 0x00, 0x13};
1327     if ((base = find_rom_data(0xa000, 0xd000, nvram4_dat, sizeof(nvram4_dat))) == 0) return false;
1328     D(bug("nvram4 %08lx\n", base));
1329     wp = (uint16 *)(ROM_BASE + base + 16);
1330     *wp++ = htons(0x1a2e); // move.b ($000f,a6),d5
1331     *wp++ = htons(0x000f);
1332     *wp++ = htons(M68K_EMUL_OP_NVRAM3);
1333     *wp++ = htons(0x4cee); // movem.l ($ff88,a6),d3-d7/a2-a4
1334     *wp++ = htons(0x1cf8);
1335     *wp++ = htons(0xff88);
1336     *wp++ = htons(0x4e5e); // unlk a6
1337     *wp = htons(M68K_RTS);
1338    
1339     static const uint8 nvram5_dat[] = {0x0c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0a, 0x70, 0x00, 0x21, 0xf8, 0x02, 0x0c, 0x01, 0xe4};
1340     if ((base = find_rom_data(0xa000, 0xd000, nvram5_dat, sizeof(nvram5_dat))) == 0) return false;
1341     D(bug("nvram5 %08lx\n", base));
1342     wp = (uint16 *)(ROM_BASE + base + 6);
1343     *wp = htons(M68K_NOP);
1344    
1345     static const uint8 nvram6_dat[] = {0x2f, 0x0a, 0x24, 0x48, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f};
1346     if ((base = find_rom_data(0x9000, 0xb000, nvram6_dat, sizeof(nvram6_dat))) == 0) return false;
1347     D(bug("nvram6 %08lx\n", base));
1348     wp = (uint16 *)(ROM_BASE + base);
1349     *wp++ = htons(0x7000); // moveq #0,d0
1350     *wp++ = htons(0x2080); // move.l d0,(a0)
1351     *wp++ = htons(0x4228); // clr.b 4(a0)
1352     *wp++ = htons(0x0004);
1353     *wp = htons(M68K_RTS);
1354    
1355     static const uint8 nvram7_dat[] = {0x42, 0x2a, 0x00, 0x04, 0x4f, 0xef, 0x00, 0x60, 0x24, 0x5f, 0x4e, 0x75, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f};
1356     base = find_rom_data(0x9000, 0xb000, nvram7_dat, sizeof(nvram7_dat));
1357     if (base) {
1358     D(bug("nvram7 %08lx\n", base));
1359     wp = (uint16 *)(ROM_BASE + base + 12);
1360     *wp = htons(M68K_RTS);
1361     }
1362     } else {
1363     static const uint8 nvram2_dat[] = {0x4e, 0xd6, 0x06, 0x41, 0x13, 0x00};
1364     if ((base = find_rom_data(0x7000, 0xb000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false;
1365     D(bug("nvram2 %08lx\n", base));
1366     wp = (uint16 *)(ROM_BASE + base + 2);
1367     *wp++ = htons(M68K_EMUL_OP_XPRAM2);
1368     *wp = htons(0x4ed3); // jmp (a3)
1369    
1370     static const uint32 nvram3_loc[] = {0x582f0, 0xa0a0, 0x7e50, 0xa1d0, 0};
1371     wp = (uint16 *)(ROM_BASE + nvram3_loc[ROMType]);
1372     *wp++ = htons(0x202f); // move.l 4(sp),d0
1373     *wp++ = htons(0x0004);
1374     *wp++ = htons(M68K_EMUL_OP_NVRAM1);
1375     if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE)
1376     *wp = htons(M68K_RTS);
1377     else {
1378     *wp++ = htons(0x1f40); // move.b d0,8(sp)
1379     *wp++ = htons(0x0008);
1380     *wp++ = htons(0x4e74); // rtd #4
1381     *wp = htons(0x0004);
1382     }
1383    
1384     static const uint32 nvram4_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0};
1385     wp = (uint16 *)(ROM_BASE + nvram4_loc[ROMType]);
1386     if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) {
1387     *wp++ = htons(0x202f); // move.l 4(sp),d0
1388     *wp++ = htons(0x0004);
1389     *wp++ = htons(0x122f); // move.b 11(sp),d1
1390     *wp++ = htons(0x000b);
1391     *wp++ = htons(M68K_EMUL_OP_NVRAM2);
1392     *wp = htons(M68K_RTS);
1393     } else {
1394     *wp++ = htons(0x202f); // move.l 6(sp),d0
1395     *wp++ = htons(0x0006);
1396     *wp++ = htons(0x122f); // move.b 4(sp),d1
1397     *wp++ = htons(0x0004);
1398     *wp++ = htons(M68K_EMUL_OP_NVRAM2);
1399     *wp++ = htons(0x4e74); // rtd #6
1400     *wp = htons(0x0006);
1401     }
1402     }
1403    
1404     // Fix MemTop/BootGlobs during system startup
1405     static const uint8 mem_top_dat[] = {0x2c, 0x6c, 0xff, 0xec, 0x2a, 0x4c, 0xdb, 0xec, 0xff, 0xf4};
1406     if ((base = find_rom_data(0x120, 0x180, mem_top_dat, sizeof(mem_top_dat))) == 0) return false;
1407     D(bug("mem_top %08lx\n", base));
1408     wp = (uint16 *)(ROM_BASE + base);
1409     *wp++ = htons(M68K_EMUL_OP_FIX_MEMTOP);
1410     *wp = htons(M68K_NOP);
1411    
1412     // Don't initialize SCC (via 0x1ac)
1413     static const uint8 scc_init_dat[] = {0x48, 0xe7, 0x38, 0xfe};
1414     if ((base = find_rom_data(0x190, 0x1f0, scc_init_dat, sizeof(scc_init_dat))) == 0) return false;
1415     D(bug("scc_init %08lx\n", base));
1416     wp = (uint16 *)(ROM_BASE + base - 2);
1417     wp = (uint16 *)(ROM_BASE + ntohs(*wp) + base - 2);
1418     *wp++ = htons(M68K_EMUL_OP_RESET);
1419     *wp = htons(M68K_RTS);
1420    
1421     // Don't EnableExtCache (via 0x1f6) and don't DisableIntSources(via 0x1fc)
1422     static const uint8 ext_cache_dat[] = {0x4e, 0x7b, 0x00, 0x02};
1423     if ((base = find_rom_data(0x1d0, 0x230, ext_cache_dat, sizeof(ext_cache_dat))) == 0) return false;
1424     D(bug("ext_cache %08lx\n", base));
1425     lp = (uint32 *)(ROM_BASE + base + 6);
1426     wp = (uint16 *)(ROM_BASE + ntohl(*lp) + base + 6);
1427     *wp = htons(M68K_RTS);
1428     lp = (uint32 *)(ROM_BASE + base + 12);
1429     wp = (uint16 *)(ROM_BASE + ntohl(*lp) + base + 12);
1430     *wp = htons(M68K_RTS);
1431    
1432     // Fake CPU speed test (SetupTimeK)
1433     static const uint8 timek_dat[] = {0x0c, 0x38, 0x00, 0x04, 0x01, 0x2f, 0x6d, 0x3c};
1434     if ((base = find_rom_data(0x400, 0x500, timek_dat, sizeof(timek_dat))) == 0) return false;
1435     D(bug("timek %08lx\n", base));
1436     wp = (uint16 *)(ROM_BASE + base);
1437     *wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA
1438     *wp++ = htons(100);
1439     *wp++ = htons(0x0d00);
1440     *wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA
1441     *wp++ = htons(100);
1442     *wp++ = htons(0x0d02);
1443     *wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA
1444     *wp++ = htons(100);
1445     *wp++ = htons(0x0b24);
1446     *wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA
1447     *wp++ = htons(100);
1448     *wp++ = htons(0x0cea);
1449     *wp = htons(M68K_RTS);
1450    
1451     // Relocate jump tables ($2000..)
1452     static const uint8 jump_tab_dat[] = {0x41, 0xfa, 0x00, 0x0e, 0x21, 0xc8, 0x20, 0x10, 0x4e, 0x75};
1453     if ((base = find_rom_data(0x3000, 0x6000, jump_tab_dat, sizeof(jump_tab_dat))) == 0) return false;
1454     D(bug("jump_tab %08lx\n", base));
1455     lp = (uint32 *)(ROM_BASE + base + 16);
1456     for (;;) {
1457     D(bug(" %08lx\n", (uint32)lp - ROM_BASE));
1458     while ((ntohl(*lp) & 0xff000000) == 0xff000000) {
1459     *lp = htonl((ntohl(*lp) & (ROM_SIZE-1)) + ROM_BASE);
1460     lp++;
1461     }
1462     while (!ntohl(*lp)) lp++;
1463     if (ntohl(*lp) != 0x41fa000e)
1464     break;
1465     lp += 4;
1466     }
1467    
1468     // Create SysZone at start of Mac RAM (SetSysAppZone, via 0x22a)
1469     static const uint8 sys_zone_dat[] = {0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x00};
1470     if ((base = find_rom_data(0x600, 0x900, sys_zone_dat, sizeof(sys_zone_dat))) == 0) return false;
1471     D(bug("sys_zone %08lx\n", base));
1472     lp = (uint32 *)(ROM_BASE + base);
1473     *lp++ = htonl(RAMBase ? RAMBase : 0x3000);
1474     *lp = htonl(RAMBase ? RAMBase + 0x1800 : 0x4800);
1475    
1476     // Set boot stack at RAMBase+4MB and fix logical/physical RAM size (CompBootStack)
1477     // The RAM size fix must be done after InitMemMgr!
1478     static const uint8 boot_stack_dat[] = {0x08, 0x38, 0x00, 0x06, 0x24, 0x0b};
1479     if ((base = find_rom_data(0x580, 0x800, boot_stack_dat, sizeof(boot_stack_dat))) == 0) return false;
1480     D(bug("boot_stack %08lx\n", base));
1481     wp = (uint16 *)(ROM_BASE + base);
1482     *wp++ = htons(0x207c); // move.l #RAMBase+0x3ffffe,a0
1483     *wp++ = htons((RAMBase + 0x3ffffe) >> 16);
1484     *wp++ = htons((RAMBase + 0x3ffffe) & 0xffff);
1485     *wp++ = htons(M68K_EMUL_OP_FIX_MEMSIZE);
1486     *wp = htons(M68K_RTS);
1487    
1488     // Get PowerPC page size (InitVMemMgr, via 0x240)
1489     static const uint8 page_size_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x10};
1490     if ((base = find_rom_data(0xb000, 0x12000, page_size_dat, sizeof(page_size_dat))) == 0) return false;
1491     D(bug("page_size %08lx\n", base));
1492     wp = (uint16 *)(ROM_BASE + base);
1493     *wp++ = htons(0x203c); // move.l #$1000,d0
1494     *wp++ = htons(0);
1495     *wp++ = htons(0x1000);
1496     *wp++ = htons(M68K_NOP);
1497     *wp = htons(M68K_NOP);
1498    
1499     // Gestalt PowerPC page size, RAM size (InitGestalt, via 0x25c)
1500     static const uint8 page_size2_dat[] = {0x26, 0x79, 0x5f, 0xff, 0xef, 0xd8, 0x25, 0x6b, 0x00, 0x10, 0x00, 0x1e};
1501     if ((base = find_rom_data(0x50000, 0x70000, page_size2_dat, sizeof(page_size2_dat))) == 0) return false;
1502     D(bug("page_size2 %08lx\n", base));
1503     wp = (uint16 *)(ROM_BASE + base);
1504     *wp++ = htons(0x257c); // move.l #$1000,$1e(a2)
1505     *wp++ = htons(0);
1506     *wp++ = htons(0x1000);
1507     *wp++ = htons(0x001e);
1508     *wp++ = htons(0x157c); // move.b #PVR,$1d(a2)
1509     *wp++ = htons(PVR >> 16);
1510     *wp++ = htons(0x001d);
1511     *wp++ = htons(0x263c); // move.l #RAMSize,d3
1512     *wp++ = htons(RAMSize >> 16);
1513     *wp++ = htons(RAMSize & 0xffff);
1514     *wp++ = htons(M68K_NOP);
1515     *wp++ = htons(M68K_NOP);
1516     *wp = htons(M68K_NOP);
1517     if (ROMType == ROMTYPE_NEWWORLD)
1518     wp = (uint16 *)(ROM_BASE + base + 0x4a);
1519     else
1520     wp = (uint16 *)(ROM_BASE + base + 0x28);
1521     *wp++ = htons(M68K_NOP);
1522     *wp = htons(M68K_NOP);
1523    
1524     // Gestalt CPU/bus clock speed (InitGestalt, via 0x25c)
1525     if (ROMType == ROMTYPE_ZANZIBAR) {
1526     wp = (uint16 *)(ROM_BASE + 0x5d87a);
1527     *wp++ = htons(0x203c); // move.l #Hz,d0
1528     *wp++ = htons(BusClockSpeed >> 16);
1529     *wp++ = htons(BusClockSpeed & 0xffff);
1530     *wp++ = htons(M68K_NOP);
1531     *wp = htons(M68K_NOP);
1532     wp = (uint16 *)(ROM_BASE + 0x5d888);
1533     *wp++ = htons(0x203c); // move.l #Hz,d0
1534     *wp++ = htons(CPUClockSpeed >> 16);
1535     *wp++ = htons(CPUClockSpeed & 0xffff);
1536     *wp++ = htons(M68K_NOP);
1537     *wp = htons(M68K_NOP);
1538     }
1539    
1540     // Don't write to GC interrupt mask register (via 0x262)
1541     if (ROMType != ROMTYPE_NEWWORLD) {
1542     static const uint8 gc_mask_dat[] = {0x83, 0xa8, 0x00, 0x24, 0x4e, 0x71};
1543     if ((base = find_rom_data(0x13000, 0x20000, gc_mask_dat, sizeof(gc_mask_dat))) == 0) return false;
1544     D(bug("gc_mask %08lx\n", base));
1545     wp = (uint16 *)(ROM_BASE + base);
1546     *wp++ = htons(M68K_NOP);
1547     *wp = htons(M68K_NOP);
1548     wp = (uint16 *)(ROM_BASE + base + 0x40);
1549     *wp++ = htons(M68K_NOP);
1550     *wp = htons(M68K_NOP);
1551     wp = (uint16 *)(ROM_BASE + base + 0x78);
1552     *wp++ = htons(M68K_NOP);
1553     *wp = htons(M68K_NOP);
1554     wp = (uint16 *)(ROM_BASE + base + 0x96);
1555     *wp++ = htons(M68K_NOP);
1556     *wp = htons(M68K_NOP);
1557    
1558     static const uint8 gc_mask2_dat[] = {0x02, 0xa8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x24};
1559     if ((base = find_rom_data(0x13000, 0x20000, gc_mask2_dat, sizeof(gc_mask2_dat))) == 0) return false;
1560     D(bug("gc_mask2 %08lx\n", base));
1561     wp = (uint16 *)(ROM_BASE + base);
1562     for (int i=0; i<5; i++) {
1563     *wp++ = htons(M68K_NOP);
1564     *wp++ = htons(M68K_NOP);
1565     *wp++ = htons(M68K_NOP);
1566     *wp++ = htons(M68K_NOP);
1567     wp += 2;
1568     }
1569     if (ROMType == ROMTYPE_ZANZIBAR) {
1570     for (int i=0; i<6; i++) {
1571     *wp++ = htons(M68K_NOP);
1572     *wp++ = htons(M68K_NOP);
1573     *wp++ = htons(M68K_NOP);
1574     *wp++ = htons(M68K_NOP);
1575     wp += 2;
1576     }
1577     }
1578     }
1579    
1580     // Don't initialize Cuda (via 0x274)
1581     static const uint8 cuda_init_dat[] = {0x08, 0xa9, 0x00, 0x04, 0x16, 0x00, 0x4e, 0x71, 0x13, 0x7c, 0x00, 0x84, 0x1c, 0x00, 0x4e, 0x71};
1582     if ((base = find_rom_data(0xa000, 0x12000, cuda_init_dat, sizeof(cuda_init_dat))) == 0) return false;
1583     D(bug("cuda_init %08lx\n", base));
1584     wp = (uint16 *)(ROM_BASE + base);
1585     *wp++ = htons(M68K_NOP);
1586     *wp++ = htons(M68K_NOP);
1587     *wp++ = htons(M68K_NOP);
1588     *wp++ = htons(M68K_NOP);
1589     *wp++ = htons(M68K_NOP);
1590     *wp++ = htons(M68K_NOP);
1591     *wp = htons(M68K_NOP);
1592    
1593     // Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them)
1594     static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c};
1595     if ((base = find_rom_data(0x6000, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false;
1596     D(bug("cpu_speed %08lx\n", base));
1597     wp = (uint16 *)(ROM_BASE + base);
1598     *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0
1599     *wp++ = htons(CPUClockSpeed / 1000000);
1600     *wp++ = htons(CPUClockSpeed / 1000000);
1601     *wp = htons(M68K_RTS);
1602     if ((base = find_rom_data(base, 0x9000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) {
1603     D(bug("cpu_speed2 %08lx\n", base));
1604     wp = (uint16 *)(ROM_BASE + base);
1605     *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0
1606     *wp++ = htons(CPUClockSpeed / 1000000);
1607     *wp++ = htons(CPUClockSpeed / 1000000);
1608     *wp = htons(M68K_RTS);
1609     }
1610    
1611     // Don't poke VIA in InitTimeMgr (via 0x298)
1612     static const uint8 time_via_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x28, 0x78, 0x01, 0xd4, 0x43, 0xec, 0x10, 0x00};
1613     if ((base = find_rom_data(0x30000, 0x40000, time_via_dat, sizeof(time_via_dat))) == 0) return false;
1614     D(bug("time_via %08lx\n", base));
1615     wp = (uint16 *)(ROM_BASE + base);
1616     *wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4
1617     *wp++ = htons(0x1f3f);
1618     *wp = htons(M68K_RTS);
1619    
1620     // Don't read from 0xff800000 (Name Registry, Open Firmware?) (via 0x2a2)
1621     // Remove this if FE03 works!!
1622     static const uint8 open_firmware_dat[] = {0x2f, 0x79, 0xff, 0x80, 0x00, 0x00, 0x00, 0xfc};
1623     if ((base = find_rom_data(0x48000, 0x58000, open_firmware_dat, sizeof(open_firmware_dat))) == 0) return false;
1624     D(bug("open_firmware %08lx\n", base));
1625     wp = (uint16 *)(ROM_BASE + base);
1626     *wp++ = htons(0x2f7c); // move.l #deadbeef,0xfc(a7)
1627     *wp++ = htons(0xdead);
1628     *wp++ = htons(0xbeef);
1629     *wp = htons(0x00fc);
1630     wp = (uint16 *)(ROM_BASE + base + 0x1a);
1631     *wp++ = htons(M68K_NOP); // (FE03 opcode, tries to jump to 0xdeadbeef)
1632     *wp = htons(M68K_NOP);
1633    
1634     // Don't EnableExtCache (via 0x2b2)
1635     static const uint8 ext_cache2_dat[] = {0x4f, 0xef, 0xff, 0xec, 0x20, 0x4f, 0x10, 0xbc, 0x00, 0x01, 0x11, 0x7c, 0x00, 0x1b};
1636     if ((base = find_rom_data(0x13000, 0x20000, ext_cache2_dat, sizeof(ext_cache2_dat))) == 0) return false;
1637     D(bug("ext_cache2 %08lx\n", base));
1638     wp = (uint16 *)(ROM_BASE + base);
1639     *wp = htons(M68K_RTS);
1640    
1641     // Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8)
1642     if (ROMType == ROMTYPE_NEWWORLD) {
1643     static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9};
1644     if ((base = find_rom_data(0x2e0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false;
1645     D(bug("tm_task %08lx\n", base));
1646     wp = (uint16 *)(ROM_BASE + base + 28);
1647     *wp++ = htons(M68K_NOP);
1648     *wp++ = htons(M68K_NOP);
1649     *wp++ = htons(M68K_NOP);
1650     *wp++ = htons(M68K_NOP);
1651     *wp++ = htons(M68K_NOP);
1652     *wp = htons(M68K_NOP);
1653     } else {
1654     static const uint8 tm_task_dat[] = {0x20, 0x3c, 0x73, 0x79, 0x73, 0x61};
1655     if ((base = find_rom_data(0x280, 0x300, tm_task_dat, sizeof(tm_task_dat))) == 0) return false;
1656     D(bug("tm_task %08lx\n", base));
1657     wp = (uint16 *)(ROM_BASE + base - 6);
1658     *wp++ = htons(M68K_NOP);
1659     *wp++ = htons(M68K_NOP);
1660     *wp = htons(M68K_NOP);
1661     }
1662    
1663     // Don't read PVR from 0x5fffef80 in DriverServicesLib (via 0x316)
1664     if (ROMType != ROMTYPE_NEWWORLD) {
1665     uint32 dsl_offset = find_rom_resource(FOURCC('n','l','i','b'), -16401);
1666     if (ROMType == ROMTYPE_ZANZIBAR) {
1667     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};
1668     if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false;
1669     } else {
1670     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};
1671     if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false;
1672     }
1673     D(bug("dsl_pvr %08lx\n", base));
1674     lp = (uint32 *)(ROM_BASE + base + 12);
1675     *lp = htonl(0x3c800000 | (PVR >> 16)); // lis r4,PVR
1676    
1677     // Don't read bus clock from 0x5fffef88 in DriverServicesLib (via 0x316)
1678     if (ROMType == ROMTYPE_ZANZIBAR) {
1679     static const uint8 dsl_bus_dat[] = {0x81, 0x07, 0x00, 0x00, 0x39, 0x20, 0x42, 0x40, 0x81, 0x62, 0xff, 0x20};
1680     if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false;
1681     D(bug("dsl_bus %08lx\n", base));
1682     lp = (uint32 *)(ROM_BASE + base);
1683     *lp = htonl(0x81000000 + XLM_BUS_CLOCK); // lwz r8,(bus clock speed)
1684     } else {
1685     static const uint8 dsl_bus_dat[] = {0x80, 0x83, 0xef, 0xe8, 0x80, 0x62, 0x00, 0x10, 0x7c, 0x04, 0x03, 0x96};
1686     if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false;
1687     D(bug("dsl_bus %08lx\n", base));
1688     lp = (uint32 *)(ROM_BASE + base);
1689     *lp = htonl(0x80800000 + XLM_BUS_CLOCK); // lwz r4,(bus clock speed)
1690     }
1691     }
1692    
1693     // Don't open InterruptTreeTNT in MotherBoardHAL init in DriverServicesLib init
1694     if (ROMType == ROMTYPE_ZANZIBAR) {
1695     lp = (uint32 *)(ROM_BASE + find_rom_resource(FOURCC('n','l','i','b'), -16408) + 0x16c);
1696     *lp = htonl(0x38600000); // li r3,0
1697     }
1698    
1699     // Patch Name Registry
1700     static const uint8 name_reg_dat[] = {0x70, 0xff, 0xab, 0xeb};
1701     if ((base = find_rom_data(0x300, 0x380, name_reg_dat, sizeof(name_reg_dat))) == 0) return false;
1702     D(bug("name_reg %08lx\n", base));
1703     wp = (uint16 *)(ROM_BASE + base);
1704     *wp = htons(M68K_EMUL_OP_NAME_REGISTRY);
1705    
1706     #if DISABLE_SCSI
1707     // Fake SCSI Manager
1708     // Remove this if SCSI Manager works!!
1709     static const uint8 scsi_mgr_a_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e};
1710     static const uint8 scsi_mgr_b_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x2f, 0x0c, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e};
1711     if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_a_dat, sizeof(scsi_mgr_a_dat))) == 0) {
1712     if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_b_dat, sizeof(scsi_mgr_b_dat))) == 0) return false;
1713     }
1714     D(bug("scsi_mgr %08lx\n", base));
1715     wp = (uint16 *)(ROM_BASE + base);
1716     *wp++ = htons(0x21fc); // move.l #xxx,0x624 (SCSIAtomic)
1717     *wp++ = htons((ROM_BASE + base + 18) >> 16);
1718     *wp++ = htons((ROM_BASE + base + 18) & 0xffff);
1719     *wp++ = htons(0x0624);
1720     *wp++ = htons(0x21fc); // move.l #xxx,0xe54 (SCSIDispatch)
1721     *wp++ = htons((ROM_BASE + base + 22) >> 16);
1722     *wp++ = htons((ROM_BASE + base + 22) & 0xffff);
1723     *wp++ = htons(0x0e54);
1724     *wp++ = htons(M68K_RTS);
1725     *wp++ = htons(M68K_EMUL_OP_SCSI_ATOMIC);
1726     *wp++ = htons(M68K_RTS);
1727     *wp++ = htons(M68K_EMUL_OP_SCSI_DISPATCH);
1728     *wp = htons(0x4ed0); // jmp (a0)
1729     wp = (uint16 *)(ROM_BASE + base + 0x20);
1730     *wp++ = htons(0x7000); // moveq #0,d0
1731     *wp = htons(M68K_RTS);
1732     #endif
1733    
1734     #if DISABLE_SCSI
1735     // Don't access SCSI variables
1736     // Remove this if SCSI Manager works!!
1737     if (ROMType == ROMTYPE_NEWWORLD) {
1738     static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00};
1739     if ((base = find_rom_data(0x1f500, 0x1f600, scsi_var_dat, sizeof(scsi_var_dat))) != 0) {
1740     D(bug("scsi_var %08lx\n", base));
1741     wp = (uint16 *)(ROM_BASE + base + 12);
1742     *wp = htons(0x6000); // bra
1743     }
1744    
1745     static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x58, 0x48, 0xe7, 0x1f, 0x38};
1746     if ((base = find_rom_data(0x1f700, 0x1f800, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) {
1747     D(bug("scsi_var2 %08lx\n", base));
1748     wp = (uint16 *)(ROM_BASE + base);
1749     *wp++ = htons(0x7000); // moveq #0,d0
1750     *wp = htons(M68K_RTS); // bra
1751     }
1752     }
1753     #endif
1754    
1755     // Don't wait in ADBInit (via 0x36c)
1756     static const uint8 adb_init_dat[] = {0x08, 0x2b, 0x00, 0x05, 0x01, 0x5d, 0x66, 0xf8};
1757     if ((base = find_rom_data(0x31000, 0x3d000, adb_init_dat, sizeof(adb_init_dat))) == 0) return false;
1758     D(bug("adb_init %08lx\n", base));
1759     wp = (uint16 *)(ROM_BASE + base + 6);
1760     *wp = htons(M68K_NOP);
1761    
1762     // Modify check in InitResources() so that addresses >0x80000000 work
1763     static const uint8 init_res_dat[] = {0x4a, 0xb8, 0x0a, 0x50, 0x6e, 0x20};
1764     if ((base = find_rom_data(0x78000, 0x8c000, init_res_dat, sizeof(init_res_dat))) == 0) return false;
1765     D(bug("init_res %08lx\n", base));
1766     bp = (uint8 *)(ROM_BASE + base + 4);
1767     *bp = 0x66;
1768    
1769     // Modify vCheckLoad() so that we can patch resources (68k Resource Manager)
1770     static const uint8 check_load_dat[] = {0x20, 0x78, 0x07, 0xf0, 0x4e, 0xd0};
1771     if ((base = find_rom_data(0x78000, 0x8c000, check_load_dat, sizeof(check_load_dat))) == 0) return false;
1772     D(bug("check_load %08lx\n", base));
1773     wp = (uint16 *)(ROM_BASE + base);
1774     *wp++ = htons(M68K_JMP);
1775     *wp++ = htons((ROM_BASE + CHECK_LOAD_PATCH_SPACE) >> 16);
1776     *wp = htons((ROM_BASE + CHECK_LOAD_PATCH_SPACE) & 0xffff);
1777     wp = (uint16 *)(ROM_BASE + CHECK_LOAD_PATCH_SPACE);
1778     *wp++ = htons(0x2f03); // move.l d3,-(a7)
1779     *wp++ = htons(0x2078); // move.l $07f0,a0
1780     *wp++ = htons(0x07f0);
1781     *wp++ = htons(M68K_JSR_A0);
1782     *wp++ = htons(M68K_EMUL_OP_CHECKLOAD);
1783     *wp = htons(M68K_RTS);
1784    
1785     // Replace .Sony driver
1786     sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4);
1787     if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD)
1788     sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4, true); // First DRVR 4 is .MFMFloppy
1789     if (sony_offset == 0) {
1790     sony_offset = find_rom_resource(FOURCC('n','d','r','v'), -20196); // NewWorld 1.6 has "PCFloppy" ndrv
1791     if (sony_offset == 0)
1792     return false;
1793     lp = (uint32 *)(ROM_BASE + rsrc_ptr + 8);
1794     *lp = htonl(FOURCC('D','R','V','R'));
1795     wp = (uint16 *)(ROM_BASE + rsrc_ptr + 12);
1796     *wp = htons(4);
1797     }
1798     D(bug("sony_offset %08lx\n", sony_offset));
1799     memcpy((void *)(ROM_BASE + sony_offset), sony_driver, sizeof(sony_driver));
1800    
1801     // Install .Disk and .AppleCD drivers
1802     memcpy((void *)(ROM_BASE + sony_offset + 0x100), disk_driver, sizeof(disk_driver));
1803     memcpy((void *)(ROM_BASE + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver));
1804    
1805     // Install serial drivers
1806     memcpy((void *)(ROM_BASE + sony_offset + 0x300), ain_driver, sizeof(ain_driver));
1807     memcpy((void *)(ROM_BASE + sony_offset + 0x400), aout_driver, sizeof(aout_driver));
1808     memcpy((void *)(ROM_BASE + sony_offset + 0x500), bin_driver, sizeof(bin_driver));
1809     memcpy((void *)(ROM_BASE + sony_offset + 0x600), bout_driver, sizeof(bout_driver));
1810    
1811     // Copy icons to ROM
1812     SonyDiskIconAddr = ROM_BASE + sony_offset + 0x800;
1813     memcpy((void *)(ROM_BASE + sony_offset + 0x800), SonyDiskIcon, sizeof(SonyDiskIcon));
1814     SonyDriveIconAddr = ROM_BASE + sony_offset + 0xa00;
1815     memcpy((void *)(ROM_BASE + sony_offset + 0xa00), SonyDriveIcon, sizeof(SonyDriveIcon));
1816     DiskIconAddr = ROM_BASE + sony_offset + 0xc00;
1817     memcpy((void *)(ROM_BASE + sony_offset + 0xc00), DiskIcon, sizeof(DiskIcon));
1818     CDROMIconAddr = ROM_BASE + sony_offset + 0xe00;
1819     memcpy((void *)(ROM_BASE + sony_offset + 0xe00), CDROMIcon, sizeof(CDROMIcon));
1820    
1821     // Patch driver install routine
1822     static const uint8 drvr_install_dat[] = {0xa7, 0x1e, 0x21, 0xc8, 0x01, 0x1c, 0x4e, 0x75};
1823     if ((base = find_rom_data(0xb00, 0xd00, drvr_install_dat, sizeof(drvr_install_dat))) == 0) return false;
1824     D(bug("drvr_install %08lx\n", base));
1825     wp = (uint16 *)(ROM_BASE + base + 8);
1826     *wp++ = htons(M68K_EMUL_OP_INSTALL_DRIVERS);
1827     *wp = htons(M68K_RTS);
1828    
1829     // Don't install serial drivers from ROM
1830     if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD) {
1831     wp = (uint16 *)(ROM_BASE + find_rom_resource(FOURCC('S','E','R','D'), 0));
1832     *wp = htons(M68K_RTS);
1833     } else {
1834     wp = (uint16 *)(ROM_BASE + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0xc4);
1835     *wp++ = htons(M68K_NOP);
1836     *wp++ = htons(M68K_NOP);
1837     *wp++ = htons(M68K_NOP);
1838     *wp++ = htons(M68K_NOP);
1839     *wp = htons(0x7000); // moveq #0,d0
1840     wp = (uint16 *)(ROM_BASE + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0x8ee);
1841     *wp = htons(M68K_NOP);
1842     }
1843     uint32 nsrd_offset = find_rom_resource(FOURCC('n','s','r','d'), 1);
1844     if (nsrd_offset) {
1845     lp = (uint32 *)(ROM_BASE + rsrc_ptr + 8);
1846     *lp = htonl(FOURCC('x','s','r','d'));
1847     }
1848    
1849     // Replace ADBOp()
1850     memcpy((void *)(ROM_BASE + find_rom_trap(0xa07c)), adbop_patch, sizeof(adbop_patch));
1851    
1852     // Replace Time Manager
1853     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xa058));
1854     *wp++ = htons(M68K_EMUL_OP_INSTIME);
1855     *wp = htons(M68K_RTS);
1856     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xa059));
1857     *wp++ = htons(0x40e7); // move sr,-(sp)
1858     *wp++ = htons(0x007c); // ori #$0700,sr
1859     *wp++ = htons(0x0700);
1860     *wp++ = htons(M68K_EMUL_OP_RMVTIME);
1861     *wp++ = htons(0x46df); // move (sp)+,sr
1862     *wp = htons(M68K_RTS);
1863     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xa05a));
1864     *wp++ = htons(0x40e7); // move sr,-(sp)
1865     *wp++ = htons(0x007c); // ori #$0700,sr
1866     *wp++ = htons(0x0700);
1867     *wp++ = htons(M68K_EMUL_OP_PRIMETIME);
1868     *wp++ = htons(0x46df); // move (sp)+,sr
1869     *wp = htons(M68K_RTS);
1870     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xa093));
1871     *wp++ = htons(M68K_EMUL_OP_MICROSECONDS);
1872     *wp = htons(M68K_RTS);
1873    
1874     // Disable Egret Manager
1875     static const uint8 egret_dat[] = {0x2f, 0x30, 0x81, 0xe2, 0x20, 0x10, 0x00, 0x18};
1876     if ((base = find_rom_data(0xa000, 0x10000, egret_dat, sizeof(egret_dat))) == 0) return false;
1877     D(bug("egret %08lx\n", base));
1878     wp = (uint16 *)(ROM_BASE + base);
1879     *wp++ = htons(0x7000);
1880     *wp = htons(M68K_RTS);
1881    
1882     // Don't call FE0A opcode in Shutdown Manager
1883     static const uint8 shutdown_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x48, 0xe7, 0x3f, 0x00, 0x2c, 0x00, 0x2e, 0x01};
1884     if ((base = find_rom_data(0x30000, 0x40000, shutdown_dat, sizeof(shutdown_dat))) == 0) return false;
1885     D(bug("shutdown %08lx\n", base));
1886     wp = (uint16 *)(ROM_BASE + base);
1887     if (ROMType == ROMTYPE_ZANZIBAR)
1888     *wp = htons(M68K_RTS);
1889     else
1890     wp[-2] = htons(0x6000); // bra
1891    
1892     // Patch PowerOff()
1893     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xa05b)); // PowerOff()
1894     *wp = htons(M68K_EMUL_RETURN);
1895    
1896     // Patch VIA interrupt handler
1897     static const uint8 via_int_dat[] = {0x70, 0x7f, 0xc0, 0x29, 0x1a, 0x00, 0xc0, 0x29, 0x1c, 0x00};
1898     if ((base = find_rom_data(0x13000, 0x1c000, via_int_dat, sizeof(via_int_dat))) == 0) return false;
1899     D(bug("via_int %08lx\n", base));
1900     uint32 level1_int = ROM_BASE + base;
1901     wp = (uint16 *)level1_int; // Level 1 handler
1902     *wp++ = htons(0x7002); // moveq #2,d0 (60Hz interrupt)
1903     *wp++ = htons(M68K_NOP);
1904     *wp++ = htons(M68K_NOP);
1905     *wp++ = htons(M68K_NOP);
1906     *wp = htons(M68K_NOP);
1907    
1908     static const uint8 via_int2_dat[] = {0x13, 0x7c, 0x00, 0x02, 0x1a, 0x00, 0x4e, 0x71, 0x52, 0xb8, 0x01, 0x6a};
1909     if ((base = find_rom_data(0x10000, 0x18000, via_int2_dat, sizeof(via_int2_dat))) == 0) return false;
1910     D(bug("via_int2 %08lx\n", base));
1911     wp = (uint16 *)(ROM_BASE + base); // 60Hz handler
1912     *wp++ = htons(M68K_EMUL_OP_IRQ);
1913     *wp++ = htons(0x4a80); // tst.l d0
1914     *wp++ = htons(0x6700); // beq xxx
1915     *wp = htons(0xffe8);
1916    
1917     if (ROMType == ROMTYPE_NEWWORLD) {
1918     static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26};
1919     if ((base = find_rom_data(0x15000, 0x18000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false;
1920     D(bug("via_int3 %08lx\n", base));
1921     wp = (uint16 *)(ROM_BASE + base); // CHRP level 1 handler
1922     *wp++ = htons(M68K_JMP);
1923     *wp++ = htons((level1_int - 12) >> 16);
1924     *wp = htons((level1_int - 12) & 0xffff);
1925     }
1926    
1927     // Patch PutScrap() for clipboard exchange with host OS
1928     uint32 put_scrap = find_rom_trap(0xa9fe); // PutScrap()
1929     wp = (uint16 *)(ROM_BASE + PUT_SCRAP_PATCH_SPACE);
1930     *wp++ = htons(M68K_EMUL_OP_PUT_SCRAP);
1931     *wp++ = htons(M68K_JMP);
1932     *wp++ = htons((ROM_BASE + put_scrap) >> 16);
1933     *wp++ = htons((ROM_BASE + put_scrap) & 0xffff);
1934     lp = (uint32 *)(ROM_BASE + 0x22);
1935     lp = (uint32 *)(ROM_BASE + ntohl(*lp));
1936     lp[0xa9fe & 0x3ff] = htonl(PUT_SCRAP_PATCH_SPACE);
1937    
1938     // Patch GetScrap() for clipboard exchange with host OS
1939     uint32 get_scrap = find_rom_trap(0xa9fd); // GetScrap()
1940     wp = (uint16 *)(ROM_BASE + GET_SCRAP_PATCH_SPACE);
1941     *wp++ = htons(M68K_EMUL_OP_GET_SCRAP);
1942     *wp++ = htons(M68K_JMP);
1943     *wp++ = htons((ROM_BASE + get_scrap) >> 16);
1944     *wp++ = htons((ROM_BASE + get_scrap) & 0xffff);
1945     lp = (uint32 *)(ROM_BASE + 0x22);
1946     lp = (uint32 *)(ROM_BASE + ntohl(*lp));
1947     lp[0xa9fd & 0x3ff] = htonl(GET_SCRAP_PATCH_SPACE);
1948    
1949     #if __BEOS__
1950     // Patch SynchIdleTime()
1951     if (PrefsFindBool("idlewait")) {
1952     wp = (uint16 *)(ROM_BASE + find_rom_trap(0xabf7) + 4); // SynchIdleTime()
1953     D(bug("SynchIdleTime at %08lx\n", wp));
1954     if (ntohs(*wp) == 0x2078) {
1955     *wp++ = htons(M68K_EMUL_OP_IDLE_TIME);
1956     *wp = htons(M68K_NOP);
1957     } else {
1958     D(bug("SynchIdleTime patch not installed\n"));
1959     }
1960     }
1961     #endif
1962    
1963     // Construct list of all sifters used by sound components in ROM
1964     D(bug("Searching for sound components with type sdev in ROM\n"));
1965     uint32 thing = find_rom_resource(FOURCC('t','h','n','g'));
1966     while (thing) {
1967     thing += ROM_BASE;
1968     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)));
1969     if (ReadMacInt32(thing) == FOURCC('s','d','e','v') && ReadMacInt32(thing + 4) == FOURCC('s','i','n','g')) {
1970     WriteMacInt32(thing + 4, FOURCC('a','w','g','c'));
1971     D(bug(" found sdev component at offset %08x in ROM\n", thing));
1972     AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID));
1973     if (ReadMacInt32(thing + componentPFCount))
1974     AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID));
1975     }
1976     thing = find_rom_resource(FOURCC('t','h','n','g'), 4711, true);
1977     }
1978    
1979     // Patch component code
1980     D(bug("Patching sifters in ROM\n"));
1981     for (int i=0; i<num_sifters; i++) {
1982     if ((thing = find_rom_resource(sifter_list[i].type, sifter_list[i].id)) != 0) {
1983     D(bug(" patching type %08x, id %d\n", sifter_list[i].type, sifter_list[i].id));
1984     // Install 68k glue code
1985     uint16 *wp = (uint16 *)(ROM_BASE + thing);
1986     *wp++ = htons(0x4e56); *wp++ = htons(0x0000); // link a6,#0
1987     *wp++ = htons(0x48e7); *wp++ = htons(0x8018); // movem.l d0/a3-a4,-(a7)
1988     *wp++ = htons(0x266e); *wp++ = htons(0x000c); // movea.l $c(a6),a3
1989     *wp++ = htons(0x286e); *wp++ = htons(0x0008); // movea.l $8(a6),a4
1990     *wp++ = htons(M68K_EMUL_OP_AUDIO_DISPATCH);
1991     *wp++ = htons(0x2d40); *wp++ = htons(0x0010); // move.l d0,$10(a6)
1992     *wp++ = htons(0x4cdf); *wp++ = htons(0x1801); // movem.l (a7)+,d0/a3-a4
1993     *wp++ = htons(0x4e5e); // unlk a6
1994     *wp++ = htons(0x4e74); *wp++ = htons(0x0008); // rtd #8
1995     }
1996     }
1997     return true;
1998     }
1999    
2000    
2001     /*
2002     * Install .Sony, disk and CD-ROM drivers
2003     */
2004    
2005     void InstallDrivers(void)
2006     {
2007     D(bug("Installing drivers...\n"));
2008     M68kRegisters r;
2009     uint8 pb[SIZEOF_IOParam];
2010    
2011     // Open .Sony driver
2012     WriteMacInt8((uint32)pb + ioPermssn, 0);
2013     WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\005.Sony");
2014     r.a[0] = (uint32)pb;
2015     Execute68kTrap(0xa000, &r); // Open()
2016    
2017     // Install disk driver
2018     r.a[0] = ROM_BASE + sony_offset + 0x100;
2019     r.d[0] = (uint32)DiskRefNum;
2020     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2021     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~DiskRefNum * 4); // Get driver handle from Unit Table
2022     Execute68kTrap(0xa029, &r); // HLock()
2023     uint32 dce = ReadMacInt32(r.a[0]);
2024     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x100);
2025     WriteMacInt16(dce + dCtlFlags, DiskDriverFlags);
2026    
2027     // Open disk driver
2028     WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\005.Disk");
2029     r.a[0] = (uint32)pb;
2030     Execute68kTrap(0xa000, &r); // Open()
2031    
2032     // Install CD-ROM driver unless nocdrom option given
2033     if (!PrefsFindBool("nocdrom")) {
2034    
2035     // Install CD-ROM driver
2036     r.a[0] = ROM_BASE + sony_offset + 0x200;
2037     r.d[0] = (uint32)CDROMRefNum;
2038     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2039     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~CDROMRefNum * 4); // Get driver handle from Unit Table
2040     Execute68kTrap(0xa029, &r); // HLock()
2041     dce = ReadMacInt32(r.a[0]);
2042     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x200);
2043     WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags);
2044    
2045     // Open CD-ROM driver
2046     WriteMacInt32((uint32)pb + ioNamePtr, (uint32)"\010.AppleCD");
2047     r.a[0] = (uint32)pb;
2048     Execute68kTrap(0xa000, &r); // Open()
2049     }
2050    
2051     // Install serial drivers
2052     r.a[0] = ROM_BASE + sony_offset + 0x300;
2053     r.d[0] = (uint32)-6;
2054     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2055     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-6) * 4); // Get driver handle from Unit Table
2056     Execute68kTrap(0xa029, &r); // HLock()
2057     dce = ReadMacInt32(r.a[0]);
2058     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x300);
2059     WriteMacInt16(dce + dCtlFlags, 0x4d00);
2060    
2061     r.a[0] = ROM_BASE + sony_offset + 0x400;
2062     r.d[0] = (uint32)-7;
2063     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2064     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-7) * 4); // Get driver handle from Unit Table
2065     Execute68kTrap(0xa029, &r); // HLock()
2066     dce = ReadMacInt32(r.a[0]);
2067     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x400);
2068     WriteMacInt16(dce + dCtlFlags, 0x4e00);
2069    
2070     r.a[0] = ROM_BASE + sony_offset + 0x500;
2071     r.d[0] = (uint32)-8;
2072     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2073     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-8) * 4); // Get driver handle from Unit Table
2074     Execute68kTrap(0xa029, &r); // HLock()
2075     dce = ReadMacInt32(r.a[0]);
2076     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x500);
2077     WriteMacInt16(dce + dCtlFlags, 0x4d00);
2078    
2079     r.a[0] = ROM_BASE + sony_offset + 0x600;
2080     r.d[0] = (uint32)-9;
2081     Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem()
2082     r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-9) * 4); // Get driver handle from Unit Table
2083     Execute68kTrap(0xa029, &r); // HLock()
2084     dce = ReadMacInt32(r.a[0]);
2085     WriteMacInt32(dce + dCtlDriver, ROM_BASE + sony_offset + 0x600);
2086     WriteMacInt16(dce + dCtlFlags, 0x4e00);
2087     }