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