ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/main_amiga.cpp
Revision: 1.26
Committed: 2009-10-18T16:21:19Z (15 years, 1 month ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.25: +1 -1 lines
Log Message:
fix PrefsInit on amiga

File Contents

# Content
1 /*
2 * main_amiga.cpp - Startup code for AmigaOS
3 *
4 * Basilisk II (C) 1997-2008 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 ErrorAlert(STR_ENFORCER_RUNNING_ERR);
197 QuitEmulator();
198 }
199
200 // These two can fail (the respective gfx support won't be available, then)
201 P96Base = OpenLibrary((UBYTE *) "Picasso96API.library", 2);
202 CyberGfxBase = OpenLibrary((UBYTE *) "cybergraphics.library", 2);
203
204 // Read preferences
205 PrefsInit(NULL, argc, argv);
206
207 // Open AHI
208 ahi_port = CreateMsgPort();
209 if (ahi_port) {
210 ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest));
211 if (ahi_io) {
212 ahi_io->ahir_Version = 2;
213 if (OpenDevice((UBYTE *) AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, 0) == 0) {
214 AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device;
215 }
216 }
217 }
218
219 // Init system routines
220 SysInit();
221
222 // Show preferences editor
223 if (!PrefsFindBool("nogui"))
224 if (!PrefsEditor())
225 QuitEmulator();
226
227 // Check start of Chip memory (because we need access to 0x0000..0x2000)
228 if ((uint32)FindName(&SysBase->MemList, (UBYTE *) "chip memory") < 0x2000) {
229 ErrorAlert(STR_NO_PREPARE_EMUL_ERR);
230 QuitEmulator();
231 }
232
233 // Open timer.device
234 timereq = (struct timerequest *)AllocVec(sizeof(timerequest), MEMF_PUBLIC | MEMF_CLEAR);
235 if (timereq == NULL) {
236 ErrorAlert(STR_NO_MEM_ERR);
237 QuitEmulator();
238 }
239 if (OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) {
240 ErrorAlert(STR_NO_TIMER_DEV_ERR);
241 QuitEmulator();
242 }
243 TimerBase = (struct Library *)timereq->tr_node.io_Device;
244
245 // Allocate scratch memory
246 ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
247 if (ScratchMem == NULL) {
248 ErrorAlert(STR_NO_MEM_ERR);
249 QuitEmulator();
250 }
251 ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block
252
253 // Create area for Mac RAM and ROM (ROM must be higher in memory,
254 // so we allocate one big chunk and put the ROM at the top of it)
255 RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
256 if (RAMSize < 1024*1024) {
257 WarningAlert(GetString(STR_SMALL_RAM_WARN));
258 RAMSize = 1024*1024;
259 }
260 RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC);
261 if (RAMBaseHost == NULL) {
262 uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000;
263 char xText[120];
264
265 sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize);
266
267 if (ChoiceAlert(xText, "Use", "Quit") != 1)
268 QuitEmulator();
269
270 RAMSize = newRAMSize;
271 RAMBaseHost = (uint8 *)AllocVec(RAMSize - 0x100000, MEMF_PUBLIC);
272 if (RAMBaseHost == NULL) {
273 ErrorAlert(STR_NO_MEM_ERR);
274 QuitEmulator();
275 }
276 }
277 RAMBaseMac = (uint32)RAMBaseHost;
278 D(bug("Mac RAM starts at %08lx\n", RAMBaseHost));
279 ROMBaseHost = RAMBaseHost + RAMSize;
280 ROMBaseMac = (uint32)ROMBaseHost;
281 D(bug("Mac ROM starts at %08lx\n", ROMBaseHost));
282
283 // Get rom file path from preferences
284 const char *rom_path = PrefsFindString("rom");
285
286 // Load Mac ROM
287 BPTR rom_fh = Open(rom_path ? (char *)rom_path : (char *)ROM_FILE_NAME, MODE_OLDFILE);
288 if (rom_fh == 0) {
289 ErrorAlert(STR_NO_ROM_FILE_ERR);
290 QuitEmulator();
291 }
292 printf(GetString(STR_READING_ROM_FILE));
293 Seek(rom_fh, 0, OFFSET_END);
294 ROMSize = Seek(rom_fh, 0, OFFSET_CURRENT);
295 if (ROMSize != 512*1024 && ROMSize != 1024*1024) {
296 ErrorAlert(STR_ROM_SIZE_ERR);
297 Close(rom_fh);
298 QuitEmulator();
299 }
300 Seek(rom_fh, 0, OFFSET_BEGINNING);
301 if (Read(rom_fh, ROMBaseHost, ROMSize) != ROMSize) {
302 ErrorAlert(STR_ROM_FILE_READ_ERR);
303 Close(rom_fh);
304 QuitEmulator();
305 }
306
307 // Set CPU and FPU type
308 UWORD attn = SysBase->AttnFlags;
309 CPUType = attn & AFF_68040 ? 4 : (attn & AFF_68030 ? 3 : 2);
310 CPUIs68060 = attn & AFF_68060;
311 FPUType = attn & AFF_68881 ? 1 : 0;
312
313 // Initialize everything
314 if (!InitAll(NULL))
315 QuitEmulator();
316
317 // Move VBR away from 0 if neccessary
318 MoveVBR();
319
320 // On 68060, disable Super Bypass mode because of a CPU bug that is triggered by MacOS 8
321 if (CPUIs68060)
322 DisableSuperBypass();
323
324 memset((UBYTE *) 8, 0, 0x2000-8);
325
326 // Install trap handler
327 EmulatedSR = 0x2700;
328 OldTrapHandler = MainTask->tc_TrapCode;
329 MainTask->tc_TrapCode = (APTR)TrapHandlerAsm;
330
331 // Allocate signal for interrupt emulation and install exception handler
332 IRQSig = AllocSignal(-1);
333 IRQSigMask = 1 << IRQSig;
334 OldExceptionHandler = MainTask->tc_ExceptCode;
335 MainTask->tc_ExceptCode = (APTR)ExceptionHandlerAsm;
336 SetExcept(SIGBREAKF_CTRL_C | IRQSigMask, SIGBREAKF_CTRL_C | IRQSigMask);
337
338 // Start XPRAM watchdog process
339 xpram_proc = CreateNewProcTags(
340 NP_Entry, (ULONG)xpram_func,
341 NP_Name, (ULONG)"Basilisk II XPRAM Watchdog",
342 NP_Priority, 0,
343 TAG_END
344 );
345
346 // Start 60Hz process
347 tick_proc = CreateNewProcTags(
348 NP_Entry, (ULONG)tick_func,
349 NP_Name, (ULONG)"Basilisk II 60Hz",
350 NP_Priority, 5,
351 TAG_END
352 );
353
354 // Set task priority to -1 so we don't use all processing time
355 SetTaskPri(MainTask, -1);
356
357 WriteMacInt32(0xbff, 0); // MacsBugFlags
358
359 // Swap stack to Mac RAM area
360 stack_swap.stk_Lower = RAMBaseHost;
361 stack_swap.stk_Upper = (ULONG)RAMBaseHost + RAMSize;
362 stack_swap.stk_Pointer = RAMBaseHost + 0x8000;
363 StackSwap(&stack_swap);
364 stack_swapped = true;
365
366 // Jump to ROM boot routine
367 Start680x0();
368
369 QuitEmulator();
370 return 0;
371 }
372
373 void Start680x0(void)
374 {
375 typedef void (*rom_func)(void);
376 rom_func fp = (rom_func)(ROMBaseHost + 0x2a);
377 fp();
378 }
379
380
381 /*
382 * Quit emulator (__saveds because it might be called from an exception)
383 */
384
385 // Assembly entry point
386 void __saveds quit_emulator(void)
387 {
388 QuitEmulator();
389 }
390
391 void QuitEmulator(void)
392 {
393 // Stop 60Hz process
394 if (tick_proc) {
395 SetSignal(0, SIGF_SINGLE);
396 tick_proc_active = false;
397 Wait(SIGF_SINGLE);
398 }
399
400 // Stop XPRAM watchdog process
401 if (xpram_proc) {
402 SetSignal(0, SIGF_SINGLE);
403 xpram_proc_active = false;
404 Wait(SIGF_SINGLE);
405 }
406
407 // Restore stack
408 if (stack_swapped) {
409 stack_swapped = false;
410 StackSwap(&stack_swap);
411 }
412
413 // Remove exception handler
414 if (IRQSig >= 0) {
415 SetExcept(0, SIGBREAKF_CTRL_C | IRQSigMask);
416 MainTask->tc_ExceptCode = OldExceptionHandler;
417 FreeSignal(IRQSig);
418 }
419
420 // Remove trap handler
421 MainTask->tc_TrapCode = OldTrapHandler;
422
423 // Deinitialize everything
424 ExitAll();
425
426 // Delete RAM/ROM area
427 if (RAMBaseHost)
428 FreeVec(RAMBaseHost);
429
430 // Delete scratch memory area
431 if (ScratchMem)
432 FreeMem((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
433
434 // Close timer.device
435 if (TimerBase)
436 CloseDevice((struct IORequest *)timereq);
437 if (timereq)
438 FreeVec(timereq);
439
440 // Exit system routines
441 SysExit();
442
443 // Close AHI
444 if (AHIBase)
445 CloseDevice((struct IORequest *)ahi_io);
446 if (ahi_io)
447 DeleteIORequest((struct IORequest *)ahi_io);
448 if (ahi_port)
449 DeleteMsgPort(ahi_port);
450
451 // Exit preferences
452 PrefsExit();
453
454 // Close libraries
455 if (CyberGfxBase)
456 CloseLibrary(CyberGfxBase);
457 if (P96Base)
458 CloseLibrary(P96Base);
459 if (AslBase)
460 CloseLibrary(AslBase);
461 if (IFFParseBase)
462 CloseLibrary(IFFParseBase);
463 if (GadToolsBase)
464 CloseLibrary(GadToolsBase);
465 if (IntuitionBase)
466 CloseLibrary((struct Library *)IntuitionBase);
467 if (GfxBase)
468 CloseLibrary(GfxBase);
469
470 exit(0);
471 }
472
473
474 /*
475 * Code was patched, flush caches if neccessary (i.e. when using a real 680x0
476 * or a dynamically recompiling emulator)
477 */
478
479 void FlushCodeCache(void *start, uint32 size)
480 {
481 CacheClearE(start, size, CACRF_ClearI | CACRF_ClearD);
482 }
483
484
485 /*
486 * Mutexes
487 */
488
489 struct B2_mutex {
490 int dummy; //!!
491 };
492
493 B2_mutex *B2_create_mutex(void)
494 {
495 return new B2_mutex;
496 }
497
498 void B2_lock_mutex(B2_mutex *mutex)
499 {
500 }
501
502 void B2_unlock_mutex(B2_mutex *mutex)
503 {
504 }
505
506 void B2_delete_mutex(B2_mutex *mutex)
507 {
508 delete mutex;
509 }
510
511
512 /*
513 * Interrupt flags (must be handled atomically!)
514 */
515
516 uint32 InterruptFlags;
517
518 void SetInterruptFlag(uint32 flag)
519 {
520 AtomicOr(&InterruptFlags, flag);
521 }
522
523 void ClearInterruptFlag(uint32 flag)
524 {
525 AtomicAnd(&InterruptFlags, ~flag);
526 }
527
528 void TriggerInterrupt(void)
529 {
530 Signal(MainTask, IRQSigMask);
531 }
532
533 void TriggerNMI(void)
534 {
535 AsmTriggerNMI();
536 }
537
538
539 /*
540 * 60Hz thread (really 60.15Hz)
541 */
542
543 static __saveds void tick_func(void)
544 {
545 int tick_counter = 0;
546 struct MsgPort *timer_port = NULL;
547 struct timerequest *timer_io = NULL;
548 ULONG timer_mask = 0;
549
550 // Start 60Hz timer
551 timer_port = CreateMsgPort();
552 if (timer_port) {
553 timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
554 if (timer_io) {
555 if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
556 timer_mask = 1 << timer_port->mp_SigBit;
557 timer_io->tr_node.io_Command = TR_ADDREQUEST;
558 timer_io->tr_time.tv_secs = 0;
559 timer_io->tr_time.tv_micro = 16625;
560 SendIO((struct IORequest *)timer_io);
561 }
562 }
563 }
564
565 while (tick_proc_active) {
566
567 // Wait for timer tick
568 Wait(timer_mask);
569
570 // Restart timer
571 timer_io->tr_node.io_Command = TR_ADDREQUEST;
572 timer_io->tr_time.tv_secs = 0;
573 timer_io->tr_time.tv_micro = 16625;
574 SendIO((struct IORequest *)timer_io);
575
576 // Pseudo Mac 1Hz interrupt, update local time
577 if (++tick_counter > 60) {
578 tick_counter = 0;
579 WriteMacInt32(0x20c, TimerDateTime());
580 SetInterruptFlag(INTFLAG_1HZ);
581 TriggerInterrupt();
582 }
583
584 // Trigger 60Hz interrupt
585 SetInterruptFlag(INTFLAG_60HZ);
586 TriggerInterrupt();
587 }
588
589 // Stop timer
590 if (timer_io) {
591 if (!CheckIO((struct IORequest *)timer_io))
592 AbortIO((struct IORequest *)timer_io);
593 WaitIO((struct IORequest *)timer_io);
594 CloseDevice((struct IORequest *)timer_io);
595 DeleteIORequest(timer_io);
596 }
597 if (timer_port)
598 DeleteMsgPort(timer_port);
599
600 // Main task asked for termination, send signal
601 Forbid();
602 Signal(MainTask, SIGF_SINGLE);
603 }
604
605
606 /*
607 * XPRAM watchdog thread (saves XPRAM every minute)
608 */
609
610 static __saveds void xpram_func(void)
611 {
612 uint8 last_xpram[XPRAM_SIZE];
613 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
614
615 while (xpram_proc_active) {
616 for (int i=0; i<60 && xpram_proc_active; i++)
617 Delay(50); // Only wait 1 second so we quit promptly when xpram_proc_active becomes false
618 if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
619 memcpy(last_xpram, XPRAM, XPRAM_SIZE);
620 SaveXPRAM();
621 }
622 }
623
624 // Main task asked for termination, send signal
625 Forbid();
626 Signal(MainTask, SIGF_SINGLE);
627 }
628
629
630 /*
631 * Display error alert
632 */
633
634 void ErrorAlert(const char *text)
635 {
636 if (PrefsFindBool("nogui")) {
637 printf(GetString(STR_SHELL_ERROR_PREFIX), text);
638 return;
639 }
640 EasyStruct req;
641 req.es_StructSize = sizeof(EasyStruct);
642 req.es_Flags = 0;
643 req.es_Title = (UBYTE *)GetString(STR_ERROR_ALERT_TITLE);
644 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_ERROR_PREFIX);
645 req.es_GadgetFormat = (UBYTE *)GetString(STR_QUIT_BUTTON);
646 EasyRequest(NULL, &req, NULL, (ULONG)text);
647 }
648
649
650 /*
651 * Display warning alert
652 */
653
654 void WarningAlert(const char *text)
655 {
656 if (PrefsFindBool("nogui")) {
657 printf(GetString(STR_SHELL_WARNING_PREFIX), text);
658 return;
659 }
660 EasyStruct req;
661 req.es_StructSize = sizeof(EasyStruct);
662 req.es_Flags = 0;
663 req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
664 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
665 req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON);
666 EasyRequest(NULL, &req, NULL, (ULONG)text);
667 }
668
669
670 /*
671 * Display choice alert
672 */
673
674 bool ChoiceAlert(const char *text, const char *pos, const char *neg)
675 {
676 char str[256];
677 sprintf(str, "%s|%s", pos, neg);
678 EasyStruct req;
679 req.es_StructSize = sizeof(EasyStruct);
680 req.es_Flags = 0;
681 req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
682 req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
683 req.es_GadgetFormat = (UBYTE *)str;
684 return EasyRequest(NULL, &req, NULL, (ULONG)text);
685 }
686
687
688 /*
689 * Illegal Instruction and Privilege Violation trap handlers
690 */
691
692 struct trap_regs { // This must match the layout of M68kRegisters
693 uint32 d[8];
694 uint32 a[8];
695 uint16 sr;
696 uint32 pc;
697 };
698
699 void __saveds IllInstrHandler(trap_regs *r)
700 {
701 // D(bug("IllInstrHandler/%ld\n", __LINE__));
702
703 uint16 opcode = *(uint16 *)(r->pc);
704 if ((opcode & 0xff00) != 0x7100) {
705 printf("Illegal Instruction %04x at %08lx\n", *(uint16 *)(r->pc), r->pc);
706 printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
707 "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
708 "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
709 "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
710 "sr %04x\n",
711 r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
712 r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
713 r->sr);
714 QuitEmulator();
715 } else {
716 // Disable interrupts
717 uint16 sr = EmulatedSR;
718 EmulatedSR |= 0x0700;
719
720 // Call opcode routine
721 EmulOp(opcode, (M68kRegisters *)r);
722 r->pc += 2;
723
724 // Restore interrupts
725 EmulatedSR = sr;
726 if ((EmulatedSR & 0x0700) == 0 && InterruptFlags)
727 Signal(MainTask, IRQSigMask);
728 }
729 }
730
731 void __saveds PrivViolHandler(trap_regs *r)
732 {
733 printf("Privileged instruction %04x %04x at %08lx\n", *(uint16 *)(r->pc), *(uint16 *)(r->pc + 2), r->pc);
734 printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
735 "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
736 "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
737 "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
738 "sr %04x\n",
739 r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
740 r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
741 r->sr);
742 QuitEmulator();
743 }