ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/rom_patches.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 2002-02-04T16:58:13Z (22 years, 9 months ago) by cebix
Branch: cebix
CVS Tags: start
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

# Content
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 }