diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index eeb079c98..0783d0b2d 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -37,6 +37,8 @@ endif() set(SOURCE_FILES AudioProcessor.cpp + CheatsModel.cpp + CheatsView.cpp ConfigController.cpp Display.cpp GBAApp.cpp @@ -60,6 +62,7 @@ set(SOURCE_FILES VideoView.cpp) qt5_wrap_ui(UI_FILES + CheatsView.ui GIFView.ui LoadSaveState.ui LogView.ui diff --git a/src/platform/qt/CheatsModel.cpp b/src/platform/qt/CheatsModel.cpp new file mode 100644 index 000000000..913f86394 --- /dev/null +++ b/src/platform/qt/CheatsModel.cpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "CheatsModel.h" + +extern "C" { +#include "gba/cheats.h" +#include "util/vfs.h" +} + +using namespace QGBA; + +CheatsModel::CheatsModel(GBACheatDevice* device, QObject* parent) + : QAbstractItemModel(parent) + , m_device(device) +{ +} + +QVariant CheatsModel::data(const QModelIndex& index, int role) const { + if (!index.isValid()) { + return QVariant(); + } + + int row = index.row(); + const GBACheatSet* cheats = static_cast(index.internalPointer()); + switch (role) { + case Qt::DisplayRole: + return cheats->name ? cheats->name : tr("(untitled)"); + case Qt::CheckStateRole: + return Qt::Checked; + default: + return QVariant(); + } +} + +QModelIndex CheatsModel::index(int row, int column, const QModelIndex& parent) const { + return createIndex(row, column, *GBACheatSetsGetPointer(&m_device->cheats, row)); +} + +QModelIndex CheatsModel::parent(const QModelIndex& index) const { + return QModelIndex(); +} + +int CheatsModel::columnCount(const QModelIndex& parent) const { + return 1; +} + +int CheatsModel::rowCount(const QModelIndex& parent) const { + if (parent.isValid()) { + return 0; + } + return GBACheatSetsSize(&m_device->cheats); +} + +void CheatsModel::loadFile(const QString& path) { + VFile* vf = VFileOpen(path.toLocal8Bit().constData(), O_RDONLY); + if (!vf) { + return; + } + beginResetModel(); + GBACheatParseFile(m_device, vf); + endResetModel(); + vf->close(vf); +} \ No newline at end of file diff --git a/src/platform/qt/CheatsModel.h b/src/platform/qt/CheatsModel.h new file mode 100644 index 000000000..6d8ec1dc2 --- /dev/null +++ b/src/platform/qt/CheatsModel.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef QGBA_CHEATS_MODEL +#define QGBA_CHEATS_MODEL + +#include + +struct GBACheatDevice; + +namespace QGBA { + +class CheatsModel : public QAbstractItemModel { +Q_OBJECT + +public: + CheatsModel(GBACheatDevice* m_device, QObject* parent = nullptr); + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + virtual QModelIndex index(int row, int column, const QModelIndex& parent) const override; + virtual QModelIndex parent(const QModelIndex& index) const override; + + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + void loadFile(const QString& path); + +private: + GBACheatDevice* m_device; +}; + +} + +#endif \ No newline at end of file diff --git a/src/platform/qt/CheatsView.cpp b/src/platform/qt/CheatsView.cpp new file mode 100644 index 000000000..a9f4f6bd1 --- /dev/null +++ b/src/platform/qt/CheatsView.cpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "CheatsView.h" + +#include + +using namespace QGBA; + +CheatsView::CheatsView(GBACheatDevice* device, QWidget* parent) + : QWidget(parent) + , m_model(device) +{ + m_ui.setupUi(this); + + m_ui.cheatList->setModel(&m_model); + + connect(m_ui.load, SIGNAL(clicked()), this, SLOT(load())); +} + +void CheatsView::load() { + QString filename = QFileDialog::getOpenFileName(this, tr("Select cheats file")); + if (!filename.isEmpty()) { + m_model.loadFile(filename); + } +} \ No newline at end of file diff --git a/src/platform/qt/CheatsView.h b/src/platform/qt/CheatsView.h new file mode 100644 index 000000000..f247b37f1 --- /dev/null +++ b/src/platform/qt/CheatsView.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef QGBA_CHEATS_VIEW +#define QGBA_CHEATS_VIEW + +#include + +#include "CheatsModel.h" + +#include "ui_CheatsView.h" + +struct GBACheatDevice; + +namespace QGBA { + +class CheatsView : public QWidget { +Q_OBJECT + +public: + CheatsView(GBACheatDevice* device, QWidget* parent = nullptr); + +private slots: + void load(); + +private: + Ui::CheatsView m_ui; + CheatsModel m_model; +}; + +} + +#endif \ No newline at end of file diff --git a/src/platform/qt/CheatsView.ui b/src/platform/qt/CheatsView.ui new file mode 100644 index 000000000..e98646e36 --- /dev/null +++ b/src/platform/qt/CheatsView.ui @@ -0,0 +1,150 @@ + + + CheatsView + + + + 0 + 0 + 422 + 389 + + + + Cheats + + + + + + false + + + Remove + + + + + + + false + + + Add New Set + + + + + + + false + + + Add GameShark + + + + + + + false + + + Add Pro Action Replay + + + + + + + false + + + Add CodeBreaker + + + + + + + Load + + + + + + + false + + + Add + + + + + + + false + + + Save + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Qt::MoveAction + + + true + + + + + + + false + + + + 0 + 0 + + + + + 180 + 16777215 + + + + + + + + cheatList + addSet + load + codeEntry + add + addGSA + addPAR + addCB + + + + diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index b32d69d66..58d106239 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -46,6 +46,9 @@ GameController::GameController(QObject* parent) GBAVideoSoftwareRendererCreate(m_renderer); m_renderer->outputBuffer = (color_t*) m_drawContext; m_renderer->outputBufferStride = 256; + + GBACheatDeviceCreate(&m_cheatDevice); + m_threadContext.state = THREAD_INITIALIZED; m_threadContext.debugger = 0; m_threadContext.frameskip = 0; @@ -53,6 +56,7 @@ GameController::GameController(QObject* parent) m_threadContext.renderer = &m_renderer->d; m_threadContext.userData = this; m_threadContext.rewindBufferCapacity = 0; + m_threadContext.cheats = &m_cheatDevice; m_threadContext.logLevel = -1; m_lux.p = this; diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 9d1945a3e..2c11837f6 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -13,6 +13,7 @@ #include extern "C" { +#include "gba/cheats.h" #include "gba/hardware.h" #include "gba/supervisor/thread.h" #ifdef BUILD_SDL @@ -44,6 +45,7 @@ public: const uint32_t* drawContext() const { return m_drawContext; } GBAThread* thread() { return &m_threadContext; } + GBACheatDevice* cheatDevice() { return &m_cheatDevice; } void threadInterrupt(); void threadContinue(); @@ -136,6 +138,7 @@ private: uint32_t* m_drawContext; GBAThread m_threadContext; GBAVideoSoftwareRenderer* m_renderer; + GBACheatDevice m_cheatDevice; int m_activeKeys; int m_logLevels; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 8b735cf55..cb2634902 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -14,6 +14,7 @@ #include #include +#include "CheatsView.h" #include "ConfigController.h" #include "GameController.h" #include "GBAKeyEditor.h" @@ -231,6 +232,7 @@ void Window::openOverrideWindow() { overrideWindow->setAttribute(Qt::WA_DeleteOnClose); overrideWindow->show(); } + void Window::openSensorWindow() { SensorView* sensorWindow = new SensorView(m_controller); connect(this, SIGNAL(shutdown()), sensorWindow, SLOT(close())); @@ -238,6 +240,13 @@ void Window::openSensorWindow() { sensorWindow->show(); } +void Window::openCheatsWindow() { + CheatsView* cheatsWindow = new CheatsView(m_controller->cheatDevice()); + connect(this, SIGNAL(shutdown()), cheatsWindow, SLOT(close())); + cheatsWindow->setAttribute(Qt::WA_DeleteOnClose); + cheatsWindow->show(); +} + #ifdef BUILD_SDL void Window::openGamepadWindow() { GBAKeyEditor* keyEditor = new GBAKeyEditor(&m_inputController, SDL_BINDING_BUTTON); @@ -683,6 +692,10 @@ void Window::setupMenu(QMenuBar* menubar) { connect(sensors, SIGNAL(triggered()), this, SLOT(openSensorWindow())); addControlledAction(toolsMenu, sensors, "sensorWindow"); + QAction* cheats = new QAction(tr("&Cheats..."), toolsMenu); + connect(cheats, SIGNAL(triggered()), this, SLOT(openCheatsWindow())); + addControlledAction(toolsMenu, cheats, "cheatsWindow"); + #ifdef USE_GDB_STUB QAction* gdbWindow = new QAction(tr("Start &GDB server..."), toolsMenu); connect(gdbWindow, SIGNAL(triggered()), this, SLOT(gdbOpen())); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 4554d8c51..490b7dc37 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -69,6 +69,7 @@ public slots: void openOverrideWindow(); void openSensorWindow(); + void openCheatsWindow(); #ifdef BUILD_SDL void openGamepadWindow();