home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / AmigaOS / main_amiga.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-02  |  17.7 KB  |  704 lines

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