src/main.c

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