2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
49 //#define __memcheck__
52 extern uint16 mem_check;
54 INLINE uint8 S9xGetByte (uint32 Address)
58 sprintf(str,"rd @ %04X",Address);
62 mem_check+=(Address>>16)+Address;
64 #if defined(VAR_CYCLES) || defined(CPU_SHUTDOWN)
66 uint8 *GetAddress = Memory.Map [block = (Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
68 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
70 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
73 CPU.Cycles += Memory.MemorySpeed [block];
76 if (Memory.BlockIsRAM [block])
77 CPU.WaitAddress = CPU.PCAtOpcodeStart;
79 return (*(GetAddress + (Address & 0xffff)));
82 switch ((int) GetAddress)
84 case CMemory::MAP_PPU:
87 CPU.Cycles += ONE_CYCLE;
89 return (S9xGetPPU (Address & 0xffff));
90 case CMemory::MAP_CPU:
92 CPU.Cycles += ONE_CYCLE;
94 return (S9xGetCPU (Address & 0xffff));
95 case CMemory::MAP_DSP:
97 CPU.Cycles += SLOW_ONE_CYCLE;
99 return (S9xGetDSP (Address & 0xffff));
100 case CMemory::MAP_SA1RAM:
101 case CMemory::MAP_LOROM_SRAM:
103 CPU.Cycles += SLOW_ONE_CYCLE;
105 return (*(Memory.SRAM + ((Address & CPU.Memory_SRAMMask))));
107 case CMemory::MAP_HIROM_SRAM:
109 CPU.Cycles += SLOW_ONE_CYCLE;
111 return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 +
112 ((Address & 0xf0000) >> 3)) & CPU.Memory_SRAMMask)));
114 case CMemory::MAP_DEBUG:
116 printf ("R(B) %06x\n", Address);
119 case CMemory::MAP_BWRAM:
121 CPU.Cycles += SLOW_ONE_CYCLE;
123 return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)));
125 case CMemory::MAP_C4:
126 return (S9xGetC4 (Address & 0xffff));
129 case CMemory::MAP_NONE:
131 CPU.Cycles += SLOW_ONE_CYCLE;
134 printf ("R(B) %06x\n", Address);
136 return ((Address >> 8) & 0xff);
140 INLINE uint16 S9xGetWord (uint32 Address)
144 sprintf(str,"rd @ %04X",Address);
148 mem_check+=(Address>>16)+Address;
150 if ((Address & 0x1fff) == 0x1fff)
152 return (S9xGetByte (Address) | (S9xGetByte (Address + 1) << 8));
154 #if defined(VAR_CYCLES) || defined(CPU_SHUTDOWN)
156 uint8 *GetAddress = Memory.Map [block = (Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
158 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
160 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
163 CPU.Cycles += Memory.MemorySpeed [block] << 1;
166 if (Memory.BlockIsRAM [block])
167 CPU.WaitAddress = CPU.PCAtOpcodeStart;
169 #ifdef FAST_LSB_WORD_ACCESS
170 return (*(uint16 *) (GetAddress + (Address & 0xffff)));
172 return (*(GetAddress + (Address & 0xffff)) |
173 (*(GetAddress + (Address & 0xffff) + 1) << 8));
177 switch ((int) GetAddress)
179 case CMemory::MAP_PPU:
182 CPU.Cycles += TWO_CYCLES;
184 return (S9xGetPPU (Address & 0xffff) |
185 (S9xGetPPU ((Address + 1) & 0xffff) << 8));
186 case CMemory::MAP_CPU:
188 CPU.Cycles += TWO_CYCLES;
190 return (S9xGetCPU (Address & 0xffff) |
191 (S9xGetCPU ((Address + 1) & 0xffff) << 8));
192 case CMemory::MAP_DSP:
194 CPU.Cycles += SLOW_ONE_CYCLE * 2;
196 return (S9xGetDSP (Address & 0xffff) |
197 (S9xGetDSP ((Address + 1) & 0xffff) << 8));
198 case CMemory::MAP_SA1RAM:
199 case CMemory::MAP_LOROM_SRAM:
201 CPU.Cycles += SLOW_ONE_CYCLE * 2;
203 return (*(Memory.SRAM + (Address & CPU.Memory_SRAMMask)) |
204 (*(Memory.SRAM + ((Address + 1) & CPU.Memory_SRAMMask)) << 8));
206 case CMemory::MAP_HIROM_SRAM:
208 CPU.Cycles += SLOW_ONE_CYCLE * 2;
210 return (*(Memory.SRAM +
211 (((Address & 0x7fff) - 0x6000 +
212 ((Address & 0xf0000) >> 3)) & CPU.Memory_SRAMMask)) |
214 ((((Address + 1) & 0x7fff) - 0x6000 +
215 (((Address + 1) & 0xf0000) >> 3)) & CPU.Memory_SRAMMask)) << 8));
217 case CMemory::MAP_BWRAM:
219 CPU.Cycles += SLOW_ONE_CYCLE * 2;
221 return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) |
222 (*(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) << 8));
224 case CMemory::MAP_DEBUG:
226 printf ("R(W) %06x\n", Address);
229 case CMemory::MAP_C4:
230 return (S9xGetC4 (Address & 0xffff) |
231 (S9xGetC4 ((Address + 1) & 0xffff) << 8));
234 case CMemory::MAP_NONE:
236 CPU.Cycles += SLOW_ONE_CYCLE * 2;
239 printf ("R(W) %06x\n", Address);
241 return (((Address >> 8) | (Address & 0xff00)) & 0xffff);
245 INLINE void S9xSetByte (uint8 Byte, uint32 Address)
249 sprintf(str,"wr @ %04X %02X",Address,Byte);
256 #if defined(CPU_SHUTDOWN)
257 CPU.WaitAddress = NULL;
259 #if defined(VAR_CYCLES)
261 uint8 *SetAddress = Memory.WriteMap [block = ((Address >> MEMMAP_SHIFT) & MEMMAP_MASK)];
263 uint8 *SetAddress = Memory.WriteMap [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
266 if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
269 CPU.Cycles += Memory.MemorySpeed [block];
272 SetAddress += Address & 0xffff;
274 if (SetAddress == SA1.WaitByteAddress1 ||
275 SetAddress == SA1.WaitByteAddress2)
277 SA1.Executing = SA1.S9xOpcodes != NULL;
283 *(SetAddress + (Address & 0xffff)) = Byte;
288 switch ((int) SetAddress)
290 case CMemory::MAP_PPU:
293 CPU.Cycles += ONE_CYCLE;
295 S9xSetPPU (Byte, Address & 0xffff);
298 case CMemory::MAP_CPU:
300 CPU.Cycles += ONE_CYCLE;
302 S9xSetCPU (Byte, Address & 0xffff);
305 case CMemory::MAP_DSP:
307 CPU.Cycles += SLOW_ONE_CYCLE;
309 S9xSetDSP (Byte, Address & 0xffff);
312 case CMemory::MAP_LOROM_SRAM:
314 CPU.Cycles += SLOW_ONE_CYCLE;
316 if (CPU.Memory_SRAMMask)
318 *(Memory.SRAM + (Address & CPU.Memory_SRAMMask)) = Byte;
319 CPU.SRAMModified = TRUE;
323 case CMemory::MAP_HIROM_SRAM:
325 CPU.Cycles += SLOW_ONE_CYCLE;
327 if (CPU.Memory_SRAMMask)
329 *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 +
330 ((Address & 0xf0000) >> 3)) & CPU.Memory_SRAMMask)) = Byte;
331 CPU.SRAMModified = TRUE;
335 case CMemory::MAP_BWRAM:
337 CPU.Cycles += SLOW_ONE_CYCLE;
339 *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte;
340 CPU.SRAMModified = TRUE;
343 case CMemory::MAP_DEBUG:
345 printf ("W(B) %06x\n", Address);
348 case CMemory::MAP_SA1RAM:
350 CPU.Cycles += SLOW_ONE_CYCLE;
352 *(Memory.SRAM + (Address & 0xffff)) = Byte;
353 SA1.Executing = !SA1.Waiting;
356 case CMemory::MAP_C4:
357 S9xSetC4 (Byte, Address & 0xffff);
361 case CMemory::MAP_NONE:
363 CPU.Cycles += SLOW_ONE_CYCLE;
366 printf ("W(B) %06x\n", Address);
372 INLINE void S9xSetWord (uint16 Word, uint32 Address)
376 sprintf(str,"wr @ %04X %04X",Address,Word);
382 #if defined(CPU_SHUTDOWN)
383 CPU.WaitAddress = NULL;
385 #if defined (VAR_CYCLES)
387 uint8 *SetAddress = Memory.WriteMap [block = ((Address >> MEMMAP_SHIFT) & MEMMAP_MASK)];
389 uint8 *SetAddress = Memory.WriteMap [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
392 if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
395 CPU.Cycles += Memory.MemorySpeed [block] << 1;
397 #if defined(CPU_SHUTDOWN) && defined(USE_SA1)
398 uint8 *SetAddressSA1 = SetAddress + (Address & 0xffff);
399 if (SetAddressSA1 == SA1.WaitByteAddress1 ||
400 SetAddressSA1 == SA1.WaitByteAddress2)
402 SA1.Executing = SA1.S9xOpcodes != NULL;
406 #ifdef FAST_LSB_WORD_ACCESS
407 *(uint16 *) (SetAddress + (Address & 0xffff)) = Word;
409 *(SetAddress + (Address & 0xffff)) = (uint8) Word;
410 *(SetAddress + ((Address + 1) & 0xffff)) = Word >> 8;
415 switch ((int) SetAddress)
417 case CMemory::MAP_PPU:
420 CPU.Cycles += TWO_CYCLES;
422 S9xSetPPU ((uint8) Word, Address & 0xffff);
423 S9xSetPPU (Word >> 8, (Address & 0xffff) + 1);
426 case CMemory::MAP_CPU:
428 CPU.Cycles += TWO_CYCLES;
430 S9xSetCPU ((uint8) Word, (Address & 0xffff));
431 S9xSetCPU (Word >> 8, (Address & 0xffff) + 1);
434 case CMemory::MAP_DSP:
436 CPU.Cycles += SLOW_ONE_CYCLE * 2;
438 S9xSetDSP ((uint8) Word, (Address & 0xffff));
439 S9xSetDSP (Word >> 8, (Address & 0xffff) + 1);
442 case CMemory::MAP_LOROM_SRAM:
444 CPU.Cycles += SLOW_ONE_CYCLE * 2;
446 if (CPU.Memory_SRAMMask)
448 *(Memory.SRAM + (Address & CPU.Memory_SRAMMask)) = (uint8) Word;
449 *(Memory.SRAM + ((Address + 1) & CPU.Memory_SRAMMask)) = Word >> 8;
450 CPU.SRAMModified = TRUE;
454 case CMemory::MAP_HIROM_SRAM:
456 CPU.Cycles += SLOW_ONE_CYCLE * 2;
458 if (CPU.Memory_SRAMMask)
461 (((Address & 0x7fff) - 0x6000 +
462 ((Address & 0xf0000) >> MEMMAP_SHIFT) & CPU.Memory_SRAMMask))) = (uint8) Word;
464 ((((Address + 1) & 0x7fff) - 0x6000 +
465 (((Address + 1) & 0xf0000) >> MEMMAP_SHIFT) & CPU.Memory_SRAMMask))) = (uint8) (Word >> 8);
466 CPU.SRAMModified = TRUE;
470 case CMemory::MAP_BWRAM:
472 CPU.Cycles += SLOW_ONE_CYCLE * 2;
474 *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = (uint8) Word;
475 *(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) = (uint8) (Word >> 8);
476 CPU.SRAMModified = TRUE;
479 case CMemory::MAP_DEBUG:
481 printf ("W(W) %06x\n", Address);
484 case CMemory::MAP_SA1RAM:
486 CPU.Cycles += SLOW_ONE_CYCLE;
488 *(Memory.SRAM + (Address & 0xffff)) = (uint8) Word;
489 *(Memory.SRAM + ((Address + 1) & 0xffff)) = (uint8) (Word >> 8);
490 SA1.Executing = !SA1.Waiting;
493 case CMemory::MAP_C4:
494 S9xSetC4 (Word & 0xff, Address & 0xffff);
495 S9xSetC4 ((uint8) (Word >> 8), (Address + 1) & 0xffff);
499 case CMemory::MAP_NONE:
501 CPU.Cycles += SLOW_ONE_CYCLE * 2;
504 printf ("W(W) %06x\n", Address);
510 INLINE uint8 *GetBasePointer (uint32 Address)
512 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
513 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
516 switch ((int) GetAddress)
518 case CMemory::MAP_PPU:
519 return (Memory.FillRAM - 0x2000);
520 case CMemory::MAP_CPU:
521 return (Memory.FillRAM - 0x4000);
522 case CMemory::MAP_DSP:
523 return (Memory.FillRAM - 0x6000);
524 case CMemory::MAP_SA1RAM:
525 case CMemory::MAP_LOROM_SRAM:
526 return (Memory.SRAM);
527 case CMemory::MAP_BWRAM:
528 return (Memory.BWRAM - 0x6000);
529 case CMemory::MAP_HIROM_SRAM:
530 return (Memory.SRAM - 0x6000);
531 case CMemory::MAP_C4:
532 return (Memory.C4RAM - 0x6000);
533 case CMemory::MAP_DEBUG:
535 printf ("GBP %06x\n", Address);
538 case CMemory::MAP_NONE:
540 printf ("GBP %06x\n", Address);
546 INLINE uint8 *S9xGetMemPointer (uint32 Address)
548 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
549 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
550 return (GetAddress + (Address & 0xffff));
552 switch ((int) GetAddress)
554 case CMemory::MAP_PPU:
555 return (Memory.FillRAM - 0x2000 + (Address & 0xffff));
556 case CMemory::MAP_CPU:
557 return (Memory.FillRAM - 0x4000 + (Address & 0xffff));
558 case CMemory::MAP_DSP:
559 return (Memory.FillRAM - 0x6000 + (Address & 0xffff));
560 case CMemory::MAP_SA1RAM:
561 case CMemory::MAP_LOROM_SRAM:
562 return (Memory.SRAM + (Address & 0xffff));
563 case CMemory::MAP_BWRAM:
564 return (Memory.BWRAM - 0x6000 + (Address & 0xffff));
565 case CMemory::MAP_HIROM_SRAM:
566 return (Memory.SRAM - 0x6000 + (Address & 0xffff));
568 case CMemory::MAP_C4:
569 return (Memory.C4RAM - 0x6000 + (Address & 0xffff));
571 case CMemory::MAP_DEBUG:
573 printf ("GMP %06x\n", Address);
576 case CMemory::MAP_NONE:
578 printf ("GMP %06x\n", Address);
584 INLINE void S9xSetPCBase (uint32 Address)
588 uint8 *GetAddress = Memory.Map [block = (Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
590 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
592 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
595 CPU.MemSpeed = Memory.MemorySpeed [block];
596 CPU.MemSpeedx2 = CPU.MemSpeed << 1;
598 CPU.PCBase = GetAddress;
599 CPU.PC = GetAddress + (Address & 0xffff);
603 switch ((int) GetAddress)
605 case CMemory::MAP_PPU:
607 CPU.MemSpeed = ONE_CYCLE;
608 CPU.MemSpeedx2 = TWO_CYCLES;
610 CPU.PCBase = Memory.FillRAM - 0x2000;
611 CPU.PC = CPU.PCBase + (Address & 0xffff);
614 case CMemory::MAP_CPU:
616 CPU.MemSpeed = ONE_CYCLE;
617 CPU.MemSpeedx2 = TWO_CYCLES;
619 CPU.PCBase = Memory.FillRAM - 0x4000;
620 CPU.PC = CPU.PCBase + (Address & 0xffff);
623 case CMemory::MAP_DSP:
625 CPU.MemSpeed = SLOW_ONE_CYCLE;
626 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
628 CPU.PCBase = Memory.FillRAM - 0x6000;
629 CPU.PC = CPU.PCBase + (Address & 0xffff);
632 case CMemory::MAP_SA1RAM:
633 case CMemory::MAP_LOROM_SRAM:
635 CPU.MemSpeed = SLOW_ONE_CYCLE;
636 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
638 CPU.PCBase = Memory.SRAM;
639 CPU.PC = CPU.PCBase + (Address & 0xffff);
642 case CMemory::MAP_BWRAM:
644 CPU.MemSpeed = SLOW_ONE_CYCLE;
645 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
647 CPU.PCBase = Memory.BWRAM - 0x6000;
648 CPU.PC = CPU.PCBase + (Address & 0xffff);
650 case CMemory::MAP_HIROM_SRAM:
652 CPU.MemSpeed = SLOW_ONE_CYCLE;
653 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
655 CPU.PCBase = Memory.SRAM - 0x6000;
656 CPU.PC = CPU.PCBase + (Address & 0xffff);
659 case CMemory::MAP_C4:
661 CPU.MemSpeed = SLOW_ONE_CYCLE;
662 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
664 CPU.PCBase = Memory.C4RAM - 0x6000;
665 CPU.PC = CPU.PCBase + (Address & 0xffff);
668 case CMemory::MAP_DEBUG:
670 printf ("SBP %06x\n", Address);
674 case CMemory::MAP_NONE:
676 CPU.MemSpeed = SLOW_ONE_CYCLE;
677 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
680 printf ("SBP %06x\n", Address);
682 CPU.PCBase = Memory.SRAM;
683 CPU.PC = Memory.SRAM + (Address & 0xffff);