initial upstream import
[drnoksnes] / cpuexec.h
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
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).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
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.
25  *
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.
29  *
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.
33  *
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
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #ifndef _CPUEXEC_H_
42 #define _CPUEXEC_H_
43 #include "ppu.h"
44 #include "memmap.h"
45 #include "65c816.h"
46
47 #define DO_HBLANK_CHECK() \
48     if (CPU.Cycles >= CPU.NextEvent) \
49         S9xDoHBlankProcessing ();
50
51 struct SOpcodes {
52 #ifdef __WIN32__
53         void (__cdecl *S9xOpcode)( void);
54 #else
55         void (*S9xOpcode)( void);
56 #endif
57 };
58
59 struct SICPU
60 {
61 /*
62     uint8  *Speed;
63     struct SOpcodes *S9xOpcodes;
64     uint8  _Carry;
65     uint8  _Zero;
66     uint8  _Negative;
67     uint8  _Overflow;
68 */
69         bool8  CPUExecuting;
70     uint32 ShiftedPB;
71     uint32 ShiftedDB;
72     uint32 Frame;
73     uint32 Scanline;
74     uint32 FrameAdvanceCount;
75 };
76
77 START_EXTERN_C
78 void S9xMainLoop (void);
79 void S9xReset (void);
80 void S9xDoHBlankProcessing ();
81 void S9xClearIRQ (uint32);
82 void S9xSetIRQ (uint32);
83
84 extern struct SOpcodes S9xOpcodesM1X1 [256];
85 extern struct SOpcodes S9xOpcodesM1X0 [256];
86 extern struct SOpcodes S9xOpcodesM0X1 [256];
87 extern struct SOpcodes S9xOpcodesM0X0 [256];
88
89 #ifndef VAR_CYCLES
90 extern uint8 S9xE1M1X1 [256];
91 extern uint8 S9xE0M1X0 [256];
92 extern uint8 S9xE0M1X1 [256];
93 extern uint8 S9xE0M0X0 [256];
94 extern uint8 S9xE0M0X1 [256];
95 #endif
96
97 extern struct SICPU ICPU;
98 END_EXTERN_C
99
100 STATIC inline void CLEAR_IRQ_SOURCE (uint32 M)
101 {
102     CPU.IRQActive &= ~M;
103     if (!CPU.IRQActive)
104         CPU.Flags &= ~IRQ_PENDING_FLAG;
105 }
106
107 #if 0
108 STATIC inline void S9xUnpackStatus()
109 {
110     ICPU._Zero = (Registers.PL & Zero) == 0;
111     ICPU._Negative = (Registers.PL & Negative);
112     ICPU._Carry = (Registers.PL & Carry);
113     ICPU._Overflow = (Registers.PL & Overflow) >> 6;
114 }
115
116 STATIC inline void S9xPackStatus()
117 {
118     Registers.PL &= ~(Zero | Negative | Carry | Overflow);
119     Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) |
120                     (ICPU._Negative & 0x80) | (ICPU._Overflow << 6);
121 }
122
123 STATIC inline void S9xFixCycles ()
124 {
125     if (CheckEmulation ())
126     {
127 #ifndef VAR_CYCLES
128         ICPU.Speed = S9xE1M1X1;
129 #endif
130         ICPU.S9xOpcodes = S9xOpcodesM1X1;
131     }
132     else
133     if (CheckMemory ())
134     {
135         if (CheckIndex ())
136         {
137 #ifndef VAR_CYCLES
138             ICPU.Speed = S9xE0M1X1;
139 #endif
140             ICPU.S9xOpcodes = S9xOpcodesM1X1;
141         }
142         else
143         {
144 #ifndef VAR_CYCLES
145             ICPU.Speed = S9xE0M1X0;
146 #endif
147             ICPU.S9xOpcodes = S9xOpcodesM1X0;
148         }
149     }
150     else
151     {
152         if (CheckIndex ())
153         {
154 #ifndef VAR_CYCLES
155             ICPU.Speed = S9xE0M0X1;
156 #endif
157             ICPU.S9xOpcodes = S9xOpcodesM0X1;
158         }
159         else
160         {
161 #ifndef VAR_CYCLES
162             ICPU.Speed = S9xE0M0X0;
163 #endif
164             ICPU.S9xOpcodes = S9xOpcodesM0X0;
165         }
166     }
167 }
168 #endif
169
170 STATIC inline void S9xReschedule ()
171 {
172     uint8 which;
173     long max;
174     
175     if (CPU.WhichEvent == HBLANK_START_EVENT ||
176         CPU.WhichEvent == HTIMER_AFTER_EVENT)
177     {
178         which = HBLANK_END_EVENT;
179         max = Settings.H_Max;
180     }
181     else
182     {
183         which = HBLANK_START_EVENT;
184         max = Settings.HBlankStart;
185     }
186
187     if (PPU.HTimerEnabled &&
188         (long) PPU.HTimerPosition < max &&
189         (long) PPU.HTimerPosition > CPU.NextEvent &&
190         (!PPU.VTimerEnabled ||
191          (PPU.VTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos)))
192     {
193         which = (long) PPU.HTimerPosition < Settings.HBlankStart ?
194                         HTIMER_BEFORE_EVENT : HTIMER_AFTER_EVENT;
195         max = PPU.HTimerPosition;
196     }
197     CPU.NextEvent = max;
198     CPU.WhichEvent = which;
199 }
200
201 #endif