add preliminary WD279x emulation to core

Sun, 05 Dec 2010 16:20:00 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 05 Dec 2010 16:20:00 +0000
changeset 52
a350dfa92895
parent 51
e5a92d7beecf
child 53
e1693c4b8a0c

add preliminary WD279x emulation to core

src/main.c file | annotate | diff | revisions
src/memory.c file | annotate | diff | revisions
src/state.c file | annotate | diff | revisions
src/state.h file | annotate | diff | revisions
     1.1 --- a/src/main.c	Sun Dec 05 16:18:50 2010 +0000
     1.2 +++ b/src/main.c	Sun Dec 05 16:20:00 2010 +0000
     1.3 @@ -188,6 +188,10 @@
     1.4  	printf("Set %dx%d at %d bits-per-pixel mode\n\n", screen->w, screen->h, screen->format->BitsPerPixel);
     1.5  	SDL_WM_SetCaption("FreeBee 3B1 emulator", "FreeBee");
     1.6  
     1.7 +	// Load a disc image
     1.8 +	FILE *disc = fopen("discim", "rb");
     1.9 +	wd2797_load(&state.fdc_ctx, disc, 512, 10, 2);
    1.10 +
    1.11  	/***
    1.12  	 * The 3B1 CPU runs at 10MHz, with DMA running at 1MHz and video refreshing at
    1.13  	 * around 60Hz (???), with a 60Hz periodic interrupt.
    1.14 @@ -237,5 +241,9 @@
    1.15  		if (exitEmu) break;
    1.16  	}
    1.17  
    1.18 +	// Release the disc image
    1.19 +	wd2797_unload(&state.fdc_ctx);
    1.20 +	fclose(disc);
    1.21 +
    1.22  	return 0;
    1.23  }
     2.1 --- a/src/memory.c	Sun Dec 05 16:18:50 2010 +0000
     2.2 +++ b/src/memory.c	Sun Dec 05 16:20:00 2010 +0000
     2.3 @@ -310,6 +310,9 @@
     2.4  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
     2.5  						break;
     2.6  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
     2.7 +						data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
     2.8 +						printf("WD279X: rd %02X ==> %02X\n", (address >> 1) & 3, data);
     2.9 +						handled = true;
    2.10  						break;
    2.11  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
    2.12  						break;
    2.13 @@ -472,6 +475,9 @@
    2.14  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
    2.15  						break;
    2.16  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
    2.17 +						data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
    2.18 +						printf("WD279X: rd %02X ==> %02X\n", (address >> 1) & 3, data);
    2.19 +						handled = true;
    2.20  						break;
    2.21  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
    2.22  						break;
    2.23 @@ -643,6 +649,9 @@
    2.24  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
    2.25  						break;
    2.26  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
    2.27 +						data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
    2.28 +						printf("WD279X: rd %02X ==> %02X\n", (address >> 1) & 3, data);
    2.29 +						handled = true;
    2.30  						break;
    2.31  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
    2.32  						break;
    2.33 @@ -762,6 +771,8 @@
    2.34  				break;
    2.35  			case 0x0A0000:				// Miscellaneous Control Register
    2.36  				// TODO: handle the ctrl bits properly
    2.37 +				// TODO: &0x8000 --> dismiss 60hz intr
    2.38 +				state.dma_reading = (value & 0x4000);
    2.39  				state.leds = (~value & 0xF00) >> 8;
    2.40  				printf("LEDs: %s %s %s %s\n",
    2.41  						(state.leds & 8) ? "R" : "-",
    2.42 @@ -779,8 +790,22 @@
    2.43  				handled = true;
    2.44  				break;
    2.45  			case 0x0D0000:				// DMA Address Register
    2.46 +				if (address & 0x004000) {
    2.47 +					// A14 high -- set most significant bits
    2.48 +					state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
    2.49 +				} else {
    2.50 +					// A14 low -- set least significant bits
    2.51 +					state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
    2.52 +				}
    2.53  				break;
    2.54  			case 0x0E0000:				// Disk Control Register
    2.55 +				// B7 = FDD controller reset
    2.56 +				if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
    2.57 +				// B6 = drive 0 select -- TODO
    2.58 +				// B5 = motor enable -- TODO
    2.59 +				// B4 = HDD controller reset -- TODO
    2.60 +				// B3 = HDD0 select -- TODO
    2.61 +				// B2,1,0 = HDD0 head select
    2.62  				break;
    2.63  			case 0x0F0000:				// Line Printer Data Register
    2.64  				break;
    2.65 @@ -810,6 +835,9 @@
    2.66  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
    2.67  						break;
    2.68  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
    2.69 +						wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
    2.70 +						printf("WD279X: wr %02X ==> %02X\n\t", (address >> 1) & 3, value);
    2.71 +						//handled = true;
    2.72  						break;
    2.73  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
    2.74  						break;
    2.75 @@ -936,6 +964,8 @@
    2.76  				break;
    2.77  			case 0x0A0000:				// Miscellaneous Control Register
    2.78  				// TODO: handle the ctrl bits properly
    2.79 +				// TODO: &0x8000 --> dismiss 60hz intr
    2.80 +				state.dma_reading = (value & 0x4000);
    2.81  				state.leds = (~value & 0xF00) >> 8;
    2.82  				printf("LEDs: %s %s %s %s\n",
    2.83  						(state.leds & 8) ? "R" : "-",
    2.84 @@ -953,8 +983,22 @@
    2.85  				handled = true;
    2.86  				break;
    2.87  			case 0x0D0000:				// DMA Address Register
    2.88 +				if (address & 0x004000) {
    2.89 +					// A14 high -- set most significant bits
    2.90 +					state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
    2.91 +				} else {
    2.92 +					// A14 low -- set least significant bits
    2.93 +					state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
    2.94 +				}
    2.95  				break;
    2.96  			case 0x0E0000:				// Disk Control Register
    2.97 +				// B7 = FDD controller reset
    2.98 +				if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
    2.99 +				// B6 = drive 0 select -- TODO
   2.100 +				// B5 = motor enable -- TODO
   2.101 +				// B4 = HDD controller reset -- TODO
   2.102 +				// B3 = HDD0 select -- TODO
   2.103 +				// B2,1,0 = HDD0 head select
   2.104  				break;
   2.105  			case 0x0F0000:				// Line Printer Data Register
   2.106  				break;
   2.107 @@ -983,6 +1027,9 @@
   2.108  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
   2.109  						break;
   2.110  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   2.111 +						wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
   2.112 +						printf("WD279X: wr %02X ==> %02X\n\t", (address >> 1) & 3, value);
   2.113 +						//handled = true;
   2.114  						break;
   2.115  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   2.116  						break;
   2.117 @@ -1109,10 +1156,14 @@
   2.118  				break;
   2.119  			case 0x0A0000:				// Miscellaneous Control Register
   2.120  				// TODO: handle the ctrl bits properly
   2.121 -				if ((address & 1) == 0)
   2.122 -					;// CTL bits
   2.123 -				else
   2.124 +				if ((address & 1) == 0) {
   2.125 +					// low byte
   2.126 +				} else {
   2.127 +					// hight byte
   2.128 +					// TODO: &0x8000 --> dismiss 60hz intr
   2.129 +					state.dma_reading = (value & 0x40);
   2.130  					state.leds = (~value & 0xF);
   2.131 +				}
   2.132  				printf("LEDs: %s %s %s %s\n",
   2.133  						(state.leds & 8) ? "R" : "-",
   2.134  						(state.leds & 4) ? "G" : "-",
   2.135 @@ -1129,8 +1180,22 @@
   2.136  				handled = true;
   2.137  				break;
   2.138  			case 0x0D0000:				// DMA Address Register
   2.139 +				if (address & 0x004000) {
   2.140 +					// A14 high -- set most significant bits
   2.141 +					state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
   2.142 +				} else {
   2.143 +					// A14 low -- set least significant bits
   2.144 +					state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
   2.145 +				}
   2.146  				break;
   2.147  			case 0x0E0000:				// Disk Control Register
   2.148 +				// B7 = FDD controller reset
   2.149 +				if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
   2.150 +				// B6 = drive 0 select -- TODO
   2.151 +				// B5 = motor enable -- TODO
   2.152 +				// B4 = HDD controller reset -- TODO
   2.153 +				// B3 = HDD0 select -- TODO
   2.154 +				// B2,1,0 = HDD0 head select
   2.155  				break;
   2.156  			case 0x0F0000:				// Line Printer Data Register
   2.157  				break;
   2.158 @@ -1159,6 +1224,9 @@
   2.159  					case 0x000000:		// [ef][08]xxxx ==> WD1010 hard disc controller
   2.160  						break;
   2.161  					case 0x010000:		// [ef][19]xxxx ==> WD2797 floppy disc controller
   2.162 +						wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
   2.163 +						printf("WD279X: wr %02X ==> %02X\n\t", (address >> 1) & 3, value);
   2.164 +						//handled = true;
   2.165  						break;
   2.166  					case 0x020000:		// [ef][2a]xxxx ==> Miscellaneous Control Register 2
   2.167  						break;
     3.1 --- a/src/state.c	Sun Dec 05 16:18:50 2010 +0000
     3.2 +++ b/src/state.c	Sun Dec 05 16:20:00 2010 +0000
     3.3 @@ -2,6 +2,7 @@
     3.4  #include <stddef.h>
     3.5  #include <malloc.h>
     3.6  #include <stdio.h>
     3.7 +#include "wd279x.h"
     3.8  #include "state.h"
     3.9  
    3.10  int state_init(size_t ramsize)
    3.11 @@ -60,6 +61,9 @@
    3.12  	fclose(r14c);
    3.13  	fclose(r15c);
    3.14  
    3.15 +	// Initialise the disc controller
    3.16 +	wd2797_init(&state.fdc_ctx);
    3.17 +
    3.18  	return 0;
    3.19  }
    3.20  
    3.21 @@ -69,6 +73,9 @@
    3.22  		free(state.ram);
    3.23  		state.ram = NULL;
    3.24  	}
    3.25 +	
    3.26 +	// Deinitialise the disc controller
    3.27 +	wd2797_done(&state.fdc_ctx);
    3.28  }
    3.29  
    3.30  
     4.1 --- a/src/state.h	Sun Dec 05 16:18:50 2010 +0000
     4.2 +++ b/src/state.h	Sun Dec 05 16:20:00 2010 +0000
     4.3 @@ -4,6 +4,7 @@
     4.4  #include <stddef.h>
     4.5  #include <stdint.h>
     4.6  #include <stdbool.h>
     4.7 +#include "wd279x.h"
     4.8  
     4.9  // Maximum size of the Boot PROMs. Must be a binary power of two.
    4.10  #define ROM_SIZE 32768
    4.11 @@ -17,30 +18,37 @@
    4.12  	// Boot PROM can be up to 32Kbytes total size
    4.13  	uint8_t		rom[ROM_SIZE];		///< Boot PROM data buffer
    4.14  
    4.15 -	// Main system RAM
    4.16 +	//// Main system RAM
    4.17  	uint8_t		*ram;				///< RAM data buffer
    4.18  	size_t		ram_size;			///< Size of RAM buffer in bytes
    4.19  
    4.20 -	// Video RAM
    4.21 -	uint8_t		vram[0x8000];		///< Video RAM
    4.22 +	/// Video RAM
    4.23 +	uint8_t		vram[0x8000];
    4.24  
    4.25 -	// Map RAM
    4.26 -	uint8_t		map[0x800];			///< Map RAM
    4.27 +	/// Map RAM
    4.28 +	uint8_t		map[0x800];
    4.29  
    4.30 -	// Registers
    4.31 +	//// Registers
    4.32  	uint16_t	genstat;			///< General Status Register
    4.33  	uint16_t	bsr0;				///< Bus Status Register 0
    4.34  	uint16_t	bsr1;				///< Bus Status Register 1
    4.35  
    4.36 -	// MISCELLANEOUS CONTROL REGISTER
    4.37 +	//// MISCELLANEOUS CONTROL REGISTER
    4.38 +	bool		dma_reading;		///< True if Disc DMA reads from the controller, false otherwise
    4.39  	uint8_t		leds;				///< LED status, 1=on, in order red3/green2/yellow1/red0 from bit3 to bit0
    4.40  
    4.41 -	// GENERAL CONTROL REGISTER
    4.42 +	//// GENERAL CONTROL REGISTER
    4.43  	/// GENCON.ROMLMAP -- false ORs the address with 0x800000, forcing the
    4.44  	/// 68010 to access ROM instead of RAM when booting. TRM page 2-36.
    4.45  	bool		romlmap;
    4.46  	/// GENCON.PIE -- Parity Error Check Enable
    4.47  	bool		pie;
    4.48 +
    4.49 +	/// DMA Address Register
    4.50 +	uint32_t	dma_address;
    4.51 +
    4.52 +	/// Floppy disc controller context
    4.53 +	WD2797_CTX	fdc_ctx;
    4.54  } S_state;
    4.55  
    4.56  // Global emulator state. Yes, I know global variables are evil, please don't