mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' (early part) into medusa
This commit is contained in:
commit
dfdccb12a9
3
CHANGES
3
CHANGES
|
@ -75,7 +75,6 @@ Emulation fixes:
|
|||
- GBA Video: Fix Hblank timing (fixes mgba.io/i/2131, mgba.io/i/2310)
|
||||
- GBA Video: Fix rare crash in modes 3-5
|
||||
Other fixes:
|
||||
- 3DS: Ensure writes update file modification time (fixes mgba.io/i/2444)
|
||||
- Core: Don't attempt to restore rewind diffs past start of rewind
|
||||
- Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451)
|
||||
- FFmpeg: Fix crash when encoding audio with some containers
|
||||
|
@ -83,11 +82,13 @@ Other fixes:
|
|||
- GB: Fix temporary saves
|
||||
- GB, GBA: Save writeback-pending masked saves on unload (fixes mgba.io/i/2396)
|
||||
- mGUI: Fix FPS counter after closing menu
|
||||
- Qt: Fix some hangs when using the debugger console
|
||||
- VFS: Failed file mapping should return NULL on POSIX
|
||||
Misc:
|
||||
- Core: Suspend runloop when a core crashes
|
||||
- Debugger: Save and restore CLI history
|
||||
- Debugger: GDB now works while the game is paused
|
||||
- GB MBC: Filter out MBC errors when cartridge is yanked (fixes mgba.io/i/2488)
|
||||
- GB Video: Add default SGB border
|
||||
- GBA: Automatically skip BIOS if ROM has invalid logo
|
||||
- GBA: Refine multiboot detection (fixes mgba.io/i/2192)
|
||||
|
|
|
@ -85,6 +85,7 @@ struct mCoreThreadInternal {
|
|||
|
||||
struct mCoreSync sync;
|
||||
struct mCoreRewindContext rewind;
|
||||
struct mCore* core;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -143,6 +143,8 @@ struct mDebugger {
|
|||
void (*update)(struct mDebugger*);
|
||||
void (*entered)(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
void (*custom)(struct mDebugger*);
|
||||
|
||||
void (*interrupt)(struct mDebugger*);
|
||||
};
|
||||
|
||||
struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore*);
|
||||
|
|
|
@ -77,6 +77,7 @@ struct CLIDebuggerBackend {
|
|||
void (*lineAppend)(struct CLIDebuggerBackend*, const char* line);
|
||||
const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len);
|
||||
void (*historyAppend)(struct CLIDebuggerBackend*, const char* line);
|
||||
void (*interrupt)(struct CLIDebuggerBackend*);
|
||||
};
|
||||
|
||||
struct CLIDebugger {
|
||||
|
@ -87,6 +88,7 @@ struct CLIDebugger {
|
|||
|
||||
int traceRemaining;
|
||||
struct VFile* traceVf;
|
||||
bool skipStatus;
|
||||
};
|
||||
|
||||
void CLIDebuggerCreate(struct CLIDebugger*);
|
||||
|
|
|
@ -92,6 +92,15 @@ static void _wait(struct mCoreThreadInternal* threadContext) {
|
|||
MutexUnlock(&threadContext->sync.audioBufferMutex);
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
if (threadContext->core && threadContext->core->debugger) {
|
||||
struct mDebugger* debugger = threadContext->core->debugger;
|
||||
if (debugger->interrupt) {
|
||||
debugger->interrupt(debugger);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MutexLock(&threadContext->stateMutex);
|
||||
ConditionWake(&threadContext->stateCond);
|
||||
}
|
||||
|
@ -216,6 +225,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
|
|||
}
|
||||
|
||||
core->reset(core);
|
||||
threadContext->impl->core = core;
|
||||
_changeState(threadContext->impl, mTHREAD_RUNNING, true);
|
||||
|
||||
if (threadContext->resetCallback) {
|
||||
|
@ -519,7 +529,11 @@ void mCoreThreadContinue(struct mCoreThread* threadContext) {
|
|||
MutexLock(&threadContext->impl->stateMutex);
|
||||
--threadContext->impl->interruptDepth;
|
||||
if (threadContext->impl->interruptDepth < 1 && mCoreThreadIsActive(threadContext)) {
|
||||
threadContext->impl->state = mTHREAD_REQUEST;
|
||||
if (threadContext->impl->requested) {
|
||||
threadContext->impl->state = mTHREAD_REQUEST;
|
||||
} else {
|
||||
threadContext->impl->state = mTHREAD_RUNNING;
|
||||
}
|
||||
ConditionWake(&threadContext->impl->stateCond);
|
||||
}
|
||||
MutexUnlock(&threadContext->impl->stateMutex);
|
||||
|
|
|
@ -994,21 +994,33 @@ bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_
|
|||
static void _commandLine(struct mDebugger* debugger) {
|
||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||
const char* line;
|
||||
size_t len;
|
||||
_printStatus(cliDebugger, 0);
|
||||
size_t len;
|
||||
if (cliDebugger->skipStatus) {
|
||||
cliDebugger->skipStatus = false;
|
||||
} else {
|
||||
_printStatus(cliDebugger, 0);
|
||||
}
|
||||
while (debugger->state == DEBUGGER_PAUSED) {
|
||||
line = cliDebugger->backend->readline(cliDebugger->backend, &len);
|
||||
if (!line || len == 0) {
|
||||
debugger->state = DEBUGGER_SHUTDOWN;
|
||||
return;
|
||||
}
|
||||
if (line[0] == '\033') {
|
||||
cliDebugger->skipStatus = true;
|
||||
return;
|
||||
}
|
||||
if (line[0] == '\n') {
|
||||
line = cliDebugger->backend->historyLast(cliDebugger->backend, &len);
|
||||
if (line && len) {
|
||||
CLIDebuggerRunCommand(cliDebugger, line, len);
|
||||
}
|
||||
} else {
|
||||
CLIDebuggerRunCommand(cliDebugger, line, len);
|
||||
if (line[0] == '#') {
|
||||
cliDebugger->skipStatus = true;
|
||||
} else {
|
||||
CLIDebuggerRunCommand(cliDebugger, line, len);
|
||||
}
|
||||
cliDebugger->backend->historyAppend(cliDebugger->backend, line);
|
||||
}
|
||||
}
|
||||
|
@ -1019,6 +1031,7 @@ static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason r
|
|||
if (cliDebugger->traceRemaining > 0) {
|
||||
cliDebugger->traceRemaining = 0;
|
||||
}
|
||||
cliDebugger->skipStatus = false;
|
||||
switch (reason) {
|
||||
case DEBUGGER_ENTER_MANUAL:
|
||||
case DEBUGGER_ENTER_ATTACHED:
|
||||
|
@ -1077,6 +1090,7 @@ static void _cliDebuggerInit(struct mDebugger* debugger) {
|
|||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||
cliDebugger->traceRemaining = 0;
|
||||
cliDebugger->traceVf = NULL;
|
||||
cliDebugger->skipStatus = false;
|
||||
cliDebugger->backend->init(cliDebugger->backend);
|
||||
if (cliDebugger->system && cliDebugger->system->init) {
|
||||
cliDebugger->system->init(cliDebugger->system);
|
||||
|
@ -1119,6 +1133,13 @@ static void _cliDebuggerCustom(struct mDebugger* debugger) {
|
|||
}
|
||||
}
|
||||
|
||||
static void _cliDebuggerInterrupt(struct mDebugger* debugger) {
|
||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||
if (cliDebugger->backend->interrupt) {
|
||||
cliDebugger->backend->interrupt(cliDebugger->backend);
|
||||
}
|
||||
}
|
||||
|
||||
void CLIDebuggerCreate(struct CLIDebugger* debugger) {
|
||||
debugger->d.init = _cliDebuggerInit;
|
||||
debugger->d.deinit = _cliDebuggerDeinit;
|
||||
|
@ -1126,6 +1147,7 @@ void CLIDebuggerCreate(struct CLIDebugger* debugger) {
|
|||
debugger->d.paused = _commandLine;
|
||||
debugger->d.update = NULL;
|
||||
debugger->d.entered = _reportEntry;
|
||||
debugger->d.interrupt = _cliDebuggerInterrupt;
|
||||
debugger->d.type = DEBUGGER_CLI;
|
||||
|
||||
debugger->system = NULL;
|
||||
|
|
|
@ -761,12 +761,13 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) {
|
|||
void GDBStubCreate(struct GDBStub* stub) {
|
||||
stub->socket = INVALID_SOCKET;
|
||||
stub->connection = INVALID_SOCKET;
|
||||
stub->d.init = 0;
|
||||
stub->d.init = NULL;
|
||||
stub->d.deinit = _gdbStubDeinit;
|
||||
stub->d.paused = _gdbStubWait;
|
||||
stub->d.update = _gdbStubUpdate;
|
||||
stub->d.entered = _gdbStubEntered;
|
||||
stub->d.custom = _gdbStubPoll;
|
||||
stub->d.interrupt = NULL;
|
||||
stub->d.type = DEBUGGER_GDB;
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
stub->lineAck = GDB_ACK_PENDING;
|
||||
|
|
|
@ -152,7 +152,7 @@ void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char
|
|||
}
|
||||
|
||||
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = malloc(sizeof(*elbe));
|
||||
struct CLIDebuggerEditLineBackend* elbe = calloc(1, sizeof(*elbe));
|
||||
elbe->d.printf = _CLIDebuggerEditLinePrintf;
|
||||
elbe->d.init = _CLIDebuggerEditLineInit;
|
||||
elbe->d.deinit = _CLIDebuggerEditLineDeinit;
|
||||
|
@ -160,5 +160,6 @@ struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
|
|||
elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend;
|
||||
elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast;
|
||||
elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend;
|
||||
elbe->d.interrupt = NULL;
|
||||
return &elbe->d;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@ const uint32_t GB_LOGO_HASH = 0x46195417;
|
|||
mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC", "gb.mbc");
|
||||
|
||||
static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) {
|
||||
UNUSED(gb);
|
||||
UNUSED(address);
|
||||
UNUSED(value);
|
||||
|
||||
mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
|
||||
if (!gb->yankedRomSize) {
|
||||
mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
|
||||
}
|
||||
}
|
||||
|
||||
static void _GBMBC1(struct GB*, uint16_t address, uint8_t value);
|
||||
|
|
|
@ -26,6 +26,7 @@ DebuggerConsoleController::DebuggerConsoleController(QObject* parent)
|
|||
m_backend.d.lineAppend = lineAppend;
|
||||
m_backend.d.historyLast = historyLast;
|
||||
m_backend.d.historyAppend = historyAppend;
|
||||
m_backend.d.interrupt = interrupt;
|
||||
m_backend.self = this;
|
||||
|
||||
CLIDebuggerCreate(&m_cliDebugger);
|
||||
|
@ -90,7 +91,6 @@ void DebuggerConsoleController::deinit(struct CLIDebuggerBackend* be) {
|
|||
const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
Backend* consoleBe = reinterpret_cast<Backend*>(be);
|
||||
DebuggerConsoleController* self = consoleBe->self;
|
||||
CoreController::Interrupter interrupter(self->m_gameController);
|
||||
QMutexLocker lock(&self->m_mutex);
|
||||
while (self->m_lines.isEmpty()) {
|
||||
self->m_cond.wait(&self->m_mutex);
|
||||
|
@ -132,6 +132,17 @@ void DebuggerConsoleController::historyAppend(struct CLIDebuggerBackend* be, con
|
|||
self->m_history.append(QString::fromUtf8(line));
|
||||
}
|
||||
|
||||
void DebuggerConsoleController::interrupt(struct CLIDebuggerBackend* be) {
|
||||
Backend* consoleBe = reinterpret_cast<Backend*>(be);
|
||||
DebuggerConsoleController* self = consoleBe->self;
|
||||
QMutexLocker lock(&self->m_mutex);
|
||||
self->m_cond.wakeOne();
|
||||
if (!self->m_lines.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
self->m_lines.append("\033");
|
||||
}
|
||||
|
||||
void DebuggerConsoleController::historyLoad() {
|
||||
QFile log(ConfigController::configDir() + "/cli_history.log");
|
||||
QStringList history;
|
||||
|
|
|
@ -46,6 +46,7 @@ private:
|
|||
static void lineAppend(struct CLIDebuggerBackend* be, const char* line);
|
||||
static const char* historyLast(struct CLIDebuggerBackend* be, size_t* len);
|
||||
static void historyAppend(struct CLIDebuggerBackend* be, const char* line);
|
||||
static void interrupt(struct CLIDebuggerBackend* be);
|
||||
|
||||
CLIDebugger m_cliDebugger{};
|
||||
|
||||
|
|
|
@ -463,6 +463,7 @@ void PainterGL::create() {
|
|||
painter->m_gl->swapBuffers(painter->m_surface);
|
||||
painter->makeCurrent();
|
||||
|
||||
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||
if (painter->m_widget && painter->supportsShaders()) {
|
||||
QOpenGLFunctions_Baseline* fn = painter->m_gl->versionFunctions<QOpenGLFunctions_Baseline>();
|
||||
fn->glFinish();
|
||||
|
@ -472,6 +473,7 @@ void PainterGL::create() {
|
|||
gl2Backend->finalShader.tex = painter->m_finalTex[painter->m_finalTexIdx];
|
||||
mGLES2ContextUseFramebuffer(gl2Backend);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
m_backend->init(m_backend, 0);
|
||||
|
|
|
@ -577,6 +577,9 @@ void FrameView::frameCallback(FrameView* viewer, std::shared_ptr<bool> lock) {
|
|||
void FrameView::exportFrame() {
|
||||
QString filename = GBAApp::app()->getSaveFileName(this, tr("Export frame"),
|
||||
tr("Portable Network Graphics (*.png)"));
|
||||
if (filename.isNull()) {
|
||||
return;
|
||||
}
|
||||
CoreController::Interrupter interrupter(m_controller);
|
||||
m_framebuffer.save(filename, "PNG");
|
||||
}
|
||||
|
|
|
@ -86,7 +86,9 @@ void GIFView::stopRecording() {
|
|||
|
||||
void GIFView::selectFile() {
|
||||
QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif);;WebP ( *.webp);;Animated Portable Network Graphics (*.png *.apng)"));
|
||||
m_ui.filename->setText(filename);
|
||||
if (!filename.isNull()) {
|
||||
m_ui.filename->setText(filename);
|
||||
}
|
||||
}
|
||||
|
||||
void GIFView::setFilename(const QString& filename) {
|
||||
|
|
|
@ -266,6 +266,7 @@ void ObjView::updateObjList(int maxObj) {
|
|||
item->setText(QString::number(i));
|
||||
item->setData(Qt::UserRole, i);
|
||||
item->setSizeHint(QSize(64, 96));
|
||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
if (m_objId == i) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
|
|
|
@ -136,6 +136,9 @@ void PaletteView::exportPalette(int start, int length) {
|
|||
CoreController::Interrupter interrupter(m_controller);
|
||||
QString filename = GBAApp::app()->getSaveFileName(this, tr("Export palette"),
|
||||
tr("Windows PAL (*.pal);;Adobe Color Table (*.act)"));
|
||||
if (filename.isNull()) {
|
||||
return;
|
||||
}
|
||||
VFile* vf = VFileDevice::open(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
if (!vf) {
|
||||
LOG(QT, ERROR) << tr("Failed to open output palette file: %1").arg(filename);
|
||||
|
|
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
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
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<app version="1">
|
||||
<name>mGBA</name>
|
||||
<coder>Jeffrey Pfau (endrift)</coder>
|
||||
<coder>Vicki Pfau (endrift)</coder>
|
||||
<version>${VERSION_STRING}</version>
|
||||
<short_description>mGBA Game Boy Advance emulator</short_description>
|
||||
</app>
|
||||
|
|
Loading…
Reference in New Issue