Merge branch 'master' into port/psp2

This commit is contained in:
Jeffrey Pfau 2015-08-17 01:39:53 -07:00
commit 9f36284fd1
19 changed files with 135 additions and 86 deletions

119
CHANGES
View File

@ -1,4 +1,4 @@
0.3.0: (Future) 0.3.0: (2015-08-16)
Features: Features:
- Ability to hide individual background layers, or OBJs - Ability to hide individual background layers, or OBJs
- Ability to mute individual audio channels - Ability to mute individual audio channels
@ -34,95 +34,98 @@ Features:
- Configurable audio output sample rate - Configurable audio output sample rate
Bugfixes: Bugfixes:
- ARM7: Fix SWI and IRQ timings - ARM7: Fix SWI and IRQ timings
- GBA Audio: Force audio FIFOs to 32-bit
- GBA Memory: Improve Thumb open bus behavior
- VFS: Fix resource leaks if some allocations fail
- Video: Fix an issue with very long filenames
- GBA Video: Blended sprites should never have other effects applied
- GBA: Fix crash if a 512kb flash save is loaded when a game has a 1Mb flash override
- Qt: Better cleanup when a game crashes
- Qt: Fix open ROM dialog filtering for archive formats
- ARM7: Fix Thumb MUL timing - ARM7: Fix Thumb MUL timing
- Qt: Cap the maximum number of multiplayer windows - ARM7: Fix timing of multiplies to use N cycles
- Qt: Fix maximum year in sensor override - ARM7: ARMHotplugDetach should call deinit
- Debugger: Fix use-after-free in breakpoint clearing code
- GBA: Fix crash if a 512kb flash save is loaded when a game has a 1Mb flash override
- GBA: Cap audio FIFO read size during deserialization - GBA: Cap audio FIFO read size during deserialization
- GBA: Check for corrupted savestates when loading - GBA: Check for corrupted savestates when loading
- GBA: Check for improperly sized savestates when loading - GBA: Check for improperly sized savestates when loading
- GBA: Check for savestates made from differently sized ROMs - GBA: Check for savestates made from differently sized ROMs
- GBA Video: Fix out-of-bounds tiles in mosaic
- GBA Memory: Fix potential DMA issue when loading a savestate
- GBA Audio: Fix audio pitch changing when adjusting buffer size
- SDL: Fix SDL build when OpenGL is missing
- ARM7: Fix timing of multiplies to use N cycles
- GBA: Fix calls to endian-independent loadstores - GBA: Fix calls to endian-independent loadstores
- GBA Video: Fix windows not affecting sprites
- VFS: Fix line-reading to return proper values
- GBA Memory: Fix load/store multiple video memory waitstates
- GBA: Fix timing of reading from timer registers - GBA: Fix timing of reading from timer registers
- Util: Allow loading IPS patches that grow the ROM - GBA: Ensure cycles never go negative
- GBA Audio: Force audio FIFOs to 32-bit
- GBA Audio: Fix audio pitch changing when adjusting buffer size
- GBA Audio: Fix sample order in audio channel 3 - GBA Audio: Fix sample order in audio channel 3
- GBA Audio: Fix 8-bit writes to audio channel 3 frequency - GBA Audio: Fix 8-bit writes to audio channel 3 frequency
- ARM7: ARMHotplugDetach should call deinit - GBA Cheats: Fix Pro Action Replay and GameShark issues when used together
- GBA Memory: Improve Thumb open bus behavior
- GBA Memory: Fix potential DMA issue when loading a savestate
- GBA Memory: Fix load/store multiple video memory waitstates
- GBA SIO: Fix reseting when there are SIO devices attached
- GBA Video: Blended sprites should never have other effects applied
- GBA Video: Fix out-of-bounds tiles in mosaic
- GBA Video: Fix windows not affecting sprites
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
- GBA Video: Fix timing on first scanline
- Qt: Better cleanup when a game crashes
- Qt: Fix open ROM dialog filtering for archive formats
- Qt: Cap the maximum number of multiplayer windows
- Qt: Fix maximum year in sensor override
- Qt: Fix window being too tall after exiting fullscreen - Qt: Fix window being too tall after exiting fullscreen
- Qt: Fix a missing va_end call in the log handler lambda within the GameController constructor - Qt: Fix a missing va_end call in the log handler lambda within the GameController constructor
- GBA Cheats: Fix Pro Action Replay and GameShark issues when used together
- Qt: Fix analog buttons not getting unmapped - Qt: Fix analog buttons not getting unmapped
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
- Qt: Fix passing command line options - Qt: Fix passing command line options
- Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls - Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
- GBA Video: Fix timing on first scanline - SDL: Fix SDL build when OpenGL is missing
- GBA: Ensure cycles never go negative - Util: Allow loading IPS patches that grow the ROM
- VFS: Fix resource leaks if some allocations fail
- VFS: Fix line-reading to return proper values
- Video: Fix an issue with very long filenames
- Util: Fix formatting of floats
Misc: Misc:
- Qt: Handle saving input settings better
- Debugger: Free watchpoints in addition to breakpoints
- Qt: Move GL frame drawing back onto its own thread
- GBA: Add status log level
- GBA Thread: Add functionality for running callbacks on the GBA thread
- Qt: Fast forward (held) option moved from Other to Emulation menu
- All: Add --help flag for command line programs - All: Add --help flag for command line programs
- Qt: Show version info in window title
- All: Fix sanitize-deb script to set file permissions properly if run as (fake)root - All: Fix sanitize-deb script to set file permissions properly if run as (fake)root
- GBA SIO: Add a dummy driver for Normal mode
- GBA: GBARewind now returns how many states it has rewound
- All: Enable static linking for Windows - All: Enable static linking for Windows
- All: Enable static linking for OS X - All: Enable static linking for OS X
- All: Threads are now named
- All: Proper handling of Unicode file paths
- ARM7: Add emulation for Undefined CPU mode
- ARM7: Reduce the size of the Thumb instruction table
- GBA: Add status log level
- GBA: GBARewind now returns how many states it has rewound
- GBA: SIO logging layer
- GBA BIOS: Stub out SoundBias
- GBA: More accurate cycle estimation for ROM prefetch and flash save chips
- GBA: Don't include GBACLIDebugger struct unless needed
- GBA: Savedata is now synced shortly after data finishes being written
- GBA: Process multiple timer events at once, if necessary
- GBA Audio: Implement audio reset for channels A/B
- GBA Audio: Process multiple audio events at once, if necessary
- GBA Hardware: Backport generic RTC source into core
- GBA Input: Allow axes and buttons to be mapped to the same key
- GBA Memory: Run multiple DMAs in a tight loop if they all occur before present
- GBA SIO: Add a dummy driver for Normal mode
- GBA Thread: Add functionality for running callbacks on the GBA thread
- GBA Thread: Split GBASync into a separate file
- GBA Video: Refactor software renderer into separate files
- GBA Video: Slightly optimize mode 0 mosaic rendering
- Debugger: Free watchpoints in addition to breakpoints
- Qt: Handle saving input settings better
- Qt: Move GL frame drawing back onto its own thread
- Qt: Fast forward (held) option moved from Other to Emulation menu
- Qt: Show version info in window title
- Qt: Migrate multiplayer window handling into GBAApp - Qt: Migrate multiplayer window handling into GBAApp
- Qt: Unified file opening and saving with last location - Qt: Unified file opening and saving with last location
- Qt: Fix windows being resizable when they shouldn't have been - Qt: Fix windows being resizable when they shouldn't have been
- Qt: Only hide cursor in full screen - Qt: Only hide cursor in full screen
- Perf: Ability to load savestates immediately on launch
- Qt: Replace pause-after-frame mutex with an atomic - Qt: Replace pause-after-frame mutex with an atomic
- Util: Allow disabling the threading code entirely
- GBA: SIO logging layer
- Qt: Add application icon and XDG desktop files - Qt: Add application icon and XDG desktop files
- GBA Thread: Split GBASync into a separate file
- SDL: Properly check for initialization
- SDL: Clean up initialization functions
- All: Threads are now named
- Qt: Rename "Fullscreen" to "Toggle fullscreen" - Qt: Rename "Fullscreen" to "Toggle fullscreen"
- Qt: Don't save window size when entering fullscreen - Qt: Don't save window size when entering fullscreen
- Qt: Make the default fullscreen binding for Windows be Alt-Enter - Qt: Make the default fullscreen binding for Windows be Alt-Enter
- GBA Video: Refactor software renderer into separate files
- ARM7: Add emulation for Undefined CPU mode
- GBA: More accurate cycle estimation for ROM prefetch and flash save chips
- ARM7: Reduce the size of the Thumb instruction table
- GBA: Don't include GBACLIDebugger struct unless needed
- SDL: Clean up GL context
- GBA Audio: Implement audio reset for channels A/B
- GBA Hardware: Backport generic RTC source into core
- All: Proper handling of Unicode file paths
- GBA Video: Slightly optimize mode 0 mosaic rendering
- VFS: Add sync method to force syncing with backing
- GBA: Savedata is now synced shortly after data finishes being written
- GBA Input: Allow axes and buttons to be mapped to the same key
- GBA BIOS: Stub out SoundBias
- Qt: Gamepads can now have both buttons and analog axes mapped to the same key - Qt: Gamepads can now have both buttons and analog axes mapped to the same key
- Qt: Increase usability of key mapper - Qt: Increase usability of key mapper
- Qt: Show checkmark for window sizes - Qt: Show checkmark for window sizes
- Qt: Set window path to loaded ROM - Qt: Set window path to loaded ROM
- GBA Memory: Run multiple DMAs in a tight loop if they all occur before present - Perf: Ability to load savestates immediately on launch
- GBA Audio: Process multiple audio events at once, if necessary - SDL: Properly check for initialization
- GBA: Process multiple timer events at once, if necessary - SDL: Clean up initialization functions
- SDL: Clean up GL context
- Util: Allow disabling the threading code entirely
- VFS: Add sync method to force syncing with backing
0.2.1: (2015-05-13) 0.2.1: (2015-05-13)
Bugfixes: Bugfixes:

