Source

gb_emulator / gb_emulator / include / gb_emulator / gb.hpp

Full commit
/*  Copyright © 2011 Chris Spencer <spencercw@gmail.com>

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef GB_HPP_5D666040_89F8_11E0_9282_0002A5D5C51B
#define GB_HPP_5D666040_89F8_11E0_9282_0002A5D5C51B

// Ignore warnings about DLL interfaces on member variables
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif

#include <stdint.h>

#include <string>
#include <vector>

#include <boost/asio/io_service.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>

#include <gb_emulator/defs.hpp>
#include <gb_emulator/gb_cpu.hpp>
#include <gb_emulator/gb_debugger.h>
#include <gb_emulator/gb_debugger_module.h>
#include <gb_emulator/gb_timers.hpp>

class GbCommsSerial;
class GbConfig;
class GbDebugger;
class GbInput;
class GbMemoryImpl;
class GbSoundSdl;
class GbSoundWasapi;
class GbVideoD3D11;
class GbVideoSdl;

//! Main class for the GameBoy emulator.
/**
 * This class encompasses the entire emulator state.
 */
class GB_EMULATOR_API Gb
{
	friend class GbCommsSerial;
	friend class GbCpu;
	friend class GbTimers;
	friend class GbInput;
	friend class GbMemoryImpl;
	friend class GbSound;
	friend class GbSoundSdl;
	friend class GbSoundWasapi;
	friend class GbVideo;
	friend class GbVideoD3D11;
	friend class GbDebugger;

public:
	//! Constructor; sets the configuration options and loads the BIOS.
	Gb(const GbConfig &config);

	//! Destructor.
	~Gb();

	//! Runs the emulator.
	/**
	 * This doesn't return until the emulator exited or there is an error.
	 */
	void run();

	//! Resets the emulator.
	/**
	 * Path to the new ROM to load; may be empty, in which case no ROM is loaded.
	 */
	void reset(const boost::filesystem::path &rom = boost::filesystem::path());

	//! Saves the current state of the emulator.
	/**
	 * The file is saved with the same name as the ROM file with the extension replaced with ".sav".
	 */
	void save() const;

	//! Loads the emulator state from file.
	/**
	 * This is to be used in conjunction with save().
	 */
	void load();

	//! Saves the battery-backed RAM to a file.
	/**
	 * This is what games use to save data. The data is automatically reloaded when the emulator
	 * starts if the file is present.
	 */
	void saveRam() const;

private:
	// Possible syncronisation clock sources
	enum ClockSource
	{
		// The syncronisation clock is derived from the clock provided by the sound sub-system
		CLOCK_NORMAL,
		// The syncronisation clock provided by a remote server. This is used when an active serial
		// comms connection is established to keep the two emulators in sync.
		CLOCK_REMOTE
	};

	// I/O service used by various sub-systems
	boost::asio::io_service ioService_;

#ifdef _WIN32
	// Loaded plugin modules. The values in this vector are not actually used; they are only saved
	// so they are automatically freed when the class is destructed. Note it is important that these
	// are freed after the values in debuggers_.
	std::vector<boost::shared_ptr<HINSTANCE__> > debuggerModules_;
#endif
	// Loaded debuggers
	std::vector<boost::shared_ptr<GbDebuggerModule> > debuggers_;

	// Emulator state
	std::basic_string<uint8_t> bios_;
	std::basic_string<uint8_t> rom_;

	// Number of frames to draw before sleeping. This is incremented at ~57Hz using the sound clock
	// (soundTimerCallback) and decremented every time one frame's worth of CPU cycles is executed.
	// This is used to keep the emulator running at the correct speed and to keep the sound being
	// generated at exactly the same rate at which it is consumed.
	unsigned frames_;

	// The source of the synchronisation clock. This is used to keep the emulator running at the
	// correct speed.
	ClockSource clockSource_;

	boost::scoped_ptr<GbCpu> cpu_;
	boost::scoped_ptr<GbSound> sound_;
	boost::scoped_ptr<GbVideo> video_;
	boost::scoped_ptr<GbMemoryImpl> mem_;
	boost::scoped_ptr<GbInput> input_;
	boost::scoped_ptr<GbCommsSerial> serial_;
	int serialCycles_;
	GbTimers timers_;
	GbDebugger debugger_;
	bool gbc_;

	// Filenames
	boost::filesystem::path installDir_;
	boost::filesystem::path biosFilename_;
	boost::filesystem::path romFilename_;
	boost::filesystem::path saveFilename_;
	boost::filesystem::path saveRamFilename_;

	// Disabled operations
	Gb(const Gb &);
	Gb & operator=(const Gb &);

	// Common initialisation code
	void init(const boost::filesystem::path &bios);

	// Loads the given ROM file
	void loadRom(const boost::filesystem::path &romPath);

	// Loads the battery-backed RAM from the saved file, if available
	void loadRam();

	// Loads any debugger plugins
	void loadDebuggers();

	// Callback which is called at ~57Hz using the sound clock. This simply increments frames_ to
	// indicate another frame's worth of CPU cycles should be executed.
	void soundTimerCallback();

#ifndef _WIN32
	static int timespecSubtract(timespec *result, const timespec *lhs, const timespec *rhs);
#endif
};

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif