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 (22 years, 5 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

# User Rev Content
1 cebix 1.1 /*
2     * main_amiga.cpp - Startup code for AmigaOS
3     *
4 jlachmann 1.22 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #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 jlachmann 1.22 #define __USE_SYSBASE
30 cebix 1.1 #include <proto/exec.h>
31     #include <proto/dos.h>
32     #include <proto/intuition.h>
33 jlachmann 1.22 #include <inline/exec.h>
34     #include <inline/dos.h>
35     #include <inline/intuition.h>
36 cebix 1.1
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 cebix 1.4 // Options for libnix
64     unsigned long __stack = 0x4000; // Stack requirement
65     int __nocommandline = 1; // Disable command line parsing
66 cebix 1.3
67    
68 cebix 1.1 // Constants
69     static const char ROM_FILE_NAME[] = "ROM";
70 cebix 1.3 static const char __ver[] = "$VER: " VERSION_STRING " " __DATE__;
71 cebix 1.1 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 cebix 1.3 struct Library *GfxBase = NULL;
93     struct IntuitionBase *IntuitionBase = NULL;
94 cebix 1.1 struct Library *GadToolsBase = NULL;
95 cebix 1.3 struct Library *IFFParseBase = NULL;
96 cebix 1.1 struct Library *AslBase = NULL;
97     struct Library *P96Base = NULL;
98 cebix 1.6 struct Library *CyberGfxBase = NULL;
99 cebix 1.1 struct Library *TimerBase = NULL;
100     struct Library *AHIBase = NULL;
101     struct Library *DiskBase = NULL;
102    
103     struct Task *MainTask; // Our task
104 gbeauche 1.11 uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes
105 cebix 1.1 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 cebix 1.14 static struct Process *xpram_proc = NULL; // XPRAM watchdog
116     static volatile bool xpram_proc_active = true; // Flag for quitting the XPRAM watchdog
117    
118 cebix 1.1 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 cebix 1.14 extern "C" void DisableSuperBypass(void);
131 cebix 1.1 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 cebix 1.3 extern "C" void quit_emulator(void);
136 cebix 1.12 extern "C" void AsmTriggerNMI(void);
137 cebix 1.1 uint16 EmulatedSR; // Emulated SR (supervisor bit and interrupt mask)
138    
139    
140 cebix 1.3 // Prototypes
141     static void jump_to_rom(void);
142 cebix 1.14 static void xpram_func(void);
143 cebix 1.3 static void tick_func(void);
144    
145    
146 cebix 1.1 /*
147     * Main program
148     */
149    
150 cebix 1.13 int main(int argc, char **argv)
151 cebix 1.1 {
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 jlachmann 1.22 GfxBase = OpenLibrary((UBYTE *) "graphics.library", 39);
166 cebix 1.3 if (GfxBase == NULL) {
167     printf("Cannot open graphics.library V39.\n");
168     exit(1);
169     }
170 jlachmann 1.22 IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *) "intuition.library", 39);
171 cebix 1.3 if (IntuitionBase == NULL) {
172     printf("Cannot open intuition.library V39.\n");
173     CloseLibrary(GfxBase);
174     exit(1);
175     }
176 jlachmann 1.22 DiskBase = (struct Library *)OpenResource((UBYTE *) "disk.resource");
177 cebix 1.1 if (DiskBase == NULL)
178     QuitEmulator();
179 jlachmann 1.22 GadToolsBase = OpenLibrary((UBYTE *) "gadtools.library", 39);
180 cebix 1.1 if (GadToolsBase == NULL) {
181 cebix 1.17 ErrorAlert(STR_NO_GADTOOLS_LIB_ERR);
182 cebix 1.1 QuitEmulator();
183     }
184 jlachmann 1.22 IFFParseBase = OpenLibrary((UBYTE *) "iffparse.library", 39);
185 cebix 1.3 if (IFFParseBase == NULL) {
186 cebix 1.17 ErrorAlert(STR_NO_IFFPARSE_LIB_ERR);
187 cebix 1.3 QuitEmulator();
188     }
189 jlachmann 1.22 AslBase = OpenLibrary((UBYTE *) "asl.library", 36);
190 cebix 1.1 if (AslBase == NULL) {
191 cebix 1.17 ErrorAlert(STR_NO_ASL_LIB_ERR);
192 cebix 1.1 QuitEmulator();
193     }
194 cebix 1.6
195 jlachmann 1.20 if (FindTask((UBYTE *) "« Enforcer »"))
196     {
197     ErrorAlert(STR_ENFORCER_RUNNING_ERR);
198     QuitEmulator();
199     }
200    
201 cebix 1.6 // These two can fail (the respective gfx support won't be available, then)
202 jlachmann 1.22 P96Base = OpenLibrary((UBYTE *) "Picasso96API.library", 2);
203     CyberGfxBase = OpenLibrary((UBYTE *) "cybergraphics.library", 2);
204 cebix 1.1
205 cebix 1.3 // Read preferences
206 cebix 1.13 PrefsInit(argc, argv);
207 cebix 1.3
208 cebix 1.1 // 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 jlachmann 1.22 if (OpenDevice((UBYTE *) AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, 0) == 0) {
215 cebix 1.1 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 jlachmann 1.22 if ((uint32)FindName(&SysBase->MemList, (UBYTE *) "chip memory") < 0x2000) {
230 cebix 1.17 ErrorAlert(STR_NO_PREPARE_EMUL_ERR);
231 cebix 1.1 QuitEmulator();
232     }
233    
234     // Open timer.device
235     timereq = (struct timerequest *)AllocVec(sizeof(timerequest), MEMF_PUBLIC | MEMF_CLEAR);
236     if (timereq == NULL) {
237 cebix 1.17 ErrorAlert(STR_NO_MEM_ERR);
238 cebix 1.1 QuitEmulator();
239     }
240 jlachmann 1.22 if (OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) {
241 cebix 1.17 ErrorAlert(STR_NO_TIMER_DEV_ERR);
242 cebix 1.1 QuitEmulator();
243     }
244     TimerBase = (struct Library *)timereq->tr_node.io_Device;
245    
246     // Allocate scratch memory
247 gbeauche 1.11 ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
248 cebix 1.1 if (ScratchMem == NULL) {
249 cebix 1.17 ErrorAlert(STR_NO_MEM_ERR);
250 cebix 1.1 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 jlachmann 1.9 RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC);
262 cebix 1.10 if (RAMBaseHost == NULL) {
263 jlachmann 1.9 uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000;
264     char xText[120];
265    
266     sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize);
267    
268 cebix 1.10 if (ChoiceAlert(xText, "Use", "Quit") != 1)
269 jlachmann 1.9 QuitEmulator();
270    
271     RAMSize = newRAMSize;
272 jlachmann 1.22 RAMBaseHost = (uint8 *)AllocVec(RAMSize - 0x100000, MEMF_PUBLIC);
273 jlachmann 1.9 if (RAMBaseHost == NULL) {
274 cebix 1.17 ErrorAlert(STR_NO_MEM_ERR);
275 jlachmann 1.9 QuitEmulator();
276     }
277 cebix 1.10 }
278 cebix 1.1 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 cebix 1.3 BPTR rom_fh = Open(rom_path ? (char *)rom_path : (char *)ROM_FILE_NAME, MODE_OLDFILE);
289 cebix 1.16 if (rom_fh == 0) {
290 cebix 1.17 ErrorAlert(STR_NO_ROM_FILE_ERR);
291 cebix 1.1 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 cebix 1.17 ErrorAlert(STR_ROM_SIZE_ERR);
298 cebix 1.1 Close(rom_fh);
299     QuitEmulator();
300     }
301     Seek(rom_fh, 0, OFFSET_BEGINNING);
302     if (Read(rom_fh, ROMBaseHost, ROMSize) != ROMSize) {
303 cebix 1.17 ErrorAlert(STR_ROM_FILE_READ_ERR);
304 cebix 1.1 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 cebix 1.2 // Initialize everything
315     if (!InitAll())
316 cebix 1.1 QuitEmulator();
317    
318     // Move VBR away from 0 if neccessary
319     MoveVBR();
320    
321 cebix 1.14 // On 68060, disable Super Bypass mode because of a CPU bug that is triggered by MacOS 8
322     if (CPUIs68060)
323     DisableSuperBypass();
324    
325 jlachmann 1.22 memset((UBYTE *) 8, 0, 0x2000-8);
326    
327 cebix 1.1 // 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 cebix 1.14 // 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 cebix 1.1 // Start 60Hz process
348     tick_proc = CreateNewProcTags(
349 cebix 1.3 NP_Entry, (ULONG)tick_func,
350     NP_Name, (ULONG)"Basilisk II 60Hz",
351 cebix 1.1 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 cebix 1.10 WriteMacInt32(0xbff, 0); // MacsBugFlags
359 jlachmann 1.9
360 cebix 1.1 // 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 cebix 1.3 // Assembly entry point
387     void __saveds quit_emulator(void)
388     {
389     QuitEmulator();
390     }
391    
392     void QuitEmulator(void)
393 cebix 1.1 {
394 cebix 1.14 // Stop 60Hz process
395 cebix 1.7 if (tick_proc) {
396     SetSignal(0, SIGF_SINGLE);
397     tick_proc_active = false;
398     Wait(SIGF_SINGLE);
399     }
400    
401 cebix 1.14 // 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 cebix 1.1 // 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 cebix 1.2 // Deinitialize everything
425     ExitAll();
426 cebix 1.1
427     // Delete RAM/ROM area
428     if (RAMBaseHost)
429 jlachmann 1.9 FreeVec(RAMBaseHost);
430 cebix 1.1
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 cebix 1.6 if (CyberGfxBase)
457     CloseLibrary(CyberGfxBase);
458 cebix 1.1 if (P96Base)
459     CloseLibrary(P96Base);
460     if (AslBase)
461     CloseLibrary(AslBase);
462 cebix 1.3 if (IFFParseBase)
463     CloseLibrary(IFFParseBase);
464 cebix 1.1 if (GadToolsBase)
465     CloseLibrary(GadToolsBase);
466 cebix 1.3 if (IntuitionBase)
467     CloseLibrary((struct Library *)IntuitionBase);
468     if (GfxBase)
469     CloseLibrary(GfxBase);
470 cebix 1.1
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 cebix 1.18 * 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 cebix 1.1 * 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 jlachmann 1.9 }
533    
534     void TriggerNMI(void)
535     {
536     AsmTriggerNMI();
537 cebix 1.1 }
538    
539    
540     /*
541 cebix 1.14 * 60Hz thread (really 60.15Hz)
542 cebix 1.1 */
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 jlachmann 1.22 if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
557 cebix 1.1 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 cebix 1.7 SetInterruptFlag(INTFLAG_1HZ);
582     TriggerInterrupt();
583 cebix 1.1 }
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 cebix 1.14
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 cebix 1.19 uint8 last_xpram[XPRAM_SIZE];
614     memcpy(last_xpram, XPRAM, XPRAM_SIZE);
615 cebix 1.14
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 cebix 1.19 if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
620     memcpy(last_xpram, XPRAM, XPRAM_SIZE);
621 cebix 1.14 SaveXPRAM();
622     }
623     }
624 cebix 1.1
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 cebix 1.3 EasyRequest(NULL, &req, NULL, (ULONG)text);
648 cebix 1.1 }
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 cebix 1.3 EasyRequest(NULL, &req, NULL, (ULONG)text);
668 cebix 1.1 }
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 cebix 1.3 return EasyRequest(NULL, &req, NULL, (ULONG)text);
686 cebix 1.1 }
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 jlachmann 1.22 // D(bug("IllInstrHandler/%ld\n", __LINE__));
703    
704 cebix 1.1 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 cebix 1.8 EmulOp(opcode, (M68kRegisters *)r);
723 cebix 1.1 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     }