]> git.sesse.net Git - pistorm/blob - emulator.c
Some random cleanup
[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 #include "gpio/gpio.h"
22
23 #include "platforms/amiga/Gayle.h"
24 #include "platforms/amiga/gayle-ide/ide.h"
25 #include "platforms/amiga/amiga-registers.h"
26
27 int kb_hook_enabled = 0;
28 int mouse_hook_enabled = 0;
29 int cpu_emulation_running = 1;
30
31 char mouse_dx = 0, mouse_dy = 0;
32 char mouse_buttons = 0;
33
34 #define KICKBASE 0xF80000
35 #define KICKSIZE 0x7FFFF
36
37 int mem_fd, mouse_fd = -1, keyboard_fd = -1;
38 int mem_fd_gpclk;
39 int gayle_emulation_enabled = 1;
40
41 // Configurable emulator options
42 unsigned int cpu_type = M68K_CPU_TYPE_68000;
43 unsigned int loop_cycles = 300;
44 struct emulator_config *cfg = NULL;
45 char keyboard_file[256] = "/dev/input/event0";
46
47 //unsigned char g_kick[524288];
48 //unsigned char g_ram[FASTSIZE + 1]; /* RAM */
49 int ovl;
50 static volatile unsigned char maprom;
51
52 void sigint_handler(int sig_num) {
53   //if (sig_num) { }
54   //cpu_emulation_running = 0;
55
56   //return;
57   printf("Received sigint %d, exiting.\n", sig_num);
58   if (mouse_fd != -1)
59     close(mouse_fd);
60   if (mem_fd)
61     close(mem_fd);
62
63   if (cfg->platform->shutdown) {
64     cfg->platform->shutdown(cfg);
65   }
66
67   exit(0);
68 }
69
70 int main(int argc, char *argv[]) {
71   int g;
72   const struct sched_param priority = {99};
73
74   // Some command line switch stuffles
75   for (g = 1; g < argc; g++) {
76     if (strcmp(argv[g], "--disable-gayle") == 0) {
77       gayle_emulation_enabled = 0;
78     }
79     else if (strcmp(argv[g], "--cpu_type") == 0 || strcmp(argv[g], "--cpu") == 0) {
80       if (g + 1 >= argc) {
81         printf("%s switch found, but no CPU type specified.\n", argv[g]);
82       } else {
83         g++;
84         cpu_type = get_m68k_cpu_type(argv[g]);
85       }
86     }
87     else if (strcmp(argv[g], "--config-file") == 0 || strcmp(argv[g], "--config") == 0) {
88       if (g + 1 >= argc) {
89         printf("%s switch found, but no config filename specified.\n", argv[g]);
90       } else {
91         g++;
92         cfg = load_config_file(argv[g]);
93       }
94     }
95     else if (strcmp(argv[g], "--keyboard-file") == 0 || strcmp(argv[g], "--kbfile") == 0) {
96       if (g + 1 >= argc) {
97         printf("%s switch found, but no keyboard device path specified.\n", argv[g]);
98       } else {
99         g++;
100         strcpy(keyboard_file, argv[g]);
101       }
102     }
103   }
104
105   if (!cfg) {
106     printf("No config file specified. Trying to load default.cfg...\n");
107     cfg = load_config_file("default.cfg");
108     if (!cfg) {
109       printf("Couldn't load default.cfg, empty emulator config will be used.\n");
110       cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
111       if (!cfg) {
112         printf("Failed to allocate memory for emulator config!\n");
113         return 1;
114       }
115       memset(cfg, 0x00, sizeof(struct emulator_config));
116     }
117   }
118
119   if (cfg) {
120     if (cfg->cpu_type) cpu_type = cfg->cpu_type;
121     if (cfg->loop_cycles) loop_cycles = cfg->loop_cycles;
122
123     if (!cfg->platform)
124       cfg->platform = make_platform_config("none", "generic");
125     cfg->platform->platform_initial_setup(cfg);
126   }
127
128   if (cfg->mouse_enabled) {
129     mouse_fd = open(cfg->mouse_file, O_RDONLY | O_NONBLOCK);
130     if (mouse_fd == -1) {
131       printf("Failed to open %s, can't enable mouse hook.\n", cfg->mouse_file);
132       cfg->mouse_enabled = 0;
133     }
134   }
135
136   keyboard_fd = open(keyboard_file, O_RDONLY | O_NONBLOCK);
137   if (keyboard_fd == -1) {
138     printf("Failed to open keyboard event source.\n");
139   }
140
141   sched_setscheduler(0, SCHED_FIFO, &priority);
142   mlockall(MCL_CURRENT);  // lock in memory to keep us from paging out
143
144   InitGayle();
145
146   signal(SIGINT, sigint_handler);
147   setup_io();
148
149   //goto skip_everything;
150
151   // Enable 200MHz CLK output on GPIO4, adjust divider and pll source depending
152   // on pi model
153   printf("Enable 200MHz GPCLK0 on GPIO4\n");
154   gpio_enable_200mhz();
155
156   // reset cpld statemachine first
157
158   write_reg(0x01);
159   usleep(100);
160   usleep(1500);
161   write_reg(0x00);
162   usleep(100);
163
164   // reset amiga and statemachine
165   skip_everything:;
166   cpu_pulse_reset();
167   ovl = 1;
168   m68k_write_memory_8(0xbfe201, 0x0001);  // AMIGA OVL
169   m68k_write_memory_8(0xbfe001, 0x0001);  // AMIGA OVL high (ROM@0x0)
170
171   usleep(1500);
172
173   m68k_init();
174   printf("Setting CPU type to %d.\n", cpu_type);
175   m68k_set_cpu_type(cpu_type);
176   m68k_pulse_reset();
177
178   if (maprom == 1) {
179     m68k_set_reg(M68K_REG_PC, 0xF80002);
180   } else {
181     m68k_set_reg(M68K_REG_PC, 0x0);
182   }
183
184 /*
185           pthread_t id;
186           int err;
187           err = pthread_create(&id, NULL, &iplThread, NULL);
188           if (err != 0)
189               printf("\ncan't create IPL thread :[%s]", strerror(err));
190           else
191               printf("\n IPL Thread created successfully\n");
192 */
193   char c = 0;
194
195   m68k_pulse_reset();
196   while (42) {
197     if (mouse_hook_enabled) {
198       if (get_mouse_status(&mouse_dx, &mouse_dy, &mouse_buttons)) {
199         //printf("Maus: %d (%.2X), %d (%.2X), B:%.2X\n", mouse_dx, mouse_dx, mouse_dy, mouse_dy, mouse_buttons);
200       }
201     }
202
203     if (cpu_emulation_running)
204       m68k_execute(loop_cycles);
205     
206     // FIXME: Rework this to use keyboard events instead.
207     /*while (get_key_char(&c)) {
208       if (c == cfg->keyboard_toggle_key && !kb_hook_enabled) {
209         kb_hook_enabled = 1;
210         printf("Keyboard hook enabled.\n");
211       }
212       else if (c == 0x1B && kb_hook_enabled) {
213         kb_hook_enabled = 0;
214         printf("Keyboard hook disabled.\n");
215       }
216       if (!kb_hook_enabled) {
217         if (c == cfg->mouse_toggle_key) {
218           mouse_hook_enabled ^= 1;
219           printf("Mouse hook %s.\n", mouse_hook_enabled ? "enabled" : "disabled");
220           mouse_dx = mouse_dy = mouse_buttons = 0;
221         }
222         if (c == 'r') {
223           cpu_emulation_running ^= 1;
224           printf("CPU emulation is now %s\n", cpu_emulation_running ? "running" : "stopped");
225         }
226         if (c == 'R') {
227           cpu_pulse_reset();
228           m68k_pulse_reset();
229           printf("CPU emulation reset.\n");
230         }
231         if (c == 'q') {
232           printf("Quitting and exiting emulator.\n");
233           goto stop_cpu_emulation;
234         }
235       }
236     }*/
237 /*
238     if (toggle == 1){
239       srdata = read_reg();
240       m68k_set_irq((srdata >> 13) & 0xff);
241     } else {
242          m68k_set_irq(0);
243     };
244     usleep(1);
245 */
246
247     gpio_handle_irq();
248   }
249
250   stop_cpu_emulation:;
251
252   if (mouse_fd != -1)
253     close(mouse_fd);
254   if (mem_fd)
255     close(mem_fd);
256
257   return 0;
258 }
259
260 void cpu_pulse_reset(void) {
261   write_reg(0x00);
262   // printf("Status Reg%x\n",read_reg());
263   usleep(100000);
264   write_reg(0x02);
265   // printf("Status Reg%x\n",read_reg());
266 }
267
268 int cpu_irq_ack(int level) {
269   printf("cpu irq ack\n");
270   return level;
271 }
272
273 static unsigned int target = 0;
274
275 #define PLATFORM_CHECK_READ(a) \
276   if (address >= cfg->custom_low && address < cfg->custom_high) { \
277     unsigned int target = 0; \
278     switch(cfg->platform->id) { \
279       case PLATFORM_AMIGA: { \
280         if (custom_read_amiga(cfg, address, &target, a) != -1) { \
281           return target; \
282         } \
283         break; \
284       } \
285       default: \
286         break; \
287     } \
288   } \
289   if (ovl || (address >= cfg->mapped_low && address < cfg->mapped_high)) { \
290     if (handle_mapped_read(cfg, address, &target, a) != -1) \
291       return target; \
292   }
293
294 unsigned int m68k_read_memory_8(unsigned int address) {
295   PLATFORM_CHECK_READ(OP_TYPE_BYTE);
296
297     address &=0xFFFFFF;
298     return read8((uint32_t)address);
299 }
300
301 unsigned int m68k_read_memory_16(unsigned int address) {
302   PLATFORM_CHECK_READ(OP_TYPE_WORD);
303
304   if (mouse_hook_enabled) {
305     if (address == JOY0DAT) {
306       // Forward mouse valueses to Amyga.
307       unsigned short result = (mouse_dy << 8) | (mouse_dx);
308       mouse_dx = mouse_dy = 0;
309       return (unsigned int)result;
310     }
311     if (address == CIAAPRA) {
312       unsigned short result = (unsigned int)read16((uint32_t)address);
313       if (mouse_buttons & 0x01) {
314         mouse_buttons -= 1;
315         return (unsigned int)(result | 0x40);
316       }
317       else
318           return (unsigned int)result;
319     }
320     if (address == POTGOR) {
321       unsigned short result = (unsigned int)read16((uint32_t)address);
322       if (mouse_buttons & 0x02) {
323         mouse_buttons -= 2;
324         return (unsigned int)(result | 0x2);
325       }
326       else
327           return (unsigned int)result;
328     }
329   }
330
331
332   address &=0xFFFFFF;
333   return (unsigned int)read16((uint32_t)address);
334 }
335
336 unsigned int m68k_read_memory_32(unsigned int address) {
337   PLATFORM_CHECK_READ(OP_TYPE_LONGWORD);
338
339   address &=0xFFFFFF;
340   uint16_t a = read16(address);
341   uint16_t b = read16(address + 2);
342   return (a << 16) | b;
343 }
344
345 #define PLATFORM_CHECK_WRITE(a) \
346   if (address >= cfg->custom_low && address < cfg->custom_high) { \
347     switch(cfg->platform->id) { \
348       case PLATFORM_AMIGA: { \
349         if (custom_write_amiga(cfg, address, value, a) != -1) { \
350           return; \
351         } \
352         break; \
353       } \
354       default: \
355         break; \
356     } \
357   } \
358   if (address >= cfg->mapped_low && address < cfg->mapped_high) { \
359     if (handle_mapped_write(cfg, address, value, a) != -1) \
360       return; \
361   }
362
363 void m68k_write_memory_8(unsigned int address, unsigned int value) {
364   PLATFORM_CHECK_WRITE(OP_TYPE_BYTE);
365
366   if (address == 0xbfe001) {
367     if (ovl != (value & (1 << 0))) {
368       ovl = (value & (1 << 0));
369       printf("OVL:%x\n", ovl);
370     }
371   }
372
373   address &=0xFFFFFF;
374   write8((uint32_t)address, value);
375   return;
376 }
377
378 void m68k_write_memory_16(unsigned int address, unsigned int value) {
379   PLATFORM_CHECK_WRITE(OP_TYPE_WORD);
380
381   address &=0xFFFFFF;
382   write16((uint32_t)address, value);
383   return;
384 }
385
386 void m68k_write_memory_32(unsigned int address, unsigned int value) {
387   PLATFORM_CHECK_WRITE(OP_TYPE_LONGWORD);
388
389   address &=0xFFFFFF;
390   write16(address, value >> 16);
391   write16(address + 2, value);
392   return;
393 }