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