//////////////////////////////////////////////////////////////////////////////////////// // // 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_API_CARTRIDGE_H #define NST_API_CARTRIDGE_H #include #include #include #include "NstApiInput.hpp" #include "NstApiMachine.hpp" #ifdef NST_PRAGMA_ONCE #pragma once #endif #if NST_MSVC >= 1200 #pragma warning( push ) #pragma warning( disable : 4512 ) #endif namespace Nes { namespace Api { /** * Cartridge interface. */ class Cartridge : public Base { struct ChooseProfileCaller; public: /** * Interface constructor. * * @param instance emulator instance */ template Cartridge(T& instance) : Base(instance) {} /** * Cartridge profile context. **/ struct Profile { Profile() throw(); ~Profile() throw(); /** * Hash checksum. * * Stores SHA-1 and CRC-32 combined or just one of the two. */ class Hash : public Core::ImplicitBool { public: enum { SHA1_LENGTH = 40, SHA1_WORD_LENGTH = SHA1_LENGTH / 8, CRC32_LENGTH = 8, CRC32_WORD_LENGTH = CRC32_LENGTH / 8 }; /** * Default constructor. */ Hash() throw(); /** * Constructs new checksum from null-terminated strings. * * @param sha SHA-1 string, set to NULL if values shouldn't be used * @param crc CRC-32 string, set to NULL if value shouldn't be used */ Hash(const char* sha,const char* crc) throw(); /** * Constructs new checksum from null-terminated wide-strings. * * @param sha SHA-1 string, set to NULL if values shouldn't be used * @param crc CRC-32 string, set to NULL if value shouldn't be used */ Hash(const wchar_t* sha,const wchar_t* crc) throw(); /** * Constructs new checksum from input values. * * @param sha SHA-1 value, set to NULL if values shouldn't be used * @param crc CRC-32 value, set to 0 if value shouldn't be used */ Hash(const dword* sha,dword crc) throw(); /** * Tests for less-than. * * @param hash hash to compare with * @return true if input hash is less than this */ bool operator < (const Hash& hash) const throw(); /** * Tests for equality. * * @param hash hash to compare with * @return true if hashes are equal */ bool operator == (const Hash& hash) const throw(); /** * Checks if checksum is cleared. * * @return true if cleared */ bool operator ! () const throw(); /** * Computes and updates checksum from input. * * @param mem pointer to memory * @param length length of memory in bytes */ void Compute(const void* mem,ulong length) throw(); /** * Assigns new checksum from null-terminated strings. * * @param sha SHA-1 string, set to NULL if values shouldn't be used * @param crc CRC-32 string, set to NULL if value shouldn't be used */ void Assign(const char* sha,const char* crc) throw(); /** * Assigns new checksum from null-terminated wide-strings. * * @param sha SHA-1 string, set to NULL if values shouldn't be used * @param crc CRC-32 string, set to NULL if value shouldn't be used */ void Assign(const wchar_t* sha,const wchar_t* crc) throw(); /** * Assigns new checksum from input values. * * @param sha SHA-1 value, set to NULL if values shouldn't be used * @param crc CRC-32 value, set to 0 if value shouldn't be used */ void Assign(const dword* sha,dword crc) throw(); /** * Returns the current checksum. * * @param sha SHA-1 string to be filled, set to to NULL if not needed * @param crc CRC-32 string to be filled, set to NULL if not needed */ void Get(char* sha,char* crc) const throw(); /** * Clears the current checksum. */ void Clear() throw(); /** * Returns the current SHA-1 values. * * @return SHA-1 values, zero-filled if unused */ const dword* GetSha1() const throw(); /** * Returns the current CRC-32 value. * * @return CRC-32 value, 0 if unused */ dword GetCrc32() const throw(); private: template void Import(const T*,const T*); template static bool Set(dword&,const T* NST_RESTRICT); dword data[CRC32_WORD_LENGTH+SHA1_WORD_LENGTH]; }; /** * Game context. */ struct Game { Game() throw(); /** * Game title. */ std::wstring title; /** * Alternative game title. */ std::wstring altTitle; /** * Class. */ std::wstring clss; /** * Sub-class. */ std::wstring subClss; /** * Catalog. */ std::wstring catalog; /** * Publisher. */ std::wstring publisher; /** * Developer. */ std::wstring developer; /** * Port Developer. */ std::wstring portDeveloper; /** * Region. */ std::wstring region; /** * Revision. */ std::wstring revision; /** * Utilized controller adapter. */ Input::Adapter adapter; /** * Utilized controllers. */ Input::Type controllers[5]; /** * Number of players. */ uint players; }; /** * Dump context. */ struct Dump { Dump() throw(); /** * Dump state type. */ enum State { /** * Good dump. */ OK, /** * Bad dump. */ BAD, /** * Unknown dump. */ UNKNOWN }; /** * Dumped by. */ std::wstring by; /** * Dump date. */ std::wstring date; /** * Dump state. */ State state; }; /** * System context. */ struct System { System() throw(); /** * System Type. */ enum Type { /** * NES NTSC console. */ NES_NTSC = Core::SYSTEM_NES_NTSC, /** * NES PAL console. */ NES_PAL = Core::SYSTEM_NES_PAL, /** * NES PAL-A console. */ NES_PAL_A = Core::SYSTEM_NES_PAL_A, /** * NES PAL-B console. */ NES_PAL_B = Core::SYSTEM_NES_PAL_B, /** * Famicom console. */ FAMICOM = Core::SYSTEM_FAMICOM, /** * Dendy console (clone). */ DENDY = Core::SYSTEM_DENDY, /** * Vs UniSystem arcade. */ VS_UNISYSTEM = Core::SYSTEM_VS_UNISYSTEM, /** * Vs DualSystem arcade. */ VS_DUALSYSTEM = Core::SYSTEM_VS_DUALSYSTEM, /** * PlayChoice-10 arcade. */ PLAYCHOICE_10 = Core::SYSTEM_PLAYCHOICE_10 }; /** * CPU type. */ enum Cpu { /** * RP2A03 NTSC CPU. */ CPU_RP2A03 = Core::CPU_RP2A03, /** * RP2A07 PAL CPU. */ CPU_RP2A07 = Core::CPU_RP2A07, /** * Dendy CPU (clone). */ CPU_DENDY = Core::CPU_DENDY }; /** * PPU type. */ enum Ppu { /** * RP2C02 NTSC PPU. */ PPU_RP2C02 = Core::PPU_RP2C02, /** * RP2C03B RGB PPU. */ PPU_RP2C03B = Core::PPU_RP2C03B, /** * RP2C03G RGB PPU. */ PPU_RP2C03G = Core::PPU_RP2C03G, /** * RP2C04-0001 RGB PPU. */ PPU_RP2C04_0001 = Core::PPU_RP2C04_0001, /** * RP2C04-0002 RGB PPU. */ PPU_RP2C04_0002 = Core::PPU_RP2C04_0002, /** * RP2C04-0003 RGB PPU. */ PPU_RP2C04_0003 = Core::PPU_RP2C04_0003, /** * RP2C04-0004 RGB PPU. */ PPU_RP2C04_0004 = Core::PPU_RP2C04_0004, /** * RC2C03B RGB PPU. */ PPU_RC2C03B = Core::PPU_RC2C03B, /** * RC2C03C RGB PPU. */ PPU_RC2C03C = Core::PPU_RC2C03C, /** * RC2C05-01 RGB PPU. */ PPU_RC2C05_01 = Core::PPU_RC2C05_01, /** * RC2C05-02 RGB PPU. */ PPU_RC2C05_02 = Core::PPU_RC2C05_02, /** * RC2C05-03 RGB PPU. */ PPU_RC2C05_03 = Core::PPU_RC2C05_03, /** * RC2C05-04 RGB PPU. */ PPU_RC2C05_04 = Core::PPU_RC2C05_04, /** * RC2C05-05 RGB PPU. */ PPU_RC2C05_05 = Core::PPU_RC2C05_05, /** * RP2C07 PAL PPU. */ PPU_RP2C07 = Core::PPU_RP2C07, /** * Dendy PPU (clone). */ PPU_DENDY = Core::PPU_DENDY }; /** * System type. */ Type type; /** * CPU type. */ Cpu cpu; /** * PPU type. */ Ppu ppu; }; /** * Cartridge property. */ struct Property { /** * Name. */ std::wstring name; /** * Value. */ std::wstring value; }; /** * Cartridge properties. */ typedef std::vector Properties; /** * Board context. */ class Board { template dword GetComponentSize(const T&) const; template bool HasComponentBattery(const T&) const; public: Board() throw(); ~Board() throw(); /** * Returns total size of PRG-ROM. * * @return size */ dword GetPrg() const throw(); /** * Returns total size of CHR-ROM. * * @return size */ dword GetChr() const throw(); /** * Returns total size of W-RAM. * * @return size */ dword GetWram() const throw(); /** * Returns total size of V-RAM. * * @return size */ dword GetVram() const throw(); /** * Returns battery status. * * @return true if a battery is present */ bool HasBattery() const throw(); /** * Returns W-RAM battery status. * * @return true if a battery is present and connected to W-RAM */ bool HasWramBattery() const throw(); /** * Returns custom chip battery status. * * @return true if a battery is present and connected to a custom chip */ bool HasMmcBattery() const throw(); enum { SOLDERPAD_H = 0x1, SOLDERPAD_V = 0x2, NO_MAPPER = 0xFFFF }; /** * Pin context. */ struct Pin { Pin() throw(); /** * Pin number. */ uint number; /** * Pin function. */ std::wstring function; }; /** * Pins. */ typedef std::vector Pins; /** * Analogue sound sample context. */ struct Sample { Sample() throw(); /** * Sound sample id. */ uint id; /** * Sound sample file. */ std::wstring file; }; /** * Analogue sound samples. */ typedef std::vector Samples; /** * ROM chip. */ struct Rom { Rom() throw(); /** * ROM chip ID. */ dword id; /** * ROM chip size. */ dword size; /** * ROM chip name. */ std::wstring name; /** * File pointing to ROM chip. */ std::wstring file; /** * ROM chip package method. */ std::wstring package; /** * ROM chip pins. */ Pins pins; /** * ROM chip checksum. */ Hash hash; }; /** * RAM chip. */ struct Ram { Ram() throw(); /** * RAM chip ID. */ dword id; /** * RAM chip size. */ dword size; /** * File pointing to RAM chip. */ std::wstring file; /** * RAM chip package method. */ std::wstring package; /** * RAM chip pins. */ Pins pins; /** * Battery connected to RAM chip. */ bool battery; }; /** * Custom chip. */ struct Chip { Chip() throw(); /** * Custom chip type. */ std::wstring type; /** * File pointing to custom chip. */ std::wstring file; /** * Custom chip package type. */ std::wstring package; /** * Custom chip pins. */ Pins pins; /** * Analogue sound samples for custom chip. */ Samples samples; /** * battery connected to custom chip. */ bool battery; }; /** * ROM chips. */ typedef std::vector Roms; /** * RAM chips. */ typedef std::vector Rams; /** * Custom chips. */ typedef std::vector Chips; /** * PRG-ROM chips. */ typedef Roms Prg; /** * CHR-ROM chips. */ typedef Roms Chr; /** * W-RAM chips. */ typedef Rams Wram; /** * V-RAM chips. */ typedef Rams Vram; /** * Board type. */ std::wstring type; /** * CIC type. */ std::wstring cic; /** * Board PCB name. */ std::wstring pcb; /** * PRG-ROM. */ Prg prg; /** * CHR-ROM. */ Chr chr; /** * W-RAM. */ Wram wram; /** * V-RAM. */ Vram vram; /** * Custom chips. */ Chips chips; /** * Solder pads. */ uint solderPads; /** * Mapper ID. */ uint mapper; /** * Submapper ID. */ uint subMapper; /** * CHR RAM Size. */ uint chrRam; }; /** * Hash of ROM chips combined. */ Hash hash; /** * Dump context. */ Dump dump; /** * Game context. */ Game game; /** * System context. */ System system; /** * Board context. */ Board board; /** * Properties. */ Properties properties; /** * Multi-region game. */ bool multiRegion; /** * Soft-patching state. */ bool patched; }; /** * Database interface */ class Database { Core::Machine& emulator; bool Create(); public: /** * Interface constructor. * * @param instance emulator instance */ Database(Core::Machine& instance) : emulator(instance) {} /** * Database entry. */ class Entry : public Core::ImplicitBool { public: /** * Returns the profile of this entry. * * @param profile object to be filled * @return result code */ Result GetProfile(Profile& profile) const throw(); /** * Returns the game title. * * @return game title or empty string on invalid entry */ const wchar_t* GetTitle() const throw(); /** * Returns the target region. * * @return target region or empty string on invalid entry */ const wchar_t* GetRegion() const throw(); /** * Returns the target system. * * @return target system */ Profile::System::Type GetSystem() const throw(); /** * Checks if the game targets multiple regions. * * @return true if targeting multiple regions */ bool IsMultiRegion () const throw(); /** * Returns hash code of ROM chips combined. * * @return hash code or NULL on invalid entry */ const Profile::Hash* GetHash() const throw(); /** * Returns total size of PRG-ROM. * * @return size or 0 on invalid entry */ dword GetPrgRom() const throw(); /** * Returns total size of CHR-ROM. * * @return size or 0 on invalid entry */ dword GetChrRom() const throw(); /** * Returns total size of W-RAM. * * @return size or 0 on invalid entry */ uint GetWram() const throw(); /** * Returns total size of V-RAM. * * @return size or 0 on invalid entry */ uint GetVram() const throw(); /** * Returns mapper ID. * * @return mapper ID or 0 on invalid entry */ uint GetMapper() const throw(); /** * Returns battery status. * * @return true if a battery is present */ bool HasBattery() const throw(); /** * Returns the dump state. * * @return dump state */ Profile::Dump::State GetDumpState() const throw(); private: friend class Database; const void* ref; Entry(const void* r) : ref(r) {} public: /** * Default constructor. */ Entry() : ref(NULL) {} /** * Checks if entry is invalid. * * @return true if invalid */ bool operator ! () const { return !ref; } }; /** * Resets and loads internal XML database. * * @param stream input stream * @return result code */ Result Load(std::istream& stream) throw(); /** * Resets and loads internal and external XML databases. * * @param streamInternal input stream to internal XML database * @param streamExternal input stream to external XML database * @return result code */ Result Load(std::istream& streamInternal,std::istream& streamExternal) throw(); /** * Removes all databases from the system. */ void Unload() throw(); /** * Enables image corrections. * * @param state true to enable, default is true * @return result code */ Result Enable(bool state=true) throw(); /** * Checks if image corrections are enabled. * * @return true if enabled */ bool IsEnabled() const throw(); /** * Checks if any database has been loaded into the system. * * @return true if loaded */ bool IsLoaded() const throw(); /** * Attempts to locate and return an entry from one of the databases. * * @param hash hash code of combined ROMs * @param system preferred system in case of multiple profiles * @return entry found */ Entry FindEntry(const Profile::Hash& hash,Machine::FavoredSystem system) const throw(); /** * Attempts to locate and return an entry from one of the databases. * * @param mem pointer to memory of combined ROMs * @param size size of memory * @param system preferred system in case of multiple profiles * @return entry found */ Entry FindEntry(const void* mem,ulong size,Machine::FavoredSystem system) const throw(); }; /** * iNES header format context. */ struct NesHeader { NesHeader() throw(); /** * Clears settings. */ void Clear() throw(); /** * Imports settings from iNES file header in memory. * * @param pointer to iNES header at least 16 byte in size * @param size size of memory * @return result code */ Result Import(const void* mem,ulong size) throw(); /** * Exports settings to iNES file header in memory. * * @param pointer to iNES header at least 16 byte in size * @param size size of memory * @return result code */ Result Export(void* mem,ulong size) const throw(); enum { MAX_PRG_ROM = 0x4000 * 0xFFFUL, MAX_CHR_ROM = 0x2000 * 0xFFFUL }; /** * Region type. */ enum Region { /** * NTSC only. */ REGION_NTSC = 1, /** * PAL only. */ REGION_PAL, /** * Both PAL and NTSC. */ REGION_BOTH }; /** * System type. */ enum System { /** * Console. */ SYSTEM_CONSOLE, /** * Vs System */ SYSTEM_VS, /** * PlayChoice-10 */ SYSTEM_PC10 }; /** * PPU type. */ enum Ppu { /** * RP2C02 NTSC PPU. */ PPU_RP2C02 = Core::PPU_RP2C02, /** * RP2C03B RGB PPU. */ PPU_RP2C03B = Core::PPU_RP2C03B, /** * RP2C03G RGB PPU. */ PPU_RP2C03G = Core::PPU_RP2C03G, /** * RP2C04-0001 RGB PPU. */ PPU_RP2C04_0001 = Core::PPU_RP2C04_0001, /** * RP2C04-0002 RGB PPU. */ PPU_RP2C04_0002 = Core::PPU_RP2C04_0002, /** * RP2C04-0003 RGB PPU. */ PPU_RP2C04_0003 = Core::PPU_RP2C04_0003, /** * RP2C04-0004 RGB PPU. */ PPU_RP2C04_0004 = Core::PPU_RP2C04_0004, /** * RC2C03B RGB PPU. */ PPU_RC2C03B = Core::PPU_RC2C03B, /** * RC2C03C RGB PPU. */ PPU_RC2C03C = Core::PPU_RC2C03C, /** * RC2C05-01 RGB PPU. */ PPU_RC2C05_01 = Core::PPU_RC2C05_01, /** * RC2C05-02 RGB PPU. */ PPU_RC2C05_02 = Core::PPU_RC2C05_02, /** * RC2C05-03 RGB PPU. */ PPU_RC2C05_03 = Core::PPU_RC2C05_03, /** * RC2C05-04 RGB PPU. */ PPU_RC2C05_04 = Core::PPU_RC2C05_04, /** * RC2C05-05 RGB PPU. */ PPU_RC2C05_05 = Core::PPU_RC2C05_05, /** * RP2C07 PAL PPU. */ PPU_RP2C07 = Core::PPU_RP2C07 }; /** * Name-table mirroring type. */ enum Mirroring { /** * Horizontal mirroring. */ MIRRORING_HORIZONTAL, /** * Vertical mirroring. */ MIRRORING_VERTICAL, /** * Four-screen mirroring. */ MIRRORING_FOURSCREEN, /** * Single-screen mirroring. */ MIRRORING_SINGLESCREEN, /** * Software-controlled mirroring. */ MIRRORING_CONTROLLED }; /** * System. */ System system; /** * Region. */ Region region; /** * PRG-ROM size. */ dword prgRom; /** * volatile PRG-RAM (aka W-RAM) size. */ dword prgRam; /** * Non-volatile PRG-RAM (aka W-RAM) size. */ dword prgNvRam; /** * CHR-ROM size. */ dword chrRom; /** * volatile CHR-RAM (aka V-RAM) size. */ dword chrRam; /** * Non-volatile CHR-RAM (aka V-RAM) size. */ dword chrNvRam; /** * PPU. */ Ppu ppu; /** * Name-table mirroring. */ Mirroring mirroring; /** * Mapper ID. */ ushort mapper; /** * Sub-mapper ID. */ uchar subMapper; /** * iNES version number. */ uchar version; /** * Vs System security bits. */ uchar security; /** * Trainer. */ bool trainer; /** * Input Device Type. */ uchar inputType; }; /** * Returns the current cartridge profile. * * @return pointer to current profile, NULL if no cartridge has been loaded into the system */ const Profile* GetProfile() const throw(); /** * Creates a profile of an XML ROM set file. * * @param stream input stream to XML file * @param system preferred system in case of multiple profiles * @param askProfile allow callback triggering for choosing between multiple profiles * @param profile object to be filled * @return result code */ static Result ReadRomset(std::istream& stream,Machine::FavoredSystem system,bool askProfile,Profile& profile) throw(); /** * Creates a profile of an iNES file. * * @param stream input stream to iNES file * @param system preferred system in case of multiple profiles * @param profile object to be filled * @return result code */ static Result ReadInes(std::istream& stream,Machine::FavoredSystem system,Profile& profile) throw(); /** * Creates a profile of a UNIF file. * * @param stream input stream to UNIF file * @param system preferred system in case of multiple profiles * @param profile object to be filled * @return result code */ static Result ReadUnif(std::istream& stream,Machine::FavoredSystem system,Profile& profile) throw(); /** * Returns the database interface. * * @return database interface */ Database GetDatabase() throw() { return emulator; } enum { CHOOSE_DEFAULT_PROFILE = INT_MAX }; /** * Cartridge profile chooser callback prototype. * * @param userData optional user data * @param profiles pointer to an array of profiles * @param profileNames pointer to a wide-string array of profile names * @param numProfiles number of profiles to choose between * @return array index of chosen profile */ typedef uint (NST_CALLBACK *ChooseProfileCallback) (UserData userData,const Profile* profiles,const std::wstring* profileNames,uint numProfiles); /** * Cartridge profile chooser callback manager. * * Static object used for adding the user defined callback. */ static ChooseProfileCaller chooseProfileCallback; }; /** * Cartridge profile chooser callback invoker. * * Used internally by the core. */ struct Cartridge::ChooseProfileCaller : Core::UserCallback { uint operator () (const Profile* profiles,const std::wstring* names,uint count) const { return function ? function( userdata, profiles, names, count ) : CHOOSE_DEFAULT_PROFILE; } }; } } #if NST_MSVC >= 1200 #pragma warning( pop ) #endif #endif