Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

C64_Amiga.i

Go to the documentation of this file.
00001 /*
00002  *  C64_Amiga.i - Put the pieces together, Amiga specific stuff
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  */
00006 
00007 #include <proto/exec.h>
00008 #include <proto/timer.h>
00009 
00010 
00011 // Library bases
00012 struct Device *TimerBase;
00013 
00014 
00015 /*
00016  *  Constructor, system-dependent things
00017  */
00018 
00019 void C64::c64_ctor1(void)
00020 {
00021         // Open game_io
00022         game_port = CreateMsgPort();
00023         game_io = (struct IOStdReq *)CreateIORequest(game_port, sizeof(IOStdReq));
00024         game_io->io_Message.mn_Node.ln_Type = NT_UNKNOWN;
00025         game_open = port_allocated = false;
00026         if (!OpenDevice("gameport.device", 1, (struct IORequest *)game_io, 0))
00027                 game_open = true;
00028 }
00029 
00030 void C64::c64_ctor2(void)
00031 {
00032         // Initialize joystick variables
00033         joy_state = 0xff;
00034 
00035         // Open timer_io
00036         timer_port = CreateMsgPort();
00037         timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
00038         OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0);
00039 
00040         // Get timer base
00041         TimerBase = timer_io->tr_node.io_Device;
00042 
00043         // Preset speedometer start time
00044         GetSysTime(&start_time);
00045 }
00046 
00047 
00048 /*
00049  *  Destructor, system-dependent things
00050  */
00051 
00052 void C64::c64_dtor(void)
00053 {
00054         // Stop and delete timer_io
00055         if (timer_io != NULL) {
00056                 if (!CheckIO((struct IORequest *)timer_io))
00057                         WaitIO((struct IORequest *)timer_io);
00058                 CloseDevice((struct IORequest *)timer_io);
00059                 DeleteIORequest((struct IORequest *)timer_io);
00060         }
00061 
00062         if (timer_port != NULL)
00063                 DeleteMsgPort(timer_port);
00064 
00065         if (game_open) {
00066                 if (!CheckIO((struct IORequest *)game_io)) {
00067                         AbortIO((struct IORequest *)game_io);
00068                         WaitIO((struct IORequest *)game_io);
00069                 }
00070                 CloseDevice((struct IORequest *)game_io);
00071         }
00072 
00073         if (game_io != NULL)
00074                 DeleteIORequest((struct IORequest *)game_io);
00075 
00076         if (game_port != NULL)
00077                 DeleteMsgPort(game_port);
00078 }
00079 
00080 
00081 /*
00082  *  Start emulation
00083  */
00084 
00085 void C64::Run(void)
00086 {
00087         // Reset chips
00088         TheCPU->Reset();
00089         TheSID->Reset();
00090         TheCIA1->Reset();
00091         TheCIA2->Reset();
00092         TheCPU1541->Reset();
00093 
00094         // Patch kernal IEC routines
00095         orig_kernal_1d84 = Kernal[0x1d84];
00096         orig_kernal_1d85 = Kernal[0x1d85];
00097         PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc);
00098 
00099         // Start timer_io
00100         timer_io->tr_node.io_Command = TR_ADDREQUEST;
00101         timer_io->tr_time.tv_secs = 0;
00102         timer_io->tr_time.tv_micro = ThePrefs.SkipFrames * 20000;  // 20ms per frame
00103         SendIO((struct IORequest *)timer_io);
00104 
00105         // Start the CPU thread
00106         thread_running = true;
00107         quit_thyself = false;
00108         have_a_break = false;
00109         thread_func();
00110 }
00111 
00112 
00113 /*
00114  *  Stop emulation
00115  */
00116 
00117 void C64::Quit(void)
00118 {
00119         // Ask the thread to quit itself if it is running
00120         if (thread_running) {
00121                 quit_thyself = true;
00122                 thread_running = false;
00123         }
00124 }
00125 
00126 
00127 /*
00128  *  Pause emulation
00129  */
00130 
00131 void C64::Pause(void)
00132 {
00133         TheSID->PauseSound();
00134 }
00135 
00136 
00137 /*
00138  *  Resume emulation
00139  */
00140 
00141 void C64::Resume(void)
00142 {
00143         TheSID->ResumeSound();
00144 }
00145 
00146 
00147 /*
00148  *  Vertical blank: Poll keyboard and joysticks, update window
00149  */
00150 
00151 void C64::VBlank(bool draw_frame)
00152 {
00153         struct timeval end_time;
00154         long speed_index;
00155 
00156         // Poll keyboard
00157         TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
00158 
00159         // Poll joysticks
00160         TheCIA1->Joystick1 = poll_joystick(0);
00161         TheCIA1->Joystick2 = poll_joystick(1);
00162 
00163         if (ThePrefs.JoystickSwap) {
00164                 uint8 tmp = TheCIA1->Joystick1;
00165                 TheCIA1->Joystick1 = TheCIA1->Joystick2;
00166                 TheCIA1->Joystick2 = tmp;
00167         }
00168 
00169         // Joystick keyboard emulation
00170         if (TheDisplay->NumLock())
00171                 TheCIA1->Joystick1 &= joykey;
00172         else
00173                 TheCIA1->Joystick2 &= joykey;
00174 
00175         // Count TOD clocks
00176         TheCIA1->CountTOD();
00177         TheCIA2->CountTOD();
00178 
00179         // Update window if needed
00180         if (draw_frame) {
00181         TheDisplay->Update();
00182 
00183                 // Calculate time between VBlanks, display speedometer
00184                 GetSysTime(&end_time);
00185                 SubTime(&end_time, &start_time);
00186                 speed_index = 20000 * 100 * ThePrefs.SkipFrames / (end_time.tv_micro + 1);
00187 
00188                 // Abort timer_io if speed limiter is off
00189                 if (!ThePrefs.LimitSpeed) {
00190                         if (!CheckIO((struct IORequest *)timer_io))
00191                                 AbortIO((struct IORequest *)timer_io);
00192                 } else if (speed_index > 100)
00193                         speed_index = 100;
00194 
00195                 // Wait for timer_io (limit speed)
00196                 WaitIO((struct IORequest *)timer_io);
00197 
00198                 // Restart timer_io
00199                 timer_io->tr_node.io_Command = TR_ADDREQUEST;
00200                 timer_io->tr_time.tv_secs = 0;
00201                 timer_io->tr_time.tv_micro = ThePrefs.SkipFrames * 20000;  // 20ms per frame
00202                 SendIO((struct IORequest *)timer_io);
00203 
00204                 GetSysTime(&start_time);
00205 
00206                 TheDisplay->Speedometer(speed_index);
00207         }
00208 }
00209 
00210 
00211 /*
00212  *  Open/close joystick drivers given old and new state of
00213  *  joystick preferences
00214  */
00215 
00216 void C64::open_close_joysticks(bool oldjoy1, bool oldjoy2, bool newjoy1, bool newjoy2)
00217 {
00218         if (game_open && (oldjoy2 != newjoy2))
00219 
00220                 if (newjoy2) {  // Open joystick
00221                         joy_state = 0xff;
00222                         port_allocated = false;
00223 
00224                         // Allocate game port
00225                         BYTE ctype;
00226                         Forbid();
00227                         game_io->io_Command = GPD_ASKCTYPE;
00228                         game_io->io_Data = &ctype;
00229                         game_io->io_Length = 1;
00230                         DoIO((struct IORequest *)game_io);
00231 
00232                         if (ctype != GPCT_NOCONTROLLER)
00233                                 Permit();
00234                         else {
00235                                 ctype = GPCT_ABSJOYSTICK;
00236                                 game_io->io_Command = GPD_SETCTYPE;
00237                                 game_io->io_Data = &ctype;
00238                                 game_io->io_Length = 1;
00239                                 DoIO((struct IORequest *)game_io);
00240                                 Permit();
00241 
00242                                 port_allocated = true;
00243 
00244                                 // Set trigger conditions
00245                                 game_trigger.gpt_Keys = GPTF_UPKEYS | GPTF_DOWNKEYS;
00246                                 game_trigger.gpt_Timeout = 65535;
00247                                 game_trigger.gpt_XDelta = 1;
00248                                 game_trigger.gpt_YDelta = 1;
00249                                 game_io->io_Command = GPD_SETTRIGGER;
00250                                 game_io->io_Data = &game_trigger;
00251                                 game_io->io_Length = sizeof(struct GamePortTrigger);
00252                                 DoIO((struct IORequest *)game_io);
00253 
00254                                 // Flush device buffer
00255                                 game_io->io_Command = CMD_CLEAR;
00256                                 DoIO((struct IORequest *)game_io);
00257 
00258                                 // Start reading joystick events
00259                                 game_io->io_Command = GPD_READEVENT;
00260                                 game_io->io_Data = &game_event;
00261                                 game_io->io_Length = sizeof(struct InputEvent);
00262                                 SendIO((struct IORequest *)game_io);
00263                         }
00264 
00265                 } else {        // Close joystick
00266 
00267                         // Abort game_io
00268                         if (!CheckIO((struct IORequest *)game_io)) {
00269                                 AbortIO((struct IORequest *)game_io);
00270                                 WaitIO((struct IORequest *)game_io);
00271                         }
00272 
00273                         // Free game port
00274                         if (port_allocated) {
00275                                 BYTE ctype = GPCT_NOCONTROLLER;
00276                                 game_io->io_Command = GPD_SETCTYPE;
00277                                 game_io->io_Data = &ctype;
00278                                 game_io->io_Length = 1;
00279                                 DoIO((struct IORequest *)game_io);
00280 
00281                                 port_allocated = false;
00282                         }
00283                 }
00284 }
00285 
00286 
00287 /*
00288  *  Poll joystick port, return CIA mask
00289  */
00290 
00291 uint8 C64::poll_joystick(int port)
00292 {
00293         if (port == 0)
00294                 return 0xff;
00295 
00296         if (game_open && port_allocated) {
00297 
00298                 // Joystick event arrived?
00299                 while (GetMsg(game_port) != NULL) {
00300 
00301                         // Yes, analyze event
00302                         switch (game_event.ie_Code) {
00303                                 case IECODE_LBUTTON:                                    // Button pressed
00304                                         joy_state &= 0xef;
00305                                         break;
00306 
00307                                 case IECODE_LBUTTON | IECODE_UP_PREFIX: // Button released
00308                                         joy_state |= 0x10;
00309                                         break;
00310 
00311                                 case IECODE_NOBUTTON:                                   // Joystick moved
00312                                         if (game_event.ie_X == 1)
00313                                                 joy_state &= 0xf7;                              // Right
00314                                         if (game_event.ie_X == -1)
00315                                                 joy_state &= 0xfb;                              // Left
00316                                         if (game_event.ie_X == 0)
00317                                                 joy_state |= 0x0c;
00318                                         if (game_event.ie_Y == 1)
00319                                                 joy_state &= 0xfd;                              // Down
00320                                         if (game_event.ie_Y == -1)
00321                                                 joy_state &= 0xfe;                              // Up
00322                                         if (game_event.ie_Y == 0)
00323                                                 joy_state |= 0x03;
00324                                         break;
00325                         }
00326 
00327                         // Start reading the next event
00328                         game_io->io_Command = GPD_READEVENT;
00329                         game_io->io_Data = &game_event;
00330                         game_io->io_Length = sizeof(struct InputEvent);
00331                         SendIO((struct IORequest *)game_io);
00332                 }
00333                 return joy_state;
00334 
00335         } else
00336                 return 0xff;
00337 }
00338 
00339 
00340 /*
00341  * The emulation's main loop
00342  */
00343 
00344 void C64::thread_func(void)
00345 {
00346         while (!quit_thyself) {
00347 
00348 #ifdef FRODO_SC
00349                 // The order of calls is important here
00350                 if (TheVIC->EmulateCycle())
00351                         TheSID->EmulateLine();
00352                 TheCIA1->CheckIRQs();
00353                 TheCIA2->CheckIRQs();
00354                 TheCIA1->EmulateCycle();
00355                 TheCIA2->EmulateCycle();
00356                 TheCPU->EmulateCycle();
00357 
00358                 if (ThePrefs.Emul1541Proc) {
00359                         TheCPU1541->CountVIATimers(1);
00360                         if (!TheCPU1541->Idle)
00361                                 TheCPU1541->EmulateCycle();
00362                 }
00363                 CycleCounter++;
00364 #else
00365                 // The order of calls is important here
00366                 int cycles = TheVIC->EmulateLine();
00367                 TheSID->EmulateLine();
00368 #if !PRECISE_CIA_CYCLES
00369                 TheCIA1->EmulateLine(ThePrefs.CIACycles);
00370                 TheCIA2->EmulateLine(ThePrefs.CIACycles);
00371 #endif
00372 
00373                 if (ThePrefs.Emul1541Proc) {
00374                         int cycles_1541 = ThePrefs.FloppyCycles;
00375                         TheCPU1541->CountVIATimers(cycles_1541);
00376 
00377                         if (!TheCPU1541->Idle) {
00378                                 // 1541 processor active, alternately execute
00379                                 //  6502 and 6510 instructions until both have
00380                                 //  used up their cycles
00381                                 while (cycles >= 0 || cycles_1541 >= 0)
00382                                         if (cycles > cycles_1541)
00383                                                 cycles -= TheCPU->EmulateLine(1);
00384                                         else
00385                                                 cycles_1541 -= TheCPU1541->EmulateLine(1);
00386                         } else
00387                                 TheCPU->EmulateLine(cycles);
00388                 } else
00389                         // 1541 processor disabled, only emulate 6510
00390                         TheCPU->EmulateLine(cycles);
00391 #endif
00392         }
00393 }

Generated on Tue Feb 8 04:07:21 2005 for E32frodo by doxygen 1.3.3