Mon, 06 Dec 2010 01:43:04 +0000
fix side-select bug in WDC FDC driver, was causing all reads to occur on side0... now the Loader boots!
Loader will boot, but immediately gives up on the floppy drive... Not sure why.
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); }