1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17 /***************************************************************************/
18 /* */
19 /* HARDware PCEngine */
20 /* */
21 /* This source file implements all functions relatives to pc engine inner */
22 /* hardware (memory access e.g.) */
23 /* */
24 /***************************************************************************/
25
26 #include "utils.h"
27 #include "hard_pce.h"
28 #include "pce.h"
29 #if defined(BSD_CD_HARDWARE_SUPPORT)
30 #include "pcecd.h"
31 #else
32 // nothing yet on purpose
33 #endif
34
35 /**
36 * Variables declaration
37 * cf explanations in the header file
38 **/
39
40 struct_hard_pce *hard_pce;
41
42 UChar *RAM;
43
44 // Video
45 UInt16 *SPRAM;
46 UChar *VRAM2;
47 UChar *VRAMS;
48 UChar *Pal;
49 UChar *vchange;
50 UChar *vchanges;
51 UChar *WRAM;
52 UChar *VRAM;
53 UInt32 *p_scanline;
54
55 // Audio
56 UChar *PCM;
57
58 // I/O
59 IO *p_io;
60
61 // CD
62 /**/ UChar * cd_read_buffer;
63 UChar *cd_sector_buffer;
64 UChar *cd_extra_mem;
65 UChar *cd_extra_super_mem;
66 UChar *ac_extra_mem;
67
68 UInt32 pce_cd_read_datacnt;
69 /**/ UChar cd_sectorcnt;
70 UChar pce_cd_curcmd;
71 /**/
72 // Memory
73 UChar *zp_base;
74 UChar *sp_base;
75 UChar *mmr;
76 UChar *IOAREA;
77
78 // Interruption
79 UInt32 *p_cyclecount;
80 UInt32 *p_cyclecountold;
81
82 const UInt32 TimerPeriod = 1097;
83
84 // registers
85
86 #if defined(SHARED_MEMORY)
87
88 //! Shared memory handle
89 static int shm_handle;
90
91 UInt16 *p_reg_pc;
92 UChar *p_reg_a;
93 UChar *p_reg_x;
94 UChar *p_reg_y;
95 UChar *p_reg_p;
96 UChar *p_reg_s;
97
98 #else
99
100 UInt16 reg_pc;
101 UChar reg_a;
102 UChar reg_x;
103 UChar reg_y;
104 UChar reg_p;
105 UChar reg_s;
106
107 #endif
108
109 // Mapping
110 UChar *PageR[8];
111 UChar *ROMMapR[256];
112
113 UChar *PageW[8];
114 UChar *ROMMapW[256];
115
116 UChar* trap_ram_read;
117 UChar* trap_ram_write;
118
119 // Miscellaneous
120 UInt32 *p_cycles;
121 SInt32 *p_external_control_cpu;
122
123 //! External rom size hack for shared memory indication
124 extern int ROM_size;
125
126 /**
127 * Predeclaration of access functions
128 **/
129 UChar read_memory_simple(UInt16);
130 UChar read_memory_sf2(UInt16);
131 UChar read_memory_arcade_card(UInt16);
132
133 void write_memory_simple(UInt16,UChar);
134 void write_memory_arcade_card(UInt16,UChar);
135
136
137
138 //! Function to write into memory. Defaulted to the basic one
139 void (*write_memory_function)(UInt16,UChar) = write_memory_simple;
140
141 //! Function to read from memory. Defaulted to the basic one
142 UChar (*read_memory_function)(UInt16) = read_memory_simple;
143
144 /**
145 * Initialize the hardware
146 **/
147 void
hard_init(void)148 hard_init (void)
149 {
150
151 trap_ram_read = malloc(0x2000);
152 trap_ram_write = malloc(0x2000);
153
154 if ((trap_ram_read == NULL) || (trap_ram_write == NULL))
155 fprintf(stderr, "Couldn't allocate trap_ram* (%s:%d)", __FILE__, __LINE__);
156
157 #if defined(SHARED_MEMORY)
158 shm_handle =
159 shmget ((key_t) SHM_HANDLE, sizeof (struct_hard_pce),
160 IPC_CREAT | IPC_EXCL | 0666);
161 if (shm_handle == -1)
162 fprintf (stderr, "Couldn't get shared memory\n");
163 else
164 {
165 hard_pce = (struct_hard_pce *) shmat (shm_handle, NULL, 0);
166 if (hard_pce == NULL)
167 fprintf (stderr, "Couldn't attach shared memory\n");
168
169 p_reg_pc = &hard_pce->s_reg_pc;
170 p_reg_a = &hard_pce->s_reg_a;
171 p_reg_x = &hard_pce->s_reg_x;
172 p_reg_y = &hard_pce->s_reg_y;
173 p_reg_p = &hard_pce->s_reg_p;
174 p_reg_s = &hard_pce->s_reg_s;
175 p_external_control_cpu = &hard_pce->s_external_control_cpu;
176
177 }
178 #else
179 hard_pce = (struct_hard_pce *) malloc(sizeof(struct_hard_pce));
180 #endif
181
182 memset(hard_pce, 0, sizeof(struct_hard_pce));
183
184 RAM = hard_pce->RAM;
185 PCM = hard_pce->PCM;
186 WRAM = hard_pce->WRAM;
187 VRAM = hard_pce->VRAM;
188 VRAM2 = hard_pce->VRAM2;
189 VRAMS = (UChar*)hard_pce->VRAMS;
190 vchange = hard_pce->vchange;
191 vchanges = hard_pce->vchanges;
192
193 cd_extra_mem = hard_pce->cd_extra_mem;
194 cd_extra_super_mem = hard_pce->cd_extra_super_mem;
195 ac_extra_mem = hard_pce->ac_extra_mem;
196 cd_sector_buffer = hard_pce->cd_sector_buffer;
197
198 SPRAM = hard_pce->SPRAM;
199 Pal = hard_pce->Pal;
200
201 p_scanline = &hard_pce->s_scanline;
202
203 p_cyclecount = &hard_pce->s_cyclecount;
204 p_cyclecountold = &hard_pce->s_cyclecountold;
205
206 p_cycles = &hard_pce->s_cycles;
207
208 mmr = hard_pce->mmr;
209
210 p_io = &hard_pce->s_io;
211
212 #if defined(SHARED_MEMORY)
213 /* Add debug on beginning option by setting 0 here */
214 external_control_cpu = -1;
215
216 hard_pce->rom_shared_memory_size = 0x2000 * ROM_size;
217
218 #endif
219
220 if ((option.want_arcade_card_emulation) && (CD_emulation > 0))
221 {
222 read_memory_function = read_memory_arcade_card;
223 write_memory_function = write_memory_arcade_card;
224 }
225 else
226 {
227 read_memory_function = read_memory_simple;
228 write_memory_function = write_memory_simple;
229 }
230 }
231
232 /**
233 * Terminate the hardware
234 **/
235 void
hard_term(void)236 hard_term (void)
237 {
238 #if defined(SHARED_MEMORY)
239 if (shmctl (shm_handle, IPC_RMID, NULL) == -1)
240 fprintf (stderr, "Couldn't destroy shared memory\n");
241 #else
242 free(hard_pce);
243 #endif
244 free(trap_ram_read);
245 free(trap_ram_write);
246 }
247
248 /**
249 * Functions to access PCE hardware
250 **/
251
252 int return_value_mask_tab_0002[32] =
253 {
254 0xFF,
255 0xFF,
256 0xFF,
257 0xFF, /* unused */
258 0xFF, /* unused */
259 0xFF,
260 0xFF,
261 0xFF,
262 0xFF, /* 8 */
263 0xFF,
264 0x1F, /* A */
265 0x7F,
266 0x1F, /* C */
267 0xFF,
268 0xFF, /* E */
269 0x1F,
270 0xFF, /* 10 */
271 0xFF,
272 /* No data for remaining reg, assuming 0xFF */
273 0xFF,
274 0xFF,
275 0xFF,
276 0xFF,
277 0xFF,
278 0xFF,
279 0xFF,
280 0xFF,
281 0xFF,
282 0xFF,
283 0xFF,
284 0xFF,
285 0xFF,
286 0xFF
287 };
288
289 int return_value_mask_tab_0003[32] =
290 {
291 0xFF,
292 0xFF,
293 0xFF,
294 0xFF, /* unused */
295 0xFF, /* unused */
296 0x1F,
297 0x03,
298 0x03,
299 0x01, /* 8 */ /* ?? */
300 0x00,
301 0x7F, /* A */
302 0x7F,
303 0xFF, /* C */
304 0x01,
305 0x00, /* E */
306 0x00,
307 0xFF, /* 10 */
308 0xFF,
309 /* No data for remaining reg, assuming 0xFF */
310 0xFF,
311 0xFF,
312 0xFF,
313 0xFF,
314 0xFF,
315 0xFF,
316 0xFF,
317 0xFF,
318 0xFF,
319 0xFF,
320 0xFF,
321 0xFF,
322 0xFF,
323 0xFF
324 };
325
326
327 int return_value_mask_tab_0400[8] =
328 {
329 0xFF,
330 0x00,
331 0xFF,
332 0x01,
333 0xFF,
334 0x01,
335 0xFF, /* unused */
336 0xFF /* unused */
337 };
338
339 int return_value_mask_tab_0800[16] =
340 {
341 0x03,
342 0xFF,
343 0xFF,
344 0x0F,
345 0xDF,
346 0xFF,
347 0x1F,
348 0x9F,
349 0xFF,
350 0x83,
351 /* No data for remainig reg, assuming 0xFF */
352 0xFF,
353 0xFF,
354 0xFF,
355 0xFF,
356 0xFF,
357 0xFF
358 };
359
360 int return_value_mask_tab_0c00[2] =
361 {
362 0x7F,
363 0x01
364 };
365
366 int return_value_mask_tab_1400[4] =
367 {
368 0xFF,
369 0xFF,
370 0x03,
371 0x03
372 };
373
374
375 //! Returns the useful value mask depending on port value
376 static int
return_value_mask(UInt16 A)377 return_value_mask(UInt16 A)
378 {
379 if (A < 0x400) // VDC
380 {
381 if ((A & 0x3) == 0x02)
382 {
383 return return_value_mask_tab_0002[io.vdc_reg];
384 }
385 else
386 if ((A & 0x3) == 0x03)
387 {
388 return return_value_mask_tab_0003[io.vdc_reg];
389 }
390 else
391 return 0xFF;
392 }
393
394 if (A < 0x800) // VCE
395 return return_value_mask_tab_0400[A & 0x07];
396
397 if (A < 0xC00) /* PSG */
398 return return_value_mask_tab_0800[A & 0x0F];
399
400 if (A < 0x1000) /* Timer */
401 return return_value_mask_tab_0c00[A & 0x01];
402
403 if (A < 0x1400) /* Joystick / IO port */
404 return 0xFF;
405
406 if (A < 0x1800) /* Interruption acknowledgement */
407 return return_value_mask_tab_1400[A & 0x03];
408
409 /* We don't know for higher ports */
410 return 0xFF;
411 }
412
413 /* read */
414 UChar
IO_read_raw(UInt16 A)415 IO_read_raw (UInt16 A)
416 {
417 UChar ret;
418
419 #ifndef FINAL_RELEASE
420 if ((A & 0x1F00) == 0x1A00)
421 Log ("AC Read at %04x\n", A);
422 #endif
423
424 switch (A & 0x1FC0)
425 {
426 case 0x0000: /* VDC */
427 switch (A & 3)
428 {
429 case 0:
430 #if defined(GFX_DEBUG)
431 gfx_debug_printf("Returning vdc_status = 0x%02x", io.vdc_status);
432 #endif
433 ret = io.vdc_status;
434 io.vdc_status = 0; //&=VDC_InVBlank;//&=~VDC_BSY;
435 #if defined(GFX_DEBUG)
436 Log("$0000 returns %02X\n", ret);
437 #endif
438 return ret;
439 case 1:
440 return 0;
441 case 2:
442 if (io.vdc_reg == VRR)
443 return VRAM[io.VDC[MARR].W * 2];
444 else
445 return io.VDC[io.vdc_reg].B.l;
446 case 3:
447 if (io.vdc_reg == VRR)
448 {
449 ret = VRAM[io.VDC[MARR].W * 2 + 1];
450 io.VDC[MARR].W += io.vdc_inc;
451 return ret;
452 }
453 else
454 return io.VDC[io.vdc_reg].B.h;
455 }
456 break;
457
458 case 0x0400: /* VCE */
459 switch (A & 7)
460 {
461 case 4:
462 return io.VCE[io.vce_reg.W].B.l;
463 case 5:
464 return io.VCE[io.vce_reg.W++].B.h;
465 }
466 break;
467 case 0x0800: /* PSG */
468 switch (A & 15)
469 {
470 case 0:
471 return io.psg_ch;
472 case 1:
473 return io.psg_volume;
474 case 2:
475 return io.PSG[io.psg_ch][2];
476 case 3:
477 return io.PSG[io.psg_ch][3];
478 case 4:
479 return io.PSG[io.psg_ch][4];
480 case 5:
481 return io.PSG[io.psg_ch][5];
482 case 6:
483 {
484 int ofs = io.PSG[io.psg_ch][PSG_DATA_INDEX_REG];
485 io.PSG[io.psg_ch][PSG_DATA_INDEX_REG] = (UChar)((io.PSG[io.psg_ch][PSG_DATA_INDEX_REG] + 1) & 31);
486 return io.wave[io.psg_ch][ofs];
487 }
488 case 7:
489 return io.PSG[io.psg_ch][7];
490
491 case 8:
492 return io.psg_lfo_freq;
493 case 9:
494 return io.psg_lfo_ctrl;
495 default:
496 return NODATA;
497 }
498 break;
499 case 0x0c00: /* timer */
500 return io.timer_counter;
501
502 case 0x1000: /* joypad */
503 ret = io.JOY[io.joy_counter] ^ 0xff;
504 if (io.joy_select & 1)
505 ret >>= 4;
506 else
507 {
508 ret &= 15;
509 io.joy_counter = (UChar)((io.joy_counter + 1) % 5);
510 }
511
512 /* return ret | Country; *//* country 0:JPN 1<<6=US */
513 return ret | 0x30; // those 2 bits are always on, bit 6 = 0 (Jap), bit 7 = 0 (Attached cd)
514
515 case 0x1400: /* IRQ */
516 switch (A & 15)
517 {
518 case 2:
519 return io.irq_mask;
520 case 3:
521 ret = io.irq_status;
522 io.irq_status = 0;
523 return ret;
524 }
525 break;
526
527
528 case 0x18C0: // Memory management ?
529 switch (A & 15)
530 {
531 case 5:
532 case 1:
533 return 0xAA;
534 case 2:
535 case 6:
536 return 0x55;
537 case 3:
538 case 7:
539 return 0x03;
540 }
541 break;
542
543 case 0x1AC0:
544 switch (A & 15)
545 {
546 case 0:
547 return (UChar) (io.ac_shift);
548 case 1:
549 return (UChar) (io.ac_shift >> 8);
550 case 2:
551 return (UChar) (io.ac_shift >> 16);
552 case 3:
553 return (UChar) (io.ac_shift >> 24);
554 case 4:
555 return io.ac_shiftbits;
556 case 5:
557 return io.ac_unknown4;
558 case 14:
559 return (UChar)(option.want_arcade_card_emulation ? 0x10 : NODATA);
560 case 15:
561 return (UChar)(option.want_arcade_card_emulation ? 0x51 : NODATA);
562 default:
563 Log ("Unknown Arcade card port access : 0x%04X\n", A);
564 }
565 break;
566
567 case 0x1A00:
568 {
569 UChar ac_port = (UChar)((A >> 4) & 3);
570 switch (A & 15)
571 {
572 case 0:
573 case 1:
574 /*
575 * switch (io.ac_control[ac_port] & (AC_USE_OFFSET | AC_USE_BASE))
576 * {
577 * case 0:
578 * return ac_extra_mem[0];
579 * case AC_USE_OFFSET:
580 * ret = ac_extra_mem[io.ac_offset[ac_port]];
581 * if (!(io.ac_control[ac_port] & AC_INCREMENT_BASE))
582 * io.ac_offset[ac_port]+=io.ac_incr[ac_port];
583 * return ret;
584 * case AC_USE_BASE:
585 * ret = ac_extra_mem[io.ac_base[ac_port]];
586 * if (io.ac_control[ac_port] & AC_INCREMENT_BASE)
587 * io.ac_base[ac_port]+=io.ac_incr[ac_port];
588 * return ret;
589 * default:
590 * ret = ac_extra_mem[io.ac_base[ac_port] + io.ac_offset[ac_port]];
591 * if (io.ac_control[ac_port] & AC_INCREMENT_BASE)
592 * io.ac_base[ac_port]+=io.ac_incr[ac_port];
593 * else
594 * io.ac_offset[ac_port]+=io.ac_incr[ac_port];
595 * return ret;
596 * }
597 * return 0;
598 */
599
600
601 #if defined(CD_DEBUG) && !defined(FINAL_RELEASE)
602 printf("Reading from AC main port. ac_port = %d. %suse offset. %sincrement. %sincrement base\n",
603 ac_port,
604 io.ac_control[ac_port] & AC_USE_OFFSET ? "": "not ",
605 io.ac_control[ac_port] & AC_ENABLE_INC ? "": "not ",
606 io.ac_control[ac_port] & AC_INCREMENT_BASE ? "" : "not ");
607 #endif
608 if (io.ac_control[ac_port] & AC_USE_OFFSET)
609 ret = ac_extra_mem[((io.ac_base[ac_port] +
610 io.
611 ac_offset[ac_port]) &
612 0x1fffff)];
613 else
614 ret = ac_extra_mem[((io.
615 ac_base[ac_port]) &
616 0x1fffff)];
617
618 if (io.ac_control[ac_port] & AC_ENABLE_INC)
619 {
620 if (io.
621 ac_control[ac_port] & AC_INCREMENT_BASE)
622 io.ac_base[ac_port] =
623 (io.ac_base[ac_port] +
624 io.
625 ac_incr[ac_port]) & 0xffffff;
626 else
627 io.ac_offset[ac_port] = (UInt16)
628 ((io.ac_offset[ac_port] +
629 io.
630 ac_incr[ac_port]) & 0xffff);
631 }
632
633 #if defined(CD_DEBUG) && !defined(FINAL_RELEASE)
634 printf("Returned 0x%02x. now, base = 0x%x. offset = 0x%x, increment = 0x%x\n", ret, io.ac_base[ac_port], io.ac_offset[ac_port], io.ac_incr[ac_port]);
635 #endif
636 return ret;
637
638
639 case 2:
640 return (UChar) (io.ac_base[ac_port]);
641 case 3:
642 return (UChar) (io.ac_base[ac_port] >> 8);
643 case 4:
644 return (UChar) (io.ac_base[ac_port] >> 16);
645 case 5:
646 return (UChar) (io.ac_offset[ac_port]);
647 case 6:
648 return (UChar) (io.ac_offset[ac_port] >> 8);
649 case 7:
650 return (UChar) (io.ac_incr[ac_port]);
651 case 8:
652 return (UChar) (io.ac_incr[ac_port] >> 8);
653 case 9:
654 return io.ac_control[ac_port];
655 default:
656 Log ("Unknown Arcade card port access : 0x%04X\n", A);
657 }
658 break;
659 }
660 case 0x1800: // CD-ROM extention
661 #if defined(BSD_CD_HARDWARE_SUPPORT)
662 return pce_cd_handle_read_1800(A);
663 #else
664 return gpl_pce_cd_handle_read_1800(A);
665 #endif
666 }
667 #ifndef FINAL_RELEASE
668 #if !defined(KERNEL_DS)
669 fprintf (stderr, "ignore I/O read %04X\nat PC = %04X\n", A, M.PC.W);
670 #endif
671 #endif
672 return NODATA;
673 }
674
675 //! Adds the io_buffer feature
IO_read(UInt16 A)676 UChar IO_read (UInt16 A)
677 {
678 int mask;
679 UChar temporary_return_value;
680
681 if ((A < 0x800) || (A >= 0x1800)) // latch isn't affected out of the 0x800 - 0x1800 range
682 return IO_read_raw(A);
683
684 mask = return_value_mask(A);
685
686 temporary_return_value = IO_read_raw(A);
687
688 io.io_buffer = temporary_return_value | (io.io_buffer & ~mask);
689
690 return io.io_buffer;
691 }
692
693 #if defined(TEST_ROM_RELOCATED)
694 extern UChar* ROM;
695 #endif
696
697 /**
698 * Change bank setting
699 **/
700 void
bank_set(UChar P,UChar V)701 bank_set (UChar P, UChar V)
702 {
703
704 #if defined(CD_DEBUG)
705 if (V >= 0x40 && V <= 0x43)
706 printf("AC pseudo bank switching !!! (mmr[%d] = %d)\n", P, V);
707 #endif
708
709 #if defined(TEST_ROM_RELOCATED)
710 if ((P >= 2) && ((V < 0x68) || (V >= 0x88)))
711 {
712 int physical_bank = mmr[reg_pc >> 13];
713 if (physical_bank >= 0x68)
714 physical_bank -= 0x68;
715 printf("Relocation error PC = 0x%04x (logical bank 0x%0x(0x%02x), physical bank 0x%0x(0x%02x), offset 0x%04x, global offset 0x%x)\nBank %x into MMR %d\nPatching into BRK\n",
716 reg_pc,
717 mmr[reg_pc >> 13],
718 mmr[reg_pc >> 13],
719 physical_bank,
720 physical_bank,
721 reg_pc & 0x1FFF,
722 physical_bank * 0x2000 + (reg_pc & 0x1FFF),
723 V,
724 P
725 );
726 if (V >= 0x80) {
727 printf("Not a physical bank, aborting patching\n");
728 } else {
729 V += 0x68;
730 patch_rom(cart_name, physical_bank * 0x2000 + (reg_pc & 0x1FFF), 0);
731 ROM[physical_bank * 0x2000 + (reg_pc & 0x1FFF)] = 0;
732 }
733 }
734 fprintf(stderr, "Bank set MMR[%d]=%02x at %04x\n", P, V, reg_pc);
735 #endif
736
737 mmr[P] = V;
738 if (ROMMapR[V] == IOAREA)
739 {
740 PageR[P] = IOAREA;
741 PageW[P] = IOAREA;
742 }
743 else
744 {
745 PageR[P] = ROMMapR[V] - P * 0x2000;
746 PageW[P] = ROMMapW[V] - P * 0x2000;
747 }
748 }
749
write_memory_simple(UInt16 A,UChar V)750 void write_memory_simple(UInt16 A, UChar V)
751 {
752 if (PageW[A >> 13] == IOAREA)
753 IO_write (A, V);
754 else
755 PageW[A >> 13][A] = V;
756 }
757
write_memory_sf2(UInt16 A,UChar V)758 void write_memory_sf2(UInt16 A, UChar V)
759 {
760 if (PageW[A >> 13] == IOAREA)
761 IO_write (A, V);
762 else
763 /* support for SF2CE silliness */
764 if ((A & 0x1ffc) == 0x1ff0)
765 {
766 int i;
767
768 ROMMapR[0x40] = ROMMapR[0] + 0x80000;
769 ROMMapR[0x40] += (A & 3) * 0x80000;
770
771 for (i = 0x41; i <= 0x7f; i++)
772 {
773 ROMMapR[i] = ROMMapR[i - 1] + 0x2000;
774 // This could be slightly sped up by setting a fixed RAMMapW
775 ROMMapW[i] = ROMMapW[i - 1] + 0x2000;
776 }
777 }
778 else
779 PageW[A >> 13][A] = V;
780 }
781
write_memory_arcade_card(UInt16 A,UChar V)782 void write_memory_arcade_card(UInt16 A, UChar V)
783 {
784 if ((mmr[A >> 13] >= 0x40) && (mmr[A >> 13] <= 0x43))
785 {
786 /*
787 #if defined(CD_DEBUG)
788 fprintf(stderr, "writing 0x%02x to AC pseudo bank (%d)\n", V, mmr[A >> 13] - 0x40);
789 #endif
790 */
791 IO_write((UInt16)(0x1A00 + ((mmr[A >> 13] - 0x40) << 4)), V);
792 }
793 else
794 if (PageW[A >> 13] == IOAREA)
795 IO_write (A, V);
796 else
797 PageW[A >> 13][A] = V;
798 }
799
read_memory_simple(UInt16 A)800 UChar read_memory_simple(UInt16 A)
801 {
802 if (PageR[A >> 13] != IOAREA)
803 return PageR[A >> 13][A];
804 else
805 return IO_read (A);
806 }
807
read_memory_arcade_card(UInt16 A)808 UChar read_memory_arcade_card(UInt16 A)
809 {
810 if ((mmr[A >> 13] >= 0x40) && (mmr[A >> 13] <= 0x43))
811 {
812 /*
813 #if defined(CD_DEBUG)
814 fprintf(stderr, "reading AC pseudo bank (%d)\n", mmr[A >> 13] - 0x40);
815 #endif
816 */
817 return IO_read((UInt16)(0x1A00 + ((mmr[A >> 13] - 0x40) << 4)));
818 }
819 else
820 if (PageR[A >> 13] != IOAREA)
821 return PageR[A >> 13][A];
822 else
823 return IO_read (A);
824 }
825
826 static char opcode_long_buffer[256];
827 static UInt16 opcode_long_position;
828
get_opcode_long()829 char * get_opcode_long()
830 {
831 //! size of data used by the current opcode
832 int size;
833
834 unsigned char opcode;
835
836 //! Buffer of opcode data, maximum is 7 (for xfer opcodes)
837 unsigned char opbuf[7];
838
839 int i;
840
841 opcode = Rd6502(opcode_long_position);
842
843 size = addr_info_debug[optable_debug[opcode].addr_mode].size;
844
845 opbuf[0] = opcode;
846 opcode_long_position++;
847 for (i = 1; i < size; i++)
848 opbuf[i] = Rd6502 (opcode_long_position++);
849
850 /* This line is the real 'meat' of the disassembler: */
851
852 (*addr_info_debug[optable_debug[opcode].addr_mode].func) /* function */
853 (opcode_long_buffer, opcode_long_position - size, opbuf, optable_debug[opcode].opname); /* parm's passed */
854
855 return opcode_long_buffer;
856
857 }
858
859
dump_pce_cpu_environment()860 void dump_pce_cpu_environment() {
861
862 int i;
863
864 Log("Dumping PCE cpu environement\n");
865
866 Log("PC = 0x%04x\n", reg_pc);
867 Log("A = 0x%02x\n", reg_a);
868 Log("X = 0x%02x\n", reg_x);
869 Log("Y = 0x%02x\n", reg_y);
870 Log("P = 0x%02x\n", reg_p);
871 Log("S = 0x%02x\n", reg_s);
872
873 for (i = 0; i < 8; i++)
874 {
875 Log("MMR[%d] = 0x%02x\n", i, mmr[i]);
876 }
877
878 opcode_long_position = reg_pc & 0xE000;
879
880 while (opcode_long_position <= reg_pc)
881 {
882 Log("%04X: %s\n", opcode_long_position, get_opcode_long());
883 }
884
885 Log("--------------------------------------------------------\n");
886
887 }
888