mirror of https://github.com/mgba-emu/mgba.git
Qt: Sloppy first pass at refactor
This commit is contained in:
parent
fc905657ad
commit
d0771b78e2
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -20,7 +20,7 @@ DisplayQt::DisplayQt(QWidget* parent)
|
|||
{
|
||||
}
|
||||
|
||||
void DisplayQt::startDrawing(GBAThread*) {
|
||||
void DisplayQt::startDrawing(mCoreThread*) {
|
||||
m_isDrawing = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue