00001 /* 00002 * C64_epoc32.i - EPOC32 specific stuff 00003 * 00004 * Frodo (C) 1994-1997 Christian Bauer 00005 * 00006 * -> ported to Epoc32 by Alfred E. Heggestad & Jal Panvel (c) 1999-2000 00007 */ 00008 00009 #include <process.h> 00010 #include "main.h" 00011 #include "sys/time.h" 00012 00013 #ifndef BOOL 00014 #define BOOL bool 00015 #endif 00016 00017 #define DWORD long 00018 00019 #define FRAME_INTERVAL (1000/SCREEN_FREQ) // in milliseconds 00020 #ifdef FRODO_SC 00021 #define SPEEDOMETER_INTERVAL 4000 // in milliseconds 00022 #else 00023 #define SPEEDOMETER_INTERVAL 1000 // in milliseconds 00024 #endif 00025 #define JOYSTICK_SENSITIVITY 40 // % of live range 00026 #define JOYSTICK_MIN 0x0000 // min value of range 00027 #define JOYSTICK_MAX 0xffff // max value of range 00028 #define JOYSTICK_RANGE (JOYSTICK_MAX - JOYSTICK_MIN) 00029 00030 00031 00032 #ifndef HAVE_USLEEP 00033 /* 00034 * NAME: 00035 * usleep -- This is the precision timer for Test Set 00036 * Automation. It uses the select(2) system 00037 * call to delay for the desired number of 00038 * micro-seconds. This call returns ZERO 00039 * (which is usually ignored) on successful 00040 * completion, -1 otherwise. 00041 * 00042 * ALGORITHM: 00043 * 1) We range check the passed in microseconds and log a 00044 * warning message if appropriate. We then return without 00045 * delay, flagging an error. 00046 * 2) Load the Seconds and micro-seconds portion of the 00047 * interval timer structure. 00048 * 3) Call select(2) with no file descriptors set, just the 00049 * timer, this results in either delaying the proper 00050 * ammount of time or being interupted early by a signal. 00051 * 00052 * HISTORY: 00053 * Added when the need for a subsecond timer was evident. 00054 * 00055 * AUTHOR: 00056 * Michael J. Dyer Telephone: AT&T 414.647.4044 00057 * General Electric Medical Systems GE DialComm 8 *767.4044 00058 * P.O. Box 414 Mail Stop 12-27 Sect'y AT&T 414.647.4584 00059 * Milwaukee, Wisconsin USA 53201 8 *767.4584 00060 * internet: mike@sherlock.med.ge.com GEMS WIZARD e-mail: DYER 00061 */ 00062 00063 #include <unistd.h> 00064 00065 #ifdef USE_STDLIB 00066 #include <stdlib.h> 00067 #include <stdio.h> 00068 #include <errno.h> 00069 #endif 00070 00071 #include <time.h> 00072 #include <sys/time.h> 00073 #include <sys/param.h> 00074 #include <sys/types.h> 00075 00076 int usleep(unsigned long int microSeconds) 00077 { 00078 unsigned int Seconds, uSec; 00079 int nfds, readfds, writefds, exceptfds; 00080 struct timeval Timer; 00081 00082 nfds = readfds = writefds = exceptfds = 0; 00083 00084 if( (microSeconds == (unsigned long) 0) 00085 || microSeconds > (unsigned long) 4000000 ) 00086 { 00087 #ifdef USE_STDLIB 00088 errno = ERANGE; /* value out of range */ 00089 #else 00090 #endif 00091 perror( "usleep time out of range ( 0 -> 4000000 ) " ); 00092 return -1; 00093 } 00094 00095 Seconds = microSeconds / (unsigned long) 1000000; 00096 uSec = microSeconds % (unsigned long) 1000000; 00097 00098 Timer.tv_sec = Seconds; 00099 Timer.tv_usec = uSec; 00100 00101 return 0; 00102 } 00103 #endif 00104 00105 00106 00107 void C64::c64_ctor1() 00111 { 00112 #if _DEBUG 00113 vic_time = 0; 00114 #endif 00115 } 00116 00117 00118 void C64::c64_ctor2() 00119 { 00120 } 00121 00122 00123 void C64::c64_dtor() 00124 /* 00125 * Destructor, system-dependent things 00126 */ 00127 { 00128 } 00129 00130 00131 void C64::Run() 00135 { 00136 TheCPU->Reset(); 00137 TheSID->Reset(); 00138 TheCIA1->Reset(); 00139 TheCIA2->Reset(); 00140 TheCPU1541->Reset(); 00141 00142 // Patch kernal IEC routines 00143 orig_kernal_1d84 = Kernal[0x1d84]; 00144 orig_kernal_1d85 = Kernal[0x1d85]; 00145 PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc); 00146 00147 // Start the CPU thread 00148 } 00149 00150 00151 void C64::Quit() 00155 { 00156 quit_thyself = TRUE; 00157 } 00158 00159 00160 00161 void C64::VBlank(bool draw_frame) 00165 { 00166 // Poll keyboard 00167 TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey); 00168 if (TheDisplay->quit_requested) 00169 quit_thyself = true; 00170 00171 // Poll joysticks 00172 if (ThePrefs.Joystick1On) 00173 TheCIA1->Joystick1 = poll_joystick(0); 00174 if (ThePrefs.Joystick2On) 00175 TheCIA1->Joystick2 = poll_joystick(1); 00176 00177 // TheCIA1->Joystick1 = 0xff; 00178 // TheCIA1->Joystick2 = 0xff; 00179 00180 #ifndef __SYMBIAN32__ 00181 if (ThePrefs.JoystickSwap) { 00182 uint8 tmp = TheCIA1->Joystick1; 00183 TheCIA1->Joystick1 = TheCIA1->Joystick2; 00184 TheCIA1->Joystick2 = tmp; 00185 } 00186 #endif 00187 00188 00189 // Count TOD clocks 00190 TheCIA1->CountTOD(); 00191 TheCIA2->CountTOD(); 00192 00193 // Update window if needed 00194 if (draw_frame) 00195 { 00196 TheDisplay->Update(); 00197 00198 #ifdef BACKGND_UPDATE 00199 if(TheVIC->ec_changed > 0) // reset flag 00200 --TheVIC->ec_changed; 00201 #endif 00202 // Calculate time between VBlanks, display speedometer 00203 struct timeval tv; 00204 #ifdef USE_STDLIB 00205 gettimeofday(&tv, NULL); 00206 #else 00207 tv.tv_usec = User::TickCount() * 15625; 00208 tv.tv_sec = tv.tv_usec / 1000000; 00209 tv.tv_usec %= 1000000; 00210 #endif 00211 00212 00213 if ((tv.tv_usec -= tv_start.tv_usec) < 0) { 00214 tv.tv_usec += 1000000; 00215 tv.tv_sec -= 1; 00216 } 00217 tv.tv_sec -= tv_start.tv_sec; 00218 double elapsed_time = (double)tv.tv_sec * 1000000 + tv.tv_usec; 00219 speed_index = 20000 / (elapsed_time + 1) * ThePrefs.SkipFrames * 100; 00220 00221 // Limit speed to 100% if desired 00222 if ((speed_index > 100) && ThePrefs.LimitSpeed) { 00223 usleep((unsigned long)(ThePrefs.SkipFrames * 20000 - (long)elapsed_time)); //AEH 991030 00224 speed_index = 100; 00225 } 00226 00227 #ifdef USE_STDLIB 00228 gettimeofday(&tv_start, NULL); 00229 #else 00230 tv_start.tv_usec = User::TickCount() * 15625; 00231 tv_start.tv_sec = tv_start.tv_usec / 1000000; 00232 tv_start.tv_usec %= 1000000; 00233 #endif 00234 00235 TheDisplay->Speedometer((int)speed_index); 00236 } 00237 00238 #ifdef __SYMBIAN32__ 00239 00240 // 00241 // handle asyncronous snapshots 00242 // the dialogs are now done in the AppUi class 00243 // 00244 CE32FrodoAppUi* appui = iFrodoPtr->iDocPtr->iAppUiPtr; 00245 __CHECK_NULL(appui); 00246 00247 switch(appui->iSnapState) 00248 { 00249 case ESnapShotSave: 00250 { 00256 if(appui->iCurrentFile.Length()) 00257 SaveSnapshot((char*)appui->iCurrentFile.PtrZ()); 00258 appui->iSnapState = ESnapShotIdle; 00259 } 00260 break; 00261 00262 case ESnapShotLoad: 00263 { 00264 if(appui->iCurrentFile.Length()) 00265 LoadSnapshot((char*)appui->iCurrentFile.PtrZ()); 00266 appui->iSnapState = ESnapShotIdle; 00267 } 00268 break; 00269 00270 case ESnapShotIdle: 00271 default: 00272 break; 00273 } 00274 00275 #endif // __SYMBIAN32__ 00276 00277 } 00278 00279 00280 00281 /* 00282 * Open/close joystick drivers given old and new state of 00283 * joystick preferences 00284 */ 00285 00286 00287 /* 00288 * Poll joystick port, return CIA mask 00289 */ 00290 uint8 C64::poll_joystick(int port) 00291 { 00292 return joykey; 00293 00294 //TODO: insert Joystick input types here: 00295 00296 // uint8 j=0xff; 00297 // if (port==1) j=iJoyPadObserver->GetJoyPadState(); 00298 // return j; 00299 00300 } 00301 00302 00303 bool C64::TogglePause(void) 00307 { 00308 have_a_break = !have_a_break; 00309 if (have_a_break) 00310 iSoundHaveBeenPaused = ETrue; 00311 else 00312 iFrodoPtr->StartC64(); 00313 return have_a_break; 00314 } 00315 00316 bool C64::Paused() 00320 { 00321 return have_a_break; 00322 } 00323 00324 void C64::thread_func() 00325 { 00326 for(TInt i=0;i<TOTAL_RASTERS;i++) 00327 { 00328 00329 int cycles = TheVIC->EmulateLine(); 00330 00331 TheSID->EmulateLine(); 00332 00333 TheCIA1->EmulateLine(ThePrefs.CIACycles); 00334 TheCIA2->EmulateLine(ThePrefs.CIACycles); 00335 00336 if (ThePrefs.Emul1541Proc) { 00337 int cycles_1541 = ThePrefs.FloppyCycles; 00338 TheCPU1541->CountVIATimers(cycles_1541); 00339 00340 if (!TheCPU1541->Idle) { 00341 // 1541 processor active, alternately execute 00342 // 6502 and 6510 instructions until both have 00343 // used up their cycles 00344 while (cycles >= 0 || cycles_1541 >= 0) 00345 if (cycles > cycles_1541) 00346 cycles -= TheCPU->EmulateLine(1); 00347 else 00348 cycles_1541 -= TheCPU1541->EmulateLine(1); 00349 } else 00350 TheCPU->EmulateLine(cycles); 00351 } else 00352 00353 // 1541 processor disabled, only emulate 6510 00354 TheCPU->EmulateLine(cycles); 00355 00356 } 00357 00358 } // end, C64::thread_func 00359 00360 00361 00362 // EOF - C64_epoc32.i