View File

@ -31,7 +31,7 @@
DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
info->op1.reg = opcode & 0x0007; \ info->op1.reg = opcode & 0x0007; \
info->memory.baseReg = (opcode >> 3) & 0x0007; \ info->memory.baseReg = (opcode >> 3) & 0x0007; \
info->memory.offset.immediate = ((opcode >> 6) & 0x0007) * WIDTH; \ info->memory.offset.immediate = ((opcode >> 6) & 0x001F) * WIDTH; \
info->memory.width = (enum ARMMemoryAccessType) WIDTH; \ info->memory.width = (enum ARMMemoryAccessType) WIDTH; \
info->operandFormat = ARM_OPERAND_REGISTER_1 | \ info->operandFormat = ARM_OPERAND_REGISTER_1 | \
ARM_OPERAND_AFFECTED_1 | \ ARM_OPERAND_AFFECTED_1 | \

View File

@ -155,6 +155,7 @@ void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address)
if (breakpoint->address == address) { if (breakpoint->address == address) {
*previous = *next; *previous = *next;
free(breakpoint); free(breakpoint);
continue;
} }
previous = next; previous = next;
} }
@ -179,6 +180,7 @@ void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address)
if (watchpoint->address == address) { if (watchpoint->address == address) {
*previous = *next; *previous = *next;
free(watchpoint); free(watchpoint);
continue;
} }
previous = next; previous = next;
} }

