ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/main_amiga.cpp
(Generate patch)

Comparing BasiliskII/src/AmigaOS/main_amiga.cpp (file contents):
Revision 1.2 by cebix, 1999-10-19T17:41:21Z vs.
Revision 1.24 by gbeauche, 2008-01-01T09:40:31Z

# Line 1 | Line 1
1   /*
2   *  main_amiga.cpp - Startup code for AmigaOS
3   *
4 < *  Basilisk II (C) 1997-1999 Christian Bauer
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
# Line 26 | Line 26
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"
# Line 56 | Line 60
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 " " __AMIGADATE__;
70 > static const char __ver[] = "$VER: " VERSION_STRING " " __DATE__;
71   static const int SCRATCH_MEM_SIZE = 65536;
72  
73  
# Line 80 | Line 89 | bool TwentyFourBitAddressing;
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 < uint32 ScratchMem = NULL;                                               // Scratch memory for Mac ROM writes
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
# Line 99 | Line 112 | static struct timerequest *timereq = NUL
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  
# Line 106 | Line 122 | static bool stack_swapped = false;                             //
122   static StackSwapStruct stack_swap;
123  
124  
109 // Prototypes
110 static void jump_to_rom(void);
111 static void tick_func(void);
112
113
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(void)
150 > int main(int argc, char **argv)
151   {
152          // Initialize variables
153          RAMBaseHost = NULL;
# Line 141 | Line 161 | int main(void)
161          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
162          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
163  
144        // Read preferences
145        PrefsInit();
146
164          // Open libraries
165 <        DiskBase = (struct Library *)OpenResource((UBYTE *)"disk.resource");
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);
179 >        GadToolsBase = OpenLibrary((UBYTE *) "gadtools.library", 39);
180          if (GadToolsBase == NULL) {
181 <                ErrorAlert(GetString(STR_NO_GADTOOLS_LIB_ERR));
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);
189 >        AslBase = OpenLibrary((UBYTE *) "asl.library", 36);
190          if (AslBase == NULL) {
191 <                ErrorAlert(GetString(STR_NO_ASL_LIB_ERR));
191 >                ErrorAlert(STR_NO_ASL_LIB_ERR);
192                  QuitEmulator();
193          }
194 <        P96Base = OpenLibrary((UBYTE *)"Picasso96API.library", 2);
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(argc, argv);
206  
207          // Open AHI
208          ahi_port = CreateMsgPort();
# Line 166 | Line 210 | int main(void)
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) {
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                  }
# Line 181 | Line 225 | int main(void)
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(GetString(STR_NO_PREPARE_EMUL_ERR));
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(GetString(STR_NO_MEM_ERR));
236 >                ErrorAlert(STR_NO_MEM_ERR);
237                  QuitEmulator();
238          }
239 <        if (OpenDevice((UBYTE *)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) {
240 <                ErrorAlert(GetString(STR_NO_TIMER_DEV_ERR));
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 = (uint32)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
246 >        ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
247          if (ScratchMem == NULL) {
248 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
248 >                ErrorAlert(STR_NO_MEM_ERR);
249                  QuitEmulator();
250          }
251          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
# Line 213 | Line 257 | int main(void)
257                  WarningAlert(GetString(STR_SMALL_RAM_WARN));
258                  RAMSize = 1024*1024;
259          }
260 <        RAMBaseHost = (uint8 *)AllocMem(RAMSize + 0x100000, MEMF_PUBLIC);
260 >        RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC);
261          if (RAMBaseHost == NULL) {
262 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
263 <                QuitEmulator();
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));
# Line 228 | Line 284 | int main(void)
284          const char *rom_path = PrefsFindString("rom");
285  
286          // Load Mac ROM
287 <        BPTR rom_fh = Open(rom_path ? (char *)rom_path : ROM_FILE_NAME, MODE_OLDFILE);
288 <        if (rom_fh == NULL) {
289 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
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(GetString(STR_ROM_SIZE_ERR));
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(GetString(STR_ROM_FILE_READ_ERR));
302 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
303                  Close(rom_fh);
304                  QuitEmulator();
305          }
# Line 261 | Line 317 | int main(void)
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;
# Line 273 | Line 335 | int main(void)
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, tick_func,
349 <                NP_Name, "Basilisk II 60Hz",
348 >                NP_Entry, (ULONG)tick_func,
349 >                NP_Name, (ULONG)"Basilisk II 60Hz",
350                  NP_Priority, 5,
351                  TAG_END
352          );
# Line 284 | Line 354 | int main(void)
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;
# Line 310 | Line 382 | void Start680x0(void)
382   *  Quit emulator (__saveds because it might be called from an exception)
383   */
384  
385 < void __saveds QuitEmulator(void)
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;
# Line 325 | Line 417 | void __saveds QuitEmulator(void)
417                  FreeSignal(IRQSig);
418          }
419  
328        // Stop 60Hz thread
329        if (tick_proc) {
330                SetSignal(0, SIGF_SINGLE);
331                tick_proc_active = false;
332                Wait(SIGF_SINGLE);
333        }
334
420          // Remove trap handler
421          MainTask->tc_TrapCode = OldTrapHandler;
422  
# Line 340 | Line 425 | void __saveds QuitEmulator(void)
425  
426          // Delete RAM/ROM area
427          if (RAMBaseHost)
428 <                FreeMem(RAMBaseHost, RAMSize + 0x100000);
428 >                FreeVec(RAMBaseHost);
429  
430          // Delete scratch memory area
431          if (ScratchMem)
# Line 367 | Line 452 | void __saveds QuitEmulator(void)
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   }
# Line 390 | Line 483 | void FlushCodeCache(void *start, uint32
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  
# Line 410 | Line 530 | void TriggerInterrupt(void)
530          Signal(MainTask, IRQSigMask);
531   }
532  
533 + void TriggerNMI(void)
534 + {
535 +        AsmTriggerNMI();
536 + }
537 +
538  
539   /*
540 < *  60Hz thread
540 > *  60Hz thread (really 60.15Hz)
541   */
542  
543   static __saveds void tick_func(void)
# Line 427 | Line 552 | static __saveds void tick_func(void)
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)) {
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;
# Line 452 | Line 577 | static __saveds void tick_func(void)
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
# Line 477 | Line 604 | static __saveds void tick_func(void)
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  
# Line 492 | Line 643 | void ErrorAlert(const char *text)
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, text);
646 >        EasyRequest(NULL, &req, NULL, (ULONG)text);
647   }
648  
649  
# Line 512 | Line 663 | void WarningAlert(const char *text)
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, text);
666 >        EasyRequest(NULL, &req, NULL, (ULONG)text);
667   }
668  
669  
# Line 530 | Line 681 | bool ChoiceAlert(const char *text, const
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, text);
684 >        return EasyRequest(NULL, &req, NULL, (ULONG)text);
685   }
686  
687  
# Line 547 | Line 698 | struct trap_regs {     // This must match th
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);
# Line 565 | Line 718 | void __saveds IllInstrHandler(trap_regs
718                  EmulatedSR |= 0x0700;
719  
720                  // Call opcode routine
721 <                EmulOp(*(uint16 *)(r->pc), (M68kRegisters *)r);
721 >                EmulOp(opcode, (M68kRegisters *)r);
722                  r->pc += 2;
723  
724                  // Restore interrupts

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines