add main emulation loop with preliminary timing

Wed, 01 Dec 2010 21:29:44 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 01 Dec 2010 21:29:44 +0000
changeset 20
bea459bc22a8
parent 19
ea417ac1d83a
child 21
e31d2ede6c6b

add main emulation loop with preliminary timing

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