//////////////////////////////////////////////////////////////////////////////////////// // // 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_VSSYSTEM_H #define NST_VSSYSTEM_H #include "../api/NstApiInput.hpp" #include "../NstDipSwitches.hpp" #include "../NstCartridge.hpp" #ifdef NST_PRAGMA_ONCE #pragma once #endif namespace Nes { namespace Core { class Cartridge::VsSystem { public: enum Mode { MODE_STD, MODE_RBI, MODE_TKO, MODE_XEV }; static VsSystem* Create(Cpu&,Ppu&,PpuModel,dword); static void Destroy(VsSystem*); void Reset(bool); void SaveState(State::Saver&,dword) const; void LoadState(State::Loader&); protected: struct Context; explicit VsSystem(Context&); virtual ~VsSystem(); private: class RbiBaseball; class SuperXevious; class TkoBoxing; virtual void Reset() {} virtual void SubSave(State::Saver&) const {} virtual void SubLoad(State::Loader&,dword) {} class Dip; class VsDipSwitches : public DipSwitches { public: VsDipSwitches(Dip*&,uint); ~VsDipSwitches(); inline uint Reg(uint) const; inline void Reset(); void BeginFrame(Input::Controllers*); private: uint NumDips() const; uint NumValues(uint) const; cstring GetDipName(uint) const; cstring GetValueName(uint,uint) const; uint GetValue(uint) const; void SetValue(uint,uint); uint coinTimer; Dip* const table; const uint size; uint regs[2]; }; enum { DIPSWITCH_4016_MASK = 0x03, DIPSWITCH_4016_SHIFT = 3, DIPSWITCH_4017_MASK = 0xFC, DIPSWITCH_4017_SHIFT = 0, COIN_1 = Input::Controllers::VsSystem::COIN_1, COIN_2 = Input::Controllers::VsSystem::COIN_2, COIN = COIN_1|COIN_2, STATUS_4016_MASK = uint(DIPSWITCH_4016_MASK) << DIPSWITCH_4016_SHIFT | COIN, STATUS_4017_MASK = uint(DIPSWITCH_4017_MASK) << DIPSWITCH_4017_SHIFT }; NES_DECL_PEEK( Nop ); NES_DECL_POKE( Nop ); NES_DECL_PEEK( 4016 ); NES_DECL_POKE( 4016 ); NES_DECL_PEEK( 4017 ); NES_DECL_POKE( 4017 ); NES_DECL_PEEK( 4020 ); NES_DECL_POKE( 4020 ); protected: Cpu& cpu; Ppu& ppu; private: class InputMapper { typedef Input::Controllers::Pad Pad; virtual void Fix(Pad (&)[4],const uint (&)[2]) const = 0; void* userData; Pad::PollCallback userCallback; struct Type1; struct Type2; struct Type3; struct Type4; struct Type5; public: enum Type { TYPE_NONE, TYPE_1, TYPE_2, TYPE_3, TYPE_4, TYPE_5 }; static InputMapper* Create(Type); virtual ~InputMapper() {} void Begin(const Api::Input,Input::Controllers*); void End() const; }; InputMapper* const inputMapper; Io::Port p4016; Io::Port p4017; VsDipSwitches dips; uint coin; const PpuModel ppuModel; public: void BeginFrame(const Api::Input& input,Input::Controllers* controllers) { dips.BeginFrame( controllers ); if (inputMapper) inputMapper->Begin( input, controllers ); } void VSync() const { if (inputMapper) inputMapper->End(); } PpuModel GetPpuModel() const { return ppuModel; } DipSwitches& GetDipSwiches() { return dips; } }; } } #endif