From 8c81fc44a05bd07e62a381bb93fa9e5e34bdcf7f Mon Sep 17 00:00:00 2001 From: Leo Date: Mon, 20 Jul 2020 12:53:17 +0800 Subject: [PATCH 01/36] Vita: Fix flickering when using frameskip --- src/platform/psp2/psp2-context.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index b777ec938..444679d33 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -52,7 +52,7 @@ static enum ScreenMode { static void* outputBuffer; static int currentTex; -static vita2d_texture* tex[4]; +static vita2d_texture* tex[2]; static vita2d_texture* screenshot; static Thread audioThread; static bool interframeBlending = false; @@ -326,8 +326,6 @@ void mPSP2Setup(struct mGUIRunner* runner) { runner->core->desiredVideoDimensions(runner->core, &width, &height); tex[0] = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); tex[1] = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); - tex[2] = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); - tex[3] = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); currentTex = 0; screenshot = vita2d_create_empty_texture_format(256, toPow2(height), SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR); @@ -494,8 +492,6 @@ void mPSP2Teardown(struct mGUIRunner* runner) { CircleBufferDeinit(&rumble.history); vita2d_free_texture(tex[0]); vita2d_free_texture(tex[1]); - vita2d_free_texture(tex[2]); - vita2d_free_texture(tex[3]); vita2d_free_texture(screenshot); mappedMemoryFree(outputBuffer, 256 * 256 * 4); frameLimiter = true; @@ -588,15 +584,27 @@ void _drawTex(vita2d_texture* t, unsigned width, unsigned height, bool faded, bo } void mPSP2Swap(struct mGUIRunner* runner) { - currentTex = (currentTex + 1) & 3; - runner->core->setVideoBuffer(runner->core, vita2d_texture_get_datap(tex[currentTex]), 256); + bool frameAvailable; + if (runner->core->platform(runner->core) == PLATFORM_GBA) { + struct GBA* gba = runner->core->board; + frameAvailable = gba->video.frameskipCounter <= 0; + } else if (runner->core->platform(runner->core) == PLATFORM_GB) { + struct GB* gb = runner->core->board; + frameAvailable = gb->video.frameskipCounter <= 0; + } else { + frameAvailable = false; + } + if (frameAvailable) { + currentTex = !currentTex; + runner->core->setVideoBuffer(runner->core, vita2d_texture_get_datap(tex[currentTex]), 256); + } } void mPSP2Draw(struct mGUIRunner* runner, bool faded) { unsigned width, height; runner->core->desiredVideoDimensions(runner->core, &width, &height); if (interframeBlending) { - _drawTex(tex[(currentTex - 1) & 3], width, height, faded, false); + _drawTex(tex[!currentTex], width, height, faded, false); } _drawTex(tex[currentTex], width, height, faded, interframeBlending); } From 8ee4b3c0463ad402aa60e5c9f406da812952f9a0 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Thu, 30 Jul 2020 18:59:12 -0500 Subject: [PATCH 02/36] Stack traces: add detection for other calling conventions and stack manipulation --- include/mgba/internal/arm/decoder-inlines.h | 12 +++ include/mgba/internal/arm/isa-inlines.h | 35 ++++++ src/arm/debugger/debugger.c | 113 +++++++++++++++----- src/debugger/gdb-stub.c | 1 + src/debugger/stack-trace.c | 10 +- 5 files changed, 141 insertions(+), 30 deletions(-) diff --git a/include/mgba/internal/arm/decoder-inlines.h b/include/mgba/internal/arm/decoder-inlines.h index ad108383c..11d41d520 100644 --- a/include/mgba/internal/arm/decoder-inlines.h +++ b/include/mgba/internal/arm/decoder-inlines.h @@ -22,4 +22,16 @@ info->nInstructionCycles = 1; \ info->nDataCycles = 1; +static inline bool ARMInstructionIsBranch(enum ARMMnemonic mnemonic) { + switch (mnemonic) { + case ARM_MN_B: + case ARM_MN_BL: + case ARM_MN_BX: + // TODO: case: ARM_MN_BLX: + return true; + default: + return false; + } +} + #endif diff --git a/include/mgba/internal/arm/isa-inlines.h b/include/mgba/internal/arm/isa-inlines.h index 0cabcfee2..22dde1c9c 100644 --- a/include/mgba/internal/arm/isa-inlines.h +++ b/include/mgba/internal/arm/isa-inlines.h @@ -107,4 +107,39 @@ static inline uint32_t _ARMPCAddress(struct ARMCore* cpu) { return cpu->gprs[ARM_PC] - _ARMInstructionLength(cpu) * 2; } +static inline bool ARMTestCondition(struct ARMCore* cpu, unsigned condition) { + switch (condition) { + case 0x0: + return ARM_COND_EQ; + case 0x1: + return ARM_COND_NE; + case 0x2: + return ARM_COND_CS; + case 0x3: + return ARM_COND_CC; + case 0x4: + return ARM_COND_MI; + case 0x5: + return ARM_COND_PL; + case 0x6: + return ARM_COND_VS; + case 0x7: + return ARM_COND_VC; + case 0x8: + return ARM_COND_HI; + case 0x9: + return ARM_COND_LS; + case 0xA: + return ARM_COND_GE; + case 0xB: + return ARM_COND_LT; + case 0xC: + return ARM_COND_GT; + case 0xD: + return ARM_COND_LE; + default: + return true; + } +} + #endif diff --git a/src/arm/debugger/debugger.c b/src/arm/debugger/debugger.c index 8a79a5ad8..fefcaec30 100644 --- a/src/arm/debugger/debugger.c +++ b/src/arm/debugger/debugger.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,14 +17,56 @@ DEFINE_VECTOR(ARMDebugBreakpointList, struct ARMDebugBreakpoint); +static bool ARMDecodeCombined(struct ARMCore* cpu, struct ARMInstructionInfo* info) { + if (cpu->executionMode == MODE_ARM) { + ARMDecodeARM(cpu->prefetch[0], info); + return true; + } else { + struct ARMInstructionInfo info2; + ARMDecodeThumb(cpu->prefetch[0], info); + ARMDecodeThumb(cpu->prefetch[1], &info2); + return ARMDecodeThumbCombine(info, &info2, info); + } +} + static bool ARMDebuggerUpdateStackTraceInternal(struct mDebuggerPlatform* d, uint32_t pc) { struct ARMDebugger* debugger = (struct ARMDebugger*) d; struct ARMCore* cpu = debugger->cpu; struct ARMInstructionInfo info; - uint32_t instruction = cpu->prefetch[0]; struct mStackTrace* stack = &d->p->stackTrace; + + struct mStackFrame* frame = mStackTraceGetFrame(stack, 0); + if (frame && frame->frameBaseAddress < (uint32_t) cpu->gprs[ARM_SP]) { + // The stack frame has been popped off the stack. This means the function + // has been returned from, or that the stack pointer has been otherwise + // manipulated. Either way, the function is done executing. + bool shouldBreak = debugger->stackTraceMode & STACK_TRACE_BREAK_ON_RETURN; + do { + shouldBreak = shouldBreak || frame->breakWhenFinished; + mStackTracePop(stack); + frame = mStackTraceGetFrame(stack, 0); + } while (frame && frame->frameBaseAddress < (uint32_t) cpu->gprs[ARM_SP]); + if (shouldBreak) { + struct mDebuggerEntryInfo debuggerInfo = { + .address = pc, + .type.st.traceType = STACK_TRACE_BREAK_ON_RETURN, + .pointId = 0 + }; + mDebuggerEnter(d->p, DEBUGGER_ENTER_STACK, &debuggerInfo); + return true; + } else { + return false; + } + } + bool interrupt = false; - ARMDecodeARM(instruction, &info); + bool isWideInstruction = ARMDecodeCombined(cpu, &info); + if (!isWideInstruction && info.mnemonic == ARM_MN_BL) { + return false; + } + if (!ARMTestCondition(cpu, info.condition)) { + return false; + } if (_ARMModeHasSPSR(cpu->cpsr.priv)) { struct mStackFrame* irqFrame = mStackTraceGetFrame(stack, 0); @@ -41,15 +84,9 @@ static bool ARMDebuggerUpdateStackTraceInternal(struct mDebuggerPlatform* d, uin return false; } - struct mStackFrame* frame = mStackTraceGetFrame(stack, 0); - bool isCall = (info.branchType & ARM_BRANCH_LINKED); + bool isCall = interrupt || (info.branchType & ARM_BRANCH_LINKED); uint32_t destAddress; - if (frame && frame->finished) { - mStackTracePop(stack); - frame = NULL; - } - if (interrupt && info.branchType == ARM_BRANCH_NONE) { // The stack frame was already pushed up above, so there's no // action necessary here, but we still want to check for a @@ -57,6 +94,7 @@ static bool ARMDebuggerUpdateStackTraceInternal(struct mDebuggerPlatform* d, uin // // The first instruction could possibly be a call, which would // need ANOTHER stack frame, so only skip if it's not. + destAddress = pc; } else if (info.operandFormat & ARM_OPERAND_MEMORY_1) { // This is most likely ldmia ..., {..., pc}, which is a function return. // To find which stack slot holds the return address, count the number of set bits. @@ -69,10 +107,39 @@ static bool ARMDebuggerUpdateStackTraceInternal(struct mDebuggerPlatform* d, uin } destAddress = info.op1.immediate + cpu->gprs[ARM_PC]; } else if (info.operandFormat & ARM_OPERAND_REGISTER_1) { - if (!isCall && info.op1.reg != ARM_LR && !(_ARMModeHasSPSR(cpu->cpsr.priv) && info.op1.reg == ARM_PC)) { - return false; + if (isCall) { + destAddress = cpu->gprs[info.op1.reg]; + } else { + bool isExceptionReturn = _ARMModeHasSPSR(cpu->cpsr.priv) && info.affectsCPSR && info.op1.reg == ARM_PC; + bool isMovPcLr = (info.operandFormat & ARM_OPERAND_REGISTER_2) && info.op1.reg == ARM_PC && info.op2.reg == ARM_LR; + bool isBranch = ARMInstructionIsBranch(info.mnemonic); + int reg = (isBranch ? info.op1.reg : info.op2.reg); + destAddress = cpu->gprs[reg]; + if (isBranch || (info.op1.reg == ARM_PC && !isMovPcLr)) { + // ARMv4 doesn't have the BLX opcode, so it uses an assignment to LR before a BX for that purpose. + struct ARMInstructionInfo prevInfo; + if (cpu->executionMode == MODE_ARM) { + ARMDecodeARM(cpu->memory.load32(cpu, pc - 4, NULL), &prevInfo); + } else { + ARMDecodeThumb(cpu->memory.load16(cpu, pc - 2, NULL), &prevInfo); + } + if ((prevInfo.operandFormat & (ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1)) == (ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1) && prevInfo.op1.reg == ARM_LR) { + isCall = true; + } else if ((isBranch ? info.op1.reg : info.op2.reg) == ARM_LR) { + isBranch = true; + } else if (frame && frame->frameBaseAddress == (uint32_t) cpu->gprs[ARM_SP]) { + // A branch to something that isn't LR isn't a standard function return, but it might potentially + // be a nonstandard one. As a heuristic, if the stack pointer and the destination address match + // where we came from, consider it to be a function return. + isBranch = (destAddress > frame->callAddress + 1 && destAddress <= frame->callAddress + 5); + } else { + isBranch = false; + } + } + if (!isCall && !isBranch && !isExceptionReturn && !isMovPcLr) { + return false; + } } - destAddress = cpu->gprs[info.op1.reg]; } else { mLOG(DEBUGGER, ERROR, "Unknown branch operand in stack trace"); return false; @@ -83,21 +150,16 @@ static bool ARMDebuggerUpdateStackTraceInternal(struct mDebuggerPlatform* d, uin } if (isCall) { - int instructionLength = _ARMInstructionLength(debugger->cpu); + int instructionLength = isWideInstruction ? WORD_SIZE_ARM : WORD_SIZE_THUMB; frame = mStackTracePush(stack, pc, destAddress + instructionLength, cpu->gprs[ARM_SP], &cpu->regs); if (!(debugger->stackTraceMode & STACK_TRACE_BREAK_ON_CALL)) { return false; } } else { - frame = mStackTraceGetFrame(stack, 0); - if (!frame) { + mStackTracePop(stack); + if (!(debugger->stackTraceMode & STACK_TRACE_BREAK_ON_RETURN)) { return false; } - if (!frame->breakWhenFinished && !(debugger->stackTraceMode & STACK_TRACE_BREAK_ON_RETURN)) { - mStackTracePop(stack); - return false; - } - frame->finished = true; } struct mDebuggerEntryInfo debuggerInfo = { .address = pc, @@ -404,21 +466,18 @@ static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* len char disassembly[64]; struct ARMInstructionInfo info; + bool isWideInstruction = ARMDecodeCombined(cpu, &info); if (cpu->executionMode == MODE_ARM) { uint32_t instruction = cpu->prefetch[0]; sprintf(disassembly, "%08X: ", instruction); - ARMDecodeARM(instruction, &info); ARMDisassemble(&info, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); } else { - struct ARMInstructionInfo info2; - struct ARMInstructionInfo combined; uint16_t instruction = cpu->prefetch[0]; - uint16_t instruction2 = cpu->prefetch[1]; ARMDecodeThumb(instruction, &info); - ARMDecodeThumb(instruction2, &info2); - if (ARMDecodeThumbCombine(&info, &info2, &combined)) { + if (isWideInstruction) { + uint16_t instruction2 = cpu->prefetch[1]; sprintf(disassembly, "%04X%04X: ", instruction, instruction2); - ARMDisassemble(&combined, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); + ARMDisassemble(&info, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); } else { sprintf(disassembly, " %04X: ", instruction); ARMDisassemble(&info, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index 10c802108..3c0a77f37 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -82,6 +82,7 @@ static void _gdbStubEntered(struct mDebugger* debugger, enum mDebuggerEntryReaso snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGILL); break; case DEBUGGER_ENTER_ATTACHED: + case DEBUGGER_ENTER_STACK: return; } _sendMessage(stub); diff --git a/src/debugger/stack-trace.c b/src/debugger/stack-trace.c index acb7b505e..4d6357698 100644 --- a/src/debugger/stack-trace.c +++ b/src/debugger/stack-trace.c @@ -65,7 +65,7 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out size_t written = snprintf(out, *length, "#%d ", frame); CHECK_LENGTH(); if (prevFrame) { - written += snprintf(out + written, *length - written, "%08X ", prevFrame->entryAddress); + written += snprintf(out + written, *length - written, "0x%08X ", prevFrame->entryAddress); CHECK_LENGTH(); } if (!stackFrame) { @@ -83,9 +83,13 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out } if (prevFrame) { int32_t offset = stackFrame->callAddress - prevFrame->entryAddress; - written += snprintf(out + written, *length - written, "at %08X [%08X+%d]\n", stackFrame->callAddress, prevFrame->entryAddress, offset); + if (offset >= 0) { + written += snprintf(out + written, *length - written, "at 0x%08X [0x%08X+%d]\n", stackFrame->callAddress, prevFrame->entryAddress, offset); + } else { + written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); + } } else { - written += snprintf(out + written, *length - written, "at %08X\n", stackFrame->callAddress); + written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); } *length = written; } From 8a9a8859a68b8abdc2632cfe9dcf3b91a281f685 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 01:31:49 -0700 Subject: [PATCH 03/36] Qt: Display memory cleanup --- src/platform/qt/DisplayGL.cpp | 10 ++-------- src/platform/qt/DisplayGL.h | 3 +++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index b5759e8cf..c6ccbe9bc 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -327,18 +327,12 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion) m_backend->lockAspectRatio = false; m_backend->interframeBlending = false; - for (int i = 0; i < 3; ++i) { - m_free.append(new uint32_t[1024 * 2048]); + for (auto& buf : m_buffers) { + m_free.append(&buf.front()); } } PainterGL::~PainterGL() { - while (!m_queue.isEmpty()) { - delete[] m_queue.dequeue(); - } - for (auto item : m_free) { - delete[] item; - } m_gl->makeCurrent(m_surface); #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 6948eec96..84463069a 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -25,6 +25,8 @@ #include #include +#include + #include "VideoProxy.h" #include "platform/video-backend.h" @@ -119,6 +121,7 @@ private: void dequeue(); void dequeueAll(); + std::array, 3> m_buffers; QList m_free; QQueue m_queue; uint32_t* m_buffer; From 4807d684825af75f16b19cd03a4dbbd6520f4a60 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 01:33:47 -0700 Subject: [PATCH 04/36] Qt: Attempt to fix DisplayGL crash --- src/platform/qt/DisplayGL.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index c6ccbe9bc..d1e619c09 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -487,8 +487,6 @@ void PainterGL::performDraw() { m_backend->resized(m_backend, m_size.width() * r, m_size.height() * r); if (m_buffer) { m_backend->postFrame(m_backend, m_buffer); - m_free.append(m_buffer); - m_buffer = nullptr; } m_backend->drawFrame(m_backend); m_painter.endNativePainting(); @@ -498,7 +496,7 @@ void PainterGL::performDraw() { } void PainterGL::enqueue(const uint32_t* backing) { - m_mutex.lock(); + QMutexLocker locker(&m_mutex); uint32_t* buffer = nullptr; if (backing) { if (m_free.isEmpty()) { @@ -506,17 +504,17 @@ void PainterGL::enqueue(const uint32_t* backing) { } else { buffer = m_free.takeLast(); } - QSize size = m_context->screenDimensions(); - memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); + if (buffer) { + QSize size = m_context->screenDimensions(); + memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); + } } m_queue.enqueue(buffer); - m_mutex.unlock(); } void PainterGL::dequeue() { - m_mutex.lock(); + QMutexLocker locker(&m_mutex); if (m_queue.isEmpty()) { - m_mutex.unlock(); return; } uint32_t* buffer = m_queue.dequeue(); @@ -524,10 +522,7 @@ void PainterGL::dequeue() { m_free.append(m_buffer); m_buffer = nullptr; } - if (buffer) { - m_buffer = buffer; - } - m_mutex.unlock(); + m_buffer = buffer; } void PainterGL::dequeueAll() { From 1a8657315e26f25190bfe24c75327f16974acf01 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 17:29:09 -0700 Subject: [PATCH 05/36] 3DS: Fix compilation flags --- src/platform/3ds/CMakeToolchain.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/3ds/CMakeToolchain.txt b/src/platform/3ds/CMakeToolchain.txt index cccfb6a78..ea0fb7e70 100644 --- a/src/platform/3ds/CMakeToolchain.txt +++ b/src/platform/3ds/CMakeToolchain.txt @@ -7,7 +7,7 @@ else() endif() set(cross_prefix arm-none-eabi-) -set(arch_flags "-march=armv6k -mtune=mpcore -mfloat-abi=hard -ffunction-sections") +set(arch_flags "-march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -ffunction-sections") set(inc_flags "-I${CTRULIB}/include ${arch_flags} -mword-relocations") set(link_flags "-L${CTRULIB}/lib -lctru -specs=3dsx.specs ${arch_flags} -Wl,--gc-sections") From 0fdc3436895a2b21afdf17069e24681f3093d211 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 17:36:59 -0700 Subject: [PATCH 06/36] GB Core: Fix some MINIMAL_CORE differences --- src/gb/core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gb/core.c b/src/gb/core.c index b42bcbf1e..0f17c4cc8 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -64,8 +64,10 @@ struct mVideoLogContext; struct GBCore { struct mCore d; struct GBVideoSoftwareRenderer renderer; +#ifndef MINIMAL_CORE struct GBVideoProxyRenderer proxyRenderer; struct mVideoLogContext* logContext; +#endif struct mCoreCallbacks logCallbacks; uint8_t keys; struct mCPUComponent* components[CPU_COMPONENT_MAX]; @@ -90,6 +92,9 @@ static bool _GBCoreInit(struct mCore* core) { gbcore->overrides = NULL; gbcore->debuggerPlatform = NULL; gbcore->cheatDevice = NULL; +#ifndef MINIMAL_CORE + gbcore->logContext = NULL; +#endif GBCreate(gb); memset(gbcore->components, 0, sizeof(gbcore->components)); @@ -101,6 +106,10 @@ static bool _GBCoreInit(struct mCore* core) { GBVideoSoftwareRendererCreate(&gbcore->renderer); gbcore->renderer.outputBuffer = NULL; +#ifndef MINIMAL_CORE + gbcore->proxyRenderer.logger = NULL; +#endif + gbcore->keys = 0; gb->keySource = &gbcore->keys; From e27963bd29653427b99a97742c48a79e7d3a887a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 18:02:29 -0700 Subject: [PATCH 07/36] GB/GBA Video: Move dummy renderer to core --- include/mgba/internal/gb/video.h | 6 +++ include/mgba/internal/gba/video.h | 2 + src/gb/core.c | 4 ++ src/gb/video.c | 84 +++++++++++++++++++------------ src/gba/core.c | 66 ++++++++++++------------ src/gba/video.c | 48 +++++++++++------- 6 files changed, 125 insertions(+), 85 deletions(-) diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index b7dc54ecf..13473776a 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -10,9 +10,12 @@ CXX_GUARD_START +#include #include #include +mLOG_DECLARE_CATEGORY(GB_VIDEO); + enum { GB_VIDEO_HORIZONTAL_PIXELS = 160, GB_VIDEO_VERTICAL_PIXELS = 144, @@ -160,7 +163,10 @@ struct GBVideo { void GBVideoInit(struct GBVideo* video); void GBVideoReset(struct GBVideo* video); void GBVideoDeinit(struct GBVideo* video); + +void GBVideoDummyRendererCreate(struct GBVideoRenderer*); void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer); + void GBVideoSkipBIOS(struct GBVideo* video); void GBVideoProcessDots(struct GBVideo* video, uint32_t cyclesLate); diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 87e5c38cc..c9ae1974a 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -221,6 +221,8 @@ struct GBAVideo { void GBAVideoInit(struct GBAVideo* video); void GBAVideoReset(struct GBAVideo* video); void GBAVideoDeinit(struct GBAVideo* video); + +void GBAVideoDummyRendererCreate(struct GBAVideoRenderer*); void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer* renderer); void GBAVideoWriteDISPSTAT(struct GBAVideo* video, uint16_t value); diff --git a/src/gb/core.c b/src/gb/core.c index 0f17c4cc8..ebbacbfd2 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -64,6 +64,7 @@ struct mVideoLogContext; struct GBCore { struct mCore d; struct GBVideoSoftwareRenderer renderer; + struct GBVideoRenderer dummyRenderer; #ifndef MINIMAL_CORE struct GBVideoProxyRenderer proxyRenderer; struct mVideoLogContext* logContext; @@ -419,6 +420,9 @@ static void _GBCoreReset(struct mCore* core) { struct GB* gb = (struct GB*) core->board; if (gbcore->renderer.outputBuffer) { GBVideoAssociateRenderer(&gb->video, &gbcore->renderer.d); + } else { + GBVideoDummyRendererCreate(&gbcore->dummyRenderer); + GBVideoAssociateRenderer(&gb->video, &gbcore->dummyRenderer); } if (gb->memory.rom) { diff --git a/src/gb/video.c b/src/gb/video.c index 85522ddf8..09588fc14 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -16,6 +16,8 @@ #include +mLOG_DEFINE_CATEGORY(GB_VIDEO, "GB Video", "gb.video"); + static void GBVideoDummyRendererInit(struct GBVideoRenderer* renderer, enum GBModel model, bool borders); static void GBVideoDummyRendererDeinit(struct GBVideoRenderer* renderer); static uint8_t GBVideoDummyRendererWriteVideoRegister(struct GBVideoRenderer* renderer, uint16_t address, uint8_t value); @@ -38,26 +40,8 @@ static void _endMode2(struct mTiming* timing, void* context, uint32_t cyclesLate static void _endMode3(struct mTiming* timing, void* context, uint32_t cyclesLate); static void _updateFrameCount(struct mTiming* timing, void* context, uint32_t cyclesLate); -static struct GBVideoRenderer dummyRenderer = { - .init = GBVideoDummyRendererInit, - .deinit = GBVideoDummyRendererDeinit, - .writeVideoRegister = GBVideoDummyRendererWriteVideoRegister, - .writeSGBPacket = GBVideoDummyRendererWriteSGBPacket, - .writeVRAM = GBVideoDummyRendererWriteVRAM, - .writeOAM = GBVideoDummyRendererWriteOAM, - .writePalette = GBVideoDummyRendererWritePalette, - .drawRange = GBVideoDummyRendererDrawRange, - .finishScanline = GBVideoDummyRendererFinishScanline, - .finishFrame = GBVideoDummyRendererFinishFrame, - .enableSGBBorder = GBVideoDummyRendererEnableSGBBorder, - .getPixels = GBVideoDummyRendererGetPixels, - .putPixels = GBVideoDummyRendererPutPixels, -}; - void GBVideoInit(struct GBVideo* video) { - video->renderer = &dummyRenderer; - video->renderer->cache = NULL; - video->renderer->sgbRenderMode = 0; + video->renderer = NULL; video->vram = anonymousMemoryMap(GB_SIZE_VRAM); video->frameskip = 0; @@ -84,12 +68,6 @@ void GBVideoInit(struct GBVideo* video) { video->dmgPalette[11] = 0x0000; video->sgbBorders = true; - - video->renderer->sgbCharRam = NULL; - video->renderer->sgbMapRam = NULL; - video->renderer->sgbPalRam = NULL; - video->renderer->sgbAttributes = NULL; - video->renderer->sgbAttributeFiles = NULL; } void GBVideoReset(struct GBVideo* video) { @@ -116,6 +94,12 @@ void GBVideoReset(struct GBVideo* video) { memset(video->renderer->sgbAttributes, 0, 90 * 45); video->sgbCommandHeader = 0; video->sgbBufferIndex = 0; + } else { + video->renderer->sgbCharRam = NULL; + video->renderer->sgbMapRam = NULL; + video->renderer->sgbPalRam = NULL; + video->renderer->sgbAttributes = NULL; + video->renderer->sgbAttributeFiles = NULL; } video->palette[0] = video->dmgPalette[0]; @@ -131,6 +115,11 @@ void GBVideoReset(struct GBVideo* video) { video->palette[9 * 4 + 2] = video->dmgPalette[10]; video->palette[9 * 4 + 3] = video->dmgPalette[11]; + if (!video->renderer) { + mLOG(GB_VIDEO, FATAL, "No renderer associated"); + return; + } + video->renderer->deinit(video->renderer); video->renderer->init(video->renderer, video->p->model, video->sgbBorders); @@ -173,15 +162,44 @@ void GBVideoDeinit(struct GBVideo* video) { } } +void GBVideoDummyRendererCreate(struct GBVideoRenderer* renderer) { + static const struct GBVideoRenderer dummyRenderer = { + .init = GBVideoDummyRendererInit, + .deinit = GBVideoDummyRendererDeinit, + .writeVideoRegister = GBVideoDummyRendererWriteVideoRegister, + .writeSGBPacket = GBVideoDummyRendererWriteSGBPacket, + .writeVRAM = GBVideoDummyRendererWriteVRAM, + .writeOAM = GBVideoDummyRendererWriteOAM, + .writePalette = GBVideoDummyRendererWritePalette, + .drawRange = GBVideoDummyRendererDrawRange, + .finishScanline = GBVideoDummyRendererFinishScanline, + .finishFrame = GBVideoDummyRendererFinishFrame, + .enableSGBBorder = GBVideoDummyRendererEnableSGBBorder, + .getPixels = GBVideoDummyRendererGetPixels, + .putPixels = GBVideoDummyRendererPutPixels, + }; + memcpy(renderer, &dummyRenderer, sizeof(*renderer)); +} + void GBVideoAssociateRenderer(struct GBVideo* video, struct GBVideoRenderer* renderer) { - video->renderer->deinit(video->renderer); - renderer->cache = video->renderer->cache; - renderer->sgbRenderMode = video->renderer->sgbRenderMode; - renderer->sgbCharRam = video->renderer->sgbCharRam; - renderer->sgbMapRam = video->renderer->sgbMapRam; - renderer->sgbPalRam = video->renderer->sgbPalRam; - renderer->sgbAttributeFiles = video->renderer->sgbAttributeFiles; - renderer->sgbAttributes = video->renderer->sgbAttributes; + if (video->renderer) { + video->renderer->deinit(video->renderer); + renderer->cache = video->renderer->cache; + renderer->sgbRenderMode = video->renderer->sgbRenderMode; + renderer->sgbCharRam = video->renderer->sgbCharRam; + renderer->sgbMapRam = video->renderer->sgbMapRam; + renderer->sgbPalRam = video->renderer->sgbPalRam; + renderer->sgbAttributeFiles = video->renderer->sgbAttributeFiles; + renderer->sgbAttributes = video->renderer->sgbAttributes; + } else { + renderer->cache = NULL; + renderer->sgbRenderMode = 0; + renderer->sgbCharRam = NULL; + renderer->sgbMapRam = NULL; + renderer->sgbPalRam = NULL; + renderer->sgbAttributeFiles = NULL; + renderer->sgbAttributes = NULL; + } video->renderer = renderer; renderer->vram = video->vram; video->renderer->init(video->renderer, video->p->model, video->sgbBorders); diff --git a/src/gba/core.c b/src/gba/core.c index c8f9c7348..c1aa5b047 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -130,6 +130,7 @@ struct mVideoLogContext; struct GBACore { struct mCore d; struct GBAVideoSoftwareRenderer renderer; + struct GBAVideoRenderer dummyRenderer; #if defined(BUILD_GLES2) || defined(BUILD_GLES3) struct GBAVideoGLRenderer glRenderer; #endif @@ -382,9 +383,11 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c renderer = &gbacore->proxyRenderer.d; } #endif - if (renderer) { - GBAVideoAssociateRenderer(&gba->video, renderer); + if (!renderer) { + renderer = &gbacore->dummyRenderer; + GBAVideoDummyRendererCreate(renderer); } + GBAVideoAssociateRenderer(&gba->video, renderer); } } @@ -542,42 +545,39 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe static void _GBACoreReset(struct mCore* core) { struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = (struct GBA*) core->board; - if (gbacore->renderer.outputBuffer + struct GBAVideoRenderer* renderer = NULL; + if (gbacore->renderer.outputBuffer) { + renderer = &gbacore->renderer.d; + } + int fakeBool ATTRIBUTE_UNUSED; #if defined(BUILD_GLES2) || defined(BUILD_GLES3) - || gbacore->glRenderer.outputTex != (unsigned) -1 -#endif - ) { - struct GBAVideoRenderer* renderer = NULL; - if (gbacore->renderer.outputBuffer) { - renderer = &gbacore->renderer.d; - } - int fakeBool ATTRIBUTE_UNUSED; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) - if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { - mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); - renderer = &gbacore->glRenderer.d; - } else { - gbacore->glRenderer.scale = 1; - } + if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { + mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); + renderer = &gbacore->glRenderer.d; + } else { + gbacore->glRenderer.scale = 1; + } #endif #ifndef DISABLE_THREADING - if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) { - if (!core->videoLogger) { - core->videoLogger = &gbacore->threadProxy.d; - } - } -#endif -#ifndef MINIMAL_CORE - if (renderer && core->videoLogger) { - gbacore->proxyRenderer.logger = core->videoLogger; - GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); - renderer = &gbacore->proxyRenderer.d; - } -#endif - if (renderer) { - GBAVideoAssociateRenderer(&gba->video, renderer); + if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) { + if (!core->videoLogger) { + core->videoLogger = &gbacore->threadProxy.d; } } +#endif +#ifndef MINIMAL_CORE + if (renderer && core->videoLogger) { + gbacore->proxyRenderer.logger = core->videoLogger; + GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); + renderer = &gbacore->proxyRenderer.d; + } +#endif + if (!renderer) { + renderer = &gbacore->dummyRenderer; + GBAVideoDummyRendererCreate(renderer); + } + + GBAVideoAssociateRenderer(&gba->video, renderer); #ifndef MINIMAL_CORE int useAudioMixer; diff --git a/src/gba/video.c b/src/gba/video.c index 785cc80bd..2d2c7f453 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -53,23 +53,8 @@ MGBA_EXPORT const int GBAVideoObjSizes[16][2] = { { 0, 0 }, }; -static struct GBAVideoRenderer dummyRenderer = { - .init = GBAVideoDummyRendererInit, - .reset = GBAVideoDummyRendererReset, - .deinit = GBAVideoDummyRendererDeinit, - .writeVideoRegister = GBAVideoDummyRendererWriteVideoRegister, - .writeVRAM = GBAVideoDummyRendererWriteVRAM, - .writePalette = GBAVideoDummyRendererWritePalette, - .writeOAM = GBAVideoDummyRendererWriteOAM, - .drawScanline = GBAVideoDummyRendererDrawScanline, - .finishFrame = GBAVideoDummyRendererFinishFrame, - .getPixels = GBAVideoDummyRendererGetPixels, - .putPixels = GBAVideoDummyRendererPutPixels, -}; - void GBAVideoInit(struct GBAVideo* video) { - video->renderer = &dummyRenderer; - video->renderer->cache = NULL; + video->renderer = NULL; video->vram = anonymousMemoryMap(SIZE_VRAM); video->frameskip = 0; video->event.name = "GBA Video"; @@ -94,12 +79,16 @@ void GBAVideoReset(struct GBAVideo* video) { video->frameCounter = 0; video->frameskipCounter = 0; - video->renderer->vram = video->vram; video->shouldStall = 0; memset(video->palette, 0, sizeof(video->palette)); memset(video->oam.raw, 0, sizeof(video->oam.raw)); + if (!video->renderer) { + mLOG(GBA_VIDEO, FATAL, "No renderer associated"); + return; + } + video->renderer->vram = video->vram; video->renderer->reset(video->renderer); } @@ -108,9 +97,30 @@ void GBAVideoDeinit(struct GBAVideo* video) { mappedMemoryFree(video->vram, SIZE_VRAM); } +void GBAVideoDummyRendererCreate(struct GBAVideoRenderer* renderer) { + static const struct GBAVideoRenderer dummyRenderer = { + .init = GBAVideoDummyRendererInit, + .reset = GBAVideoDummyRendererReset, + .deinit = GBAVideoDummyRendererDeinit, + .writeVideoRegister = GBAVideoDummyRendererWriteVideoRegister, + .writeVRAM = GBAVideoDummyRendererWriteVRAM, + .writePalette = GBAVideoDummyRendererWritePalette, + .writeOAM = GBAVideoDummyRendererWriteOAM, + .drawScanline = GBAVideoDummyRendererDrawScanline, + .finishFrame = GBAVideoDummyRendererFinishFrame, + .getPixels = GBAVideoDummyRendererGetPixels, + .putPixels = GBAVideoDummyRendererPutPixels, + }; + memcpy(renderer, &dummyRenderer, sizeof(*renderer)); +} + void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer* renderer) { - video->renderer->deinit(video->renderer); - renderer->cache = video->renderer->cache; + if (video->renderer) { + video->renderer->deinit(video->renderer); + renderer->cache = video->renderer->cache; + } else { + renderer->cache = NULL; + } video->renderer = renderer; renderer->palette = video->palette; renderer->vram = video->vram; From d8c7e3e3c382545cccf908d99628657c6b1f1c4e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 18:34:55 -0700 Subject: [PATCH 08/36] GB/GBA Core: Simplify renderer setup --- src/gb/core.c | 8 +++---- src/gba/core.c | 64 +++++++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/gb/core.c b/src/gb/core.c index ebbacbfd2..e54db230f 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -63,8 +63,8 @@ static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = { struct mVideoLogContext; struct GBCore { struct mCore d; - struct GBVideoSoftwareRenderer renderer; struct GBVideoRenderer dummyRenderer; + struct GBVideoSoftwareRenderer renderer; #ifndef MINIMAL_CORE struct GBVideoProxyRenderer proxyRenderer; struct mVideoLogContext* logContext; @@ -104,6 +104,9 @@ static bool _GBCoreInit(struct mCore* core) { mRTCGenericSourceInit(&core->rtc, core); gb->memory.rtc = &core->rtc.d; + GBVideoDummyRendererCreate(&gbcore->dummyRenderer); + GBVideoAssociateRenderer(&gb->video, &gbcore->dummyRenderer); + GBVideoSoftwareRendererCreate(&gbcore->renderer); gbcore->renderer.outputBuffer = NULL; @@ -420,9 +423,6 @@ static void _GBCoreReset(struct mCore* core) { struct GB* gb = (struct GB*) core->board; if (gbcore->renderer.outputBuffer) { GBVideoAssociateRenderer(&gb->video, &gbcore->renderer.d); - } else { - GBVideoDummyRendererCreate(&gbcore->dummyRenderer); - GBVideoAssociateRenderer(&gb->video, &gbcore->dummyRenderer); } if (gb->memory.rom) { diff --git a/src/gba/core.c b/src/gba/core.c index c1aa5b047..f78786562 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -129,8 +129,8 @@ struct mVideoLogContext; struct GBACore { struct mCore d; - struct GBAVideoSoftwareRenderer renderer; struct GBAVideoRenderer dummyRenderer; + struct GBAVideoSoftwareRenderer renderer; #if defined(BUILD_GLES2) || defined(BUILD_GLES3) struct GBAVideoGLRenderer glRenderer; #endif @@ -183,6 +183,9 @@ static bool _GBACoreInit(struct mCore* core) { mRTCGenericSourceInit(&core->rtc, core); gba->rtcSource = &core->rtc.d; + GBAVideoDummyRendererCreate(&gbacore->dummyRenderer); + GBAVideoAssociateRenderer(&gba->video, &gbacore->dummyRenderer); + GBAVideoSoftwareRendererCreate(&gbacore->renderer); gbacore->renderer.outputBuffer = NULL; @@ -383,11 +386,9 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c renderer = &gbacore->proxyRenderer.d; } #endif - if (!renderer) { - renderer = &gbacore->dummyRenderer; - GBAVideoDummyRendererCreate(renderer); + if (renderer) { + GBAVideoAssociateRenderer(&gba->video, renderer); } - GBAVideoAssociateRenderer(&gba->video, renderer); } } @@ -545,40 +546,43 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe static void _GBACoreReset(struct mCore* core) { struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = (struct GBA*) core->board; - struct GBAVideoRenderer* renderer = NULL; - if (gbacore->renderer.outputBuffer) { - renderer = &gbacore->renderer.d; - } - int fakeBool ATTRIBUTE_UNUSED; + if (gbacore->renderer.outputBuffer #if defined(BUILD_GLES2) || defined(BUILD_GLES3) - if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { - mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); - renderer = &gbacore->glRenderer.d; - } else { - gbacore->glRenderer.scale = 1; - } + || gbacore->glRenderer.outputTex != (unsigned) -1 +#endif + ) { + struct GBAVideoRenderer* renderer = NULL; + if (gbacore->renderer.outputBuffer) { + renderer = &gbacore->renderer.d; + } + int fakeBool ATTRIBUTE_UNUSED; +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) + if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { + mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); + renderer = &gbacore->glRenderer.d; + } else { + gbacore->glRenderer.scale = 1; + } #endif #ifndef DISABLE_THREADING - if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) { - if (!core->videoLogger) { - core->videoLogger = &gbacore->threadProxy.d; + if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) { + if (!core->videoLogger) { + core->videoLogger = &gbacore->threadProxy.d; + } } - } #endif #ifndef MINIMAL_CORE - if (renderer && core->videoLogger) { - gbacore->proxyRenderer.logger = core->videoLogger; - GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); - renderer = &gbacore->proxyRenderer.d; - } + if (renderer && core->videoLogger) { + gbacore->proxyRenderer.logger = core->videoLogger; + GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer); + renderer = &gbacore->proxyRenderer.d; + } #endif - if (!renderer) { - renderer = &gbacore->dummyRenderer; - GBAVideoDummyRendererCreate(renderer); + if (renderer) { + GBAVideoAssociateRenderer(&gba->video, renderer); + } } - GBAVideoAssociateRenderer(&gba->video, renderer); - #ifndef MINIMAL_CORE int useAudioMixer; if (!gbacore->audioMixer && mCoreConfigGetIntValue(&core->config, "gba.audioHle", &useAudioMixer) && useAudioMixer) { From 26555959f25ba2d28e7be154e952a1779db8badb Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 19:22:18 -0500 Subject: [PATCH 09/36] Util: support non-string keys in hash tables --- include/mgba-util/table.h | 7 +++ src/util/table.c | 97 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/include/mgba-util/table.h b/include/mgba-util/table.h index a03fb3734..bd8d62993 100644 --- a/include/mgba-util/table.h +++ b/include/mgba-util/table.h @@ -35,12 +35,19 @@ void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer( void HashTableDeinit(struct Table* table); void* HashTableLookup(const struct Table*, const char* key); +void* HashTableLookupBinary(const struct Table*, const void* key, size_t keylen); void HashTableInsert(struct Table*, const char* key, void* value); +void HashTableInsertBinary(struct Table*, const void* key, size_t keylen, void* value); void HashTableRemove(struct Table*, const char* key); +void HashTableRemoveBinary(struct Table*, const void* key, size_t keylen); void HashTableClear(struct Table*); void HashTableEnumerate(const struct Table*, void (handler(const char* key, void* value, void* user)), void* user); +const char* HashTableSearch(const struct Table* table, bool (predicate(const char* key, const void* value, const void* user)), const void* user); +const char* HashTableSearchPointer(const struct Table* table, const void* value); +const char* HashTableSearchData(const struct Table* table, const void* value, size_t bytes); +const char* HashTableSearchString(const struct Table* table, const char* value); size_t HashTableSize(const struct Table*); CXX_GUARD_END diff --git a/src/util/table.c b/src/util/table.c index f4a85557f..0bfe24a87 100644 --- a/src/util/table.c +++ b/src/util/table.c @@ -12,7 +12,8 @@ #define TABLE_INITIAL_SIZE 8 #define TABLE_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == key -#define HASH_TABLE_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == hash && strncmp(LIST->list[(INDEX)].stringKey, key, LIST->list[(INDEX)].keylen) == 0 +#define HASH_TABLE_STRNCMP_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == hash && strncmp(LIST->list[(INDEX)].stringKey, key, LIST->list[(INDEX)].keylen) == 0 +#define HASH_TABLE_MEMCMP_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == hash && memcmp(LIST->list[(INDEX)].stringKey, key, LIST->list[(INDEX)].keylen) == 0 #define TABLE_LOOKUP_START(COMPARATOR, LIST, KEY) \ uint32_t entry = (KEY) & (table->tableSize - 1); \ @@ -176,7 +177,16 @@ void HashTableDeinit(struct Table* table) { void* HashTableLookup(const struct Table* table, const char* key) { uint32_t hash = hash32(key, strlen(key), 0); const struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_COMPARATOR, list, hash) { + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { + return lookupResult->value; + } TABLE_LOOKUP_END; + return 0; +} + +void* HashTableLookupBinary(const struct Table* table, const void* key, size_t keylen) { + uint32_t hash = hash32(key, keylen, 0); + const struct TableList* list; + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { return lookupResult->value; } TABLE_LOOKUP_END; return 0; @@ -185,7 +195,7 @@ void* HashTableLookup(const struct Table* table, const char* key) { void HashTableInsert(struct Table* table, const char* key, void* value) { uint32_t hash = hash32(key, strlen(key), 0); struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_COMPARATOR, list, hash) { + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { if (value != lookupResult->value) { if (table->deinitializer) { table->deinitializer(lookupResult->value); @@ -203,10 +213,40 @@ void HashTableInsert(struct Table* table, const char* key, void* value) { ++table->size; } +void HashTableInsertBinary(struct Table* table, const void* key, size_t keylen, void* value) { + uint32_t hash = hash32(key, keylen, 0); + struct TableList* list; + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { + if (value != lookupResult->value) { + if (table->deinitializer) { + table->deinitializer(lookupResult->value); + } + lookupResult->value = value; + } + return; + } TABLE_LOOKUP_END; + list = _resizeAsNeeded(table, list, hash); + list->list[list->nEntries].key = hash; + list->list[list->nEntries].stringKey = malloc(keylen); + memcpy(list->list[list->nEntries].stringKey, key, keylen); + list->list[list->nEntries].keylen = keylen; + list->list[list->nEntries].value = value; + ++list->nEntries; + ++table->size; +} + void HashTableRemove(struct Table* table, const char* key) { uint32_t hash = hash32(key, strlen(key), 0); struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_COMPARATOR, list, hash) { + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { + _removeItemFromList(table, list, i); // TODO: Move i out of the macro + } TABLE_LOOKUP_END; +} + +void HashTableRemoveBinary(struct Table* table, const void* key, size_t keylen) { + uint32_t hash = hash32(key, keylen, 0); + struct TableList* list; + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { _removeItemFromList(table, list, i); // TODO: Move i out of the macro } TABLE_LOOKUP_END; } @@ -240,6 +280,55 @@ void HashTableEnumerate(const struct Table* table, void (handler(const char* key } } +const char* HashTableSearch(const struct Table* table, bool (predicate(const char* key, const void* value, const void* user)), const void* user) { + size_t i; + const char* result = NULL; + for (i = 0; i < table->tableSize; ++i) { + const struct TableList* list = &table->table[i]; + size_t j; + for (j = 0; j < list->nEntries; ++j) { + if (predicate(list->list[j].stringKey, list->list[j].value, user)) { + return list->list[j].stringKey; + } + } + } + return result; +} + +static bool HashTableRefEqual(const char* key, const void* value, const void* user) { + UNUSED(key); + return value == user; +} + +const char* HashTableSearchPointer(const struct Table* table, const void* value) { + return HashTableSearch(table, HashTableRefEqual, value); +} + +struct HashTableSearchParam { + const void* value; + size_t bytes; +}; + +static bool HashTableMemcmp(const char* key, const void* value, const void* user) { + UNUSED(key); + const struct HashTableSearchParam* ref = user; + return memcmp(value, ref->value, ref->bytes) == 0; +} + +const char* HashTableSearchData(const struct Table* table, const void* value, const size_t bytes) { + struct HashTableSearchParam ref = { value, bytes }; + return HashTableSearch(table, HashTableMemcmp, &ref); +} + +static bool HashTableStrcmp(const char* key, const void* value, const void* user) { + UNUSED(key); + return strcmp(value, user) == 0; +} + +const char* HashTableSearchString(const struct Table* table, const char* value) { + return HashTableSearch(table, HashTableStrcmp, value); +} + size_t HashTableSize(const struct Table* table) { return table->size; } From 044710c3a809f48f95dfd1be160bc219461e3aea Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 20:00:59 -0500 Subject: [PATCH 10/36] Debugger: reverse symbol lookup --- include/mgba/internal/debugger/symbols.h | 1 + src/debugger/cli-debugger.c | 52 +++++++++++++++++++++++- src/debugger/symbols.c | 16 +++++++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/include/mgba/internal/debugger/symbols.h b/include/mgba/internal/debugger/symbols.h index 30801a446..12af32564 100644 --- a/include/mgba/internal/debugger/symbols.h +++ b/include/mgba/internal/debugger/symbols.h @@ -16,6 +16,7 @@ struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void); void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols*); bool mDebuggerSymbolLookup(const struct mDebuggerSymbols*, const char* name, int32_t* value, int* segment); +const char* mDebuggerSymbolReverseLookup(const struct mDebuggerSymbols*, int32_t value, int segment); void mDebuggerSymbolAdd(struct mDebuggerSymbols*, const char* name, int32_t value, int segment); void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name); diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 178457c40..dae2bc527 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -72,6 +72,8 @@ static void _source(struct CLIDebugger*, struct CLIDebugVector*); static void _backtrace(struct CLIDebugger*, struct CLIDebugVector*); static void _finish(struct CLIDebugger*, struct CLIDebugVector*); static void _setStackTraceMode(struct CLIDebugger*, struct CLIDebugVector*); +static void _setSymbol(struct CLIDebugger*, struct CLIDebugVector*); +static void _findSymbol(struct CLIDebugger*, struct CLIDebugVector*); static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "backtrace", _backtrace, "i", "Print backtrace of all or specified frames" }, @@ -92,8 +94,10 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "r/1", _readByte, "I", "Read a byte from a specified offset" }, { "r/2", _readHalfword, "I", "Read a halfword from a specified offset" }, { "r/4", _readWord, "I", "Read a word from a specified offset" }, - { "stack", _setStackTraceMode, "S", "Changes the stack tracing mode" }, + { "set", _setSymbol, "SI", "Assign a symbol to an address" }, + { "stack", _setStackTraceMode, "S", "Change the stack tracing mode" }, { "status", _printStatus, "", "Print the current status" }, + { "symbol", _findSymbol, "I", "Find the symbol name for an address" }, { "trace", _trace, "Is", "Trace a number of instructions" }, { "w/1", _writeByte, "II", "Write a byte at a specified offset" }, { "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" }, @@ -1178,10 +1182,11 @@ static void _backtrace(struct CLIDebugger* debugger, struct CLIDebugVector* dv) frames = dv->intValue; } ssize_t i; + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; for (i = 0; i < frames; ++i) { char trace[1024]; size_t traceSize = sizeof(trace) - 2; - mStackTraceFormatFrame(stack, i, trace, &traceSize); + mStackTraceFormatFrame(stack, symbolTable, i, trace, &traceSize); debugger->backend->printf(debugger->backend, "%s", trace); } } @@ -1232,3 +1237,46 @@ static void _setStackTraceMode(struct CLIDebugger* debugger, struct CLIDebugVect debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); } } + +static void _setSymbol(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; + if (!symbolTable) { + debugger->backend->printf(debugger->backend, "No symbol table available.\n"); + return; + } + if (!dv || !dv->next) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + return; + } + if (dv->type != CLIDV_CHAR_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + mDebuggerSymbolAdd(symbolTable, dv->charValue, dv->next->intValue, dv->next->segmentValue); +} + +static void _findSymbol(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; + if (!symbolTable) { + debugger->backend->printf(debugger->backend, "No symbol table available.\n"); + return; + } + if (!dv) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + return; + } + if (dv->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + const char* name = mDebuggerSymbolReverseLookup(symbolTable, dv->intValue, dv->segmentValue); + if (name) { + if (dv->segmentValue >= 0) { + debugger->backend->printf(debugger->backend, " 0x%02X:%08X = %s\n", dv->segmentValue, dv->intValue, name); + } else { + debugger->backend->printf(debugger->backend, " 0x%08X = %s\n", dv->intValue, name); + } + } else { + debugger->backend->printf(debugger->backend, "Not found.\n"); + } +} diff --git a/src/debugger/symbols.c b/src/debugger/symbols.c index 26d392c3b..1cfa246a3 100644 --- a/src/debugger/symbols.c +++ b/src/debugger/symbols.c @@ -7,6 +7,7 @@ #include #include +#include #include struct mDebuggerSymbol { @@ -16,16 +17,19 @@ struct mDebuggerSymbol { struct mDebuggerSymbols { struct Table names; + struct Table reverse; }; struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void) { struct mDebuggerSymbols* st = malloc(sizeof(*st)); HashTableInit(&st->names, 0, free); + HashTableInit(&st->reverse, 0, free); return st; } void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols* st) { HashTableDeinit(&st->names); + HashTableDeinit(&st->reverse); free(st); } @@ -39,15 +43,25 @@ bool mDebuggerSymbolLookup(const struct mDebuggerSymbols* st, const char* name, return true; } +const char* mDebuggerSymbolReverseLookup(const struct mDebuggerSymbols* st, int32_t value, int segment) { + struct mDebuggerSymbol sym = { value, segment }; + return HashTableLookupBinary(&st->reverse, &sym, sizeof(sym)); +} + void mDebuggerSymbolAdd(struct mDebuggerSymbols* st, const char* name, int32_t value, int segment) { struct mDebuggerSymbol* sym = malloc(sizeof(*sym)); sym->value = value; sym->segment = segment; HashTableInsert(&st->names, name, sym); + HashTableInsertBinary(&st->reverse, sym, sizeof(*sym), strdup(name)); } void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* name) { - HashTableRemove(&st->names, name); + struct mDebuggerSymbol* sym = HashTableLookup(&st->names, name); + if (sym) { + HashTableRemoveBinary(&st->reverse, sym, sizeof(*sym)); + HashTableRemove(&st->names, name); + } } void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols* st, struct VFile* vf) { From 002e9c8802e93766f4cd544432779e57f706a929 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 20:01:23 -0500 Subject: [PATCH 11/36] Debugger: look up symbols in stack traces --- include/mgba/internal/debugger/stack-trace.h | 8 ++- src/debugger/stack-trace.c | 53 +++++++++++++++----- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/include/mgba/internal/debugger/stack-trace.h b/include/mgba/internal/debugger/stack-trace.h index 443faa64c..11268aae3 100644 --- a/include/mgba/internal/debugger/stack-trace.h +++ b/include/mgba/internal/debugger/stack-trace.h @@ -14,6 +14,8 @@ CXX_GUARD_START #include #include +struct mDebuggerSymbols; + enum mStackTraceMode { STACK_TRACE_DISABLED = 0, STACK_TRACE_ENABLED = 1, @@ -23,8 +25,11 @@ enum mStackTraceMode { }; struct mStackFrame { + int callSegment; uint32_t callAddress; + int entrySegment; uint32_t entryAddress; + int frameBaseSegment; uint32_t frameBaseAddress; void* regs; bool finished; @@ -47,8 +52,9 @@ void mStackTraceDeinit(struct mStackTrace* stack); void mStackTraceClear(struct mStackTrace* stack); size_t mStackTraceGetDepth(struct mStackTrace* stack); struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs); +struct mStackFrame* mStackTracePushSegmented(struct mStackTrace* stack, int pcSegment, uint32_t pc, int destSegment, uint32_t destAddress, int spSegment, uint32_t sp, void* regs); struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t frame); -void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out, size_t* length); +void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* st, uint32_t frame, char* out, size_t* length); void mStackTracePop(struct mStackTrace* stack); CXX_GUARD_END diff --git a/src/debugger/stack-trace.c b/src/debugger/stack-trace.c index 4d6357698..a10c0bde8 100644 --- a/src/debugger/stack-trace.c +++ b/src/debugger/stack-trace.c @@ -4,6 +4,7 @@ * 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 +#include #include @@ -40,8 +41,11 @@ size_t mStackTraceGetDepth(struct mStackTrace* stack) { struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs) { struct mStackFrame* frame = mStackFramesAppend(&stack->stack); + frame->callSegment = -1; frame->callAddress = pc; + frame->entrySegment = -1; frame->entryAddress = destAddress; + frame->frameBaseSegment = -1; frame->frameBaseAddress = sp; frame->regs = malloc(stack->registersSize); frame->finished = false; @@ -51,6 +55,14 @@ struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint return frame; } +struct mStackFrame* mStackTracePushSegmented(struct mStackTrace* stack, int pcSegment, uint32_t pc, int destSegment, uint32_t destAddress, int spSegment, uint32_t sp, void* regs) { + struct mStackFrame* frame = mStackTracePush(stack, pc, destAddress, sp, regs); + frame->callSegment = pcSegment; + frame->entrySegment = destSegment; + frame->frameBaseSegment = spSegment; + return frame; +} + struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t frame) { size_t depth = mStackTraceGetDepth(stack); if (frame >= depth) { @@ -59,20 +71,26 @@ struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t fram return mStackFramesGetPointer(&stack->stack, depth - frame - 1); } -void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out, size_t* length) { +void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* st, uint32_t frame, char* out, size_t* length) { struct mStackFrame* stackFrame = mStackTraceGetFrame(stack, frame); struct mStackFrame* prevFrame = mStackTraceGetFrame(stack, frame + 1); size_t written = snprintf(out, *length, "#%d ", frame); CHECK_LENGTH(); - if (prevFrame) { - written += snprintf(out + written, *length - written, "0x%08X ", prevFrame->entryAddress); - CHECK_LENGTH(); - } if (!stackFrame) { - written += snprintf(out + written, *length - written, "no stack frame available)\n"); + written += snprintf(out + written, *length - written, "(no stack frame available)\n"); *length = written; return; - } else if (stack->formatRegisters) { + } + const char* functionName = mDebuggerSymbolReverseLookup(st, stackFrame->entryAddress, stackFrame->entrySegment); + if (functionName) { + written += snprintf(out + written, *length - written, "%s ", functionName); + } else if (prevFrame->entrySegment >= 0) { + written += snprintf(out + written, *length - written, "0x%02X:%08X ", stackFrame->entrySegment, stackFrame->entryAddress); + } else { + written += snprintf(out + written, *length - written, "0x%08X ", stackFrame->entryAddress); + } + CHECK_LENGTH(); + if (stack->formatRegisters) { written += snprintf(out + written, *length - written, "("); CHECK_LENGTH(); char buffer[1024]; @@ -81,16 +99,27 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out written += snprintf(out + written, *length - written, "%s)\n ", buffer); CHECK_LENGTH(); } + if (stackFrame->callSegment >= 0) { + written += snprintf(out + written, *length - written, "at 0x%02X:%08X", stackFrame->callSegment, stackFrame->callAddress); + } else { + written += snprintf(out + written, *length - written, "at 0x%08X", stackFrame->callAddress); + } + CHECK_LENGTH(); if (prevFrame) { int32_t offset = stackFrame->callAddress - prevFrame->entryAddress; if (offset >= 0) { - written += snprintf(out + written, *length - written, "at 0x%08X [0x%08X+%d]\n", stackFrame->callAddress, prevFrame->entryAddress, offset); - } else { - written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); + functionName = mDebuggerSymbolReverseLookup(st, prevFrame->entryAddress, prevFrame->entrySegment); + if (functionName) { + written += snprintf(out + written, *length - written, " [%s+%d]", functionName, offset); + } else if (stackFrame->entrySegment >= 0) { + written += snprintf(out + written, *length - written, " [0x%02X:%08X+%d]", prevFrame->entrySegment, prevFrame->entryAddress, offset); + } else { + written += snprintf(out + written, *length - written, " [0x%08X+%d]", prevFrame->entryAddress, offset); + } } - } else { - written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); } + CHECK_LENGTH(); + written += snprintf(out + written, *length - written, "\n"); *length = written; } From a98c01bafc031dc9bfa379b960bc88f1731a62e3 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 17:24:06 -0500 Subject: [PATCH 12/36] Debugger: add support for simple command scripts --- CHANGES | 1 + include/mgba/internal/debugger/cli-debugger.h | 5 + src/debugger/CMakeLists.txt | 4 + src/debugger/cli-debugger-scripting.c | 137 ++++++++++++++++++ src/debugger/cli-debugger.c | 7 +- src/platform/sdl/main.c | 5 +- 6 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/debugger/cli-debugger-scripting.c diff --git a/CHANGES b/CHANGES index 3d666de74..938ba84d4 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Features: - Add WebP and APNG recording - Support for unlicensed Pokemon Jade/Diamond Game Boy mapper - Stack tracing tools in ARM debugger (by ahigerd) + - Command scripts for CLI debugger (by ahigerd) Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation diff --git a/include/mgba/internal/debugger/cli-debugger.h b/include/mgba/internal/debugger/cli-debugger.h index 367b7bf64..12e987468 100644 --- a/include/mgba/internal/debugger/cli-debugger.h +++ b/include/mgba/internal/debugger/cli-debugger.h @@ -95,6 +95,11 @@ void CLIDebuggerAttachBackend(struct CLIDebugger*, struct CLIDebuggerBackend*); bool CLIDebuggerTabComplete(struct CLIDebugger*, const char* token, bool initial, size_t len); +bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_t count); +#if ENABLE_SCRIPTING +void CLIDebuggerScriptEngineInstall(struct mScriptBridge* sb); +#endif + CXX_GUARD_END #endif diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index a5c40eb31..dde31390f 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -6,6 +6,10 @@ set(SOURCE_FILES symbols.c stack-trace.c) +if(ENABLE_SCRIPTING) + list(APPEND SOURCE_FILES cli-debugger-scripting.c) +endif() + set(TEST_FILES test/lexer.c test/parser.c) diff --git a/src/debugger/cli-debugger-scripting.c b/src/debugger/cli-debugger-scripting.c new file mode 100644 index 000000000..d61229f64 --- /dev/null +++ b/src/debugger/cli-debugger-scripting.c @@ -0,0 +1,137 @@ +/* Copyright (c) 2013-2020 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 +#include +#include + +#include +#include + +static const char* CLIScriptEngineName(struct mScriptEngine*); +static bool CLIScriptEngineInit(struct mScriptEngine*, struct mScriptBridge*); +static void CLIScriptEngineDeinit(struct mScriptEngine*); +static bool CLIScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf); +static bool CLIScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf); +static void CLIScriptEngineRun(struct mScriptEngine*); +static bool CLIScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out); +static void CLIScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); + +struct CLIScriptStatement { + char* command; + size_t commandLen; +}; + +DECLARE_VECTOR(CLIScript, struct CLIScriptStatement); +DEFINE_VECTOR(CLIScript, struct CLIScriptStatement); + +struct CLIScriptEngine { + struct mScriptEngine d; + struct mScriptBridge* sb; + struct CLIScript script; +}; + +static void CLIScriptEngineClear(struct CLIScriptEngine* engine) { + size_t i = CLIScriptSize(&engine->script); + while (i-- > 0) { + struct CLIScriptStatement* statement = CLIScriptGetPointer(&engine->script, i); + free(statement->command); + } + CLIScriptClear(&engine->script); +} + +struct CLIScriptEngine* CLICreateScriptEngine(void) { + struct CLIScriptEngine* engine = malloc(sizeof(*engine)); + engine->d.name = CLIScriptEngineName; + engine->d.init = CLIScriptEngineInit; + engine->d.deinit = CLIScriptEngineDeinit; + engine->d.isScript = CLIScriptEngineIsScript; + engine->d.loadScript = CLIScriptEngineLoadScript; + engine->d.run = CLIScriptEngineRun; + engine->d.lookupSymbol = CLIScriptEngineLookupSymbol; + engine->d.debuggerEntered = CLIScriptDebuggerEntered; + engine->sb = NULL; + return engine; +} + +void CLIDebuggerScriptEngineInstall(struct mScriptBridge* sb) { + struct CLIScriptEngine* se = CLICreateScriptEngine(); + mScriptBridgeInstallEngine(sb, &se->d); +} + +const char* CLIScriptEngineName(struct mScriptEngine* se) { + UNUSED(se); + return "cli-debugger"; +} + +bool CLIScriptEngineInit(struct mScriptEngine* se, struct mScriptBridge* sb) { + struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se; + engine->sb = sb; + CLIScriptInit(&engine->script, 0); + return true; +} + +void CLIScriptEngineDeinit(struct mScriptEngine* se) { + struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se; + CLIScriptEngineClear(engine); + CLIScriptDeinit(&engine->script); + free(se); +} + +bool CLIScriptEngineIsScript(struct mScriptEngine* se, const char* name, struct VFile* vf) { + UNUSED(se); + UNUSED(vf); + return endswith(name, ".mrc"); +} + +bool CLIScriptEngineLoadScript(struct mScriptEngine* se, const char* name, struct VFile* vf) { + UNUSED(name); + struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se; + char buffer[256]; + ssize_t size; + CLIScriptEngineClear(engine); + struct CLIScriptStatement* statement; + while ((size = vf->readline(vf, buffer, sizeof(buffer))) > 0) { + if (buffer[size - 1] == '\n') { + --size; + } + statement = CLIScriptAppend(&engine->script); + statement->command = strndup(buffer, size); + statement->commandLen = size; + } + return true; +} + +void CLIScriptEngineRun(struct mScriptEngine* se) { + struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se; + struct CLIDebugger* debugger = (struct CLIDebugger*) mScriptBridgeGetDebugger(engine->sb); + struct CLIScriptStatement* statement; + size_t statementCount = CLIScriptSize(&engine->script); + size_t i; + for (i = 0; i < statementCount; i++) { + statement = CLIScriptGetPointer(&engine->script, i); + CLIDebuggerRunCommand(debugger, statement->command, statement->commandLen); + } +} + +bool CLIScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) { + UNUSED(se); + UNUSED(name); + UNUSED(out); + return false; +} + +void CLIScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { + UNUSED(reason); + UNUSED(info); + struct CLIScriptEngine* engine = (struct CLIScriptEngine*) se; + + struct mDebugger* debugger = mScriptBridgeGetDebugger(engine->sb); + if (!debugger) { + return; + } + + // TODO: CLIDebuggerEntered(reason, info); +} diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index dae2bc527..dcdd33a65 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -137,6 +137,7 @@ static struct CLIDebuggerCommandAlias _debuggerCommandAliases[] = { { "p/x", "print/x" }, { "q", "quit" }, { "w", "watch" }, + { ".", "source" }, { 0, 0 } }; @@ -944,7 +945,7 @@ static int _tryCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandS return -1; } -static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count) { +bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_t count) { const char* firstSpace = strchr(line, ' '); size_t cmdLength; if (firstSpace) { @@ -984,10 +985,10 @@ static void _commandLine(struct mDebugger* debugger) { if (line[0] == '\n') { line = cliDebugger->backend->historyLast(cliDebugger->backend, &len); if (line && len) { - _parse(cliDebugger, line, len); + CLIDebuggerRunCommand(cliDebugger, line, len); } } else { - _parse(cliDebugger, line, len); + CLIDebuggerRunCommand(cliDebugger, line, len); cliDebugger->backend->historyAppend(cliDebugger->backend, line); } } diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index deda42506..2b2704a9c 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -210,6 +210,9 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { #ifdef ENABLE_PYTHON mPythonSetup(bridge); #endif +#ifdef USE_DEBUGGERS + CLIDebuggerScriptEngineInstall(bridge); +#endif #endif #ifdef USE_DEBUGGERS @@ -223,7 +226,7 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { #endif mDebuggerAttach(debugger, renderer->core); mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL); - #ifdef ENABLE_SCRIPTING +#ifdef ENABLE_SCRIPTING mScriptBridgeSetDebugger(bridge, debugger); #endif } From 1756baae74630583173793a3128c39b6473a6ec9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 19:03:42 -0700 Subject: [PATCH 13/36] Debugger: Fix Python build --- include/mgba/internal/debugger/cli-debugger.h | 2 +- src/debugger/cli-debugger.c | 2 +- src/debugger/debugger.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mgba/internal/debugger/cli-debugger.h b/include/mgba/internal/debugger/cli-debugger.h index 12e987468..6175ce628 100644 --- a/include/mgba/internal/debugger/cli-debugger.h +++ b/include/mgba/internal/debugger/cli-debugger.h @@ -96,7 +96,7 @@ void CLIDebuggerAttachBackend(struct CLIDebugger*, struct CLIDebuggerBackend*); bool CLIDebuggerTabComplete(struct CLIDebugger*, const char* token, bool initial, size_t len); bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_t count); -#if ENABLE_SCRIPTING +#ifdef ENABLE_SCRIPTING void CLIDebuggerScriptEngineInstall(struct mScriptBridge* sb); #endif diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index dcdd33a65..691474f3a 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -13,7 +13,7 @@ #include #include -#if ENABLE_SCRIPTING +#ifdef ENABLE_SCRIPTING #include #endif diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 675e04698..169123451 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -14,7 +14,7 @@ #include #endif -#if ENABLE_SCRIPTING +#ifdef ENABLE_SCRIPTING #include #endif From 4617c40ac4647d2c9526e39bb6ff9b7d12fac1e0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 19:08:45 -0700 Subject: [PATCH 14/36] 3DS: Migrate to userAppInit --- src/platform/3ds/ctru-heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/3ds/ctru-heap.c b/src/platform/3ds/ctru-heap.c index ccd38090e..25e606c1d 100644 --- a/src/platform/3ds/ctru-heap.c +++ b/src/platform/3ds/ctru-heap.c @@ -15,7 +15,7 @@ size_t romBufferSize; FS_Archive sdmcArchive; -__attribute__((constructor)) static void init(void) { +void userAppInit(void) { FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); romBuffer = malloc(0x02000000); From 0d6946dceecb7d364c13258b6d9cfc8a9eb20bd1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 19:16:45 -0700 Subject: [PATCH 15/36] 3DS: Migrate to libctru CondVar --- include/mgba-util/platform/3ds/threading.h | 41 +++++----------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/include/mgba-util/platform/3ds/threading.h b/include/mgba-util/platform/3ds/threading.h index 6ce2432b1..27e2b39d1 100644 --- a/include/mgba-util/platform/3ds/threading.h +++ b/include/mgba-util/platform/3ds/threading.h @@ -15,11 +15,7 @@ typedef ThreadFunc ThreadEntry; typedef LightLock Mutex; -typedef struct { - Mutex mutex; - Handle semaphore; - u32 waiting; -} Condition; +typedef CondVar Condition; static inline int MutexInit(Mutex* mutex) { LightLock_Init(mutex); @@ -46,47 +42,26 @@ static inline int MutexUnlock(Mutex* mutex) { } static inline int ConditionInit(Condition* cond) { - Result res = MutexInit(&cond->mutex); - if (res) { - return res; - } - res = svcCreateSemaphore(&cond->semaphore, 0, 1); - cond->waiting = 0; - return res; + CondVar_Init(cond); + return 0; } static inline int ConditionDeinit(Condition* cond) { - return svcCloseHandle(cond->semaphore); + UNUSED(cond); + return 0; } static inline int ConditionWait(Condition* cond, Mutex* mutex) { - MutexLock(&cond->mutex); - ++cond->waiting; - MutexUnlock(mutex); - MutexUnlock(&cond->mutex); - svcWaitSynchronization(cond->semaphore, U64_MAX); - MutexLock(mutex); + CondVar_Wait(cond, mutex); return 0; } static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { - MutexLock(&cond->mutex); - ++cond->waiting; - MutexUnlock(mutex); - MutexUnlock(&cond->mutex); - svcWaitSynchronization(cond->semaphore, timeoutMs * 10000000LL); - MutexLock(mutex); - return 0; + return CondVar_WaitTimeout(cond, mutex, timeoutMs * 10000000LL); } static inline int ConditionWake(Condition* cond) { - MutexLock(&cond->mutex); - if (cond->waiting) { - --cond->waiting; - s32 count = 0; - svcReleaseSemaphore(&count, cond->semaphore, 1); - } - MutexUnlock(&cond->mutex); + CondVar_Signal(cond); return 0; } From cc06e177bbab013167c620a9bd860f4f6c120564 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 19:44:13 -0700 Subject: [PATCH 16/36] 3DS: Make pre-init garbage slightly less bad --- src/platform/3ds/main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 25afcd004..2f26c49d1 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -122,6 +122,15 @@ static bool _initGpu(void) { return false; } + C3D_FrameBegin(0); + C3D_FrameDrawOn(bottomScreen[0]); + C3D_RenderTargetClear(bottomScreen[0], C3D_CLEAR_COLOR, 0, 0); + C3D_FrameDrawOn(topScreen[0]); + C3D_RenderTargetClear(topScreen[0], C3D_CLEAR_COLOR, 0, 0); + C3D_RenderTargetSetOutput(topScreen[0], GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_RenderTargetSetOutput(bottomScreen[0], GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); + C3D_FrameEnd(0); + if (!C3D_TexInitVRAM(&upscaleBufferTex, 512, 512, GPU_RGB8)) { return false; } @@ -130,6 +139,11 @@ static bool _initGpu(void) { return false; } + C3D_FrameBegin(0); + C3D_FrameDrawOn(upscaleBuffer); + C3D_RenderTargetClear(upscaleBuffer, C3D_CLEAR_COLOR, 0, 0); + C3D_FrameEnd(0); + return ctrInitGpu(); } From 21a23b3a7a862180dd057321c5fb317c7d9865c4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 22:01:11 -0700 Subject: [PATCH 17/36] 3DS: Use "wide mode" where applicable for slightly better filtering --- CHANGES | 1 + src/platform/3ds/main.c | 43 ++++++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 938ba84d4..90ae34920 100644 --- a/CHANGES +++ b/CHANGES @@ -56,6 +56,7 @@ Other fixes: - SM83: Simplify register pair access on big endian - Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830) Misc: + - 3DS: Use "wide mode" where applicable for slightly better filtering - GB: Allow pausing event loop while CPU is blocked - GBA: Allow pausing event loop while CPU is blocked - Debugger: Keep track of global cycle count diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 2f26c49d1..6ffe46da2 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -114,8 +115,13 @@ static bool _initGpu(void) { return false; } - topScreen[0] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); - topScreen[1] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); + if (gfxIsWide()) { + topScreen[0] = C3D_RenderTargetCreate(240, 800, GPU_RB_RGB8, 0); + topScreen[1] = C3D_RenderTargetCreate(240, 800, GPU_RB_RGB8, 0); + } else { + topScreen[0] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); + topScreen[1] = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, 0); + } bottomScreen[0] = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); bottomScreen[1] = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); if (!topScreen[0] || !topScreen[1] || !bottomScreen[0] || !bottomScreen[1]) { @@ -470,6 +476,7 @@ static u32 _setupTex(int out, bool faded) { static void _drawTex(struct mCore* core, bool faded, bool both) { unsigned screen_w, screen_h; + bool isWide = screenMode >= SM_PA_TOP && gfxIsWide(); switch (screenMode) { case SM_PA_BOTTOM: C3D_FrameDrawOn(bottomScreen[doubleBuffer]); @@ -478,7 +485,7 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { break; case SM_PA_TOP: C3D_FrameDrawOn(topScreen[doubleBuffer]); - screen_w = 400; + screen_w = isWide ? 800 : 400; screen_h = 240; break; default: @@ -487,6 +494,7 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { screen_h = 512; break; } + int wide = isWide ? 2 : 1; unsigned corew, coreh; core->desiredVideoDimensions(core, &corew, &coreh); @@ -497,24 +505,16 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { w = GB_VIDEO_HORIZONTAL_PIXELS; h = GB_VIDEO_VERTICAL_PIXELS; } - int innerw = w; - int innerh = h; - // Get greatest common divisor - while (w != 0) { - int temp = h % w; - h = w; - w = temp; - } - int gcd = h; - unsigned aspectw = innerw / gcd; - unsigned aspecth = innerh / gcd; + int aspectw = w; + int aspecth = h; + int gcd = reduceFraction(&aspecth, &aspectw); int x = 0; int y = 0; switch (screenMode) { case SM_PA_TOP: case SM_PA_BOTTOM: - w = corew; + w = corew * wide; h = coreh; x = (screen_w - w) / 2; y = (screen_h - h) / 2; @@ -544,8 +544,8 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { } ctrFlushBatch(); - innerw = corew; - innerh = coreh; + int innerw = corew; + int innerh = coreh; corew = w; coreh = h; screen_h = 240; @@ -554,7 +554,7 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { screen_w = 320; } else { C3D_FrameDrawOn(topScreen[doubleBuffer]); - screen_w = 400; + screen_w = isWide ? 800 : 400; } ctrSetViewportSize(screen_w, screen_h, true); @@ -566,6 +566,7 @@ static void _drawTex(struct mCore* core, bool faded, bool both) { case SM_AF_BOTTOM: afw = screen_w / (float) aspectw; afh = screen_h / (float) aspecth; + innerw *= wide; if (afw * aspecth > screen_h) { w = innerw * afh / gcd; h = innerh * afh / gcd; @@ -846,6 +847,12 @@ int main() { gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, true); + u8 model = 0; + CFGU_GetSystemModel(&model); + if (model != 3 /* o2DS */) { + gfxSetWide(true); + } + if (!_initGpu()) { outputTexture[0].data = 0; _cleanup(); From 580aec949cb5221b1cdc02b3f04f11537a09c181 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jul 2020 22:21:33 -0700 Subject: [PATCH 18/36] 3DS: Fix garbage on borders of scaled screens --- CHANGES | 1 + src/platform/3ds/main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 90ae34920..49f4f8099 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Emulation fixes: - SM83: Emulate HALT bug - SM83: Fix flags on little endian PowerPC Other fixes: + - 3DS: Fix garbage on borders of scaled screens - All: Improve export headers (fixes mgba.io/i/1738) - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) - All: Correct more format strings on Windows (fixes mgba.io/i/1817) diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index 6ffe46da2..3b5357ba8 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -859,6 +859,7 @@ int main() { return 1; } + C3D_TexSetWrap(&upscaleBufferTex, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR); int i; From 9fc8fdb73ba9756a775178ac8128cba2732dea0b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Aug 2020 03:35:14 -0700 Subject: [PATCH 19/36] Qt: Begin mopping up warnings --- src/platform/qt/Window.cpp | 43 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 5d3f4d920..1b281241e 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -582,7 +582,7 @@ void Window::keyReleaseEvent(QKeyEvent* event) { event->accept(); } -void Window::resizeEvent(QResizeEvent* event) { +void Window::resizeEvent(QResizeEvent*) { if (!isFullScreen()) { m_config->setOption("height", m_screenWidget->height()); m_config->setOption("width", m_screenWidget->width()); @@ -874,7 +874,8 @@ void Window::gameFailed() { fail->show(); } -void Window::unimplementedBiosCall(int call) { +void Window::unimplementedBiosCall(int) { + // TODO: Mention which call? if (m_hitUnimplementedBiosCall) { return; } @@ -1126,7 +1127,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addAction(tr("Load &patch..."), "loadPatch", this, &Window::selectPatch, "file"); #ifdef M_CORE_GBA - Action* bootBIOS = m_actions.addAction(tr("Boot BIOS"), "bootBIOS", [this]() { + m_actions.addAction(tr("Boot BIOS"), "bootBIOS", [this]() { setController(m_manager->loadBIOS(PLATFORM_GBA, m_config->getOption("gba.bios")), QString()); }, "file"); #endif @@ -1137,7 +1138,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_platformActions.insert(PLATFORM_GBA, scanCard); #endif - Action* romInfo = addGameAction(tr("ROM &info..."), "romInfo", openControllerTView(), "file"); + addGameAction(tr("ROM &info..."), "romInfo", openControllerTView(), "file"); m_actions.addMenu(tr("Recent"), "mru", "file"); m_actions.addSeparator("file"); @@ -1242,7 +1243,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_controller->stop(); }, "emu"); - Action* yank = addGameAction(tr("Yank game pak"), "yank", [this]() { + addGameAction(tr("Yank game pak"), "yank", [this]() { m_controller->yankPak(); }, "emu"); @@ -1275,7 +1276,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addMenu(tr("Fast forward speed"), "fastForwardSpeed", "emu"); ConfigOption* ffspeed = m_config->addOption("fastForwardRatio"); - ffspeed->connect([this](const QVariant& value) { + ffspeed->connect([this](const QVariant&) { reloadConfig(); }, this); ffspeed->addValue(tr("Unbounded"), -1.0f, &m_actions, "fastForwardSpeed"); @@ -1305,14 +1306,14 @@ void Window::setupMenu(QMenuBar* menubar) { ConfigOption* videoSync = m_config->addOption("videoSync"); videoSync->addBoolean(tr("Sync to &video"), &m_actions, "emu"); - videoSync->connect([this](const QVariant& value) { + videoSync->connect([this](const QVariant&) { reloadConfig(); }, this); m_config->updateOption("videoSync"); ConfigOption* audioSync = m_config->addOption("audioSync"); audioSync->addBoolean(tr("Sync to &audio"), &m_actions, "emu"); - audioSync->connect([this](const QVariant& value) { + audioSync->connect([this](const QVariant&) { reloadConfig(); }, this); m_config->updateOption("audioSync"); @@ -1425,7 +1426,7 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addMenu(tr("Frame&skip"),"skip", "av"); ConfigOption* skip = m_config->addOption("frameskip"); - skip->connect([this](const QVariant& value) { + skip->connect([this](const QVariant&) { reloadConfig(); }, this); for (int i = 0; i <= 10; ++i) { @@ -1564,62 +1565,62 @@ void Window::setupMenu(QMenuBar* menubar) { }, "tools"); ConfigOption* skipBios = m_config->addOption("skipBios"); - skipBios->connect([this](const QVariant& value) { + skipBios->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* useBios = m_config->addOption("useBios"); - useBios->connect([this](const QVariant& value) { + useBios->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* buffers = m_config->addOption("audioBuffers"); - buffers->connect([this](const QVariant& value) { + buffers->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* sampleRate = m_config->addOption("sampleRate"); - sampleRate->connect([this](const QVariant& value) { + sampleRate->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* volume = m_config->addOption("volume"); - volume->connect([this](const QVariant& value) { + volume->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* volumeFf = m_config->addOption("fastForwardVolume"); - volumeFf->connect([this](const QVariant& value) { + volumeFf->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* muteFf = m_config->addOption("fastForwardMute"); - muteFf->connect([this](const QVariant& value) { + muteFf->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* rewindEnable = m_config->addOption("rewindEnable"); - rewindEnable->connect([this](const QVariant& value) { + rewindEnable->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* rewindBufferCapacity = m_config->addOption("rewindBufferCapacity"); - rewindBufferCapacity->connect([this](const QVariant& value) { + rewindBufferCapacity->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* allowOpposingDirections = m_config->addOption("allowOpposingDirections"); - allowOpposingDirections->connect([this](const QVariant& value) { + allowOpposingDirections->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* saveStateExtdata = m_config->addOption("saveStateExtdata"); - saveStateExtdata->connect([this](const QVariant& value) { + saveStateExtdata->connect([this](const QVariant&) { reloadConfig(); }, this); ConfigOption* loadStateExtdata = m_config->addOption("loadStateExtdata"); - loadStateExtdata->connect([this](const QVariant& value) { + loadStateExtdata->connect([this](const QVariant&) { reloadConfig(); }, this); From 153d1619043788dc3b36102342131f53ee25675d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Aug 2020 04:01:45 -0700 Subject: [PATCH 20/36] Qt: Add sugar for addGameAction on a CoreController call --- src/platform/qt/Window.cpp | 37 ++++++++++++++----------------------- src/platform/qt/Window.h | 1 + 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 1b281241e..25f7b7bfb 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1182,14 +1182,10 @@ void Window::setupMenu(QMenuBar* menubar) { m_actions.addSeparator("quickLoad"); m_actions.addSeparator("quickSave"); - Action* undoLoadState = addGameAction(tr("Undo load state"), "undoLoadState", [this]() { - m_controller->loadBackupState(); - }, "quickLoad", QKeySequence("F11")); + Action* undoLoadState = addGameAction(tr("Undo load state"), "undoLoadState", &CoreController::loadBackupState, "quickLoad", QKeySequence("F11")); m_nonMpActions.append(undoLoadState); - Action* undoSaveState = addGameAction(tr("Undo save state"), "undoSaveState", [this]() { - m_controller->saveBackupState(); - }, "quickSave", QKeySequence("Shift+F11")); + Action* undoSaveState = addGameAction(tr("Undo save state"), "undoSaveState", &CoreController::saveBackupState, "quickSave", QKeySequence("Shift+F11")); m_nonMpActions.append(undoSaveState); m_actions.addSeparator("quickLoad"); @@ -1235,17 +1231,9 @@ void Window::setupMenu(QMenuBar* menubar) { #endif m_actions.addMenu(tr("&Emulation"), "emu"); - addGameAction(tr("&Reset"), "reset", [this]() { - m_controller->reset(); - }, "emu", QKeySequence("Ctrl+R")); - - addGameAction(tr("Sh&utdown"), "shutdown", [this]() { - m_controller->stop(); - }, "emu"); - - addGameAction(tr("Yank game pak"), "yank", [this]() { - m_controller->yankPak(); - }, "emu"); + addGameAction(tr("&Reset"), "reset", &CoreController::reset, "emu", QKeySequence("Ctrl+R")); + addGameAction(tr("Sh&utdown"), "shutdown", &CoreController::stop, "emu"); + addGameAction(tr("Yank game pak"), "yank", &CoreController::yankPak, "emu"); m_actions.addSeparator("emu"); @@ -1258,9 +1246,7 @@ void Window::setupMenu(QMenuBar* menubar) { }, "emu", QKeySequence("Ctrl+P")); connect(this, &Window::paused, pause, &Action::setActive); - addGameAction(tr("&Next frame"), "frameAdvance", [this]() { - m_controller->frameAdvance(); - }, "emu", QKeySequence("Ctrl+N")); + addGameAction(tr("&Next frame"), "frameAdvance", &CoreController::frameAdvance, "emu", QKeySequence("Ctrl+N")); m_actions.addSeparator("emu"); @@ -1781,9 +1767,14 @@ Action* Window::addGameAction(const QString& visibleName, const QString& name, A template Action* Window::addGameAction(const QString& visibleName, const QString& name, T* obj, V (T::*method)(), const QString& menu, const QKeySequence& shortcut) { return addGameAction(visibleName, name, [this, obj, method]() { - if (m_controller) { - (obj->*method)(); - } + (obj->*method)(); + }, menu, shortcut); +} + +template +Action* Window::addGameAction(const QString& visibleName, const QString& name, V (CoreController::*method)(), const QString& menu, const QKeySequence& shortcut) { + return addGameAction(visibleName, name, [this, method]() { + (m_controller.get()->*method)(); }, menu, shortcut); } diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 178f60ce8..ba8d4d771 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -164,6 +164,7 @@ private: Action* addGameAction(const QString& visibleName, const QString& name, Action::Function action, const QString& menu = {}, const QKeySequence& = {}); template Action* addGameAction(const QString& visibleName, const QString& name, T* obj, V (T::*action)(), const QString& menu = {}, const QKeySequence& = {}); + template Action* addGameAction(const QString& visibleName, const QString& name, V (CoreController::*action)(), const QString& menu = {}, const QKeySequence& = {}); Action* addGameAction(const QString& visibleName, const QString& name, Action::BooleanFunction action, const QString& menu = {}, const QKeySequence& = {}); void updateTitle(float fps = -1); From b9acc05292b424376e8474f7b0e9672e4d3aaa93 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Aug 2020 04:03:26 -0700 Subject: [PATCH 21/36] Test: Fix CInemaTest.directory size --- src/platform/test/cinema-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/test/cinema-main.c b/src/platform/test/cinema-main.c index 4c18d40ae..d2d0c4fe9 100644 --- a/src/platform/test/cinema-main.c +++ b/src/platform/test/cinema-main.c @@ -70,7 +70,7 @@ enum CInemaRebaseline { }; struct CInemaTest { - char directory[MAX_TEST]; + char directory[PATH_MAX]; char filename[MAX_TEST]; char name[MAX_TEST]; enum CInemaStatus status; From 639c0bf0e9499870d122e1579184a99f3f8561cd Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Aug 2020 23:05:05 -0700 Subject: [PATCH 22/36] Qt: More warning fixes --- src/platform/qt/AssetTile.cpp | 2 -- src/platform/qt/AssetView.cpp | 6 ++---- src/platform/qt/CheatsModel.cpp | 12 +++++------- src/platform/qt/ColorPicker.cpp | 1 - src/platform/qt/Display.h | 2 +- src/platform/qt/DisplayQt.cpp | 1 + src/platform/qt/DisplayQt.h | 4 ++-- src/platform/qt/ShortcutController.h | 2 +- src/platform/qt/ShortcutModel.cpp | 5 ++--- 9 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index cda468757..437ece086 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -130,8 +130,6 @@ void AssetTile::setFlip(bool h, bool v) { void AssetTile::selectColor(int index) { const color_t* data; mTileCache* tileCache = m_tileCaches[m_index >= m_boundary]; - unsigned bpp = 8 << tileCache->bpp; - int paletteId = m_paletteId; data = mTileCacheGetTile(tileCache, m_index >= m_boundary ? m_index - m_boundary : m_index, m_paletteId); color_t color = data[index]; m_ui.color->setColor(0, color); diff --git a/src/platform/qt/AssetView.cpp b/src/platform/qt/AssetView.cpp index 20dbd1641..04e9ad7c6 100644 --- a/src/platform/qt/AssetView.cpp +++ b/src/platform/qt/AssetView.cpp @@ -144,8 +144,8 @@ QImage AssetView::compositeObj(const ObjInfo& objInfo) { image.setColorTable(palette); uchar* bits = image.bits(); unsigned t = objInfo.tile; - for (int y = 0; y < objInfo.height; ++y) { - for (int x = 0; x < objInfo.width; ++x, ++t) { + for (unsigned y = 0; y < objInfo.height; ++y) { + for (unsigned x = 0; x < objInfo.width; ++x, ++t) { compositeTile(static_cast(mTileCacheGetVRAM(tileCache, t)), bits, objInfo.width * 8, x * 8, y * 8, objInfo.bits); } t += objInfo.stride - objInfo.width; @@ -183,7 +183,6 @@ bool AssetView::lookupObjGBA(int id, struct ObjInfo* info) { unsigned height = GBAVideoObjSizes[shape * 4 + size][1]; unsigned tile = GBAObjAttributesCGetTile(obj->c); unsigned palette = GBAObjAttributesCGetPalette(obj->c); - unsigned tileBase = tile; unsigned paletteSet; unsigned bits; if (GBAObjAttributesAIs256Color(obj->a)) { @@ -237,7 +236,6 @@ bool AssetView::lookupObjGB(int id, struct ObjInfo* info) { const GB* gb = static_cast(m_controller->thread()->core->board); const GBObj* obj = &gb->video.oam.obj[id]; - unsigned width = 8; unsigned height = 8; GBRegisterLCDC lcdc = gb->memory.io[REG_LCDC]; if (GBRegisterLCDCIsObjSize(lcdc)) { diff --git a/src/platform/qt/CheatsModel.cpp b/src/platform/qt/CheatsModel.cpp index 77e608ec8..a04b30b1f 100644 --- a/src/platform/qt/CheatsModel.cpp +++ b/src/platform/qt/CheatsModel.cpp @@ -42,11 +42,10 @@ QVariant CheatsModel::data(const QModelIndex& index, int role) const { } } - if (index.row() >= mCheatSetsSize(&m_device->cheats)) { + if ((size_t) index.row() >= mCheatSetsSize(&m_device->cheats)) { return QVariant(); } - int row = index.row(); const mCheatSet* cheats = *mCheatSetsGetPointer(&m_device->cheats, index.row()); switch (role) { case Qt::DisplayRole: @@ -60,11 +59,10 @@ QVariant CheatsModel::data(const QModelIndex& index, int role) const { } bool CheatsModel::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.parent().isValid() || index.row() > mCheatSetsSize(&m_device->cheats)) { + if (!index.isValid() || index.parent().isValid() || (size_t) index.row() > mCheatSetsSize(&m_device->cheats)) { return false; } - int row = index.row(); mCheatSet* cheats = *mCheatSetsGetPointer(&m_device->cheats, index.row()); switch (role) { case Qt::DisplayRole: @@ -119,7 +117,7 @@ Qt::ItemFlags CheatsModel::flags(const QModelIndex& index) const { return Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -int CheatsModel::columnCount(const QModelIndex& parent) const { +int CheatsModel::columnCount(const QModelIndex&) const { return 1; } @@ -141,14 +139,14 @@ mCheatSet* CheatsModel::itemAt(const QModelIndex& index) { if (index.parent().isValid()) { return static_cast(index.internalPointer()); } - if (index.row() >= mCheatSetsSize(&m_device->cheats)) { + if ((size_t) index.row() >= mCheatSetsSize(&m_device->cheats)) { return nullptr; } return *mCheatSetsGetPointer(&m_device->cheats, index.row()); } void CheatsModel::removeAt(const QModelIndex& index) { - if (!index.isValid() || index.parent().isValid() || index.row() >= mCheatSetsSize(&m_device->cheats)) { + if (!index.isValid() || index.parent().isValid() || (size_t) index.row() >= mCheatSetsSize(&m_device->cheats)) { return; } int row = index.row(); diff --git a/src/platform/qt/ColorPicker.cpp b/src/platform/qt/ColorPicker.cpp index 818a25fd4..22328b54a 100644 --- a/src/platform/qt/ColorPicker.cpp +++ b/src/platform/qt/ColorPicker.cpp @@ -46,7 +46,6 @@ bool ColorPicker::eventFilter(QObject* obj, QEvent* event) { if (event->type() != QEvent::MouseButtonRelease) { return false; } - int colorId; if (obj != m_parent) { return false; } diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index e739358c1..5e2d26f6d 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -51,7 +51,7 @@ public: virtual bool supportsShaders() const = 0; virtual VideoShader* shaders() = 0; virtual int framebufferHandle() { return -1; } - virtual void setVideoScale(int scale) {} + virtual void setVideoScale(int) {} virtual void setVideoProxy(std::shared_ptr proxy) { m_videoProxy = proxy; } std::shared_ptr videoProxy() { return m_videoProxy; } diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index 764bf88ca..c46ee18e6 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -96,6 +96,7 @@ void DisplayQt::paintEvent(QPaintEvent*) { if (isFiltered()) { painter.setRenderHint(QPainter::SmoothPixmapTransform); } + // TODO: Refactor this code out (since it's copied in like 3 places) QSize s = size(); QSize ds = s; if (isAspectRatioLocked()) { diff --git a/src/platform/qt/DisplayQt.h b/src/platform/qt/DisplayQt.h index 5795ccb45..e8623468f 100644 --- a/src/platform/qt/DisplayQt.h +++ b/src/platform/qt/DisplayQt.h @@ -42,8 +42,8 @@ protected: private: bool m_isDrawing = false; - unsigned m_width; - unsigned m_height; + int m_width; + int m_height; QImage m_backing{nullptr}; QImage m_oldBacking{nullptr}; std::shared_ptr m_context = nullptr; diff --git a/src/platform/qt/ShortcutController.h b/src/platform/qt/ShortcutController.h index 3a82f034d..eb24cdc96 100644 --- a/src/platform/qt/ShortcutController.h +++ b/src/platform/qt/ShortcutController.h @@ -30,7 +30,7 @@ public: Action* action() { return m_action; } const Action* action() const { return m_action; } - const int shortcut() const { return m_shortcut; } + int shortcut() const { return m_shortcut; } QString visibleName() const { return m_action ? m_action->visibleName() : QString(); } QString name() const { return m_action ? m_action->name() : QString(); } int button() const { return m_button; } diff --git a/src/platform/qt/ShortcutModel.cpp b/src/platform/qt/ShortcutModel.cpp index 331fa6c37..54fa83fcf 100644 --- a/src/platform/qt/ShortcutModel.cpp +++ b/src/platform/qt/ShortcutModel.cpp @@ -27,7 +27,6 @@ QVariant ShortcutModel::data(const QModelIndex& index, int role) const { if (role != Qt::DisplayRole || !index.isValid()) { return QVariant(); } - int row = index.row(); const Item* item = static_cast(index.internalPointer()); const Shortcut* shortcut = item->shortcut; switch (index.column()) { @@ -101,7 +100,7 @@ QModelIndex ShortcutModel::parent(const QModelIndex& index) const { return createIndex(m_controller->indexIn(parent), 0, pitem); } -int ShortcutModel::columnCount(const QModelIndex& index) const { +int ShortcutModel::columnCount(const QModelIndex&) const { return 3; } @@ -131,7 +130,7 @@ void ShortcutModel::addRowNamed(const QString& name) { endInsertRows(); } -void ShortcutModel::clearMenu(const QString& name) { +void ShortcutModel::clearMenu(const QString&) { // TODO beginResetModel(); endResetModel(); From 9ab0f2d1b59d7c6f3bcb28f48e5a17d7cb00e1ec Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Aug 2020 23:12:26 -0700 Subject: [PATCH 23/36] README: Add missing Switch mention, update notes on macOS --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a649ee0c..a25674898 100644 --- a/README.md +++ b/README.md @@ -76,10 +76,11 @@ Supported Platforms ------------------- - Windows Vista or newer -- OS X 10.7 (Lion)[[3]](#osxver) or newer +- OS X 10.8 (Mountain Lion)[[3]](#osxver) or newer - Linux - FreeBSD - Nintendo 3DS +- Nintendo Switch - Wii - PlayStation Vita @@ -238,7 +239,7 @@ Footnotes [2] Flash memory size detection does not work in some cases. These can be configured at runtime, but filing a bug is recommended if such a case is encountered. -[3] 10.7 is only needed for the Qt port. The SDL port is known to work on 10.5, and may work on older. +[3] 10.8 is only needed for the Qt port. It may be possible to build or running the Qt port on 10.7 or older, but this is not officially supported. The SDL port is known to work on 10.5, and may work on older. [downloads]: http://mgba.io/downloads.html [source]: https://github.com/mgba-emu/mgba/ From 7551afc952498113047689d16c97447caea627da Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Aug 2020 15:35:03 -0700 Subject: [PATCH 24/36] GBA Video: Fix frameskip affecting timing --- src/gba/video.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gba/video.c b/src/gba/video.c index 2d2c7f453..adaf008a8 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -148,8 +148,10 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { } video->p->memory.io[REG_VCOUNT >> 1] = video->vcount; - if (video->vcount < GBA_VIDEO_VERTICAL_PIXELS && video->frameskipCounter <= 0) { - video->renderer->drawScanline(video->renderer, video->vcount); + if (video->vcount < GBA_VIDEO_VERTICAL_PIXELS) { + if (video->frameskipCounter <= 0) { + video->renderer->drawScanline(video->renderer, video->vcount); + } video->shouldStall = 1; } From 7caac4ae44587da2d1d87c5ff944d97cf7019a8d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Aug 2020 15:40:34 -0700 Subject: [PATCH 25/36] Vita: Clean up merged commit --- CHANGES | 1 + src/platform/psp2/psp2-context.c | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 49f4f8099..f9aad2661 100644 --- a/CHANGES +++ b/CHANGES @@ -55,6 +55,7 @@ Other fixes: - Qt: Add missing option for Wisdom Tree in overrides list - Util: Fix crash if PNG header fails to write - SM83: Simplify register pair access on big endian + - Vita: Fix flickering when using frameskip (fixes mgba.io/i/1822) - Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830) Misc: - 3DS: Use "wide mode" where applicable for slightly better filtering diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index 444679d33..7ecd89f71 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -584,15 +584,13 @@ void _drawTex(vita2d_texture* t, unsigned width, unsigned height, bool faded, bo } void mPSP2Swap(struct mGUIRunner* runner) { - bool frameAvailable; + bool frameAvailable = true; if (runner->core->platform(runner->core) == PLATFORM_GBA) { struct GBA* gba = runner->core->board; frameAvailable = gba->video.frameskipCounter <= 0; } else if (runner->core->platform(runner->core) == PLATFORM_GB) { struct GB* gb = runner->core->board; frameAvailable = gb->video.frameskipCounter <= 0; - } else { - frameAvailable = false; } if (frameAvailable) { currentTex = !currentTex; From 5caf256631945a8afd679b5ecb742ec50958a2dd Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 14:01:19 -0700 Subject: [PATCH 26/36] Test: Fix build on Wii --- src/platform/test/perf-main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/test/perf-main.c b/src/platform/test/perf-main.c index 54b1a5ea0..d75ca539d 100644 --- a/src/platform/test/perf-main.c +++ b/src/platform/test/perf-main.c @@ -23,6 +23,7 @@ #include #endif #ifdef GEKKO +#define asm __asm__ #include #include #ifdef FIXED_ROM_BUFFER From b02fba9d28ee22fb0c8a2d9aa6488c7319b5c401 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 15:44:05 -0700 Subject: [PATCH 27/36] GBA Memory: Fix instability on Wii when using AGBPrint --- CHANGES | 1 + src/gba/gba.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index f9aad2661..16e79309d 100644 --- a/CHANGES +++ b/CHANGES @@ -46,6 +46,7 @@ Other fixes: - FFmpeg: Fix encoding of time base - GB Core: Fix extracting SRAM when none is present - GBA: Fix leak if attempting to load BIOS multiple times + - GBA Memory: Fix instability on Wii when using AGBPrint - GBA Savedata: Fix extracting save when not yet configured in-game - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) diff --git a/src/gba/gba.c b/src/gba/gba.c index 14573c556..c1f87d2e5 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -130,7 +130,9 @@ void GBAUnloadROM(struct GBA* gba) { if (gba->yankedRomSize) { gba->yankedRomSize = 0; } +#if !defined(FIXED_ROM_BUFFER) && !defined(__wii__) mappedMemoryFree(gba->memory.rom, SIZE_CART0); +#endif } if (gba->romVf) { From 1950780999d5642cb41086116ee7b256955a54a7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 15:53:47 -0700 Subject: [PATCH 28/36] CMake: 3DS/Wii tiny cleanup --- CMakeLists.txt | 8 -------- src/platform/3ds/CMakeLists.txt | 2 +- src/platform/wii/CMakeLists.txt | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27d9f09bd..64b8ac75c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,10 +261,6 @@ if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII OR DEFINED SWITCH) set(USE_LIBZIP OFF CACHE BOOL "") endif() -if(DEFINED 3DS) - add_definitions(-DFIXED_ROM_BUFFER) -endif() - if(DEFINED SWITCH) set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3" FORCE) endif() @@ -282,10 +278,6 @@ if(WII) add_definitions(-U__STRICT_ANSI__) endif() -if(3DS OR WII) - add_definitions(-D_GNU_SOURCE) -endif() - include(CheckCCompilerFlag) include(CheckFunctionExists) include(CheckIncludeFiles) diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt index b077ca53a..29da450fa 100644 --- a/src/platform/3ds/CMakeLists.txt +++ b/src/platform/3ds/CMakeLists.txt @@ -10,7 +10,7 @@ find_program(RAW2C raw2c) set(STRIP "${cross_prefix_path}strip" CACHE INTERNAL "symbol stripper") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format" PARENT_SCOPE) -set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64) +set(OS_DEFINES _GNU_SOURCE COLOR_16_BIT COLOR_5_6_5 FIXED_ROM_BUFFER IOAPI_NO_64) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if(${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo) diff --git a/src/platform/wii/CMakeLists.txt b/src/platform/wii/CMakeLists.txt index d0a1a7821..318c176a6 100644 --- a/src/platform/wii/CMakeLists.txt +++ b/src/platform/wii/CMakeLists.txt @@ -3,7 +3,7 @@ find_program(GXTEXCONV gxtexconv) find_program(RAW2C raw2c) find_program(WIILOAD wiiload) -set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 USE_VFS_FILE IOAPI_NO_64 FIXED_ROM_BUFFER) +set(OS_DEFINES _GNU_SOURCE COLOR_16_BIT COLOR_5_6_5 USE_VFS_FILE IOAPI_NO_64 FIXED_ROM_BUFFER) list(APPEND CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-devlist.c) include_directories(${CMAKE_CURRENT_BINARY_DIR}) From 12aa775316589df17edf1685e5448aa2c1160b0e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 15:58:21 -0700 Subject: [PATCH 29/36] Wii: Log in a way that Dolphin picks up --- src/feature/gui/gui-runner.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/feature/gui/gui-runner.c b/src/feature/gui/gui-runner.c index 54752b2e9..b8c2d9a5c 100644 --- a/src/feature/gui/gui-runner.c +++ b/src/feature/gui/gui-runner.c @@ -287,6 +287,9 @@ static void _log(struct mLogger* logger, int category, enum mLogLevel level, con guiLogger->vf = NULL; } } +#ifdef GEKKO + puts(log2); +#endif } static void _updateLoading(size_t read, size_t size, void* context) { From c6fb561465046bd9eafc8bccf11cd2f1c8bb34ab Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 16:06:07 -0700 Subject: [PATCH 30/36] Vita: Clean this up properly --- src/platform/psp2/psp2-context.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/platform/psp2/psp2-context.c b/src/platform/psp2/psp2-context.c index 7ecd89f71..74eb7b039 100644 --- a/src/platform/psp2/psp2-context.c +++ b/src/platform/psp2/psp2-context.c @@ -585,12 +585,19 @@ void _drawTex(vita2d_texture* t, unsigned width, unsigned height, bool faded, bo void mPSP2Swap(struct mGUIRunner* runner) { bool frameAvailable = true; - if (runner->core->platform(runner->core) == PLATFORM_GBA) { - struct GBA* gba = runner->core->board; - frameAvailable = gba->video.frameskipCounter <= 0; - } else if (runner->core->platform(runner->core) == PLATFORM_GB) { - struct GB* gb = runner->core->board; - frameAvailable = gb->video.frameskipCounter <= 0; + switch (runner->core->platform(runner->core)) { +#ifdef M_CORE_GBA + case PLATFORM_GBA: + frameAvailable = ((struct GBA*) runner->core->board)->video.frameskipCounter <= 0; + break; +#endif +#ifdef M_CORE_GB + case PLATFORM_GB: + frameAvailable = ((struct GB*) runner->core->board)->video.frameskipCounter <= 0; + break; +#endif + default: + break; } if (frameAvailable) { currentTex = !currentTex; From c6ca0d25c01f1b65a2d90636e5b550eee27a545e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 17:55:44 -0700 Subject: [PATCH 31/36] GBA SIO: Fix Normal mode being totally broken (fixes #1800) --- CHANGES | 1 + src/gba/io.c | 2 + src/gba/sio/lockstep.c | 58 ++++++++++++++--------- src/platform/qt/MultiplayerController.cpp | 2 + 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index 16e79309d..2181dbb4d 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ Emulation fixes: - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) - GBA Savedata: Fix potential corruption when loading a 1Mbit flash save - GBA SIO: Fix copying Normal mode transfer values + - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing - GBA Video: Fix invalid read in mode 4 mosaic diff --git a/src/gba/io.c b/src/gba/io.c index a601f6855..c3faf0cc8 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -527,6 +527,8 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { case REG_JOY_TRANS_HI: gba->memory.io[REG_JOYSTAT >> 1] |= JOYSTAT_TRANS_BIT; // Fall through + case REG_SIODATA32_LO: + case REG_SIODATA32_HI: case REG_SIOMLT_SEND: case REG_JOYCNT: case REG_JOYSTAT: diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index 5b441cc63..a2ecfc5b5 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -30,6 +30,7 @@ void GBASIOLockstepInit(struct GBASIOLockstep* lockstep) { lockstep->multiRecv[2] = 0xFFFF; lockstep->multiRecv[3] = 0xFFFF; lockstep->attachedMulti = 0; + lockstep->attachedNormal = 0; } void GBASIOLockstepNodeCreate(struct GBASIOLockstepNode* node) { @@ -44,11 +45,14 @@ bool GBASIOLockstepAttachNode(struct GBASIOLockstep* lockstep, struct GBASIOLock if (lockstep->d.attached == MAX_GBAS) { return false; } + mLockstepLock(&lockstep->d); lockstep->players[lockstep->d.attached] = node; node->p = lockstep; node->id = lockstep->d.attached; + node->normalSO = true; node->transferFinished = true; ++lockstep->d.attached; + mLockstepUnlock(&lockstep->d); return true; } @@ -56,6 +60,7 @@ void GBASIOLockstepDetachNode(struct GBASIOLockstep* lockstep, struct GBASIOLock if (lockstep->d.attached == 0) { return; } + mLockstepLock(&lockstep->d); int i; for (i = 0; i < lockstep->d.attached; ++i) { if (lockstep->players[i] != node) { @@ -66,8 +71,10 @@ void GBASIOLockstepDetachNode(struct GBASIOLockstep* lockstep, struct GBASIOLock lockstep->players[i - 1]->id = i - 1; } --lockstep->d.attached; + lockstep->players[lockstep->d.attached] = NULL; break; } + mLockstepUnlock(&lockstep->d); } bool GBASIOLockstepNodeInit(struct GBASIODriver* driver) { @@ -107,6 +114,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) { } break; case SIO_NORMAL_32: + ATOMIC_ADD(node->p->attachedNormal, 1); node->d.writeRegister = GBASIOLockstepNodeNormalWriteRegister; break; default: @@ -132,6 +140,9 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) { case SIO_MULTI: ATOMIC_SUB(node->p->attachedMulti, 1); break; + case SIO_NORMAL_32: + ATOMIC_SUB(node->p->attachedNormal, 1); + break; default: break; } @@ -148,11 +159,6 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) { node->p->d.unload(&node->p->d, node->id); - node->p->multiRecv[0] = 0xFFFF; - node->p->multiRecv[1] = 0xFFFF; - node->p->multiRecv[2] = 0xFFFF; - node->p->multiRecv[3] = 0xFFFF; - _finishTransfer(node); if (!node->id) { @@ -173,7 +179,7 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver mLockstepLock(&node->p->d); if (address == REG_SIOCNT) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04x", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); enum mLockstepPhase transferActive; ATOMIC_LOAD(transferActive, node->p->d.transferActive); @@ -200,7 +206,9 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver value &= 0xFF83; value |= driver->p->siocnt & 0x00FC; } else if (address == REG_SIOMLT_SEND) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOMLT_SEND <- %04x", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOMLT_SEND <- %04X", node->id, value); + } else { + mLOG(GBA_SIO, STUB, "Lockstep %i: Unknown reg %03X <- %04X", node->id, address, value); } mLockstepUnlock(&node->p->d); @@ -246,7 +254,7 @@ static void _finishTransfer(struct GBASIOLockstepNode* node) { if (node->id) { sio->siocnt = GBASIONormalSetSi(sio->siocnt, GBASIONormalGetIdleSo(node->p->players[node->id - 1]->d.p->siocnt)); node->d.p->p->memory.io[REG_SIODATA32_LO >> 1] = node->p->normalRecv[node->id - 1]; - node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] |= node->p->normalRecv[node->id - 1] >> 16; + node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] = node->p->normalRecv[node->id - 1] >> 16; } else { node->d.p->p->memory.io[REG_SIODATA32_LO >> 1] = 0xFFFF; node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] = 0xFFFF; @@ -303,8 +311,8 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) { break; case SIO_NORMAL_32: node->p->multiRecv[0] = 0xFFFF; - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04x", node->id, node->d.p->p->memory.io[REG_SIODATA32_LO >> 1]); - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04x", node->id, node->d.p->p->memory.io[REG_SIODATA32_HI >> 1]); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, node->d.p->p->memory.io[REG_SIODATA32_LO >> 1]); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, node->d.p->p->memory.io[REG_SIODATA32_HI >> 1]); node->p->normalRecv[0] = node->d.p->p->memory.io[REG_SIODATA32_LO >> 1]; node->p->normalRecv[0] |= node->d.p->p->memory.io[REG_SIODATA32_HI >> 1] << 16; break; @@ -473,27 +481,31 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive mLockstepLock(&node->p->d); if (address == REG_SIOCNT) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04x", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04X", node->id, value); value &= 0xFF8B; if (!node->id) { - value = GBASIONormalFillSi(value); + value = GBASIONormalClearSi(value); } - if (value & 0x0080 && !node->id) { - // Internal shift clock - if (value & 1) { - ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); - } - // Frequency - if (value & 2) { - node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 1024; + if (value & 0x0080) { + if (!node->id) { + // Internal shift clock + if (value & 1) { + ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING); + } + // Frequency + if (value & 2) { + node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 1024; + } else { + node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 8192; + } } else { - node->p->d.transferCycles = GBA_ARM7TDMI_FREQUENCY / 8192; + } } } else if (address == REG_SIODATA32_LO) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04x", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_LO <- %04X", node->id, value); } else if (address == REG_SIODATA32_HI) { - mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04x", node->id, value); + mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIODATA32_HI <- %04X", node->id, value); } mLockstepUnlock(&node->p->d); diff --git a/src/platform/qt/MultiplayerController.cpp b/src/platform/qt/MultiplayerController.cpp index 352e9d325..3a792d494 100644 --- a/src/platform/qt/MultiplayerController.cpp +++ b/src/platform/qt/MultiplayerController.cpp @@ -221,6 +221,7 @@ bool MultiplayerController::attachGame(CoreController* controller) { m_players.append({controller, node}); GBASIOSetDriver(&gba->sio, &node->d, SIO_MULTI); + GBASIOSetDriver(&gba->sio, &node->d, SIO_NORMAL_32); emit gameAttached(); return true; @@ -267,6 +268,7 @@ void MultiplayerController::detachGame(CoreController* controller) { GBA* gba = static_cast(thread->core->board); GBASIOLockstepNode* node = reinterpret_cast(gba->sio.drivers.multiplayer); GBASIOSetDriver(&gba->sio, nullptr, SIO_MULTI); + GBASIOSetDriver(&gba->sio, nullptr, SIO_NORMAL_32); if (node) { GBASIOLockstepDetachNode(&m_gbaLockstep, node); delete node; From 41211639ba654e54ad1a1212682e4f829f3aad33 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Mon, 3 Aug 2020 20:29:14 -0500 Subject: [PATCH 32/36] Stack traces: fix flipped variables that cause a crash --- src/debugger/stack-trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debugger/stack-trace.c b/src/debugger/stack-trace.c index a10c0bde8..50c3a523c 100644 --- a/src/debugger/stack-trace.c +++ b/src/debugger/stack-trace.c @@ -84,7 +84,7 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* const char* functionName = mDebuggerSymbolReverseLookup(st, stackFrame->entryAddress, stackFrame->entrySegment); if (functionName) { written += snprintf(out + written, *length - written, "%s ", functionName); - } else if (prevFrame->entrySegment >= 0) { + } else if (stackFrame->entrySegment >= 0) { written += snprintf(out + written, *length - written, "0x%02X:%08X ", stackFrame->entrySegment, stackFrame->entryAddress); } else { written += snprintf(out + written, *length - written, "0x%08X ", stackFrame->entryAddress); @@ -111,7 +111,7 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* functionName = mDebuggerSymbolReverseLookup(st, prevFrame->entryAddress, prevFrame->entrySegment); if (functionName) { written += snprintf(out + written, *length - written, " [%s+%d]", functionName, offset); - } else if (stackFrame->entrySegment >= 0) { + } else if (prevFrame->entrySegment >= 0) { written += snprintf(out + written, *length - written, " [0x%02X:%08X+%d]", prevFrame->entrySegment, prevFrame->entryAddress, offset); } else { written += snprintf(out + written, *length - written, " [0x%08X+%d]", prevFrame->entryAddress, offset); From 8cba417141eec8b1a165cf14516e90bc72302f7f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 20:30:05 -0700 Subject: [PATCH 33/36] ARM: Fix warnings --- src/arm/isa-arm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index f62786d85..465e37a53 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -447,12 +447,12 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { #define ARM_MS_POST_store ARMSetPrivilegeMode(cpu, privilegeMode); #define ARM_MS_POST_load \ - if ((rs & 0x8000) && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + if (!(rs & 0x8000)) { \ + ARMSetPrivilegeMode(cpu, privilegeMode); \ + } else if (_ARMModeHasSPSR(cpu->cpsr.priv)) { \ cpu->cpsr = cpu->spsr; \ _ARMReadCPSR(cpu); \ - } else { \ - ARMSetPrivilegeMode(cpu, privilegeMode); \ - } \ + } #define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, LS, WRITEBACK, S_PRE, S_POST, DIRECTION, POST_BODY) \ DEFINE_INSTRUCTION_ARM(NAME, \ From fbe143fbd011bcaac3b9667f3223e479b5aa6bba Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 21:51:10 -0700 Subject: [PATCH 34/36] CHANGES: Update for 0.8.3 --- CHANGES | 63 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/CHANGES b/CHANGES index 2181dbb4d..eebb477be 100644 --- a/CHANGES +++ b/CHANGES @@ -8,16 +8,9 @@ Features: Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation - - ARM: Fix LDM^ writeback to user-mode register - - ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698) - - ARM: Fix edge case with Thumb SBC flags (fixes mgba.io/i/1818) - GB: Partially fix timing for skipped BIOS - - GB Memory: Fix OAM DMA from top 8 kB - GB MBC: Fix MBC1 mode changing behavior - - GB MBC: Fix MBC1 RAM enable bit selection - - GB MBC: Fix MBC2 bit selection - GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716) - - GB Video: Always initialize palette - GBA: Fix timing advancing too quickly in rare cases - GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Improve HLE BIOS timing @@ -25,53 +18,67 @@ Emulation fixes: - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Improve gamepak prefetch timing - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) - - GBA Savedata: Fix potential corruption when loading a 1Mbit flash save - GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing - - GBA Video: Fix invalid read in mode 4 mosaic - - GBA Video: Fix color of disabled screen - SM83: Emulate HALT bug - - SM83: Fix flags on little endian PowerPC Other fixes: - - 3DS: Fix garbage on borders of scaled screens - All: Improve export headers (fixes mgba.io/i/1738) - - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) - - All: Correct more format strings on Windows (fixes mgba.io/i/1817) - - ARM: Fix decoder detection of branches with ALU and LDR instrctions - - CMake: Fix build with libzip 1.7 - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix some small memory leaks - FFmpeg: Fix encoding of time base - - GB Core: Fix extracting SRAM when none is present - - GBA: Fix leak if attempting to load BIOS multiple times - - GBA Memory: Fix instability on Wii when using AGBPrint - - GBA Savedata: Fix extracting save when not yet configured in-game - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) - - Qt: Fix file handle leak on opening an invalid ROM - Qt: Fix a race condition in the frame inspector - - Qt: Fix Italian RTC translation (fixes mgba.io/i/1798) - - Qt: Add missing option for Wisdom Tree in overrides list - - Util: Fix crash if PNG header fails to write - SM83: Simplify register pair access on big endian - - Vita: Fix flickering when using frameskip (fixes mgba.io/i/1822) - - Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830) Misc: - 3DS: Use "wide mode" where applicable for slightly better filtering - GB: Allow pausing event loop while CPU is blocked - GBA: Allow pausing event loop while CPU is blocked - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG - - FFmpeg: Use range coder for FFV1 to reduce output size - Qt: Renderer can be changed while a game is running - Qt: Add hex index to palette view - Qt: Add transformation matrix info to sprite view + - Util: Reset vector size on deinit + +0.8.3: (2020-08-03) +Emulation fixes: + - ARM: Fix LDM^ writeback to user-mode register + - ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698) + - ARM: Fix edge case with Thumb SBC flags (fixes mgba.io/i/1818) + - GB MBC: Fix MBC1 RAM enable bit selection + - GB MBC: Fix MBC2 bit selection + - GB Memory: Fix OAM DMA from top 8 kB + - GB Video: Always initialize palette + - GBA Savedata: Fix potential corruption when loading a 1Mbit flash save + - GBA Video: Fix invalid read in mode 4 mosaic + - GBA Video: Fix color of disabled screen + - SM83: Fix flags on little endian PowerPC +Other fixes: + - 3DS: Fix garbage on borders of scaled screens + - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) + - All: Correct more format strings on Windows (fixes mgba.io/i/1817) + - ARM: Fix decoder detection of branches with ALU and LDR instrctions + - CMake: Fix build with libzip 1.7 + - CMake: Add missing dllexports.h file to dev installation + - GB Core: Fix extracting SRAM when none is present + - GBA: Fix leak if attempting to load BIOS multiple times + - GBA Memory: Fix instability on Wii when using AGBPrint + - GBA Savedata: Fix extracting save when not yet configured in-game + - Qt: Fix file handle leak on opening an invalid ROM + - Qt: Fix Italian RTC translation (fixes mgba.io/i/1798) + - Qt: Add missing option for Wisdom Tree in overrides list + - Qt: Fix stability regression on AMD drivers (fixes mgba.io/i/1791) + - Util: Fix crash if PNG header fails to write + - Vita: Fix flickering when using frameskip (fixes mgba.io/i/1822) + - Wii: Fix pixelated filtering on interframe blending (fixes mgba.io/i/1830) +Misc: + - FFmpeg: Use range coder for FFV1 to reduce output size - Qt: Add per-page scrolling to memory view (fixes mgba.io/i/1795) - Qt: Add setting to display ROM filename in title (closes mgba.io/i/1784) - - Util: Reset vector size on deinit 0.8.2: (2020-06-14) Emulation fixes: From 453791d28987558d3d2eb3d4facc829b84ab8257 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 3 Aug 2020 22:02:18 -0700 Subject: [PATCH 35/36] Qt: WebP is not APNG --- src/platform/qt/GIFView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index 820ef9547..977537c6f 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -85,7 +85,7 @@ void GIFView::stopRecording() { } void GIFView::selectFile() { - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.webp *.apng)")); + 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); } From d68bf5bd1a483c83a9fe30c8d5a0d6adab2286b5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 4 Aug 2020 18:01:35 -0700 Subject: [PATCH 36/36] OpenGL: Attempt to fix some build configurations (fixes #1839) --- CMakeLists.txt | 31 +++++++++++++++--------- include/mgba/internal/gba/renderers/gl.h | 2 +- src/gba/core.c | 20 +++++++-------- src/gba/renderers/gl.c | 2 +- src/platform/opengl/gles2.c | 20 +++++++++++++-- src/platform/opengl/gles2.h | 3 +++ src/platform/qt/CMakeLists.txt | 10 ++++---- src/platform/qt/Display.cpp | 8 +++--- src/platform/qt/Display.h | 4 --- src/platform/qt/DisplayGL.cpp | 20 +++++++-------- src/platform/qt/DisplayGL.h | 2 +- 11 files changed, 72 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64b8ac75c..69048056e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ if(NOT LIBMGBA_ONLY) set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)") set(BUILD_GL ON CACHE BOOL "Build with OpenGL") set(BUILD_GLES2 ON CACHE BOOL "Build with OpenGL|ES 2") - set(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3") + set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3") set(USE_EPOXY ON CACHE STRING "Build with libepoxy") set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies") set(DISTBUILD OFF CACHE BOOL "Build distribution packages") @@ -427,6 +427,7 @@ if(CMAKE_SYSTEM_NAME MATCHES ".*BSD|DragonFly") else() find_feature(USE_EDITLINE "libedit") endif() + if(BUILD_GL) find_package(OpenGL QUIET) if(NOT OPENGL_FOUND) @@ -436,18 +437,26 @@ endif() if(NOT BUILD_GL) set(OPENGL_LIBRARY "" CACHE PATH "" FORCE) endif() -if(BUILD_GLES2 AND NOT BUILD_RASPI AND NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|Darwin|Linux|.*BSD|DragonFly|Haiku)$") + +if(BUILD_GLES2 AND NOT BUILD_RASPI) find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h) find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM) if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY) set(BUILD_GLES2 OFF CACHE BOOL "OpenGL|ES 2 not found" FORCE) endif() endif() -if(NOT BUILD_GLES2) - set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE) +if(BUILD_GLES3) + find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h) + find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2) + if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY) + set(BUILD_GLES3 OFF CACHE BOOL "OpenGL|ES 3 not found" FORCE) + endif() endif() + if(BUILD_GL) - list(APPEND OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c) + list(APPEND OS_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) list(APPEND DEPENDENCY_LIB ${OPENGL_LIBRARY}) include_directories(${OPENGL_INCLUDE_DIR}) endif() @@ -457,11 +466,9 @@ if(BUILD_GLES2) include_directories(${OPENGLES2_INCLUDE_DIR}) endif() if(BUILD_GLES3) - find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h) - find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2) - if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY) - set(BUILD_GLES3 OFF CACHE BOOL "OpenGL|ES 3 not found" FORCE) - endif() + list(APPEND OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) + list(APPEND DEPENDENCY_LIB ${OPENGLES3_LIBRARY}) + include_directories(${OPENGLES3_INCLUDE_DIR}) endif() if(DISABLE_DEPS) @@ -700,7 +707,7 @@ endif() if(USE_EPOXY) list(APPEND OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) - add_definitions(-DBUILD_GL -DBUILD_GLES2) + add_definitions(-DBUILD_GL -DBUILD_GLES2 -DBUILD_GLES3) list(APPEND FEATURES EPOXY) include_directories(AFTER ${EPOXY_INCLUDE_DIRS}) link_directories(${EPOXY_LIBRARY_DIRS}) @@ -897,7 +904,7 @@ else() endif() if(BUILD_GL) - add_definitions(-DBUILD_GL) + add_definitions(-DBUILD_GL -DBUILD_GLES2 -DBUILD_GLES3) endif() if(BUILD_GLES2) diff --git a/include/mgba/internal/gba/renderers/gl.h b/include/mgba/internal/gba/renderers/gl.h index 9831f3def..f4a886fe9 100644 --- a/include/mgba/internal/gba/renderers/gl.h +++ b/include/mgba/internal/gba/renderers/gl.h @@ -16,7 +16,7 @@ CXX_GUARD_START #include #include -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #ifdef USE_EPOXY #include diff --git a/src/gba/core.c b/src/gba/core.c index f78786562..b4377d90e 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -18,7 +18,7 @@ #ifndef DISABLE_THREADING #include #endif -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #include #endif #include @@ -131,7 +131,7 @@ struct GBACore { struct mCore d; struct GBAVideoRenderer dummyRenderer; struct GBAVideoSoftwareRenderer renderer; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 struct GBAVideoGLRenderer glRenderer; #endif #ifndef MINIMAL_CORE @@ -189,7 +189,7 @@ static bool _GBACoreInit(struct mCore* core) { GBAVideoSoftwareRendererCreate(&gbacore->renderer); gbacore->renderer.outputBuffer = NULL; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 GBAVideoGLRendererCreate(&gbacore->glRenderer); gbacore->glRenderer.outputTex = -1; #endif @@ -241,7 +241,7 @@ static bool _GBACoreSupportsFeature(const struct mCore* core, enum mCoreFeature UNUSED(core); switch (feature) { case mCORE_FEATURE_OPENGL: -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 return true; #else return false; @@ -353,7 +353,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } struct GBACore* gbacore = (struct GBACore*) core; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (strcmp("videoScale", option) == 0) { if (config != &core->config) { mCoreConfigCopyValue(&core->config, config, "videoScale"); @@ -371,7 +371,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c if (gbacore->renderer.outputBuffer) { renderer = &gbacore->renderer.d; } -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); renderer = &gbacore->glRenderer.d; @@ -393,7 +393,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } static void _GBACoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) { -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 const struct GBACore* gbacore = (const struct GBACore*) core; int scale = gbacore->glRenderer.scale; #else @@ -413,7 +413,7 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s } static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) { -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 struct GBACore* gbacore = (struct GBACore*) core; gbacore->glRenderer.outputTex = texid; #else @@ -547,7 +547,7 @@ static void _GBACoreReset(struct mCore* core) { struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = (struct GBA*) core->board; if (gbacore->renderer.outputBuffer -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 || gbacore->glRenderer.outputTex != (unsigned) -1 #endif ) { @@ -556,7 +556,7 @@ static void _GBACoreReset(struct mCore* core) { renderer = &gbacore->renderer.d; } int fakeBool ATTRIBUTE_UNUSED; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); renderer = &gbacore->glRenderer.d; diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index b75d91b2d..2695643ac 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #include #include diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index a8052cab1..be2e88142 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -159,6 +159,7 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) { mGLES2ShaderInit(&context->finalShader, 0, 0, 0, 0, false, 0, 0); mGLES2ShaderInit(&context->interframeShader, 0, _interframeFragmentShader, -1, -1, false, 0, 0); +#ifdef BUILD_GLES3 if (context->initialShader.vao != (GLuint) -1) { glBindVertexArray(context->initialShader.vao); glBindBuffer(GL_ARRAY_BUFFER, context->vbo); @@ -168,6 +169,7 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) { glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glBindVertexArray(0); } +#endif glDeleteFramebuffers(1, &context->finalShader.fbo); glDeleteTextures(1, &context->finalShader.tex); @@ -305,9 +307,12 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) { glUseProgram(shader->program); glUniform1i(shader->texLocation, 0); glUniform2f(shader->texSizeLocation, context->d.width - padW, context->d.height - padH); +#ifdef BUILD_GLES3 if (shader->vao != (GLuint) -1) { glBindVertexArray(shader->vao); - } else { + } else +#endif + { glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glEnableVertexAttribArray(shader->positionLocation); glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); @@ -399,9 +404,11 @@ void mGLES2ContextDrawFrame(struct VideoBackend* v) { } glBindFramebuffer(GL_FRAMEBUFFER, 0); glUseProgram(0); +#ifdef BUILD_GLES3 if (context->finalShader.vao != (GLuint) -1) { glBindVertexArray(0); } +#endif } void mGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) { @@ -516,6 +523,7 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f shader->uniforms[i].location = glGetUniformLocation(shader->program, shader->uniforms[i].name); } +#ifdef BUILD_GLES3 const GLubyte* extensions = glGetString(GL_EXTENSIONS); if (shaderBuffer[0] == _gles2Header || version[0] >= '3' || (extensions && strstr((const char*) extensions, "_vertex_array_object") != NULL)) { glGenVertexArrays(1, &shader->vao); @@ -523,7 +531,9 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f glEnableVertexAttribArray(shader->positionLocation); glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); glBindVertexArray(0); - } else { + } else +#endif + { shader->vao = -1; } @@ -535,9 +545,11 @@ void mGLES2ShaderDeinit(struct mGLES2Shader* shader) { glDeleteShader(shader->fragmentShader); glDeleteProgram(shader->program); glDeleteFramebuffers(1, &shader->fbo); +#ifdef BUILD_GLES3 if (shader->vao != (GLuint) -1) { glDeleteVertexArrays(1, &shader->vao); } +#endif } void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shaders, size_t nShaders) { @@ -555,16 +567,20 @@ void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shad glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); +#ifdef BUILD_GLES3 if (context->shaders[i].vao != (GLuint) -1) { glBindVertexArray(context->shaders[i].vao); glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glEnableVertexAttribArray(context->shaders[i].positionLocation); glVertexAttribPointer(context->shaders[i].positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); } +#endif } +#ifdef BUILD_GLES3 if (context->initialShader.vao != (GLuint) -1) { glBindVertexArray(0); } +#endif glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/platform/opengl/gles2.h b/src/platform/opengl/gles2.h index 8cf5b2b0e..51173cfa1 100644 --- a/src/platform/opengl/gles2.h +++ b/src/platform/opengl/gles2.h @@ -22,6 +22,9 @@ CXX_GUARD_START #endif #else #include +#ifdef BUILD_GLES3 +#include +#endif #endif #include "platform/video-backend.h" diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index cba2de1d7..6a3aa9221 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -24,7 +24,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(Qt5 COMPONENTS Core Widgets OpenGL Network Multimedia) -if(NOT BUILD_GL AND NOT BUILD_GLES2) +if(NOT BUILD_GL AND NOT BUILD_GLES2 AND NOT BUILD_GLES3) message(WARNING "OpenGL is recommended to build the Qt port") endif() @@ -241,7 +241,7 @@ if(NOT DEFINED DATADIR) set(DATADIR ${CMAKE_INSTALL_DATADIR}/${BINARY_NAME}) endif() endif() -if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) +if(BUILD_GLES2 OR BUILD_GLES3 OR BUILD_EPOXY) install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) endif() install(FILES ${CMAKE_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt) @@ -291,8 +291,8 @@ if(WIN32) endif() list(APPEND QT_LIBRARIES Qt5::Widgets Qt5::Network) -if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) - list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) +if(BUILD_GL OR BUILD_GLES2 OR BUILD_GLES3 OR BUILD_EPOXY) + list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY} ${OPENGLES3_LIBRARY}) endif() if(QT_STATIC) find_library(QTPCRE NAMES qtpcre2 qtpcre) @@ -302,7 +302,7 @@ if(QT_STATIC) endif() list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} dwmapi uxtheme imm32 -static-libgcc -static-libstdc++) set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32") - set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) + set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY} ${OPENGLES3_LIBRARY}) elseif(APPLE) find_package(Cups) find_package(Qt5PrintSupport) diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 3f916ec7b..44ec240f7 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -10,21 +10,21 @@ using namespace QGBA; -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) Display::Driver Display::s_driver = Display::Driver::OPENGL; #else Display::Driver Display::s_driver = Display::Driver::QT; #endif Display* Display::create(QWidget* parent) { -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) QSurfaceFormat format; format.setSwapInterval(1); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); #endif switch (s_driver) { -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) case Driver::OPENGL: if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { format.setVersion(3, 0); @@ -44,7 +44,7 @@ Display* Display::create(QWidget* parent) { return new DisplayQt(parent); default: -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) return new DisplayGL(format, parent); #else return new DisplayQt(parent); diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index 5e2d26f6d..8c952a33f 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -27,12 +27,8 @@ Q_OBJECT public: enum class Driver { QT = 0, -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) OPENGL = 1, -#endif -#ifdef BUILD_GL OPENGL1 = 2, -#endif }; Display(QWidget* parent = nullptr); diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index d1e619c09..cfccfb496 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "DisplayGL.h" -#if defined(BUILD_GL) || defined(BUILD_GLES2) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) #include "CoreController.h" @@ -23,7 +23,7 @@ #ifdef BUILD_GL #include "platform/opengl/gl.h" #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) #include "platform/opengl/gles2.h" #ifdef _WIN32 #include @@ -265,7 +265,7 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion) #ifdef BUILD_GL mGLContext* glBackend; #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) mGLES2Context* gl2Backend; #endif @@ -284,7 +284,7 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion) epoxy_handle_external_wglMakeCurrent(); #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) auto version = m_gl->format().version(); QStringList extensions = QString(reinterpret_cast(glGetString(GL_EXTENSIONS))).split(' '); if (forceVersion != 1 && ((version == qMakePair(2, 1) && extensions.contains("GL_ARB_framebuffer_object")) || version.first > 2)) { @@ -316,7 +316,7 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion) }; m_backend->init(m_backend, 0); -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_supportsShaders) { m_shader.preprocessShader = static_cast(&reinterpret_cast(m_backend)->initialShader); } @@ -337,7 +337,7 @@ PainterGL::~PainterGL() { #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_shader.passes) { mGLES2ShaderFree(&m_shader); } @@ -411,7 +411,7 @@ void PainterGL::start() { epoxy_handle_external_wglMakeCurrent(); #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_supportsShaders && m_shader.passes) { mGLES2ShaderAttach(reinterpret_cast(m_backend), static_cast(m_shader.passes), m_shader.nPasses); } @@ -552,7 +552,7 @@ void PainterGL::setShaders(struct VDir* dir) { if (!supportsShaders()) { return; } -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (!m_started) { m_gl->makeCurrent(m_surface); #if defined(_WIN32) && defined(USE_EPOXY) @@ -576,7 +576,7 @@ void PainterGL::clearShaders() { if (!supportsShaders()) { return; } -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (!m_started) { m_gl->makeCurrent(m_surface); #if defined(_WIN32) && defined(USE_EPOXY) @@ -598,7 +598,7 @@ VideoShader* PainterGL::shaders() { } int PainterGL::glTex() { -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (supportsShaders()) { mGLES2Context* gl2Backend = reinterpret_cast(m_backend); return gl2Backend->tex; diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 84463069a..cb6ba3222 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once -#if defined(BUILD_GL) || defined(BUILD_GLES2) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) #include "Display.h"