View File

@ -163,8 +163,7 @@ void GBAReset(struct ARMCore* cpu) {
GBAAudioReset(&gba->audio); GBAAudioReset(&gba->audio);
GBAIOInit(gba); GBAIOInit(gba);
GBASIODeinit(&gba->sio); GBASIOReset(&gba->sio);
GBASIOInit(&gba->sio);
gba->timersEnabled = 0; gba->timersEnabled = 0;
memset(gba->timers, 0, sizeof(gba->timers)); memset(gba->timers, 0, sizeof(gba->timers));

View File

@ -59,10 +59,14 @@ void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
} }
void GBAHardwareClear(struct GBACartridgeHardware* hw) { void GBAHardwareClear(struct GBACartridgeHardware* hw) {
hw->devices = HW_NONE; hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
hw->direction = GPIO_WRITE_ONLY; hw->direction = GPIO_WRITE_ONLY;
hw->pinState = 0; hw->pinState = 0;
hw->direction = 0; hw->direction = 0;
if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
}
} }
void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {

View File

@ -446,8 +446,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
} else { } else {
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
LOAD_BAD; LOAD_BAD;
uint32_t v2 = value; value = (value >> ((address & 2) * 8)) & 0xFFFF;
LOAD_16(value, address & 2, &v2);
} }
break; break;
case REGION_WORKING_RAM: case REGION_WORKING_RAM:
@ -506,8 +505,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
LOAD_BAD; LOAD_BAD;
uint32_t v2 = value; value = (value >> ((address & 2) * 8)) & 0xFFFF;
LOAD_16(value, address & 2, &v2);
break; break;
} }

