/* Copyright (c) 2013-2017 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include #include #include #include #include "VFileDevice.h" #include #include #include #include #include #include #ifdef M_CORE_GB #include #endif #ifdef M_CORE_GBA #include #endif struct mCore; namespace QGBA { class ConfigController; class InputController; class LogController; class MultiplayerController; class Override; class CoreController : public QObject { Q_OBJECT public: static const bool VIDEO_SYNC = false; static const bool AUDIO_SYNC = true; enum class Feature { OPENGL = mCORE_FEATURE_OPENGL, }; class Interrupter { public: Interrupter(CoreController*, bool fromThread = false); Interrupter(std::shared_ptr, bool fromThread = false); Interrupter(const Interrupter&); ~Interrupter(); private: CoreController* m_parent; }; CoreController(mCore* core, QObject* parent = nullptr); ~CoreController(); mCoreThread* thread() { return &m_threadContext; } const color_t* drawContext(); QImage getPixels(); bool isPaused(); bool hasStarted(); mPlatform platform() const; QSize screenDimensions() const; bool supportsFeature(Feature feature) const { return m_threadContext.core->supportsFeature(m_threadContext.core, static_cast(feature)); } bool hardwareAccelerated() const { return m_hwaccel; } void loadConfig(ConfigController*); mCheatDevice* cheatDevice() { return m_threadContext.core->cheatDevice(m_threadContext.core); } #ifdef USE_DEBUGGERS mDebugger* debugger() { return m_threadContext.core->debugger; } void setDebugger(mDebugger*); #endif void setMultiplayerController(MultiplayerController*); void clearMultiplayerController(); MultiplayerController* multiplayerController() { return m_multiplayer; } mCacheSet* graphicCaches(); int stateSlot() const { return m_stateSlot; } void setOverride(std::unique_ptr override); Override* override() { return m_override.get(); } void setInputController(InputController*); void setLogger(LogController*); bool audioSync() const { return m_audioSync; } bool videoSync() const { return m_videoSync; } void addFrameAction(std::function callback); public slots: void start(); void stop(); void reset(); void setPaused(bool paused); void frameAdvance(); void setSync(bool enable); void setRewinding(bool); void rewind(int count = 0); void setFastForward(bool); void forceFastForward(bool); void loadState(int slot = 0); void loadState(const QString& path); void saveState(int slot = 0); void saveState(const QString& path); void loadBackupState(); void saveBackupState(); void loadSave(const QString&, bool temporary); void loadPatch(const QString&); void scanCard(const QString&); void replaceGame(const QString&); void yankPak(); void addKey(int key); void clearKey(int key); void setAutofire(int key, bool enable); #ifdef USE_PNG void screenshot(); #endif void setRealTime(); void setFixedTime(const QDateTime& time); void setFakeEpoch(const QDateTime& time); void importSharkport(const QString& path); void exportSharkport(const QString& path); #ifdef M_CORE_GB void attachPrinter(); void detachPrinter(); void endPrint(); #endif #ifdef M_CORE_GBA void attachBattleChipGate(); void detachBattleChipGate(); void setBattleChipId(uint16_t id); void setBattleChipFlavor(int flavor); #endif void setAVStream(mAVStream*); void clearAVStream(); void clearOverride(); void startVideoLog(const QString& path, bool compression = true); void startVideoLog(VFile* vf, bool compression = true); void endVideoLog(bool closeVf = true); void setFramebufferHandle(int fb); signals: void started(); void paused(); void unpaused(); void stopping(); void crashed(const QString& errorMessage); void failed(); void frameAvailable(); void didReset(); void stateLoaded(); void rewound(); void rewindChanged(bool); void fastForwardChanged(bool); void unimplementedBiosCall(int); void statusPosted(const QString& message); void logPosted(int level, int category, const QString& log); void imagePrinted(const QImage&); private: void updateKeys(); int updateAutofire(); void finishFrame(); void updateFastForward(); mCoreThread m_threadContext{}; bool m_patched = false; QByteArray m_activeBuffer; QByteArray m_completeBuffer; bool m_hwaccel = false; std::unique_ptr m_cacheSet; std::unique_ptr m_override; QList> m_resetActions; QList> m_frameActions; QMutex m_actionMutex{QMutex::Recursive}; QMutex m_bufferMutex; int m_activeKeys = 0; bool m_autofire[32] = {}; int m_autofireStatus[32] = {}; int m_autofireThreshold = 1; VFileDevice m_backupLoadState; QByteArray m_backupSaveState{nullptr}; int m_stateSlot = 1; QString m_statePath; int m_loadStateFlags; int m_saveStateFlags; bool m_audioSync = AUDIO_SYNC; bool m_videoSync = VIDEO_SYNC; bool m_autosave; bool m_autoload; int m_autosaveCounter = 0; int m_fastForward = false; int m_fastForwardForced = false; int m_fastForwardVolume = -1; int m_fastForwardMute = -1; float m_fastForwardRatio = -1.f; float m_fastForwardHeldRatio = -1.f; float m_fpsTarget; InputController* m_inputController = nullptr; LogController* m_log = nullptr; MultiplayerController* m_multiplayer = nullptr; mVideoLogContext* m_vl = nullptr; VFile* m_vlVf = nullptr; #ifdef M_CORE_GB struct QGBPrinter { GBPrinter d; CoreController* parent; } m_printer; #endif #ifdef M_CORE_GBA GBASIOBattlechipGate m_battlechip; QByteArray m_eReaderData; #endif }; }