ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/main_amiga.cpp
Revision: 1.22
Committed: 2002-06-23T08:27:05Z (21 years, 11 months ago) by jlachmann
Branch: MAIN
Changes since 1.21: +22 -14 lines
Log Message:
Adapted to OO video scheme; Audio volume/muting/sample rate now settable

File Contents

# Content
1 /*
2 * main_amiga.cpp - Startup code for AmigaOS
3 *
4 * Basilisk II (C) 1997-2001 Christian Bauer
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 #include <exec/types.h>
22 #include <exec/execbase.h>
23 #include <exec/memory.h>
24 #include <exec/tasks.h>
25 #include <dos/dostags.h>
26 #include <intuition/intuition.h>
27 #include <devices/timer.h>
28 #include <devices/ahi.h>
29 #define __USE_SYSBASE
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <proto/intuition.h>
33 #include <inline/exec.h>
34 #include <inline/dos.h>
35 #include <inline/intuition.h>
36
37 #include "sysdeps.h"
38 #include "cpu_emulation.h"
39 #include "main.h"
40 #include "xpram.h"
41 #include "timer.h"
42 #include "sony.h"
43 #include "disk.h"
44 #include "cdrom.h"
45 #include "scsi.h"
46 #include "audio.h"
47 #include "video.h"
48 #include "serial.h"
49 #include "ether.h"
50 #include "clip.h"
51 #include "emul_op.h"
52 #include "rom_patches.h"
53 #include "prefs.h"
54 #include "prefs_editor.h"
55 #include "sys.h"
56 #include "user_strings.h"
57 #include "version.h"
58
59 #define DEBUG 0
60 #include "debug.h"
61
62
63 // Options for libnix
64 unsigned long __stack = 0x4000; // Stack requirement
65 int __nocommandline = 1; // Disable command line parsing
66
67
68 // Constants
69 static const char ROM_FILE_NAME[] = "ROM";
70 static const char __ver[] = "$VER: " VERSION_STRING " " __DATE__;
71 static const int SCRATCH_MEM_SIZE = 65536;
72
73
74 // RAM and ROM pointers
75 uint32 RAMBaseMac; // RAM base (Mac address space)
76 uint8 *RAMBaseHost; // RAM base (host address space)
77 uint32 RAMSize; // Size of RAM
78 uint32 ROMBaseMac; // ROM base (Mac address space)
79 uint8 *ROMBaseHost; // ROM base (host address space)
80 uint32 ROMSize; // Size of ROM
81
82
83 // CPU and FPU type, addressing mode
84 int CPUType;
85 bool CPUIs68060;
86 int FPUType;
87 bool TwentyFourBitAddressing;
88
89
90 // Global variables
91 extern ExecBase *SysBase;
92 struct Library *GfxBase = NULL;
93 struct IntuitionBase *IntuitionBase = NULL;
94 struct Library *GadToolsBase = NULL;
95 struct Library *IFFParseBase = NULL;
96 struct Library *AslBase = NULL;
97 struct Library *P96Base = NULL;
98 struct Library *CyberGfxBase = NULL;
99 struct Library *TimerBase = NULL;
100 struct Library *AHIBase = NULL;
101 struct Library *DiskBase = NULL;
102
103 struct Task *MainTask; // Our task
104 uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes
105 APTR OldTrapHandler = NULL; // Old trap handler
106 APTR OldExceptionHandler = NULL; // Old exception handler
107 BYTE IRQSig = -1; // "Interrupt" signal number
108 ULONG IRQSigMask = 0; // "Interrupt" signal mask
109
110 static struct timerequest *timereq = NULL; // IORequest for timer
111
112 static struct MsgPort *ahi_port = NULL; // Port for AHI
113 static struct AHIRequest *ahi_io = NULL; // IORequest for AHI
114
115 static struct Process *xpram_proc = NULL; // XPRAM watchdog
116 static volatile bool xpram_proc_active = true; // Flag for quitting the XPRAM watchdog
117
118 static struct Process *tick_proc = NULL; // 60Hz process
119 static volatile bool tick_proc_active = true; // Flag for quitting the 60Hz process
120
121 static bool stack_swapped = false; // Stack swapping
122 static StackSwapStruct stack_swap;
123
124
125 // Assembly functions
126 struct trap_regs;
127 extern "C" void AtomicAnd(uint32 *p, uint32 val);
128 extern "C" void AtomicOr(uint32 *p, uint32 val);
129 extern "C" void MoveVBR(void);
130 extern "C" void DisableSuperBypass(void);
131 extern "C" void TrapHandlerAsm(void);
132 extern "C" void ExceptionHandlerAsm(void);
133 extern "C" void IllInstrHandler(trap_regs *regs);
134 extern "C" void PrivViolHandler(trap_regs *regs);
135 extern "C" void quit_emulator(void);
136 extern "C" void AsmTriggerNMI(void);
137 uint16 EmulatedSR; // Emulated SR (supervisor bit and interrupt mask)
138
139
140 // Prototypes
141 static void jump_to_rom(void);
142 static void xpram_func(void);
143 static void tick_func(void);
144
145
146 /*
147 * Main program
148 */
149
150 int main(int argc, char **argv)
151 {
152 // Initialize variables
153 RAMBaseHost = NULL;
154 ROMBaseHost = NULL;
155 MainTask = FindTask(NULL);
156 struct DateStamp ds;
157 DateStamp(&ds);
158 srand(ds.ds_Tick);
159
160 // Print some info
161 printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
162 printf(" %s\n", GetString(STR_ABOUT_TEXT2));
163
164 // Open libraries
165 GfxBase = OpenLibrary((UBYTE *) "graphics.library", 39);
166 if (GfxBase == NULL) {
167 printf("Cannot open graphics.library V39.\n");
168 exit(1);
169 }
170 IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *) "intuition.library", 39);
171 if (IntuitionBase == NULL) {
172 printf("Cannot open intuition.library V39.\n");
173 CloseLibrary(GfxBase);
174 exit(1);
175 }
176 DiskBase = (struct Library *)OpenResource((UBYTE *) "disk.resource");
177 if (DiskBase == NULL)
178 QuitEmulator();
179 GadToolsBase = OpenLibrary((UBYTE *) "gadtools.library", 39);
180 if (GadToolsBase == NULL) {
181 ErrorAlert(STR_NO_GADTOOLS_LIB_ERR);
182 QuitEmulator();
183 }
184 IFFParseBase = OpenLibrary((UBYTE *) "iffparse.library", 39);
185 if (IFFParseBase == NULL) {
186 ErrorAlert(STR_NO_IFFPARSE_LIB_ERR);
187 QuitEmulator();
188 }
189 AslBase = OpenLibrary((UBYTE *) "asl.library", 36);
190 if (AslBase == NULL) {
191 ErrorAlert(STR_NO_ASL_LIB_ERR);
192 QuitEmulator();
193 }
194
195 if (FindTask((UBYTE *) "« Enforcer »"))
196 {
197 ErrorAlert(STR_ENFORCER_RUNNING_ERR);
198 QuitEmulator();
199 }
200
201 // These two can fail (the respective gfx support won't be available, then)
202 P96Base = OpenLibrary((UBYTE *) "Picasso96API.library", 2);
203 CyberGfxBase = OpenLibrary((UBYTE *) "cybergraphics.library", 2);
204
205 // Read preferences
206 PrefsInit(argc, argv);
207
208 // Open AHI
209 ahi_port = CreateMsgPort();
210 if (ahi_port) {
211 ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest));
212 if (ahi_io) {
213 ahi_io->ahir_Version = 2;
214 if (OpenDevice((UBYTE *) AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, 0) == 0) {
215 AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device;
216 }
217 }
218 }
219
220 // Init system routines
221 SysInit();
222
223 // Show preferences editor
224 if (!PrefsFindBool("nogui"))
225 if (!PrefsEditor())
226 QuitEmulator();
227
228 // Check start of Chip memory (because we need access to 0x0000..0x2000)
229 if ((uint32)FindName(&SysBase->MemList, (UBYTE *) "chip memory") < 0x2000) {
230 ErrorAlert(STR_NO_PREPARE_EMUL_ERR);
231 QuitEmulator();
232 }
233
234 // Open timer.device
235 timereq = (struct timerequest *)AllocVec(sizeof(timerequest), MEMF_PUBLIC | MEMF_CLEAR);
236 if (timereq == NULL) {
237 ErrorAlert(STR_NO_MEM_ERR);
238 QuitEmulator();
239 }
240 if (OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) {
241 ErrorAlert(STR_NO_TIMER_DEV_ERR);
242 QuitEmulator();
243 }
244 TimerBase = (struct Library *)timereq->tr_node.io_Device;
245
246 // Allocate scratch memory
247 ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
248 if (ScratchMem == NULL) {
249 ErrorAlert(STR_NO_MEM_ERR);
250 QuitEmulator();
251 }
252 ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block
253
254 // Create area for Mac RAM and ROM (ROM must be higher in memory,
255 // so we allocate one big chunk and put the ROM at the top of it)
256 RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
257 if (RAMSize < 1024*1024) {
258 WarningAlert(GetString(STR_SMALL_RAM_WARN));
259 RAMSize = 1024*1024;
260 }
261 RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC);
262 if (RAMBaseHost == NULL) {
263 uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000;
264 char xText[120];
265
266 sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize);
267
268 if (ChoiceAlert(xText, "Use", "Quit") != 1)
269 QuitEmulator();
270
271 RAMSize = newRAMSize;
272 RAMBaseHost = (uint8 *)AllocVec(RAMSize - 0x100000, MEMF_PUBLIC);
273 if (RAMBaseHost == NULL) {
274 ErrorAlert(STR_NO_MEM_ERR);
275 QuitEmulator();
276 }
277 }
278 RAMBaseMac = (uint32)RAMBaseHost;
279 D(bug("Mac RAM starts at %08lx\n", RAMBaseHost));
280 ROMBaseHost = RAMBaseHost + RAMSize;
281 ROMBaseMac = (uint32)ROMBaseHost;
282 D(bug("Mac ROM starts at %08lx\n", ROMBaseHost));
283
284 // Get rom file path from preferences
285 const char *rom_path = PrefsFindString("rom");
286
287 // Load Mac ROM
288 BPTR rom_fh = Open(rom_path ? (char *)rom_path : (char *)ROM_FILE_NAME, MODE_OLDFILE);
289 if (rom_fh == 0) {
290 ErrorAlert(STR_NO_ROM_FILE_ERR);
291 QuitEmulator();
292 }
293 printf(GetString(STR_READING_ROM_FILE));
294 Seek(rom_fh, 0, OFFSET_END);
295 ROMSize = Seek(rom_fh, 0, OFFSET_CURRENT);
296 if (ROMSize != 512*1024 && ROMSize != 1024*1024) {
297 ErrorAlert(STR_ROM_SIZE_ERR);
298 Close(rom_fh);
299 QuitEmulator();
300 }
301 Seek(rom_fh, 0, OFFSET_BEGINNING);
302 if (Read(rom_fh, ROMBaseHost, ROMSize) != ROMSize) {
303 ErrorAlert(STR_ROM_FILE_READ_ERR);
304 Close(rom_fh);
305 QuitEmulator();
306 }
307
308 // Set CPU and FPU type
309 UWORD attn = SysBase->AttnFlags;
310 CPUType = attn & AFF_68040 ? 4 : (attn & AFF_68030 ? 3 : 2);
311 CPUIs68060 = attn & AFF_68060;
312 FPUType = attn & AFF_68881 ? 1 : 0;
313
314 // Initialize everything
315 if (!InitAll())
316 QuitEmulator();
317
318 // Move VBR away from 0 if neccessary
319 MoveVBR();
320
321 // On 68060, disable Super Bypass mode because of a CPU bug that is triggered by MacOS 8
322 if (CPUIs68060)
323 DisableSuperBypass();
324
325 memset((UBYTE *) 8, 0, 0x2000-8);
326
327 // Install trap handler
328 EmulatedSR = 0x2700;
329 OldTrapHandler = MainTask->tc_TrapCode;
330 MainTask->tc_TrapCode = (APTR)TrapHandlerAsm;
331
332 // Allocate signal for interrupt emulation and install exception handler
333 IRQSig = AllocSignal(-1);
334 IRQSigMask = 1 << IRQSig;
335 OldExceptionHandler = MainTask->tc_ExceptCode;
336 MainTask->tc_ExceptCode = (APTR)ExceptionHandlerAsm;
337 SetExcept(SIGBREAKF_CTRL_C | IRQSigMask, SIGBREAKF_CTRL_C | IRQSigMask);
338
339 // Start XPRAM watchdog process
340 xpram_proc = CreateNewProcTags(
341 NP_Entry, (ULONG)xpram_func,
342 NP_Name, (ULONG)"Basilisk II XPRAM Watchdog",
343 NP_Priority, 0,
344 TAG_END
345 );
346
347 // Start 60Hz process
348 tick_proc = CreateNewProcTags(
349 NP_Entry, (ULONG)tick_func,
350 NP_Name, (ULONG)"Basilisk II 60Hz",
351 NP_Priority, 5,
352 TAG_END
353 );
354
355 // Set task priority to -1 so we don't use all processing time
356 SetTaskPri(MainTask, -1);
357
358 WriteMacInt32(0xbff, 0); // MacsBugFlags
359
360 // Swap stack to Mac RAM area
361 stack_swap.stk_Lower = RAMBaseHost;
362 stack_swap.stk_Upper = (ULONG)RAMBaseHost + RAMSize;
363 stack_swap.stk_Pointer = RAMBaseHost + 0x8000;
364 StackSwap(&stack_swap);
365 stack_swapped = true;
366
367 // Jump to ROM boot routine
368 Start680x0();
369
370 QuitEmulator();
371 return 0;
372 }
373
374 void Start680x0(void)
375 {
376 typedef void (*rom_func)(void);
377 rom_func fp = (rom_func)(ROMBaseHost + 0x2a);
378 fp();
379 }
380
381
382 /*
383 * Quit emulator (__saveds because it might be called from an exception)
384 */
385
386 // Assembly entry point
387 void __saveds quit_emulator(void)
388 {
389 QuitEmulator();
390 }
391
392 void QuitEmulator(void)
393 {
394 // Stop 60Hz process
395 if (tick_proc) {
396 SetSignal(0, SIGF_SINGLE);
397 tick_proc_active = false;
398 Wait(SIGF_SINGLE);
399 }
400
401 // Stop XPRAM watchdog process
402 if (xpram_proc) {
403 SetSignal(0, SIGF_SINGLE);
404 xpram_proc_active = false;
405 Wait(SIGF_SINGLE);
406 }
407
408 // Restore stack
409 if (stack_swapped) {
410 stack_swapped = false;
411 StackSwap(&stack_swap);
412 }
413
414 // Remove exception handler
415 if (IRQSig >= 0) {
416 SetExcept(0, SIGBREAKF_CTRL_C | IRQSigMask);
417 MainTask->tc_ExceptCode = OldExceptionHandler;
418 FreeSignal(IRQSig);
419 }
420
421 // Remove trap handler
422 MainTask->tc_TrapCode = OldTrapHandler;
423
424 // Deinitialize everything
425 ExitAll();
426
427 // Delete RAM/ROM area
428 if (RAMBaseHost)
429 FreeVec(RAMBaseHost);
430
431 // Delete scratch memory area
432 if (ScratchMem)
433 FreeMem((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
434
435 // Close timer.device
436 if (TimerBase)
437 CloseDevice((struct IORequest *)timereq);
438 if (timereq)
439 FreeVec(timereq);
440
441 // Exit system routines
442 SysExit();
443
444 // Close AHI
445 if (AHIBase)
446 CloseDevice((struct IORequest *)ahi_io);
447 if (ahi_io)
448 DeleteIORequest((struct IORequest *)ahi_io);
449 if (ahi_port)
450 DeleteMsgPort(ahi_port);
451
452 // Exit preferences
453 PrefsExit();
454
455 // Close libraries
456 if (CyberGfxBase)
457 CloseLibrary(CyberGfxBase);
458 if (P96Base)
459 CloseLibrary(P96Base);
460 if (AslBase)
461 CloseLibrary(AslBase);
462 if (IFFParseBase)
463 CloseLibrary(IFFParseBase);
464 if (GadToolsBase)
465 CloseLibrary(GadToolsBase);
466 if (IntuitionBase)
467 CloseLibrary((struct Library *)IntuitionBase);
468 if (GfxBase)
469 CloseLibrary(GfxBase);
470
471 exit(0);
472 }
473
474
475 /*
476 * Code was patched, flush caches if neccessary (i.e. when using a real 680x0
477 * or a dynamically recompiling emulator)
478 */
479
480 void FlushCodeCache(void *start, uint32 size)
481 {
482 CacheClearE(start, size, CACRF_ClearI | CACRF_ClearD);
483 }
484
485
486 /*
487 * Mutexes
488 */
489
490 struct B2_mutex {
491 int dummy; //!!
492 };
493
494 B2_mutex *B2_create_mutex(void)
495 {
496 return new B2_mutex;
497 }
498
499 void B2_lock_mutex(B2_mutex *mutex)
500 {
501 }
502
503 void B2_unlock_mutex(B2_mutex *mutex)
504 {
505 }
506
507 void B2_delete_mutex(B2_mutex *mutex)
508 {
509 delete mutex;
510 }
511
512
513 /*
514 * Interrupt flags (must be handled atomically!)
515 */
516
517 uint32 InterruptFlags;
518
519 void SetInterruptFlag(uint32 flag)
520 {
521 AtomicOr(&InterruptFlags, flag);
522 }
523
524 void ClearInterruptFlag(uint32 flag)
525 {
526 AtomicAnd(&InterruptFlags, ~flag);
527 }
528
529 void TriggerInterrupt(void)
530 {
531 Signal(MainTask, IRQSigMask);
532 }
533
534 void TriggerNMI(void)
535 {
536 AsmTriggerNMI();
537 }
538
539
540 /*
541 * 60Hz thread (really 60.15Hz)
542 */
543
544 static __saveds void tick_func(void)
545 {
546 int tick_counter = 0;
547 struct MsgPort *timer_port = NULL;
548 struct timerequest *timer_io = NULL;
549 ULONG timer_mask = 0;
550
551 // Start 60Hz timer
552 timer_port = CreateMsgPort();
553 if (timer_port) {
554 timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
555 if (timer_io) {
556 if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
557 timer_mask = 1 << timer_port->mp_SigBit;
558 timer_io->tr_node.io_Command = TR_ADDREQUEST;
559 timer_io->tr_time.tv_secs = 0;
560 timer_io->tr_time.tv_micro = 16625;
561 SendIO((struct IORequest *)timer_io);
562 }
563 }
564 }
565
566 while (tick_proc_active) {
567
568 // Wait for timer tick
569 Wait(timer_mask);
570
571 // Restart timer
572 timer_io->tr_node.io_Command = TR_ADDREQUEST;
573 timer_io->tr_time.tv_secs = 0;
574 timer_io->tr_time.tv_micro = 16625;
575 SendIO((struct IORequest *)timer_io);
576
577 // Pseudo Mac 1Hz interrupt, update local time
578 if (++tick_counter > 60) {
579 tick_counter = 0;
580 WriteMacInt32(0x20c, TimerDateTime());
581 SetInterruptFlag(INTFLAG_1HZ);
582 TriggerInterrupt();
583 }
584
585 // Trigger 60Hz interrupt
586 SetInterruptFlag(INTFLAG_60HZ);
587 TriggerInterrupt();
588 }
589
590 // Stop timer
591 if (timer_io) {
592 if (!CheckIO((struct IORequest *)timer_io))
593 AbortIO((struct IORequest *)timer_io);
594 WaitIO((struct IORequest *)timer_io);
595 CloseDevice((struct IORequest *)timer_io);
596 DeleteIORequest(timer_io);
597 }
598 if (timer_port)
599 DeleteMsgPort(timer_port);
600
601 // Main task asked for termination, send signal
602 Forbid();
603 Signal(MainTask, SIGF_SINGLE);
604 }
605
606
607 /*
608 * XPRAM watchdog thread (saves XPRAM every minute)
609 */
610
611 static __saveds void xpram_func(void)
612 {
613 uint8 last_xpram[XPRAM_SIZE];
614 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
615
616 while (xpram_proc_active) {
617 for (int i=0; i<60 && xpram_proc_active; i++)
618 Delay(50); // Only wait 1 second so we quit promptly when xpram_proc_active becomes false
619 if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
620 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
621 SaveXPRAM();
622 }
623 }
624
625 // Main task asked for termination, send signal
626 Forbid();
627 Signal(MainTask, SIGF_SINGLE);
628 }
629
630
631 /*
632 * Display error alert
633 */
634
635 void ErrorAlert(const char *text)
636 {
637 if (PrefsFindBool("nogui")) {
638 printf(GetString(STR_SHELL_ERROR_PREFIX), text);
639 return;
640 }
641 EasyStruct req;
642 req.es_StructSize = sizeof(EasyStruct);
643 req.es_Flags = 0;
644 req.es_Title = (UBYTE *)GetString(STR_ERROR_ALERT_TITLE);
645 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_ERROR_PREFIX);
646 req.es_GadgetFormat = (UBYTE *)GetString(STR_QUIT_BUTTON);
647 EasyRequest(NULL, &req, NULL, (ULONG)text);
648 }
649
650
651 /*
652 * Display warning alert
653 */
654
655 void WarningAlert(const char *text)
656 {
657 if (PrefsFindBool("nogui")) {
658 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
659 return;
660 }
661 EasyStruct req;
662 req.es_StructSize = sizeof(EasyStruct);
663 req.es_Flags = 0;
664 req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
665 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
666 req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON);
667 EasyRequest(NULL, &req, NULL, (ULONG)text);
668 }
669
670
671 /*
672 * Display choice alert
673 */
674
675 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
676 {
677 char str[256];
678 sprintf(str, "%s|%s", pos, neg);
679 EasyStruct req;
680 req.es_StructSize = sizeof(EasyStruct);
681 req.es_Flags = 0;
682 req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
683 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
684 req.es_GadgetFormat = (UBYTE *)str;
685 return EasyRequest(NULL, &req, NULL, (ULONG)text);
686 }
687
688
689 /*
690 * Illegal Instruction and Privilege Violation trap handlers
691 */
692
693 struct trap_regs { // This must match the layout of M68kRegisters
694 uint32 d[8];
695 uint32 a[8];
696 uint16 sr;
697 uint32 pc;
698 };
699
700 void __saveds IllInstrHandler(trap_regs *r)
701 {
702 // D(bug("IllInstrHandler/%ld\n", __LINE__));
703
704 uint16 opcode = *(uint16 *)(r->pc);
705 if ((opcode & 0xff00) != 0x7100) {
706 printf("Illegal Instruction %04x at %08lx\n", *(uint16 *)(r->pc), r->pc);
707 printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
708 "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
709 "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
710 "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
711 "sr %04x\n",
712 r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
713 r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
714 r->sr);
715 QuitEmulator();
716 } else {
717 // Disable interrupts
718 uint16 sr = EmulatedSR;
719 EmulatedSR |= 0x0700;
720
721 // Call opcode routine
722 EmulOp(opcode, (M68kRegisters *)r);
723 r->pc += 2;
724
725 // Restore interrupts
726 EmulatedSR = sr;
727 if ((EmulatedSR & 0x0700) == 0 && InterruptFlags)
728 Signal(MainTask, IRQSigMask);
729 }
730 }
731
732 void __saveds PrivViolHandler(trap_regs *r)
733 {
734 printf("Privileged instruction %04x %04x at %08lx\n", *(uint16 *)(r->pc), *(uint16 *)(r->pc + 2), r->pc);
735 printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
736 "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
737 "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
738 "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
739 "sr %04x\n",
740 r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
741 r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
742 r->sr);
743 QuitEmulator();
744 }