1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #ifndef NST_BASE_H
26 #define NST_BASE_H
27 
28 #include <climits>
29 #include "api/NstApiConfig.hpp"
30 
31 //--------------------------------------------------------------------------------------
32 // Microsoft Visual C++
33 //--------------------------------------------------------------------------------------
34 
35 #ifdef _MSC_VER
36 #define NST_MSVC _MSC_VER
37 #else
38 #define NST_MSVC 0
39 #endif
40 
41 //--------------------------------------------------------------------------------------
42 // Intel C/C++ Compiler
43 //--------------------------------------------------------------------------------------
44 
45 #ifdef __INTEL_COMPILER
46 #define NST_ICC __INTEL_COMPILER
47 #else
48 #define NST_ICC 0
49 #endif
50 
51 //--------------------------------------------------------------------------------------
52 // GNU Compiler Collection
53 //--------------------------------------------------------------------------------------
54 
55 #ifdef __GNUC__
56 #define NST_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
57 #else
58 #define NST_GCC 0
59 #endif
60 
61 //--------------------------------------------------------------------------------------
62 // Borland C++
63 //--------------------------------------------------------------------------------------
64 
65 #ifdef __BORLANDC__
66 #define NST_BCB __BORLANDC__
67 #else
68 #define NST_BCB 0
69 #endif
70 
71 //--------------------------------------------------------------------------------------
72 // Metrowerks CodeWarrior
73 //--------------------------------------------------------------------------------------
74 
75 #ifdef __MWERKS__
76 #define NST_MWERKS __MWERKS__
77 #else
78 #define NST_MWERKS 0
79 #endif
80 
81 //--------------------------------------------------------------------------------------
82 
83 #ifdef NST_PRAGMA_ONCE
84 #pragma once
85 #elif NST_MSVC >= 1020 || NST_MWERKS >= 0x3000
86 #pragma once
87 #define NST_PRAGMA_ONCE
88 #endif
89 
90 //--------------------------------------------------------------------------------------
91 
92 #ifndef NST_CALL
93 #define NST_CALL
94 #endif
95 
96 namespace Nes
97 {
98 	typedef signed char schar;
99 	typedef unsigned char uchar;
100 	typedef unsigned short ushort;
101 	typedef unsigned int uint;
102 	typedef unsigned long ulong;
103 
104 	#if UCHAR_MAX >= 0xFF
105 	typedef unsigned char byte;
106 	#else
107 	#error Unsupported plattform!
108 	#endif
109 
110 	#if UCHAR_MAX >= 0xFFFF
111 	typedef unsigned char word;
112 	#elif USHRT_MAX >= 0xFFFF
113 	typedef unsigned short word;
114 	#elif UINT_MAX >= 0xFFFF
115 	typedef unsigned int word;
116 	#else
117 	#error Unsupported plattform!
118 	#endif
119 
120 	#if SCHAR_MAX >= 32767 && SCHAR_MIN <= -32767
121 	typedef signed char iword;
122 	#elif SHRT_MAX >= 32767 && SHRT_MIN <= -32767
123 	typedef signed short iword;
124 	#elif INT_MAX >= 32767 && INT_MIN <= -32767
125 	typedef signed int iword;
126 	#else
127 	#error Unsupported plattform!
128 	#endif
129 
130 	#if UCHAR_MAX >= 0xFFFFFFFF
131 	typedef unsigned char dword;
132 	#elif USHRT_MAX >= 0xFFFFFFFF
133 	typedef unsigned short dword;
134 	#elif UINT_MAX >= 0xFFFFFFFF
135 	typedef unsigned int dword;
136 	#elif ULONG_MAX >= 0xFFFFFFFF
137 	typedef unsigned long dword;
138 	#else
139 	#error Unsupported plattform!
140 	#endif
141 
142 	#if SCHAR_MAX >= 2147483647 && SCHAR_MIN <= -2147483647
143 	typedef signed char idword;
144 	#elif SHRT_MAX >= 2147483647 && SHRT_MIN <= -2147483647
145 	typedef signed short idword;
146 	#elif INT_MAX >= 2147483647 && INT_MIN <= -2147483647
147 	typedef signed int idword;
148 	#elif LONG_MAX >= 2147483647 && LONG_MIN <= -2147483647
149 	typedef signed long idword;
150 	#else
151 	#error Unsupported plattform!
152 	#endif
153 
154 	/**
155 	* General result codes.
156 	*/
157 	enum Result
158 	{
159 		/**
160 		* NTSC/PAL region mismatch.
161 		*/
162 		RESULT_ERR_WRONG_MODE = -13,
163 		/**
164 		* Missing FDS BIOS.
165 		*/
166 		RESULT_ERR_MISSING_BIOS = -12,
167 		/**
168 		* Unsupported or malformed mapper.
169 		*/
170 		RESULT_ERR_UNSUPPORTED_MAPPER = -11,
171 		/**
172 		* Vs DualSystem is unsupported.
173 		*/
174 		RESULT_ERR_UNSUPPORTED_VSSYSTEM = -10,
175 		/**
176 		* File format version is no longer supported.
177 		*/
178 		RESULT_ERR_UNSUPPORTED_FILE_VERSION = -9,
179 		/**
180 		* Unsupported operation.
181 		*/
182 		RESULT_ERR_UNSUPPORTED = -8,
183 		/**
184 		* Invalid CRC checksum.
185 		*/
186 		RESULT_ERR_INVALID_CRC = -7,
187 		/**
188 		* Corrupt file.
189 		*/
190 		RESULT_ERR_CORRUPT_FILE = -6,
191 		/**
192 		* Invalid file.
193 		*/
194 		RESULT_ERR_INVALID_FILE = -5,
195 		/**
196 		* Invalid parameter(s).
197 		*/
198 		RESULT_ERR_INVALID_PARAM = -4,
199 		/**
200 		* System not ready.
201 		*/
202 		RESULT_ERR_NOT_READY = -3,
203 		/**
204 		* Out of memory.
205 		*/
206 		RESULT_ERR_OUT_OF_MEMORY = -2,
207 		/**
208 		* Generic error.
209 		*/
210 		RESULT_ERR_GENERIC = -1,
211 		/**
212 		* Success.
213 		*/
214 		RESULT_OK = 0,
215 		/**
216 		* Success but operation had no effect.
217 		*/
218 		RESULT_NOP = 1,
219 		/**
220 		* Success but image dump may be bad.
221 		*/
222 		RESULT_WARN_BAD_DUMP = 2,
223 		/**
224 		* Success but PRG-ROM may be bad.
225 		*/
226 		RESULT_WARN_BAD_PROM = 3,
227 		/**
228 		* Success but CHR-ROM may be bad.
229 		*/
230 		RESULT_WARN_BAD_CROM = 4,
231 		/**
232 		* Success but file header may have incorrect data.
233 		*/
234 		RESULT_WARN_BAD_FILE_HEADER = 5,
235 		/**
236 		* Success but save data has been lost.
237 		*/
238 		RESULT_WARN_SAVEDATA_LOST = 6,
239 		/**
240 		* Success but data may have been replaced.
241 		*/
242 		RESULT_WARN_DATA_REPLACED = 8
243 	};
244 
245 	namespace Core
246 	{
247 		enum Region
248 		{
249 			REGION_NTSC,
250 			REGION_PAL
251 		};
252 
253 		enum System
254 		{
255 			SYSTEM_NES_NTSC,
256 			SYSTEM_NES_PAL,
257 			SYSTEM_NES_PAL_A,
258 			SYSTEM_NES_PAL_B,
259 			SYSTEM_FAMICOM,
260 			SYSTEM_DENDY,
261 			SYSTEM_VS_UNISYSTEM,
262 			SYSTEM_VS_DUALSYSTEM,
263 			SYSTEM_PLAYCHOICE_10
264 		};
265 
266 		enum FavoredSystem
267 		{
268 			FAVORED_NES_NTSC,
269 			FAVORED_NES_PAL,
270 			FAVORED_FAMICOM,
271 			FAVORED_DENDY
272 		};
273 
274 		enum CpuModel
275 		{
276 			CPU_RP2A03,
277 			CPU_RP2A07,
278 			CPU_DENDY
279 		};
280 
281 		enum PpuModel
282 		{
283 			PPU_RP2C02,
284 			PPU_RP2C03B,
285 			PPU_RP2C03G,
286 			PPU_RP2C04_0001,
287 			PPU_RP2C04_0002,
288 			PPU_RP2C04_0003,
289 			PPU_RP2C04_0004,
290 			PPU_RC2C03B,
291 			PPU_RC2C03C,
292 			PPU_RC2C05_01,
293 			PPU_RC2C05_02,
294 			PPU_RC2C05_03,
295 			PPU_RC2C05_04,
296 			PPU_RC2C05_05,
297 			PPU_RP2C07,
298 			PPU_DENDY
299 		};
300 
301 		enum
302 		{
303 			CLK_M2_MUL      = 6,
304 			CLK_NTSC        = 39375000UL * CLK_M2_MUL,
305 			CLK_NTSC_DIV    = 11,
306 			CLK_NTSC_HVSYNC = 525UL * 455 * CLK_NTSC_DIV * CLK_M2_MUL / 4,
307 			CLK_PAL         = 35468950UL * CLK_M2_MUL,
308 			CLK_PAL_DIV     = 8,
309 			CLK_PAL_HVSYNC  = 625UL * 1418758 / (10000/CLK_PAL_DIV) * CLK_M2_MUL
310 		};
311 
312 		enum
313 		{
314 			CPU_RP2A03_CC = 12,
315 			CPU_RP2A07_CC = 16,
316 			CPU_DENDY_CC  = 15
317 		};
318 
319 		enum
320 		{
321 			PPU_RP2C02_CC         = 4,
322 			PPU_RP2C02_HACTIVE    = PPU_RP2C02_CC * 256,
323 			PPU_RP2C02_HBLANK     = PPU_RP2C02_CC * 85,
324 			PPU_RP2C02_HSYNC      = PPU_RP2C02_HACTIVE + PPU_RP2C02_HBLANK,
325 			PPU_RP2C02_VACTIVE    = 240,
326 			PPU_RP2C02_VSLEEP     = 1,
327 			PPU_RP2C02_VINT       = 20,
328 			PPU_RP2C02_VDUMMY     = 1,
329 			PPU_RP2C02_VBLANK     = PPU_RP2C02_VSLEEP + PPU_RP2C02_VINT + PPU_RP2C02_VDUMMY,
330 			PPU_RP2C02_VSYNC      = PPU_RP2C02_VACTIVE + PPU_RP2C02_VBLANK,
331 			PPU_RP2C02_HVSYNCBOOT = PPU_RP2C02_VACTIVE * PPU_RP2C02_HSYNC + PPU_RP2C02_CC * 312,
332 			PPU_RP2C02_HVREGBOOT  = (PPU_RP2C02_VACTIVE + PPU_RP2C02_VINT) * PPU_RP2C02_HSYNC + PPU_RP2C02_CC * 314,
333 			PPU_RP2C02_HVINT      = PPU_RP2C02_VINT * ulong(PPU_RP2C02_HSYNC),
334 			PPU_RP2C02_HVSYNC_0   = PPU_RP2C02_VSYNC * ulong(PPU_RP2C02_HSYNC),
335 			PPU_RP2C02_HVSYNC_1   = PPU_RP2C02_VSYNC * ulong(PPU_RP2C02_HSYNC) - PPU_RP2C02_CC,
336 			PPU_RP2C02_HVSYNC     = (PPU_RP2C02_HVSYNC_0 + ulong(PPU_RP2C02_HVSYNC_1)) / 2,
337 			PPU_RP2C02_FPS        = (CLK_NTSC + CLK_NTSC_DIV * ulong(PPU_RP2C02_HVSYNC) / 2) / (CLK_NTSC_DIV * ulong(PPU_RP2C02_HVSYNC)),
338 			PPU_RP2C07_CC         = 5,
339 			PPU_RP2C07_HACTIVE    = PPU_RP2C07_CC * 256,
340 			PPU_RP2C07_HBLANK     = PPU_RP2C07_CC * 85,
341 			PPU_RP2C07_HSYNC      = PPU_RP2C07_HACTIVE + PPU_RP2C07_HBLANK,
342 			PPU_RP2C07_VACTIVE    = 240,
343 			PPU_RP2C07_VSLEEP     = 1,
344 			PPU_RP2C07_VINT       = 70,
345 			PPU_RP2C07_VDUMMY     = 1,
346 			PPU_RP2C07_VBLANK     = PPU_RP2C07_VSLEEP + PPU_RP2C07_VINT + PPU_RP2C07_VDUMMY,
347 			PPU_RP2C07_VSYNC      = PPU_RP2C07_VACTIVE + PPU_RP2C07_VBLANK,
348 			PPU_RP2C07_HVSYNCBOOT = PPU_RP2C07_VACTIVE * PPU_RP2C07_HSYNC + PPU_RP2C07_CC * 312,
349 			PPU_RP2C07_HVREGBOOT  = (PPU_RP2C07_VACTIVE + PPU_RP2C07_VINT) * PPU_RP2C07_HSYNC + PPU_RP2C07_CC * 314,
350 			PPU_RP2C07_HVINT      = PPU_RP2C07_VINT * ulong(PPU_RP2C07_HSYNC),
351 			PPU_RP2C07_HVSYNC     = PPU_RP2C07_VSYNC * ulong(PPU_RP2C07_HSYNC),
352 			PPU_RP2C07_FPS        = (CLK_PAL + CLK_PAL_DIV * ulong(PPU_RP2C07_HVSYNC) / 2) / (CLK_PAL_DIV * ulong(PPU_RP2C07_HVSYNC)),
353 			PPU_DENDY_CC          = 5,
354 			PPU_DENDY_HACTIVE     = PPU_DENDY_CC * 256,
355 			PPU_DENDY_HBLANK      = PPU_DENDY_CC * 85,
356 			PPU_DENDY_HSYNC       = PPU_DENDY_HACTIVE + PPU_DENDY_HBLANK,
357 			PPU_DENDY_VACTIVE     = 240,
358 			PPU_DENDY_VSLEEP      = 51,
359 			PPU_DENDY_VINT        = 20,
360 			PPU_DENDY_VDUMMY      = 1,
361 			PPU_DENDY_VBLANK      = PPU_DENDY_VSLEEP + PPU_DENDY_VINT + PPU_DENDY_VDUMMY,
362 			PPU_DENDY_VSYNC       = PPU_DENDY_VACTIVE + PPU_DENDY_VBLANK,
363 			PPU_DENDY_HVSYNCBOOT  = PPU_DENDY_VACTIVE * PPU_DENDY_HSYNC + PPU_DENDY_CC * 312,
364 			PPU_DENDY_HVREGBOOT   = (PPU_DENDY_VACTIVE + PPU_DENDY_VINT) * PPU_DENDY_HSYNC + PPU_DENDY_CC * 314,
365 			PPU_DENDY_HVINT       = PPU_DENDY_VINT * ulong(PPU_DENDY_HSYNC),
366 			PPU_DENDY_HVSYNC      = PPU_DENDY_VSYNC * ulong(PPU_DENDY_HSYNC),
367 			PPU_DENDY_FPS         = (CLK_PAL + CLK_PAL_DIV * ulong(PPU_DENDY_HVSYNC) / 2) / (CLK_PAL_DIV * ulong(PPU_DENDY_HVSYNC))
368 		};
369 
370 		template<typename T>
371 		class ImplicitBool;
372 
373 		template<>
374 		class ImplicitBool<void>
375 		{
376 		public:
377 
378 			int type;
379 			typedef int ImplicitBool<void>::*Type;
380 		};
381 
382 		template<typename T>
383 		class ImplicitBool
384 		{
385 			template<typename U> void operator == (const ImplicitBool<U>&) const;
386 			template<typename U> void operator != (const ImplicitBool<U>&) const;
387 
388 		public:
389 
operator ImplicitBool<void>::Type() const390 			operator ImplicitBool<void>::Type () const
391 			{
392 				return !static_cast<const T&>(*this) ? 0 : &ImplicitBool<void>::type;
393 			}
394 		};
395 	}
396 }
397 
398 #define NES_FAILED(x_) ((x_) < Nes::RESULT_OK)
399 #define NES_SUCCEEDED(x_) ((x_) >= Nes::RESULT_OK)
400 
401 #endif
402