1 /* gngeo a neogeo emulator
2 * Copyright (C) 2001 Peponas Mathieu
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /* cyclone interface */
20
21
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #ifdef USE_CYCLONE
28
29 #include <stdlib.h>
30
31 #include "cyclone/Cyclone.h"
32 #include "memory.h"
33 #include "emu.h"
34 #include "state.h"
35 #include "debug.h"
36 #include "video.h"
37 #include "conf.h"
38
39 struct Cyclone MyCyclone;
40 static int total_cycles;
41 static int time_slice;
42 Uint32 cyclone_pc;
43 extern int current_line;
44 Uint8 save_buffer[128];
45
46 extern Uint32 irq2pos_value;
cyclone68k_store_video_word(Uint32 addr,Uint16 data)47 static __inline__ void cyclone68k_store_video_word(Uint32 addr, Uint16 data)
48 {
49 //SDL_Swap16(data);
50 //printf("mem68k_store_video_word %08x %04x\n",addr,data);
51
52 addr &= 0xFFFF;
53 switch (addr) {
54 case 0x0:
55 memory.vid.vptr = data & 0xffff;
56 break;
57 case 0x2:
58 //if (((vptr<<1)==0x10800+0x8) ) printf("Store to video %08x @pc=%08x\n",vptr<<1,cpu_68k_getpc());
59 /*
60 if (((vptr<<1)==0x10000+0x17e) ||
61 ((vptr<<1)==0x10400+0x17e) ||
62 ((vptr<<1)==0x10800+0x17e) ) printf("Store to video %08x @pc=%08x\n",vptr<<1,cpu_68k_getpc());
63 */
64 WRITE_WORD(&memory.vid.ram[memory.vid.vptr << 1], data);
65 memory.vid.vptr = (memory.vid.vptr + memory.vid.modulo) & 0xffff;
66 break;
67 case 0x4:
68 memory.vid.modulo = (int) data;
69 break;
70 case 0x6:
71 write_neo_control(data);
72 break;
73 case 0x8:
74 write_irq2pos((memory.vid.irq2pos & 0xffff) | ((Uint32) data << 16));
75 break;
76 case 0xa:
77 write_irq2pos((memory.vid.irq2pos & 0xffff0000) | (Uint32) data);
78 break;
79 case 0xc:
80 /* games write 7 or 4 at 0x3c000c at every frame */
81 /* IRQ acknowledge */
82 break;
83 }
84
85
86 }
87
print_one_reg(Uint32 r)88 static void print_one_reg(Uint32 r) {
89 printf("reg=%08x\n",r);
90 }
91
swap_memory(Uint8 * mem,Uint32 length)92 static void swap_memory(Uint8 * mem, Uint32 length)
93 {
94 int i, j;
95
96 /* swap bytes in each word */
97 for (i = 0; i < length; i += 2) {
98 j = mem[i];
99 mem[i] = mem[i + 1];
100 mem[i + 1] = j;
101 }
102 }
103
MyCheckPc(unsigned int pc)104 static unsigned int MyCheckPc(unsigned int pc) {
105 int i;
106 pc-=MyCyclone.membase; // Get the real program counter
107
108 pc&=0xFFFFFF;
109 MyCyclone.membase=-1;
110
111 /* printf("## Check pc %08x\n",pc);
112 for(i=0;i<8;i++) printf(" d%d=%08x a%d=%08x\n",i,MyCyclone.d[i],i,MyCyclone.a[i]); */
113
114 //printf("PC %08x %08x\n",(pc&0xF00000),(pc&0xF00000)>>20);
115 switch((pc&0xF00000)>>20) {
116 case 0x0:
117 MyCyclone.membase=(int)memory.rom.cpu_m68k.p;
118 break;
119 case 0x2:
120 MyCyclone.membase=(int)(memory.rom.cpu_m68k.p+bankaddress)-0x200000;
121 break;
122 case 0x1:
123 if (pc<=0x10FFff)
124 MyCyclone.membase=(int)memory.ram-0x100000;
125 break;
126 case 0xC:
127 if (pc<=0xc1FFff)
128 MyCyclone.membase=(int)memory.rom.bios_m68k.p-0xc00000;
129 break;
130 }
131
132 if (MyCyclone.membase==-1) {
133 printf("ERROROROOR %08x\n",pc);
134 exit(1);
135 }
136
137 return MyCyclone.membase+pc; // New program counter
138 }
139
140 #define MEMHANDLER_READ(start,end,func) {if (a>=start && a<=end) return func(a);}
141 #define MEMHANDLER_WRITE(start,end,func) {if (a>=start && a<=end) {func(a,d);return;}}
142
MyRead8(unsigned int a)143 static unsigned int MyRead8 (unsigned int a) {
144 unsigned int addr=a&0xFFFFF;
145 unsigned int b=((a&0xF0000)>>16);
146 a&=0xFFFFFF;
147 switch((a&0xFF0000)>>20) {
148 case 0x0:
149 return (READ_BYTE_ROM(memory.rom.cpu_m68k.p + addr))&0xFF;
150 break;
151 case 0x2:
152 if (memory.bksw_unscramble)
153 return mem68k_fetch_bk_normal_byte(a);
154 return (READ_BYTE_ROM(memory.rom.cpu_m68k.p + bankaddress + addr))&0xFF;
155 break;
156 case 0x1:
157 return (READ_BYTE_ROM(memory.ram + (addr&0xFFFF)))&0xFF;
158 break;
159 case 0xC:
160 if (b<=1) return (READ_BYTE_ROM(memory.rom.bios_m68k.p + addr))&0xFF;
161 break;
162 case 0xd:
163 if (b==0) return mem68k_fetch_sram_byte(a)&0xFF;
164 break;
165 case 0x4:
166 if (b==0) return mem68k_fetch_pal_byte(a)&0xFF;
167 break;
168 case 0x3:
169 if (b==0xC) return mem68k_fetch_video_byte(a)&0xFF;
170 if (b==0) return mem68k_fetch_ctl1_byte(a)&0xFF;
171 if (b==4) return mem68k_fetch_ctl2_byte(a)&0xFF;
172 if (b==8) return mem68k_fetch_ctl3_byte(a)&0xFF;
173 if (b==2) return mem68k_fetch_coin_byte(a)&0xFF;
174 break;
175 case 0x8:
176 if (b==0) return mem68k_fetch_memcrd_byte(a)&0xFF;
177 break;
178 }
179
180 return 0xFF;
181 }
MyRead16(unsigned int a)182 static unsigned int MyRead16 (unsigned int a) {
183 unsigned int addr=a&0xFFFFF;
184 unsigned int b=((a&0xF0000)>>16);
185 //printf("read 32 %08x\n",a);
186 a&=0xFFFFFF;
187
188 switch((a&0xFF0000)>>20) {
189 case 0x0:
190 return (READ_WORD_ROM(memory.rom.cpu_m68k.p + addr))&0xFFFF;
191 break;
192 case 0x2:
193 if (memory.bksw_unscramble)
194 return mem68k_fetch_bk_normal_word(a);
195 return (READ_WORD_ROM(memory.rom.cpu_m68k.p + bankaddress + addr))&0xFFFF;
196
197 break;
198 case 0x1:
199 return (READ_WORD_ROM(memory.ram + (addr&0xFFFF)))&0xFFFF;
200 break;
201 case 0xC:
202 if (b<=1) return (READ_WORD_ROM(memory.rom.bios_m68k.p + addr))&0xFFFF;
203 break;
204
205 case 0xd:
206 if (b==0) return mem68k_fetch_sram_word(a)&0xFFFF;
207 break;
208 case 0x4:
209 if (b==0) return mem68k_fetch_pal_word(a)&0xFFFF;
210 break;
211 case 0x3:
212 if (b==0xC) return mem68k_fetch_video_word(a)&0xFFFF;
213 if (b==0) return mem68k_fetch_ctl1_word(a)&0xFFFF;
214 if (b==4) return mem68k_fetch_ctl2_word(a)&0xFFFF;
215 if (b==8) return mem68k_fetch_ctl3_word(a)&0xFFFF;
216 if (b==2) return mem68k_fetch_coin_word(a)&0xFFFF;
217 break;
218 case 0x8:
219 if (b==0) return mem68k_fetch_memcrd_word(a)&0xFFFF;
220 break;
221 }
222
223 return 0xF0F0;
224 }
MyRead32(unsigned int a)225 static unsigned int MyRead32 (unsigned int a) {
226 //int i;
227 unsigned int addr=a&0xFFFFF;
228 unsigned int b=((a&0xF0000)>>16);
229 a&=0xFFFFFF;
230
231 switch((a&0xFF0000)>>20) {
232 case 0x0:
233 //return mem68k_fetch_cpu_long(a);
234 return ((READ_WORD_ROM(memory.rom.cpu_m68k.p + addr))<<16) |
235 (READ_WORD_ROM(memory.rom.cpu_m68k.p + (addr+2)));
236 break;
237 case 0x2:
238 //return mem68k_fetch_bk_normal_long(a);
239 if (memory.bksw_unscramble)
240 return mem68k_fetch_bk_normal_long(a);
241 return ((READ_WORD_ROM(memory.rom.cpu_m68k.p + bankaddress + addr))<<16) |
242 (READ_WORD_ROM(memory.rom.cpu_m68k.p + bankaddress + (addr+2)));
243 break;
244 case 0x1:
245 //return mem68k_fetch_ram_long(a);
246 addr&=0xFFFF;
247 return ((READ_WORD_ROM(memory.ram + addr))<<16) |
248 (READ_WORD_ROM(memory.ram + (addr+2)));
249 break;
250 case 0xC:
251 //return mem68k_fetch_bios_long(a);
252 if (b<=1) return ((READ_WORD_ROM(memory.rom.bios_m68k.p + addr))<<16) |
253 (READ_WORD_ROM(memory.rom.bios_m68k.p + (addr+2)));
254 break;
255
256 case 0xd:
257 if (b==0) return mem68k_fetch_sram_long(a);
258 break;
259 case 0x4:
260 if (b==0) return mem68k_fetch_pal_long(a);
261 break;
262 case 0x3:
263 if (b==0xC) return mem68k_fetch_video_long(a);
264 if (b==0) return mem68k_fetch_ctl1_long(a);
265 if (b==4) return mem68k_fetch_ctl2_long(a);
266 if (b==8) return mem68k_fetch_ctl3_long(a);
267 if (b==2) return mem68k_fetch_coin_long(a);
268 break;
269 case 0x8:
270 if (b==0) return mem68k_fetch_memcrd_long(a);
271 break;
272 }
273
274 return 0xFF00FF00;
275 }
MyWrite8(unsigned int a,unsigned int d)276 static void MyWrite8 (unsigned int a,unsigned int d) {
277 unsigned int b=((a&0xF0000)>>16);
278 a&=0xFFFFFF;
279 d&=0xFF;
280 switch((a&0xFF0000)>>20) {
281 case 0x1:
282 WRITE_BYTE_ROM(memory.ram + (a&0xffff),d);
283 return ;
284 break;
285 case 0x3:
286 if (b==0xc) {mem68k_store_video_byte(a,d);return;}
287 if (b==8) {mem68k_store_pd4990_byte(a,d);return;}
288 if (b==2) {mem68k_store_z80_byte(a,d);return;}
289 if (b==0xA) {mem68k_store_setting_byte(a,d);return;}
290 break;
291 case 0x4:
292 if (b==0) mem68k_store_pal_byte(a,d);
293 return;
294 break;
295 case 0xD:
296 if (b==0) mem68k_store_sram_byte(a,d);return;
297 break;
298 case 0x2:
299 if (b==0xF) mem68k_store_bk_normal_byte(a,d);return;
300 break;
301 case 0x8:
302 if (b==0) mem68k_store_memcrd_byte(a,d);return;
303 break;
304
305 }
306
307 if(a==0x300001) memory.watchdog=0; // Watchdog
308
309 //printf("Unhandled write8 @ %08x = %02x\n",a,d);
310 }
MyWrite16(unsigned int a,unsigned int d)311 static void MyWrite16(unsigned int a,unsigned int d) {
312 unsigned int b=((a&0xF0000)>>16);
313 a&=0xFFFFFF;
314 d&=0xFFFF;
315 //if (d&0x8000) printf("WEIRD %x %x\n",a,d);
316
317 switch((a&0xFF0000)>>20) {
318 case 0x1:
319 WRITE_WORD_ROM(memory.ram + (a&0xffff),d);
320 return;
321 //mem68k_store_ram_word(a,d);return;
322 break;
323 case 0x3:
324 if (b==0xc) {
325 mem68k_store_video_word(a,d);return;}
326 if (b==8) {mem68k_store_pd4990_word(a,d);return;}
327 if (b==2) {mem68k_store_z80_word(a,d);return;}
328 if (b==0xA) {mem68k_store_setting_word(a,d);return;}
329 break;
330 case 0x4:
331 if (b==0) mem68k_store_pal_word(a,d);return;
332 break;
333 case 0xD:
334 if (b==0) mem68k_store_sram_word(a,d);return;
335 break;
336 case 0x2:
337 if (b==0xF) mem68k_store_bk_normal_word(a,d);return;
338 break;
339 case 0x8:
340 if (b==0) mem68k_store_memcrd_word(a,d);return;
341 break;
342 }
343
344 //printf("Unhandled write16 @ %08x = %04x\n",a,d);
345 }
MyWrite32(unsigned int a,unsigned int d)346 static void MyWrite32(unsigned int a,unsigned int d) {
347 unsigned int b=((a&0xF0000)>>16);
348 a&=0xFFFFFF;
349 d&=0xFFFFFFFF;
350 switch((a&0xFF0000)>>20) {
351 case 0x1:
352 WRITE_WORD_ROM(memory.ram + (a&0xffff),d>>16);
353 WRITE_WORD_ROM(memory.ram + (a&0xffff)+2,d&0xFFFF);
354 return;
355 break;
356 case 0x3:
357 if (b==0xc) {
358 mem68k_store_video_word(a,d>>16);
359 mem68k_store_video_word(a+2,d & 0xffff);
360 return;
361 }
362 if (b==8) {mem68k_store_pd4990_long(a,d);return;}
363 if (b==2) {mem68k_store_z80_long(a,d);return;}
364 if (b==0xA) {mem68k_store_setting_long(a,d);return;}
365 break;
366 case 0x4:
367 if (b==0) mem68k_store_pal_long(a,d);return;
368 break;
369 case 0xD:
370 if (b==0) mem68k_store_sram_long(a,d);return;
371 break;
372 case 0x2:
373 if (b==0xF) mem68k_store_bk_normal_long(a,d);return;
374 break;
375 case 0x8:
376 if (b==0) mem68k_store_memcrd_long(a,d);return;
377 break;
378 }
379
380 //printf("Unhandled write32 @ %08x = %08x\n",a,d);
381 }
382
cpu_68k_post_load_state(void)383 static void cpu_68k_post_load_state(void) {
384
385 MyCyclone.read8=MyRead8;
386 MyCyclone.read16=MyRead16;
387 MyCyclone.read32=MyRead32;
388
389 MyCyclone.write8=MyWrite8;
390 MyCyclone.write16=MyWrite16;
391 MyCyclone.write32=MyWrite32;
392
393 MyCyclone.checkpc=MyCheckPc;
394
395 MyCyclone.fetch8 =MyRead8;
396 MyCyclone.fetch16 =MyRead16;
397 MyCyclone.fetch32 =MyRead32;
398
399 cpu_68k_bankswitch(bankaddress);
400 MyCyclone.membase=0;
401 MyCyclone.pc=MyCheckPc(cyclone_pc);
402 //printf("Loaded PC=%08x\n",cyclone_pc);
403 }
404
cpu_68k_pre_save_state(void)405 static void cpu_68k_pre_save_state(void) {
406 cyclone_pc=MyCyclone.pc-MyCyclone.membase;
407 //printf("Saved PC=%08x\n",cyclone_pc);
408 }
409
cpu_68k_init_save_state(void)410 static void cpu_68k_init_save_state(void) {
411
412 create_state_register(ST_68k,"cyclone68k",1,(void *)&MyCyclone,sizeof(MyCyclone),REG_UINT8);
413 create_state_register(ST_68k,"pc",1,(void *)&cyclone_pc,sizeof(Uint32),REG_UINT32);
414 create_state_register(ST_68k,"bank",1,(void *)&bankaddress,sizeof(Uint32),REG_UINT32);
415 create_state_register(ST_68k,"ram",1,(void *)memory.ram,0x10000,REG_UINT8);
416 //create_state_register(ST_68k,"kof2003_bksw",1,(void *)memory.kof2003_bksw,0x1000,REG_UINT8);
417 create_state_register(ST_68k,"current_vector",1,(void *)memory.rom.cpu_m68k.p,0x80,REG_UINT8);
418 set_post_load_function(ST_68k,cpu_68k_post_load_state);
419 set_pre_save_function(ST_68k,cpu_68k_pre_save_state);
420
421 }
cpu_68k_mkstate(gzFile * gzf,int mode)422 void cpu_68k_mkstate(gzFile *gzf,int mode) {
423 printf("Save state mode %s PC=%08x\n",(mode==STREAD?"READ":"WRITE"),MyCyclone.pc-MyCyclone.membase);
424 if (mode==STWRITE) CyclonePack(&MyCyclone, save_buffer);
425 mkstate_data(gzf, save_buffer, 128, mode);
426 if (mode == STREAD) CycloneUnpack(&MyCyclone, save_buffer);
427 printf("Save state Phase 2 PC=%08x\n", (mode == STREAD ? "READ" : "WRITE"), MyCyclone.pc - MyCyclone.membase);
428 }
cpu_68k_getcycle(void)429 int cpu_68k_getcycle(void) {
430 return total_cycles-MyCyclone.cycles;
431 }
bankswitcher_init()432 void bankswitcher_init() {
433 bankaddress=0;
434 }
cyclone_debug(unsigned short o)435 int cyclone_debug(unsigned short o) {
436 printf("CYCLONE DEBUG %04x\n",o);
437 return 0;
438 }
439
cpu_68k_init(void)440 void cpu_68k_init(void) {
441 int overclk=CF_VAL(cf_get_item_by_name("68kclock"));
442 //printf("INIT \n");
443 CycloneInit();
444 memset(&MyCyclone, 0,sizeof(MyCyclone));
445 /*
446 swap_memory(memory.rom.cpu_m68k.p, memory.rom.cpu_m68k.size);
447 swap_memory(memory.rom.bios_m68k.p, memory.rom.bios_m68k.size);
448 swap_memory(memory.game_vector, 0x80);
449 */
450 MyCyclone.read8=MyRead8;
451 MyCyclone.read16=MyRead16;
452 MyCyclone.read32=MyRead32;
453
454 MyCyclone.write8=MyWrite8;
455 MyCyclone.write16=MyWrite16;
456 MyCyclone.write32=MyWrite32;
457
458 MyCyclone.checkpc=MyCheckPc;
459
460 MyCyclone.fetch8 =MyRead8;
461 MyCyclone.fetch16 =MyRead16;
462 MyCyclone.fetch32 =MyRead32;
463
464 //MyCyclone.InvalidOpCallback=cyclone_debug;
465 //MyCyclone.print_reg=print_one_reg;
466 bankswitcher_init();
467
468
469
470 if (memory.rom.cpu_m68k.size > 0x100000) {
471 bankaddress = 0x100000;
472 }
473 //cpu_68k_init_save_state();
474
475
476 time_slice=(overclk==0?
477 200000:200000+(overclk*200000/100.0))/262.0;
478 }
479
cpu_68k_reset(void)480 void cpu_68k_reset(void) {
481
482 //printf("Reset \n");
483 MyCyclone.srh=0x27; // Set supervisor mode
484 //CycloneSetSr(&MyCyclone,0x27);
485 //MyCyclone.srh=0x20;
486 //MyCyclone.irq=7;
487 MyCyclone.irq=0;
488 MyCyclone.a[7]=MyCyclone.read32(0);
489
490 MyCyclone.membase=0;
491 MyCyclone.pc=MyCyclone.checkpc(MyCyclone.read32(4)); // Get Program Counter
492
493 //printf("PC=%08x\n SP=%08x\n",MyCyclone.pc-MyCyclone.membase,MyCyclone.a[7]);
494 }
495
cpu_68k_run(Uint32 nb_cycle)496 int cpu_68k_run(Uint32 nb_cycle) {
497 Uint32 i;
498 if (conf.raster) {
499 total_cycles=nb_cycle;MyCyclone.cycles=nb_cycle;
500 CycloneRun(&MyCyclone);
501 return -MyCyclone.cycles;
502 } else {
503 #if 1
504 current_line=0;
505
506 total_cycles=nb_cycle;
507 //MyCyclone.cycles=nb_cycle;
508 MyCyclone.cycles=0;//time_slice;
509 for (i=0;i<261;i++) {
510 MyCyclone.cycles+=time_slice;
511 CycloneRun(&MyCyclone);
512 current_line++;
513 }
514 #else
515 total_cycles=nb_cycle;MyCyclone.cycles=nb_cycle;
516 CycloneRun(&MyCyclone);
517 #endif
518 return -MyCyclone.cycles;
519 }
520 //return 0;
521 }
522
cpu_68k_interrupt(int a)523 void cpu_68k_interrupt(int a) {
524 //printf("Interrupt %d\n",a);
525 MyCyclone.irq=a;
526 }
527
cpu_68k_bankswitch(Uint32 address)528 void cpu_68k_bankswitch(Uint32 address) {
529 //printf("Bankswitch %08x\n",address);
530 bankaddress = address;
531 }
532
cpu_68k_disassemble(int pc,int nb_instr)533 void cpu_68k_disassemble(int pc, int nb_instr) {
534 /* TODO */
535 }
536
cpu_68k_dumpreg(void)537 void cpu_68k_dumpreg(void) {
538 int i;
539 for(i=0;i<8;i++) printf(" d%d=%08x a%d=%08x\n",i,MyCyclone.d[i],i,MyCyclone.a[i]);
540 /*printf("stack:\n");
541 for (i=0;i<10;i++) {
542 printf("%02d - %08x\n",i,mem68k_fetch_ram_long(MyCyclone.a[7]+i*4));
543 }*/
544
545 }
546
cpu_68k_run_step(void)547 int cpu_68k_run_step(void) {
548 MyCyclone.cycles=0;
549 CycloneRun(&MyCyclone);
550 return -MyCyclone.cycles;
551 }
552
cpu_68k_getpc(void)553 Uint32 cpu_68k_getpc(void) {
554 return MyCyclone.pc-MyCyclone.membase;
555 }
556
cpu_68k_fill_state(M68K_STATE * st)557 void cpu_68k_fill_state(M68K_STATE *st) {
558 }
559
560
cpu_68k_set_state(M68K_STATE * st)561 void cpu_68k_set_state(M68K_STATE *st) {
562 }
563
cpu_68k_debuger(void (* execstep)(void),void (* dump)(void))564 int cpu_68k_debuger(void (*execstep)(void),void (*dump)(void)) {
565 /* TODO */
566 return 0;
567 }
568
569
570
571 #endif
572