improve error and DMA handling

Sun, 12 Dec 2010 23:47:35 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 12 Dec 2010 23:47:35 +0000
changeset 55
ba6b8e570062
parent 54
57c6ef81ae81
child 56
b3f309d46e97

improve error and DMA handling

doc/3B1 Memory Map.ods file | annotate | diff | revisions
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 Binary file doc/3B1 Memory Map.ods has changed
     2.1 --- a/src/main.c	Mon Dec 06 01:43:04 2010 +0000
     2.2 +++ b/src/main.c	Sun Dec 12 23:47:35 2010 +0000
     2.3 @@ -164,7 +164,11 @@
     2.4  
     2.5  	// set up system state
     2.6  	// 512K of RAM
     2.7 -	state_init(512*1024);
     2.8 +	int i;
     2.9 +	if ((i = state_init(512*1024)) != STATE_E_OK) {
    2.10 +		fprintf(stderr, "ERROR: Emulator initialisation failed. Error code %d.\n", i);
    2.11 +		return i;
    2.12 +	}
    2.13  
    2.14  	// set up musashi and reset the CPU
    2.15  	m68k_set_cpu_type(M68K_CPU_TYPE_68010);
    2.16 @@ -190,6 +194,10 @@
    2.17  
    2.18  	// Load a disc image
    2.19  	FILE *disc = fopen("discim", "rb");
    2.20 +	if (!disc) {
    2.21 +		fprintf(stderr, "ERROR loading disc image 'discim'.\n");
    2.22 +		return -4;
    2.23 +	}
    2.24  	wd2797_load(&state.fdc_ctx, disc, 512, 10, 2);
    2.25  
    2.26  	/***
    2.27 @@ -212,11 +220,6 @@
    2.28  		//
    2.29  		if (state.dmaen) { //((state.dma_count < 0x3fff) && state.dmaen) {
    2.30  			printf("DMA: copy addr=%08X count=%08X idmarw=%d dmarw=%d\n", state.dma_address, state.dma_count, state.idmarw, state.dma_reading);
    2.31 -			if (state.dmaenb) {
    2.32 -				state.dmaenb = false;
    2.33 -//				state.dma_address++;
    2.34 -				state.dma_count++;
    2.35 -			}
    2.36  			// DMA ready to go -- so do it.
    2.37  			size_t num = 0;
    2.38  			while (state.dma_count < 0x4000) {
     3.1 --- a/src/memory.c	Mon Dec 06 01:43:04 2010 +0000
     3.2 +++ b/src/memory.c	Sun Dec 12 23:47:35 2010 +0000
     3.3 @@ -238,8 +238,9 @@
     3.4  			case 0x050000:				// Phone status
     3.5  				break;
     3.6  			case 0x060000:				// DMA Count
     3.7 -				// U/OERR- is always inactive (bit set)
     3.8 -				data = (state.dma_count & 0x3fff) | 0x8000;
     3.9 +				// TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+?
    3.10 +				// Bit 14 is always unused, so leave it set
    3.11 +				data = (state.dma_count & 0x3fff) | 0xC000;
    3.12  				handled = true;
    3.13  				break;
    3.14  			case 0x070000:				// Line Printer Status Register
    3.15 @@ -408,8 +409,9 @@
    3.16  			case 0x050000:				// Phone status
    3.17  				break;
    3.18  			case 0x060000:				// DMA Count
    3.19 -				// U/OERR- is always inactive (bit set)
    3.20 -				data = (state.dma_count & 0x3fff) | 0x8000;
    3.21 +				// TODO: U/OERR- is always inactive (bit set)... or should it be = DMAEN+?
    3.22 +				// Bit 14 is always unused, so leave it set
    3.23 +				data = (state.dma_count & 0x3fff) | 0xC000;
    3.24  				handled = true;
    3.25  				break;
    3.26  			case 0x070000:				// Line Printer Status Register
    3.27 @@ -758,8 +760,12 @@
    3.28  				state.dma_count = (value & 0x3FFF);
    3.29  				state.idmarw = ((value & 0x4000) == 0x4000);
    3.30  				state.dmaen = ((value & 0x8000) == 0x8000);
    3.31 -				state.dmaenb = state.dmaen;
    3.32  				printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen);
    3.33 +				// This handles the "dummy DMA transfer" mentioned in the docs
    3.34 +				// TODO: access check, peripheral access
    3.35 +				if (!state.idmarw)
    3.36 +					WR32(state.ram, mapAddr(address, false), state.ram_size - 1, 0xDEAD);
    3.37 +				state.dma_count++;
    3.38  				handled = true;
    3.39  				break;
    3.40  			case 0x070000:				// Line Printer Status Register
    3.41 @@ -961,8 +967,12 @@
    3.42  				state.dma_count = (value & 0x3FFF);
    3.43  				state.idmarw = ((value & 0x4000) == 0x4000);
    3.44  				state.dmaen = ((value & 0x8000) == 0x8000);
    3.45 -				state.dmaenb = state.dmaen;
    3.46  				printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen);
    3.47 +				// This handles the "dummy DMA transfer" mentioned in the docs
    3.48 +				// TODO: access check, peripheral access
    3.49 +				if (!state.idmarw)
    3.50 +					WR32(state.ram, mapAddr(address, false), state.ram_size - 1, 0xDEAD);
    3.51 +				state.dma_count++;
    3.52  				handled = true;
    3.53  				break;
    3.54  			case 0x070000:				// Line Printer Status Register
     4.1 --- a/src/state.c	Mon Dec 06 01:43:04 2010 +0000
     4.2 +++ b/src/state.c	Sun Dec 12 23:47:35 2010 +0000
     4.3 @@ -26,9 +26,15 @@
     4.4  	// Load ROMs
     4.5  	FILE *r14c, *r15c;
     4.6  	r14c = fopen("roms/14c.bin", "rb");
     4.7 -//	if (r14c == NULL) FAIL("unable to open roms/14c.bin");
     4.8 +	if (r14c == NULL) {
     4.9 +		fprintf(stderr, "[state] Error loading roms/14c.bin.\n");
    4.10 +		return -3;
    4.11 +	}
    4.12  	r15c = fopen("roms/15c.bin", "rb");
    4.13 -//	if (r15c == NULL) FAIL("unable to open roms/15c.bin");
    4.14 +	if (r15c == NULL) {
    4.15 +		fprintf(stderr, "[state] Error loading roms/15c.bin.\n");
    4.16 +		return -3;
    4.17 +	}
    4.18  
    4.19  	// get ROM file size
    4.20  	fseek(r14c, 0, SEEK_END);
    4.21 @@ -37,8 +43,14 @@
    4.22  	fseek(r15c, 0, SEEK_END);
    4.23  	size_t romlen2 = ftell(r15c);
    4.24  	fseek(r15c, 0, SEEK_SET);
    4.25 -//	if (romlen2 != romlen) FAIL("ROMs are not the same size!");
    4.26 -//	if ((romlen + romlen2) > ROM_SIZE) FAIL("ROMs are too large to fit in memory!");
    4.27 +	if (romlen2 != romlen) {
    4.28 +		fprintf(stderr, "[state] ROMs are not the same size!\n");
    4.29 +		return -3;
    4.30 +	}
    4.31 +	if ((romlen + romlen2) > ROM_SIZE) {
    4.32 +		fprintf(stderr, "[state] ROM files are too large!\n");
    4.33 +		return -3;
    4.34 +	}
    4.35  
    4.36  	// sanity checks completed; load the ROMs!
    4.37  	uint8_t *romdat1, *romdat2;
     5.1 --- a/src/state.h	Mon Dec 06 01:43:04 2010 +0000
     5.2 +++ b/src/state.h	Sun Dec 12 23:47:35 2010 +0000
     5.3 @@ -10,6 +10,16 @@
     5.4  #define ROM_SIZE 32768
     5.5  
     5.6  /**
     5.7 + * State error codes
     5.8 + */
     5.9 +typedef enum {
    5.10 +	STATE_E_OK				= 0,	///< Operation succeeded
    5.11 +	STATE_E_BAD_RAMSIZE		= -1,	///< Bad RAM size specified (not a multiple of 512K, or less than 512K)
    5.12 +	STATE_E_NO_MEMORY		= -2,	///< Out of memory while allocating state variables
    5.13 +	STATE_E_ROM_LOAD_FAIL	= -3	///< Error loading ROMs
    5.14 +} STATE_ERR;
    5.15 +
    5.16 +/**
    5.17   * @brief Emulator state storage
    5.18   *
    5.19   * This structure stores the internal state of the emulator.