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)
466 (((Address + 1) & 0x7fff) - 0x6000) +
467 ((((Address + 1) & 0xf0000) >> MEMMAP_SHIFT) & CPU.Memory_SRAMMask)
468 ) = (uint8) (Word >> 8);
470 CPU.SRAMModified = TRUE;
474 case CMemory::MAP_BWRAM:
476 CPU.Cycles += SLOW_ONE_CYCLE * 2;
478 *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = (uint8) Word;
479 *(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) = (uint8) (Word >> 8);
480 CPU.SRAMModified = TRUE;
483 case CMemory::MAP_DEBUG:
485 printf ("W(W) %06x\n", Address);
488 case CMemory::MAP_SA1RAM:
490 CPU.Cycles += SLOW_ONE_CYCLE;
492 *(Memory.SRAM + (Address & 0xffff)) = (uint8) Word;
493 *(Memory.SRAM + ((Address + 1) & 0xffff)) = (uint8) (Word >> 8);
494 SA1.Executing = !SA1.Waiting;
497 case CMemory::MAP_C4:
498 S9xSetC4 (Word & 0xff, Address & 0xffff);
499 S9xSetC4 ((uint8) (Word >> 8), (Address + 1) & 0xffff);
503 case CMemory::MAP_NONE:
505 CPU.Cycles += SLOW_ONE_CYCLE * 2;
508 printf ("W(W) %06x\n", Address);
514 INLINE uint8 *GetBasePointer (uint32 Address)
516 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
517 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
520 switch ((int) GetAddress)
522 case CMemory::MAP_PPU:
523 return (Memory.FillRAM - 0x2000);
524 case CMemory::MAP_CPU:
525 return (Memory.FillRAM - 0x4000);
526 case CMemory::MAP_DSP:
527 return (Memory.FillRAM - 0x6000);
528 case CMemory::MAP_SA1RAM:
529 case CMemory::MAP_LOROM_SRAM:
530 return (Memory.SRAM);
531 case CMemory::MAP_BWRAM:
532 return (Memory.BWRAM - 0x6000);
533 case CMemory::MAP_HIROM_SRAM:
534 return (Memory.SRAM - 0x6000);
535 case CMemory::MAP_C4:
536 return (Memory.C4RAM - 0x6000);
537 case CMemory::MAP_DEBUG:
539 printf ("GBP %06x\n", Address);
542 case CMemory::MAP_NONE:
544 printf ("GBP %06x\n", Address);
550 INLINE uint8 *S9xGetMemPointer (uint32 Address)
552 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
553 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
554 return (GetAddress + (Address & 0xffff));
556 switch ((int) GetAddress)
558 case CMemory::MAP_PPU:
559 return (Memory.FillRAM - 0x2000 + (Address & 0xffff));
560 case CMemory::MAP_CPU:
561 return (Memory.FillRAM - 0x4000 + (Address & 0xffff));
562 case CMemory::MAP_DSP:
563 return (Memory.FillRAM - 0x6000 + (Address & 0xffff));
564 case CMemory::MAP_SA1RAM:
565 case CMemory::MAP_LOROM_SRAM:
566 return (Memory.SRAM + (Address & 0xffff));
567 case CMemory::MAP_BWRAM:
568 return (Memory.BWRAM - 0x6000 + (Address & 0xffff));
569 case CMemory::MAP_HIROM_SRAM:
570 return (Memory.SRAM - 0x6000 + (Address & 0xffff));
572 case CMemory::MAP_C4:
573 return (Memory.C4RAM - 0x6000 + (Address & 0xffff));
575 case CMemory::MAP_DEBUG:
577 printf ("GMP %06x\n", Address);
580 case CMemory::MAP_NONE:
582 printf ("GMP %06x\n", Address);
588 INLINE void S9xSetPCBase (uint32 Address)
592 uint8 *GetAddress = Memory.Map [block = (Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
594 uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK];
596 if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
599 CPU.MemSpeed = Memory.MemorySpeed [block];
600 CPU.MemSpeedx2 = CPU.MemSpeed << 1;
602 CPU.PCBase = GetAddress;
603 CPU.PC = GetAddress + (Address & 0xffff);
607 switch ((int) GetAddress)
609 case CMemory::MAP_PPU:
611 CPU.MemSpeed = ONE_CYCLE;
612 CPU.MemSpeedx2 = TWO_CYCLES;
614 CPU.PCBase = Memory.FillRAM - 0x2000;
615 CPU.PC = CPU.PCBase + (Address & 0xffff);
618 case CMemory::MAP_CPU:
620 CPU.MemSpeed = ONE_CYCLE;
621 CPU.MemSpeedx2 = TWO_CYCLES;
623 CPU.PCBase = Memory.FillRAM - 0x4000;
624 CPU.PC = CPU.PCBase + (Address & 0xffff);
627 case CMemory::MAP_DSP:
629 CPU.MemSpeed = SLOW_ONE_CYCLE;
630 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
632 CPU.PCBase = Memory.FillRAM - 0x6000;
633 CPU.PC = CPU.PCBase + (Address & 0xffff);
636 case CMemory::MAP_SA1RAM:
637 case CMemory::MAP_LOROM_SRAM:
639 CPU.MemSpeed = SLOW_ONE_CYCLE;
640 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
642 CPU.PCBase = Memory.SRAM;
643 CPU.PC = CPU.PCBase + (Address & 0xffff);
646 case CMemory::MAP_BWRAM:
648 CPU.MemSpeed = SLOW_ONE_CYCLE;
649 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
651 CPU.PCBase = Memory.BWRAM - 0x6000;
652 CPU.PC = CPU.PCBase + (Address & 0xffff);
654 case CMemory::MAP_HIROM_SRAM:
656 CPU.MemSpeed = SLOW_ONE_CYCLE;
657 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
659 CPU.PCBase = Memory.SRAM - 0x6000;
660 CPU.PC = CPU.PCBase + (Address & 0xffff);
663 case CMemory::MAP_C4:
665 CPU.MemSpeed = SLOW_ONE_CYCLE;
666 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
668 CPU.PCBase = Memory.C4RAM - 0x6000;
669 CPU.PC = CPU.PCBase + (Address & 0xffff);
672 case CMemory::MAP_DEBUG:
674 printf ("SBP %06x\n", Address);
678 case CMemory::MAP_NONE:
680 CPU.MemSpeed = SLOW_ONE_CYCLE;
681 CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
684 printf ("SBP %06x\n", Address);
686 CPU.PCBase = Memory.SRAM;
687 CPU.PC = Memory.SRAM + (Address & 0xffff);