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