Qt: Sloppy first pass at refactor

This commit is contained in:
Jeffrey Pfau 2016-02-07 20:07:35 -08:00
parent fc905657ad
commit d0771b78e2
32 changed files with 309 additions and 369 deletions

View File

@ -922,7 +922,7 @@ void GBAFrameEnded(struct GBA* gba) {
GBAHardwarePlayerUpdate(gba); GBAHardwarePlayerUpdate(gba);
} }
struct GBAThread* thread = GBAThreadGetContext(); struct mCoreThread* thread = mCoreThreadGet();
if (!thread) { if (!thread) {
return; return;
} }
@ -931,12 +931,7 @@ void GBAFrameEnded(struct GBA* gba) {
thread->frameCallback(thread); thread->frameCallback(thread);
} }
if (gba->rr && gba->rr->queryReset(gba->rr)) { // TODO: Put back RR
// TODO: Clean up reset scheduling
MutexLock(&thread->stateMutex);
thread->state = THREAD_RESETING;
MutexUnlock(&thread->stateMutex);
}
} }
void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {

View File

@ -8,9 +8,9 @@
#include "LogController.h" #include "LogController.h"
extern "C" { extern "C" {
#include "core/thread.h"
#include "gba/gba.h" #include "gba/gba.h"
#include "gba/audio.h" #include "gba/audio.h"
#include "gba/supervisor/thread.h"
} }
using namespace QGBA; using namespace QGBA;
@ -25,18 +25,18 @@ AudioDevice::AudioDevice(QObject* parent)
} }
void AudioDevice::setFormat(const QAudioFormat& format) { void AudioDevice::setFormat(const QAudioFormat& format) {
if (!m_context || !GBAThreadIsActive(m_context)) { if (!m_context || !mCoreThreadIsActive(m_context)) {
LOG(INFO) << tr("Can't set format of context-less audio device"); LOG(INFO) << tr("Can't set format of context-less audio device");
return; return;
} }
double fauxClock = GBAAudioCalculateRatio(1, m_context->fpsTarget, 1); double fauxClock = GBAAudioCalculateRatio(1, 60, 1); // TODO: Put back fpsTarget
mCoreSyncLockAudio(&m_context->sync); mCoreSyncLockAudio(&m_context->sync);
blip_set_rates(m_context->gba->audio.psg.left, GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock); blip_set_rates(m_context->core->getAudioChannel(m_context->core, 0), GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock);
blip_set_rates(m_context->gba->audio.psg.right, GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock); blip_set_rates(m_context->core->getAudioChannel(m_context->core, 1), GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock);
mCoreSyncUnlockAudio(&m_context->sync); mCoreSyncUnlockAudio(&m_context->sync);
} }
void AudioDevice::setInput(GBAThread* input) { void AudioDevice::setInput(mCoreThread* input) {
m_context = input; m_context = input;
} }
@ -45,18 +45,18 @@ qint64 AudioDevice::readData(char* data, qint64 maxSize) {
maxSize = 0xFFFFFFFF; maxSize = 0xFFFFFFFF;
} }
if (!m_context->gba) { if (!m_context->core) {
LOG(WARN) << tr("Audio device is missing its GBA"); LOG(WARN) << tr("Audio device is missing its core");
return 0; return 0;
} }
mCoreSyncLockAudio(&m_context->sync); mCoreSyncLockAudio(&m_context->sync);
int available = blip_samples_avail(m_context->gba->audio.psg.left); int available = blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0));
if (available > maxSize / sizeof(GBAStereoSample)) { if (available > maxSize / sizeof(GBAStereoSample)) {
available = maxSize / sizeof(GBAStereoSample); available = maxSize / sizeof(GBAStereoSample);
} }
blip_read_samples(m_context->gba->audio.psg.left, &reinterpret_cast<GBAStereoSample*>(data)->left, available, true); blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast<GBAStereoSample*>(data)->left, available, true);
blip_read_samples(m_context->gba->audio.psg.right, &reinterpret_cast<GBAStereoSample*>(data)->right, available, true); blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast<GBAStereoSample*>(data)->right, available, true);
mCoreSyncConsumeAudio(&m_context->sync); mCoreSyncConsumeAudio(&m_context->sync);
return available * sizeof(GBAStereoSample); return available * sizeof(GBAStereoSample);
} }

View File

@ -9,7 +9,7 @@
#include <QAudioFormat> #include <QAudioFormat>
#include <QIODevice> #include <QIODevice>
struct GBAThread; struct mCoreThread;
namespace QGBA { namespace QGBA {
@ -19,7 +19,7 @@ Q_OBJECT
public: public:
AudioDevice(QObject* parent = nullptr); AudioDevice(QObject* parent = nullptr);
void setInput(GBAThread* input); void setInput(mCoreThread* input);
void setFormat(const QAudioFormat& format); void setFormat(const QAudioFormat& format);
protected: protected:
@ -27,7 +27,7 @@ protected:
virtual qint64 writeData(const char* data, qint64 maxSize) override; virtual qint64 writeData(const char* data, qint64 maxSize) override;
private: private:
GBAThread* m_context; mCoreThread* m_context;
float m_drift; float m_drift;
float m_ratio; float m_ratio;
}; };

View File

