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

C64_Acorn.i

Go to the documentation of this file.
00001 /*
00002  * C64_Acorn.i
00003  *
00004  * RISC OS specific stuff concerning the actual emulator
00005  * Frodo (C) 1994-1997 Christian Bauer
00006  * Acorn port by Andreas Dehmel, 1997
00007  *
00008  */
00009 
00010 
00011 #include "Prefs.h"
00012 #include "ROlib.h"
00013 #include "AcornGUI.h"
00014 
00015 
00016 void C64::LoadSystemConfig(const char *filename)
00017 {
00018   FILE *fp;
00019 
00020   if ((fp = fopen(filename, "r")) != NULL)
00021   {
00022     int i;
00023     Joy_Keys *jk;
00024     int args[10];
00025     char line[256];
00026 
00027     while (fgets(line, 255, fp) != 0)
00028     {
00029       char *b = line;
00030       register char c;
00031 
00032       do {c = *b++;} while (c > 32);
00033       if (c == 32)      // keyword mustn't contain spaces
00034       {
00035         *(b-1) = '\0';
00036         do {c = *b++;} while ((c >= 32) && (c != '='));
00037         if (c == '=')   // read in keyword's arguments
00038         {
00039           int i=0;
00040 
00041           while ((*b != '\0') && (i < 10))
00042           {
00043             args[i++] = strtol(b, &b, 10);
00044           }
00045           if (strcmp(line, "PollAfter") == 0) {PollAfter = args[0];}
00046           else if (strcmp(line, "SpeedAfter") == 0) {SpeedAfter = args[0];}
00047           else if (strcmp(line, "PollSoundAfter") == 0) {PollSoundAfter = args[0];}
00048           else if (strcmp(line, "JoystickKeys1") == 0)
00049           {
00050             jk = &(TheDisplay->JoystickKeys[0]);
00051             jk->up = args[0]; jk->down = args[1]; jk->left = args[2]; jk->right = args[3];
00052             jk->fire = args[4];
00053           }
00054           else if (strcmp(line, "JoystickKeys2") == 0)
00055           {
00056             jk = &(TheDisplay->JoystickKeys[1]);
00057             jk->up = args[0]; jk->down = args[1]; jk->left = args[2]; jk->right = args[3];
00058             jk->fire = args[4];
00059           }
00060           else
00061           {
00062             _kernel_oserror err;
00063 
00064             err.errnum = 0;
00065             sprintf(err.errmess,"Bad keyword <%s> in system configure file!",line);
00066             Wimp_ReportError(&err,1,TASKNAME);
00067           }
00068         }
00069       }
00070     }
00071     fclose(fp);
00072   }
00073 }
00074 
00075 
00076 void C64::SaveSystemConfig(const char *filename)
00077 {
00078   FILE *fp;
00079 
00080   if ((fp = fopen(filename, "w")) != NULL)
00081   {
00082     int i;
00083     Joy_Keys *jk;
00084 
00085     fprintf(fp,"PollAfter = %d\n", PollAfter);
00086     fprintf(fp,"SpeedAfter = %d\n", SpeedAfter);
00087     fprintf(fp,"PollSoundAfter = %d\n", PollSoundAfter);
00088     for (i=0; i<2; i++)
00089     {
00090       jk = &(TheDisplay->JoystickKeys[i]);
00091       fprintf(fp,"JoystickKeys%d",i+1);
00092       fprintf(fp," = %d %d %d %d %d\n", jk->up, jk->down, jk->left, jk->right, jk->fire);
00093     }
00094     fclose(fp);
00095   }
00096 }
00097 
00098 
00099 void C64::ReadTimings(int *poll_after, int *speed_after, int *sound_after)
00100 {
00101   *poll_after = PollAfter; *speed_after = SpeedAfter; *sound_after = PollSoundAfter;
00102 }
00103 
00104 
00105 void C64::WriteTimings(int poll_after, int speed_after, int sound_after)
00106 {
00107   PollAfter = poll_after; SpeedAfter = speed_after; PollSoundAfter = sound_after;
00108 }
00109 
00110 
00111 void C64::RequestSnapshot(void)
00112 {
00113   // Snapshots are only possible if the emulation progresses to the next vsync
00114   if (have_a_break) Resume();
00115   make_a_snapshot = true;
00116 }
00117 
00118 
00119 void C64::c64_ctor1(void)
00120 {
00121   TheWIMP = new WIMP(this);
00122   PollAfter = 20;       // poll every 20 centiseconds
00123   SpeedAfter = 200;     // update speedometer every 2 seconds
00124   PollSoundAfter = 50;  // poll DigitalRenderer every 50 lines
00125   HostVolume = Sound_Volume(0);
00126   // Just a precaution
00127   if (HostVolume < 0) {HostVolume = 0;}
00128   if (HostVolume > MaximumVolume) {HostVolume = MaximumVolume;}
00129   Poll = false;
00130   make_a_snapshot = false;
00131 }
00132 
00133 
00134 void C64::c64_ctor2(void)
00135 {
00136   LoadSystemConfig(DEFAULT_SYSCONF);
00137   // was started from multitasking so pretend ScrollLock OFF no matter what
00138   laststate = (ReadKeyboardStatus() & ~2); SingleTasking = false;
00139   lastptr = 1;
00140 }
00141 
00142 
00143 void C64::c64_dtor(void)
00144 {
00145   delete TheWIMP;
00146 }
00147 
00148 
00149 void C64::open_close_joysticks(bool oldjoy1, bool oldjoy2, bool newjoy1, bool newjoy2)
00150 {
00151   // Check if the Joystick module is loaded. If not then write an illegal value to
00152   // the joystick state.
00153   if (Joystick_Read(0) == -2) {joystate[0] = 0;} else {joystate[0] = 0xff;}
00154   if (Joystick_Read(1) == -2) {joystate[1] = 0;} else {joystate[1] = 0xff;}
00155 }
00156 
00157 
00158 uint8 C64::poll_joystick(int port)
00159 {
00160   register int state;
00161   uint8 joy;
00162 
00163   if ((state = Joystick_Read(port)) != -2) // module present
00164   {
00165     if (state == -1) {joy = joystate[port];}    // use old value
00166     else
00167     {
00168       joy = 0xff;
00169       if ((state & (JoyButton1 + JoyButton2)) != 0) {joy &= 0xef;} // fire
00170       if ((state & 0x80) == 0) // positive direction #1
00171       {
00172         if ((state & 0xff) >= JoyDir_Thresh) {joy &= 0xfe;}             // up
00173       }
00174       else
00175       {
00176         if ((256 - (state & 0xff)) >= JoyDir_Thresh) {joy &= 0xfd;}     // down
00177       }
00178       if ((state & 0x8000) == 0) // positive direction #2
00179       {
00180         if ((state & 0xff00) >= JoyDir_Thresh<<8) {joy &= 0xf7;}        // right
00181       }
00182       else
00183       {
00184         if ((0x10000 - (state & 0xff00)) >= JoyDir_Thresh<<8) {joy &= 0xfb;} // left
00185       }
00186     }
00187     joystate[port] = joy; return(joy);
00188   }
00189   else
00190   {
00191     joystate[port] = 0; return(0xff);
00192   }
00193 }
00194 
00195 
00196 void C64::VBlank(bool draw_frame)
00197 {
00198   int Now, KeyState;
00199   bool InputFocus;
00200 
00201   // Poll keyboard if the window has the input focus.
00202   InputFocus = TheWIMP->EmuWindow->HaveInput();
00203   if (InputFocus)
00204   {
00205     TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey, &joykey2);
00206   }
00207 
00208   // Poll Joysticks
00209   TheCIA1->Joystick1 = (ThePrefs.Joystick1On) ? poll_joystick(0) : 0xff;
00210   TheCIA1->Joystick2 = (ThePrefs.Joystick2On) ? poll_joystick(1) : 0xff;
00211 
00212   // Swap joysticks?
00213   if (ThePrefs.JoystickSwap)
00214   {
00215     register uint8 h;
00216 
00217     h = TheCIA1->Joystick1; TheCIA1->Joystick1 = TheCIA1->Joystick2; TheCIA1->Joystick2 = h;
00218   }
00219 
00220   // Read keyboard state directly since we'll also need ScrollLock later!
00221   KeyState = ReadKeyboardStatus();
00222   if (InputFocus)
00223   {
00224     // Keyboard emulates which joystick? (NumLock ==> Port 2, else Port 1)
00225     if ((KeyState & 4) == 0)
00226     {
00227       TheCIA1->Joystick2 &= joykey;
00228     }
00229     else        // joykey2 only mapped if numLOCK is off.
00230     {
00231       TheCIA1->Joystick1 &= joykey; TheCIA1->Joystick2 &= joykey2;
00232     }
00233   }
00234 
00235   if (draw_frame)
00236   {
00237     TheDisplay->Update();
00238   }
00239 
00240   // Make snapshot?
00241   if (make_a_snapshot)
00242   {
00243     SaveSnapshot((TheWIMP->SnapFile)+44);
00244     make_a_snapshot = false;
00245   }
00246 
00247   Now = OS_ReadMonotonicTime();
00248 
00249   // Limit speed? (hahaha.... ah well...)
00250   if (ThePrefs.LimitSpeed)
00251   {
00252     int Now;
00253 
00254     while ((Now - LastFrame) < 2) // 2cs per frame = 50fps (original speed)
00255     {
00256       Now = OS_ReadMonotonicTime();
00257     }
00258     LastFrame = Now;
00259   }
00260   FramesSince++;
00261 
00262   // Update speedometer (update, not force redraw!)?
00263   if ((Now - LastSpeed) >= SpeedAfter)
00264   {
00265     char b[16];
00266 
00267     if ((Now - LastSpeed) <= 0) {Now = LastSpeed+1;}
00268     // Speed: 100% equals 50fps (round result)
00269     sprintf(b,"%d%%\0",((400*FramesSince)/(Now - LastSpeed) + 1) >> 1);
00270     TheWIMP->EmuPane->WriteIconTextU(Icon_Pane_Speed,b);
00271     LastSpeed = Now; FramesSince = 0;
00272   }
00273 
00274   if (InputFocus)
00275   {
00276     // Scroll lock state changed?
00277     if (((KeyState ^ laststate) & 2) != 0)
00278     {
00279       // change to single tasking: turn off mouse, else restore previous pointer
00280       if ((KeyState & 2) != 0) {lastptr = SetMousePointer(0); SingleTasking = true;}
00281       else {SetMousePointer(lastptr); OS_FlushBuffer(9); SingleTasking = false;}
00282     }
00283     if ((KeyState & 2) != 0) {lastptr = SetMousePointer(0);}
00284     else {SetMousePointer(lastptr); OS_FlushBuffer(9);}
00285   }
00286 
00287   // Poll? ScrollLock forces single tasking, i.e. overrides timings.
00288   if (!SingleTasking)
00289   {
00290     if ((Now - LastPoll) >= PollAfter)
00291     {
00292       Poll = true;
00293     }
00294   }
00295   laststate = KeyState;
00296 }
00297 
00298 
00299 void C64::Run(void)
00300 {
00301   // Resetting chips
00302   TheCPU->Reset();
00303   TheSID->Reset();
00304   TheCIA1->Reset();
00305   TheCIA2->Reset();
00306   TheCPU1541->Reset();
00307 
00308   // Patch kernel IEC routines (copied from C64_Amiga.i
00309   orig_kernal_1d84 = Kernal[0x1d84];
00310   orig_kernal_1d85 = Kernal[0x1d85];
00311   PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc);
00312 
00313   // Start the emulation
00314   thread_running = true; quit_thyself = false; have_a_break = false;
00315   thread_func();
00316 }
00317 
00318 
00319 void C64::Quit(void)
00320 {
00321   if (thread_running)
00322   {
00323     quit_thyself = true; thread_running = false;
00324   }
00325 }
00326 
00327 
00328 void C64::Pause(void)
00329 {
00330   have_a_break = true; TheSID->PauseSound();
00331 }
00332 
00333 
00334 void C64::Resume(void)
00335 {
00336   have_a_break = false; TheSID->ResumeSound();
00337 }
00338 
00339 
00340 void C64::thread_func(void)
00341 {
00342   LastPoll = LastFrame = LastSpeed = OS_ReadMonotonicTime(); FramesSince = 0;
00343 
00344   while (!quit_thyself)
00345   {
00346 #ifdef FRODO_SC
00347     if (TheVIC->EmulateCycle()) {TheSID->EmulateLine();}
00348     TheCIA1->EmulateCycle();
00349     TheCIA2->EmulateCycle();
00350     TheCPU->EmulateCycle();
00351 
00352     if (ThePrefs.Emul1541Proc)
00353     {
00354       TheCPU1541->CountVIATimers(1);
00355       if (!TheCPU1541->Idle) {TheCPU1541->EmulateCycle();}
00356     }
00357     CycleCounter++;
00358 
00359 #else
00360     // Emulate each device one rasterline. Order is important!
00361     int cycles = TheVIC->EmulateLine();
00362     TheSID->EmulateLine();
00363 #if !PRECISE_CIA_CYCLES
00364         TheCIA1->EmulateLine(ThePrefs.CIACycles);
00365         TheCIA2->EmulateLine(ThePrefs.CIACycles);
00366 #endif
00367 
00368     if (ThePrefs.Emul1541Proc)
00369     {
00370       int cycles_1541 = ThePrefs.FloppyCycles;
00371       TheCPU1541->CountVIATimers(cycles_1541);
00372       if (!TheCPU1541->Idle)
00373       {
00374         while ((cycles >= 0) || (cycles_1541 >= 0))
00375         {
00376           if (cycles > cycles_1541) {cycles -= TheCPU->EmulateLine(1);}
00377           else {cycles_1541 -= TheCPU1541->EmulateLine(1);}
00378         }
00379       }
00380       else {TheCPU->EmulateLine(cycles);}
00381     }
00382     else
00383     {
00384       TheCPU->EmulateLine(cycles);
00385     }
00386 #endif
00387 
00388     // Single-tasking: busy-wait 'til unpause
00389     while (SingleTasking && have_a_break)
00390     {
00391       int KeyState;
00392 
00393       TheDisplay->CheckForUnpause(true);        // unpause?
00394       KeyState = ReadKeyboardStatus();
00395       if ((KeyState & 2) == 0)          // leave single tasking?
00396       {
00397         SetMousePointer(lastptr); OS_FlushBuffer(9); SingleTasking = false;
00398       }
00399       laststate = KeyState;
00400     }
00401     if (!SingleTasking)
00402     {
00403       // The system-specific part of this function
00404       if (Poll || have_a_break)
00405       {
00406         TheWIMP->Poll(have_a_break);
00407         LastPoll = LastFrame = OS_ReadMonotonicTime(); Poll = false;
00408       }
00409     }
00410   }
00411 }

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