src/main.c

changeset 32
a44afcf2354c
parent 30
3190629004b2
child 34
e8ebd433270a
     1.1 --- a/src/main.c	Thu Dec 02 16:37:55 2010 +0000
     1.2 +++ b/src/main.c	Thu Dec 02 17:01:34 2010 +0000
     1.3 @@ -77,9 +77,9 @@
     1.4  		uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03;
     1.5  		if (pagebits != 0) {
     1.6  			if (writing)
     1.7 -				state.map[addr*2] |= 0x60;		// Page written to (dirty)
     1.8 +				state.map[page*2] |= 0x60;		// Page written to (dirty)
     1.9  			else
    1.10 -				state.map[addr*2] |= 0x40;		// Page accessed but not written
    1.11 +				state.map[page*2] |= 0x40;		// Page accessed but not written
    1.12  		}
    1.13  
    1.14  		// Return the address with the new physical page spliced in
    1.15 @@ -139,7 +139,77 @@
    1.16   * m68k memory read/write support functions for Musashi
    1.17   ********************************************************/
    1.18  
    1.19 -// read m68k memory
    1.20 +/**
    1.21 + * @brief	Check memory access permissions for a write operation.
    1.22 + * @note	This used to be a single macro (merged with ACCESS_CHECK_RD), but
    1.23 + * 			gcc throws warnings when you have a return-with-value in a void
    1.24 + * 			function, even if the return-with-value is completely unreachable.
    1.25 + * 			Similarly it doesn't like it if you have a return without a value
    1.26 + * 			in a non-void function, even if it's impossible to ever reach the
    1.27 + * 			return-with-no-value. UGH!
    1.28 + */
    1.29 +#define ACCESS_CHECK_WR() do {									\
    1.30 +		/* MEM_STATUS st; */									\
    1.31 +		switch (checkMemoryAccess(address, true)) {				\
    1.32 +			case MEM_ALLOWED:									\
    1.33 +				/* Access allowed */							\
    1.34 +				break;											\
    1.35 +			case MEM_PAGEFAULT:									\
    1.36 +				/* Page fault */								\
    1.37 +				state.genstat = 0x8FFF;							\
    1.38 +				m68k_pulse_bus_error();							\
    1.39 +				return;											\
    1.40 +			case MEM_UIE:										\
    1.41 +				/* User access to memory above 4MB */			\
    1.42 +				state.genstat = 0x9EFF;							\
    1.43 +				m68k_pulse_bus_error();							\
    1.44 +				return;											\
    1.45 +			case MEM_KERNEL:									\
    1.46 +			case MEM_PAGE_NO_WE:								\
    1.47 +				/* kernel access or page not write enabled */	\
    1.48 +				/* TODO: which regs need setting? */			\
    1.49 +				m68k_pulse_bus_error();							\
    1.50 +				return;											\
    1.51 +		}														\
    1.52 +	} while (false)
    1.53 +
    1.54 +/**
    1.55 + * @brief Check memory access permissions for a read operation.
    1.56 + * @note	This used to be a single macro (merged with ACCESS_CHECK_WR), but
    1.57 + * 			gcc throws warnings when you have a return-with-value in a void
    1.58 + * 			function, even if the return-with-value is completely unreachable.
    1.59 + * 			Similarly it doesn't like it if you have a return without a value
    1.60 + * 			in a non-void function, even if it's impossible to ever reach the
    1.61 + * 			return-with-no-value. UGH!
    1.62 + */
    1.63 +#define ACCESS_CHECK_RD() do {									\
    1.64 +		/* MEM_STATUS st; */									\
    1.65 +		switch (checkMemoryAccess(address, false)) {			\
    1.66 +			case MEM_ALLOWED:									\
    1.67 +				/* Access allowed */							\
    1.68 +				break;											\
    1.69 +			case MEM_PAGEFAULT:									\
    1.70 +				/* Page fault */								\
    1.71 +				state.genstat = 0xCFFF;							\
    1.72 +				m68k_pulse_bus_error();							\
    1.73 +				return 0xFFFFFFFF;								\
    1.74 +			case MEM_UIE:										\
    1.75 +				/* User access to memory above 4MB */			\
    1.76 +				state.genstat = 0xDEFF;							\
    1.77 +				m68k_pulse_bus_error();							\
    1.78 +				return 0xFFFFFFFF;								\
    1.79 +			case MEM_KERNEL:									\
    1.80 +			case MEM_PAGE_NO_WE:								\
    1.81 +				/* kernel access or page not write enabled */	\
    1.82 +				/* TODO: which regs need setting? */			\
    1.83 +				m68k_pulse_bus_error();							\
    1.84 +				return 0xFFFFFFFF;								\
    1.85 +		}														\
    1.86 +	} while (false)
    1.87 +
    1.88 +/**
    1.89 + * @brief Read M68K memory, 32-bit
    1.90 + */
    1.91  uint32_t m68k_read_memory_32(uint32_t address)
    1.92  {
    1.93  	uint32_t data = 0xFFFFFFFF;
    1.94 @@ -148,12 +218,15 @@
    1.95  	if (!state.romlmap)
    1.96  		address |= 0x800000;
    1.97  
    1.98 +	// Check access permissions
    1.99 +	ACCESS_CHECK_RD();
   1.100 +
   1.101  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.102  		// ROM access
   1.103  		data = RD32(state.rom, address, ROM_SIZE - 1);
   1.104  	} else if (address <= (state.ram_size - 1)) {
   1.105 -		// RAM access -- TODO: mapping
   1.106 -		data = RD32(state.ram, address, state.ram_size - 1);
   1.107 +		// RAM access
   1.108 +		data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1);
   1.109  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.110  		// VRAM access
   1.111  		data = RD32(state.vram, address, 0x7FFF);
   1.112 @@ -167,6 +240,9 @@
   1.113  	return data;
   1.114  }
   1.115  
   1.116 +/**
   1.117 + * @brief Read M68K memory, 16-bit
   1.118 + */
   1.119  uint32_t m68k_read_memory_16(uint32_t address)
   1.120  {
   1.121  	uint16_t data = 0xFFFF;
   1.122 @@ -175,12 +251,15 @@
   1.123  	if (!state.romlmap)
   1.124  		address |= 0x800000;
   1.125  
   1.126 +	// Check access permissions
   1.127 +	ACCESS_CHECK_RD();
   1.128 +
   1.129  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.130  		// ROM access
   1.131  		data = RD16(state.rom, address, ROM_SIZE - 1);
   1.132  	} else if (address <= (state.ram_size - 1)) {
   1.133 -		// RAM access -- TODO: mapping
   1.134 -		data = RD16(state.ram, address, state.ram_size - 1);
   1.135 +		// RAM access
   1.136 +		data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1);
   1.137  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.138  		// VRAM access
   1.139  		data = RD16(state.vram, address, 0x7FFF);
   1.140 @@ -195,6 +274,9 @@
   1.141  	return data;
   1.142  }
   1.143  
   1.144 +/**
   1.145 + * @brief Read M68K memory, 8-bit
   1.146 + */
   1.147  uint32_t m68k_read_memory_8(uint32_t address)
   1.148  {
   1.149  	uint8_t data = 0xFF;
   1.150 @@ -203,12 +285,15 @@
   1.151  	if (!state.romlmap)
   1.152  		address |= 0x800000;
   1.153  
   1.154 +	// Check access permissions
   1.155 +	ACCESS_CHECK_RD();
   1.156 +
   1.157  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.158  		// ROM access
   1.159  		data = RD8(state.rom, address, ROM_SIZE - 1);
   1.160  	} else if (address <= (state.ram_size - 1)) {
   1.161 -		// RAM access -- TODO: mapping
   1.162 -		data = RD8(state.ram, address, state.ram_size - 1);
   1.163 +		// RAM access
   1.164 +		data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1);
   1.165  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.166  		// VRAM access
   1.167  		data = RD8(state.vram, address, 0x7FFF);
   1.168 @@ -223,19 +308,25 @@
   1.169  	return data;
   1.170  }
   1.171  
   1.172 -// write m68k memory
   1.173 +/**
   1.174 + * @brief Write M68K memory, 32-bit
   1.175 + */
   1.176  void m68k_write_memory_32(uint32_t address, uint32_t value)
   1.177  {
   1.178  	// If ROMLMAP is set, force system to access ROM
   1.179  	if (!state.romlmap)
   1.180  		address |= 0x800000;
   1.181  
   1.182 +	// Check access permissions
   1.183 +	ACCESS_CHECK_WR();
   1.184 +
   1.185  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.186  		// ROM access
   1.187 -		// TODO: bus error here? can't write to rom!
   1.188 +		// According to HwNote15 (John B. Milton), there is no write protection
   1.189 +		// here. You can write to ROM, but nothing happens.
   1.190  	} else if (address <= (state.ram_size - 1)) {
   1.191 -		// RAM -- TODO: mapping
   1.192 -		WR32(state.ram, address, state.ram_size - 1, value);
   1.193 +		// RAM access
   1.194 +		WR32(state.ram, mapAddr(address, true), state.ram_size - 1, value);
   1.195  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.196  		// VRAM access
   1.197  		WR32(state.vram, address, 0x7fff, value);
   1.198 @@ -250,18 +341,25 @@
   1.199  	}
   1.200  }
   1.201  
   1.202 +/**
   1.203 + * @brief Write M68K memory, 16-bit
   1.204 + */
   1.205  void m68k_write_memory_16(uint32_t address, uint32_t value)
   1.206  {
   1.207  	// If ROMLMAP is set, force system to access ROM
   1.208  	if (!state.romlmap)
   1.209  		address |= 0x800000;
   1.210  
   1.211 +	// Check access permissions
   1.212 +	ACCESS_CHECK_WR();
   1.213 +
   1.214  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.215  		// ROM access
   1.216 -		// TODO: bus error here? can't write to rom!
   1.217 +		// According to HwNote15 (John B. Milton), there is no write protection
   1.218 +		// here. You can write to ROM, but nothing happens.
   1.219  	} else if (address <= (state.ram_size - 1)) {
   1.220 -		// RAM access -- TODO: mapping
   1.221 -		WR16(state.ram, address, state.ram_size - 1, value);
   1.222 +		// RAM access
   1.223 +		WR16(state.ram, mapAddr(address, true), state.ram_size - 1, value);
   1.224  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.225  		// VRAM access
   1.226  		WR16(state.vram, address, 0x7fff, value);
   1.227 @@ -284,18 +382,25 @@
   1.228  	}
   1.229  }
   1.230  
   1.231 +/**
   1.232 + * @brief Write M68K memory, 8-bit
   1.233 + */
   1.234  void m68k_write_memory_8(uint32_t address, uint32_t value)
   1.235  {
   1.236  	// If ROMLMAP is set, force system to access ROM
   1.237  	if (!state.romlmap)
   1.238  		address |= 0x800000;
   1.239  
   1.240 +	// Check access permissions
   1.241 +	ACCESS_CHECK_WR();
   1.242 +
   1.243  	if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
   1.244  		// ROM access
   1.245 -		// TODO: bus error here? can't write to rom!
   1.246 +		// According to HwNote15 (John B. Milton), there is no write protection
   1.247 +		// here. You can write to ROM, but nothing happens.
   1.248  	} else if (address <= (state.ram_size - 1)) {
   1.249 -		// RAM access -- TODO: mapping
   1.250 -		WR8(state.ram, address, state.ram_size - 1, value);
   1.251 +		// RAM access
   1.252 +		WR8(state.ram, mapAddr(address, true), state.ram_size - 1, value);
   1.253  	} else if ((address >= 0x420000) && (address <= 0x427FFF)) {
   1.254  		// VRAM access
   1.255  		WR8(state.vram, address, 0x7fff, value);
   1.256 @@ -354,7 +459,7 @@
   1.257  		printf("Could not find a suitable video mode: %s.\n", SDL_GetError());
   1.258  		exit(EXIT_FAILURE);
   1.259  	}
   1.260 -	printf("Set %dx%d at %d bits-per-pixel mode\n", screen->w, screen->h, screen->format->BitsPerPixel);
   1.261 +	printf("Set %dx%d at %d bits-per-pixel mode\n\n", screen->w, screen->h, screen->format->BitsPerPixel);
   1.262  	SDL_WM_SetCaption("FreeBee 3B1 emulator", "FreeBee");
   1.263  
   1.264  	/***