]> git.sesse.net Git - pistorm/blob - emulator.c
send nmi/int7 when pause pressed
[pistorm] / emulator.c
1 #include <assert.h>
2 #include <dirent.h>
3 #include <endian.h>
4 #include <fcntl.h>
5 #include <pthread.h>
6 #include <sched.h>
7 #include <signal.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/mman.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <sys/ioctl.h>
17 #include "m68k.h"
18 #include "main.h"
19 #include "platforms/platforms.h"
20 #include "input/input.h"
21
22 #include "platforms/amiga/Gayle.h"
23 #include "platforms/amiga/gayle-ide/ide.h"
24 #include "platforms/amiga/amiga-registers.h"
25 #include "platforms/amiga/rtg/rtg.h"
26 #include "platforms/amiga/hunk-reloc.h"
27 #include "platforms/amiga/piscsi/piscsi.h"
28 #include "platforms/amiga/piscsi/piscsi-enums.h"
29 #include "platforms/amiga/net/pi-net.h"
30 #include "platforms/amiga/net/pi-net-enums.h"
31 #include "gpio/ps_protocol.h"
32
33 unsigned char read_ranges;
34 unsigned int read_addr[8];
35 unsigned int read_upper[8];
36 unsigned char *read_data[8];
37 unsigned char write_ranges;
38 unsigned int write_addr[8];
39 unsigned int write_upper[8];
40 unsigned char *write_data[8];
41
42 int kb_hook_enabled = 0;
43 int mouse_hook_enabled = 0;
44 int cpu_emulation_running = 1;
45
46 char mouse_dx = 0, mouse_dy = 0;
47 char mouse_buttons = 0;
48
49 extern uint8_t gayle_int;
50 extern uint8_t gayle_ide_enabled;
51 extern uint8_t gayle_emulation_enabled;
52 extern uint8_t gayle_a4k_int;
53 extern volatile unsigned int *gpio;
54 extern volatile uint16_t srdata;
55 extern uint8_t realtime_graphics_debug;
56 uint8_t realtime_disassembly, int2_enabled = 0;
57 uint32_t do_disasm = 0;
58
59 char disasm_buf[4096];
60
61 #define KICKBASE 0xF80000
62 #define KICKSIZE 0x7FFFF
63
64 int mem_fd, mouse_fd = -1, keyboard_fd = -1;
65 int mem_fd_gpclk;
66 int irq;
67 int gayleirq;
68
69 #define NOP asm("nop"); asm("nop"); asm("nop"); asm("nop");
70
71 // Configurable emulator options
72 unsigned int cpu_type = M68K_CPU_TYPE_68000;
73 unsigned int loop_cycles = 300;
74 struct emulator_config *cfg = NULL;
75 char keyboard_file[256] = "/dev/input/event1";
76
77 void *iplThread(void *args) {
78   printf("IPL thread running\n");
79
80   while (1) {
81     if (!gpio_get_irq()) {
82       irq = 1;
83       m68k_end_timeslice();
84     }
85     else {
86       irq = 0;
87     }
88
89     if (gayle_ide_enabled) {
90       if (((gayle_int & 0x80) || gayle_a4k_int) && (get_ide(0)->drive[0].intrq || get_ide(0)->drive[1].intrq)) {
91         //get_ide(0)->drive[0].intrq = 0;
92         gayleirq = 1;
93         m68k_end_timeslice();
94       }
95       else
96         gayleirq = 0;
97     }
98     //usleep(0);
99     NOP NOP NOP NOP NOP NOP
100     NOP NOP NOP NOP NOP NOP
101     NOP NOP NOP NOP NOP NOP
102     NOP NOP NOP NOP NOP NOP
103     NOP NOP NOP NOP NOP NOP
104     NOP NOP NOP NOP NOP NOP
105     NOP NOP NOP NOP NOP NOP
106     NOP NOP NOP NOP NOP NOP
107     NOP NOP NOP NOP NOP NOP
108     NOP NOP NOP NOP NOP NOP
109     NOP NOP NOP NOP NOP NOP
110     NOP NOP NOP NOP NOP NOP
111   }
112   return args;
113 }
114
115 void stop_cpu_emulation(uint8_t disasm_cur) {
116   m68k_end_timeslice();
117   if (disasm_cur) {
118     m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type);
119     printf("REGA: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1), m68k_get_reg(NULL, M68K_REG_A2), m68k_get_reg(NULL, M68K_REG_A3), \
120             m68k_get_reg(NULL, M68K_REG_A4), m68k_get_reg(NULL, M68K_REG_A5), m68k_get_reg(NULL, M68K_REG_A6), m68k_get_reg(NULL, M68K_REG_A7));
121     printf("REGD: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2), m68k_get_reg(NULL, M68K_REG_D3), \
122             m68k_get_reg(NULL, M68K_REG_D4), m68k_get_reg(NULL, M68K_REG_D5), m68k_get_reg(NULL, M68K_REG_D6), m68k_get_reg(NULL, M68K_REG_D7));
123     printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf);
124     realtime_disassembly = 1;
125   }
126
127   cpu_emulation_running = 0;
128   do_disasm = 0;
129 }
130
131 unsigned int ovl;
132 static volatile unsigned char maprom;
133
134 void sigint_handler(int sig_num) {
135   //if (sig_num) { }
136   //cpu_emulation_running = 0;
137
138   //return;
139   printf("Received sigint %d, exiting.\n", sig_num);
140   if (mouse_fd != -1)
141     close(mouse_fd);
142   if (mem_fd)
143     close(mem_fd);
144
145   if (cfg->platform->shutdown) {
146     cfg->platform->shutdown(cfg);
147   }
148
149   exit(0);
150 }
151
152 int main(int argc, char *argv[]) {
153   int g;
154   //const struct sched_param priority = {99};
155
156   // Some command line switch stuffles
157   for (g = 1; g < argc; g++) {
158     if (strcmp(argv[g], "--cpu_type") == 0 || strcmp(argv[g], "--cpu") == 0) {
159       if (g + 1 >= argc) {
160         printf("%s switch found, but no CPU type specified.\n", argv[g]);
161       } else {
162         g++;
163         cpu_type = get_m68k_cpu_type(argv[g]);
164       }
165     }
166     else if (strcmp(argv[g], "--config-file") == 0 || strcmp(argv[g], "--config") == 0) {
167       if (g + 1 >= argc) {
168         printf("%s switch found, but no config filename specified.\n", argv[g]);
169       } else {
170         g++;
171         cfg = load_config_file(argv[g]);
172       }
173     }
174     else if (strcmp(argv[g], "--keyboard-file") == 0 || strcmp(argv[g], "--kbfile") == 0) {
175       if (g + 1 >= argc) {
176         printf("%s switch found, but no keyboard device path specified.\n", argv[g]);
177       } else {
178         g++;
179         strcpy(keyboard_file, argv[g]);
180       }
181     }
182   }
183
184   if (!cfg) {
185     printf("No config file specified. Trying to load default.cfg...\n");
186     cfg = load_config_file("default.cfg");
187     if (!cfg) {
188       printf("Couldn't load default.cfg, empty emulator config will be used.\n");
189       cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
190       if (!cfg) {
191         printf("Failed to allocate memory for emulator config!\n");
192         return 1;
193       }
194       memset(cfg, 0x00, sizeof(struct emulator_config));
195     }
196   }
197
198   if (cfg) {
199     if (cfg->cpu_type) cpu_type = cfg->cpu_type;
200     if (cfg->loop_cycles) loop_cycles = cfg->loop_cycles;
201
202     if (!cfg->platform)
203       cfg->platform = make_platform_config("none", "generic");
204     cfg->platform->platform_initial_setup(cfg);
205   }
206
207   if (cfg->mouse_enabled) {
208     mouse_fd = open(cfg->mouse_file, O_RDONLY | O_NONBLOCK);
209     if (mouse_fd == -1) {
210       printf("Failed to open %s, can't enable mouse hook.\n", cfg->mouse_file);
211       cfg->mouse_enabled = 0;
212     }
213   }
214
215   keyboard_fd = open(keyboard_file, O_RDONLY | O_NONBLOCK);
216   if (keyboard_fd == -1) {
217     printf("Failed to open keyboard event source.\n");
218   }
219
220   InitGayle();
221
222   signal(SIGINT, sigint_handler);
223   /*setup_io();
224
225   //goto skip_everything;
226
227   // Enable 200MHz CLK output on GPIO4, adjust divider and pll source depending
228   // on pi model
229   printf("Enable 200MHz GPCLK0 on GPIO4\n");
230   gpio_enable_200mhz();
231
232   // reset cpld statemachine first
233
234   write_reg(0x01);
235   usleep(100);
236   usleep(1500);
237   write_reg(0x00);
238   usleep(100);
239
240   // reset amiga and statemachine
241   skip_everything:;
242
243   usleep(1500);
244
245   m68k_init();
246   printf("Setting CPU type to %d.\n", cpu_type);
247   m68k_set_cpu_type(cpu_type);
248   cpu_pulse_reset();
249
250   if (maprom == 1) {
251     m68k_set_reg(M68K_REG_PC, 0xF80002);
252   } else {
253     m68k_set_reg(M68K_REG_PC, 0x0);
254   }*/
255   ps_setup_protocol();
256   ps_reset_state_machine();
257   ps_pulse_reset();
258
259   usleep(1500);
260   m68k_init();
261   printf("Setting CPU type to %d.\n", cpu_type);
262   m68k_set_cpu_type(cpu_type);
263   cpu_pulse_reset();
264
265   char c = 0, c_code = 0, c_type = 0;
266
267   pthread_t id;
268   int err;
269   err = pthread_create(&id, NULL, &iplThread, NULL);
270   if (err != 0)
271     printf("can't create IPL thread :[%s]", strerror(err));
272   else
273     printf("IPL Thread created successfully\n");
274
275   m68k_pulse_reset();
276   while (42) {
277     if (mouse_hook_enabled) {
278       get_mouse_status(&mouse_dx, &mouse_dy, &mouse_buttons);
279     }
280
281     if (realtime_disassembly && (do_disasm || cpu_emulation_running)) {
282       m68k_disassemble(disasm_buf, m68k_get_reg(NULL, M68K_REG_PC), cpu_type);
283       printf("REGA: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1), m68k_get_reg(NULL, M68K_REG_A2), m68k_get_reg(NULL, M68K_REG_A3), \
284               m68k_get_reg(NULL, M68K_REG_A4), m68k_get_reg(NULL, M68K_REG_A5), m68k_get_reg(NULL, M68K_REG_A6), m68k_get_reg(NULL, M68K_REG_A7));
285       printf("REGD: 0:$%.8X 1:$%.8X 2:$%.8X 3:$%.8X 4:$%.8X 5:$%.8X 6:$%.8X 7:$%.8X\n", m68k_get_reg(NULL, M68K_REG_D0), m68k_get_reg(NULL, M68K_REG_D1), m68k_get_reg(NULL, M68K_REG_D2), m68k_get_reg(NULL, M68K_REG_D3), \
286               m68k_get_reg(NULL, M68K_REG_D4), m68k_get_reg(NULL, M68K_REG_D5), m68k_get_reg(NULL, M68K_REG_D6), m68k_get_reg(NULL, M68K_REG_D7));
287       printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf);
288       if (do_disasm)
289         do_disasm--;
290       m68k_execute(1);
291     }
292     else {
293       if (cpu_emulation_running)
294         m68k_execute(loop_cycles);
295     }
296
297     if (irq) {
298       unsigned int status = read_reg();
299       m68k_set_irq((status & 0xe000) >> 13);
300       //irq = 0;
301     }
302     else if (gayleirq && int2_enabled) {
303       write16(0xdff09c, 0x8000 | (1 << 3));
304       m68k_set_irq(2);
305       //irq = 0;
306     }
307     else {
308       m68k_set_irq(0);
309     }
310
311     while (get_key_char(&c, &c_code, &c_type)) {
312       if (c && c == cfg->keyboard_toggle_key && !kb_hook_enabled) {
313         kb_hook_enabled = 1;
314         printf("Keyboard hook enabled.\n");
315       }
316       else if (kb_hook_enabled) {
317         if (c == 0x1B && c_type) {
318           kb_hook_enabled = 0;
319           printf("Keyboard hook disabled.\n");
320         }
321         else {
322           /*printf("Key code: %.2X - ", c_code);
323           switch (c_type) {
324             case 0:
325               printf("released.\n");
326               break;
327             case 1:
328               printf("pressed.\n");
329               break;
330             case 2:
331               printf("repeat.\n");
332               break;
333             default:
334               printf("unknown.\n");
335               break;
336           }*/
337           if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled) {
338             m68k_set_irq(2);
339           }
340         }
341       }
342
343       if (!kb_hook_enabled && c_type) {
344         if (c && c == cfg->mouse_toggle_key) {
345           mouse_hook_enabled ^= 1;
346           printf("Mouse hook %s.\n", mouse_hook_enabled ? "enabled" : "disabled");
347           mouse_dx = mouse_dy = mouse_buttons = 0;
348         }
349         if (c == 'r') {
350           cpu_emulation_running ^= 1;
351           printf("CPU emulation is now %s\n", cpu_emulation_running ? "running" : "stopped");
352         }
353         if (c == 'g') {
354           realtime_graphics_debug ^= 1;
355           printf("Real time graphics debug is now %s\n", realtime_graphics_debug ? "on" : "off");
356         }
357         if (c == 'R') {
358           cpu_pulse_reset();
359           //m68k_pulse_reset();
360           printf("CPU emulation reset.\n");
361         }
362         if (c == 'q') {
363           printf("Quitting and exiting emulator.\n");
364           goto stop_cpu_emulation;
365         }
366         if (c == 'd') {
367           realtime_disassembly ^= 1;
368           do_disasm = 1;
369           printf("Real time disassembly is now %s\n", realtime_disassembly ? "on" : "off");
370         }
371         if (c == 'D') {
372           int r = get_mapped_item_by_address(cfg, 0x08000000);
373           if (r != -1) {
374             printf("Dumping first 16MB of mapped range %d.\n", r);
375             FILE *dmp = fopen("./memdmp.bin", "wb+");
376             fwrite(cfg->map_data[r], 16 * SIZE_MEGA, 1, dmp);
377             fclose(dmp);
378           }
379         }
380         if (c == 's' && realtime_disassembly) {
381           do_disasm = 1;
382         }
383         if (c == 'S' && realtime_disassembly) {
384           do_disasm = 128;
385         }
386
387         // pause pressed; trigger nmi (int level 7)
388         if (c == 0x01) {
389           m68k_set_irq(7);
390         }
391       }
392     }
393   }
394
395   stop_cpu_emulation:;
396
397   if (mouse_fd != -1)
398     close(mouse_fd);
399   if (mem_fd)
400     close(mem_fd);
401
402   return 0;
403 }
404
405 void cpu_pulse_reset(void) {
406   ps_pulse_reset();
407   //write_reg(0x00);
408   // printf("Status Reg%x\n",read_reg());
409   //usleep(100000);
410   //write_reg(0x02);
411   // printf("Status Reg%x\n",read_reg());
412   if (cfg->platform->handle_reset)
413     cfg->platform->handle_reset(cfg);
414
415   ovl = 1;
416   m68k_write_memory_8(0xbfe201, 0x0001);  // AMIGA OVL
417   m68k_write_memory_8(0xbfe001, 0x0001);  // AMIGA OVL high (ROM@0x0)
418
419   m68k_pulse_reset();
420 }
421
422 int cpu_irq_ack(int level) {
423   printf("cpu irq ack\n");
424   return level;
425 }
426
427 static unsigned int target = 0;
428 static uint8_t send_keypress = 0;
429
430 uint8_t cdtv_dmac_reg_idx_read();
431 void cdtv_dmac_reg_idx_write(uint8_t value);
432 uint32_t cdtv_dmac_read(uint32_t address, uint8_t type);
433 void cdtv_dmac_write(uint32_t address, uint32_t value, uint8_t type);
434
435 #define PLATFORM_CHECK_READ(a) \
436   if (address >= cfg->custom_low && address < cfg->custom_high) { \
437     unsigned int target = 0; \
438     switch(cfg->platform->id) { \
439       case PLATFORM_AMIGA: { \
440         if (address >= PISCSI_OFFSET && address < PISCSI_UPPER) { \
441           return handle_piscsi_read(address, a); \
442         } \
443         if (address >= PINET_OFFSET && address < PINET_UPPER) { \
444           return handle_pinet_read(address, a); \
445         } \
446         if (address >= PIGFX_RTG_BASE && address < PIGFX_UPPER) { \
447           return rtg_read((address & 0x0FFFFFFF), a); \
448         } \
449         if (custom_read_amiga(cfg, address, &target, a) != -1) { \
450           return target; \
451         } \
452         break; \
453       } \
454       default: \
455         break; \
456     } \
457   } \
458   if (ovl || (address >= cfg->mapped_low && address < cfg->mapped_high)) { \
459     if (handle_mapped_read(cfg, address, &target, a) != -1) \
460       return target; \
461   }
462
463 unsigned int m68k_read_memory_8(unsigned int address) {
464   PLATFORM_CHECK_READ(OP_TYPE_BYTE);
465
466   /*if (address >= 0xE90000 && address < 0xF00000) {
467     printf("BYTE read from DMAC @%.8X:", address);
468     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_BYTE);
469     printf("%.2X\n", v);
470     m68k_end_timeslice();
471     cpu_emulation_running = 0;
472     return v;
473   }*/
474
475   /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x080032F0 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x080032F0 + 0x4000) {
476     stop_cpu_emulation(1);
477   }*/
478
479
480   if (address & 0xFF000000)
481     return 0;
482
483   unsigned char result = (unsigned int)read8((uint32_t)address);
484
485   if (mouse_hook_enabled) {
486     if (address == CIAAPRA) {
487       if (mouse_buttons & 0x01) {
488         //mouse_buttons -= 1;
489         return (unsigned int)(result ^ 0x40);
490       }
491       else
492           return (unsigned int)result;
493     }
494   }
495   if (kb_hook_enabled) {
496     if (address == CIAAICR) {
497       if (get_num_kb_queued() && (!send_keypress || send_keypress == 1)) {
498         result |= 0x08;
499         if (!send_keypress)
500           send_keypress = 1;
501       }
502       if (send_keypress == 2) {
503         result |= 0x02;
504         send_keypress = 0;
505       }
506       return result;
507     }
508     if (address == CIAADAT) {
509       if (send_keypress) {
510         uint8_t c = 0, t = 0;
511         pop_queued_key(&c, &t);
512         t ^= 0x01;
513         result = ((c << 1) | t) ^ 0xFF;
514         send_keypress = 2;
515       }
516       return result;
517     }
518   }
519
520   return result;
521 }
522
523 unsigned int m68k_read_memory_16(unsigned int address) {
524   PLATFORM_CHECK_READ(OP_TYPE_WORD);
525
526   /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x080032F0 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x080032F0 + 0x4000) {
527     stop_cpu_emulation(1);
528   }*/
529
530   /*if (address >= 0xE90000 && address < 0xF00000) {
531     printf("WORD read from DMAC @%.8X:", address);
532     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_WORD);
533     printf("%.2X\n", v);
534     m68k_end_timeslice();
535     cpu_emulation_running = 0;
536     return v;
537   }*/
538
539   if (mouse_hook_enabled) {
540     if (address == JOY0DAT) {
541       // Forward mouse valueses to Amyga.
542       unsigned short result = (mouse_dy << 8) | (mouse_dx);
543       return (unsigned int)result;
544     }
545     /*if (address == CIAAPRA) {
546       unsigned short result = (unsigned int)read16((uint32_t)address);
547       if (mouse_buttons & 0x01) {
548         return (unsigned int)(result | 0x40);
549       }
550       else
551           return (unsigned int)result;
552     }*/
553     if (address == POTGOR) {
554       unsigned short result = (unsigned int)read16((uint32_t)address);
555       if (mouse_buttons & 0x02) {
556         return (unsigned int)(result ^ (0x2 << 9));
557       }
558       else
559           return (unsigned int)(result & 0xFFFD);
560     }
561   }
562
563   if (address & 0xFF000000)
564     return 0;
565
566   if (address & 0x01) {
567     return ((read8(address) << 8) | read8(address + 1));
568   }
569   return (unsigned int)read16((uint32_t)address);
570 }
571
572 unsigned int m68k_read_memory_32(unsigned int address) {
573   PLATFORM_CHECK_READ(OP_TYPE_LONGWORD);
574
575   /*if (m68k_get_reg(NULL, M68K_REG_PC) >= 0x080032F0 && m68k_get_reg(NULL, M68K_REG_PC) <= 0x080032F0 + 0x4000) {
576     stop_cpu_emulation(1);
577   }*/
578
579   /*if (address >= 0xE90000 && address < 0xF00000) {
580     printf("LONGWORD read from DMAC @%.8X:", address);
581     uint32_t v = cdtv_dmac_read(address & 0xFFFF, OP_TYPE_LONGWORD);
582     printf("%.2X\n", v);
583     m68k_end_timeslice();
584     cpu_emulation_running = 0;
585     return v;
586   }*/
587
588   if (address & 0xFF000000)
589     return 0;
590
591   if (address & 0x01) {
592     uint32_t c = read8(address);
593     c |= (be16toh(read16(address+1)) << 8);
594     c |= (read8(address + 3) << 24);
595     return htobe32(c);
596   }
597   uint16_t a = read16(address);
598   uint16_t b = read16(address + 2);
599   return (a << 16) | b;
600 }
601
602 #define PLATFORM_CHECK_WRITE(a) \
603   if (address >= cfg->custom_low && address < cfg->custom_high) { \
604     switch(cfg->platform->id) { \
605       case PLATFORM_AMIGA: { \
606         if (address >= PISCSI_OFFSET && address < PISCSI_UPPER) { \
607           handle_piscsi_write(address, value, a); \
608         } \
609         if (address >= PINET_OFFSET && address < PINET_UPPER) { \
610           handle_pinet_write(address, value, a); \
611         } \
612         if (address >= PIGFX_RTG_BASE && address < PIGFX_UPPER) { \
613           rtg_write((address & 0x0FFFFFFF), value, a); \
614           return; \
615         } \
616         if (custom_write_amiga(cfg, address, value, a) != -1) { \
617           return; \
618         } \
619         break; \
620       } \
621       default: \
622         break; \
623     } \
624   } \
625   if (address >= cfg->mapped_low && address < cfg->mapped_high) { \
626     if (handle_mapped_write(cfg, address, value, a) != -1) \
627       return; \
628   }
629
630 void m68k_write_memory_8(unsigned int address, unsigned int value) {
631   PLATFORM_CHECK_WRITE(OP_TYPE_BYTE);
632
633   /*if (address >= 0xE90000 && address < 0xF00000) {
634     printf("BYTE write to DMAC @%.8X: %.2X\n", address, value);
635     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_BYTE);
636     m68k_end_timeslice();
637     cpu_emulation_running = 0;
638     return;
639   }*/
640
641   if (address == 0xbfe001) {
642     if (ovl != (value & (1 << 0))) {
643       ovl = (value & (1 << 0));
644       printf("OVL:%x\n", ovl);
645     }
646   }
647
648   if (address & 0xFF000000)
649     return;
650
651   write8((uint32_t)address, value);
652   return;
653 }
654
655 void m68k_write_memory_16(unsigned int address, unsigned int value) {
656   PLATFORM_CHECK_WRITE(OP_TYPE_WORD);
657
658   /*if (address >= 0xE90000 && address < 0xF00000) {
659     printf("WORD write to DMAC @%.8X: %.4X\n", address, value);
660     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_WORD);
661     m68k_end_timeslice();
662     cpu_emulation_running = 0;
663     return;
664   }*/
665
666   if (address == 0xDFF030) {
667     char *serdat = (char *)&value;
668     // SERDAT word. see amiga dev docs appendix a; upper byte is control codes, and bit 0 is always 1.
669     // ignore this upper byte as it's not viewable data, only display lower byte.
670     printf("%c", serdat[0]);
671   }
672   if (address == 0xDFF09A) {
673     if (!(value & 0x8000)) {
674       if (value & 0x04) {
675         int2_enabled = 0;
676       }
677     }
678     else if (value & 0x04) {
679       int2_enabled = 1;
680     }
681   }
682
683   if (address & 0xFF000000)
684     return;
685
686   if (address & 0x01)
687     printf("Unaligned WORD write!\n");
688
689   write16((uint32_t)address, value);
690   return;
691 }
692
693 void m68k_write_memory_32(unsigned int address, unsigned int value) {
694   PLATFORM_CHECK_WRITE(OP_TYPE_LONGWORD);
695
696   /*if (address >= 0xE90000 && address < 0xF00000) {
697     printf("LONGWORD write to DMAC @%.8X: %.8X\n", address, value);
698     cdtv_dmac_write(address & 0xFFFF, value, OP_TYPE_LONGWORD);
699     m68k_end_timeslice();
700     cpu_emulation_running = 0;
701     return;
702   }*/
703
704   if (address & 0xFF000000)
705     return;
706
707   if (address & 0x01)
708     printf("Unaligned LONGWORD write!\n");
709
710   write16(address, value >> 16);
711   write16(address + 2, value);
712   return;
713 }