mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
b5d7a37aa6
4
CHANGES
4
CHANGES
|
@ -48,6 +48,7 @@ Features:
|
|||
- New unlicensed GB mappers: Pokémon Jade/Diamond, BBD, and Hitek
|
||||
- Stack tracing tools in ARM debugger (by ahigerd)
|
||||
- Command scripts for CLI debugger (by ahigerd)
|
||||
- Scheduled event dumping in CLI debugger
|
||||
- ARM disassembler now resolves addresses to symbol names
|
||||
- Add Game Boy Player feature support to ports
|
||||
- Individual window types can now be toggled in debugging views
|
||||
|
@ -130,6 +131,7 @@ Misc:
|
|||
- Core: Improve support for ROM patch cheats, supporting disabling overlapping patches
|
||||
- GB: Allow pausing event loop while CPU is blocked
|
||||
- GB: Add support for sleep and shutdown callbacks
|
||||
- GB Core: Return the current number of banks for ROM/SRAM, not theoretical max
|
||||
- GB I/O: Implement preliminary support for PCM12/PCM34 (closes mgba.io/i/1468)
|
||||
- GBA: Allow pausing event loop while CPU is blocked
|
||||
- GBA BIOS: Division by zero should emit a FATAL error
|
||||
|
@ -152,6 +154,8 @@ Misc:
|
|||
- Qt: Redo OpenGL context thread handling (fixes mgba.io/i/1724)
|
||||
- Qt: Discard additional frame draws if waiting fails
|
||||
- Qt: Unify monospace font usage
|
||||
- Qt: Add button to jump to log settings
|
||||
- Qt: Use relative paths in portable mode when applicable (fixes mgba.io/i/838)
|
||||
- SDL: Fall back to sw blit if OpenGL init fails
|
||||
- Util: Reset vector size on deinit
|
||||
- VFS: Change semantics of VFile.sync on mapped files (fixes mgba.io/i/1730)
|
||||
|
|
|
@ -203,6 +203,7 @@ void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc);
|
|||
|
||||
void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size);
|
||||
void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask);
|
||||
const struct mCoreMemoryBlock* mCoreGetMemoryBlockInfo(struct mCore* core, uint32_t address);
|
||||
|
||||
#ifdef USE_ELF
|
||||
struct ELF;
|
||||
|
|
|
@ -107,14 +107,17 @@ static void _patchROM(struct mCheatDevice* device, struct mCheatSet* cheats) {
|
|||
struct mCheatPatch* patch = mCheatPatchListGetPointer(&cheats->romPatches, i);
|
||||
int segment = -1;
|
||||
if (patch->check && patch->segment < 0) {
|
||||
int maxSegment = 0;
|
||||
for (segment = 0; segment < maxSegment; ++segment) {
|
||||
const struct mCoreMemoryBlock* block = mCoreGetMemoryBlockInfo(device->p, patch->address);
|
||||
if (!block) {
|
||||
continue;
|
||||
}
|
||||
for (segment = 0; segment < block->maxSegment; ++segment) {
|
||||
uint32_t value = _readMemSegment(device->p, patch->address, segment, patch->width);
|
||||
if (value == patch->checkValue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segment == maxSegment) {
|
||||
if (segment == block->maxSegment) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -373,6 +373,17 @@ void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) {
|
|||
}
|
||||
|
||||
void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask) {
|
||||
const struct mCoreMemoryBlock* block = mCoreGetMemoryBlockInfo(core, start);
|
||||
if (!block || !(block->flags & mask)) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t* out = core->getMemoryBlock(core, block->id, size);
|
||||
out += start - block->start;
|
||||
*size -= start - block->start;
|
||||
return out;
|
||||
}
|
||||
|
||||
const struct mCoreMemoryBlock* mCoreGetMemoryBlockInfo(struct mCore* core, uint32_t address) {
|
||||
const struct mCoreMemoryBlock* blocks;
|
||||
size_t nBlocks = core->listMemoryBlocks(core, &blocks);
|
||||
size_t i;
|
||||
|
@ -380,19 +391,13 @@ void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size
|
|||
if (!(blocks[i].flags & mCORE_MEMORY_MAPPED)) {
|
||||
continue;
|
||||
}
|
||||
if (!(blocks[i].flags & mask)) {
|
||||
if (address < blocks[i].start) {
|
||||
continue;
|
||||
}
|
||||
if (start < blocks[i].start) {
|
||||
if (address >= blocks[i].start + blocks[i].size) {
|
||||
continue;
|
||||
}
|
||||
if (start >= blocks[i].start + blocks[i].size) {
|
||||
continue;
|
||||
}
|
||||
uint8_t* out = core->getMemoryBlock(core, blocks[i].id, size);
|
||||
out += start - blocks[i].start;
|
||||
*size -= start - blocks[i].start;
|
||||
return out;
|
||||
return &blocks[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <mgba/internal/debugger/symbols.h>
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
#include <mgba/core/timing.h>
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba/internal/debugger/parser.h>
|
||||
#include <mgba-util/string.h>
|
||||
|
@ -66,6 +67,7 @@ static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
|
|||
static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _events(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
static void _source(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#endif
|
||||
|
@ -81,6 +83,7 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
|||
{ "continue", _continue, "", "Continue execution" },
|
||||
{ "delete", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" },
|
||||
{ "disassemble", _disassemble, "Ii", "Disassemble instructions" },
|
||||
{ "events", _events, "", "Print list of scheduled events" },
|
||||
{ "finish", _finish, "", "Execute until current stack frame returns" },
|
||||
{ "help", _printHelp, "S", "Print help" },
|
||||
{ "listb", _listBreakpoints, "", "List breakpoints" },
|
||||
|
@ -768,6 +771,15 @@ static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv
|
|||
debugger->system->printStatus(debugger->system);
|
||||
}
|
||||
|
||||
static void _events(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
UNUSED(dv);
|
||||
struct mTiming* timing = debugger->d.core->timing;
|
||||
struct mTimingEvent* next = timing->root;
|
||||
for (; next; next = next->next) {
|
||||
debugger->backend->printf(debugger->backend, "%s in %i cycles\n", next->name, mTimingUntil(timing, next));
|
||||
}
|
||||
}
|
||||
|
||||
struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length) {
|
||||
if (!string || length < 1) {
|
||||
return 0;
|
||||
|
|
|
@ -80,6 +80,7 @@ struct GBCore {
|
|||
const struct Configuration* overrides;
|
||||
struct mDebuggerPlatform* debuggerPlatform;
|
||||
struct mCheatDevice* cheatDevice;
|
||||
struct mCoreMemoryBlock memoryBlocks[8];
|
||||
};
|
||||
|
||||
static bool _GBCoreInit(struct mCore* core) {
|
||||
|
@ -101,6 +102,7 @@ static bool _GBCoreInit(struct mCore* core) {
|
|||
#ifndef MINIMAL_CORE
|
||||
gbcore->logContext = NULL;
|
||||
#endif
|
||||
memcpy(gbcore->memoryBlocks, _GBMemoryBlocks, sizeof(_GBMemoryBlocks));
|
||||
|
||||
GBCreate(gb);
|
||||
memset(gbcore->components, 0, sizeof(gbcore->components));
|
||||
|
@ -571,6 +573,26 @@ static void _GBCoreReset(struct mCore* core) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (gb->model < GB_MODEL_CGB) {
|
||||
memcpy(gbcore->memoryBlocks, _GBMemoryBlocks, sizeof(_GBMemoryBlocks));
|
||||
} else {
|
||||
memcpy(gbcore->memoryBlocks, _GBCMemoryBlocks, sizeof(_GBCMemoryBlocks));
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(gbcore->memoryBlocks) / sizeof(*gbcore->memoryBlocks); ++i) {
|
||||
if (gbcore->memoryBlocks[i].id == GB_REGION_CART_BANK0) {
|
||||
gbcore->memoryBlocks[i].maxSegment = gb->memory.romSize / GB_SIZE_CART_BANK0;
|
||||
} else if (gbcore->memoryBlocks[i].id == GB_REGION_EXTERNAL_RAM) {
|
||||
gbcore->memoryBlocks[i].maxSegment = gb->sramSize / GB_SIZE_EXTERNAL_RAM;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (gbcore->memoryBlocks[i].maxSegment) {
|
||||
--gbcore->memoryBlocks[i].maxSegment;
|
||||
}
|
||||
}
|
||||
|
||||
SM83Reset(core->cpu);
|
||||
|
||||
if (core->opts.skipBios) {
|
||||
|
@ -755,20 +777,9 @@ static void _GBCoreRawWrite32(struct mCore* core, uint32_t address, int segment,
|
|||
}
|
||||
|
||||
size_t _GBListMemoryBlocks(const struct mCore* core, const struct mCoreMemoryBlock** blocks) {
|
||||
const struct GB* gb = core->board;
|
||||
switch (gb->model) {
|
||||
case GB_MODEL_DMG:
|
||||
case GB_MODEL_MGB:
|
||||
case GB_MODEL_SGB:
|
||||
case GB_MODEL_SGB2:
|
||||
default:
|
||||
*blocks = _GBMemoryBlocks;
|
||||
return sizeof(_GBMemoryBlocks) / sizeof(*_GBMemoryBlocks);
|
||||
case GB_MODEL_CGB:
|
||||
case GB_MODEL_AGB:
|
||||
*blocks = _GBCMemoryBlocks;
|
||||
return sizeof(_GBCMemoryBlocks) / sizeof(*_GBCMemoryBlocks);
|
||||
}
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
*blocks = gbcore->memoryBlocks;
|
||||
return sizeof(gbcore->memoryBlocks) / sizeof(*gbcore->memoryBlocks);
|
||||
}
|
||||
|
||||
void* _GBGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
||||
|
|
|
@ -707,15 +707,16 @@ void GBProcessEvents(struct SM83Core* cpu) {
|
|||
int32_t nextEvent;
|
||||
|
||||
cpu->cycles = 0;
|
||||
#ifdef USE_DEBUGGERS
|
||||
gb->timing.globalCycles += cycles;
|
||||
#endif
|
||||
cpu->nextEvent = INT_MAX;
|
||||
|
||||
nextEvent = cycles;
|
||||
do {
|
||||
#ifdef USE_DEBUGGERS
|
||||
gb->timing.globalCycles += nextEvent;
|
||||
#endif
|
||||
nextEvent = mTimingTick(&gb->timing, nextEvent);
|
||||
} while (gb->cpuBlocked && !gb->earlyExit);
|
||||
} while (gb->cpuBlocked);
|
||||
// This loop cannot early exit until the SM83 run loop properly handles mid-M-cycle-exits
|
||||
cpu->nextEvent = nextEvent;
|
||||
|
||||
if (cpu->halted) {
|
||||
|
|
|
@ -595,10 +595,10 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
memset(&softwareRenderer->row[startX], 0, (endX - startX) * sizeof(softwareRenderer->row[0]));
|
||||
}
|
||||
|
||||
if (startX == 0) {
|
||||
_cleanOAM(softwareRenderer, y);
|
||||
}
|
||||
if (GBRegisterLCDCIsObjEnable(softwareRenderer->lcdc) && !softwareRenderer->d.disableOBJ) {
|
||||
if (startX == 0) {
|
||||
_cleanOAM(softwareRenderer, y);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < softwareRenderer->objMax; ++i) {
|
||||
GBVideoSoftwareRendererDrawObj(softwareRenderer, &softwareRenderer->obj[i], startX, endX, y);
|
||||
|
|
|
@ -288,7 +288,7 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
|
|||
int32_t cycles = cpu->cycles;
|
||||
cpu->cycles = 0;
|
||||
#ifdef USE_DEBUGGERS
|
||||
gba->timing.globalCycles += cycles;
|
||||
gba->timing.globalCycles += cycles < nextEvent ? nextEvent : cycles;
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
if (cycles < 0) {
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
#include "LogView.h"
|
||||
|
||||
#include "LogController.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include <QTextBlock>
|
||||
#include <QTextCursor>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
LogView::LogView(LogController* log, QWidget* parent)
|
||||
LogView::LogView(LogController* log, Window* window, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
@ -38,6 +39,9 @@ LogView::LogView(LogController* log, QWidget* parent)
|
|||
setLevel(mLOG_GAME_ERROR, set);
|
||||
});
|
||||
connect(m_ui.clear, &QAbstractButton::clicked, this, &LogView::clear);
|
||||
connect(m_ui.advanced, &QAbstractButton::clicked, this, [window]() {
|
||||
window->openSettingsWindow(SettingsView::Page::LOGGING);
|
||||
});
|
||||
connect(m_ui.maxLines, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
this, &LogView::setMaxLines);
|
||||
m_ui.maxLines->setValue(DEFAULT_LINE_LIMIT);
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
namespace QGBA {
|
||||
|
||||
class LogController;
|
||||
class Window;
|
||||
|
||||
class LogView : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogView(LogController* log, QWidget* parent = nullptr);
|
||||
LogView(LogController* log, Window* window, QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void levelsEnabled(int levels);
|
||||
|
|
|
@ -102,6 +102,13 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="advanced">
|
||||
<property name="text">
|
||||
<string>Advanced settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, LogController* logController, QWidget* parent)
|
||||
SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent)
|
||||
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||
, m_controller(controller)
|
||||
, m_input(inputController)
|
||||
|
@ -32,7 +32,17 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_pageIndex[Page::AV] = 0;
|
||||
m_pageIndex[Page::INTERFACE] = 1;
|
||||
m_pageIndex[Page::EMULATION] = 2;
|
||||
m_pageIndex[Page::ENHANCEMENTS] = 3;
|
||||
m_pageIndex[Page::BIOS] = 4;
|
||||
m_pageIndex[Page::PATHS] = 5;
|
||||
m_pageIndex[Page::LOGGING] = 6;
|
||||
|
||||
#ifdef M_CORE_GB
|
||||
m_pageIndex[Page::GB] = 7;
|
||||
|
||||
for (auto model : GameBoy::modelList()) {
|
||||
m_ui.gbModel->addItem(GameBoy::modelName(model), model);
|
||||
m_ui.sgbModel->addItem(GameBoy::modelName(model), model);
|
||||
|
@ -75,11 +85,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
});
|
||||
connect(m_ui.savegameBrowse, &QAbstractButton::pressed, [this] () {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory");
|
||||
if (!path.isNull()) {
|
||||
m_ui.savegameSameDir->setChecked(false);
|
||||
m_ui.savegamePath->setText(path);
|
||||
}
|
||||
selectPath(m_ui.savegamePath, m_ui.savegameSameDir);
|
||||
});
|
||||
|
||||
if (m_ui.savestatePath->text().isEmpty()) {
|
||||
|
@ -91,11 +97,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
});
|
||||
connect(m_ui.savestateBrowse, &QAbstractButton::pressed, [this] () {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory");
|
||||
if (!path.isNull()) {
|
||||
m_ui.savestateSameDir->setChecked(false);
|
||||
m_ui.savestatePath->setText(path);
|
||||
}
|
||||
selectPath(m_ui.savestatePath, m_ui.savestateSameDir);
|
||||
});
|
||||
|
||||
if (m_ui.screenshotPath->text().isEmpty()) {
|
||||
|
@ -107,11 +109,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
});
|
||||
connect(m_ui.screenshotBrowse, &QAbstractButton::pressed, [this] () {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory");
|
||||
if (!path.isNull()) {
|
||||
m_ui.screenshotSameDir->setChecked(false);
|
||||
m_ui.screenshotPath->setText(path);
|
||||
}
|
||||
selectPath(m_ui.screenshotPath, m_ui.screenshotSameDir);
|
||||
});
|
||||
|
||||
if (m_ui.patchPath->text().isEmpty()) {
|
||||
|
@ -123,11 +121,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
});
|
||||
connect(m_ui.patchBrowse, &QAbstractButton::pressed, [this] () {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory");
|
||||
if (!path.isNull()) {
|
||||
m_ui.patchSameDir->setChecked(false);
|
||||
m_ui.patchPath->setText(path);
|
||||
}
|
||||
selectPath(m_ui.patchPath, m_ui.patchSameDir);
|
||||
});
|
||||
|
||||
if (m_ui.cheatsPath->text().isEmpty()) {
|
||||
|
@ -139,11 +133,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
}
|
||||
});
|
||||
connect(m_ui.cheatsBrowse, &QAbstractButton::pressed, [this] () {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, "Select directory");
|
||||
if (!path.isNull()) {
|
||||
m_ui.cheatsSameDir->setChecked(false);
|
||||
m_ui.cheatsPath->setText(path);
|
||||
}
|
||||
selectPath(m_ui.cheatsPath, m_ui.cheatsSameDir);
|
||||
});
|
||||
connect(m_ui.clearCache, &QAbstractButton::pressed, this, &SettingsView::libraryCleared);
|
||||
|
||||
|
@ -325,6 +315,11 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC
|
|||
m_ui.logFile->setText(path);
|
||||
}
|
||||
});
|
||||
|
||||
ShortcutView* shortcutView = new ShortcutView();
|
||||
shortcutView->setController(shortcutController);
|
||||
shortcutView->setInputController(inputController);
|
||||
addPage(tr("Shortcuts"), shortcutView, Page::SHORTCUTS);
|
||||
}
|
||||
|
||||
SettingsView::~SettingsView() {
|
||||
|
@ -352,10 +347,33 @@ void SettingsView::setShaderSelector(ShaderSelector* shaderSelector) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SettingsView::selectPage(SettingsView::Page page) {
|
||||
m_ui.tabs->setCurrentRow(m_pageIndex[page]);
|
||||
}
|
||||
|
||||
QString SettingsView::makePortablePath(const QString& path) {
|
||||
if (m_controller->isPortable()) {
|
||||
QDir configDir(m_controller->configDir());
|
||||
QFileInfo pathInfo(path);
|
||||
if (pathInfo.canonicalPath() == configDir.canonicalPath()) {
|
||||
return configDir.relativeFilePath(pathInfo.canonicalFilePath());
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void SettingsView::selectBios(QLineEdit* bios) {
|
||||
QString filename = GBAApp::app()->getOpenFileName(this, tr("Select BIOS"));
|
||||
if (!filename.isEmpty()) {
|
||||
bios->setText(filename);
|
||||
bios->setText(makePortablePath(filename));
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsView::selectPath(QLineEdit* field, QCheckBox* sameDir) {
|
||||
QString path = GBAApp::app()->getOpenDirectoryName(this, tr("Select directory"));
|
||||
if (!path.isNull()) {
|
||||
sameDir->setChecked(false);
|
||||
field->setText(makePortablePath(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,6 +723,12 @@ void SettingsView::reloadConfig() {
|
|||
loadSetting("videoScale", m_ui.videoScale, 1);
|
||||
}
|
||||
|
||||
void SettingsView::addPage(const QString& name, QWidget* view, Page index) {
|
||||
m_pageIndex[index] = m_ui.tabs->count();
|
||||
m_ui.tabs->addItem(name);
|
||||
m_ui.stackedWidget->addWidget(view);
|
||||
}
|
||||
|
||||
void SettingsView::saveSetting(const char* key, const QAbstractButton* field) {
|
||||
m_controller->setOption(key, field->isChecked());
|
||||
m_controller->updateOption(key);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMap>
|
||||
|
||||
#include "ColorPicker.h"
|
||||
#include "LogConfigModel.h"
|
||||
|
@ -24,12 +25,28 @@ class ConfigController;
|
|||
class InputController;
|
||||
class InputIndex;
|
||||
class ShaderSelector;
|
||||
class ShortcutController;
|
||||
|
||||
class SettingsView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsView(ConfigController* controller, InputController* inputController, LogController* logController, QWidget* parent = nullptr);
|
||||
enum class Page {
|
||||
AV,
|
||||
INTERFACE,
|
||||
EMULATION,
|
||||
ENHANCEMENTS,
|
||||
BIOS,
|
||||
PATHS,
|
||||
LOGGING,
|
||||
GB,
|
||||
KEYBOARD,
|
||||
CONTROLLERS,
|
||||
SHORTCUTS,
|
||||
SHADERS,
|
||||
};
|
||||
|
||||
SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent = nullptr);
|
||||
~SettingsView();
|
||||
|
||||
void setShaderSelector(ShaderSelector* shaderSelector);
|
||||
|
@ -45,8 +62,12 @@ signals:
|
|||
void languageChanged();
|
||||
void libraryCleared();
|
||||
|
||||
public slots:
|
||||
void selectPage(Page);
|
||||
|
||||
private slots:
|
||||
void selectBios(QLineEdit*);
|
||||
void selectPath(QLineEdit*, QCheckBox*);
|
||||
void updateConfig();
|
||||
void reloadConfig();
|
||||
|
||||
|
@ -63,6 +84,12 @@ private:
|
|||
ColorPicker m_colorPickers[12];
|
||||
#endif
|
||||
|
||||
QMap<Page, int> m_pageIndex;
|
||||
|
||||
QString makePortablePath(const QString& path);
|
||||
|
||||
void addPage(const QString& name, QWidget* view, Page index);
|
||||
|
||||
void saveSetting(const char* key, const QAbstractButton*);
|
||||
void saveSetting(const char* key, const QComboBox*);
|
||||
void saveSetting(const char* key, const QDoubleSpinBox*);
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "ReportView.h"
|
||||
#include "ROMInfo.h"
|
||||
#include "SensorView.h"
|
||||
#include "SettingsView.h"
|
||||
#include "ShaderSelector.h"
|
||||
#include "ShortcutController.h"
|
||||
#include "TileView.h"
|
||||
|
@ -104,7 +103,7 @@ using namespace QGBA;
|
|||
Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
, m_manager(manager)
|
||||
, m_logView(new LogView(&m_log))
|
||||
, m_logView(new LogView(&m_log, this))
|
||||
, m_screenWidget(new WindowBackground())
|
||||
, m_config(config)
|
||||
, m_inputController(playerId, this)
|
||||
|
@ -501,7 +500,11 @@ void Window::exportSharkport() {
|
|||
}
|
||||
|
||||
void Window::openSettingsWindow() {
|
||||
SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, &m_log);
|
||||
openSettingsWindow(SettingsView::Page::AV);
|
||||
}
|
||||
|
||||
void Window::openSettingsWindow(SettingsView::Page page) {
|
||||
SettingsView* settingsWindow = new SettingsView(m_config, &m_inputController, m_shortcutController, &m_log);
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
if (m_display->supportsShaders()) {
|
||||
settingsWindow->setShaderSelector(m_shaderView.get());
|
||||
|
@ -518,6 +521,7 @@ void Window::openSettingsWindow() {
|
|||
connect(settingsWindow, &SettingsView::libraryCleared, m_libraryView, &LibraryController::clear);
|
||||
#endif
|
||||
openView(settingsWindow);
|
||||
settingsWindow->selectPage(page);
|
||||
}
|
||||
|
||||
void Window::startVideoLog() {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "InputController.h"
|
||||
#include "LoadSaveState.h"
|
||||
#include "LogController.h"
|
||||
#include "SettingsView.h"
|
||||
|
||||
struct mArguments;
|
||||
|
||||
namespace QGBA {
|
||||
|
@ -95,6 +97,7 @@ public slots:
|
|||
void exportSharkport();
|
||||
|
||||
void openSettingsWindow();
|
||||
void openSettingsWindow(SettingsView::Page);
|
||||
|
||||
void startVideoLog();
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -915,7 +915,7 @@ void _gameUnloaded(struct mGUIRunner* runner) {
|
|||
|
||||
void _gameLoaded(struct mGUIRunner* runner) {
|
||||
reconfigureScreen(runner);
|
||||
if (runner->core->platform(runner->core) == PLATFORM_GBA && ((struct GBA*) runner->core->board)->memory.hw.devices & HW_GYRO) {
|
||||
if (runner->core->platform(runner->core) == mPLATFORM_GBA && ((struct GBA*) runner->core->board)->memory.hw.devices & HW_GYRO) {
|
||||
int i;
|
||||
for (i = 0; i < 6; ++i) {
|
||||
u32 result = WPAD_SetMotionPlus(0, 1);
|
||||
|
|
Loading…
Reference in New Issue