Sat, 19 Apr 2014 02:19:39 -0600
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