nestopia/source/core/NstBase.hpp
2012-09-02 13:13:55 -04:00

401 lines
11 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Nestopia is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#ifndef NST_BASE_H
#define NST_BASE_H
#include <climits>
#include "api/NstApiConfig.hpp"
//--------------------------------------------------------------------------------------
// Microsoft Visual C++
//--------------------------------------------------------------------------------------
#ifdef _MSC_VER
#define NST_MSVC _MSC_VER
#else
#define NST_MSVC 0
#endif
//--------------------------------------------------------------------------------------
// Intel C/C++ Compiler
//--------------------------------------------------------------------------------------
#ifdef __INTEL_COMPILER
#define NST_ICC __INTEL_COMPILER
#else
#define NST_ICC 0
#endif
//--------------------------------------------------------------------------------------
// GNU Compiler Collection
//--------------------------------------------------------------------------------------
#ifdef __GNUC__
#define NST_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#define NST_GCC 0
#endif
//--------------------------------------------------------------------------------------
// Borland C++
//--------------------------------------------------------------------------------------
#ifdef __BORLANDC__
#define NST_BCB __BORLANDC__
#else
#define NST_BCB 0
#endif
//--------------------------------------------------------------------------------------
// Metrowerks CodeWarrior
//--------------------------------------------------------------------------------------
#ifdef __MWERKS__
#define NST_MWERKS __MWERKS__
#else
#define NST_MWERKS 0
#endif
//--------------------------------------------------------------------------------------
#ifdef NST_PRAGMA_ONCE
#pragma once
#elif NST_MSVC >= 1020 || NST_MWERKS >= 0x3000
#pragma once
#define NST_PRAGMA_ONCE
#endif
//--------------------------------------------------------------------------------------
#ifndef NST_CALL
#define NST_CALL
#endif
namespace Nes
{
typedef signed char schar;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#if UCHAR_MAX >= 0xFF
typedef unsigned char byte;
#else
#error Unsupported plattform!
#endif
#if UCHAR_MAX >= 0xFFFF
typedef unsigned char word;
#elif USHRT_MAX >= 0xFFFF
typedef unsigned short word;
#elif UINT_MAX >= 0xFFFF
typedef unsigned int word;
#else
#error Unsupported plattform!
#endif
#if SCHAR_MAX >= 32767 && SCHAR_MIN <= -32767
typedef signed char iword;
#elif SHRT_MAX >= 32767 && SHRT_MIN <= -32767
typedef signed short iword;
#elif INT_MAX >= 32767 && INT_MIN <= -32767
typedef signed int iword;
#else
#error Unsupported plattform!
#endif
#if UCHAR_MAX >= 0xFFFFFFFF
typedef unsigned char dword;
#elif USHRT_MAX >= 0xFFFFFFFF
typedef unsigned short dword;
#elif UINT_MAX >= 0xFFFFFFFF
typedef unsigned int dword;
#elif ULONG_MAX >= 0xFFFFFFFF
typedef unsigned long dword;
#else
#error Unsupported plattform!
#endif
#if SCHAR_MAX >= 2147483647 && SCHAR_MIN <= -2147483647
typedef signed char idword;
#elif SHRT_MAX >= 2147483647 && SHRT_MIN <= -2147483647
typedef signed short idword;
#elif INT_MAX >= 2147483647 && INT_MIN <= -2147483647
typedef signed int idword;
#elif LONG_MAX >= 2147483647 && LONG_MIN <= -2147483647
typedef signed long idword;
#else
#error Unsupported plattform!
#endif
/**
* General result codes.
*/
enum Result
{
/**
* NTSC/PAL region mismatch.
*/
RESULT_ERR_WRONG_MODE = -13,
/**
* Missing FDS BIOS.
*/
RESULT_ERR_MISSING_BIOS = -12,
/**
* Unsupported or malformed mapper.
*/
RESULT_ERR_UNSUPPORTED_MAPPER = -11,
/**
* Vs DualSystem is unsupported.
*/
RESULT_ERR_UNSUPPORTED_VSSYSTEM = -10,
/**
* File format version is no longer supported.
*/
RESULT_ERR_UNSUPPORTED_FILE_VERSION = -9,
/**
* Unsupported operation.
*/
RESULT_ERR_UNSUPPORTED = -8,
/**
* Invalid CRC checksum.
*/
RESULT_ERR_INVALID_CRC = -7,
/**
* Corrupt file.
*/
RESULT_ERR_CORRUPT_FILE = -6,
/**
* Invalid file.
*/
RESULT_ERR_INVALID_FILE = -5,
/**
* Invalid parameter(s).
*/
RESULT_ERR_INVALID_PARAM = -4,
/**
* System not ready.
*/
RESULT_ERR_NOT_READY = -3,
/**
* Out of memory.
*/
RESULT_ERR_OUT_OF_MEMORY = -2,
/**
* Generic error.
*/
RESULT_ERR_GENERIC = -1,
/**
* Success.
*/
RESULT_OK = 0,
/**
* Success but operation had no effect.
*/
RESULT_NOP = 1,
/**
* Success but image dump may be bad.
*/
RESULT_WARN_BAD_DUMP = 2,
/**
* Success but PRG-ROM may be bad.
*/
RESULT_WARN_BAD_PROM = 3,
/**
* Success but CHR-ROM may be bad.
*/
RESULT_WARN_BAD_CROM = 4,
/**
* Success but file header may have incorrect data.
*/
RESULT_WARN_BAD_FILE_HEADER = 5,
/**
* Success but save data has been lost.
*/
RESULT_WARN_SAVEDATA_LOST = 6,
/**
* Success but data may have been replaced.
*/
RESULT_WARN_DATA_REPLACED = 8
};
namespace Core
{
enum Region
{
REGION_NTSC,
REGION_PAL
};
enum System
{
SYSTEM_NES_NTSC,
SYSTEM_NES_PAL,
SYSTEM_NES_PAL_A,
SYSTEM_NES_PAL_B,
SYSTEM_FAMICOM,
SYSTEM_DENDY,
SYSTEM_VS_UNISYSTEM,
SYSTEM_VS_DUALSYSTEM,
SYSTEM_PLAYCHOICE_10
};
enum FavoredSystem
{
FAVORED_NES_NTSC,
FAVORED_NES_PAL,
FAVORED_FAMICOM,
FAVORED_DENDY
};
enum CpuModel
{
CPU_RP2A03,
CPU_RP2A07,
CPU_DENDY
};
enum PpuModel
{
PPU_RP2C02,
PPU_RP2C03B,
PPU_RP2C03G,
PPU_RP2C04_0001,
PPU_RP2C04_0002,
PPU_RP2C04_0003,
PPU_RP2C04_0004,
PPU_RC2C03B,
PPU_RC2C03C,
PPU_RC2C05_01,
PPU_RC2C05_02,
PPU_RC2C05_03,
PPU_RC2C05_04,
PPU_RC2C05_05,
PPU_RP2C07,
PPU_DENDY
};
enum
{
CLK_M2_MUL = 6,
CLK_NTSC = 39375000UL * CLK_M2_MUL,
CLK_NTSC_DIV = 11,
CLK_NTSC_HVSYNC = 525UL * 455 * CLK_NTSC_DIV * CLK_M2_MUL / 4,
CLK_PAL = 35468950UL * CLK_M2_MUL,
CLK_PAL_DIV = 8,
CLK_PAL_HVSYNC = 625UL * 1418758 / (10000/CLK_PAL_DIV) * CLK_M2_MUL
};
enum
{
CPU_RP2A03_CC = 12,
CPU_RP2A07_CC = 16,
CPU_DENDY_CC = 15
};
enum
{
PPU_RP2C02_CC = 4,
PPU_RP2C02_HACTIVE = PPU_RP2C02_CC * 256,
PPU_RP2C02_HBLANK = PPU_RP2C02_CC * 85,
PPU_RP2C02_HSYNC = PPU_RP2C02_HACTIVE + PPU_RP2C02_HBLANK,
PPU_RP2C02_VACTIVE = 240,
PPU_RP2C02_VSLEEP = 1,
PPU_RP2C02_VINT = 20,
PPU_RP2C02_VDUMMY = 1,
PPU_RP2C02_VBLANK = PPU_RP2C02_VSLEEP + PPU_RP2C02_VINT + PPU_RP2C02_VDUMMY,
PPU_RP2C02_VSYNC = PPU_RP2C02_VACTIVE + PPU_RP2C02_VBLANK,
PPU_RP2C02_HVSYNCBOOT = PPU_RP2C02_VACTIVE * PPU_RP2C02_HSYNC + PPU_RP2C02_CC * 312,
PPU_RP2C02_HVREGBOOT = (PPU_RP2C02_VACTIVE + PPU_RP2C02_VINT) * PPU_RP2C02_HSYNC + PPU_RP2C02_CC * 314,
PPU_RP2C02_HVINT = PPU_RP2C02_VINT * ulong(PPU_RP2C02_HSYNC),
PPU_RP2C02_HVSYNC_0 = PPU_RP2C02_VSYNC * ulong(PPU_RP2C02_HSYNC),
PPU_RP2C02_HVSYNC_1 = PPU_RP2C02_VSYNC * ulong(PPU_RP2C02_HSYNC) - PPU_RP2C02_CC,
PPU_RP2C02_HVSYNC = (PPU_RP2C02_HVSYNC_0 + ulong(PPU_RP2C02_HVSYNC_1)) / 2,
PPU_RP2C02_FPS = (CLK_NTSC + CLK_NTSC_DIV * ulong(PPU_RP2C02_HVSYNC) / 2) / (CLK_NTSC_DIV * ulong(PPU_RP2C02_HVSYNC)),
PPU_RP2C07_CC = 5,
PPU_RP2C07_HACTIVE = PPU_RP2C07_CC * 256,
PPU_RP2C07_HBLANK = PPU_RP2C07_CC * 85,
PPU_RP2C07_HSYNC = PPU_RP2C07_HACTIVE + PPU_RP2C07_HBLANK,
PPU_RP2C07_VACTIVE = 240,
PPU_RP2C07_VSLEEP = 1,
PPU_RP2C07_VINT = 70,
PPU_RP2C07_VDUMMY = 1,
PPU_RP2C07_VBLANK = PPU_RP2C07_VSLEEP + PPU_RP2C07_VINT + PPU_RP2C07_VDUMMY,
PPU_RP2C07_VSYNC = PPU_RP2C07_VACTIVE + PPU_RP2C07_VBLANK,
PPU_RP2C07_HVSYNCBOOT = PPU_RP2C07_VACTIVE * PPU_RP2C07_HSYNC + PPU_RP2C07_CC * 312,
PPU_RP2C07_HVREGBOOT = (PPU_RP2C07_VACTIVE + PPU_RP2C07_VINT) * PPU_RP2C07_HSYNC + PPU_RP2C07_CC * 314,
PPU_RP2C07_HVINT = PPU_RP2C07_VINT * ulong(PPU_RP2C07_HSYNC),
PPU_RP2C07_HVSYNC = PPU_RP2C07_VSYNC * ulong(PPU_RP2C07_HSYNC),
PPU_RP2C07_FPS = (CLK_PAL + CLK_PAL_DIV * ulong(PPU_RP2C07_HVSYNC) / 2) / (CLK_PAL_DIV * ulong(PPU_RP2C07_HVSYNC)),
PPU_DENDY_CC = 5,
PPU_DENDY_HACTIVE = PPU_DENDY_CC * 256,
PPU_DENDY_HBLANK = PPU_DENDY_CC * 85,
PPU_DENDY_HSYNC = PPU_DENDY_HACTIVE + PPU_DENDY_HBLANK,
PPU_DENDY_VACTIVE = 240,
PPU_DENDY_VSLEEP = 51,
PPU_DENDY_VINT = 20,
PPU_DENDY_VDUMMY = 1,
PPU_DENDY_VBLANK = PPU_DENDY_VSLEEP + PPU_DENDY_VINT + PPU_DENDY_VDUMMY,
PPU_DENDY_VSYNC = PPU_DENDY_VACTIVE + PPU_DENDY_VBLANK,
PPU_DENDY_HVSYNCBOOT = PPU_DENDY_VACTIVE * PPU_DENDY_HSYNC + PPU_DENDY_CC * 312,
PPU_DENDY_HVREGBOOT = (PPU_DENDY_VACTIVE + PPU_DENDY_VINT) * PPU_DENDY_HSYNC + PPU_DENDY_CC * 314,
PPU_DENDY_HVINT = PPU_DENDY_VINT * ulong(PPU_DENDY_HSYNC),
PPU_DENDY_HVSYNC = PPU_DENDY_VSYNC * ulong(PPU_DENDY_HSYNC),
PPU_DENDY_FPS = (CLK_PAL + CLK_PAL_DIV * ulong(PPU_DENDY_HVSYNC) / 2) / (CLK_PAL_DIV * ulong(PPU_DENDY_HVSYNC))
};
template<typename T>
class ImplicitBool;
template<>
class ImplicitBool<void>
{
public:
int type;
typedef int ImplicitBool<void>::*Type;
};
template<typename T>
class ImplicitBool
{
template<typename U> void operator == (const ImplicitBool<U>&) const;
template<typename U> void operator != (const ImplicitBool<U>&) const;
public:
operator ImplicitBool<void>::Type () const
{
return !static_cast<const T&>(*this) ? 0 : &ImplicitBool<void>::type;
}
};
}
}
#define NES_FAILED(x_) ((x_) < Nes::RESULT_OK)
#define NES_SUCCEEDED(x_) ((x_) >= Nes::RESULT_OK)
#endif