View File

@ -48,14 +48,11 @@ static void _switchMode(struct GBASIO* sio) {
} }
void GBASIOInit(struct GBASIO* sio) { void GBASIOInit(struct GBASIO* sio) {
sio->rcnt = RCNT_INITIAL;
sio->siocnt = 0;
sio->mode = -1;
sio->activeDriver = 0;
sio->drivers.normal = 0; sio->drivers.normal = 0;
sio->drivers.multiplayer = 0; sio->drivers.multiplayer = 0;
sio->drivers.joybus = 0; sio->drivers.joybus = 0;
_switchMode(sio); sio->activeDriver = 0;
GBASIOReset(sio);
} }
void GBASIODeinit(struct GBASIO* sio) { void GBASIODeinit(struct GBASIO* sio) {
@ -68,6 +65,17 @@ void GBASIODeinit(struct GBASIO* sio) {
if (sio->drivers.joybus && sio->drivers.joybus->deinit) { if (sio->drivers.joybus && sio->drivers.joybus->deinit) {
sio->drivers.joybus->deinit(sio->drivers.joybus); sio->drivers.joybus->deinit(sio->drivers.joybus);
} }
if (sio->drivers.normal && sio->drivers.normal->deinit) {
sio->drivers.normal->deinit(sio->drivers.normal);
}
}
void GBASIOReset(struct GBASIO* sio) {
GBASIODeinit(sio);
sio->rcnt = RCNT_INITIAL;
sio->siocnt = 0;
sio->mode = -1;
_switchMode(sio);
} }
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) { void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) {

View File

@ -65,6 +65,7 @@ struct GBASIO {
void GBASIOInit(struct GBASIO* sio); void GBASIOInit(struct GBASIO* sio);
void GBASIODeinit(struct GBASIO* sio); void GBASIODeinit(struct GBASIO* sio);
void GBASIOReset(struct GBASIO* sio);
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers); void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers);
void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode); void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode);

View File

@ -225,7 +225,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
GBARRInitPlay(&gba); GBARRInitPlay(&gba);
} }
if (threadContext->skipBios) { if (threadContext->skipBios && gba.memory.rom) {
GBASkipBIOS(&cpu); GBASkipBIOS(&cpu);
} }
@ -305,7 +305,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
MutexUnlock(&threadContext->stateMutex); MutexUnlock(&threadContext->stateMutex);
if (resetScheduled) { if (resetScheduled) {
ARMReset(&cpu); ARMReset(&cpu);
if (threadContext->skipBios) { if (threadContext->skipBios && gba.memory.rom) {
GBASkipBIOS(&cpu); GBASkipBIOS(&cpu);
} }
} }

View File

@ -21,6 +21,11 @@ AboutScreen::AboutScreen(QWidget* parent)
logo.setDevicePixelRatio(devicePixelRatio()); logo.setDevicePixelRatio(devicePixelRatio());
m_ui.logo->setPixmap(logo); m_ui.logo->setPixmap(logo);
QLatin1String tree(gitBranch);
if (tree == QLatin1String("(unknown)")) {
tree = QLatin1String(projectVersion);
}
m_ui.projectName->setText(QLatin1String(projectName)); m_ui.projectName->setText(QLatin1String(projectName));
m_ui.projectVersion->setText(QLatin1String(projectVersion)); m_ui.projectVersion->setText(QLatin1String(projectVersion));
QString gitInfo = m_ui.gitInfo->text(); QString gitInfo = m_ui.gitInfo->text();
@ -31,6 +36,6 @@ AboutScreen::AboutScreen(QWidget* parent)
description.replace("{projectName}", QLatin1String(projectName)); description.replace("{projectName}", QLatin1String(projectName));
m_ui.description->setText(description); m_ui.description->setText(description);
QString extraLinks = m_ui.extraLinks->text(); QString extraLinks = m_ui.extraLinks->text();
extraLinks.replace("{gitBranch}", QLatin1String(gitBranch)); extraLinks.replace("{gitBranch}", tree);
m_ui.extraLinks->setText(extraLinks); m_ui.extraLinks->setText(extraLinks);
} }

