1.1 diff -r cab49f90c3b9 -r 239bc48590ba src/memory.c 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/src/memory.c Thu Dec 02 23:03:13 2010 +0000 1.4 @@ -0,0 +1,1177 @@ 1.5 +#include <stdio.h> 1.6 +#include <stdlib.h> 1.7 +#include <stdint.h> 1.8 +#include <stdbool.h> 1.9 +#include "musashi/m68k.h" 1.10 +#include "state.h" 1.11 +#include "memory.h" 1.12 + 1.13 +/****************** 1.14 + * Memory mapping 1.15 + ******************/ 1.16 + 1.17 +#define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1])) 1.18 + 1.19 +uint32_t mapAddr(uint32_t addr, bool writing) 1.20 +{ 1.21 + if (addr < 0x400000) { 1.22 + // RAM access. Check against the Map RAM 1.23 + // Start by getting the original page address 1.24 + uint16_t page = (addr >> 12) & 0x3FF; 1.25 + 1.26 + // Look it up in the map RAM and get the physical page address 1.27 + uint32_t new_page_addr = MAPRAM(page) & 0x3FF; 1.28 + 1.29 + // Update the Page Status bits 1.30 + uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03; 1.31 + if (pagebits != 0) { 1.32 + if (writing) 1.33 + state.map[page*2] |= 0x60; // Page written to (dirty) 1.34 + else 1.35 + state.map[page*2] |= 0x40; // Page accessed but not written 1.36 + } 1.37 + 1.38 + // Return the address with the new physical page spliced in 1.39 + return (new_page_addr << 12) + (addr & 0xFFF); 1.40 + } else { 1.41 + // I/O, VRAM or MapRAM space; no mapping is performed or required 1.42 + // TODO: assert here? 1.43 + return addr; 1.44 + } 1.45 +} 1.46 + 1.47 +MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing) 1.48 +{ 1.49 + // Are we in Supervisor mode? 1.50 + if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000) 1.51 + // Yes. We can do anything we like. 1.52 + return MEM_ALLOWED; 1.53 + 1.54 + // If we're here, then we must be in User mode. 1.55 + // Check that the user didn't access memory outside of the RAM area 1.56 + if (addr >= 0x400000) 1.57 + return MEM_UIE; 1.58 + 1.59 + // This leaves us with Page Fault checking. Get the page bits for this page. 1.60 + uint16_t page = (addr >> 12) & 0x3FF; 1.61 + uint8_t pagebits = (MAPRAM(page) >> 13) & 0x07; 1.62 + 1.63 + // Check page is present 1.64 + if ((pagebits & 0x03) == 0) 1.65 + return MEM_PAGEFAULT; 1.66 + 1.67 + // User attempt to access the kernel 1.68 + // A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode 1.69 + if (((addr >> 19) & 0x0F) == 0) 1.70 + return MEM_KERNEL; 1.71 + 1.72 + // Check page is write enabled 1.73 + if ((pagebits & 0x04) == 0) 1.74 + return MEM_PAGE_NO_WE; 1.75 + 1.76 + // Page access allowed. 1.77 + return MEM_ALLOWED; 1.78 +} 1.79 + 1.80 +#undef MAPRAM 1.81 + 1.82 + 1.83 +/******************************************************** 1.84 + * m68k memory read/write support functions for Musashi 1.85 + ********************************************************/ 1.86 + 1.87 +/** 1.88 + * @brief Check memory access permissions for a write operation. 1.89 + * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but 1.90 + * gcc throws warnings when you have a return-with-value in a void 1.91 + * function, even if the return-with-value is completely unreachable. 1.92 + * Similarly it doesn't like it if you have a return without a value 1.93 + * in a non-void function, even if it's impossible to ever reach the 1.94 + * return-with-no-value. UGH! 1.95 + */ 1.96 +#define ACCESS_CHECK_WR(address, bits) do { \ 1.97 + bool fault = false; \ 1.98 + /* MEM_STATUS st; */ \ 1.99 + switch (checkMemoryAccess(address, true)) { \ 1.100 + case MEM_ALLOWED: \ 1.101 + /* Access allowed */ \ 1.102 + break; \ 1.103 + case MEM_PAGEFAULT: \ 1.104 + /* Page fault */ \ 1.105 + state.genstat = 0x8FFF; \ 1.106 + fault = true; \ 1.107 + break; \ 1.108 + case MEM_UIE: \ 1.109 + /* User access to memory above 4MB */ \ 1.110 + state.genstat = 0x9EFF; \ 1.111 + fault = true; \ 1.112 + break; \ 1.113 + case MEM_KERNEL: \ 1.114 + case MEM_PAGE_NO_WE: \ 1.115 + /* kernel access or page not write enabled */ \ 1.116 + /* TODO: which regs need setting? */ \ 1.117 + fault = true; \ 1.118 + break; \ 1.119 + } \ 1.120 + \ 1.121 + if (fault) { \ 1.122 + if (bits >= 16) \ 1.123 + state.bsr0 = 0x7F00; \ 1.124 + else \ 1.125 + state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 1.126 + state.bsr0 |= (address >> 16); \ 1.127 + state.bsr1 = address & 0xffff; \ 1.128 + printf("ERR: BusError WR\n"); \ 1.129 + m68k_pulse_bus_error(); \ 1.130 + return; \ 1.131 + } \ 1.132 + } while (false) 1.133 + 1.134 +/** 1.135 + * @brief Check memory access permissions for a read operation. 1.136 + * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but 1.137 + * gcc throws warnings when you have a return-with-value in a void 1.138 + * function, even if the return-with-value is completely unreachable. 1.139 + * Similarly it doesn't like it if you have a return without a value 1.140 + * in a non-void function, even if it's impossible to ever reach the 1.141 + * return-with-no-value. UGH! 1.142 + */ 1.143 +#define ACCESS_CHECK_RD(address, bits) do { \ 1.144 + bool fault = false; \ 1.145 + /* MEM_STATUS st; */ \ 1.146 + switch (checkMemoryAccess(address, false)) { \ 1.147 + case MEM_ALLOWED: \ 1.148 + /* Access allowed */ \ 1.149 + break; \ 1.150 + case MEM_PAGEFAULT: \ 1.151 + /* Page fault */ \ 1.152 + state.genstat = 0x8FFF; \ 1.153 + fault = true; \ 1.154 + break; \ 1.155 + case MEM_UIE: \ 1.156 + /* User access to memory above 4MB */ \ 1.157 + state.genstat = 0x9EFF; \ 1.158 + fault = true; \ 1.159 + break; \ 1.160 + case MEM_KERNEL: \ 1.161 + case MEM_PAGE_NO_WE: \ 1.162 + /* kernel access or page not write enabled */ \ 1.163 + /* TODO: which regs need setting? */ \ 1.164 + fault = true; \ 1.165 + break; \ 1.166 + } \ 1.167 + \ 1.168 + if (fault) { \ 1.169 + if (bits >= 16) \ 1.170 + state.bsr0 = 0x7F00; \ 1.171 + else \ 1.172 + state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \ 1.173 + state.bsr0 |= (address >> 16); \ 1.174 + state.bsr1 = address & 0xffff; \ 1.175 + printf("ERR: BusError RD\n"); \ 1.176 + m68k_pulse_bus_error(); \ 1.177 + return 0xFFFFFFFF; \ 1.178 + } \ 1.179 + } while (false) 1.180 + 1.181 +// Logging macros 1.182 +#define LOG_NOT_HANDLED_R(bits) \ 1.183 + do { \ 1.184 + if (!handled) \ 1.185 + printf("unhandled read%02d, addr=0x%08X\n", bits, address); \ 1.186 + } while (0); 1.187 + 1.188 +#define LOG_NOT_HANDLED_W(bits) \ 1.189 + do { \ 1.190 + if (!handled) \ 1.191 + printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); \ 1.192 + } while (0); 1.193 + 1.194 +/** 1.195 + * @brief Read M68K memory, 32-bit 1.196 + */ 1.197 +uint32_t m68k_read_memory_32(uint32_t address) 1.198 +{ 1.199 + uint32_t data = 0xFFFFFFFF; 1.200 + bool handled = false; 1.201 + 1.202 + // If ROMLMAP is set, force system to access ROM 1.203 + if (!state.romlmap) 1.204 + address |= 0x800000; 1.205 + 1.206 + // Check access permissions 1.207 + ACCESS_CHECK_RD(address, 32); 1.208 + 1.209 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.210 + // ROM access 1.211 + data = RD32(state.rom, address, ROM_SIZE - 1); 1.212 + handled = true; 1.213 + } else if (address <= (state.ram_size - 1)) { 1.214 + // RAM access 1.215 + data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1); 1.216 + handled = true; 1.217 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.218 + // I/O register space, zone A 1.219 + switch (address & 0x0F0000) { 1.220 + case 0x000000: // Map RAM access 1.221 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address); 1.222 + data = RD32(state.map, address, 0x7FF); 1.223 + handled = true; 1.224 + break; 1.225 + case 0x010000: // General Status Register 1.226 + data = ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 1.227 + handled = true; 1.228 + break; 1.229 + case 0x020000: // Video RAM 1.230 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address); 1.231 + data = RD32(state.vram, address, 0x7FFF); 1.232 + handled = true; 1.233 + break; 1.234 + case 0x030000: // Bus Status Register 0 1.235 + data = ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0; 1.236 + handled = true; 1.237 + break; 1.238 + case 0x040000: // Bus Status Register 1 1.239 + data = ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1; 1.240 + handled = true; 1.241 + break; 1.242 + case 0x050000: // Phone status 1.243 + break; 1.244 + case 0x060000: // DMA Count 1.245 + break; 1.246 + case 0x070000: // Line Printer Status Register 1.247 + break; 1.248 + case 0x080000: // Real Time Clock 1.249 + break; 1.250 + case 0x090000: // Phone registers 1.251 + switch (address & 0x0FF000) { 1.252 + case 0x090000: // Handset relay 1.253 + case 0x098000: 1.254 + break; 1.255 + case 0x091000: // Line select 2 1.256 + case 0x099000: 1.257 + break; 1.258 + case 0x092000: // Hook relay 1 1.259 + case 0x09A000: 1.260 + break; 1.261 + case 0x093000: // Hook relay 2 1.262 + case 0x09B000: 1.263 + break; 1.264 + case 0x094000: // Line 1 hold 1.265 + case 0x09C000: 1.266 + break; 1.267 + case 0x095000: // Line 2 hold 1.268 + case 0x09D000: 1.269 + break; 1.270 + case 0x096000: // Line 1 A-lead 1.271 + case 0x09E000: 1.272 + break; 1.273 + case 0x097000: // Line 2 A-lead 1.274 + case 0x09F000: 1.275 + break; 1.276 + } 1.277 + break; 1.278 + case 0x0A0000: // Miscellaneous Control Register 1.279 + break; 1.280 + case 0x0B0000: // TM/DIALWR 1.281 + break; 1.282 + case 0x0C0000: // CSR 1.283 + break; 1.284 + case 0x0D0000: // DMA Address Register 1.285 + break; 1.286 + case 0x0E0000: // Disk Control Register 1.287 + break; 1.288 + case 0x0F0000: // Line Printer Data Register 1.289 + break; 1.290 + } 1.291 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.292 + // I/O register space, zone B 1.293 + switch (address & 0xF00000) { 1.294 + case 0xC00000: // Expansion slots 1.295 + case 0xD00000: 1.296 + switch (address & 0xFC0000) { 1.297 + case 0xC00000: // Expansion slot 0 1.298 + case 0xC40000: // Expansion slot 1 1.299 + case 0xC80000: // Expansion slot 2 1.300 + case 0xCC0000: // Expansion slot 3 1.301 + case 0xD00000: // Expansion slot 4 1.302 + case 0xD40000: // Expansion slot 5 1.303 + case 0xD80000: // Expansion slot 6 1.304 + case 0xDC0000: // Expansion slot 7 1.305 + fprintf(stderr, "NOTE: RD32 from expansion card space, addr=0x%08X\n", address); 1.306 + break; 1.307 + } 1.308 + break; 1.309 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.310 + case 0xF00000: 1.311 + switch (address & 0x070000) { 1.312 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.313 + break; 1.314 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.315 + break; 1.316 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.317 + break; 1.318 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.319 + break; 1.320 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.321 + switch (address & 0x077000) { 1.322 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.323 + break; 1.324 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.325 + break; 1.326 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.327 + break; 1.328 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.329 + break; 1.330 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.331 + break; 1.332 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.333 + break; 1.334 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.335 + break; 1.336 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.337 + break; 1.338 + } 1.339 + break; 1.340 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.341 + break; 1.342 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.343 + switch (address & 0x07F000) { 1.344 + default: 1.345 + break; 1.346 + } 1.347 + break; 1.348 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.349 + break; 1.350 + } 1.351 + } 1.352 + } 1.353 + 1.354 + LOG_NOT_HANDLED_R(32); 1.355 + return data; 1.356 +} 1.357 + 1.358 +/** 1.359 + * @brief Read M68K memory, 16-bit 1.360 + */ 1.361 +uint32_t m68k_read_memory_16(uint32_t address) 1.362 +{ 1.363 + uint16_t data = 0xFFFF; 1.364 + bool handled = false; 1.365 + 1.366 + // If ROMLMAP is set, force system to access ROM 1.367 + if (!state.romlmap) 1.368 + address |= 0x800000; 1.369 + 1.370 + // Check access permissions 1.371 + ACCESS_CHECK_RD(address, 16); 1.372 + 1.373 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.374 + // ROM access 1.375 + data = RD16(state.rom, address, ROM_SIZE - 1); 1.376 + handled = true; 1.377 + } else if (address <= (state.ram_size - 1)) { 1.378 + // RAM access 1.379 + data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1); 1.380 + handled = true; 1.381 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.382 + // I/O register space, zone A 1.383 + switch (address & 0x0F0000) { 1.384 + case 0x000000: // Map RAM access 1.385 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address); 1.386 + data = RD16(state.map, address, 0x7FF); 1.387 + handled = true; 1.388 + break; 1.389 + case 0x010000: // General Status Register 1.390 + data = state.genstat; 1.391 + handled = true; 1.392 + break; 1.393 + case 0x020000: // Video RAM 1.394 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address); 1.395 + data = RD16(state.vram, address, 0x7FFF); 1.396 + handled = true; 1.397 + break; 1.398 + case 0x030000: // Bus Status Register 0 1.399 + data = state.bsr0; 1.400 + handled = true; 1.401 + break; 1.402 + case 0x040000: // Bus Status Register 1 1.403 + data = state.bsr1; 1.404 + handled = true; 1.405 + break; 1.406 + case 0x050000: // Phone status 1.407 + break; 1.408 + case 0x060000: // DMA Count 1.409 + break; 1.410 + case 0x070000: // Line Printer Status Register 1.411 + break; 1.412 + case 0x080000: // Real Time Clock 1.413 + break; 1.414 + case 0x090000: // Phone registers 1.415 + switch (address & 0x0FF000) { 1.416 + case 0x090000: // Handset relay 1.417 + case 0x098000: 1.418 + break; 1.419 + case 0x091000: // Line select 2 1.420 + case 0x099000: 1.421 + break; 1.422 + case 0x092000: // Hook relay 1 1.423 + case 0x09A000: 1.424 + break; 1.425 + case 0x093000: // Hook relay 2 1.426 + case 0x09B000: 1.427 + break; 1.428 + case 0x094000: // Line 1 hold 1.429 + case 0x09C000: 1.430 + break; 1.431 + case 0x095000: // Line 2 hold 1.432 + case 0x09D000: 1.433 + break; 1.434 + case 0x096000: // Line 1 A-lead 1.435 + case 0x09E000: 1.436 + break; 1.437 + case 0x097000: // Line 2 A-lead 1.438 + case 0x09F000: 1.439 + break; 1.440 + } 1.441 + break; 1.442 + case 0x0A0000: // Miscellaneous Control Register 1.443 + break; 1.444 + case 0x0B0000: // TM/DIALWR 1.445 + break; 1.446 + case 0x0C0000: // CSR 1.447 + break; 1.448 + case 0x0D0000: // DMA Address Register 1.449 + break; 1.450 + case 0x0E0000: // Disk Control Register 1.451 + break; 1.452 + case 0x0F0000: // Line Printer Data Register 1.453 + break; 1.454 + } 1.455 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.456 + // I/O register space, zone B 1.457 + switch (address & 0xF00000) { 1.458 + case 0xC00000: // Expansion slots 1.459 + case 0xD00000: 1.460 + switch (address & 0xFC0000) { 1.461 + case 0xC00000: // Expansion slot 0 1.462 + case 0xC40000: // Expansion slot 1 1.463 + case 0xC80000: // Expansion slot 2 1.464 + case 0xCC0000: // Expansion slot 3 1.465 + case 0xD00000: // Expansion slot 4 1.466 + case 0xD40000: // Expansion slot 5 1.467 + case 0xD80000: // Expansion slot 6 1.468 + case 0xDC0000: // Expansion slot 7 1.469 + fprintf(stderr, "NOTE: RD16 from expansion card space, addr=0x%08X\n", address); 1.470 + break; 1.471 + } 1.472 + break; 1.473 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.474 + case 0xF00000: 1.475 + switch (address & 0x070000) { 1.476 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.477 + break; 1.478 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.479 + break; 1.480 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.481 + break; 1.482 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.483 + break; 1.484 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.485 + switch (address & 0x077000) { 1.486 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.487 + break; 1.488 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.489 + break; 1.490 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.491 + break; 1.492 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.493 + break; 1.494 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.495 + break; 1.496 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.497 + break; 1.498 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.499 + break; 1.500 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.501 + break; 1.502 + } 1.503 + break; 1.504 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.505 + break; 1.506 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.507 + switch (address & 0x07F000) { 1.508 + default: 1.509 + break; 1.510 + } 1.511 + break; 1.512 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.513 + break; 1.514 + } 1.515 + } 1.516 + } 1.517 + 1.518 + LOG_NOT_HANDLED_R(32); 1.519 + return data; 1.520 +} 1.521 + 1.522 +/** 1.523 + * @brief Read M68K memory, 8-bit 1.524 + */ 1.525 +uint32_t m68k_read_memory_8(uint32_t address) 1.526 +{ 1.527 + uint8_t data = 0xFF; 1.528 + bool handled = false; 1.529 + 1.530 + // If ROMLMAP is set, force system to access ROM 1.531 + if (!state.romlmap) 1.532 + address |= 0x800000; 1.533 + 1.534 + // Check access permissions 1.535 + ACCESS_CHECK_RD(address, 8); 1.536 + 1.537 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.538 + // ROM access 1.539 + data = RD8(state.rom, address, ROM_SIZE - 1); 1.540 + handled = true; 1.541 + } else if (address <= (state.ram_size - 1)) { 1.542 + // RAM access 1.543 + data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1); 1.544 + handled = true; 1.545 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.546 + // I/O register space, zone A 1.547 + switch (address & 0x0F0000) { 1.548 + case 0x000000: // Map RAM access 1.549 + if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address); 1.550 + data = RD8(state.map, address, 0x7FF); 1.551 + handled = true; 1.552 + break; 1.553 + case 0x010000: // General Status Register 1.554 + if ((address & 1) == 0) 1.555 + data = (state.genstat >> 8) & 0xff; 1.556 + else 1.557 + data = (state.genstat) & 0xff; 1.558 + handled = true; 1.559 + break; 1.560 + case 0x020000: // Video RAM 1.561 + if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address); 1.562 + data = RD8(state.vram, address, 0x7FFF); 1.563 + handled = true; 1.564 + break; 1.565 + case 0x030000: // Bus Status Register 0 1.566 + if ((address & 1) == 0) 1.567 + data = (state.bsr0 >> 8) & 0xff; 1.568 + else 1.569 + data = (state.bsr0) & 0xff; 1.570 + handled = true; 1.571 + break; 1.572 + case 0x040000: // Bus Status Register 1 1.573 + if ((address & 1) == 0) 1.574 + data = (state.bsr1 >> 8) & 0xff; 1.575 + else 1.576 + data = (state.bsr1) & 0xff; 1.577 + handled = true; 1.578 + break; 1.579 + case 0x050000: // Phone status 1.580 + break; 1.581 + case 0x060000: // DMA Count 1.582 + break; 1.583 + case 0x070000: // Line Printer Status Register 1.584 + break; 1.585 + case 0x080000: // Real Time Clock 1.586 + break; 1.587 + case 0x090000: // Phone registers 1.588 + switch (address & 0x0FF000) { 1.589 + case 0x090000: // Handset relay 1.590 + case 0x098000: 1.591 + break; 1.592 + case 0x091000: // Line select 2 1.593 + case 0x099000: 1.594 + break; 1.595 + case 0x092000: // Hook relay 1 1.596 + case 0x09A000: 1.597 + break; 1.598 + case 0x093000: // Hook relay 2 1.599 + case 0x09B000: 1.600 + break; 1.601 + case 0x094000: // Line 1 hold 1.602 + case 0x09C000: 1.603 + break; 1.604 + case 0x095000: // Line 2 hold 1.605 + case 0x09D000: 1.606 + break; 1.607 + case 0x096000: // Line 1 A-lead 1.608 + case 0x09E000: 1.609 + break; 1.610 + case 0x097000: // Line 2 A-lead 1.611 + case 0x09F000: 1.612 + break; 1.613 + } 1.614 + break; 1.615 + case 0x0A0000: // Miscellaneous Control Register 1.616 + break; 1.617 + case 0x0B0000: // TM/DIALWR 1.618 + break; 1.619 + case 0x0C0000: // CSR 1.620 + break; 1.621 + case 0x0D0000: // DMA Address Register 1.622 + break; 1.623 + case 0x0E0000: // Disk Control Register 1.624 + break; 1.625 + case 0x0F0000: // Line Printer Data Register 1.626 + break; 1.627 + } 1.628 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.629 + // I/O register space, zone B 1.630 + switch (address & 0xF00000) { 1.631 + case 0xC00000: // Expansion slots 1.632 + case 0xD00000: 1.633 + switch (address & 0xFC0000) { 1.634 + case 0xC00000: // Expansion slot 0 1.635 + case 0xC40000: // Expansion slot 1 1.636 + case 0xC80000: // Expansion slot 2 1.637 + case 0xCC0000: // Expansion slot 3 1.638 + case 0xD00000: // Expansion slot 4 1.639 + case 0xD40000: // Expansion slot 5 1.640 + case 0xD80000: // Expansion slot 6 1.641 + case 0xDC0000: // Expansion slot 7 1.642 + fprintf(stderr, "NOTE: RD8 from expansion card space, addr=0x%08X\n", address); 1.643 + break; 1.644 + } 1.645 + break; 1.646 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.647 + case 0xF00000: 1.648 + switch (address & 0x070000) { 1.649 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.650 + break; 1.651 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.652 + break; 1.653 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.654 + break; 1.655 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.656 + break; 1.657 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.658 + switch (address & 0x077000) { 1.659 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.660 + break; 1.661 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.662 + break; 1.663 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.664 + break; 1.665 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.666 + break; 1.667 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.668 + break; 1.669 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.670 + break; 1.671 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.672 + break; 1.673 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.674 + break; 1.675 + } 1.676 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.677 + break; 1.678 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.679 + switch (address & 0x07F000) { 1.680 + default: 1.681 + break; 1.682 + } 1.683 + break; 1.684 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.685 + break; 1.686 + } 1.687 + } 1.688 + } 1.689 + 1.690 + LOG_NOT_HANDLED_R(8); 1.691 + 1.692 + return data; 1.693 +} 1.694 + 1.695 +/** 1.696 + * @brief Write M68K memory, 32-bit 1.697 + */ 1.698 +void m68k_write_memory_32(uint32_t address, uint32_t value) 1.699 +{ 1.700 + bool handled = false; 1.701 + 1.702 + // If ROMLMAP is set, force system to access ROM 1.703 + if (!state.romlmap) 1.704 + address |= 0x800000; 1.705 + 1.706 + // Check access permissions 1.707 + ACCESS_CHECK_WR(address, 32); 1.708 + 1.709 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.710 + // ROM access 1.711 + handled = true; 1.712 + } else if (address <= (state.ram_size - 1)) { 1.713 + // RAM access 1.714 + WR32(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.715 + handled = true; 1.716 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.717 + // I/O register space, zone A 1.718 + switch (address & 0x0F0000) { 1.719 + case 0x000000: // Map RAM access 1.720 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 1.721 + WR32(state.map, address, 0x7FF, value); 1.722 + handled = true; 1.723 + break; 1.724 + case 0x010000: // General Status Register 1.725 + state.genstat = (value & 0xffff); 1.726 + handled = true; 1.727 + break; 1.728 + case 0x020000: // Video RAM 1.729 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X, data=0x%08X\n", address, value); 1.730 + WR32(state.vram, address, 0x7FFF, value); 1.731 + handled = true; 1.732 + break; 1.733 + case 0x030000: // Bus Status Register 0 1.734 + break; 1.735 + case 0x040000: // Bus Status Register 1 1.736 + break; 1.737 + case 0x050000: // Phone status 1.738 + break; 1.739 + case 0x060000: // DMA Count 1.740 + break; 1.741 + case 0x070000: // Line Printer Status Register 1.742 + break; 1.743 + case 0x080000: // Real Time Clock 1.744 + break; 1.745 + case 0x090000: // Phone registers 1.746 + switch (address & 0x0FF000) { 1.747 + case 0x090000: // Handset relay 1.748 + case 0x098000: 1.749 + break; 1.750 + case 0x091000: // Line select 2 1.751 + case 0x099000: 1.752 + break; 1.753 + case 0x092000: // Hook relay 1 1.754 + case 0x09A000: 1.755 + break; 1.756 + case 0x093000: // Hook relay 2 1.757 + case 0x09B000: 1.758 + break; 1.759 + case 0x094000: // Line 1 hold 1.760 + case 0x09C000: 1.761 + break; 1.762 + case 0x095000: // Line 2 hold 1.763 + case 0x09D000: 1.764 + break; 1.765 + case 0x096000: // Line 1 A-lead 1.766 + case 0x09E000: 1.767 + break; 1.768 + case 0x097000: // Line 2 A-lead 1.769 + case 0x09F000: 1.770 + break; 1.771 + } 1.772 + break; 1.773 + case 0x0A0000: // Miscellaneous Control Register 1.774 + break; 1.775 + case 0x0B0000: // TM/DIALWR 1.776 + break; 1.777 + case 0x0C0000: // CSR 1.778 + break; 1.779 + case 0x0D0000: // DMA Address Register 1.780 + break; 1.781 + case 0x0E0000: // Disk Control Register 1.782 + break; 1.783 + case 0x0F0000: // Line Printer Data Register 1.784 + break; 1.785 + } 1.786 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.787 + // I/O register space, zone B 1.788 + switch (address & 0xF00000) { 1.789 + case 0xC00000: // Expansion slots 1.790 + case 0xD00000: 1.791 + switch (address & 0xFC0000) { 1.792 + case 0xC00000: // Expansion slot 0 1.793 + case 0xC40000: // Expansion slot 1 1.794 + case 0xC80000: // Expansion slot 2 1.795 + case 0xCC0000: // Expansion slot 3 1.796 + case 0xD00000: // Expansion slot 4 1.797 + case 0xD40000: // Expansion slot 5 1.798 + case 0xD80000: // Expansion slot 6 1.799 + case 0xDC0000: // Expansion slot 7 1.800 + fprintf(stderr, "NOTE: WR32 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 1.801 + handled = true; 1.802 + break; 1.803 + } 1.804 + break; 1.805 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.806 + case 0xF00000: 1.807 + switch (address & 0x070000) { 1.808 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.809 + break; 1.810 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.811 + break; 1.812 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.813 + break; 1.814 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.815 + break; 1.816 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.817 + switch (address & 0x077000) { 1.818 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.819 + break; 1.820 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.821 + break; 1.822 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.823 + break; 1.824 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.825 + state.romlmap = ((value & 0x8000) == 0x8000); 1.826 + break; 1.827 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.828 + break; 1.829 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.830 + break; 1.831 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.832 + break; 1.833 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.834 + break; 1.835 + } 1.836 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.837 + break; 1.838 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.839 + switch (address & 0x07F000) { 1.840 + default: 1.841 + break; 1.842 + } 1.843 + break; 1.844 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.845 + break; 1.846 + } 1.847 + } 1.848 + } 1.849 + 1.850 + LOG_NOT_HANDLED_W(32); 1.851 +} 1.852 + 1.853 +/** 1.854 + * @brief Write M68K memory, 16-bit 1.855 + */ 1.856 +void m68k_write_memory_16(uint32_t address, uint32_t value) 1.857 +{ 1.858 + bool handled = false; 1.859 + 1.860 + // If ROMLMAP is set, force system to access ROM 1.861 + if (!state.romlmap) 1.862 + address |= 0x800000; 1.863 + 1.864 + // Check access permissions 1.865 + ACCESS_CHECK_WR(address, 16); 1.866 + 1.867 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.868 + // ROM access 1.869 + handled = true; 1.870 + } else if (address <= (state.ram_size - 1)) { 1.871 + // RAM access 1.872 + WR16(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.873 + handled = true; 1.874 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.875 + // I/O register space, zone A 1.876 + switch (address & 0x0F0000) { 1.877 + case 0x000000: // Map RAM access 1.878 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.879 + WR16(state.map, address, 0x7FF, value); 1.880 + handled = true; 1.881 + break; 1.882 + case 0x010000: // General Status Register (read only) 1.883 + handled = true; 1.884 + break; 1.885 + case 0x020000: // Video RAM 1.886 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value); 1.887 + WR16(state.vram, address, 0x7FFF, value); 1.888 + handled = true; 1.889 + break; 1.890 + case 0x030000: // Bus Status Register 0 (read only) 1.891 + handled = true; 1.892 + break; 1.893 + case 0x040000: // Bus Status Register 1 (read only) 1.894 + handled = true; 1.895 + break; 1.896 + case 0x050000: // Phone status 1.897 + break; 1.898 + case 0x060000: // DMA Count 1.899 + break; 1.900 + case 0x070000: // Line Printer Status Register 1.901 + break; 1.902 + case 0x080000: // Real Time Clock 1.903 + break; 1.904 + case 0x090000: // Phone registers 1.905 + switch (address & 0x0FF000) { 1.906 + case 0x090000: // Handset relay 1.907 + case 0x098000: 1.908 + break; 1.909 + case 0x091000: // Line select 2 1.910 + case 0x099000: 1.911 + break; 1.912 + case 0x092000: // Hook relay 1 1.913 + case 0x09A000: 1.914 + break; 1.915 + case 0x093000: // Hook relay 2 1.916 + case 0x09B000: 1.917 + break; 1.918 + case 0x094000: // Line 1 hold 1.919 + case 0x09C000: 1.920 + break; 1.921 + case 0x095000: // Line 2 hold 1.922 + case 0x09D000: 1.923 + break; 1.924 + case 0x096000: // Line 1 A-lead 1.925 + case 0x09E000: 1.926 + break; 1.927 + case 0x097000: // Line 2 A-lead 1.928 + case 0x09F000: 1.929 + break; 1.930 + } 1.931 + break; 1.932 + case 0x0A0000: // Miscellaneous Control Register 1.933 + break; 1.934 + case 0x0B0000: // TM/DIALWR 1.935 + break; 1.936 + case 0x0C0000: // CSR 1.937 + break; 1.938 + case 0x0D0000: // DMA Address Register 1.939 + break; 1.940 + case 0x0E0000: // Disk Control Register 1.941 + break; 1.942 + case 0x0F0000: // Line Printer Data Register 1.943 + break; 1.944 + } 1.945 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.946 + // I/O register space, zone B 1.947 + switch (address & 0xF00000) { 1.948 + case 0xC00000: // Expansion slots 1.949 + case 0xD00000: 1.950 + switch (address & 0xFC0000) { 1.951 + case 0xC00000: // Expansion slot 0 1.952 + case 0xC40000: // Expansion slot 1 1.953 + case 0xC80000: // Expansion slot 2 1.954 + case 0xCC0000: // Expansion slot 3 1.955 + case 0xD00000: // Expansion slot 4 1.956 + case 0xD40000: // Expansion slot 5 1.957 + case 0xD80000: // Expansion slot 6 1.958 + case 0xDC0000: // Expansion slot 7 1.959 + fprintf(stderr, "NOTE: WR16 to expansion card space, addr=0x%08X, data=0x%04X\n", address, value); 1.960 + break; 1.961 + } 1.962 + break; 1.963 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.964 + case 0xF00000: 1.965 + switch (address & 0x070000) { 1.966 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.967 + break; 1.968 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.969 + break; 1.970 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.971 + break; 1.972 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.973 + break; 1.974 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.975 + switch (address & 0x077000) { 1.976 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.977 + break; 1.978 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.979 + break; 1.980 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.981 + break; 1.982 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.983 + state.romlmap = ((value & 0x8000) == 0x8000); 1.984 + handled = true; 1.985 + break; 1.986 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.987 + break; 1.988 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.989 + break; 1.990 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.991 + break; 1.992 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.993 + break; 1.994 + } 1.995 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.996 + break; 1.997 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.998 + switch (address & 0x07F000) { 1.999 + default: 1.1000 + break; 1.1001 + } 1.1002 + break; 1.1003 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.1004 + break; 1.1005 + } 1.1006 + } 1.1007 + } 1.1008 + 1.1009 + LOG_NOT_HANDLED_W(16); 1.1010 +} 1.1011 + 1.1012 +/** 1.1013 + * @brief Write M68K memory, 8-bit 1.1014 + */ 1.1015 +void m68k_write_memory_8(uint32_t address, uint32_t value) 1.1016 +{ 1.1017 + bool handled = false; 1.1018 + 1.1019 + // If ROMLMAP is set, force system to access ROM 1.1020 + if (!state.romlmap) 1.1021 + address |= 0x800000; 1.1022 + 1.1023 + // Check access permissions 1.1024 + ACCESS_CHECK_WR(address, 8); 1.1025 + 1.1026 + if ((address >= 0x800000) && (address <= 0xBFFFFF)) { 1.1027 + // ROM access (read only!) 1.1028 + handled = true; 1.1029 + } else if (address <= (state.ram_size - 1)) { 1.1030 + // RAM access 1.1031 + WR8(state.ram, mapAddr(address, false), state.ram_size - 1, value); 1.1032 + handled = true; 1.1033 + } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) { 1.1034 + // I/O register space, zone A 1.1035 + switch (address & 0x0F0000) { 1.1036 + case 0x000000: // Map RAM access 1.1037 + if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=%08X, data=%02X\n", address, value); 1.1038 + WR8(state.map, address, 0x7FF, value); 1.1039 + handled = true; 1.1040 + break; 1.1041 + case 0x010000: // General Status Register 1.1042 + handled = true; 1.1043 + break; 1.1044 + case 0x020000: // Video RAM 1.1045 + if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=%08X\n, data=0x%02X", address, value); 1.1046 + WR8(state.vram, address, 0x7FFF, value); 1.1047 + handled = true; 1.1048 + break; 1.1049 + case 0x030000: // Bus Status Register 0 1.1050 + handled = true; 1.1051 + break; 1.1052 + case 0x040000: // Bus Status Register 1 1.1053 + handled = true; 1.1054 + break; 1.1055 + case 0x050000: // Phone status 1.1056 + break; 1.1057 + case 0x060000: // DMA Count 1.1058 + break; 1.1059 + case 0x070000: // Line Printer Status Register 1.1060 + break; 1.1061 + case 0x080000: // Real Time Clock 1.1062 + break; 1.1063 + case 0x090000: // Phone registers 1.1064 + switch (address & 0x0FF000) { 1.1065 + case 0x090000: // Handset relay 1.1066 + case 0x098000: 1.1067 + break; 1.1068 + case 0x091000: // Line select 2 1.1069 + case 0x099000: 1.1070 + break; 1.1071 + case 0x092000: // Hook relay 1 1.1072 + case 0x09A000: 1.1073 + break; 1.1074 + case 0x093000: // Hook relay 2 1.1075 + case 0x09B000: 1.1076 + break; 1.1077 + case 0x094000: // Line 1 hold 1.1078 + case 0x09C000: 1.1079 + break; 1.1080 + case 0x095000: // Line 2 hold 1.1081 + case 0x09D000: 1.1082 + break; 1.1083 + case 0x096000: // Line 1 A-lead 1.1084 + case 0x09E000: 1.1085 + break; 1.1086 + case 0x097000: // Line 2 A-lead 1.1087 + case 0x09F000: 1.1088 + break; 1.1089 + } 1.1090 + break; 1.1091 + case 0x0A0000: // Miscellaneous Control Register 1.1092 + break; 1.1093 + case 0x0B0000: // TM/DIALWR 1.1094 + break; 1.1095 + case 0x0C0000: // CSR 1.1096 + break; 1.1097 + case 0x0D0000: // DMA Address Register 1.1098 + break; 1.1099 + case 0x0E0000: // Disk Control Register 1.1100 + break; 1.1101 + case 0x0F0000: // Line Printer Data Register 1.1102 + break; 1.1103 + } 1.1104 + } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) { 1.1105 + // I/O register space, zone B 1.1106 + switch (address & 0xF00000) { 1.1107 + case 0xC00000: // Expansion slots 1.1108 + case 0xD00000: 1.1109 + switch (address & 0xFC0000) { 1.1110 + case 0xC00000: // Expansion slot 0 1.1111 + case 0xC40000: // Expansion slot 1 1.1112 + case 0xC80000: // Expansion slot 2 1.1113 + case 0xCC0000: // Expansion slot 3 1.1114 + case 0xD00000: // Expansion slot 4 1.1115 + case 0xD40000: // Expansion slot 5 1.1116 + case 0xD80000: // Expansion slot 6 1.1117 + case 0xDC0000: // Expansion slot 7 1.1118 + fprintf(stderr, "NOTE: WR8 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value); 1.1119 + break; 1.1120 + } 1.1121 + break; 1.1122 + case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.1123 + case 0xF00000: 1.1124 + switch (address & 0x070000) { 1.1125 + case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.1126 + break; 1.1127 + case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.1128 + break; 1.1129 + case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.1130 + break; 1.1131 + case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.1132 + break; 1.1133 + case 0x040000: // [ef][4c]xxxx ==> General Control Register 1.1134 + switch (address & 0x077000) { 1.1135 + case 0x040000: // [ef][4c][08]xxx ==> EE 1.1136 + break; 1.1137 + case 0x041000: // [ef][4c][19]xxx ==> P1E 1.1138 + break; 1.1139 + case 0x042000: // [ef][4c][2A]xxx ==> BP 1.1140 + break; 1.1141 + case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP 1.1142 + if ((address & 1) == 0) 1.1143 + state.romlmap = ((value & 0x80) == 0x80); 1.1144 + handled = true; 1.1145 + break; 1.1146 + case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM 1.1147 + break; 1.1148 + case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM 1.1149 + break; 1.1150 + case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT 1.1151 + break; 1.1152 + case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video 1.1153 + break; 1.1154 + } 1.1155 + case 0x050000: // [ef][5d]xxxx ==> 8274 1.1156 + break; 1.1157 + case 0x060000: // [ef][6e]xxxx ==> Control regs 1.1158 + switch (address & 0x07F000) { 1.1159 + default: 1.1160 + break; 1.1161 + } 1.1162 + break; 1.1163 + case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller 1.1164 + break; 1.1165 + default: 1.1166 + fprintf(stderr, "NOTE: WR8 to undefined E/F-block space, addr=0x%08X, data=0x%08X\n", address, value); 1.1167 + break; 1.1168 + } 1.1169 + } 1.1170 + } 1.1171 + 1.1172 + LOG_NOT_HANDLED_W(8); 1.1173 +} 1.1174 + 1.1175 + 1.1176 +// for the disassembler 1.1177 +uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); } 1.1178 +uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); } 1.1179 +uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); } 1.1180 + 1.1181 +