Wed, 01 Dec 2010 21:29:44 +0000
add main emulation loop with preliminary timing
src/main.c | file | annotate | diff | revisions |
1.1 --- a/src/main.c Tue Nov 30 01:51:22 2010 +0000 1.2 +++ b/src/main.c Wed Dec 01 21:29:44 2010 +0000 1.3 @@ -5,8 +5,9 @@ 1.4 #include <malloc.h> 1.5 #include <string.h> 1.6 1.7 +#include "SDL.h" 1.8 + 1.9 #include "musashi/m68k.h" 1.10 - 1.11 #include "version.h" 1.12 #include "state.h" 1.13 1.14 @@ -179,40 +180,74 @@ 1.15 // 512K of RAM 1.16 state_init(512*1024); 1.17 1.18 - // set up musashi 1.19 + // set up musashi and reset the CPU 1.20 m68k_set_cpu_type(M68K_CPU_TYPE_68010); 1.21 m68k_pulse_reset(); 1.22 - 1.23 - char dasm[512]; 1.24 - m68k_disassemble(dasm, 0x80001a, M68K_CPU_TYPE_68010); 1.25 - printf("%s\n", dasm); 1.26 +/* 1.27 + size_t i = 0x80001a; 1.28 + size_t len; 1.29 + do { 1.30 + char dasm[512]; 1.31 + len = m68k_disassemble(dasm, i, M68K_CPU_TYPE_68010); 1.32 + printf("%06X: %s\n", i, dasm); 1.33 + i += len; 1.34 + } while (i < 0x8000ff); 1.35 +*/ 1.36 1.37 // set up SDL 1.38 + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { 1.39 + printf("Could not initialise SDL: %s.\n", SDL_GetError()); 1.40 + return -1; 1.41 + } 1.42 1.43 - // emulation loop! 1.44 - // repeat: 1.45 - // m68k_execute() 1.46 - // m68k_set_irq() every 60ms 1.47 - int32_t dwTimerTickCounter, dwCpuCycles; 1.48 - const int32_t CLOCKS_PER_TIMER_TICK = 10e6/60; //< number of clocks per 60Hz timer tick 1.49 - 1.50 - // initialise emulation variables 1.51 - dwTimerTickCounter = CLOCKS_PER_TIMER_TICK; 1.52 + /*** 1.53 + * The 3B1 CPU runs at 10MHz, with DMA running at 1MHz and video refreshing at 1.54 + * around 60Hz (???), with a 60Hz periodic interrupt. 1.55 + */ 1.56 + const uint32_t TIMESLOT_FREQUENCY = 240; // Hz 1.57 + const uint32_t MILLISECS_PER_TIMESLOT = 1e3 / TIMESLOT_FREQUENCY; 1.58 + const uint32_t CLOCKS_PER_60HZ = (10e6 / 60); 1.59 + uint32_t next_timeslot = SDL_GetTicks() + MILLISECS_PER_TIMESLOT; 1.60 + uint32_t clock_cycles = 0; 1.61 bool exitEmu = false; 1.62 for (;;) { 1.63 - dwCpuCycles = m68k_execute(10e6/60); 1.64 - dwTimerTickCounter -= dwCpuCycles; 1.65 + // Run the CPU for however many cycles we need to. CPU core clock is 1.66 + // 10MHz, and we're running at 240Hz/timeslot. Thus: 10e6/240 or 1.67 + // 41667 cycles per timeslot. 1.68 + clock_cycles += m68k_execute(10e6/TIMESLOT_FREQUENCY); 1.69 + 1.70 + // TODO: run DMA here 1.71 1.72 - // check for timer tick expiry 1.73 - if (dwTimerTickCounter <= 0) { 1.74 - // TODO: Timer Tick IRQ 1.75 - 1.76 + // Is it time to run the 60Hz periodic interrupt yet? 1.77 + if (clock_cycles > CLOCKS_PER_60HZ) { 1.78 + // TODO: refresh screen 1.79 + // TODO: trigger periodic interrupt (if enabled) 1.80 + // decrement clock cycle counter, we've handled the intr. 1.81 + clock_cycles -= CLOCKS_PER_60HZ; 1.82 } 1.83 1.84 + printf("timeslot\n"); 1.85 + 1.86 + // make sure frame rate is equal to real time 1.87 + uint32_t now = SDL_GetTicks(); 1.88 + if (now < next_timeslot) { 1.89 + // timeslot finished early -- eat up some time 1.90 + SDL_Delay(next_timeslot - now); 1.91 + } else { 1.92 + // timeslot finished late -- skip ahead to gain time 1.93 + // TODO: if this happens a lot, we should let the user know 1.94 + // that their PC might not be fast enough... 1.95 + next_timeslot = now; 1.96 + } 1.97 + // advance to the next timeslot 1.98 + next_timeslot += MILLISECS_PER_TIMESLOT; 1.99 + 1.100 + // if we've been asked to exit the emulator, then do so. 1.101 if (exitEmu) break; 1.102 } 1.103 1.104 // shut down and exit 1.105 + SDL_Quit(); 1.106 1.107 return 0; 1.108 }