Mon, 06 Dec 2010 01:26:37 +0000
disc dma seems to work, but still no boot ;(
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <stdbool.h>
5 #include "musashi/m68k.h"
6 #include "state.h"
7 #include "memory.h"
9 /******************
10 * Memory mapping
11 ******************/
13 #define MAPRAM(addr) (((uint16_t)state.map[addr*2] << 8) + ((uint16_t)state.map[(addr*2)+1]))
15 uint32_t mapAddr(uint32_t addr, bool writing)
16 {
17 if (addr < 0x400000) {
18 // RAM access. Check against the Map RAM
19 // Start by getting the original page address
20 uint16_t page = (addr >> 12) & 0x3FF;
22 // Look it up in the map RAM and get the physical page address
23 uint32_t new_page_addr = MAPRAM(page) & 0x3FF;
25 // Update the Page Status bits
26 uint8_t pagebits = (MAPRAM(page) >> 13) & 0x03;
27 if (pagebits != 0) {
28 if (writing)
29 state.map[page*2] |= 0x60; // Page written to (dirty)
30 else
31 state.map[page*2] |= 0x40; // Page accessed but not written
32 }
34 // Return the address with the new physical page spliced in
35 return (new_page_addr << 12) + (addr & 0xFFF);
36 } else {
37 // I/O, VRAM or MapRAM space; no mapping is performed or required
38 // TODO: assert here?
39 return addr;
40 }
41 }
43 MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing)
44 {
45 // Are we in Supervisor mode?
46 if (m68k_get_reg(NULL, M68K_REG_SR) & 0x2000)
47 // Yes. We can do anything we like.
48 return MEM_ALLOWED;
50 // If we're here, then we must be in User mode.
51 // Check that the user didn't access memory outside of the RAM area
52 if (addr >= 0x400000)
53 return MEM_UIE;
55 // This leaves us with Page Fault checking. Get the page bits for this page.
56 uint16_t page = (addr >> 12) & 0x3FF;
57 uint8_t pagebits = (MAPRAM(page) >> 13) & 0x07;
59 // Check page is present
60 if ((pagebits & 0x03) == 0)
61 return MEM_PAGEFAULT;
63 // User attempt to access the kernel
64 // A19, A20, A21, A22 low (kernel access): RAM addr before paging; not in Supervisor mode
65 if (((addr >> 19) & 0x0F) == 0)
66 return MEM_KERNEL;
68 // Check page is write enabled
69 if ((pagebits & 0x04) == 0)
70 return MEM_PAGE_NO_WE;
72 // Page access allowed.
73 return MEM_ALLOWED;
74 }
76 #undef MAPRAM
79 /********************************************************
80 * m68k memory read/write support functions for Musashi
81 ********************************************************/
83 /**
84 * @brief Check memory access permissions for a write operation.
85 * @note This used to be a single macro (merged with ACCESS_CHECK_RD), but
86 * gcc throws warnings when you have a return-with-value in a void
87 * function, even if the return-with-value is completely unreachable.
88 * Similarly it doesn't like it if you have a return without a value
89 * in a non-void function, even if it's impossible to ever reach the
90 * return-with-no-value. UGH!
91 */
92 #define ACCESS_CHECK_WR(address, bits) do { \
93 bool fault = false; \
94 /* MEM_STATUS st; */ \
95 switch (checkMemoryAccess(address, true)) { \
96 case MEM_ALLOWED: \
97 /* Access allowed */ \
98 break; \
99 case MEM_PAGEFAULT: \
100 /* Page fault */ \
101 state.genstat = 0x8BFF | (state.pie ? 0x0400 : 0); \
102 fault = true; \
103 break; \
104 case MEM_UIE: \
105 /* User access to memory above 4MB */ \
106 state.genstat = 0x9AFF | (state.pie ? 0x0400 : 0); \
107 fault = true; \
108 break; \
109 case MEM_KERNEL: \
110 case MEM_PAGE_NO_WE: \
111 /* kernel access or page not write enabled */ \
112 /* TODO: which regs need setting? */ \
113 fault = true; \
114 break; \
115 } \
116 \
117 if (fault) { \
118 if (bits >= 16) \
119 state.bsr0 = 0x7F00; \
120 else \
121 state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \
122 state.bsr0 |= (address >> 16); \
123 state.bsr1 = address & 0xffff; \
124 printf("ERR: BusError WR\n"); \
125 m68k_pulse_bus_error(); \
126 return; \
127 } \
128 } while (false)
130 /**
131 * @brief Check memory access permissions for a read operation.
132 * @note This used to be a single macro (merged with ACCESS_CHECK_WR), but
133 * gcc throws warnings when you have a return-with-value in a void
134 * function, even if the return-with-value is completely unreachable.
135 * Similarly it doesn't like it if you have a return without a value
136 * in a non-void function, even if it's impossible to ever reach the
137 * return-with-no-value. UGH!
138 */
139 #define ACCESS_CHECK_RD(address, bits) do { \
140 bool fault = false; \
141 /* MEM_STATUS st; */ \
142 switch (checkMemoryAccess(address, false)) { \
143 case MEM_ALLOWED: \
144 /* Access allowed */ \
145 break; \
146 case MEM_PAGEFAULT: \
147 /* Page fault */ \
148 state.genstat = 0xCBFF | (state.pie ? 0x0400 : 0); \
149 fault = true; \
150 break; \
151 case MEM_UIE: \
152 /* User access to memory above 4MB */ \
153 state.genstat = 0xDAFF | (state.pie ? 0x0400 : 0); \
154 fault = true; \
155 break; \
156 case MEM_KERNEL: \
157 case MEM_PAGE_NO_WE: \
158 /* kernel access or page not write enabled */ \
159 /* TODO: which regs need setting? */ \
160 fault = true; \
161 break; \
162 } \
163 \
164 if (fault) { \
165 if (bits >= 16) \
166 state.bsr0 = 0x7F00; \
167 else \
168 state.bsr0 = (address & 1) ? 0x7D00 : 0x7E00; \
169 state.bsr0 |= (address >> 16); \
170 state.bsr1 = address & 0xffff; \
171 printf("ERR: BusError RD\n"); \
172 m68k_pulse_bus_error(); \
173 return 0xFFFFFFFF; \
174 } \
175 } while (false)
177 // Logging macros
178 #define LOG_NOT_HANDLED_R(bits) \
179 do { \
180 if (!handled) \
181 printf("unhandled read%02d, addr=0x%08X\n", bits, address); \
182 } while (0);
184 #define LOG_NOT_HANDLED_W(bits) \
185 do { \
186 if (!handled) \
187 printf("unhandled write%02d, addr=0x%08X, data=0x%08X\n", bits, address, value); \
188 } while (0);
190 /**
191 * @brief Read M68K memory, 32-bit
192 */
193 uint32_t m68k_read_memory_32(uint32_t address)
194 {
195 uint32_t data = 0xFFFFFFFF;
196 bool handled = false;
198 // If ROMLMAP is set, force system to access ROM
199 if (!state.romlmap)
200 address |= 0x800000;
202 // Check access permissions
203 ACCESS_CHECK_RD(address, 32);
205 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
206 // ROM access
207 data = RD32(state.rom, address, ROM_SIZE - 1);
208 handled = true;
209 } else if (address <= (state.ram_size - 1)) {
210 // RAM access
211 data = RD32(state.ram, mapAddr(address, false), state.ram_size - 1);
212 handled = true;
213 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
214 // I/O register space, zone A
215 switch (address & 0x0F0000) {
216 case 0x000000: // Map RAM access
217 if (address > 0x4007FF) fprintf(stderr, "NOTE: RD32 from MapRAM mirror, addr=0x%08X\n", address);
218 data = RD32(state.map, address, 0x7FF);
219 handled = true;
220 break;
221 case 0x010000: // General Status Register
222 data = ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat;
223 handled = true;
224 break;
225 case 0x020000: // Video RAM
226 if (address > 0x427FFF) fprintf(stderr, "NOTE: RD32 from VideoRAM mirror, addr=0x%08X\n", address);
227 data = RD32(state.vram, address, 0x7FFF);
228 handled = true;
229 break;
230 case 0x030000: // Bus Status Register 0
231 data = ((uint32_t)state.bsr0 << 16) + (uint32_t)state.bsr0;
232 handled = true;
233 break;
234 case 0x040000: // Bus Status Register 1
235 data = ((uint32_t)state.bsr1 << 16) + (uint32_t)state.bsr1;
236 handled = true;
237 break;
238 case 0x050000: // Phone status
239 break;
240 case 0x060000: // DMA Count
241 // U/OERR- is always inactive (bit set)
242 data = (state.dma_count & 0x3fff) | 0x8000;
243 handled = true;
244 break;
245 case 0x070000: // Line Printer Status Register
246 data = 0x00120012; // no parity error, no line printer error, no irqs from FDD or HDD
247 data |= (state.fdc_ctx.irql) ? 0x00080008 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this
248 break;
249 case 0x080000: // Real Time Clock
250 break;
251 case 0x090000: // Phone registers
252 switch (address & 0x0FF000) {
253 case 0x090000: // Handset relay
254 case 0x098000:
255 break;
256 case 0x091000: // Line select 2
257 case 0x099000:
258 break;
259 case 0x092000: // Hook relay 1
260 case 0x09A000:
261 break;
262 case 0x093000: // Hook relay 2
263 case 0x09B000:
264 break;
265 case 0x094000: // Line 1 hold
266 case 0x09C000:
267 break;
268 case 0x095000: // Line 2 hold
269 case 0x09D000:
270 break;
271 case 0x096000: // Line 1 A-lead
272 case 0x09E000:
273 break;
274 case 0x097000: // Line 2 A-lead
275 case 0x09F000:
276 break;
277 }
278 break;
279 case 0x0A0000: // Miscellaneous Control Register -- write only!
280 handled = true;
281 break;
282 case 0x0B0000: // TM/DIALWR
283 break;
284 case 0x0C0000: // Clear Status Register -- write only!
285 handled = true;
286 break;
287 case 0x0D0000: // DMA Address Register
288 break;
289 case 0x0E0000: // Disk Control Register
290 break;
291 case 0x0F0000: // Line Printer Data Register
292 break;
293 }
294 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
295 // I/O register space, zone B
296 switch (address & 0xF00000) {
297 case 0xC00000: // Expansion slots
298 case 0xD00000:
299 switch (address & 0xFC0000) {
300 case 0xC00000: // Expansion slot 0
301 case 0xC40000: // Expansion slot 1
302 case 0xC80000: // Expansion slot 2
303 case 0xCC0000: // Expansion slot 3
304 case 0xD00000: // Expansion slot 4
305 case 0xD40000: // Expansion slot 5
306 case 0xD80000: // Expansion slot 6
307 case 0xDC0000: // Expansion slot 7
308 fprintf(stderr, "NOTE: RD32 from expansion card space, addr=0x%08X\n", address);
309 break;
310 }
311 break;
312 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
313 case 0xF00000:
314 switch (address & 0x070000) {
315 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
316 break;
317 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
318 data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
319 printf("WD279X: rd32 %02X ==> %02X\n", (address >> 1) & 3, data);
320 handled = true;
321 break;
322 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
323 break;
324 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
325 break;
326 case 0x040000: // [ef][4c]xxxx ==> General Control Register
327 switch (address & 0x077000) {
328 case 0x040000: // [ef][4c][08]xxx ==> EE
329 case 0x041000: // [ef][4c][19]xxx ==> PIE
330 case 0x042000: // [ef][4c][2A]xxx ==> BP
331 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
332 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
333 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
334 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
335 // All write-only registers... TODO: bus error?
336 handled = true;
337 break;
338 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video [FIXME: not in TRM]
339 break;
340 }
341 break;
342 case 0x050000: // [ef][5d]xxxx ==> 8274
343 break;
344 case 0x060000: // [ef][6e]xxxx ==> Control regs
345 switch (address & 0x07F000) {
346 default:
347 break;
348 }
349 break;
350 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
351 break;
352 }
353 }
354 }
356 LOG_NOT_HANDLED_R(32);
357 return data;
358 }
360 /**
361 * @brief Read M68K memory, 16-bit
362 */
363 uint32_t m68k_read_memory_16(uint32_t address)
364 {
365 uint16_t data = 0xFFFF;
366 bool handled = false;
368 // If ROMLMAP is set, force system to access ROM
369 if (!state.romlmap)
370 address |= 0x800000;
372 // Check access permissions
373 ACCESS_CHECK_RD(address, 16);
375 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
376 // ROM access
377 data = RD16(state.rom, address, ROM_SIZE - 1);
378 handled = true;
379 } else if (address <= (state.ram_size - 1)) {
380 // RAM access
381 data = RD16(state.ram, mapAddr(address, false), state.ram_size - 1);
382 handled = true;
383 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
384 // I/O register space, zone A
385 switch (address & 0x0F0000) {
386 case 0x000000: // Map RAM access
387 if (address > 0x4007FF) fprintf(stderr, "NOTE: RD16 from MapRAM mirror, addr=0x%08X\n", address);
388 data = RD16(state.map, address, 0x7FF);
389 handled = true;
390 break;
391 case 0x010000: // General Status Register
392 data = state.genstat;
393 handled = true;
394 break;
395 case 0x020000: // Video RAM
396 if (address > 0x427FFF) fprintf(stderr, "NOTE: RD16 from VideoRAM mirror, addr=0x%08X\n", address);
397 data = RD16(state.vram, address, 0x7FFF);
398 handled = true;
399 break;
400 case 0x030000: // Bus Status Register 0
401 data = state.bsr0;
402 handled = true;
403 break;
404 case 0x040000: // Bus Status Register 1
405 data = state.bsr1;
406 handled = true;
407 break;
408 case 0x050000: // Phone status
409 break;
410 case 0x060000: // DMA Count
411 // U/OERR- is always inactive (bit set)
412 data = (state.dma_count & 0x3fff) | 0x8000;
413 handled = true;
414 break;
415 case 0x070000: // Line Printer Status Register
416 data = 0x0012; // no parity error, no line printer error, no irqs from FDD or HDD
417 data |= (state.fdc_ctx.irql) ? 0x0008 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this
418 break;
419 case 0x080000: // Real Time Clock
420 break;
421 case 0x090000: // Phone registers
422 switch (address & 0x0FF000) {
423 case 0x090000: // Handset relay
424 case 0x098000:
425 break;
426 case 0x091000: // Line select 2
427 case 0x099000:
428 break;
429 case 0x092000: // Hook relay 1
430 case 0x09A000:
431 break;
432 case 0x093000: // Hook relay 2
433 case 0x09B000:
434 break;
435 case 0x094000: // Line 1 hold
436 case 0x09C000:
437 break;
438 case 0x095000: // Line 2 hold
439 case 0x09D000:
440 break;
441 case 0x096000: // Line 1 A-lead
442 case 0x09E000:
443 break;
444 case 0x097000: // Line 2 A-lead
445 case 0x09F000:
446 break;
447 }
448 break;
449 case 0x0A0000: // Miscellaneous Control Register -- write only!
450 handled = true;
451 break;
452 case 0x0B0000: // TM/DIALWR
453 break;
454 case 0x0C0000: // Clear Status Register -- write only!
455 handled = true;
456 break;
457 case 0x0D0000: // DMA Address Register
458 break;
459 case 0x0E0000: // Disk Control Register
460 break;
461 case 0x0F0000: // Line Printer Data Register
462 break;
463 }
464 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
465 // I/O register space, zone B
466 switch (address & 0xF00000) {
467 case 0xC00000: // Expansion slots
468 case 0xD00000:
469 switch (address & 0xFC0000) {
470 case 0xC00000: // Expansion slot 0
471 case 0xC40000: // Expansion slot 1
472 case 0xC80000: // Expansion slot 2
473 case 0xCC0000: // Expansion slot 3
474 case 0xD00000: // Expansion slot 4
475 case 0xD40000: // Expansion slot 5
476 case 0xD80000: // Expansion slot 6
477 case 0xDC0000: // Expansion slot 7
478 fprintf(stderr, "NOTE: RD16 from expansion card space, addr=0x%08X\n", address);
479 break;
480 }
481 break;
482 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
483 case 0xF00000:
484 switch (address & 0x070000) {
485 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
486 break;
487 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
488 data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
489 printf("WD279X: rd16 %02X ==> %02X\n", (address >> 1) & 3, data);
490 handled = true;
491 break;
492 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
493 break;
494 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
495 break;
496 case 0x040000: // [ef][4c]xxxx ==> General Control Register
497 switch (address & 0x077000) {
498 case 0x040000: // [ef][4c][08]xxx ==> EE
499 case 0x041000: // [ef][4c][19]xxx ==> PIE
500 case 0x042000: // [ef][4c][2A]xxx ==> BP
501 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
502 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
503 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
504 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
505 // All write-only registers... TODO: bus error?
506 handled = true;
507 break;
508 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video
509 break;
510 }
511 break;
512 case 0x050000: // [ef][5d]xxxx ==> 8274
513 break;
514 case 0x060000: // [ef][6e]xxxx ==> Control regs
515 switch (address & 0x07F000) {
516 default:
517 break;
518 }
519 break;
520 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
521 break;
522 }
523 }
524 }
526 LOG_NOT_HANDLED_R(16);
527 return data;
528 }
530 /**
531 * @brief Read M68K memory, 8-bit
532 */
533 uint32_t m68k_read_memory_8(uint32_t address)
534 {
535 uint8_t data = 0xFF;
536 bool handled = false;
538 // If ROMLMAP is set, force system to access ROM
539 if (!state.romlmap)
540 address |= 0x800000;
542 // Check access permissions
543 ACCESS_CHECK_RD(address, 8);
545 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
546 // ROM access
547 data = RD8(state.rom, address, ROM_SIZE - 1);
548 handled = true;
549 } else if (address <= (state.ram_size - 1)) {
550 // RAM access
551 data = RD8(state.ram, mapAddr(address, false), state.ram_size - 1);
552 handled = true;
553 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
554 // I/O register space, zone A
555 switch (address & 0x0F0000) {
556 case 0x000000: // Map RAM access
557 if (address > 0x4007FF) fprintf(stderr, "NOTE: RD8 from MapRAM mirror, addr=0x%08X\n", address);
558 data = RD8(state.map, address, 0x7FF);
559 handled = true;
560 break;
561 case 0x010000: // General Status Register
562 if ((address & 1) == 0)
563 data = (state.genstat >> 8) & 0xff;
564 else
565 data = (state.genstat) & 0xff;
566 handled = true;
567 break;
568 case 0x020000: // Video RAM
569 if (address > 0x427FFF) fprintf(stderr, "NOTE: RD8 from VideoRAM mirror, addr=0x%08X\n", address);
570 data = RD8(state.vram, address, 0x7FFF);
571 handled = true;
572 break;
573 case 0x030000: // Bus Status Register 0
574 if ((address & 1) == 0)
575 data = (state.bsr0 >> 8) & 0xff;
576 else
577 data = (state.bsr0) & 0xff;
578 handled = true;
579 break;
580 case 0x040000: // Bus Status Register 1
581 if ((address & 1) == 0)
582 data = (state.bsr1 >> 8) & 0xff;
583 else
584 data = (state.bsr1) & 0xff;
585 handled = true;
586 break;
587 case 0x050000: // Phone status
588 break;
589 case 0x060000: // DMA Count
590 // TODO: how to handle this in 8bit mode?
591 break;
592 case 0x070000: // Line Printer Status Register
593 printf("\tLPSR RD8 fdc irql=%d, irqe=%d\n", state.fdc_ctx.irql, state.fdc_ctx.irqe);
594 if (address & 1) {
595 data = 0x12; // no parity error, no line printer error, no irqs from FDD or HDD
596 data |= (state.fdc_ctx.irql) ? 0x08 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this
597 } else {
598 data = 0;
599 }
600 break;
601 case 0x080000: // Real Time Clock
602 break;
603 case 0x090000: // Phone registers
604 switch (address & 0x0FF000) {
605 case 0x090000: // Handset relay
606 case 0x098000:
607 break;
608 case 0x091000: // Line select 2
609 case 0x099000:
610 break;
611 case 0x092000: // Hook relay 1
612 case 0x09A000:
613 break;
614 case 0x093000: // Hook relay 2
615 case 0x09B000:
616 break;
617 case 0x094000: // Line 1 hold
618 case 0x09C000:
619 break;
620 case 0x095000: // Line 2 hold
621 case 0x09D000:
622 break;
623 case 0x096000: // Line 1 A-lead
624 case 0x09E000:
625 break;
626 case 0x097000: // Line 2 A-lead
627 case 0x09F000:
628 break;
629 }
630 break;
631 case 0x0A0000: // Miscellaneous Control Register -- write only!
632 handled = true;
633 break;
634 case 0x0B0000: // TM/DIALWR
635 break;
636 case 0x0C0000: // Clear Status Register -- write only!
637 handled = true;
638 break;
639 case 0x0D0000: // DMA Address Register
640 break;
641 case 0x0E0000: // Disk Control Register
642 break;
643 case 0x0F0000: // Line Printer Data Register
644 break;
645 }
646 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
647 // I/O register space, zone B
648 switch (address & 0xF00000) {
649 case 0xC00000: // Expansion slots
650 case 0xD00000:
651 switch (address & 0xFC0000) {
652 case 0xC00000: // Expansion slot 0
653 case 0xC40000: // Expansion slot 1
654 case 0xC80000: // Expansion slot 2
655 case 0xCC0000: // Expansion slot 3
656 case 0xD00000: // Expansion slot 4
657 case 0xD40000: // Expansion slot 5
658 case 0xD80000: // Expansion slot 6
659 case 0xDC0000: // Expansion slot 7
660 fprintf(stderr, "NOTE: RD8 from expansion card space, addr=0x%08X\n", address);
661 break;
662 }
663 break;
664 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
665 case 0xF00000:
666 switch (address & 0x070000) {
667 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
668 break;
669 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
670 data = wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3);
671 printf("WD279X: rd8 %02X ==> %02X\n", (address >> 1) & 3, data);
672 handled = true;
673 break;
674 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
675 break;
676 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
677 break;
678 case 0x040000: // [ef][4c]xxxx ==> General Control Register
679 switch (address & 0x077000) {
680 case 0x040000: // [ef][4c][08]xxx ==> EE
681 case 0x041000: // [ef][4c][19]xxx ==> PIE
682 case 0x042000: // [ef][4c][2A]xxx ==> BP
683 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
684 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
685 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
686 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
687 // All write-only registers... TODO: bus error?
688 handled = true;
689 break;
690 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video
691 break;
692 }
693 case 0x050000: // [ef][5d]xxxx ==> 8274
694 break;
695 case 0x060000: // [ef][6e]xxxx ==> Control regs
696 switch (address & 0x07F000) {
697 default:
698 break;
699 }
700 break;
701 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
702 break;
703 }
704 }
705 }
707 LOG_NOT_HANDLED_R(8);
709 return data;
710 }
712 /**
713 * @brief Write M68K memory, 32-bit
714 */
715 void m68k_write_memory_32(uint32_t address, uint32_t value)
716 {
717 bool handled = false;
719 // If ROMLMAP is set, force system to access ROM
720 if (!state.romlmap)
721 address |= 0x800000;
723 // Check access permissions
724 ACCESS_CHECK_WR(address, 32);
726 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
727 // ROM access
728 handled = true;
729 } else if (address <= (state.ram_size - 1)) {
730 // RAM access
731 WR32(state.ram, mapAddr(address, false), state.ram_size - 1, value);
732 handled = true;
733 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
734 // I/O register space, zone A
735 switch (address & 0x0F0000) {
736 case 0x000000: // Map RAM access
737 if (address > 0x4007FF) fprintf(stderr, "NOTE: WR32 to MapRAM mirror, addr=0x%08X, data=0x%08X\n", address, value);
738 WR32(state.map, address, 0x7FF, value);
739 handled = true;
740 break;
741 case 0x010000: // General Status Register
742 state.genstat = (value & 0xffff);
743 handled = true;
744 break;
745 case 0x020000: // Video RAM
746 if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X, data=0x%08X\n", address, value);
747 WR32(state.vram, address, 0x7FFF, value);
748 handled = true;
749 break;
750 case 0x030000: // Bus Status Register 0
751 break;
752 case 0x040000: // Bus Status Register 1
753 break;
754 case 0x050000: // Phone status
755 break;
756 case 0x060000: // DMA Count
757 printf("WR32 dmacount %08X\n", value);
758 state.dma_count = (value & 0x3FFF);
759 state.idmarw = ((value & 0x4000) == 0x4000);
760 state.dmaen = ((value & 0x8000) == 0x8000);
761 state.dmaenb = state.dmaen;
762 printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen);
763 handled = true;
764 break;
765 case 0x070000: // Line Printer Status Register
766 break;
767 case 0x080000: // Real Time Clock
768 break;
769 case 0x090000: // Phone registers
770 switch (address & 0x0FF000) {
771 case 0x090000: // Handset relay
772 case 0x098000:
773 break;
774 case 0x091000: // Line select 2
775 case 0x099000:
776 break;
777 case 0x092000: // Hook relay 1
778 case 0x09A000:
779 break;
780 case 0x093000: // Hook relay 2
781 case 0x09B000:
782 break;
783 case 0x094000: // Line 1 hold
784 case 0x09C000:
785 break;
786 case 0x095000: // Line 2 hold
787 case 0x09D000:
788 break;
789 case 0x096000: // Line 1 A-lead
790 case 0x09E000:
791 break;
792 case 0x097000: // Line 2 A-lead
793 case 0x09F000:
794 break;
795 }
796 break;
797 case 0x0A0000: // Miscellaneous Control Register
798 // TODO: handle the ctrl bits properly
799 // TODO: &0x8000 --> dismiss 60hz intr
800 state.dma_reading = (value & 0x4000);
801 state.leds = (~value & 0xF00) >> 8;
802 printf("LEDs: %s %s %s %s\n",
803 (state.leds & 8) ? "R" : "-",
804 (state.leds & 4) ? "G" : "-",
805 (state.leds & 2) ? "Y" : "-",
806 (state.leds & 1) ? "R" : "-");
807 handled = true;
808 break;
809 case 0x0B0000: // TM/DIALWR
810 break;
811 case 0x0C0000: // Clear Status Register
812 state.genstat = 0xFFFF;
813 state.bsr0 = 0xFFFF;
814 state.bsr1 = 0xFFFF;
815 handled = true;
816 break;
817 case 0x0D0000: // DMA Address Register
818 if (address & 0x004000) {
819 // A14 high -- set most significant bits
820 state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
821 } else {
822 // A14 low -- set least significant bits
823 state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
824 }
825 printf("WR DMA_ADDR, now %08X\n", state.dma_address);
826 handled = true;
827 break;
828 case 0x0E0000: // Disk Control Register
829 // B7 = FDD controller reset
830 if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
831 // B6 = drive 0 select -- TODO
832 // B5 = motor enable -- TODO
833 // B4 = HDD controller reset -- TODO
834 // B3 = HDD0 select -- TODO
835 // B2,1,0 = HDD0 head select
836 handled = true;
837 break;
838 case 0x0F0000: // Line Printer Data Register
839 break;
840 }
841 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
842 // I/O register space, zone B
843 switch (address & 0xF00000) {
844 case 0xC00000: // Expansion slots
845 case 0xD00000:
846 switch (address & 0xFC0000) {
847 case 0xC00000: // Expansion slot 0
848 case 0xC40000: // Expansion slot 1
849 case 0xC80000: // Expansion slot 2
850 case 0xCC0000: // Expansion slot 3
851 case 0xD00000: // Expansion slot 4
852 case 0xD40000: // Expansion slot 5
853 case 0xD80000: // Expansion slot 6
854 case 0xDC0000: // Expansion slot 7
855 fprintf(stderr, "NOTE: WR32 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value);
856 handled = true;
857 break;
858 }
859 break;
860 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
861 case 0xF00000:
862 switch (address & 0x070000) {
863 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
864 break;
865 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
866 printf("WD279X: wr32 %02X ==> %02X\n", (address >> 1) & 3, value);
867 wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
868 handled = true;
869 break;
870 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
871 break;
872 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
873 break;
874 case 0x040000: // [ef][4c]xxxx ==> General Control Register
875 switch (address & 0x077000) {
876 case 0x040000: // [ef][4c][08]xxx ==> EE
877 break;
878 case 0x041000: // [ef][4c][19]xxx ==> PIE
879 state.pie = ((value & 0x8000) == 0x8000);
880 handled = true;
881 break;
882 case 0x042000: // [ef][4c][2A]xxx ==> BP
883 break;
884 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
885 state.romlmap = ((value & 0x8000) == 0x8000);
886 handled = true;
887 break;
888 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
889 break;
890 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
891 break;
892 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
893 break;
894 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video
895 break;
896 }
897 case 0x050000: // [ef][5d]xxxx ==> 8274
898 break;
899 case 0x060000: // [ef][6e]xxxx ==> Control regs
900 switch (address & 0x07F000) {
901 default:
902 break;
903 }
904 break;
905 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
906 break;
907 }
908 }
909 }
911 LOG_NOT_HANDLED_W(32);
912 }
914 /**
915 * @brief Write M68K memory, 16-bit
916 */
917 void m68k_write_memory_16(uint32_t address, uint32_t value)
918 {
919 bool handled = false;
921 // If ROMLMAP is set, force system to access ROM
922 if (!state.romlmap)
923 address |= 0x800000;
925 // Check access permissions
926 ACCESS_CHECK_WR(address, 16);
928 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
929 // ROM access
930 handled = true;
931 } else if (address <= (state.ram_size - 1)) {
932 // RAM access
933 WR16(state.ram, mapAddr(address, false), state.ram_size - 1, value);
934 handled = true;
935 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
936 // I/O register space, zone A
937 switch (address & 0x0F0000) {
938 case 0x000000: // Map RAM access
939 if (address > 0x4007FF) fprintf(stderr, "NOTE: WR16 to MapRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
940 WR16(state.map, address, 0x7FF, value);
941 handled = true;
942 break;
943 case 0x010000: // General Status Register (read only)
944 handled = true;
945 break;
946 case 0x020000: // Video RAM
947 if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
948 WR16(state.vram, address, 0x7FFF, value);
949 handled = true;
950 break;
951 case 0x030000: // Bus Status Register 0 (read only)
952 handled = true;
953 break;
954 case 0x040000: // Bus Status Register 1 (read only)
955 handled = true;
956 break;
957 case 0x050000: // Phone status
958 break;
959 case 0x060000: // DMA Count
960 printf("WR16 dmacount %08X\n", value);
961 state.dma_count = (value & 0x3FFF);
962 state.idmarw = ((value & 0x4000) == 0x4000);
963 state.dmaen = ((value & 0x8000) == 0x8000);
964 state.dmaenb = state.dmaen;
965 printf("\tcount %04X, idmarw %d, dmaen %d\n", state.dma_count, state.idmarw, state.dmaen);
966 handled = true;
967 break;
968 case 0x070000: // Line Printer Status Register
969 break;
970 case 0x080000: // Real Time Clock
971 break;
972 case 0x090000: // Phone registers
973 switch (address & 0x0FF000) {
974 case 0x090000: // Handset relay
975 case 0x098000:
976 break;
977 case 0x091000: // Line select 2
978 case 0x099000:
979 break;
980 case 0x092000: // Hook relay 1
981 case 0x09A000:
982 break;
983 case 0x093000: // Hook relay 2
984 case 0x09B000:
985 break;
986 case 0x094000: // Line 1 hold
987 case 0x09C000:
988 break;
989 case 0x095000: // Line 2 hold
990 case 0x09D000:
991 break;
992 case 0x096000: // Line 1 A-lead
993 case 0x09E000:
994 break;
995 case 0x097000: // Line 2 A-lead
996 case 0x09F000:
997 break;
998 }
999 break;
1000 case 0x0A0000: // Miscellaneous Control Register
1001 // TODO: handle the ctrl bits properly
1002 // TODO: &0x8000 --> dismiss 60hz intr
1003 state.dma_reading = (value & 0x4000);
1004 state.leds = (~value & 0xF00) >> 8;
1005 printf("LEDs: %s %s %s %s\n",
1006 (state.leds & 8) ? "R" : "-",
1007 (state.leds & 4) ? "G" : "-",
1008 (state.leds & 2) ? "Y" : "-",
1009 (state.leds & 1) ? "R" : "-");
1010 handled = true;
1011 break;
1012 case 0x0B0000: // TM/DIALWR
1013 break;
1014 case 0x0C0000: // Clear Status Register
1015 state.genstat = 0xFFFF;
1016 state.bsr0 = 0xFFFF;
1017 state.bsr1 = 0xFFFF;
1018 handled = true;
1019 break;
1020 case 0x0D0000: // DMA Address Register
1021 if (address & 0x004000) {
1022 // A14 high -- set most significant bits
1023 state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
1024 } else {
1025 // A14 low -- set least significant bits
1026 state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
1027 }
1028 printf("WR DMA_ADDR, now %08X\n", state.dma_address);
1029 handled = true;
1030 break;
1031 case 0x0E0000: // Disk Control Register
1032 // B7 = FDD controller reset
1033 if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
1034 // B6 = drive 0 select -- TODO
1035 // B5 = motor enable -- TODO
1036 // B4 = HDD controller reset -- TODO
1037 // B3 = HDD0 select -- TODO
1038 // B2,1,0 = HDD0 head select
1039 handled = true;
1040 break;
1041 case 0x0F0000: // Line Printer Data Register
1042 break;
1043 }
1044 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
1045 // I/O register space, zone B
1046 switch (address & 0xF00000) {
1047 case 0xC00000: // Expansion slots
1048 case 0xD00000:
1049 switch (address & 0xFC0000) {
1050 case 0xC00000: // Expansion slot 0
1051 case 0xC40000: // Expansion slot 1
1052 case 0xC80000: // Expansion slot 2
1053 case 0xCC0000: // Expansion slot 3
1054 case 0xD00000: // Expansion slot 4
1055 case 0xD40000: // Expansion slot 5
1056 case 0xD80000: // Expansion slot 6
1057 case 0xDC0000: // Expansion slot 7
1058 fprintf(stderr, "NOTE: WR16 to expansion card space, addr=0x%08X, data=0x%04X\n", address, value);
1059 break;
1060 }
1061 break;
1062 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
1063 case 0xF00000:
1064 switch (address & 0x070000) {
1065 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
1066 break;
1067 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
1068 printf("WD279X: wr16 %02X ==> %02X\n", (address >> 1) & 3, value);
1069 wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
1070 handled = true;
1071 break;
1072 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
1073 break;
1074 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
1075 break;
1076 case 0x040000: // [ef][4c]xxxx ==> General Control Register
1077 switch (address & 0x077000) {
1078 case 0x040000: // [ef][4c][08]xxx ==> EE
1079 break;
1080 case 0x041000: // [ef][4c][19]xxx ==> PIE
1081 state.pie = ((value & 0x8000) == 0x8000);
1082 handled = true;
1083 break;
1084 case 0x042000: // [ef][4c][2A]xxx ==> BP
1085 break;
1086 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
1087 state.romlmap = ((value & 0x8000) == 0x8000);
1088 handled = true;
1089 break;
1090 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
1091 break;
1092 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
1093 break;
1094 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
1095 break;
1096 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video
1097 break;
1098 }
1099 case 0x050000: // [ef][5d]xxxx ==> 8274
1100 break;
1101 case 0x060000: // [ef][6e]xxxx ==> Control regs
1102 switch (address & 0x07F000) {
1103 default:
1104 break;
1105 }
1106 break;
1107 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
1108 break;
1109 }
1110 }
1111 }
1113 LOG_NOT_HANDLED_W(16);
1114 }
1116 /**
1117 * @brief Write M68K memory, 8-bit
1118 */
1119 void m68k_write_memory_8(uint32_t address, uint32_t value)
1120 {
1121 bool handled = false;
1123 // If ROMLMAP is set, force system to access ROM
1124 if (!state.romlmap)
1125 address |= 0x800000;
1127 // Check access permissions
1128 ACCESS_CHECK_WR(address, 8);
1130 if ((address >= 0x800000) && (address <= 0xBFFFFF)) {
1131 // ROM access (read only!)
1132 handled = true;
1133 } else if (address <= (state.ram_size - 1)) {
1134 // RAM access
1135 WR8(state.ram, mapAddr(address, false), state.ram_size - 1, value);
1136 handled = true;
1137 } else if ((address >= 0x400000) && (address <= 0x7FFFFF)) {
1138 // I/O register space, zone A
1139 switch (address & 0x0F0000) {
1140 case 0x000000: // Map RAM access
1141 if (address > 0x4007FF) fprintf(stderr, "NOTE: WR8 to MapRAM mirror, addr=%08X, data=%02X\n", address, value);
1142 WR8(state.map, address, 0x7FF, value);
1143 handled = true;
1144 break;
1145 case 0x010000: // General Status Register
1146 handled = true;
1147 break;
1148 case 0x020000: // Video RAM
1149 if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=%08X, data=0x%02X\n", address, value);
1150 WR8(state.vram, address, 0x7FFF, value);
1151 handled = true;
1152 break;
1153 case 0x030000: // Bus Status Register 0
1154 handled = true;
1155 break;
1156 case 0x040000: // Bus Status Register 1
1157 handled = true;
1158 break;
1159 case 0x050000: // Phone status
1160 break;
1161 case 0x060000: // DMA Count
1162 // TODO: how to handle this in 8bit mode?
1163 break;
1164 case 0x070000: // Line Printer Status Register
1165 break;
1166 case 0x080000: // Real Time Clock
1167 break;
1168 case 0x090000: // Phone registers
1169 switch (address & 0x0FF000) {
1170 case 0x090000: // Handset relay
1171 case 0x098000:
1172 break;
1173 case 0x091000: // Line select 2
1174 case 0x099000:
1175 break;
1176 case 0x092000: // Hook relay 1
1177 case 0x09A000:
1178 break;
1179 case 0x093000: // Hook relay 2
1180 case 0x09B000:
1181 break;
1182 case 0x094000: // Line 1 hold
1183 case 0x09C000:
1184 break;
1185 case 0x095000: // Line 2 hold
1186 case 0x09D000:
1187 break;
1188 case 0x096000: // Line 1 A-lead
1189 case 0x09E000:
1190 break;
1191 case 0x097000: // Line 2 A-lead
1192 case 0x09F000:
1193 break;
1194 }
1195 break;
1196 case 0x0A0000: // Miscellaneous Control Register
1197 // TODO: how to handle this in 8bit mode?
1198 /*
1199 // TODO: handle the ctrl bits properly
1200 if ((address & 1) == 0) {
1201 // low byte
1202 } else {
1203 // hight byte
1204 // TODO: &0x8000 --> dismiss 60hz intr
1205 state.dma_reading = (value & 0x40);
1206 state.leds = (~value & 0xF);
1207 }
1208 printf("LEDs: %s %s %s %s\n",
1209 (state.leds & 8) ? "R" : "-",
1210 (state.leds & 4) ? "G" : "-",
1211 (state.leds & 2) ? "Y" : "-",
1212 (state.leds & 1) ? "R" : "-");
1213 handled = true;
1214 */
1215 break;
1216 case 0x0B0000: // TM/DIALWR
1217 break;
1218 case 0x0C0000: // Clear Status Register
1219 state.genstat = 0xFFFF;
1220 state.bsr0 = 0xFFFF;
1221 state.bsr1 = 0xFFFF;
1222 handled = true;
1223 break;
1224 case 0x0D0000: // DMA Address Register
1225 if (address & 0x004000) {
1226 // A14 high -- set most significant bits
1227 state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7);
1228 } else {
1229 // A14 low -- set least significant bits
1230 state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff);
1231 }
1232 printf("WR DMA_ADDR, now %08X\n", state.dma_address);
1233 handled = true;
1234 break;
1235 case 0x0E0000: // Disk Control Register
1236 // B7 = FDD controller reset
1237 if ((value & 0x80) == 0) wd2797_reset(&state.fdc_ctx);
1238 // B6 = drive 0 select -- TODO
1239 // B5 = motor enable -- TODO
1240 // B4 = HDD controller reset -- TODO
1241 // B3 = HDD0 select -- TODO
1242 // B2,1,0 = HDD0 head select
1243 handled = true;
1244 break;
1245 case 0x0F0000: // Line Printer Data Register
1246 break;
1247 }
1248 } else if ((address >= 0xC00000) && (address <= 0xFFFFFF)) {
1249 // I/O register space, zone B
1250 switch (address & 0xF00000) {
1251 case 0xC00000: // Expansion slots
1252 case 0xD00000:
1253 switch (address & 0xFC0000) {
1254 case 0xC00000: // Expansion slot 0
1255 case 0xC40000: // Expansion slot 1
1256 case 0xC80000: // Expansion slot 2
1257 case 0xCC0000: // Expansion slot 3
1258 case 0xD00000: // Expansion slot 4
1259 case 0xD40000: // Expansion slot 5
1260 case 0xD80000: // Expansion slot 6
1261 case 0xDC0000: // Expansion slot 7
1262 fprintf(stderr, "NOTE: WR8 to expansion card space, addr=0x%08X, data=0x%08X\n", address, value);
1263 break;
1264 }
1265 break;
1266 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits
1267 case 0xF00000:
1268 switch (address & 0x070000) {
1269 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller
1270 break;
1271 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller
1272 printf("WD279X: wr8 %02X ==> %02X\n", (address >> 1) & 3, value);
1273 wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, value);
1274 handled = true;
1275 break;
1276 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2
1277 break;
1278 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits
1279 break;
1280 case 0x040000: // [ef][4c]xxxx ==> General Control Register
1281 switch (address & 0x077000) {
1282 case 0x040000: // [ef][4c][08]xxx ==> EE
1283 break;
1284 case 0x041000: // [ef][4c][19]xxx ==> PIE
1285 if ((address & 1) == 0)
1286 state.pie = ((value & 0x80) == 0x80);
1287 handled = true;
1288 break;
1289 case 0x042000: // [ef][4c][2A]xxx ==> BP
1290 break;
1291 case 0x043000: // [ef][4c][3B]xxx ==> ROMLMAP
1292 if ((address & 1) == 0)
1293 state.romlmap = ((value & 0x80) == 0x80);
1294 handled = true;
1295 break;
1296 case 0x044000: // [ef][4c][4C]xxx ==> L1 MODEM
1297 break;
1298 case 0x045000: // [ef][4c][5D]xxx ==> L2 MODEM
1299 break;
1300 case 0x046000: // [ef][4c][6E]xxx ==> D/N CONNECT
1301 break;
1302 case 0x047000: // [ef][4c][7F]xxx ==> Whole screen reverse video
1303 break;
1304 }
1305 case 0x050000: // [ef][5d]xxxx ==> 8274
1306 break;
1307 case 0x060000: // [ef][6e]xxxx ==> Control regs
1308 switch (address & 0x07F000) {
1309 default:
1310 break;
1311 }
1312 break;
1313 case 0x070000: // [ef][7f]xxxx ==> 6850 Keyboard Controller
1314 break;
1315 default:
1316 fprintf(stderr, "NOTE: WR8 to undefined E/F-block space, addr=0x%08X, data=0x%08X\n", address, value);
1317 break;
1318 }
1319 }
1320 }
1322 LOG_NOT_HANDLED_W(8);
1323 }
1326 // for the disassembler
1327 uint32_t m68k_read_disassembler_32(uint32_t addr) { return m68k_read_memory_32(addr); }
1328 uint32_t m68k_read_disassembler_16(uint32_t addr) { return m68k_read_memory_16(addr); }
1329 uint32_t m68k_read_disassembler_8 (uint32_t addr) { return m68k_read_memory_8 (addr); }