View File

@ -108,6 +108,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.videoSync = GameController::VIDEO_SYNC; m_opts.videoSync = GameController::VIDEO_SYNC;
m_opts.fpsTarget = 60; m_opts.fpsTarget = 60;
m_opts.audioBuffers = 1536; m_opts.audioBuffers = 1536;
m_opts.sampleRate = 44100;
m_opts.volume = GBA_AUDIO_VOLUME_MAX; m_opts.volume = GBA_AUDIO_VOLUME_MAX;
m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS; m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS;
m_opts.rewindEnable = false; m_opts.rewindEnable = false;

View File

@ -57,7 +57,9 @@ GBAApp::GBAApp(int& argc, char* argv[])
return; return;
} }
if (!m_configController.getQtOption("audioDriver").isNull()) {
AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt())); AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
}
Window* w = new Window(&m_configController); Window* w = new Window(&m_configController);
connect(w, &Window::destroyed, [this]() { connect(w, &Window::destroyed, [this]() {
m_windows[0] = nullptr; m_windows[0] = nullptr;

View File

@ -599,6 +599,9 @@ void GameController::setAudioBufferSamples(int samples) {
} }
void GameController::setAudioSampleRate(unsigned rate) { void GameController::setAudioSampleRate(unsigned rate) {
if (!rate) {
return;
}
if (m_audioProcessor) { if (m_audioProcessor) {
threadInterrupt(); threadInterrupt();
redoSamples(m_audioProcessor->getBufferSamples()); redoSamples(m_audioProcessor->getBufferSamples());

View File

@ -61,6 +61,7 @@ SensorView::SensorView(GameController* controller, InputController* input, QWidg
connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) { connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
m_input->setGyroSensitivity(value * 1e8f); m_input->setGyroSensitivity(value * 1e8f);
}); });
m_input->stealFocus(this);
} }
void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) { void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
@ -68,15 +69,26 @@ void SensorView::jiggerer(QAbstractButton* button, void (InputController::*sette
if (!checked) { if (!checked) {
m_jiggered = nullptr; m_jiggered = nullptr;
} else { } else {
button->setFocus();
m_jiggered = [this, button, setter](int axis) { m_jiggered = [this, button, setter](int axis) {
(m_input->*setter)(axis); (m_input->*setter)(axis);
button->setChecked(false); button->setChecked(false);
button->clearFocus();
}; };
} }
}); });
button->installEventFilter(this); button->installEventFilter(this);
} }
bool SensorView::event(QEvent* event) {
if (event->type() == QEvent::WindowActivate) {
m_input->stealFocus(this);
} else if (event->type() == QEvent::WindowDeactivate) {
m_input->releaseFocus(this);
}
return QWidget::event(event);
}
bool SensorView::eventFilter(QObject*, QEvent* event) { bool SensorView::eventFilter(QObject*, QEvent* event) {
if (event->type() == GamepadAxisEvent::Type()) { if (event->type() == GamepadAxisEvent::Type()) {
GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event); GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);

View File

@ -30,6 +30,7 @@ public:
protected: protected:
bool eventFilter(QObject*, QEvent* event) override; bool eventFilter(QObject*, QEvent* event) override;
bool event(QEvent* event);
private slots: private slots:
void updateSensors(); void updateSensors();

View File

@ -165,7 +165,7 @@ void SettingsView::saveSetting(const char* key, const QComboBox* field) {
} }
void SettingsView::saveSetting(const char* key, const QDoubleSpinBox* field) { void SettingsView::saveSetting(const char* key, const QDoubleSpinBox* field) {
saveSetting(key, field->cleanText()); saveSetting(key, field->value());
} }
void SettingsView::saveSetting(const char* key, const QLineEdit* field) { void SettingsView::saveSetting(const char* key, const QLineEdit* field) {
@ -173,14 +173,14 @@ void SettingsView::saveSetting(const char* key, const QLineEdit* field) {
} }
void SettingsView::saveSetting(const char* key, const QSlider* field) { void SettingsView::saveSetting(const char* key, const QSlider* field) {
saveSetting(key, QString::number(field->value())); saveSetting(key, field->value());
} }
void SettingsView::saveSetting(const char* key, const QSpinBox* field) { void SettingsView::saveSetting(const char* key, const QSpinBox* field) {
saveSetting(key, field->cleanText()); saveSetting(key, field->value());
} }
void SettingsView::saveSetting(const char* key, const QString& field) { void SettingsView::saveSetting(const char* key, const QVariant& field) {
m_controller->setOption(key, field); m_controller->setOption(key, field);
m_controller->updateOption(key); m_controller->updateOption(key);
} }

View File

@ -40,7 +40,7 @@ private:
void saveSetting(const char* key, const QLineEdit*); void saveSetting(const char* key, const QLineEdit*);
void saveSetting(const char* key, const QSlider*); void saveSetting(const char* key, const QSlider*);
void saveSetting(const char* key, const QSpinBox*); void saveSetting(const char* key, const QSpinBox*);
void saveSetting(const char* key, const QString&); void saveSetting(const char* key, const QVariant&);
void loadSetting(const char* key, QAbstractButton*); void loadSetting(const char* key, QAbstractButton*);
void loadSetting(const char* key, QComboBox*); void loadSetting(const char* key, QComboBox*);

View File

@ -9,20 +9,20 @@
int ftostr_l(char* restrict str, size_t size, float f, locale_t locale) { int ftostr_l(char* restrict str, size_t size, float f, locale_t locale) {
#ifdef HAVE_SNPRINTF_L #ifdef HAVE_SNPRINTF_L
return snprintf_l(str, size, locale, "%*.g", FLT_DIG, f); return snprintf_l(str, size, locale, "%.*g", FLT_DIG, f);
#elif defined(HAVE_LOCALE) #elif defined(HAVE_LOCALE)
locale_t old = uselocale(locale); locale_t old = uselocale(locale);
int res = snprintf(str, size, "%*.g", FLT_DIG, f); int res = snprintf(str, size, "%.*g", FLT_DIG, f);
uselocale(old); uselocale(old);
return res; return res;
#elif defined(HAVE_SETLOCALE) #elif defined(HAVE_SETLOCALE)
char* old = setlocale(LC_NUMERIC, locale); char* old = setlocale(LC_NUMERIC, locale);
int res = snprintf(str, size, "%*.g", FLT_DIG, f); int res = snprintf(str, size, "%.*g", FLT_DIG, f);
setlocale(LC_NUMERIC, old); setlocale(LC_NUMERIC, old);
return res; return res;
#else #else
UNUSED(locale); UNUSED(locale);
return snprintf(str, size, "%*.g", FLT_DIG, f); return snprintf(str, size, "%.*g", FLT_DIG, f);
#endif #endif
} }

View File

@ -2,9 +2,9 @@ if(NOT PROJECT_NAME)
set(PROJECT_NAME "mGBA") set(PROJECT_NAME "mGBA")
endif() endif()
set(LIB_VERSION_MAJOR 0) set(LIB_VERSION_MAJOR 0)
set(LIB_VERSION_MINOR 3) set(LIB_VERSION_MINOR 4)
set(LIB_VERSION_PATCH 0) set(LIB_VERSION_PATCH 0)
set(LIB_VERSION_ABI 0.3) set(LIB_VERSION_ABI 0.4)
set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}) set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH})
execute_process(COMMAND git describe --always --abbrev=40 --dirty OUTPUT_VARIABLE GIT_COMMIT ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND git describe --always --abbrev=40 --dirty OUTPUT_VARIABLE GIT_COMMIT ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
@ -32,6 +32,16 @@ else()
endif() endif()
endif() endif()
if(NOT GIT_COMMIT)
set(GIT_COMMIT "(unknown)")
endif()
if(NOT GIT_COMMIT_SHORT)
set(GIT_COMMIT_SHORT "(unknown)")
endif()
if(NOT GIT_BRANCH)
set(GIT_BRANCH "(unknown)")
endif()
if(CONFIG_FILE AND OUT_FILE) if(CONFIG_FILE AND OUT_FILE)
configure_file("${CONFIG_FILE}" "${OUT_FILE}") configure_file("${CONFIG_FILE}" "${OUT_FILE}")
endif() endif()