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.
45 ICPU._Zero = (W) != 0; \
46 ICPU._Negative = (uint8) ((W) >> 8);
52 STATIC INLINE void FASTCALL ADC8 (long OpAddress)
54 uint8 Work8 = S9xGetByte (OpAddress);
58 uint8 A1 = (Registers.A.W) & 0xF;
59 uint8 A2 = (Registers.A.W >> 4) & 0xF;
60 uint8 W1 = Work8 & 0xF;
61 uint8 W2 = (Work8 >> 4) & 0xF;
63 A1 += W1 + CheckCarry();
81 uint8 Ans8 = (A2 << 4) | A1;
82 if (~(Registers.AL ^ Work8) &
83 (Work8 ^ Ans8) & 0x80)
88 SETZN8 (Registers.AL);
92 uint16 Ans16 = Registers.AL + Work8 + CheckCarry();
94 ICPU._Carry = Ans16 >= 0x100;
96 if (~(Registers.AL ^ Work8) &
97 (Work8 ^ (uint8) Ans16) & 0x80)
101 Registers.AL = (uint8) Ans16;
102 SETZN8 (Registers.AL);
107 STATIC INLINE void FASTCALL ADC16 (long OpAddress)
109 uint16 Work16 = S9xGetWord (OpAddress);
113 uint8 A1 = (Registers.A.W) & 0xF;
114 uint8 A2 = (Registers.A.W >> 4) & 0xF;
115 uint8 A3 = (Registers.A.W >> 8) & 0xF;
116 uint8 A4 = (Registers.A.W >> 12) & 0xF;
117 uint8 W1 = Work16 & 0xF;
118 uint8 W2 = (Work16 >> 4) & 0xF;
119 uint8 W3 = (Work16 >> 8) & 0xF;
120 uint8 W4 = (Work16 >> 12) & 0xF;
122 A1 += W1 + CheckCarry ();
154 uint16 Ans16 = (A4 << 12) | (A3 << 8) | (A2 << 4) | (A1);
155 if (~(Registers.A.W ^ Work16) &
156 (Work16 ^ Ans16) & 0x8000)
160 Registers.A.W = Ans16;
161 SETZN16 (Registers.A.W);
165 uint32 Ans32 = Registers.A.W + Work16 + CheckCarry();
167 ICPU._Carry = Ans32 >= 0x10000;
169 if (~(Registers.A.W ^ Work16) &
170 (Work16 ^ (uint16) Ans32) & 0x8000)
174 Registers.A.W = (uint16) Ans32;
175 SETZN16 (Registers.A.W);
179 STATIC INLINE void FASTCALL AND16 (long OpAddress)
181 Registers.A.W &= S9xGetWord (OpAddress);
182 SETZN16 (Registers.A.W);
185 STATIC INLINE void FASTCALL AND8 (long OpAddress)
187 Registers.AL &= S9xGetByte (OpAddress);
188 SETZN8 (Registers.AL);
191 STATIC INLINE void FASTCALL A_ASL16 ()
194 CPU.Cycles += ONE_CYCLE;
196 ICPU._Carry = (Registers.AH & 0x80) != 0;
198 SETZN16 (Registers.A.W);
201 STATIC INLINE void FASTCALL A_ASL8 ()
204 CPU.Cycles += ONE_CYCLE;
206 ICPU._Carry = (Registers.AL & 0x80) != 0;
208 SETZN8 (Registers.AL);
211 STATIC INLINE void FASTCALL ASL16 (long OpAddress)
214 CPU.Cycles += ONE_CYCLE;
216 uint16 Work16 = S9xGetWord (OpAddress);
217 ICPU._Carry = (Work16 & 0x8000) != 0;
219 S9xSetWord (Work16, OpAddress);
223 STATIC INLINE void FASTCALL ASL8 (long OpAddress)
226 CPU.Cycles += ONE_CYCLE;
228 uint8 Work8 = S9xGetByte (OpAddress);
229 ICPU._Carry = (Work8 & 0x80) != 0;
231 S9xSetByte (Work8, OpAddress);
235 STATIC INLINE void FASTCALL BIT16 (long OpAddress)
237 uint16 Work16 = S9xGetWord (OpAddress);
238 ICPU._Overflow = (Work16 & 0x4000) != 0;
239 ICPU._Negative = (uint8) (Work16 >> 8);
240 ICPU._Zero = (Work16 & Registers.A.W) != 0;
243 STATIC INLINE void FASTCALL BIT8 (long OpAddress)
245 uint8 Work8 = S9xGetByte (OpAddress);
246 ICPU._Overflow = (Work8 & 0x40) != 0;
247 ICPU._Negative = Work8;
248 ICPU._Zero = Work8 & Registers.AL;
251 STATIC INLINE void FASTCALL CMP16 (long OpAddress)
253 int32 Int32 = (long) Registers.A.W -
254 (long) S9xGetWord (OpAddress);
255 ICPU._Carry = Int32 >= 0;
256 SETZN16 ((uint16) Int32);
259 STATIC INLINE void FASTCALL CMP8 (long OpAddress)
261 int32 Int32 = (short) Registers.AL -
262 (short) S9xGetByte (OpAddress);
263 ICPU._Carry = Int32 >= 0;
264 SETZN8 ((uint8) Int32);
267 STATIC INLINE void FASTCALL CMX16 (long OpAddress)
269 int32 Int32 = (long) Registers.X.W -
270 (long) S9xGetWord (OpAddress);
271 ICPU._Carry = Int32 >= 0;
272 SETZN16 ((uint16) Int32);
275 STATIC INLINE void FASTCALL CMX8 (long OpAddress)
277 int32 Int32 = (short) Registers.XL -
278 (short) S9xGetByte (OpAddress);
279 ICPU._Carry = Int32 >= 0;
280 SETZN8 ((uint8) Int32);
283 STATIC INLINE void FASTCALL CMY16 (long OpAddress)
285 int32 Int32 = (long) Registers.Y.W -
286 (long) S9xGetWord (OpAddress);
287 ICPU._Carry = Int32 >= 0;
288 SETZN16 ((uint16) Int32);
291 STATIC INLINE void FASTCALL CMY8 (long OpAddress)
293 int32 Int32 = (short) Registers.YL -
294 (short) S9xGetByte (OpAddress);
295 ICPU._Carry = Int32 >= 0;
296 SETZN8 ((uint8) Int32);
299 STATIC INLINE void FASTCALL A_DEC16 ()
302 CPU.Cycles += ONE_CYCLE;
305 CPU.WaitAddress = NULL;
309 SETZN16 (Registers.A.W);
312 STATIC INLINE void FASTCALL A_DEC8 ()
315 CPU.Cycles += ONE_CYCLE;
318 CPU.WaitAddress = NULL;
322 SETZN8 (Registers.AL);
325 STATIC INLINE void FASTCALL DEC16 (long OpAddress)
328 CPU.Cycles += ONE_CYCLE;
331 CPU.WaitAddress = NULL;
334 uint16 Work16 = S9xGetWord (OpAddress) - 1;
335 S9xSetWord (Work16, OpAddress);
339 STATIC INLINE void FASTCALL DEC8 (long OpAddress)
342 CPU.Cycles += ONE_CYCLE;
345 CPU.WaitAddress = NULL;
348 uint8 Work8 = S9xGetByte (OpAddress) - 1;
349 S9xSetByte (Work8, OpAddress);
353 STATIC INLINE void FASTCALL EOR16 (long OpAddress)
355 Registers.A.W ^= S9xGetWord (OpAddress);
356 SETZN16 (Registers.A.W);
359 STATIC INLINE void FASTCALL EOR8 (long OpAddress)
361 Registers.AL ^= S9xGetByte (OpAddress);
362 SETZN8 (Registers.AL);
365 STATIC INLINE void FASTCALL A_INC16 ()
368 CPU.Cycles += ONE_CYCLE;
371 CPU.WaitAddress = NULL;
375 SETZN16 (Registers.A.W);
378 STATIC INLINE void FASTCALL A_INC8 ()
381 CPU.Cycles += ONE_CYCLE;
384 CPU.WaitAddress = NULL;
388 SETZN8 (Registers.AL);
391 STATIC INLINE void FASTCALL INC16 (long OpAddress)
394 CPU.Cycles += ONE_CYCLE;
397 CPU.WaitAddress = NULL;
400 uint16 Work16 = S9xGetWord (OpAddress) + 1;
401 S9xSetWord (Work16, OpAddress);
405 STATIC INLINE void FASTCALL INC8 (long OpAddress)
408 CPU.Cycles += ONE_CYCLE;
411 CPU.WaitAddress = NULL;
414 uint8 Work8 = S9xGetByte (OpAddress) + 1;
415 S9xSetByte (Work8, OpAddress);
419 STATIC INLINE void FASTCALL LDA16 (long OpAddress)
421 Registers.A.W = S9xGetWord (OpAddress);
422 SETZN16 (Registers.A.W);
425 STATIC INLINE void FASTCALL LDA8 (long OpAddress)
427 Registers.AL = S9xGetByte (OpAddress);
428 SETZN8 (Registers.AL);
431 STATIC INLINE void FASTCALL LDX16 (long OpAddress)
433 Registers.X.W = S9xGetWord (OpAddress);
434 SETZN16 (Registers.X.W);
437 STATIC INLINE void FASTCALL LDX8 (long OpAddress)
439 Registers.XL = S9xGetByte (OpAddress);
440 SETZN8 (Registers.XL);
443 STATIC INLINE void FASTCALL LDY16 (long OpAddress)
445 Registers.Y.W = S9xGetWord (OpAddress);
446 SETZN16 (Registers.Y.W);
449 STATIC INLINE void FASTCALL LDY8 (long OpAddress)
451 Registers.YL = S9xGetByte (OpAddress);
452 SETZN8 (Registers.YL);
455 STATIC INLINE void FASTCALL A_LSR16 ()
458 CPU.Cycles += ONE_CYCLE;
460 ICPU._Carry = Registers.AL & 1;
462 SETZN16 (Registers.A.W);
465 STATIC INLINE void FASTCALL A_LSR8 ()
468 CPU.Cycles += ONE_CYCLE;
470 ICPU._Carry = Registers.AL & 1;
472 SETZN8 (Registers.AL);
475 STATIC INLINE void FASTCALL LSR16 (long OpAddress)
478 CPU.Cycles += ONE_CYCLE;
480 uint16 Work16 = S9xGetWord (OpAddress);
481 ICPU._Carry = Work16 & 1;
483 S9xSetWord (Work16, OpAddress);
487 STATIC INLINE void FASTCALL LSR8 (long OpAddress)
490 CPU.Cycles += ONE_CYCLE;
492 uint8 Work8 = S9xGetByte (OpAddress);
493 ICPU._Carry = Work8 & 1;
495 S9xSetByte (Work8, OpAddress);
499 STATIC INLINE void FASTCALL ORA16 (long OpAddress)
501 Registers.A.W |= S9xGetWord (OpAddress);
502 SETZN16 (Registers.A.W);
505 STATIC INLINE void FASTCALL ORA8 (long OpAddress)
507 Registers.AL |= S9xGetByte (OpAddress);
508 SETZN8 (Registers.AL);
511 STATIC INLINE void FASTCALL A_ROL16 ()
514 CPU.Cycles += ONE_CYCLE;
516 uint32 Work32 = (Registers.A.W << 1) | CheckCarry();
517 ICPU._Carry = Work32 >= 0x10000;
518 Registers.A.W = (uint16) Work32;
519 SETZN16 ((uint16) Work32);
522 STATIC INLINE void FASTCALL A_ROL8 ()
525 CPU.Cycles += ONE_CYCLE;
527 uint16 Work16 = Registers.AL;
529 Work16 |= CheckCarry();
530 ICPU._Carry = Work16 >= 0x100;
531 Registers.AL = (uint8) Work16;
532 SETZN8 ((uint8) Work16);
535 STATIC INLINE void FASTCALL ROL16 (long OpAddress)
538 CPU.Cycles += ONE_CYCLE;
540 uint32 Work32 = S9xGetWord (OpAddress);
542 Work32 |= CheckCarry();
543 ICPU._Carry = Work32 >= 0x10000;
544 S9xSetWord ((uint16) Work32, OpAddress);
545 SETZN16 ((uint16) Work32);
548 STATIC INLINE void FASTCALL ROL8 (long OpAddress)
551 CPU.Cycles += ONE_CYCLE;
553 uint16 Work16 = S9xGetByte (OpAddress);
555 Work16 |= CheckCarry ();
556 ICPU._Carry = Work16 >= 0x100;
557 S9xSetByte ((uint8) Work16, OpAddress);
558 SETZN8 ((uint8) Work16);
561 STATIC INLINE void FASTCALL A_ROR16 ()
564 CPU.Cycles += ONE_CYCLE;
566 uint32 Work32 = Registers.A.W;
567 Work32 |= (int) CheckCarry() << 16;
568 ICPU._Carry = (uint8) (Work32 & 1);
570 Registers.A.W = (uint16) Work32;
571 SETZN16 ((uint16) Work32);
574 STATIC INLINE void FASTCALL A_ROR8 ()
577 CPU.Cycles += ONE_CYCLE;
579 uint16 Work16 = Registers.AL | ((uint16) CheckCarry() << 8);
580 ICPU._Carry = (uint8) Work16 & 1;
582 Registers.AL = (uint8) Work16;
583 SETZN8 ((uint8) Work16);
586 STATIC INLINE void FASTCALL ROR16 (long OpAddress)
589 CPU.Cycles += ONE_CYCLE;
591 uint32 Work32 = S9xGetWord (OpAddress);
592 Work32 |= (int) CheckCarry() << 16;
593 ICPU._Carry = (uint8) (Work32 & 1);
595 S9xSetWord ((uint16) Work32, OpAddress);
596 SETZN16 ((uint16) Work32);
599 STATIC INLINE void FASTCALL ROR8 (long OpAddress)
602 CPU.Cycles += ONE_CYCLE;
604 uint16 Work16 = S9xGetByte (OpAddress);
605 Work16 |= (int) CheckCarry () << 8;
606 ICPU._Carry = (uint8) (Work16 & 1);
608 S9xSetByte ((uint8) Work16, OpAddress);
609 SETZN8 ((uint8) Work16);
612 STATIC INLINE void FASTCALL SBC16 (long OpAddress)
614 uint16 Work16 = S9xGetWord (OpAddress);
618 uint8 A1 = (Registers.A.W) & 0xF;
619 uint8 A2 = (Registers.A.W >> 4) & 0xF;
620 uint8 A3 = (Registers.A.W >> 8) & 0xF;
621 uint8 A4 = (Registers.A.W >> 12) & 0xF;
622 uint8 W1 = Work16 & 0xF;
623 uint8 W2 = (Work16 >> 4) & 0xF;
624 uint8 W3 = (Work16 >> 8) & 0xF;
625 uint8 W4 = (Work16 >> 12) & 0xF;
627 A1 -= W1 + !CheckCarry ();
656 uint16 Ans16 = (A4 << 12) | (A3 << 8) | (A2 << 4) | (A1);
657 if ((Registers.A.W ^ Work16) &
658 (Registers.A.W ^ Ans16) & 0x8000)
662 Registers.A.W = Ans16;
663 SETZN16 (Registers.A.W);
668 int32 Int32 = (long) Registers.A.W - (long) Work16 + (long) CheckCarry() - 1;
670 ICPU._Carry = Int32 >= 0;
672 if ((Registers.A.W ^ Work16) &
673 (Registers.A.W ^ (uint16) Int32) & 0x8000)
677 Registers.A.W = (uint16) Int32;
678 SETZN16 (Registers.A.W);
682 STATIC INLINE void FASTCALL SBC8 (long OpAddress)
684 uint8 Work8 = S9xGetByte (OpAddress);
687 uint8 A1 = (Registers.A.W) & 0xF;
688 uint8 A2 = (Registers.A.W >> 4) & 0xF;
689 uint8 W1 = Work8 & 0xF;
690 uint8 W2 = (Work8 >> 4) & 0xF;
692 A1 -= W1 + !CheckCarry ();
709 uint8 Ans8 = (A2 << 4) | A1;
710 if ((Registers.AL ^ Work8) &
711 (Registers.AL ^ Ans8) & 0x80)
716 SETZN8 (Registers.AL);
720 int32 Int32 = (short) Registers.AL - (short) Work8 + (short) CheckCarry() - 1;
722 ICPU._Carry = Int32 >= 0;
723 if ((Registers.AL ^ Work8) &
724 (Registers.AL ^ (uint8) Int32) & 0x80)
728 Registers.AL = (uint8) Int32;
729 SETZN8 (Registers.AL);
733 STATIC INLINE void FASTCALL STA16 (long OpAddress)
735 S9xSetWord (Registers.A.W, OpAddress);
738 STATIC INLINE void FASTCALL STA8 (long OpAddress)
740 S9xSetByte (Registers.AL, OpAddress);
743 STATIC INLINE void FASTCALL STX16 (long OpAddress)
745 S9xSetWord (Registers.X.W, OpAddress);
748 STATIC INLINE void FASTCALL STX8 (long OpAddress)
750 S9xSetByte (Registers.XL, OpAddress);
753 STATIC INLINE void FASTCALL STY16 (long OpAddress)
755 S9xSetWord (Registers.Y.W, OpAddress);
758 STATIC INLINE void FASTCALL STY8 (long OpAddress)
760 S9xSetByte (Registers.YL, OpAddress);
763 STATIC INLINE void FASTCALL STZ16 (long OpAddress)
765 S9xSetWord (0, OpAddress);
768 STATIC INLINE void FASTCALL STZ8 (long OpAddress)
770 S9xSetByte (0, OpAddress);
773 STATIC INLINE void FASTCALL TSB16 (long OpAddress)
776 CPU.Cycles += ONE_CYCLE;
778 uint16 Work16 = S9xGetWord (OpAddress);
779 ICPU._Zero = (Work16 & Registers.A.W) != 0;
780 Work16 |= Registers.A.W;
781 S9xSetWord (Work16, OpAddress);
784 STATIC INLINE void FASTCALL TSB8 (long OpAddress)
787 CPU.Cycles += ONE_CYCLE;
789 uint8 Work8 = S9xGetByte (OpAddress);
790 ICPU._Zero = Work8 & Registers.AL;
791 Work8 |= Registers.AL;
792 S9xSetByte (Work8, OpAddress);
795 STATIC INLINE void FASTCALL TRB16 (long OpAddress)
798 CPU.Cycles += ONE_CYCLE;
800 uint16 Work16 = S9xGetWord (OpAddress);
801 ICPU._Zero = (Work16 & Registers.A.W) != 0;
802 Work16 &= ~Registers.A.W;
803 S9xSetWord (Work16, OpAddress);
806 STATIC INLINE void FASTCALL TRB8 (long OpAddress)
809 CPU.Cycles += ONE_CYCLE;
811 uint8 Work8 = S9xGetByte (OpAddress);
812 ICPU._Zero = Work8 & Registers.AL;
813 Work8 &= ~Registers.AL;
814 S9xSetByte (Work8, OpAddress);