@ -13,10 +13,6 @@
#include "AudioProcessorQt.h" #include "AudioProcessorQt.h"
#endif #endif
extern "C" {
#include "gba/supervisor/thread.h"
}
using namespace QGBA; using namespace QGBA;
#ifndef BUILD_SDL #ifndef BUILD_SDL
@ -49,11 +45,11 @@ AudioProcessor* AudioProcessor::create() {
AudioProcessor::AudioProcessor(QObject* parent) AudioProcessor::AudioProcessor(QObject* parent)
: QObject(parent) : QObject(parent)
, m_context(nullptr) , m_context(nullptr)
, m_samples(GBA_AUDIO_SAMPLES) , m_samples(2048)
{ {
} }
void AudioProcessor::setInput(GBAThread* input) { void AudioProcessor::setInput(mCoreThread* input) {
m_context = input; m_context = input;
} }

View File

@ -7,7 +7,7 @@
#define QGBA_AUDIO_PROCESSOR #define QGBA_AUDIO_PROCESSOR
#include <QObject> #include <QObject>
struct GBAThread; struct mCoreThread;
namespace QGBA { namespace QGBA {
@ -29,7 +29,7 @@ public:
AudioProcessor(QObject* parent = nullptr); AudioProcessor(QObject* parent = nullptr);
virtual void setInput(GBAThread* input); virtual void setInput(mCoreThread* input);
int getBufferSamples() const { return m_samples; } int getBufferSamples() const { return m_samples; }
virtual unsigned sampleRate() const = 0; virtual unsigned sampleRate() const = 0;
@ -43,10 +43,10 @@ public slots:
virtual void requestSampleRate(unsigned) = 0; virtual void requestSampleRate(unsigned) = 0;
protected: protected:
GBAThread* input() { return m_context; } mCoreThread* input() { return m_context; }
private: private:
GBAThread* m_context; mCoreThread* m_context;
int m_samples; int m_samples;
static Driver s_driver; static Driver s_driver;
}; };

View File

@ -24,7 +24,7 @@ AudioProcessorQt::AudioProcessorQt(QObject* parent)
{ {
} }
void AudioProcessorQt::setInput(GBAThread* input) { void AudioProcessorQt::setInput(mCoreThread* input) {
AudioProcessor::setInput(input); AudioProcessor::setInput(input);
if (m_device) { if (m_device) {
m_device->setInput(input); m_device->setInput(input);
@ -59,7 +59,7 @@ bool AudioProcessorQt::start() {
m_device->setInput(input()); m_device->setInput(input());
m_device->setFormat(m_audioOutput->format()); m_device->setFormat(m_audioOutput->format());
m_audioOutput->setBufferSize(input()->audioBuffers * 4); m_audioOutput->setBufferSize(2048 * 4); // TODO?
m_audioOutput->start(m_device); m_audioOutput->start(m_device);
return m_audioOutput->state() == QAudio::ActiveState; return m_audioOutput->state() == QAudio::ActiveState;

View File

@ -19,7 +19,7 @@ Q_OBJECT
public: public:
AudioProcessorQt(QObject* parent = nullptr); AudioProcessorQt(QObject* parent = nullptr);
virtual void setInput(GBAThread* input) override; virtual void setInput(mCoreThread* input) override;
virtual unsigned sampleRate() const override; virtual unsigned sampleRate() const override;
public slots: public slots:

View File

@ -34,9 +34,15 @@ bool AudioProcessorSDL::start() {
return true; return true;
} else { } else {
if (!m_audio.samples) { if (!m_audio.samples) {
m_audio.samples = input()->audioBuffers; m_audio.samples = 2048; // TODO?
} }
return mSDLInitAudio(&m_audio, input()); if (mSDLInitAudio(&m_audio, nullptr)) {
m_audio.core = input()->core;
m_audio.sync = &input()->sync;
mSDLResumeAudio(&m_audio);
return true;
}
return false;
} }
} }
@ -49,7 +55,10 @@ void AudioProcessorSDL::setBufferSamples(int samples) {
m_audio.samples = samples; m_audio.samples = samples;
if (m_audio.thread) { if (m_audio.thread) {
mSDLDeinitAudio(&m_audio); mSDLDeinitAudio(&m_audio);
mSDLInitAudio(&m_audio, input()); mSDLInitAudio(&m_audio, nullptr);
m_audio.core = input()->core;
m_audio.sync = &input()->sync;
mSDLResumeAudio(&m_audio);
} }
} }
@ -60,7 +69,10 @@ void AudioProcessorSDL::requestSampleRate(unsigned rate) {
m_audio.sampleRate = rate; m_audio.sampleRate = rate;
if (m_audio.thread) { if (m_audio.thread) {
mSDLDeinitAudio(&m_audio); mSDLDeinitAudio(&m_audio);
mSDLInitAudio(&m_audio, input()); mSDLInitAudio(&m_audio, nullptr);
m_audio.core = input()->core;
m_audio.sync = &input()->sync;
mSDLResumeAudio(&m_audio);
} }
} }

View File

@ -30,8 +30,8 @@ CheatsView::CheatsView(GameController* controller, QWidget* parent)
connect(m_ui.save, SIGNAL(clicked()), this, SLOT(save())); connect(m_ui.save, SIGNAL(clicked()), this, SLOT(save()));
connect(m_ui.addSet, SIGNAL(clicked()), this, SLOT(addSet())); connect(m_ui.addSet, SIGNAL(clicked()), this, SLOT(addSet()));
connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet())); connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet()));
connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated())); connect(controller, SIGNAL(gameStopped(mCoreThread*)), &m_model, SLOT(invalidated()));
connect(controller, SIGNAL(stateLoaded(GBAThread*)), &m_model, SLOT(invalidated())); connect(controller, SIGNAL(stateLoaded(mCoreThread*)), &m_model, SLOT(invalidated()));
connect(m_ui.add, &QPushButton::clicked, [this]() { connect(m_ui.add, &QPushButton::clicked, [this]() {
enterCheat(GBACheatAddLine); enterCheat(GBACheatAddLine);

View File

@ -109,7 +109,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.fpsTarget = 60; m_opts.fpsTarget = 60;
m_opts.audioBuffers = 1536; m_opts.audioBuffers = 1536;
m_opts.sampleRate = 44100; m_opts.sampleRate = 44100;
m_opts.volume = GBA_AUDIO_VOLUME_MAX; m_opts.volume = 0x100;
m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS; m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS;
m_opts.rewindEnable = false; m_opts.rewindEnable = false;
m_opts.rewindBufferInterval = 0; m_opts.rewindBufferInterval = 0;

View File

@ -82,6 +82,8 @@ public:
Configuration* input() { return mCoreConfigGetInput(&m_config); } Configuration* input() { return mCoreConfigGetInput(&m_config); }
const mCoreConfig* config() { return &m_config; }
public slots: public slots:
void setOption(const char* key, bool value); void setOption(const char* key, bool value);
void setOption(const char* key, int value); void setOption(const char* key, int value);

View File

@ -10,7 +10,7 @@
#include "MessagePainter.h" #include "MessagePainter.h"
struct GBAThread; struct mCoreThread;
struct VDir; struct VDir;
struct VideoShader; struct VideoShader;
@ -47,7 +47,7 @@ signals:
void hideCursor(); void hideCursor();
public slots: public slots:
virtual void startDrawing(GBAThread* context) = 0; virtual void startDrawing(mCoreThread* context) = 0;
virtual void stopDrawing() = 0; virtual void stopDrawing() = 0;
virtual void pauseDrawing() = 0; virtual void pauseDrawing() = 0;
virtual void unpauseDrawing() = 0; virtual void unpauseDrawing() = 0;

View File

@ -62,7 +62,7 @@ VideoShader* DisplayGL::shaders() {
return shaders; return shaders;
} }
void DisplayGL::startDrawing(GBAThread* thread) { void DisplayGL::startDrawing(mCoreThread* thread) {
if (m_drawThread) { if (m_drawThread) {
return; return;
} }
@ -90,14 +90,14 @@ void DisplayGL::startDrawing(GBAThread* thread) {
void DisplayGL::stopDrawing() { void DisplayGL::stopDrawing() {
if (m_drawThread) { if (m_drawThread) {
m_isDrawing = false; m_isDrawing = false;
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadInterrupt(m_context); mCoreThreadInterrupt(m_context);
} }
QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection);
m_drawThread->exit(); m_drawThread->exit();
m_drawThread = nullptr; m_drawThread = nullptr;
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadContinue(m_context); mCoreThreadContinue(m_context);
} }
} }
} }
@ -105,12 +105,12 @@ void DisplayGL::stopDrawing() {
void DisplayGL::pauseDrawing() { void DisplayGL::pauseDrawing() {
if (m_drawThread) { if (m_drawThread) {
m_isDrawing = false; m_isDrawing = false;
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadInterrupt(m_context); mCoreThreadInterrupt(m_context);
} }
QMetaObject::invokeMethod(m_painter, "pause", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(m_painter, "pause", Qt::BlockingQueuedConnection);
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadContinue(m_context); mCoreThreadContinue(m_context);
} }
} }
} }
@ -118,12 +118,12 @@ void DisplayGL::pauseDrawing() {
void DisplayGL::unpauseDrawing() { void DisplayGL::unpauseDrawing() {
if (m_drawThread) { if (m_drawThread) {
m_isDrawing = true; m_isDrawing = true;
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadInterrupt(m_context); mCoreThreadInterrupt(m_context);
} }
QMetaObject::invokeMethod(m_painter, "unpause", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(m_painter, "unpause", Qt::BlockingQueuedConnection);
if (GBAThreadIsActive(m_context)) { if (mCoreThreadIsActive(m_context)) {
GBAThreadContinue(m_context); mCoreThreadContinue(m_context);
} }
} }
} }
@ -260,7 +260,7 @@ PainterGL::~PainterGL() {
m_backend = nullptr; m_backend = nullptr;
} }
void PainterGL::setContext(GBAThread* context) { void PainterGL::setContext(mCoreThread* context) {
m_context = context; m_context = context;
} }
@ -307,7 +307,7 @@ void PainterGL::start() {
} }
void PainterGL::draw() { void PainterGL::draw() {
if (m_queue.isEmpty() || !GBAThreadIsActive(m_context)) { if (m_queue.isEmpty() || !mCoreThreadIsActive(m_context)) {
return; return;
} }
if (mCoreSyncWaitFrameStart(&m_context->sync) || !m_queue.isEmpty()) { if (mCoreSyncWaitFrameStart(&m_context->sync) || !m_queue.isEmpty()) {

View File

@ -26,8 +26,6 @@ extern "C" {
#include "platform/video-backend.h" #include "platform/video-backend.h"
} }
struct GBAThread;
namespace QGBA { namespace QGBA {
class EmptyGLWidget : public QGLWidget { class EmptyGLWidget : public QGLWidget {
@ -53,7 +51,7 @@ public:
VideoShader* shaders() override; VideoShader* shaders() override;
public slots: public slots:
void startDrawing(GBAThread* context) override; void startDrawing(mCoreThread* context) override;
void stopDrawing() override; void stopDrawing() override;
void pauseDrawing() override; void pauseDrawing() override;
void unpauseDrawing() override; void unpauseDrawing() override;
@ -75,7 +73,7 @@ private:
QGLWidget* m_gl; QGLWidget* m_gl;
PainterGL* m_painter; PainterGL* m_painter;
QThread* m_drawThread; QThread* m_drawThread;
GBAThread* m_context; mCoreThread* m_context;
}; };
class PainterGL : public QObject { class PainterGL : public QObject {
@ -85,7 +83,7 @@ public:
PainterGL(QGLWidget* parent, QGLFormat::OpenGLVersionFlags = QGLFormat::OpenGL_Version_1_1); PainterGL(QGLWidget* parent, QGLFormat::OpenGLVersionFlags = QGLFormat::OpenGL_Version_1_1);
~PainterGL(); ~PainterGL();
void setContext(GBAThread*); void setContext(mCoreThread*);
void setMessagePainter(MessagePainter*); void setMessagePainter(MessagePainter*);
void enqueue(const uint32_t* backing); void enqueue(const uint32_t* backing);
@ -118,7 +116,7 @@ private:
QGLWidget* m_gl; QGLWidget* m_gl;
bool m_active; bool m_active;
bool m_started; bool m_started;
GBAThread* m_context; mCoreThread* m_context;
bool m_supportsShaders; bool m_supportsShaders;
VideoShader m_shader; VideoShader m_shader;
VideoBackend* m_backend; VideoBackend* m_backend;

View File

@ -20,7 +20,7 @@ DisplayQt::DisplayQt(QWidget* parent)
{ {
} }
void DisplayQt::startDrawing(GBAThread*) { void DisplayQt::startDrawing(mCoreThread*) {
m_isDrawing = true; m_isDrawing = true;
} }

View File

@ -11,8 +11,6 @@
#include <QImage> #include <QImage>
#include <QTimer> #include <QTimer>
struct GBAThread;
namespace QGBA { namespace QGBA {
class DisplayQt : public Display { class DisplayQt : public Display {
@ -26,7 +24,7 @@ public:
VideoShader* shaders() override { return nullptr; } VideoShader* shaders() override { return nullptr; }
public slots: public slots:
void startDrawing(GBAThread* context) override; void startDrawing(mCoreThread* context) override;
void stopDrawing() override { m_isDrawing = false; } void stopDrawing() override { m_isDrawing = false; }
void pauseDrawing() override { m_isDrawing = false; } void pauseDrawing() override { m_isDrawing = false; }
void unpauseDrawing() override { m_isDrawing = true; } void unpauseDrawing() override { m_isDrawing = true; }

View File

@ -43,7 +43,7 @@ GBAApp::GBAApp(int& argc, char* argv[])
SocketSubsystemInit(); SocketSubsystemInit();
qRegisterMetaType<const uint32_t*>("const uint32_t*"); qRegisterMetaType<const uint32_t*>("const uint32_t*");
qRegisterMetaType<GBAThread*>("GBAThread*"); qRegisterMetaType<mCoreThread*>("mCoreThread*");
QApplication::setApplicationName(projectName); QApplication::setApplicationName(projectName);
QApplication::setApplicationVersion(projectVersion); QApplication::setApplicationVersion(projectVersion);

View File

@ -21,6 +21,7 @@ extern "C" {
#include "core/config.h" #include "core/config.h"
#include "core/directories.h" #include "core/directories.h"
#include "gba/audio.h" #include "gba/audio.h"
#include "gba/core.h"
#include "gba/gba.h" #include "gba/gba.h"
#include "gba/serialize.h" #include "gba/serialize.h"
#include "gba/sharkport.h" #include "gba/sharkport.h"
@ -56,30 +57,15 @@ GameController::GameController(QObject* parent)
, m_autofireStatus{} , m_autofireStatus{}
, m_inputController(nullptr) , m_inputController(nullptr)
, m_multiplayer(nullptr) , m_multiplayer(nullptr)
, m_stream(nullptr)
, m_stateSlot(1) , m_stateSlot(1)
, m_backupLoadState(nullptr) , m_backupLoadState(nullptr)
, m_backupSaveState(nullptr) , m_backupSaveState(nullptr)
, m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS) , m_saveStateFlags(SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_CHEATS)
, m_loadStateFlags(SAVESTATE_SCREENSHOT) , m_loadStateFlags(SAVESTATE_SCREENSHOT)
{ {
m_renderer = new GBAVideoSoftwareRenderer;
GBAVideoSoftwareRendererCreate(m_renderer);
m_renderer->outputBuffer = (color_t*) m_drawContext;
m_renderer->outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
GBACheatDeviceCreate(&m_cheatDevice); GBACheatDeviceCreate(&m_cheatDevice);
m_threadContext.state = THREAD_INITIALIZED;
m_threadContext.debugger = 0;
m_threadContext.frameskip = 0;
m_threadContext.bios = 0;
m_threadContext.renderer = &m_renderer->d;
m_threadContext.userData = this;
m_threadContext.rewindBufferCapacity = 0;
m_threadContext.cheats = &m_cheatDevice;
m_threadContext.logLevel = GBA_LOG_ALL;
mDirectorySetInit(&m_threadContext.dirs);
m_lux.p = this; m_lux.p = this;
m_lux.sample = [](GBALuminanceSource* context) { m_lux.sample = [](GBALuminanceSource* context) {
GameControllerLux* lux = static_cast<GameControllerLux*>(context); GameControllerLux* lux = static_cast<GameControllerLux*>(context);
@ -92,63 +78,65 @@ GameController::GameController(QObject* parent)
}; };
setLuminanceLevel(0); setLuminanceLevel(0);
m_threadContext.startCallback = [](GBAThread* context) { m_threadContext.startCallback = [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
if (controller->m_audioProcessor) { if (controller->m_audioProcessor) {
controller->m_audioProcessor->setInput(context); controller->m_audioProcessor->setInput(context);
} }
context->gba->luminanceSource = &controller->m_lux; mRTCGenericSourceInit(&controller->m_rtc, context->core);
GBARTCGenericSourceInit(&controller->m_rtc, context->gba); context->core->setRTC(context->core, &controller->m_rtc.d);
context->gba->rtcSource = &controller->m_rtc.d;
context->gba->rumble = controller->m_inputController->rumble();
context->gba->rotationSource = controller->m_inputController->rotationSource();
context->gba->audio.psg.forceDisableCh[0] = !controller->m_audioChannels[0];
context->gba->audio.psg.forceDisableCh[1] = !controller->m_audioChannels[1];
context->gba->audio.psg.forceDisableCh[2] = !controller->m_audioChannels[2];
context->gba->audio.psg.forceDisableCh[3] = !controller->m_audioChannels[3];
context->gba->audio.forceDisableChA = !controller->m_audioChannels[4];
context->gba->audio.forceDisableChB = !controller->m_audioChannels[5];
context->gba->video.renderer->disableBG[0] = !controller->m_videoLayers[0];
context->gba->video.renderer->disableBG[1] = !controller->m_videoLayers[1];
context->gba->video.renderer->disableBG[2] = !controller->m_videoLayers[2];
context->gba->video.renderer->disableBG[3] = !controller->m_videoLayers[3];
context->gba->video.renderer->disableOBJ = !controller->m_videoLayers[4];
controller->m_fpsTarget = context->fpsTarget;
if (context->dirs.state && GBALoadState(context, context->dirs.state, 0, controller->m_loadStateFlags)) { GBA* gba = static_cast<GBA*>(context->core->board);
GBADeleteState(context->gba, context->dirs.state, 0); gba->luminanceSource = &controller->m_lux;
gba->rumble = controller->m_inputController->rumble();
gba->rotationSource = controller->m_inputController->rotationSource();
gba->audio.psg.forceDisableCh[0] = !controller->m_audioChannels[0];
gba->audio.psg.forceDisableCh[1] = !controller->m_audioChannels[1];
gba->audio.psg.forceDisableCh[2] = !controller->m_audioChannels[2];
gba->audio.psg.forceDisableCh[3] = !controller->m_audioChannels[3];
gba->audio.forceDisableChA = !controller->m_audioChannels[4];
gba->audio.forceDisableChB = !controller->m_audioChannels[5];
gba->video.renderer->disableBG[0] = !controller->m_videoLayers[0];
gba->video.renderer->disableBG[1] = !controller->m_videoLayers[1];
gba->video.renderer->disableBG[2] = !controller->m_videoLayers[2];
gba->video.renderer->disableBG[3] = !controller->m_videoLayers[3];
gba->video.renderer->disableOBJ = !controller->m_videoLayers[4];
// TODO: Put back fpsTarget
if (mCoreLoadState(context->core, 0, controller->m_loadStateFlags)) {
mCoreDeleteState(context->core, 0);
} }
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context)); QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(mCoreThread*, context));
}; };
m_threadContext.cleanCallback = [](GBAThread* context) { m_threadContext.cleanCallback = [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context)); QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(mCoreThread*, context));
}; };
m_threadContext.frameCallback = [](GBAThread* context) { m_threadContext.frameCallback = [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
memcpy(controller->m_frontBuffer, controller->m_drawContext, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL); memcpy(controller->m_frontBuffer, controller->m_drawContext, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer)); QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer));
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
GBAThreadPauseFromThread(context); mCoreThreadPauseFromThread(context);
QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(GBAThread*, context)); QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(mCoreThread*, context));
} }
}; };
m_threadContext.stopCallback = [](GBAThread* context) { /*m_threadContext.stopCallback = [](mCoreThread* context) {
if (!context) { if (!context) {
return false; return false;
} }
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
if (!GBASaveState(context, context->dirs.state, 0, controller->m_saveStateFlags)) { if (!mCoreSaveState(context->core, 0, controller->m_saveStateFlags)) {
return false; return false;
} }
QMetaObject::invokeMethod(controller, "closeGame"); QMetaObject::invokeMethod(controller, "closeGame");
return true; return true;
}; };*/
m_threadContext.logHandler = [](GBAThread* context, enum GBALogLevel level, const char* format, va_list args) { /*m_threadContext.logHandler = [](mCoreThread* context, enum GBALogLevel level, const char* format, va_list args) {
static const char* stubMessage = "Stub software interrupt: %02X"; static const char* stubMessage = "Stub software interrupt: %02X";
static const char* savestateMessage = "State %i loaded"; static const char* savestateMessage = "State %i loaded";
static const char* savestateFailedMessage = "State %i failed to load"; static const char* savestateFailedMessage = "State %i failed to load";
@ -192,10 +180,12 @@ GameController::GameController(QObject* parent)
QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message)); QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message));
} }
QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(const QString&, message)); QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(const QString&, message));
}; };*/
m_threadContext.userData = this;
connect(&m_rewindTimer, &QTimer::timeout, [this]() { connect(&m_rewindTimer, &QTimer::timeout, [this]() {
GBARewind(&m_threadContext, 1); // TODO: Put rewind back
emit frameAvailable(m_drawContext); emit frameAvailable(m_drawContext);
emit rewound(&m_threadContext); emit rewound(&m_threadContext);
}); });
@ -204,7 +194,7 @@ GameController::GameController(QObject* parent)
m_audioThread->setObjectName("Audio Thread"); m_audioThread->setObjectName("Audio Thread");
m_audioThread->start(QThread::TimeCriticalPriority); m_audioThread->start(QThread::TimeCriticalPriority);
m_audioProcessor->moveToThread(m_audioThread); m_audioProcessor->moveToThread(m_audioThread);
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gamePaused(mCoreThread*)), m_audioProcessor, SLOT(pause()));
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents())); connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(pollEvents()));
connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateAutofire())); connect(this, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateAutofire()));
} }
@ -216,8 +206,6 @@ GameController::~GameController() {
clearMultiplayerController(); clearMultiplayerController();
closeGame(); closeGame();
GBACheatDeviceDestroy(&m_cheatDevice); GBACheatDeviceDestroy(&m_cheatDevice);
mDirectorySetDeinit(&m_threadContext.dirs);
delete m_renderer;
delete[] m_drawContext; delete[] m_drawContext;
delete[] m_frontBuffer; delete[] m_frontBuffer;
delete m_backupLoadState; delete m_backupLoadState;
@ -241,40 +229,27 @@ void GameController::clearMultiplayerController() {
} }
void GameController::setOverride(const GBACartridgeOverride& override) { void GameController::setOverride(const GBACartridgeOverride& override) {
m_threadContext.override = override; // TODO: Put back overrides
m_threadContext.hasOverride = true;
} }
void GameController::setOptions(const mCoreOptions* opts) { void GameController::setConfig(const mCoreConfig* config) {
setFrameskip(opts->frameskip); if (!m_gameOpen) {
setAudioSync(opts->audioSync); return;
setVideoSync(opts->videoSync); }
setSkipBIOS(opts->skipBios);
setUseBIOS(opts->useBios);
setRewind(opts->rewindEnable, opts->rewindBufferCapacity, opts->rewindBufferInterval);
setVolume(opts->volume);
setMute(opts->mute);
threadInterrupt(); threadInterrupt();
mDirectorySetMapOptions(&m_threadContext.dirs, opts); mCoreLoadForeignConfig(m_threadContext.core, config);
// TODO: Put back idle optimization
threadContinue(); threadContinue();
} }
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
Debugger* GameController::debugger() { Debugger* GameController::debugger() {
return m_threadContext.debugger; // TODO: Put back debugger
return nullptr;
} }
void GameController::setDebugger(Debugger* debugger) { void GameController::setDebugger(Debugger* debugger) {
threadInterrupt(); threadInterrupt();
if (m_threadContext.debugger && GBAThreadIsActive(&m_threadContext)) { // TODO: Put back debugger
GBADetachDebugger(m_threadContext.gba);
}
m_threadContext.debugger = debugger;
if (m_threadContext.debugger && GBAThreadIsActive(&m_threadContext)) {
GBAAttachDebugger(m_threadContext.gba, m_threadContext.debugger);
}
threadContinue(); threadContinue();
} }
#endif #endif
@ -315,28 +290,36 @@ void GameController::openGame(bool biosOnly) {
m_threadContext.sync.audioWait = m_audioSync; m_threadContext.sync.audioWait = m_audioSync;
} }
m_threadContext.bootBios = biosOnly; m_threadContext.core = GBACoreCreate();
if (biosOnly) { m_threadContext.core->init(m_threadContext.core);
m_threadContext.fname = nullptr; m_threadContext.core->setVideoBuffer(m_threadContext.core, m_drawContext, VIDEO_HORIZONTAL_PIXELS);
} else {
m_threadContext.fname = strdup(m_fname.toUtf8().constData()); if (!biosOnly) {
GBAThreadLoadROM(&m_threadContext, m_threadContext.fname); mCoreLoadFile(m_threadContext.core, m_fname.toUtf8().constData());
} }
if (!m_bios.isNull() && m_useBios) { if (!m_bios.isNull() && m_useBios) {
m_threadContext.bios = VFileDevice::open(m_bios, O_RDONLY); VFile* bios = VFileDevice::open(m_bios, O_RDONLY);
} else { if (bios) {
m_threadContext.bios = nullptr; // TODO: Lifetime issues?
m_threadContext.core->loadBIOS(m_threadContext.core, bios, 0);
}
} }
if (!m_patch.isNull()) { if (!m_patch.isNull()) {
m_threadContext.patch = VFileDevice::open(m_patch, O_RDONLY); VFile* patch = VFileDevice::open(m_patch, O_RDONLY);
if (patch) {
m_threadContext.core->loadPatch(m_threadContext.core, patch);
}
patch->close(patch);
} }
m_inputController->recalibrateAxes(); m_inputController->recalibrateAxes();
memset(m_drawContext, 0xF8, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * 4); memset(m_drawContext, 0xF8, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * 4);
if (!GBAThreadStart(&m_threadContext)) { m_threadContext.core->setAVStream(m_threadContext.core, m_stream);
if (!mCoreThreadStart(&m_threadContext)) {
m_gameOpen = false; m_gameOpen = false;
emit gameFailed(); emit gameFailed();
} else if (m_audioProcessor) { } else if (m_audioProcessor) {
@ -360,7 +343,7 @@ void GameController::yankPak() {
return; return;
} }
threadInterrupt(); threadInterrupt();
GBAYankROM(m_threadContext.gba); GBAYankROM(static_cast<GBA*>(m_threadContext.core->board));
threadContinue(); threadContinue();
} }
@ -371,8 +354,7 @@ void GameController::replaceGame(const QString& path) {
m_fname = path; m_fname = path;
threadInterrupt(); threadInterrupt();
m_threadContext.fname = strdup(m_fname.toLocal8Bit().constData()); mCoreLoadFile(m_threadContext.core, m_fname.toLocal8Bit().constData());
GBAThreadReplaceROM(&m_threadContext, m_threadContext.fname);
threadContinue(); threadContinue();
} }
@ -396,7 +378,7 @@ void GameController::importSharkport(const QString& path) {
return; return;
} }
threadInterrupt(); threadInterrupt();
GBASavedataImportSharkPort(m_threadContext.gba, vf, false); GBASavedataImportSharkPort(static_cast<GBA*>(m_threadContext.core->board), vf, false);
threadContinue(); threadContinue();
vf->close(vf); vf->close(vf);
} }
@ -411,7 +393,7 @@ void GameController::exportSharkport(const QString& path) {
return; return;
} }
threadInterrupt(); threadInterrupt();
GBASavedataExportSharkPort(m_threadContext.gba, vf); GBASavedataExportSharkPort(static_cast<GBA*>(m_threadContext.core->board), vf);
threadContinue(); threadContinue();
vf->close(vf); vf->close(vf);
} }
@ -423,18 +405,14 @@ void GameController::closeGame() {
m_gameOpen = false; m_gameOpen = false;
m_rewindTimer.stop(); m_rewindTimer.stop();
if (GBAThreadIsPaused(&m_threadContext)) { if (mCoreThreadIsPaused(&m_threadContext)) {
GBAThreadUnpause(&m_threadContext); mCoreThreadUnpause(&m_threadContext);
} }
m_audioProcessor->pause(); m_audioProcessor->pause();
GBAThreadEnd(&m_threadContext); mCoreThreadEnd(&m_threadContext);
GBAThreadJoin(&m_threadContext); mCoreThreadJoin(&m_threadContext);
// Make sure the event queue clears out before the thread is reused // Make sure the event queue clears out before the thread is reused
QCoreApplication::processEvents(); QCoreApplication::processEvents();
if (m_threadContext.fname) {
free(const_cast<char*>(m_threadContext.fname));
m_threadContext.fname = nullptr;
}
m_patch = QString(); m_patch = QString();
@ -445,6 +423,8 @@ void GameController::closeGame() {
} }
GBACheatSetsClear(&m_cheatDevice.cheats); GBACheatSetsClear(&m_cheatDevice.cheats);
m_threadContext.core->deinit(m_threadContext.core);
m_gameOpen = false; m_gameOpen = false;
emit gameStopped(&m_threadContext); emit gameStopped(&m_threadContext);
} }
@ -459,17 +439,17 @@ bool GameController::isPaused() {
if (!m_gameOpen) { if (!m_gameOpen) {
return false; return false;
} }
return GBAThreadIsPaused(&m_threadContext); return mCoreThreadIsPaused(&m_threadContext);
} }
void GameController::setPaused(bool paused) { void GameController::setPaused(bool paused) {
if (!isLoaded() || m_rewindTimer.isActive() || paused == GBAThreadIsPaused(&m_threadContext)) { if (!isLoaded() || m_rewindTimer.isActive() || paused == mCoreThreadIsPaused(&m_threadContext)) {
return; return;
} }
if (paused) { if (paused) {
m_pauseAfterFrame.testAndSetRelaxed(false, true); m_pauseAfterFrame.testAndSetRelaxed(false, true);
} else { } else {
GBAThreadUnpause(&m_threadContext); mCoreThreadUnpause(&m_threadContext);
startAudio(); startAudio();
emit gameUnpaused(&m_threadContext); emit gameUnpaused(&m_threadContext);
} }
@ -481,7 +461,7 @@ void GameController::reset() {
} }
bool wasPaused = isPaused(); bool wasPaused = isPaused();
setPaused(false); setPaused(false);
GBAThreadReset(&m_threadContext); mCoreThreadReset(&m_threadContext);
if (wasPaused) { if (wasPaused) {
setPaused(true); setPaused(true);
} }
@ -489,13 +469,13 @@ void GameController::reset() {
void GameController::threadInterrupt() { void GameController::threadInterrupt() {
if (m_gameOpen) { if (m_gameOpen) {
GBAThreadInterrupt(&m_threadContext); mCoreThreadInterrupt(&m_threadContext);
} }
} }
void GameController::threadContinue() { void GameController::threadContinue() {
if (m_gameOpen) { if (m_gameOpen) {
GBAThreadContinue(&m_threadContext); mCoreThreadContinue(&m_threadContext);
} }
} }
@ -511,25 +491,19 @@ void GameController::frameAdvance() {
void GameController::setRewind(bool enable, int capacity, int interval) { void GameController::setRewind(bool enable, int capacity, int interval) {
if (m_gameOpen) { if (m_gameOpen) {
threadInterrupt(); threadInterrupt();
GBARewindSettingsChanged(&m_threadContext, enable ? capacity : 0, enable ? interval : 0); // TODO: Put back rewind
threadContinue(); threadContinue();
} else { } else {
if (enable) { // TODO: Put back rewind
m_threadContext.rewindBufferInterval = interval;
m_threadContext.rewindBufferCapacity = capacity;
} else {
m_threadContext.rewindBufferInterval = 0;
m_threadContext.rewindBufferCapacity = 0;
}
} }
} }
void GameController::rewind(int states) { void GameController::rewind(int states) {
threadInterrupt(); threadInterrupt();
if (!states) { if (!states) {
GBARewindAll(&m_threadContext); // TODO: Put back rewind
} else { } else {
GBARewind(&m_threadContext, states); // TODO: Put back rewind
} }
threadContinue(); threadContinue();
emit frameAvailable(m_drawContext); emit frameAvailable(m_drawContext);
@ -544,8 +518,8 @@ void GameController::startRewinding() {
return; return;
} }
m_wasPaused = isPaused(); m_wasPaused = isPaused();
if (!GBAThreadIsPaused(&m_threadContext)) { if (!mCoreThreadIsPaused(&m_threadContext)) {
GBAThreadPause(&m_threadContext); mCoreThreadPause(&m_threadContext);
} }
m_rewindTimer.start(); m_rewindTimer.start();
} }
@ -631,6 +605,7 @@ void GameController::setAudioChannelEnabled(int channel, bool enable) {
if (channel > 5 || channel < 0) { if (channel > 5 || channel < 0) {
return; return;
} }
GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
m_audioChannels[channel] = enable; m_audioChannels[channel] = enable;
if (isLoaded()) { if (isLoaded()) {
switch (channel) { switch (channel) {
@ -638,13 +613,13 @@ void GameController::setAudioChannelEnabled(int channel, bool enable) {
case 1: case 1:
case 2: case 2:
case 3: case 3:
m_threadContext.gba->audio.psg.forceDisableCh[channel] = !enable; gba->audio.psg.forceDisableCh[channel] = !enable;
break; break;
case 4: case 4:
m_threadContext.gba->audio.forceDisableChA = !enable; gba->audio.forceDisableChA = !enable;
break; break;
case 5: case 5:
m_threadContext.gba->audio.forceDisableChB = !enable; gba->audio.forceDisableChB = !enable;
break; break;
} }
} }
@ -667,6 +642,7 @@ void GameController::setVideoLayerEnabled(int layer, bool enable) {
if (layer > 4 || layer < 0) { if (layer > 4 || layer < 0) {
return; return;
} }
GBA* gba = static_cast<GBA*>(m_threadContext.core->board);
m_videoLayers[layer] = enable; m_videoLayers[layer] = enable;
if (isLoaded()) { if (isLoaded()) {
switch (layer) { switch (layer) {
@ -674,10 +650,10 @@ void GameController::setVideoLayerEnabled(int layer, bool enable) {
case 1: case 1:
case 2: case 2:
case 3: case 3:
m_threadContext.gba->video.renderer->disableBG[layer] = !enable; gba->video.renderer->disableBG[layer] = !enable;
break; break;
case 4: case 4:
m_threadContext.gba->video.renderer->disableOBJ = !enable; gba->video.renderer->disableOBJ = !enable;
break; break;
} }
} }
@ -686,9 +662,9 @@ void GameController::setVideoLayerEnabled(int layer, bool enable) {
void GameController::setFPSTarget(float fps) { void GameController::setFPSTarget(float fps) {
threadInterrupt(); threadInterrupt();
m_fpsTarget = fps; m_fpsTarget = fps;
m_threadContext.fpsTarget = fps; // TODO: Put back fpsTarget
if (m_turbo && m_turboSpeed > 0) { if (m_turbo && m_turboSpeed > 0) {
m_threadContext.fpsTarget *= m_turboSpeed; // TODO: Put back fpsTarget
} }
if (m_audioProcessor) { if (m_audioProcessor) {
redoSamples(m_audioProcessor->getBufferSamples()); redoSamples(m_audioProcessor->getBufferSamples());
@ -696,12 +672,6 @@ void GameController::setFPSTarget(float fps) {
threadContinue(); threadContinue();
} }
void GameController::setSkipBIOS(bool set) {
threadInterrupt();
m_threadContext.skipBios = set;
threadContinue();
}
void GameController::setUseBIOS(bool use) { void GameController::setUseBIOS(bool use) {
if (use == m_useBios) { if (use == m_useBios) {
return; return;
@ -714,7 +684,7 @@ void GameController::setUseBIOS(bool use) {
} }
void GameController::loadState(int slot) { void GameController::loadState(int slot) {
if (!m_threadContext.fname) { if (m_fname.isEmpty()) {
// We're in the BIOS // We're in the BIOS
return; return;
} }
@ -722,13 +692,13 @@ void GameController::loadState(int slot) {
m_stateSlot = slot; m_stateSlot = slot;
m_backupSaveState.clear(); m_backupSaveState.clear();
} }
GBARunOnThread(&m_threadContext, [](GBAThread* context) { mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
if (!controller->m_backupLoadState) { if (!controller->m_backupLoadState) {
controller->m_backupLoadState = new GBASerializedState; controller->m_backupLoadState = VFileMemChunk(nullptr, 0);
} }
GBASerialize(context->gba, controller->m_backupLoadState); context->core->saveState(context->core, controller->m_backupLoadState, controller->m_saveStateFlags);
if (GBALoadState(context, context->dirs.state, controller->m_stateSlot, controller->m_loadStateFlags)) { if (mCoreLoadState(context->core, controller->m_stateSlot, controller->m_loadStateFlags)) {
controller->frameAvailable(controller->m_drawContext); controller->frameAvailable(controller->m_drawContext);
controller->stateLoaded(context); controller->stateLoaded(context);
} }
@ -736,22 +706,22 @@ void GameController::loadState(int slot) {
} }
void GameController::saveState(int slot) { void GameController::saveState(int slot) {
if (!m_threadContext.fname) { if (m_fname.isEmpty()) {
// We're in the BIOS // We're in the BIOS
return; return;
} }
if (slot > 0) { if (slot > 0) {
m_stateSlot = slot; m_stateSlot = slot;
} }
GBARunOnThread(&m_threadContext, [](GBAThread* context) { mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
VFile* vf = GBAGetState(context->gba, context->dirs.state, controller->m_stateSlot, false); VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, false);
if (vf) { if (vf) {
controller->m_backupSaveState.resize(vf->size(vf)); controller->m_backupSaveState.resize(vf->size(vf));
vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size());
vf->close(vf); vf->close(vf);
} }
GBASaveState(context, context->dirs.state, controller->m_stateSlot, controller->m_saveStateFlags); mCoreSaveState(context->core, controller->m_stateSlot, controller->m_saveStateFlags);
}); });
} }
@ -760,14 +730,15 @@ void GameController::loadBackupState() {
return; return;
} }
GBARunOnThread(&m_threadContext, [](GBAThread* context) { mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
if (GBADeserialize(context->gba, controller->m_backupLoadState)) { controller->m_backupLoadState->seek(controller->m_backupLoadState, 0, SEEK_SET);
GBALog(context->gba, GBA_LOG_STATUS, "Undid state load"); if (context->core->loadState(context->core, controller->m_backupLoadState, controller->m_loadStateFlags)) {
mLOG(STATUS, INFO, "Undid state load");
controller->frameAvailable(controller->m_drawContext); controller->frameAvailable(controller->m_drawContext);
controller->stateLoaded(context); controller->stateLoaded(context);
} }
delete controller->m_backupLoadState; controller->m_backupLoadState->close(controller->m_backupLoadState);
controller->m_backupLoadState = nullptr; controller->m_backupLoadState = nullptr;
}); });
} }
@ -777,60 +748,21 @@ void GameController::saveBackupState() {
return; return;
} }
GBARunOnThread(&m_threadContext, [](GBAThread* context) { mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) {
GameController* controller = static_cast<GameController*>(context->userData); GameController* controller = static_cast<GameController*>(context->userData);
VFile* vf = GBAGetState(context->gba, context->dirs.state, controller->m_stateSlot, true); VFile* vf = mCoreGetState(context->core, controller->m_stateSlot, true);
if (vf) { if (vf) {
vf->write(vf, controller->m_backupSaveState.constData(), controller->m_backupSaveState.size()); vf->write(vf, controller->m_backupSaveState.constData(), controller->m_backupSaveState.size());
vf->close(vf); vf->close(vf);
GBALog(context->gba, GBA_LOG_STATUS, "Undid state save"); mLOG(STATUS, INFO, "Undid state save");
} }
controller->m_backupSaveState.clear(); controller->m_backupSaveState.clear();
}); });
} }
void GameController::setVideoSync(bool set) {
m_videoSync = set;
if (!m_turbo) {
threadInterrupt();
m_threadContext.sync.videoFrameWait = set;
threadContinue();
}
}
void GameController::setAudioSync(bool set) {
m_audioSync = set;
if (!m_turbo) {
threadInterrupt();
m_threadContext.sync.audioWait = set;
threadContinue();
}
}
void GameController::setFrameskip(int skip) {
threadInterrupt();
m_threadContext.frameskip = skip;
if (isLoaded()) {
m_threadContext.gba->video.frameskip = skip;
}
threadContinue();
}
void GameController::setVolume(int volume) {
threadInterrupt();
m_threadContext.volume = volume;
if (isLoaded()) {
m_threadContext.gba->audio.masterVolume = volume;
}
threadContinue();
}
void GameController::setMute(bool mute) { void GameController::setMute(bool mute) {
threadInterrupt(); threadInterrupt();
m_threadContext.mute = mute; // TODO: Put back mute
if (isLoaded()) {
m_threadContext.gba->audio.masterVolume = mute ? 0 : m_threadContext.volume;
}
threadContinue(); threadContinue();
} }
@ -855,15 +787,15 @@ void GameController::setTurboSpeed(float ratio) {
void GameController::enableTurbo() { void GameController::enableTurbo() {
threadInterrupt(); threadInterrupt();
if (!m_turbo) { if (!m_turbo) {
m_threadContext.fpsTarget = m_fpsTarget; // TODO: Put back fpsTarget
m_threadContext.sync.audioWait = m_audioSync; m_threadContext.sync.audioWait = m_audioSync;
m_threadContext.sync.videoFrameWait = m_videoSync; m_threadContext.sync.videoFrameWait = m_videoSync;
} else if (m_turboSpeed <= 0) { } else if (m_turboSpeed <= 0) {
m_threadContext.fpsTarget = m_fpsTarget; // TODO: Put back fpsTarget
m_threadContext.sync.audioWait = false; m_threadContext.sync.audioWait = false;
m_threadContext.sync.videoFrameWait = false; m_threadContext.sync.videoFrameWait = false;
} else { } else {
m_threadContext.fpsTarget = m_fpsTarget * m_turboSpeed; // TODO: Put back fpsTarget
m_threadContext.sync.audioWait = true; m_threadContext.sync.audioWait = true;
m_threadContext.sync.videoFrameWait = false; m_threadContext.sync.videoFrameWait = false;
} }
@ -875,25 +807,27 @@ void GameController::enableTurbo() {
void GameController::setAVStream(mAVStream* stream) { void GameController::setAVStream(mAVStream* stream) {
threadInterrupt(); threadInterrupt();
m_threadContext.stream = stream; m_stream = stream;
if (isLoaded()) { if (isLoaded()) {
m_threadContext.gba->stream = stream; m_threadContext.core->setAVStream(m_threadContext.core, stream);
} }
threadContinue(); threadContinue();
} }
void GameController::clearAVStream() { void GameController::clearAVStream() {
threadInterrupt(); threadInterrupt();
m_threadContext.stream = nullptr; m_stream = nullptr;
if (isLoaded()) { if (isLoaded()) {
m_threadContext.gba->stream = nullptr; m_threadContext.core->setAVStream(m_threadContext.core, nullptr);
} }
threadContinue(); threadContinue();
} }
#ifdef USE_PNG #ifdef USE_PNG
void GameController::screenshot() { void GameController::screenshot() {
GBARunOnThread(&m_threadContext, GBAThreadTakeScreenshot); mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* context) {
mCoreTakeScreenshot(context->core);
});
} }
#endif #endif
@ -914,7 +848,7 @@ void GameController::reloadAudioDriver() {
m_audioProcessor->requestSampleRate(sampleRate); m_audioProcessor->requestSampleRate(sampleRate);
} }
m_audioProcessor->moveToThread(m_audioThread); m_audioProcessor->moveToThread(m_audioThread);
connect(this, SIGNAL(gamePaused(GBAThread*)), m_audioProcessor, SLOT(pause())); connect(this, SIGNAL(gamePaused(mCoreThread*)), m_audioProcessor, SLOT(pause()));
if (isLoaded()) { if (isLoaded()) {
m_audioProcessor->setInput(&m_threadContext); m_audioProcessor->setInput(&m_threadContext);
startAudio(); startAudio();
@ -969,13 +903,15 @@ void GameController::updateKeys() {
int activeKeys = m_activeKeys; int activeKeys = m_activeKeys;
activeKeys |= m_activeButtons; activeKeys |= m_activeButtons;
activeKeys &= ~m_inactiveKeys; activeKeys &= ~m_inactiveKeys;
m_threadContext.activeKeys = activeKeys; if (isLoaded()) {
m_threadContext.core->setKeys(m_threadContext.core, activeKeys);
}
} }
void GameController::redoSamples(int samples) { void GameController::redoSamples(int samples) {
m_threadContext.audioBuffers = samples; // TODO: Put back audio buffers
if (m_threadContext.gba) { if (m_threadContext.core) {
GBAAudioResizeBuffer(&m_threadContext.gba->audio, m_threadContext.audioBuffers); GBAAudioResizeBuffer(&static_cast<GBA*>(m_threadContext.core->board)->audio, samples);
} }
QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged"); QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged");
} }

View File

@ -16,18 +16,20 @@
#include <memory> #include <memory>
extern "C" { extern "C" {
#include "core/thread.h"
#include "gba/cheats.h" #include "gba/cheats.h"
#include "gba/context/overrides.h"
#include "gba/hardware.h" #include "gba/hardware.h"
#include "gba/supervisor/thread.h" #include "gba/input.h"
#ifdef BUILD_SDL #ifdef BUILD_SDL
#include "sdl-events.h" #include "sdl-events.h"
#endif #endif
} }
struct GBAAudio; struct GBAAudio;
struct mCoreOptions; struct mCoreConfig;
struct GBAVideoSoftwareRenderer;
struct Configuration; struct Configuration;
struct Debugger;
class QThread; class QThread;
@ -48,29 +50,28 @@ public:
~GameController(); ~GameController();
const uint32_t* drawContext() const { return m_drawContext; } const uint32_t* drawContext() const { return m_drawContext; }
GBAThread* thread() { return &m_threadContext; } mCoreThread* thread() { return &m_threadContext; }
GBACheatDevice* cheatDevice() { return &m_cheatDevice; } GBACheatDevice* cheatDevice() { return &m_cheatDevice; }
void threadInterrupt(); void threadInterrupt();
void threadContinue(); void threadContinue();
bool isPaused(); bool isPaused();
bool isLoaded() { return m_gameOpen && GBAThreadIsActive(&m_threadContext); } bool isLoaded() { return m_gameOpen && mCoreThreadIsActive(&m_threadContext); }
bool audioSync() const { return m_audioSync; } bool audioSync() const { return m_audioSync; }
bool videoSync() const { return m_videoSync; } bool videoSync() const { return m_videoSync; }
void setInputController(InputController* controller) { m_inputController = controller; } void setInputController(InputController* controller) { m_inputController = controller; }
void setOverrides(Configuration* overrides) { m_threadContext.overrides = overrides; }
void setMultiplayerController(MultiplayerController* controller); void setMultiplayerController(MultiplayerController* controller);
MultiplayerController* multiplayerController() { return m_multiplayer; } MultiplayerController* multiplayerController() { return m_multiplayer; }
void clearMultiplayerController(); void clearMultiplayerController();
void setOverride(const GBACartridgeOverride& override); void setOverride(const GBACartridgeOverride& override);
void clearOverride() { m_threadContext.hasOverride = false; } void clearOverride() { /* TODO: Put back overrides */ }
void setOptions(const mCoreOptions*); void setConfig(const mCoreConfig*);
int stateSlot() const { return m_stateSlot; } int stateSlot() const { return m_stateSlot; }
@ -81,14 +82,14 @@ public:
signals: signals:
void frameAvailable(const uint32_t*); void frameAvailable(const uint32_t*);
void gameStarted(GBAThread*); void gameStarted(mCoreThread*);
void gameStopped(GBAThread*); void gameStopped(mCoreThread*);
void gamePaused(GBAThread*); void gamePaused(mCoreThread*);
void gameUnpaused(GBAThread*); void gameUnpaused(mCoreThread*);
void gameCrashed(const QString& errorMessage); void gameCrashed(const QString& errorMessage);
void gameFailed(); void gameFailed();
void stateLoaded(GBAThread*); void stateLoaded(mCoreThread*);
void rewound(GBAThread*); void rewound(mCoreThread*);
void unimplementedBiosCall(int); void unimplementedBiosCall(int);
void luminanceValueChanged(int); void luminanceValueChanged(int);
@ -101,7 +102,6 @@ public slots:
void loadBIOS(const QString& path); void loadBIOS(const QString& path);
void yankPak(); void yankPak();
void replaceGame(const QString& path); void replaceGame(const QString& path);
void setSkipBIOS(bool);
void setUseBIOS(bool); void setUseBIOS(bool);
void loadPatch(const QString& path); void loadPatch(const QString& path);
void importSharkport(const QString& path); void importSharkport(const QString& path);
@ -129,10 +129,6 @@ public slots:
void saveState(int slot = 0); void saveState(int slot = 0);
void loadBackupState(); void loadBackupState();
void saveBackupState(); void saveBackupState();
void setVideoSync(bool);
void setAudioSync(bool);
void setFrameskip(int);
void setVolume(int);
void setMute(bool); void setMute(bool);
void setTurbo(bool, bool forced = true); void setTurbo(bool, bool forced = true);
void setTurboSpeed(float ratio = -1); void setTurboSpeed(float ratio = -1);
@ -174,8 +170,7 @@ private:
uint32_t* m_drawContext; uint32_t* m_drawContext;
uint32_t* m_frontBuffer; uint32_t* m_frontBuffer;
GBAThread m_threadContext; mCoreThread m_threadContext;
GBAVideoSoftwareRenderer* m_renderer;
GBACheatDevice m_cheatDevice; GBACheatDevice m_cheatDevice;
int m_activeKeys; int m_activeKeys;
int m_activeButtons; int m_activeButtons;
@ -210,7 +205,7 @@ private:
int m_autofireStatus[GBA_KEY_MAX]; int m_autofireStatus[GBA_KEY_MAX];
int m_stateSlot; int m_stateSlot;
GBASerializedState* m_backupLoadState; struct VFile* m_backupLoadState;
QByteArray m_backupSaveState; QByteArray m_backupSaveState;
int m_saveStateFlags; int m_saveStateFlags;
int m_loadStateFlags; int m_loadStateFlags;
@ -218,6 +213,8 @@ private:
InputController* m_inputController; InputController* m_inputController;
MultiplayerController* m_multiplayer; MultiplayerController* m_multiplayer;
mAVStream* m_stream;
struct GameControllerLux : GBALuminanceSource { struct GameControllerLux : GBALuminanceSource {
GameController* p; GameController* p;
uint8_t value; uint8_t value;
@ -225,7 +222,7 @@ private:
uint8_t m_luxValue; uint8_t m_luxValue;
int m_luxLevel; int m_luxLevel;
GBARTCGenericSource m_rtc; mRTCGenericSource m_rtc;
}; };
} }

