mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
445 lines
8.5 KiB
C++
445 lines
8.5 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_MANAGER_EMULATOR_H
|
|
#define NST_MANAGER_EMULATOR_H
|
|
|
|
#pragma once
|
|
|
|
#include "NstCollectionVector.hpp"
|
|
#include "NstObjectDelegate.hpp"
|
|
#include "NstString.hpp"
|
|
#include "../core/api/NstApiEmulator.hpp"
|
|
#include "../core/api/NstApiVideo.hpp"
|
|
#include "../core/api/NstApiSound.hpp"
|
|
#include "../core/api/NstApiInput.hpp"
|
|
#include "../core/api/NstApiMachine.hpp"
|
|
#include "../core/api/NstApiUser.hpp"
|
|
|
|
namespace Nes
|
|
{
|
|
using namespace Api;
|
|
}
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Managers
|
|
{
|
|
class Emulator : public Nes::Emulator
|
|
{
|
|
public:
|
|
|
|
Emulator();
|
|
~Emulator();
|
|
|
|
typedef int Data;
|
|
|
|
enum Alert
|
|
{
|
|
NOISY,
|
|
QUIETLY,
|
|
STICKY
|
|
};
|
|
|
|
enum DiskImageSaveMethod
|
|
{
|
|
DISKIMAGE_SAVE_DISABLED,
|
|
DISKIMAGE_SAVE_TO_IMAGE,
|
|
DISKIMAGE_SAVE_TO_PATCH
|
|
};
|
|
|
|
enum Event
|
|
{
|
|
EVENT_LOAD = 1,
|
|
EVENT_UNLOAD,
|
|
EVENT_POWER_ON,
|
|
EVENT_POWER_OFF,
|
|
EVENT_RESET_SOFT,
|
|
EVENT_RESET_HARD,
|
|
EVENT_MODE_NTSC,
|
|
EVENT_MODE_PAL,
|
|
EVENT_PAUSE,
|
|
EVENT_RESUME,
|
|
EVENT_NETPLAY_MODE,
|
|
EVENT_SPEED,
|
|
EVENT_BASE_SPEED,
|
|
EVENT_SPEEDING_ON,
|
|
EVENT_SPEEDING_OFF,
|
|
EVENT_DISK_INSERT,
|
|
EVENT_DISK_EJECT,
|
|
EVENT_DISK_NONSTANDARD,
|
|
EVENT_DISK_QUERY_BIOS,
|
|
EVENT_TAPE_PLAYING,
|
|
EVENT_TAPE_RECORDING,
|
|
EVENT_TAPE_STOPPED,
|
|
EVENT_MOVIE_PLAYING,
|
|
EVENT_MOVIE_PLAYING_STOPPED,
|
|
EVENT_MOVIE_RECORDING,
|
|
EVENT_MOVIE_RECORDING_STOPPED,
|
|
EVENT_REWINDING_ON,
|
|
EVENT_REWINDING_OFF,
|
|
EVENT_REWINDING_PREPARE,
|
|
EVENT_REWINDING_START,
|
|
EVENT_REWINDING_STOP,
|
|
EVENT_NSF_PLAY,
|
|
EVENT_NSF_STOP,
|
|
EVENT_NSF_SELECT,
|
|
EVENT_PORT1_CONTROLLER,
|
|
EVENT_PORT2_CONTROLLER,
|
|
EVENT_PORT3_CONTROLLER,
|
|
EVENT_PORT4_CONTROLLER,
|
|
EVENT_PORT5_CONTROLLER,
|
|
EVENT_PORT_ADAPTER
|
|
};
|
|
|
|
enum Command
|
|
{
|
|
COMMAND_RESET = 1,
|
|
COMMAND_DISK_INSERT,
|
|
COMMAND_DISK_EJECT
|
|
};
|
|
|
|
enum
|
|
{
|
|
NUM_COMMANDS = 3,
|
|
DEFAULT_SPEED = 0,
|
|
MASTER = 0
|
|
};
|
|
|
|
struct Context
|
|
{
|
|
Context();
|
|
~Context();
|
|
|
|
enum
|
|
{
|
|
UNKNOWN = INT_MAX
|
|
};
|
|
|
|
Path image;
|
|
Path save;
|
|
Path state;
|
|
Path tape;
|
|
Path movie;
|
|
Path samples;
|
|
uint controllers[Nes::Input::NUM_PORTS];
|
|
uint mode;
|
|
};
|
|
|
|
void Stop();
|
|
void Pause(bool);
|
|
void ResetSpeed(uint,bool,bool);
|
|
void SetSpeed(uint);
|
|
uint GetDefaultSpeed();
|
|
uint GetBaseSpeed();
|
|
uint GetSpeed();
|
|
void ToggleSpeed(bool);
|
|
void ToggleRewind(bool);
|
|
|
|
bool Load
|
|
(
|
|
const Collection::Buffer&,
|
|
const Path&,
|
|
const Collection::Buffer&,
|
|
bool,
|
|
const Context&,
|
|
Nes::Machine::FavoredSystem,
|
|
Nes::Machine::AskProfile,
|
|
bool
|
|
);
|
|
|
|
void Unload();
|
|
void SendCommand(Command,Data=0);
|
|
bool SaveState(Collection::Buffer&,bool,Alert=NOISY);
|
|
bool LoadState(Collection::Buffer&,Alert=NOISY);
|
|
bool Power(bool);
|
|
void Execute(Nes::Video::Output*,Nes::Sound::Output*,Nes::Input::Controllers*);
|
|
void BeginNetplayMode();
|
|
void EndNetplayMode();
|
|
void StopNetplay();
|
|
void Unhook();
|
|
|
|
bool IsImage();
|
|
bool IsGame();
|
|
bool IsCart();
|
|
bool IsFds();
|
|
bool IsNsf();
|
|
bool IsOn();
|
|
bool IsImageOn();
|
|
bool IsGameOn();
|
|
bool IsCartOn();
|
|
bool IsFdsOn();
|
|
bool IsNsfOn();
|
|
bool IsLocked();
|
|
|
|
static uint ResultToString(Nes::Result);
|
|
|
|
private:
|
|
|
|
struct Callbacks;
|
|
|
|
class EventHandler
|
|
{
|
|
friend class Emulator;
|
|
friend struct Callbacks;
|
|
|
|
typedef Object::Delegate<void,Event,Data> Callback;
|
|
typedef Collection::Vector<Callback> Callbacks;
|
|
|
|
Callbacks callbacks;
|
|
|
|
~EventHandler();
|
|
|
|
void operator () (Event,Data=0) const;
|
|
void Add(const Callback&);
|
|
|
|
public:
|
|
|
|
void Remove(const void*);
|
|
|
|
template<typename Data,typename Code>
|
|
void Add(Data* data,Code code)
|
|
{
|
|
Add( Callback(data,code) );
|
|
}
|
|
};
|
|
|
|
struct Settings
|
|
{
|
|
Settings();
|
|
~Settings();
|
|
|
|
void Reset();
|
|
|
|
struct Timing
|
|
{
|
|
inline Timing();
|
|
|
|
uint speed;
|
|
uint baseSpeed;
|
|
bool speeding;
|
|
bool sync;
|
|
bool tripleBuffering;
|
|
bool rewinding;
|
|
};
|
|
|
|
struct Fds
|
|
{
|
|
inline Fds();
|
|
|
|
DiskImageSaveMethod save;
|
|
};
|
|
|
|
struct Cartridge
|
|
{
|
|
inline Cartridge();
|
|
|
|
bool writeProtect;
|
|
};
|
|
|
|
Timing timing;
|
|
|
|
struct
|
|
{
|
|
Path start;
|
|
Path image;
|
|
Path save;
|
|
Path tape;
|
|
Path samples;
|
|
} paths;
|
|
|
|
Cartridge cartridge;
|
|
Fds fds;
|
|
bool askSave;
|
|
};
|
|
|
|
struct State
|
|
{
|
|
typedef Object::Delegate<bool> Activator;
|
|
typedef Object::Delegate<void> Inactivator;
|
|
|
|
inline State();
|
|
|
|
bool NoActivator();
|
|
void NoInactivator();
|
|
|
|
bool running;
|
|
bool paused;
|
|
Activator activator;
|
|
Inactivator inactivator;
|
|
};
|
|
|
|
struct Netplay : ImplicitBool<Netplay>
|
|
{
|
|
Netplay();
|
|
|
|
typedef Object::Delegate<void,Command,Data> Commander;
|
|
typedef Object::Delegate<void,Nes::Input::Controllers&> Executor;
|
|
|
|
Executor executor;
|
|
Commander commander;
|
|
uint player;
|
|
uint players;
|
|
|
|
bool operator ! () const
|
|
{
|
|
return !executor;
|
|
}
|
|
};
|
|
|
|
bool UsesBaseSpeed() const;
|
|
void StartNetplay(const Netplay::Executor&,const Netplay::Commander&,uint,uint);
|
|
bool Start();
|
|
|
|
Nes::Result Load
|
|
(
|
|
const Collection::Buffer&,
|
|
const Collection::Buffer&,
|
|
bool,
|
|
Nes::Machine::FavoredSystem,
|
|
Nes::Machine::AskProfile,
|
|
bool
|
|
);
|
|
|
|
void LoadFileData(Nes::User::File&,bool,Path,wcstring) const;
|
|
void LoadImageData(Nes::User::File&) const;
|
|
void SaveImageData(Nes::User::File&) const;
|
|
void SaveDiskData(Nes::User::File&) const;
|
|
void LoadDiskData(Nes::User::File&) const;
|
|
void LoadSampleData(wcstring,Nes::User::File&) const;
|
|
|
|
State state;
|
|
EventHandler events;
|
|
Netplay netplay;
|
|
Settings settings;
|
|
|
|
public:
|
|
|
|
bool Resume()
|
|
{
|
|
return state.running || Start();
|
|
}
|
|
|
|
bool Running() const
|
|
{
|
|
return state.running;
|
|
}
|
|
|
|
bool Paused() const
|
|
{
|
|
return state.paused;
|
|
}
|
|
|
|
bool Speeding() const
|
|
{
|
|
return settings.timing.speeding;
|
|
}
|
|
|
|
bool Rewinding() const
|
|
{
|
|
return settings.timing.rewinding;
|
|
}
|
|
|
|
void AskBeforeSaving()
|
|
{
|
|
settings.askSave = true;
|
|
}
|
|
|
|
DiskImageSaveMethod GetDiskImageSaveMethod() const
|
|
{
|
|
return settings.fds.save;
|
|
}
|
|
|
|
void SetDiskImageSaveMethod(DiskImageSaveMethod method)
|
|
{
|
|
settings.fds.save = method;
|
|
}
|
|
|
|
void WriteProtectCartridge(bool state)
|
|
{
|
|
settings.cartridge.writeProtect = state;
|
|
}
|
|
|
|
bool CartridgeWriteProtected() const
|
|
{
|
|
return settings.cartridge.writeProtect;
|
|
}
|
|
|
|
const Path& GetStartPath() const
|
|
{
|
|
return settings.paths.start;
|
|
}
|
|
|
|
const Path& GetImagePath() const
|
|
{
|
|
return settings.paths.image;
|
|
}
|
|
|
|
const Path& GetSavePath() const
|
|
{
|
|
return settings.paths.save;
|
|
}
|
|
|
|
bool SyncFrameRate() const
|
|
{
|
|
return settings.timing.sync;
|
|
}
|
|
|
|
bool UseTripleBuffering() const
|
|
{
|
|
return settings.timing.tripleBuffering;
|
|
}
|
|
|
|
uint GetPlayer() const
|
|
{
|
|
return netplay.player;
|
|
}
|
|
|
|
uint NetPlayers() const
|
|
{
|
|
return netplay.players;
|
|
}
|
|
|
|
EventHandler& Events()
|
|
{
|
|
return events;
|
|
}
|
|
|
|
template<typename Data,typename Activator,typename Inactivator>
|
|
void Hook(Data data,Activator activator,Inactivator inactivator)
|
|
{
|
|
state.activator.Set( data, activator );
|
|
state.inactivator.Set( data, inactivator );
|
|
}
|
|
|
|
template<typename Data,typename Executor,typename Commander>
|
|
void StartNetplay(Data data,Executor executor,Commander commander,uint player,uint players)
|
|
{
|
|
StartNetplay( Netplay::Executor(data,executor), Netplay::Commander(data,commander), player, players );
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|