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