View File

@ -1073,7 +1073,7 @@ void IOViewer::updateRegister() {
uint16_t value = 0; uint16_t value = 0;
m_controller->threadInterrupt(); m_controller->threadInterrupt();
if (m_controller->isLoaded()) { if (m_controller->isLoaded()) {
value = GBAView16(m_controller->thread()->cpu, BASE_IO | m_register); value = GBAView16(static_cast<ARMCore*>(m_controller->thread()->core->cpu), BASE_IO | m_register);
} }
m_controller->threadContinue(); m_controller->threadContinue();
@ -1096,7 +1096,7 @@ void IOViewer::bitFlipped() {
void IOViewer::writeback() { void IOViewer::writeback() {
m_controller->threadInterrupt(); m_controller->threadInterrupt();
if (m_controller->isLoaded()) { if (m_controller->isLoaded()) {
GBAIOWrite(m_controller->thread()->gba, m_register, m_value); GBAIOWrite(static_cast<GBA*>(m_controller->thread()->core->board), m_register, m_value);
} }
m_controller->threadContinue(); m_controller->threadContinue();
updateRegister(); updateRegister();

View File

@ -169,8 +169,8 @@ bool LoadSaveState::eventFilter(QObject* object, QEvent* event) {
} }
void LoadSaveState::loadState(int slot) { void LoadSaveState::loadState(int slot) {
GBAThread* thread = m_controller->thread(); mCoreThread* thread = m_controller->thread();
VFile* vf = GBAGetState(thread->gba, thread->dirs.state, slot, false); VFile* vf = mCoreGetState(thread->core, slot, 0);
if (!vf) { if (!vf) {
m_slots[slot - 1]->setText(tr("Empty")); m_slots[slot - 1]->setText(tr("Empty"));
return; return;

View File

@ -87,7 +87,7 @@ MemoryModel::MemoryModel(QWidget* parent)
} }
void MemoryModel::setController(GameController* controller) { void MemoryModel::setController(GameController* controller) {
m_cpu = controller->thread()->cpu; m_cpu = static_cast<ARMCore*>(controller->thread()->core->cpu);
} }
void MemoryModel::setRegion(uint32_t base, uint32_t size, const QString& name) { void MemoryModel::setRegion(uint32_t base, uint32_t size, const QString& name) {

View File

@ -9,6 +9,7 @@
#include "GameController.h" #include "GameController.h"
extern "C" { extern "C" {
#include "core/core.h"
#include "gba/memory.h" #include "gba/memory.h"
} }
@ -31,12 +32,12 @@ MemoryView::MemoryView(GameController* controller, QWidget* parent)
connect(m_ui.hexfield, SIGNAL(selectionChanged(uint32_t, uint32_t)), this, SLOT(updateSelection(uint32_t, uint32_t))); connect(m_ui.hexfield, SIGNAL(selectionChanged(uint32_t, uint32_t)), this, SLOT(updateSelection(uint32_t, uint32_t)));
connect(controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(close())); connect(controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
connect(controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(update())); connect(controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(update()));
connect(controller, SIGNAL(gamePaused(GBAThread*)), this, SLOT(update())); connect(controller, SIGNAL(gamePaused(mCoreThread*)), this, SLOT(update()));
connect(controller, SIGNAL(stateLoaded(GBAThread*)), this, SLOT(update())); connect(controller, SIGNAL(stateLoaded(mCoreThread*)), this, SLOT(update()));
connect(controller, SIGNAL(rewound(GBAThread*)), this, SLOT(update())); connect(controller, SIGNAL(rewound(mCoreThread*)), this, SLOT(update()));
} }
void MemoryView::setIndex(int index) { void MemoryView::setIndex(int index) {
@ -83,7 +84,7 @@ void MemoryView::updateStatus() {
if (!m_controller->isLoaded()) { if (!m_controller->isLoaded()) {
return; return;
} }
ARMCore* cpu = m_controller->thread()->cpu; ARMCore* cpu = static_cast<ARMCore*>(m_controller->thread()->core->cpu);
union { union {
uint32_t u32; uint32_t u32;
int32_t i32; int32_t i32;

View File

@ -29,13 +29,13 @@ bool MultiplayerController::attachGame(GameController* controller) {
MutexUnlock(&m_lockstep.mutex); MutexUnlock(&m_lockstep.mutex);
controller->threadInterrupt(); controller->threadInterrupt();
GBAThread* thread = controller->thread(); mCoreThread* thread = controller->thread();
if (controller->isLoaded()) { /*if (controller->isLoaded()) {
GBASIOSetDriver(&thread->gba->sio, &node->d, SIO_MULTI); GBASIOSetDriver(&thread->gba->sio, &node->d, SIO_MULTI);
GBASIOSetDriver(&thread->gba->sio, &node->d, SIO_NORMAL_32); GBASIOSetDriver(&thread->gba->sio, &node->d, SIO_NORMAL_32);
} }
thread->sioDrivers.multiplayer = &node->d; thread->sioDrivers.multiplayer = &node->d;
thread->sioDrivers.normal = &node->d; thread->sioDrivers.normal = &node->d;*/
controller->threadContinue(); controller->threadContinue();
emit gameAttached(); emit gameAttached();
return true; return true;
@ -44,8 +44,8 @@ bool MultiplayerController::attachGame(GameController* controller) {
void MultiplayerController::detachGame(GameController* controller) { void MultiplayerController::detachGame(GameController* controller) {
controller->threadInterrupt(); controller->threadInterrupt();
MutexLock(&m_lockstep.mutex); MutexLock(&m_lockstep.mutex);
GBAThread* thread = nullptr; mCoreThread* thread = nullptr;
for (int i = 0; i < m_lockstep.attached; ++i) { /*for (int i = 0; i < m_lockstep.attached; ++i) {
thread = controller->thread(); thread = controller->thread();
if (thread->sioDrivers.multiplayer == &m_lockstep.players[i]->d) { if (thread->sioDrivers.multiplayer == &m_lockstep.players[i]->d) {
break; break;
@ -62,7 +62,7 @@ void MultiplayerController::detachGame(GameController* controller) {
thread->sioDrivers.normal = nullptr; thread->sioDrivers.normal = nullptr;
GBASIOLockstepDetachNode(&m_lockstep, node); GBASIOLockstepDetachNode(&m_lockstep, node);
delete node; delete node;
} }*/
MutexUnlock(&m_lockstep.mutex); MutexUnlock(&m_lockstep.mutex);
controller->threadContinue(); controller->threadContinue();
emit gameDetached(); emit gameDetached();
@ -72,11 +72,11 @@ int MultiplayerController::playerId(GameController* controller) {
MutexLock(&m_lockstep.mutex); MutexLock(&m_lockstep.mutex);
int id = -1; int id = -1;
for (int i = 0; i < m_lockstep.attached; ++i) { for (int i = 0; i < m_lockstep.attached; ++i) {
GBAThread* thread = controller->thread(); mCoreThread* thread = controller->thread();
if (thread->sioDrivers.multiplayer == &m_lockstep.players[i]->d) { /*if (thread->sioDrivers.multiplayer == &m_lockstep.players[i]->d) {
id = i; id = i;
break; break;
} }*/
} }
MutexUnlock(&m_lockstep.mutex); MutexUnlock(&m_lockstep.mutex);
return id; return id;

View File

@ -21,8 +21,8 @@ OverrideView::OverrideView(GameController* controller, ConfigController* config,
{ {
m_ui.setupUi(this); m_ui.setupUi(this);
connect(controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*))); connect(controller, SIGNAL(gameStarted(mCoreThread*)), this, SLOT(gameStarted(mCoreThread*)));
connect(controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped())); connect(controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(gameStopped()));
connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) { connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) {
m_ui.hwRTC->setEnabled(!enabled); m_ui.hwRTC->setEnabled(!enabled);
@ -99,12 +99,13 @@ void OverrideView::updateOverrides() {
} }
} }
void OverrideView::gameStarted(GBAThread* thread) { void OverrideView::gameStarted(mCoreThread* thread) {
if (!thread->gba) { if (!thread->core) {
gameStopped(); gameStopped();
return; return;
} }
m_ui.savetype->setCurrentIndex(thread->gba->memory.savedata.type + 1); GBA* gba = static_cast<GBA*>(thread->core->board);
m_ui.savetype->setCurrentIndex(gba->memory.savedata.type + 1);
m_ui.savetype->setEnabled(false); m_ui.savetype->setEnabled(false);
m_ui.hwAutodetect->setEnabled(false); m_ui.hwAutodetect->setEnabled(false);
@ -114,23 +115,23 @@ void OverrideView::gameStarted(GBAThread* thread) {
m_ui.hwTilt->setEnabled(false); m_ui.hwTilt->setEnabled(false);
m_ui.hwRumble->setEnabled(false); m_ui.hwRumble->setEnabled(false);
m_ui.hwRTC->setChecked(thread->gba->memory.hw.devices & HW_RTC); m_ui.hwRTC->setChecked(gba->memory.hw.devices & HW_RTC);
m_ui.hwGyro->setChecked(thread->gba->memory.hw.devices & HW_GYRO); m_ui.hwGyro->setChecked(gba->memory.hw.devices & HW_GYRO);
m_ui.hwLight->setChecked(thread->gba->memory.hw.devices & HW_LIGHT_SENSOR); m_ui.hwLight->setChecked(gba->memory.hw.devices & HW_LIGHT_SENSOR);
m_ui.hwTilt->setChecked(thread->gba->memory.hw.devices & HW_TILT); m_ui.hwTilt->setChecked(gba->memory.hw.devices & HW_TILT);
m_ui.hwRumble->setChecked(thread->gba->memory.hw.devices & HW_RUMBLE); m_ui.hwRumble->setChecked(gba->memory.hw.devices & HW_RUMBLE);
m_ui.hwGBPlayer->setChecked(thread->gba->memory.hw.devices & HW_GB_PLAYER_DETECTION); m_ui.hwGBPlayer->setChecked(gba->memory.hw.devices & HW_GB_PLAYER_DETECTION);
if (thread->gba->idleLoop != IDLE_LOOP_NONE) { if (gba->idleLoop != IDLE_LOOP_NONE) {
m_ui.idleLoop->setText(QString::number(thread->gba->idleLoop, 16)); m_ui.idleLoop->setText(QString::number(gba->idleLoop, 16));
} else { } else {
m_ui.idleLoop->clear(); m_ui.idleLoop->clear();
} }
GBAGetGameCode(thread->gba, m_override.id); GBAGetGameCode(gba, m_override.id);
m_override.hardware = thread->gba->memory.hw.devices; m_override.hardware = gba->memory.hw.devices;
m_override.savetype = thread->gba->memory.savedata.type; m_override.savetype = gba->memory.savedata.type;
m_override.idleLoop = thread->gba->idleLoop; m_override.idleLoop = gba->idleLoop;
m_ui.idleLoop->setEnabled(false); m_ui.idleLoop->setEnabled(false);

View File

@ -14,7 +14,7 @@ extern "C" {
#include "gba/context/overrides.h" #include "gba/context/overrides.h"
} }
struct GBAThread; struct mCoreThread;
namespace QGBA { namespace QGBA {
@ -32,7 +32,7 @@ public slots:
private slots: private slots:
void updateOverrides(); void updateOverrides();
void gameStarted(GBAThread*); void gameStarted(mCoreThread*);
void gameStopped(); void gameStopped();
private: private:

View File

@ -46,14 +46,14 @@ PaletteView::PaletteView(GameController* controller, QWidget* parent)
connect(m_ui.exportBG, &QAbstractButton::clicked, [this] () { exportPalette(0, 256); }); connect(m_ui.exportBG, &QAbstractButton::clicked, [this] () { exportPalette(0, 256); });
connect(m_ui.exportOBJ, &QAbstractButton::clicked, [this] () { exportPalette(256, 256); }); connect(m_ui.exportOBJ, &QAbstractButton::clicked, [this] () { exportPalette(256, 256); });
connect(controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(close())); connect(controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
} }
void PaletteView::updatePalette() { void PaletteView::updatePalette() {
if (!m_controller->thread() || !m_controller->thread()->gba) { if (!m_controller->thread() || !m_controller->thread()->core) {
return; return;
} }
const uint16_t* palette = m_controller->thread()->gba->video.palette; const uint16_t* palette = static_cast<GBA*>(m_controller->thread()->core->board)->video.palette;
for (int i = 0; i < 256; ++i) { for (int i = 0; i < 256; ++i) {
m_ui.bgGrid->setColor(i, palette[i]); m_ui.bgGrid->setColor(i, palette[i]);
m_ui.objGrid->setColor(i, palette[i + 256]); m_ui.objGrid->setColor(i, palette[i + 256]);
@ -63,7 +63,7 @@ void PaletteView::updatePalette() {
} }
void PaletteView::selectIndex(int index) { void PaletteView::selectIndex(int index) {
uint16_t color = m_controller->thread()->gba->video.palette[index]; uint16_t color = static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[index];
m_ui.selected->setColor(0, color); m_ui.selected->setColor(0, color);
uint32_t r = GBA_R5(color); uint32_t r = GBA_R5(color);
uint32_t g = GBA_G5(color); uint32_t g = GBA_G5(color);
@ -100,9 +100,9 @@ void PaletteView::exportPalette(int start, int length) {
} }
QString filter = dialog->selectedNameFilter(); QString filter = dialog->selectedNameFilter();
if (filter.contains("*.pal")) { if (filter.contains("*.pal")) {
GBAExportPaletteRIFF(vf, length, &m_controller->thread()->gba->video.palette[start]); GBAExportPaletteRIFF(vf, length, &static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[start]);
} else if (filter.contains("*.act")) { } else if (filter.contains("*.act")) {
GBAExportPaletteACT(vf, length, &m_controller->thread()->gba->video.palette[start]); GBAExportPaletteACT(vf, length, &static_cast<GBA*>(m_controller->thread()->core->board)->video.palette[start]);
} }
vf->close(vf); vf->close(vf);
m_controller->threadContinue(); m_controller->threadContinue();

View File

@ -26,7 +26,7 @@ ROMInfo::ROMInfo(GameController* controller, QWidget* parent)
const NoIntroDB* db = GBAApp::app()->gameDB(); const NoIntroDB* db = GBAApp::app()->gameDB();
controller->threadInterrupt(); controller->threadInterrupt();
GBA* gba = controller->thread()->gba; GBA* gba = static_cast<GBA*>(controller->thread()->core->board);
char title[13] = {}; char title[13] = {};
GBAGetGameCode(gba, title); GBAGetGameCode(gba, title);
m_ui.id->setText(QLatin1String(title)); m_ui.id->setText(QLatin1String(title));

View File

@ -9,6 +9,11 @@
#include "GamepadAxisEvent.h" #include "GamepadAxisEvent.h"
#include "InputController.h" #include "InputController.h"
extern "C" {
#include "core/core.h"
#include "gba/gba.h"
}
using namespace QGBA; using namespace QGBA;
SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent) SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent)
@ -105,7 +110,7 @@ bool SensorView::eventFilter(QObject*, QEvent* event) {
void SensorView::updateSensors() { void SensorView::updateSensors() {
m_controller->threadInterrupt(); m_controller->threadInterrupt();
if (m_rotation->sample && if (m_rotation->sample &&
(!m_controller->isLoaded() || !(m_controller->thread()->gba->memory.hw.devices & (HW_GYRO | HW_TILT)))) { (!m_controller->isLoaded() || !(static_cast<GBA*>(m_controller->thread()->core->board)->memory.hw.devices & (HW_GYRO | HW_TILT)))) {
m_rotation->sample(m_rotation); m_rotation->sample(m_rotation);
m_rotation->sample(m_rotation); m_rotation->sample(m_rotation);
m_rotation->sample(m_rotation); m_rotation->sample(m_rotation);

View File

@ -79,7 +79,6 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
m_controller = new GameController(this); m_controller = new GameController(this);
m_controller->setInputController(&m_inputController); m_controller->setInputController(&m_inputController);
m_controller->setOverrides(m_config->overrides());
updateTitle(); updateTitle();
m_display = Display::create(this); m_display = Display::create(this);
@ -95,13 +94,13 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
m_screenWidget->setLockAspectRatio(m_logo.width(), m_logo.height()); m_screenWidget->setLockAspectRatio(m_logo.width(), m_logo.height());
setCentralWidget(m_screenWidget); setCentralWidget(m_screenWidget);
connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*))); connect(m_controller, SIGNAL(gameStarted(mCoreThread*)), this, SLOT(gameStarted(mCoreThread*)));
connect(m_controller, SIGNAL(gameStarted(GBAThread*)), &m_inputController, SLOT(suspendScreensaver())); connect(m_controller, SIGNAL(gameStarted(mCoreThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_display, SLOT(stopDrawing()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(gameStopped()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), &m_inputController, SLOT(resumeScreensaver())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(stateLoaded(GBAThread*)), m_display, SLOT(forceDraw())); connect(m_controller, SIGNAL(stateLoaded(mCoreThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, SIGNAL(rewound(GBAThread*)), m_display, SLOT(forceDraw())); connect(m_controller, SIGNAL(rewound(mCoreThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, &GameController::gamePaused, [this]() { connect(m_controller, &GameController::gamePaused, [this]() {
QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), VIDEO_HORIZONTAL_PIXELS, QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), VIDEO_HORIZONTAL_PIXELS,
VIDEO_VERTICAL_PIXELS, VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL, QImage::Format_RGBX8888); VIDEO_VERTICAL_PIXELS, VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL, QImage::Format_RGBX8888);
@ -110,18 +109,18 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
m_screenWidget->setPixmap(pixmap); m_screenWidget->setPixmap(pixmap);
m_screenWidget->setLockAspectRatio(3, 2); m_screenWidget->setLockAspectRatio(3, 2);
}); });
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), m_display, SLOT(pauseDrawing())); connect(m_controller, SIGNAL(gamePaused(mCoreThread*)), m_display, SLOT(pauseDrawing()));
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), menuBar(), SLOT(show())); connect(m_controller, SIGNAL(gamePaused(mCoreThread*)), menuBar(), SLOT(show()));
connect(m_controller, &GameController::gameUnpaused, [this]() { connect(m_controller, &GameController::gameUnpaused, [this]() {
if(isFullScreen()) { if(isFullScreen()) {
menuBar()->hide(); menuBar()->hide();
} }
}); });
#endif #endif
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), &m_inputController, SLOT(resumeScreensaver())); connect(m_controller, SIGNAL(gamePaused(mCoreThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), m_display, SLOT(unpauseDrawing())); connect(m_controller, SIGNAL(gameUnpaused(mCoreThread*)), m_display, SLOT(unpauseDrawing()));
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), &m_inputController, SLOT(suspendScreensaver())); connect(m_controller, SIGNAL(gameUnpaused(mCoreThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(postLog(int, const QString&)), &m_log, SLOT(postLog(int, const QString&))); connect(m_controller, SIGNAL(postLog(int, const QString&)), &m_log, SLOT(postLog(int, const QString&)));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(recordFrame())); connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(recordFrame()));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), m_display, SLOT(framePosted(const uint32_t*))); connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), m_display, SLOT(framePosted(const uint32_t*)));
@ -132,7 +131,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
connect(&m_log, SIGNAL(levelsSet(int)), m_controller, SLOT(setLogLevel(int))); connect(&m_log, SIGNAL(levelsSet(int)), m_controller, SLOT(setLogLevel(int)));
connect(&m_log, SIGNAL(levelsEnabled(int)), m_controller, SLOT(enableLogLevel(int))); connect(&m_log, SIGNAL(levelsEnabled(int)), m_controller, SLOT(enableLogLevel(int)));
connect(&m_log, SIGNAL(levelsDisabled(int)), m_controller, SLOT(disableLogLevel(int))); connect(&m_log, SIGNAL(levelsDisabled(int)), m_controller, SLOT(disableLogLevel(int)));
connect(this, SIGNAL(startDrawing(GBAThread*)), m_display, SLOT(startDrawing(GBAThread*)), Qt::QueuedConnection); connect(this, SIGNAL(startDrawing(mCoreThread*)), m_display, SLOT(startDrawing(mCoreThread*)), Qt::QueuedConnection);
connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing())); connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing()));
connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame())); connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame()));
connect(this, SIGNAL(shutdown()), m_logView, SLOT(hide())); connect(this, SIGNAL(shutdown()), m_logView, SLOT(hide()));
@ -254,7 +253,7 @@ void Window::reloadConfig() {
m_controller->setLoadStateExtdata(flags); m_controller->setLoadStateExtdata(flags);
} }
m_controller->setOptions(opts); m_controller->setConfig(m_config->config());
m_display->lockAspectRatio(opts->lockAspectRatio); m_display->lockAspectRatio(opts->lockAspectRatio);
m_display->filter(opts->resampleVideo); m_display->filter(opts->resampleVideo);
@ -418,8 +417,8 @@ void Window::openVideoWindow() {
m_videoView = new VideoView(); m_videoView = new VideoView();
connect(m_videoView, SIGNAL(recordingStarted(mAVStream*)), m_controller, SLOT(setAVStream(mAVStream*))); connect(m_videoView, SIGNAL(recordingStarted(mAVStream*)), m_controller, SLOT(setAVStream(mAVStream*)));
connect(m_videoView, SIGNAL(recordingStopped()), m_controller, SLOT(clearAVStream()), Qt::DirectConnection); connect(m_videoView, SIGNAL(recordingStopped()), m_controller, SLOT(clearAVStream()), Qt::DirectConnection);
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_videoView, SLOT(stopRecording())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_videoView, SLOT(stopRecording()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_videoView, SLOT(close())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_videoView, SLOT(close()));
connect(this, SIGNAL(shutdown()), m_videoView, SLOT(close())); connect(this, SIGNAL(shutdown()), m_videoView, SLOT(close()));
} }
m_videoView->show(); m_videoView->show();
@ -432,8 +431,8 @@ void Window::openGIFWindow() {
m_gifView = new GIFView(); m_gifView = new GIFView();
connect(m_gifView, SIGNAL(recordingStarted(mAVStream*)), m_controller, SLOT(setAVStream(mAVStream*))); connect(m_gifView, SIGNAL(recordingStarted(mAVStream*)), m_controller, SLOT(setAVStream(mAVStream*)));
connect(m_gifView, SIGNAL(recordingStopped()), m_controller, SLOT(clearAVStream()), Qt::DirectConnection); connect(m_gifView, SIGNAL(recordingStopped()), m_controller, SLOT(clearAVStream()), Qt::DirectConnection);
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_gifView, SLOT(stopRecording())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_gifView, SLOT(stopRecording()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_gifView, SLOT(close())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_gifView, SLOT(close()));
connect(this, SIGNAL(shutdown()), m_gifView, SLOT(close())); connect(this, SIGNAL(shutdown()), m_gifView, SLOT(close()));
} }
m_gifView->show(); m_gifView->show();
@ -597,7 +596,7 @@ void Window::toggleFullScreen() {
} }
} }
void Window::gameStarted(GBAThread* context) { void Window::gameStarted(mCoreThread* context) {
char title[13] = { '\0' }; char title[13] = { '\0' };
MutexLock(&context->stateMutex); MutexLock(&context->stateMutex);
if (context->state < THREAD_EXITING) { if (context->state < THREAD_EXITING) {
@ -611,10 +610,10 @@ void Window::gameStarted(GBAThread* context) {
action->setDisabled(false); action->setDisabled(false);
} }
multiplayerChanged(); multiplayerChanged();
if (context->fname) { /*if (context->fname) {
setWindowFilePath(context->fname); setWindowFilePath(context->fname);
appendMRU(context->fname); appendMRU(context->fname);
} }*/
updateTitle(); updateTitle();
attachWidget(m_display); attachWidget(m_display);
@ -716,11 +715,11 @@ void Window::updateTitle(float fps) {
if (m_controller->isLoaded()) { if (m_controller->isLoaded()) {
const NoIntroDB* db = GBAApp::app()->gameDB(); const NoIntroDB* db = GBAApp::app()->gameDB();
NoIntroGame game; NoIntroGame game;
if (db && NoIntroDBLookupGameByCRC(db, m_controller->thread()->gba->romCrc32, &game)) { if (db && NoIntroDBLookupGameByCRC(db, static_cast<GBA*>(m_controller->thread()->core->board)->romCrc32, &game)) {
title = QLatin1String(game.name); title = QLatin1String(game.name);
} else { } else {
char gameTitle[13] = { '\0' }; char gameTitle[13] = { '\0' };
GBAGetGameTitle(m_controller->thread()->gba, gameTitle); GBAGetGameTitle(static_cast<GBA*>(m_controller->thread()->core->board), gameTitle);
title = gameTitle; title = gameTitle;
} }
} }
@ -749,7 +748,7 @@ void Window::openStateWindow(LoadSave ls) {
bool wasPaused = m_controller->isPaused(); bool wasPaused = m_controller->isPaused();
m_stateWindow = new LoadSaveState(m_controller); m_stateWindow = new LoadSaveState(m_controller);
connect(this, SIGNAL(shutdown()), m_stateWindow, SLOT(close())); connect(this, SIGNAL(shutdown()), m_stateWindow, SLOT(close()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_stateWindow, SLOT(close())); connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), m_stateWindow, SLOT(close()));
connect(m_stateWindow, &LoadSaveState::closed, [this]() { connect(m_stateWindow, &LoadSaveState::closed, [this]() {
detachWidget(m_stateWindow); detachWidget(m_stateWindow);
m_stateWindow = nullptr; m_stateWindow = nullptr;
@ -979,14 +978,14 @@ void Window::setupMenu(QMenuBar* menubar) {
ConfigOption* videoSync = m_config->addOption("videoSync"); ConfigOption* videoSync = m_config->addOption("videoSync");
videoSync->addBoolean(tr("Sync to &video"), emulationMenu); videoSync->addBoolean(tr("Sync to &video"), emulationMenu);
videoSync->connect([this](const QVariant& value) { videoSync->connect([this](const QVariant& value) {
m_controller->setVideoSync(value.toBool()); reloadConfig();
}, this); }, this);
m_config->updateOption("videoSync"); m_config->updateOption("videoSync");
ConfigOption* audioSync = m_config->addOption("audioSync"); ConfigOption* audioSync = m_config->addOption("audioSync");
audioSync->addBoolean(tr("Sync to &audio"), emulationMenu); audioSync->addBoolean(tr("Sync to &audio"), emulationMenu);
audioSync->connect([this](const QVariant& value) { audioSync->connect([this](const QVariant& value) {
m_controller->setAudioSync(value.toBool()); reloadConfig();
}, this); }, this);
m_config->updateOption("audioSync"); m_config->updateOption("audioSync");
@ -1061,7 +1060,7 @@ void Window::setupMenu(QMenuBar* menubar) {
QMenu* skipMenu = avMenu->addMenu(tr("Frame&skip")); QMenu* skipMenu = avMenu->addMenu(tr("Frame&skip"));
ConfigOption* skip = m_config->addOption("frameskip"); ConfigOption* skip = m_config->addOption("frameskip");
skip->connect([this](const QVariant& value) { skip->connect([this](const QVariant& value) {
m_controller->setFrameskip(value.toInt()); reloadConfig();
}, this); }, this);
for (int i = 0; i <= 10; ++i) { for (int i = 0; i <= 10; ++i) {
skip->addValue(QString::number(i), i, skipMenu); skip->addValue(QString::number(i), i, skipMenu);
@ -1209,12 +1208,12 @@ void Window::setupMenu(QMenuBar* menubar) {
ConfigOption* skipBios = m_config->addOption("skipBios"); ConfigOption* skipBios = m_config->addOption("skipBios");
skipBios->connect([this](const QVariant& value) { skipBios->connect([this](const QVariant& value) {
m_controller->setSkipBIOS(value.toBool()); reloadConfig();
}, this); }, this);
ConfigOption* useBios = m_config->addOption("useBios"); ConfigOption* useBios = m_config->addOption("useBios");
useBios->connect([this](const QVariant& value) { useBios->connect([this](const QVariant& value) {
m_controller->setUseBIOS(value.toBool()); reloadConfig();
}, this); }, this);
ConfigOption* buffers = m_config->addOption("audioBuffers"); ConfigOption* buffers = m_config->addOption("audioBuffers");
@ -1229,7 +1228,7 @@ void Window::setupMenu(QMenuBar* menubar) {
ConfigOption* volume = m_config->addOption("volume"); ConfigOption* volume = m_config->addOption("volume");
volume->connect([this](const QVariant& value) { volume->connect([this](const QVariant& value) {
m_controller->setVolume(value.toInt()); reloadConfig();
}, this); }, this);
ConfigOption* rewindEnable = m_config->addOption("rewindEnable"); ConfigOption* rewindEnable = m_config->addOption("rewindEnable");

View File

@ -50,7 +50,7 @@ public:
void resizeFrame(int width, int height); void resizeFrame(int width, int height);
signals: signals:
void startDrawing(GBAThread*); void startDrawing(mCoreThread*);
void shutdown(); void shutdown();
void audioBufferSamplesChanged(int samples); void audioBufferSamplesChanged(int samples);
void sampleRateChanged(unsigned samples); void sampleRateChanged(unsigned samples);
@ -111,7 +111,7 @@ protected:
virtual void mouseDoubleClickEvent(QMouseEvent*) override; virtual void mouseDoubleClickEvent(QMouseEvent*) override;
private slots: private slots:
void gameStarted(GBAThread*); void gameStarted(mCoreThread*);
void gameStopped(); void gameStopped();
void gameCrashed(const QString&); void gameCrashed(const QString&);
void gameFailed(); void gameFailed();

View File

@ -196,7 +196,7 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) {
return 1; return 1;
} }
mCoreAutoloadSave(renderer->core); mCoreAutoloadSave(renderer->core);
// TODO: Create debugger // TODO: Put back debugger
if (args->patch) { if (args->patch) {
struct VFile* patch = VFileOpen(args->patch, O_RDONLY); struct VFile* patch = VFileOpen(args->patch, O_RDONLY);