src/main.c

changeset 112
a392eb8f9806
parent 111
4c85846b09cd
child 120
df40e6668a46
     1.1 --- a/src/main.c	Sat Nov 17 19:13:08 2012 +0000
     1.2 +++ b/src/main.c	Sat Nov 17 19:18:29 2012 +0000
     1.3 @@ -39,6 +39,23 @@
     1.4  	}
     1.5  }
     1.6  
     1.7 +static int load_hd()
     1.8 +{
     1.9 +
    1.10 +	state.hdc_disc0 = fopen("hd.img", "r+b");
    1.11 +	if (!state.hdc_disc0){
    1.12 +		fprintf(stderr, "ERROR loading disc image 'hd.img'.\n");
    1.13 +		state.hdc_disc0 = NULL;
    1.14 +		return (0);
    1.15 +	}else{
    1.16 +		wd2010_init(&state.hdc_ctx, state.hdc_disc0, 512, 16, 8);
    1.17 +		fprintf(stderr, "Disc image loaded.\n");
    1.18 +		return (1);
    1.19 +	}
    1.20 +}
    1.21 +
    1.22 +
    1.23 +
    1.24  /**
    1.25   * @brief Set the pixel at (x, y) to the given value
    1.26   * @note The surface must be locked before calling this!
    1.27 @@ -229,6 +246,8 @@
    1.28  	// Load a disc image
    1.29  	load_fd();
    1.30  
    1.31 +	load_hd();
    1.32 +
    1.33  	/***
    1.34  	 * The 3B1 CPU runs at 10MHz, with DMA running at 1MHz and video refreshing at
    1.35  	 * around 60Hz (???), with a 60Hz periodic interrupt.
    1.36 @@ -240,7 +259,8 @@
    1.37  	uint32_t next_timeslot = SDL_GetTicks() + MILLISECS_PER_TIMESLOT;
    1.38  	uint32_t clock_cycles = 0, tmp;
    1.39  	bool exitEmu = false;
    1.40 -	bool lastirq_fdc = false;
    1.41 +
    1.42 +	/*bool lastirq_fdc = false;*/
    1.43  	for (;;) {
    1.44  		// Run the CPU for however many cycles we need to. CPU core clock is
    1.45  		// 10MHz, and we're running at 240Hz/timeslot. Thus: 10e6/240 or
    1.46 @@ -254,77 +274,48 @@
    1.47  			size_t num = 0;
    1.48  			while (state.dma_count < 0x4000) {
    1.49  				uint16_t d = 0;
    1.50 -
    1.51  				// num tells us how many words we've copied. If this is greater than the per-timeslot DMA maximum, bail out!
    1.52  				if (num > (1e6/TIMESLOT_FREQUENCY)) break;
    1.53  
    1.54  				// Evidently we have more words to copy. Copy them.
    1.55 -				if (!wd2797_get_drq(&state.fdc_ctx)) {
    1.56 -					// Bail out, no data available. Try again later.
    1.57 -					// TODO: handle HDD controller too
    1.58 +				if (state.fd_selected){
    1.59 +					if (!wd2797_get_drq(&state.fdc_ctx)) {
    1.60 +						// Bail out, no data available. Try again later.
    1.61 +						break;
    1.62 +					}
    1.63 +				}else if (state.hd_selected){
    1.64 +					if (!wd2010_get_drq(&state.hdc_ctx)) {
    1.65 +						// Bail out, no data available. Try again later.
    1.66 +						break;
    1.67 +					}
    1.68 +				}else{
    1.69 +					printf("ERROR: DMA attempt with no drive selected!\n");
    1.70 +				}
    1.71 +				if (!access_check_dma(state.dma_reading)) {
    1.72  					break;
    1.73  				}
    1.74 -
    1.75 -				// Check memory access permissions
    1.76 -				// TODO: enforce these!!!! use ACCESS_CHECK_* for guidance.
    1.77 -				bool access_ok;
    1.78 -				switch (checkMemoryAccess(state.dma_address, !state.dma_reading)) {
    1.79 -					case MEM_PAGEFAULT:
    1.80 -						// Page fault
    1.81 -						state.genstat = 0x8BFF
    1.82 -							| (state.dma_reading ? 0x4000 : 0)
    1.83 -							| (state.pie ? 0x0400 : 0);
    1.84 -						access_ok = false;
    1.85 -						break;
    1.86 -
    1.87 -					case MEM_UIE:
    1.88 -						// User access to memory above 4MB
    1.89 -						// FIXME? Shouldn't be possible with DMA... assert this?
    1.90 -						state.genstat = 0x9AFF
    1.91 -							| (state.dma_reading ? 0x4000 : 0)
    1.92 -							| (state.pie ? 0x0400 : 0);
    1.93 -						access_ok = false;
    1.94 -						break;
    1.95 -
    1.96 -					case MEM_KERNEL:
    1.97 -					case MEM_PAGE_NO_WE:
    1.98 -						// Kernel access or page not write enabled
    1.99 -						access_ok = false;
   1.100 -						break;
   1.101 -
   1.102 -					case MEM_ALLOWED:
   1.103 -						access_ok = true;
   1.104 -						break;
   1.105 -				}
   1.106 -				if (!access_ok) {
   1.107 -					state.bsr0 = 0x3C00;
   1.108 -					state.bsr0 |= (state.dma_address >> 16);
   1.109 -					state.bsr1 = state.dma_address & 0xffff;
   1.110 -					if (state.ee) m68k_pulse_bus_error();
   1.111 -					printf("BUS ERROR FROM DMA: genstat=%04X, bsr0=%04X, bsr1=%04X\n", state.genstat, state.bsr0, state.bsr1);
   1.112 -
   1.113 -					// TODO: FIXME: if we get a pagefault, it NEEDS to be tagged as 'peripheral sourced'... this is a HACK!
   1.114 -					printf("REALLY BIG FSCKING HUGE ERROR: DMA Memory Access caused a FAULT!\n");
   1.115 -					exit(-1);
   1.116 -				}
   1.117 -
   1.118 +				uint32_t newAddr;
   1.119  				// Map logical address to a physical RAM address
   1.120 -				uint32_t newAddr = mapAddr(state.dma_address, !state.dma_reading);
   1.121 +				newAddr = mapAddr(state.dma_address, !state.dma_reading);
   1.122  
   1.123  				if (!state.dma_reading) {
   1.124 -					// Data available. Get it from the FDC. TODO: handle HDD too
   1.125 -					d = wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.126 -					d <<= 8;
   1.127 -					d += wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.128 -
   1.129 +					// Data available. Get it from the FDC or HDC.
   1.130 +					if (state.fd_selected) {
   1.131 +						d = wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.132 +						d <<= 8;
   1.133 +						d += wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA);
   1.134 +					}else if (state.hd_selected) {
   1.135 +						d = wd2010_read_data(&state.hdc_ctx);
   1.136 +						d <<= 8;
   1.137 +						d += wd2010_read_data(&state.hdc_ctx);
   1.138 +					}
   1.139  					if (newAddr <= 0x1FFFFF) {
   1.140  						WR16(state.base_ram, newAddr, state.base_ram_size - 1, d);
   1.141  					} else if (newAddr >= 0x200000) {
   1.142  						WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, d);
   1.143  					}
   1.144 -					m68k_write_memory_16(state.dma_address, d);
   1.145  				} else {
   1.146 -					// Data write to FDC. TODO: handle HDD too.
   1.147 +					// Data write to FDC or HDC.
   1.148  
   1.149  					// Get the data from RAM
   1.150  					if (newAddr <= 0x1fffff) {
   1.151 @@ -336,9 +327,14 @@
   1.152  							d = 0xffff;
   1.153  					}
   1.154  
   1.155 -					// Send the data to the FDD
   1.156 -					wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d >> 8));
   1.157 -					wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d & 0xff));
   1.158 +					// Send the data to the FDD or HDD
   1.159 +					if (state.fd_selected){
   1.160 +						wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d >> 8));
   1.161 +						wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d & 0xff));
   1.162 +					}else if (state.hd_selected){
   1.163 +						wd2010_write_data(&state.hdc_ctx, (d >> 8));
   1.164 +						wd2010_write_data(&state.hdc_ctx, (d & 0xff));
   1.165 +					}
   1.166  				}
   1.167  
   1.168  				// Increment DMA address
   1.169 @@ -350,9 +346,11 @@
   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 = 0;
   1.174 -				state.dmaen = false;
   1.175 +				state.dma_count = 0x3fff;
   1.176 +				/*state.dmaen = false;*/
   1.177  			}
   1.178 +		}else if (wd2010_get_drq(&state.hdc_ctx)){
   1.179 +			wd2010_dma_miss(&state.hdc_ctx);
   1.180  		}else if (wd2797_get_drq(&state.fdc_ctx)){
   1.181  			wd2797_dma_miss(&state.fdc_ctx);
   1.182  		}
   1.183 @@ -364,8 +362,9 @@
   1.184  				lastirq_fdc = true;
   1.185  				m68k_set_irq(2);
   1.186  			}
   1.187 +		}
   1.188  */
   1.189 -		if (wd2797_get_irq(&state.fdc_ctx)){
   1.190 +		if (wd2797_get_irq(&state.fdc_ctx) || wd2010_get_irq(&state.hdc_ctx)) {
   1.191  			m68k_set_irq(2);
   1.192  		}else if (keyboard_get_irq(&state.kbd)) {
   1.193  			m68k_set_irq(3);