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);
}
struct GBAThread* thread = GBAThreadGetContext();
struct mCoreThread* thread = mCoreThreadGet();
if (!thread) {
return;
}
@ -931,12 +931,7 @@ void GBAFrameEnded(struct GBA* gba) {
thread->frameCallback(thread);
}
if (gba->rr && gba->rr->queryReset(gba->rr)) {
// TODO: Clean up reset scheduling
MutexLock(&thread->stateMutex);
thread->state = THREAD_RESETING;
MutexUnlock(&thread->stateMutex);
}
// TODO: Put back RR
}
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"
extern "C" {
#include "core/thread.h"
#include "gba/gba.h"
#include "gba/audio.h"
#include "gba/supervisor/thread.h"
}
using namespace QGBA;
@ -25,18 +25,18 @@ AudioDevice::AudioDevice(QObject* parent)
}
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");
return;
}
double fauxClock = GBAAudioCalculateRatio(1, m_context->fpsTarget, 1);
double fauxClock = GBAAudioCalculateRatio(1, 60, 1); // TODO: Put back fpsTarget
mCoreSyncLockAudio(&m_context->sync);
blip_set_rates(m_context->gba->audio.psg.left, 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, 0), 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);
}
void AudioDevice::setInput(GBAThread* input) {
void AudioDevice::setInput(mCoreThread* input) {
m_context = input;
}
@ -45,18 +45,18 @@ qint64 AudioDevice::readData(char* data, qint64 maxSize) {
maxSize = 0xFFFFFFFF;
}
if (!m_context->gba) {
LOG(WARN) << tr("Audio device is missing its GBA");
if (!m_context->core) {
LOG(WARN) << tr("Audio device is missing its core");
return 0;
}
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)) {
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->gba->audio.psg.right, &reinterpret_cast<GBAStereoSample*>(data)->right, 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->core->getAudioChannel(m_context->core, 1), &reinterpret_cast<GBAStereoSample*>(data)->right, available, true);
mCoreSyncConsumeAudio(&m_context->sync);
return available * sizeof(GBAStereoSample);
}

View File

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

View File

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

View File

@ -7,7 +7,7 @@
#define QGBA_AUDIO_PROCESSOR
#include <QObject>
struct GBAThread;
struct mCoreThread;
namespace QGBA {
@ -29,7 +29,7 @@ public:
AudioProcessor(QObject* parent = nullptr);
virtual void setInput(GBAThread* input);
virtual void setInput(mCoreThread* input);
int getBufferSamples() const { return m_samples; }
virtual unsigned sampleRate() const = 0;
@ -43,10 +43,10 @@ public slots:
virtual void requestSampleRate(unsigned) = 0;
protected:
GBAThread* input() { return m_context; }
mCoreThread* input() { return m_context; }
private:
GBAThread* m_context;
mCoreThread* m_context;
int m_samples;
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);
if (m_device) {
m_device->setInput(input);
@ -59,7 +59,7 @@ bool AudioProcessorQt::start() {
m_device->setInput(input());
m_device->setFormat(m_audioOutput->format());
m_audioOutput->setBufferSize(input()->audioBuffers * 4);
m_audioOutput->setBufferSize(2048 * 4); // TODO?
m_audioOutput->start(m_device);
return m_audioOutput->state() == QAudio::ActiveState;

View File

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

View File

@ -34,9 +34,15 @@ bool AudioProcessorSDL::start() {
return true;
} else {
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;
if (m_audio.thread) {
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;
if (m_audio.thread) {
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.addSet, SIGNAL(clicked()), this, SLOT(addSet()));
connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet()));
connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated()));
connect(controller, SIGNAL(stateLoaded(GBAThread*)), &m_model, SLOT(invalidated()));
connect(controller, SIGNAL(gameStopped(mCoreThread*)), &m_model, SLOT(invalidated()));
connect(controller, SIGNAL(stateLoaded(mCoreThread*)), &m_model, SLOT(invalidated()));
connect(m_ui.add, &QPushButton::clicked, [this]() {
enterCheat(GBACheatAddLine);

View File

@ -109,7 +109,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.fpsTarget = 60;
m_opts.audioBuffers = 1536;
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.rewindEnable = false;
m_opts.rewindBufferInterval = 0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1073,7 +1073,7 @@ void IOViewer::updateRegister() {
uint16_t value = 0;
m_controller->threadInterrupt();
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();
@ -1096,7 +1096,7 @@ void IOViewer::bitFlipped() {
void IOViewer::writeback() {
m_controller->threadInterrupt();
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();
updateRegister();

View File

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

View File

@ -87,7 +87,7 @@ MemoryModel::MemoryModel(QWidget* parent)
}
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) {

View File

@ -9,6 +9,7 @@
#include "GameController.h"
extern "C" {
#include "core/core.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(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(gamePaused(GBAThread*)), this, SLOT(update()));
connect(controller, SIGNAL(stateLoaded(GBAThread*)), this, SLOT(update()));
connect(controller, SIGNAL(rewound(GBAThread*)), this, SLOT(update()));
connect(controller, SIGNAL(gamePaused(mCoreThread*)), this, SLOT(update()));
connect(controller, SIGNAL(stateLoaded(mCoreThread*)), this, SLOT(update()));
connect(controller, SIGNAL(rewound(mCoreThread*)), this, SLOT(update()));
}
void MemoryView::setIndex(int index) {
@ -83,7 +84,7 @@ void MemoryView::updateStatus() {
if (!m_controller->isLoaded()) {
return;
}
ARMCore* cpu = m_controller->thread()->cpu;
ARMCore* cpu = static_cast<ARMCore*>(m_controller->thread()->core->cpu);
union {
uint32_t u32;
int32_t i32;

View File

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

View File

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

View File

@ -14,7 +14,7 @@ extern "C" {
#include "gba/context/overrides.h"
}
struct GBAThread;
struct mCoreThread;
namespace QGBA {
@ -32,7 +32,7 @@ public slots:
private slots:
void updateOverrides();
void gameStarted(GBAThread*);
void gameStarted(mCoreThread*);
void gameStopped();
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.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() {
if (!m_controller->thread() || !m_controller->thread()->gba) {
if (!m_controller->thread() || !m_controller->thread()->core) {
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) {
m_ui.bgGrid->setColor(i, palette[i]);
m_ui.objGrid->setColor(i, palette[i + 256]);
@ -63,7 +63,7 @@ void PaletteView::updatePalette() {
}
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);
uint32_t r = GBA_R5(color);
uint32_t g = GBA_G5(color);
@ -100,9 +100,9 @@ void PaletteView::exportPalette(int start, int length) {
}
QString filter = dialog->selectedNameFilter();
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")) {
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);
m_controller->threadContinue();

View File

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

View File

@ -9,6 +9,11 @@
#include "GamepadAxisEvent.h"
#include "InputController.h"
extern "C" {
#include "core/core.h"
#include "gba/gba.h"
}
using namespace QGBA;
SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent)
@ -105,7 +110,7 @@ bool SensorView::eventFilter(QObject*, QEvent* event) {
void SensorView::updateSensors() {
m_controller->threadInterrupt();
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);

View File

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

View File

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

View File

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