fixed timing on OSes that set a minimum time for sleeps (previously the main loop code assumed no minimum sleep time; the new version uses longer sleeps less frequently) default tip

Sat, 19 Apr 2014 02:19:39 -0600

author
andrew@localhost
date
Sat, 19 Apr 2014 02:19:39 -0600
changeset 152
d61e13d6e2a5
parent 151
b63a3999e2e7

fixed timing on OSes that set a minimum time for sleeps (previously the main loop code assumed no minimum sleep time; the new version uses longer sleeps less frequently)

src/main.c file | annotate | diff | revisions
     1.1 --- a/src/main.c	Fri Apr 18 01:34:20 2014 -0600
     1.2 +++ b/src/main.c	Sat Apr 19 02:19:39 2014 -0600
     1.3 @@ -253,127 +253,129 @@
     1.4  	 * around 60Hz (???), with a 60Hz periodic interrupt.
     1.5  	 */
     1.6  	const uint32_t SYSTEM_CLOCK = 10e6; // Hz
     1.7 -	const uint32_t TIMESLOT_FREQUENCY = 1000;//240;	// Hz
     1.8 +	const uint32_t TIMESLOT_FREQUENCY = 100;//240;	// Hz
     1.9  	const uint32_t MILLISECS_PER_TIMESLOT = 1e3 / TIMESLOT_FREQUENCY;
    1.10  	const uint32_t CLOCKS_PER_60HZ = (SYSTEM_CLOCK / 60);
    1.11 +	const uint32_t NUM_CPU_TIMESLOTS = 500;
    1.12  	uint32_t next_timeslot = SDL_GetTicks() + MILLISECS_PER_TIMESLOT;
    1.13  	uint32_t clock_cycles = 0, tmp;
    1.14  	bool exitEmu = false;
    1.15  
    1.16  	/*bool lastirq_fdc = false;*/
    1.17  	for (;;) {
    1.18 -		// Run the CPU for however many cycles we need to. CPU core clock is
    1.19 -		// 10MHz, and we're running at 240Hz/timeslot. Thus: 10e6/240 or
    1.20 -		// 41667 cycles per timeslot.
    1.21 -		tmp = m68k_execute(SYSTEM_CLOCK/TIMESLOT_FREQUENCY);
    1.22 -		clock_cycles += tmp;
    1.23 +		for (i = 0; i < NUM_CPU_TIMESLOTS; i++){
    1.24 +			// Run the CPU for however many cycles we need to. CPU core clock is
    1.25 +			// 10MHz, and we're running at 240Hz/timeslot. Thus: 10e6/240 or
    1.26 +			// 41667 cycles per timeslot.
    1.27 +			tmp = m68k_execute(SYSTEM_CLOCK/TIMESLOT_FREQUENCY / NUM_CPU_TIMESLOTS);
    1.28 +			clock_cycles += tmp;
    1.29  
    1.30 -		// Run the DMA engine
    1.31 -		if (state.dmaen) {
    1.32 -			// DMA ready to go -- so do it.
    1.33 -			size_t num = 0;
    1.34 -			while (state.dma_count < 0x4000) {
    1.35 -				uint16_t d = 0;
    1.36 -				// num tells us how many words we've copied. If this is greater than the per-timeslot DMA maximum, bail out!
    1.37 -				if (num > (1e6/TIMESLOT_FREQUENCY)) break;
    1.38 -
    1.39 -				// Evidently we have more words to copy. Copy them.
    1.40 -				if (state.fd_selected){
    1.41 -					if (!wd2797_get_drq(&state.fdc_ctx)) {
    1.42 -						// Bail out, no data available. Try again later.
    1.43 -						break;
    1.44 +			// Run the DMA engine
    1.45 +			if (state.dmaen) {
    1.46 +				// DMA ready to go -- so do it.
    1.47 +				size_t num = 0;
    1.48 +				while (state.dma_count < 0x4000) {
    1.49 +					uint16_t d = 0;
    1.50 +					// num tells us how many words we've copied. If this is greater than the per-timeslot DMA maximum, bail out!
    1.51 +					if (num > (1e6/TIMESLOT_FREQUENCY)) break;
    1.52 +	
    1.53 +					// Evidently we have more words to copy. Copy them.
    1.54 +					if (state.fd_selected){
    1.55 +						if (!wd2797_get_drq(&state.fdc_ctx)) {
    1.56 +							// Bail out, no data available. Try again later.
    1.57 +							break;
    1.58 +						}
    1.59 +					}else if (state.hd_selected){
    1.60 +						if (!wd2010_get_drq(&state.hdc_ctx)) {
    1.61 +							// Bail out, no data available. Try again later.
    1.62 +							break;
    1.63 +						}
    1.64 +					}else{
    1.65 +						printf("ERROR: DMA attempt with no drive selected!\n");
    1.66  					}
    1.67 -				}else if (state.hd_selected){
    1.68 -					if (!wd2010_get_drq(&state.hdc_ctx)) {
    1.69 -						// Bail out, no data available. Try again later.
    1.70 +					if (!access_check_dma(state.dma_reading)) {
    1.71  						break;
    1.72  					}
    1.73 -				}else{
    1.74 -					printf("ERROR: DMA attempt with no drive selected!\n");
    1.75 -				}
    1.76 -				if (!access_check_dma(state.dma_reading)) {
    1.77 -					break;
    1.78 -				}
    1.79 -				uint32_t newAddr;
    1.80 -				// Map logical address to a physical RAM address
    1.81 -				newAddr = mapAddr(state.dma_address, !state.dma_reading);
    1.82 +					uint32_t newAddr;
    1.83 +					// Map logical address to a physical RAM address
    1.84 +					newAddr = mapAddr(state.dma_address, !state.dma_reading);
    1.85 +	
    1.86 +					if (!state.dma_reading) {
    1.87 +						// Data available. Get it from the FDC or HDC.
    1.88 +						if (state.fd_selected) {
    1.89 +							d = wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
    1.90 +							d <<= 8;
    1.91 +							d += wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
    1.92 +						}else if (state.hd_selected) {
    1.93 +							d = wd2010_read_data(&state.hdc_ctx);
    1.94 +							d <<= 8;
    1.95 +							d += wd2010_read_data(&state.hdc_ctx);
    1.96 +						}
    1.97 +						if (newAddr <= 0x1FFFFF) {
    1.98 +							WR16(state.base_ram, newAddr, state.base_ram_size - 1, d);
    1.99 +						} else if (newAddr >= 0x200000) {
   1.100 +							WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, d);
   1.101 +						}
   1.102 +					} else {
   1.103 +						// Data write to FDC or HDC.
   1.104  
   1.105 -				if (!state.dma_reading) {
   1.106 -					// Data available. Get it from the FDC or HDC.
   1.107 -					if (state.fd_selected) {
   1.108 -						d = wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.109 -						d <<= 8;
   1.110 -						d += wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.111 -					}else if (state.hd_selected) {
   1.112 -						d = wd2010_read_data(&state.hdc_ctx);
   1.113 -						d <<= 8;
   1.114 -						d += wd2010_read_data(&state.hdc_ctx);
   1.115 -					}
   1.116 -					if (newAddr <= 0x1FFFFF) {
   1.117 -						WR16(state.base_ram, newAddr, state.base_ram_size - 1, d);
   1.118 -					} else if (newAddr >= 0x200000) {
   1.119 -						WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, d);
   1.120 -					}
   1.121 -				} else {
   1.122 -					// Data write to FDC or HDC.
   1.123 -
   1.124 -					// Get the data from RAM
   1.125 -					if (newAddr <= 0x1fffff) {
   1.126 -						d = RD16(state.base_ram, newAddr, state.base_ram_size - 1);
   1.127 -					} else {
   1.128 -						if (newAddr <= (state.exp_ram_size + 0x200000 - 1))
   1.129 -							d = RD16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   1.130 -						else
   1.131 -							d = 0xffff;
   1.132 +						// Get the data from RAM
   1.133 +						if (newAddr <= 0x1fffff) {
   1.134 +							d = RD16(state.base_ram, newAddr, state.base_ram_size - 1);
   1.135 +						} else {
   1.136 +							if (newAddr <= (state.exp_ram_size + 0x200000 - 1))
   1.137 +								d = RD16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1);
   1.138 +							else
   1.139 +								d = 0xffff;
   1.140 +						}
   1.141 +	
   1.142 +						// Send the data to the FDD or HDD
   1.143 +						if (state.fd_selected){
   1.144 +							wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d >> 8));
   1.145 +							wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d & 0xff));
   1.146 +						}else if (state.hd_selected){
   1.147 +							wd2010_write_data(&state.hdc_ctx, (d >> 8));
   1.148 +							wd2010_write_data(&state.hdc_ctx, (d & 0xff));
   1.149 +						}
   1.150  					}
   1.151  
   1.152 -					// Send the data to the FDD or HDD
   1.153 -					if (state.fd_selected){
   1.154 -						wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d >> 8));
   1.155 -						wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d & 0xff));
   1.156 -					}else if (state.hd_selected){
   1.157 -						wd2010_write_data(&state.hdc_ctx, (d >> 8));
   1.158 -						wd2010_write_data(&state.hdc_ctx, (d & 0xff));
   1.159 -					}
   1.160 +					// Increment DMA address
   1.161 +					state.dma_address+=2;
   1.162 +					// Increment number of words transferred
   1.163 +					num++; state.dma_count++;
   1.164  				}
   1.165  
   1.166 -				// Increment DMA address
   1.167 -				state.dma_address+=2;
   1.168 -				// Increment number of words transferred
   1.169 -				num++; state.dma_count++;
   1.170 +				// Turn off DMA engine if we finished this cycle
   1.171 +				if (state.dma_count >= 0x4000) {
   1.172 +					// FIXME? apparently this isn't required... or is it?
   1.173 +					state.dma_count = 0x3fff;
   1.174 +					/*state.dmaen = false;*/
   1.175 +				}
   1.176 +			}else if (wd2010_get_drq(&state.hdc_ctx)){
   1.177 +				wd2010_dma_miss(&state.hdc_ctx);
   1.178 +			}else if (wd2797_get_drq(&state.fdc_ctx)){
   1.179 +				wd2797_dma_miss(&state.fdc_ctx);
   1.180  			}
   1.181  
   1.182 -			// Turn off DMA engine if we finished this cycle
   1.183 -			if (state.dma_count >= 0x4000) {
   1.184 -				// FIXME? apparently this isn't required... or is it?
   1.185 -				state.dma_count = 0x3fff;
   1.186 -				/*state.dmaen = false;*/
   1.187 +
   1.188 +			// Any interrupts? --> TODO: masking
   1.189 +/*			if (!lastirq_fdc) {
   1.190 +				if (wd2797_get_irq(&state.fdc_ctx)) {
   1.191 +					lastirq_fdc = true;
   1.192 +					m68k_set_irq(2);
   1.193 +				}
   1.194  			}
   1.195 -		}else if (wd2010_get_drq(&state.hdc_ctx)){
   1.196 -			wd2010_dma_miss(&state.hdc_ctx);
   1.197 -		}else if (wd2797_get_drq(&state.fdc_ctx)){
   1.198 -			wd2797_dma_miss(&state.fdc_ctx);
   1.199 -		}
   1.200 -
   1.201 -
   1.202 -		// Any interrupts? --> TODO: masking
   1.203 -/*		if (!lastirq_fdc) {
   1.204 -			if (wd2797_get_irq(&state.fdc_ctx)) {
   1.205 -				lastirq_fdc = true;
   1.206 +*/
   1.207 +			if (wd2797_get_irq(&state.fdc_ctx) || wd2010_get_irq(&state.hdc_ctx)) {
   1.208  				m68k_set_irq(2);
   1.209 +			}else if (keyboard_get_irq(&state.kbd)) {
   1.210 +				m68k_set_irq(3);
   1.211 +			} else {
   1.212 +//				if (!state.timer_asserted){
   1.213 +					m68k_set_irq(0);
   1.214 +//				}
   1.215  			}
   1.216  		}
   1.217 -*/
   1.218 -		if (wd2797_get_irq(&state.fdc_ctx) || wd2010_get_irq(&state.hdc_ctx)) {
   1.219 -			m68k_set_irq(2);
   1.220 -		}else if (keyboard_get_irq(&state.kbd)) {
   1.221 -			m68k_set_irq(3);
   1.222 -		} else {
   1.223 -//			if (!state.timer_asserted){
   1.224 -				m68k_set_irq(0);
   1.225 -//			}
   1.226 -		}
   1.227 -
   1.228  		// Is it time to run the 60Hz periodic interrupt yet?
   1.229  		if (clock_cycles > CLOCKS_PER_60HZ) {
   1.230  			// Refresh the screen