From 7feee35ebaace24177bf1d75bd6f33bf5b02b53f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 31 Jan 2020 18:16:18 -0800 Subject: [PATCH 01/40] Core: Ensure ELF regions can be written before trying --- CHANGES | 1 + include/mgba/core/core.h | 1 + include/mgba/core/interface.h | 1 + src/core/core.c | 9 ++++++++- src/gb/core.c | 4 ++-- src/gba/core.c | 30 +++++++++++++++--------------- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index d52964440..3d6c21e10 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,7 @@ Emulation fixes: - GBA Video: Fix OpenGL sprite flag priority Other fixes: - Core: Fix race condition initializing thread proxy + - Core: Ensure ELF regions can be written before trying - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index b4e307a10..eeafb2724 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -201,6 +201,7 @@ void mCoreLoadForeignConfig(struct mCore* core, const struct mCoreConfig* config void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc); void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size); +void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask); #ifdef USE_ELF struct ELF; diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index 51ba6447f..c20816dbd 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -175,6 +175,7 @@ enum mCoreMemoryBlockFlags { mCORE_MEMORY_READ = 0x01, mCORE_MEMORY_WRITE = 0x02, mCORE_MEMORY_RW = 0x03, + mCORE_MEMORY_WORM = 0x04, mCORE_MEMORY_MAPPED = 0x10, mCORE_MEMORY_VIRTUAL = 0x20, }; diff --git a/src/core/core.c b/src/core/core.c index 0a79eabe2..f300e6d85 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -338,6 +338,10 @@ void mCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) { } void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) { + return mCoreGetMemoryBlockMasked(core, start, size, mCORE_MEMORY_MAPPED); +} + +void* mCoreGetMemoryBlockMasked(struct mCore* core, uint32_t start, size_t* size, uint32_t mask) { const struct mCoreMemoryBlock* blocks; size_t nBlocks = core->listMemoryBlocks(core, &blocks); size_t i; @@ -345,6 +349,9 @@ void* mCoreGetMemoryBlock(struct mCore* core, uint32_t start, size_t* size) { if (!(blocks[i].flags & mCORE_MEMORY_MAPPED)) { continue; } + if (!(blocks[i].flags & mask)) { + continue; + } if (start < blocks[i].start) { continue; } @@ -368,7 +375,7 @@ bool mCoreLoadELF(struct mCore* core, struct ELF* elf) { for (i = 0; i < ELFProgramHeadersSize(&ph); ++i) { size_t bsize, esize; Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i); - void* block = mCoreGetMemoryBlock(core, phdr->p_paddr, &bsize); + void* block = mCoreGetMemoryBlockMasked(core, phdr->p_paddr, &bsize, mCORE_MEMORY_WRITE | mCORE_MEMORY_WORM); char* bytes = ELFBytes(elf, &esize); if (block && bsize >= phdr->p_filesz && esize >= phdr->p_filesz + phdr->p_offset) { memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz); diff --git a/src/gb/core.c b/src/gb/core.c index 11d3f11ed..41290e84e 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -40,7 +40,7 @@ static const struct mCoreChannelInfo _GBAudioChannels[] = { static const struct mCoreMemoryBlock _GBMemoryBlocks[] = { { -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL }, - { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, + { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, { GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 }, { GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, @@ -51,7 +51,7 @@ static const struct mCoreMemoryBlock _GBMemoryBlocks[] = { static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = { { -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL }, - { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, + { GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 }, { GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 }, { GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 }, { GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 }, diff --git a/src/gba/core.c b/src/gba/core.c index 4ecf003b8..ab64241a9 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -58,9 +58,9 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocks[] = { { REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, }; static const struct mCoreMemoryBlock _GBAMemoryBlocksSRAM[] = { @@ -72,9 +72,9 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksSRAM[] = { { REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "SRAM", "Static RAM (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_SRAM, SIZE_CART_SRAM, true }, }; @@ -87,9 +87,9 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksFlash512[] = { { REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH512, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, }; @@ -102,9 +102,9 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksFlash1M[] = { { REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM, "sram", "Flash", "Flash Memory (64kiB)", BASE_CART_SRAM, BASE_CART_SRAM + SIZE_CART_FLASH512, SIZE_CART_FLASH1M, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 }, }; @@ -117,9 +117,9 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksEEPROM[] = { { REGION_PALETTE_RAM, "palette", "Palette", "Palette RAM (1kiB)", BASE_PALETTE_RAM, BASE_PALETTE_RAM + SIZE_PALETTE_RAM, SIZE_PALETTE_RAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_VRAM, "vram", "VRAM", "Video RAM (96kiB)", BASE_VRAM, BASE_VRAM + SIZE_VRAM, SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, { REGION_OAM, "oam", "OAM", "OBJ Attribute Memory (1kiB)", BASE_OAM, BASE_OAM + SIZE_OAM, SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED }, - { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, - { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED }, + { REGION_CART0, "cart0", "ROM", "Game Pak (32MiB)", BASE_CART0, BASE_CART0 + SIZE_CART0, SIZE_CART0, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART1, "cart1", "ROM WS1", "Game Pak (Waitstate 1)", BASE_CART1, BASE_CART1 + SIZE_CART1, SIZE_CART1, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, + { REGION_CART2, "cart2", "ROM WS2", "Game Pak (Waitstate 2)", BASE_CART2, BASE_CART2 + SIZE_CART2, SIZE_CART2, mCORE_MEMORY_READ | mCORE_MEMORY_WORM | mCORE_MEMORY_MAPPED }, { REGION_CART_SRAM_MIRROR, "eeprom", "EEPROM", "EEPROM (8kiB)", 0, SIZE_CART_EEPROM, SIZE_CART_EEPROM, mCORE_MEMORY_RW }, }; From 034d4bd43a7c79e01cb9ce2213aa1cf35f0f85df Mon Sep 17 00:00:00 2001 From: EmpyreusX <36258024+EmpyreusX@users.noreply.github.com> Date: Sat, 1 Feb 2020 18:56:07 +0800 Subject: [PATCH 02/40] Update and correct Chinese (Simpilfied) translation (#1658) * Update and correct Chinese (Simpilfied) translation * Update mgba-zh_CN.ts --- src/platform/qt/ts/mgba-zh_CN.ts | 430 +++++++++++++++---------------- 1 file changed, 205 insertions(+), 225 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index c922c39e8..487b171ef 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -1441,7 +1441,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Incompatible deck - 不兼容的卡组 + 卡组不兼容 @@ -1480,6 +1480,11 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Add CodeBreaker 添加 CodeBreaker + + + Add GameShark + 添加 GameShark + Add GameGenie @@ -1495,24 +1500,24 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::CoreController - + Failed to open save file: %1 - 无法打开存档: %1 + 打开存档失败: %1 - + Failed to open game file: %1 - 无法打开游戏文件: %1 + 打开游戏文件失败: %1 Failed to open snapshot file for reading: %1 - 无法读取快照文件: %1 + 读取快照文件失败: %1 Failed to open snapshot file for writing: %1 - 无法写入快照文件: %1 + 写入快照文件失败: %1 @@ -1520,7 +1525,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Failed to open game file: %1 - 无法打开游戏文件: %1 + 打开游戏文件失败: %1 @@ -1645,7 +1650,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Failed to open output GIF file: %1 - 无法打开输出的 GIF 文件: %1 + 打开输出 GIF 文件失败: %1 @@ -2612,7 +2617,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Increment and reload - 增量并重新加载 + 增量并重新载入 @@ -3110,47 +3115,47 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::LogController - + [%1] %2: %3 [%1] %2: %3 - + An error occurred 发生错误 - + DEBUG DEBUG - + STUB STUB - + INFO INFO - + WARN WARN - + ERROR ERROR - + FATAL FATAL - + GAME ERROR GAME ERROR @@ -3223,17 +3228,17 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 - + N/A - + Export map 导出映射 - + Portable Network Graphics (*.png) 便携式网络图形 (*.png) @@ -3261,49 +3266,42 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 载入 - + All 全部 - + Load TBL 载入 TBL - - - N/A - - - - Save selected memory 保存所选内存 - + Failed to open output file: %1 - 无法打开输出文件: %1 + 打开输出文件失败: %1 - + Load memory 载入内存 - + Failed to open input file: %1 - 无法打开输入文件: %1 + 打开输入文件失败: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3334,49 +3332,49 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::ObjView - - + + 0x%0 0x%0 - + Off - + Normal 一般 - + Trans 变换 - + OBJWIN OBJWIN - + Invalid 无效 - + N/A - + Export sprite 导出精灵图 - + Portable Network Graphics (*.png) 便携式网络图形 (*.png) @@ -3517,7 +3515,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 选择 BIOS - + (%1×%2) (%1×%2) @@ -3525,12 +3523,12 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::ShaderSelector - + No shader active 无活动的着色器 - + Load shader 载入着色器 @@ -3545,34 +3543,16 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 由 %1 - + Preprocessing - 预处理 + 正在预处理 - + Pass %1 通道 %1 - - QGBA::ShortcutController - - - Action - 动作 - - - - Keyboard - 键盘 - - - - Gamepad - 游戏手柄 - - QGBA::TileView @@ -3591,126 +3571,126 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 QGBA::VideoView - + Failed to open output video file: %1 - 无法打开输出视频文件: %1 + 打开输出视频文件失败: %1 - + Native (%0x%1) 原生 (%0x%1) - + Select output file - 选取输出文件 + 选择输出文件 QGBA::Window - + Game Boy Advance ROMs (%1) Game Boy Advance ROM (%1) - + Game Boy ROMs (%1) Game Boy ROM (%1) - + All ROMs (%1) 所有 ROM (%1) - + %1 Video Logs (*.mvl) %1 视频日志 (*.mvl) - + Archives (%1) 压缩文件 (%1) - - - + + + Select ROM 选择 ROM - + Select folder 选择文件夹 - + Game Boy Advance save files (%1) Game Boy Advance 存档文件 (%1) - - - + + + Select save 选择存档 - + mGBA savestate files (%1) mGBA 即时存档文件 (%1) - - + + Select savestate 选择即时存档 - + Select patch 选择补丁 - + Patches (*.ips *.ups *.bps) 补丁 (*.ips *.ups *.bps) - + Select image 选择图片 - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) 图像文件 (*.png *.gif *.jpg *.jpeg);;所有文件 (*) - - + + GameShark saves (*.sps *.xps) GameShark 存档 (*.sps *.xps) - + Select video log 选择视频日志 - + Video logs (*.mvl) 视频日志文件 (*.mvl) - + Crash 崩溃 - + The game has crashed with the following error: %1 @@ -3719,578 +3699,578 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 %1 - + Couldn't Load 无法载入 - + Could not load game. Are you sure it's in the correct format? 无法载入游戏。请确认游戏格式是否无误。 - + Unimplemented BIOS call 未实现的 BIOS 调用 - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. 该游戏使用了尚未实现的 BIOS 调用。请使用官方 BIOS 以获得最佳游戏体验。 - + Really make portable? 确定进行程序便携化? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? - 进行此操作后,模拟器将从模拟器可执行文件所在目录内加载模拟器配置。您想继续吗? + 进行此操作后,模拟器将从模拟器可执行文件所在目录内载入模拟器配置。您想继续吗? - + Restart needed 需要重新启动 - + Some changes will not take effect until the emulator is restarted. 更改将在模拟器下次启动时生效。 - + - Player %1 of %2 - 玩家 %1 共 %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File 文件(&F) - + Load &ROM... 载入 ROM(&R)... - + Load ROM in archive... 从压缩文件中载入 ROM... - + Add folder to library... 将文件夹添加到库中... - + Load alternate save... - 读取其他存档... + 载入其他存档... - + Load temporary save... - 读取临时存档... + 载入临时存档... - + Load &patch... 载入补丁文件(&P)... - + Boot BIOS 引导 BIOS - + Replace ROM... 替换 ROM... - + ROM &info... ROM 信息(&I)... - + Recent 最近打开 - + Make portable 程序便携化 - + &Load state - 读取即时存档(&L) + 载入即时存档(&L) - + Load state file... 载入即时存档文件... - + &Save state 保存即时存档(&S) - + Save state file... 保存即时存档文件... - + Quick load 快速读档 - + Quick save 快速存档 - + Load recent 载入最近 - + Save recent 保存最近 - + Undo load state 撤消读档 - + Undo save state 撤消存档 - - + + State &%1 即时存档 1(&1) - + Load camera image... - 读取相机图片... + 载入相机图片... - + Import GameShark Save 导入 GameShark 存档 - + Export GameShark Save 导出 GameShark 存档 - + New multiplayer window 新建多人游戏窗口 - + About... 关于... - + E&xit 退出(&X) - + &Emulation 模拟(&E) - + &Reset 重置(&R) - + Sh&utdown 关机(&U) - + Yank game pak 快速抽出游戏卡带 - + &Pause 暂停(&P) - + &Next frame 下一帧(&N) - + Fast forward (held) 快进 (长按) - + &Fast forward 快进(&F) - + Fast forward speed 快进速度 - + Unbounded 不限制 - + %0x %0x - + Rewind (held) 倒带 (长按) - + Re&wind 倒带(&W) - + Step backwards 步退 - + Sync to &video 视频同步(&V) - + Sync to &audio 音频同步(&A) - + Solar sensor 光线传感器 - + Increase solar level 增加光线级别 - + Decrease solar level 降低光线级别 - + Brightest solar level 光线级别为最亮 - + Darkest solar level 光线级别为最暗 - + Brightness %1 亮度 %1 - + Game Boy Printer... Game Boy 打印机... - + BattleChip Gate... BattleChip Gate... - + Audio/&Video 音频/视频(&V) - + Frame size 帧率 - + %1× %1× - + Toggle fullscreen 切换全屏 - + Lock aspect ratio 锁定纵横比 - + Force integer scaling 强制整数缩放 - + Interframe blending 帧间混合 - + Bilinear filtering 双线性过滤 - + Frame&skip 跳帧(&S) - + Mute 静音 - + FPS target 目标 FPS - + Native (59.7275) 原生 (59.7275) - + Take &screenshot 截图(&S) - + Record A/V... 录制音频/视频... - + Record GIF... 录制 GIF... - + Video layers 视频图层 - + Audio channels 音频通道 - + Adjust layer placement... 调整图层布局... - + &Tools 工具(&T) - + View &logs... 查看日志(&L)... - + Game &overrides... 覆盖游戏(&O)... - + Game Pak sensors... 游戏卡带传感器... - + &Cheats... 作弊码(&C)... - + Settings... 设置... - + Open debugger console... 打开调试器控制台... - + Start &GDB server... 打开 GDB 服务器(&G)... - + View &palette... 查看调色板(&P)... - + View &sprites... 查看精灵图(&S)... - + View &tiles... 查看瓷贴(&T)... - + View &map... 查看映射(&M)... - + &Frame inspector... 框架检查(&F)... - + View memory... 查看内存... - + Search memory... 搜索内存... - + View &I/O registers... 查看 I/O 寄存器(&I)... - + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 @@ -4813,7 +4793,7 @@ Game Boy Advance 是任天堂有限公司(Nintendo Co., Ltd.)的注册商标 Preload entire ROM into memory - 将整个 ROM 预加载到内存中 + 将整个 ROM 预载到内存中 From af59e28f906f8559fd9c4db447714e71eea3b620 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Feb 2020 12:17:45 -0800 Subject: [PATCH 03/40] GB Serialize: Fix timing bug loading channel 4 timing --- CHANGES | 1 + src/gb/audio.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 3d6c21e10..22f13ac7e 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation + - GB Serialize: Fix timing bug loading channel 4 timing - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing diff --git a/src/gb/audio.c b/src/gb/audio.c index 63af6bc1a..4bc5fa351 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -1078,9 +1078,13 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt LOAD_32LE(audio->ch4.lastEvent, 0, &state->ch4.lastEvent); LOAD_32LE(when, 0, &state->ch4.nextEvent); if (audio->ch4.envelope.dead < 2 && audio->playingCh4) { - if (when - audio->ch4.lastEvent > (uint32_t) audio->sampleInterval) { + if (!audio->ch4.lastEvent) { // Back-compat: fake this value - audio->ch4.lastEvent = when - audio->sampleInterval; + uint32_t currentTime = mTimingCurrentTime(audio->timing); + int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1; + cycles <<= audio->ch4.frequency; + cycles *= 8 * audio->timingFactor; + audio->ch4.lastEvent = currentTime + (when & (cycles - 1)) - cycles; } mTimingSchedule(audio->timing, &audio->ch4Event, when); } From fb652f411a62fd7655380c6fe2a0cf26fe98719d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Feb 2020 12:39:39 -0800 Subject: [PATCH 04/40] Travis: Fix osx deps --- .travis-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis-deps.sh b/.travis-deps.sh index 27f885203..7a93e2dfd 100755 --- a/.travis-deps.sh +++ b/.travis-deps.sh @@ -1,7 +1,7 @@ #!/bin/sh if [ $TRAVIS_OS_NAME = "osx" ]; then brew update - brew install qt5 ffmpeg sdl2 libedit libelf libpng libzip + brew install qt5 ffmpeg sdl2 libelf libpng libzip else sudo apt-get update sudo apt-get -y install libseccomp2 From 56d83bee11a478605a2d8d761975ae74348e8328 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Feb 2020 15:36:29 -0800 Subject: [PATCH 05/40] Debugger: Fix build on MINIMAL_CORE=2 --- src/gb/debugger/cli.c | 6 ++++++ src/gba/debugger/cli.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/gb/debugger/cli.c b/src/gb/debugger/cli.c index 9ad6cdd7a..cba9f4ae2 100644 --- a/src/gb/debugger/cli.c +++ b/src/gb/debugger/cli.c @@ -16,13 +16,17 @@ static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); +#endif struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = { { "frame", _frame, "", "Frame advance" }, +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 { "load", _load, "*", "Load a savestate" }, { "save", _save, "*", "Save a savestate" }, +#endif { 0, 0, 0, 0 } }; @@ -73,6 +77,7 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1; } +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { @@ -106,3 +111,4 @@ static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); } +#endif diff --git a/src/gba/debugger/cli.c b/src/gba/debugger/cli.c index 643a12b5c..5349911ab 100644 --- a/src/gba/debugger/cli.c +++ b/src/gba/debugger/cli.c @@ -16,13 +16,17 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static void _frame(struct CLIDebugger*, struct CLIDebugVector*); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger*, struct CLIDebugVector*); static void _save(struct CLIDebugger*, struct CLIDebugVector*); +#endif struct CLIDebuggerCommandSummary _GBACLIDebuggerCommands[] = { { "frame", _frame, "", "Frame advance" }, +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 { "load", _load, "*", "Load a savestate" }, { "save", _save, "*", "Save a savestate" }, +#endif { 0, 0, 0, 0 } }; @@ -72,6 +76,7 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]); } +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { @@ -107,3 +112,4 @@ static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT | SAVESTATE_RTC | SAVESTATE_METADATA); } +#endif From ba186f1a78f54297af608d8ebd8c48e0184c66b5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 1 Feb 2020 20:49:43 -0800 Subject: [PATCH 06/40] Core: Fix integer overflow in ELF loading --- CHANGES | 1 + src/core/core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 22f13ac7e..40dfa6713 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Emulation fixes: Other fixes: - Core: Fix race condition initializing thread proxy - Core: Ensure ELF regions can be written before trying + - Core: Fix integer overflow in ELF loading - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/src/core/core.c b/src/core/core.c index f300e6d85..569a6a983 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -377,7 +377,7 @@ bool mCoreLoadELF(struct mCore* core, struct ELF* elf) { Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i); void* block = mCoreGetMemoryBlockMasked(core, phdr->p_paddr, &bsize, mCORE_MEMORY_WRITE | mCORE_MEMORY_WORM); char* bytes = ELFBytes(elf, &esize); - if (block && bsize >= phdr->p_filesz && esize >= phdr->p_filesz + phdr->p_offset) { + if (block && bsize >= phdr->p_filesz && bsize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) { memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz); } else { return false; From d2f205aa9e7fdf2de299e01e7fab649c2ad6dc51 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Feb 2020 14:37:32 -0800 Subject: [PATCH 07/40] Qt: Fix window title not updating after shutting down game --- CHANGES | 1 + src/platform/qt/Window.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 40dfa6713..593f75088 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Other fixes: - Qt: Fix crash unloading shaders - Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650) - Qt: Fix extraneous dialog (fixes mgba.io/i/1654) + - Qt: Fix window title not updating after shutting down game - Util: Fix crash reading invalid ELFs Misc: - Qt: Renderer can be changed while a game is running diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 719da1f33..201c4cc28 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -806,7 +806,6 @@ void Window::gameStopped() { action->setEnabled(false); } setWindowFilePath(QString()); - updateTitle(); detachWidget(m_display.get()); m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); m_screenWidget->setLockIntegerScaling(false); @@ -834,6 +833,7 @@ void Window::gameStopped() { m_display->stopDrawing(); m_controller.reset(); + updateTitle(); m_display->setVideoProxy({}); if (m_pendingClose) { From d33f1d13926f4aa2afebad31775222cdd278411c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Feb 2020 16:05:27 -0800 Subject: [PATCH 08/40] Qt: Fix GIF view not allowing manual filename entry --- CHANGES | 1 + src/platform/qt/GIFView.cpp | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 593f75088..73c8314e8 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ Other fixes: - Qt: Fix toggled actions on gamepads (fixes mgba.io/i/1650) - Qt: Fix extraneous dialog (fixes mgba.io/i/1654) - Qt: Fix window title not updating after shutting down game + - Qt: Fix GIF view not allowing manual filename entry - Util: Fix crash reading invalid ELFs Misc: - Qt: Renderer can be changed while a game is running diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index 8a6d47fc7..eda022538 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -59,22 +59,20 @@ void GIFView::stopRecording() { emit recordingStopped(); FFmpegEncoderClose(&m_encoder); m_ui.stop->setEnabled(false); - m_ui.start->setEnabled(true); + m_ui.start->setEnabled(!m_filename.isEmpty()); m_ui.frameskip->setEnabled(true); } void GIFView::selectFile() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif)")); - if (!filename.isEmpty()) { - m_ui.filename->setText(filename); - if (!FFmpegEncoderIsOpen(&m_encoder)) { - m_ui.start->setEnabled(true); - } + m_ui.filename->setText(filename); +} + +void GIFView::setFilename(const QString& filename) { + m_filename = filename; + if (!FFmpegEncoderIsOpen(&m_encoder)) { + m_ui.start->setEnabled(!filename.isEmpty()); } } -void GIFView::setFilename(const QString& fname) { - m_filename = fname; -} - #endif From b192e6b5ed8cbe87a0460698ff57b20d05dc6e22 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Feb 2020 16:28:22 -0800 Subject: [PATCH 09/40] FFmpeg: Fix crash when -strict -2 is needed for vcodec or container --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 73c8314e8..4dc941bd6 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Other fixes: - Core: Fix race condition initializing thread proxy - Core: Ensure ELF regions can be written before trying - Core: Fix integer overflow in ELF loading + - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index b327925a3..04ab843b3 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -445,8 +445,11 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { encoder->sinkFrame = avcodec_alloc_frame(); #endif } - - if (avcodec_open2(encoder->video, vcodec, 0) < 0) { + AVDictionary* opts = 0; + av_dict_set(&opts, "strict", "-2", 0); + int res = avcodec_open2(encoder->video, vcodec, &opts); + av_dict_free(&opts); + if (res < 0) { FFmpegEncoderClose(encoder); return false; } @@ -466,7 +469,11 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { #endif } - if (avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, 0) < 0) { + AVDictionary* opts = 0; + av_dict_set(&opts, "strict", "-2", 0); + bool res = avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, &opts) < 0; + av_dict_free(&opts); + if (res) { FFmpegEncoderClose(encoder); return false; } From 8f1c3172c8f0c87093951f8715a95abe39f1bf85 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Feb 2020 16:46:11 -0800 Subject: [PATCH 10/40] FFmpeg: Disallow recording video with no audio nor video --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 4dc941bd6..2d05514df 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Other fixes: - Core: Ensure ELF regions can be written before trying - Core: Fix integer overflow in ELF loading - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container + - FFmpeg: Disallow recording video with no audio nor video - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 04ab843b3..3a67ca883 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -232,7 +232,7 @@ bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) { AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec); AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec); - if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat) { + if ((encoder->audioCodec && !acodec) || (encoder->videoCodec && !vcodec) || !oformat || (!acodec && !vcodec)) { return false; } if (encoder->audioCodec && !avformat_query_codec(oformat, acodec->id, FF_COMPLIANCE_EXPERIMENTAL)) { From 6b12eddfba654300833e3806d83011d978480f2c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 2 Feb 2020 16:46:42 -0800 Subject: [PATCH 11/40] FFmpeg: Add more presets --- CHANGES | 1 + src/platform/qt/VideoView.cpp | 17 +++++++++++++++++ src/platform/qt/VideoView.ui | 24 ++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/CHANGES b/CHANGES index 2d05514df..74c367ca8 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Other fixes: - Qt: Fix GIF view not allowing manual filename entry - Util: Fix crash reading invalid ELFs Misc: + - FFmpeg: Add more presets - Qt: Renderer can be changed while a game is running - Qt: Fix non-SDL build (fixes mgba.io/i/1656) - Switch: Make OpenGL scale adjustable while running diff --git a/src/platform/qt/VideoView.cpp b/src/platform/qt/VideoView.cpp index 94557900c..9f3767ea2 100644 --- a/src/platform/qt/VideoView.cpp +++ b/src/platform/qt/VideoView.cpp @@ -112,6 +112,15 @@ VideoView::VideoView(QWidget* parent) void VideoView::updatePresets() { m_presets.clear(); + addPreset(m_ui.preset4K, { + .container = QString(), + .vcodec = QString(), + .acodec = QString(), + .vbr = 0, + .abr = 0, + .dims = maintainAspect(QSize(3840, 2160)) + }); + addPreset(m_ui.preset1080, { .container = QString(), .vcodec = QString(), @@ -177,6 +186,14 @@ void VideoView::updatePresets() { .abr = 128 }); + addPreset(m_ui.presetMP4, { + .container = "MP4", + .vcodec = "h.264", + .acodec = "AAC", + .vbr = 800, + .abr = 128 + }); + if (m_nativeWidth && m_nativeHeight) { addPreset(m_ui.presetLossless, { .container = "MKV", diff --git a/src/platform/qt/VideoView.ui b/src/platform/qt/VideoView.ui index 24a3c5e75..0b1536e48 100644 --- a/src/platform/qt/VideoView.ui +++ b/src/platform/qt/VideoView.ui @@ -133,6 +133,13 @@ + + + + MP4 + + + @@ -150,6 +157,13 @@ + + + + 4K + + + @@ -289,6 +303,11 @@ FFV1 + + + None + + @@ -326,6 +345,11 @@ Uncompressed + + + None + + From baeb3536942f7ee9ab6cd8b119f03c30ba9d17be Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 5 Feb 2020 04:15:43 +0000 Subject: [PATCH 12/40] VFS: Fix handle leak when double-mapping (fixes #1659) --- CHANGES | 1 + src/util/vfs/vfs-fd.c | 44 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 74c367ca8..c1233dcaa 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ Other fixes: - Qt: Fix window title not updating after shutting down game - Qt: Fix GIF view not allowing manual filename entry - Util: Fix crash reading invalid ELFs + - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: - FFmpeg: Add more presets - Qt: Renderer can be changed while a game is running diff --git a/src/util/vfs/vfs-fd.c b/src/util/vfs/vfs-fd.c index ed2222551..6e8002a3b 100644 --- a/src/util/vfs/vfs-fd.c +++ b/src/util/vfs/vfs-fd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015 Jeffrey Pfau +/* 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 @@ -14,11 +14,23 @@ #include #endif +#include + +#ifdef _WIN32 +struct HandleMappingTuple { + HANDLE handle; + void* mapping; +}; + +DECLARE_VECTOR(HandleMappingList, struct HandleMappingTuple); +DEFINE_VECTOR(HandleMappingList, struct HandleMappingTuple); +#endif + struct VFileFD { struct VFile d; int fd; #ifdef _WIN32 - HANDLE hMap; + struct HandleMappingList handles; #endif }; @@ -74,12 +86,23 @@ struct VFile* VFileFromFD(int fd) { vfd->d.truncate = _vfdTruncate; vfd->d.size = _vfdSize; vfd->d.sync = _vfdSync; +#ifdef _WIN32 + HandleMappingListInit(&vfd->handles, 4); +#endif return &vfd->d; } bool _vfdClose(struct VFile* vf) { struct VFileFD* vfd = (struct VFileFD*) vf; +#ifdef _WIN32 + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + UnmapViewOfFile(HandleMappingListGetPointer(&vfd->handles, i)->mapping); + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + } + HandleMappingListDeinit(&vfd->handles); +#endif if (close(vfd->fd) < 0) { return false; } @@ -134,16 +157,25 @@ static void* _vfdMap(struct VFile* vf, size_t size, int flags) { if (size > fileSize) { size = fileSize; } - vfd->hMap = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); - return MapViewOfFile(vfd->hMap, mapFiles, 0, 0, size); + struct HandleMappingTuple tuple = {0}; + tuple.handle = CreateFileMapping((HANDLE) _get_osfhandle(vfd->fd), 0, createFlags, 0, size & 0xFFFFFFFF, 0); + tuple.mapping = MapViewOfFile(tuple.handle, mapFiles, 0, 0, size); + *HandleMappingListAppend(&vfd->handles) = tuple; + return tuple.mapping; } static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) { UNUSED(size); struct VFileFD* vfd = (struct VFileFD*) vf; + size_t i; + for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { + if (HandleMappingListGetPointer(&vfd->handles, i)->mapping == memory) { + CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); + HandleMappingListShift(&vfd->handles, i, 1); + break; + } + } UnmapViewOfFile(memory); - CloseHandle(vfd->hMap); - vfd->hMap = 0; } #endif From fa724d297d55318b0f57feade69fcd24f6058b2d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 6 Feb 2020 19:22:34 -0800 Subject: [PATCH 13/40] CMake: Include namelink in dev package --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfbcf9c1f..8c83bfc69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -842,6 +842,7 @@ if(NOT SKIP_LIBRARY) target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) + install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}-dev NAMELINK_ONLY) if(UNIX AND NOT APPLE AND NOT HAIKU) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) From 7c0f3842a064ec6bd6722d93da9dec399f48ee54 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 6 Feb 2020 19:44:34 -0800 Subject: [PATCH 14/40] CMake: Fix static build --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c83bfc69..e04e46e56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -842,7 +842,9 @@ if(NOT SKIP_LIBRARY) target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) - install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}-dev NAMELINK_ONLY) + if(BUILD_SHARED) + install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT ${BINARY_NAME}-dev NAMELINK_ONLY) + endif() if(UNIX AND NOT APPLE AND NOT HAIKU) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-16.png DESTINATION share/icons/hicolor/16x16/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/res/mgba-24.png DESTINATION share/icons/hicolor/24x24/apps RENAME mgba.png COMPONENT ${BINARY_NAME}) From 5d20aac7ed1f9d60012d9128e754bfcbee9939ba Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 8 Feb 2020 13:34:38 -0800 Subject: [PATCH 15/40] VFS: Fix unmapping order on Win32 --- src/util/vfs/vfs-fd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/vfs/vfs-fd.c b/src/util/vfs/vfs-fd.c index 6e8002a3b..dde239717 100644 --- a/src/util/vfs/vfs-fd.c +++ b/src/util/vfs/vfs-fd.c @@ -170,12 +170,12 @@ static void _vfdUnmap(struct VFile* vf, void* memory, size_t size) { size_t i; for (i = 0; i < HandleMappingListSize(&vfd->handles); ++i) { if (HandleMappingListGetPointer(&vfd->handles, i)->mapping == memory) { + UnmapViewOfFile(memory); CloseHandle(HandleMappingListGetPointer(&vfd->handles, i)->handle); HandleMappingListShift(&vfd->handles, i, 1); break; } } - UnmapViewOfFile(memory); } #endif From 4f327de2102f47e2641dca2cda94688058497866 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 8 Feb 2020 17:46:56 -0800 Subject: [PATCH 16/40] Wii: Add network socket support --- include/mgba-util/socket.h | 83 +++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/include/mgba-util/socket.h b/include/mgba-util/socket.h index e0c52fb99..aecbe9959 100644 --- a/include/mgba-util/socket.h +++ b/include/mgba-util/socket.h @@ -20,15 +20,21 @@ CXX_GUARD_START #define SOCKET_FAILED(s) ((s) == INVALID_SOCKET) typedef SOCKET Socket; #else +#ifdef GEKKO +#include +#else #include -#include -#include #include #include -#include #include +#endif +#include +#include +#include +#ifndef GEKKO #define INVALID_SOCKET (-1) +#endif #define SOCKET_FAILED(s) ((s) < 0) typedef int Socket; #endif @@ -70,6 +76,8 @@ static inline void SocketSubsystemInit() { } #elif defined(__SWITCH__) socketInitializeDefault(); +#elif defined(GEKKO) + net_init(); #endif } @@ -82,6 +90,8 @@ static inline void SocketSubsystemDeinit() { SOCUBuffer = NULL; #elif defined(__SWITCH__) socketExit(); +#elif defined(GEKKO) + net_deinit(); #endif } @@ -104,6 +114,8 @@ static inline bool SocketWouldBlock() { static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) { #ifdef _WIN32 return send(socket, (const char*) buffer, size, 0); +#elif defined(GEKKO) + return net_write(socket, buffer, size); #else return write(socket, buffer, size); #endif @@ -112,6 +124,8 @@ static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) { #if defined(_WIN32) || defined(__SWITCH__) return recv(socket, (char*) buffer, size, 0); +#elif defined(GEKKO) + return net_read(socket, buffer, size); #else return read(socket, buffer, size); #endif @@ -120,13 +134,19 @@ static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) { static inline int SocketClose(Socket socket) { #ifdef _WIN32 return closesocket(socket) == 0; +#elif defined(GEKKO) + return net_close(socket) >= 0; #else return close(socket) >= 0; #endif } static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) { +#ifdef GEKKO + Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +#else Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#endif if (SOCKET_FAILED(sock)) { return sock; } @@ -142,15 +162,23 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) #else bindInfo.sin_addr.s_addr = gethostid(); #endif +#ifdef GEKKO + err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#endif } else if (bindAddress->version == IPV4) { struct sockaddr_in bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); bindInfo.sin_addr.s_addr = htonl(bindAddress->ipv4); +#ifdef GEKKO + err = net_bind(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); @@ -168,7 +196,11 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) } static inline Socket SocketConnectTCP(int port, const struct Address* destinationAddress) { +#ifdef GEKKO + Socket sock = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +#else Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#endif if (SOCKET_FAILED(sock)) { return sock; } @@ -179,15 +211,23 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); +#ifdef GEKKO + err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#endif } else if (destinationAddress->version == IPV4) { struct sockaddr_in bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); bindInfo.sin_family = AF_INET; bindInfo.sin_port = htons(port); bindInfo.sin_addr.s_addr = htonl(destinationAddress->ipv4); +#ifdef GEKKO + err = net_connect(sock, (struct sockaddr*) &bindInfo, sizeof(bindInfo)); +#else err = connect(sock, (const struct sockaddr*) &bindInfo, sizeof(bindInfo)); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 bindInfo; memset(&bindInfo, 0, sizeof(bindInfo)); @@ -206,12 +246,23 @@ static inline Socket SocketConnectTCP(int port, const struct Address* destinatio } static inline Socket SocketListen(Socket socket, int queueLength) { +#ifdef GEKKO + return net_listen(socket, queueLength); +#else return listen(socket, queueLength); +#endif } static inline Socket SocketAccept(Socket socket, struct Address* address) { if (!address) { +#ifdef GEKKO + struct sockaddr_in addrInfo; + memset(&addrInfo, 0, sizeof(addrInfo)); + socklen_t len = sizeof(addrInfo); + return net_accept(socket, (struct sockaddr*) &addrInfo, &len); +#else return accept(socket, 0, 0); +#endif } if (address->version == IPV4) { struct sockaddr_in addrInfo; @@ -219,8 +270,12 @@ static inline Socket SocketAccept(Socket socket, struct Address* address) { addrInfo.sin_family = AF_INET; addrInfo.sin_addr.s_addr = address->ipv4; socklen_t len = sizeof(addrInfo); +#ifdef GEKKO + return net_accept(socket, (struct sockaddr*) &addrInfo, &len); +#else return accept(socket, (struct sockaddr*) &addrInfo, &len); -#ifndef _3DS +#endif +#if !defined(_3DS) && !defined(GEKKO) } else { struct sockaddr_in6 addrInfo; memset(&addrInfo, 0, sizeof(addrInfo)); @@ -237,8 +292,12 @@ static inline int SocketSetBlocking(Socket socket, bool blocking) { #ifdef _WIN32 u_long unblocking = !blocking; return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR; +#else +#ifdef GEKKO + int flags = net_fcntl(socket, F_GETFL, 0); #else int flags = fcntl(socket, F_GETFL); +#endif if (flags == -1) { return 0; } @@ -247,12 +306,20 @@ static inline int SocketSetBlocking(Socket socket, bool blocking) { } else { flags |= O_NONBLOCK; } +#ifdef GEKKO + return net_fcntl(socket, F_SETFL, flags) >= 0; +#else return fcntl(socket, F_SETFL, flags) >= 0; #endif +#endif } static inline int SocketSetTCPPush(Socket socket, int push) { +#ifdef GEKKO + return net_setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0; +#else return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0; +#endif } static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Socket* errors, int64_t timeoutMillis) { @@ -304,7 +371,11 @@ static inline int SocketPoll(size_t nSockets, Socket* reads, Socket* writes, Soc struct timeval tv; tv.tv_sec = timeoutMillis / 1000; tv.tv_usec = (timeoutMillis % 1000) * 1000; +#ifdef GEKKO + int result = net_select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv); +#else int result = select(maxFd, &rset, &wset, &eset, timeoutMillis < 0 ? 0 : &tv); +#endif int r = 0; int w = 0; int e = 0; From a3857c74720acff2a3e13dc7e2b92fb6fd73b57f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 8 Feb 2020 17:47:32 -0800 Subject: [PATCH 17/40] Wii: Support mgba-perf --- src/platform/test/perf-main.c | 38 +++++++++++++++++++++++++++++++++ src/platform/wii/CMakeLists.txt | 11 ++++++++++ src/platform/wii/main.c | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/platform/test/perf-main.c b/src/platform/test/perf-main.c index 97066fb36..ccedf267b 100644 --- a/src/platform/test/perf-main.c +++ b/src/platform/test/perf-main.c @@ -22,6 +22,14 @@ #ifdef __SWITCH__ #include #endif +#ifdef GEKKO +#include +#include +#ifdef FIXED_ROM_BUFFER +uint32_t* romBuffer; +size_t romBufferSize; +#endif +#endif #include #include @@ -83,6 +91,29 @@ int main(int argc, char** argv) { #elif defined(__SWITCH__) UNUSED(_mPerfShutdown); consoleInit(NULL); +#elif defined(GEKKO) + VIDEO_Init(); + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + GXRModeObj* vmode = VIDEO_GetPreferredMode(0); + void* xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode)); + console_init(xfb, 20, 20, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * VI_DISPLAY_PIX_SZ); + + VIDEO_Configure(vmode); + VIDEO_SetNextFramebuffer(xfb); + VIDEO_SetBlack(false); + VIDEO_Flush(); + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); + fatInitDefault(); + +#ifdef FIXED_ROM_BUFFER + romBufferSize = 0x02000000; + romBuffer = SYS_GetArena2Lo(); + SYS_SetArena2Lo((void*)((intptr_t) romBuffer + romBufferSize)); +#endif #else signal(SIGINT, _mPerfShutdown); #endif @@ -125,6 +156,8 @@ int main(int argc, char** argv) { puts("game_code,frames,duration,renderer"); #ifdef __SWITCH__ consoleUpdate(NULL); +#elif defined(GEKKO) + VIDEO_WaitVSync(); #endif } if (perfOpts.server) { @@ -145,6 +178,11 @@ int main(int argc, char** argv) { acExit(); #elif defined(__SWITCH__) consoleExit(NULL); +#elif defined(GEKKO) + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); + VIDEO_WaitVSync(); #endif return didFail; diff --git a/src/platform/wii/CMakeLists.txt b/src/platform/wii/CMakeLists.txt index 4caf73d10..d0a1a7821 100644 --- a/src/platform/wii/CMakeLists.txt +++ b/src/platform/wii/CMakeLists.txt @@ -11,6 +11,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c) list(APPEND OS_LIB wiiuse bte fat ogc) set(OS_SRC ${OS_SRC} PARENT_SCOPE) +set(OS_LIB ${OS_LIB} PARENT_SCOPE) source_group("Wii-specific code" FILES ${OS_SRC}) set(CORE_VFS_SRC ${CORE_VFS_SRC} PARENT_SCOPE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) @@ -39,6 +40,16 @@ add_custom_target(${BINARY_NAME}.dol ALL add_custom_target(run ${WIILOAD} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.dol DEPENDS ${BINARY_NAME}.dol) +if(BUILD_PERF) + add_custom_target(${BINARY_NAME}-perf.dol ALL + ${ELF2DOL} ../${BINARY_NAME}-perf ${BINARY_NAME}-perf.dol + DEPENDS ${BINARY_NAME}-perf) + + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}-perf.dol + DESTINATION . COMPONENT ${BINARY_NAME}-perf) +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/meta.xml.in ${CMAKE_CURRENT_BINARY_DIR}/meta.xml) install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 63d48214b..769469b43 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -262,7 +262,7 @@ int main(int argc, char* argv[]) { #ifdef FIXED_ROM_BUFFER romBufferSize = SIZE_CART0; romBuffer = SYS_GetArena2Lo(); - SYS_SetArena2Lo((void*)((intptr_t) romBuffer + SIZE_CART0)); + SYS_SetArena2Lo((void*)((intptr_t) romBuffer + romBufferSize)); #endif #if !defined(COLOR_16_BIT) && !defined(COLOR_5_6_5) From 2f643d79445b3cfb4d84ea6167d2c0bf005b855c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Feb 2020 14:25:37 -0800 Subject: [PATCH 18/40] FFmpeg: Add APNG recording and looping support --- CHANGES | 3 + src/feature/ffmpeg/ffmpeg-encoder.c | 11 ++++ src/feature/ffmpeg/ffmpeg-encoder.h | 2 + src/platform/qt/GIFView.cpp | 14 +++-- src/platform/qt/GIFView.ui | 94 +++++++++++++++++++++-------- src/platform/qt/Window.cpp | 2 +- 6 files changed, 95 insertions(+), 31 deletions(-) diff --git a/CHANGES b/CHANGES index c1233dcaa..642e2cf5f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ 0.9.0: (Future) +Features: + - Add APNG recording Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation @@ -34,6 +36,7 @@ Other fixes: - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: - FFmpeg: Add more presets + - FFmpeg: Add looping option for GIF/APNG - Qt: Renderer can be changed while a game is running - Qt: Fix non-SDL build (fixes mgba.io/i/1656) - Switch: Make OpenGL scale adjustable while running diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 3a67ca883..ca6272f4f 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -61,6 +61,7 @@ void FFmpegEncoderInit(struct FFmpegEncoder* encoder) { encoder->iheight = GBA_VIDEO_VERTICAL_PIXELS; encoder->frameskip = 1; encoder->skipResidue = 0; + encoder->loop = false; encoder->ipixFormat = #ifdef COLOR_16_BIT #ifdef COLOR_5_6_5 @@ -228,6 +229,10 @@ void FFmpegEncoderSetDimensions(struct FFmpegEncoder* encoder, int width, int he encoder->height = height > 0 ? height : GBA_VIDEO_VERTICAL_PIXELS; } +void FFmpegEncoderSetLooping(struct FFmpegEncoder* encoder, bool loop) { + encoder->loop = loop; +} + bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) { AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec); @@ -469,6 +474,12 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { #endif } + if (strcmp(encoder->containerFormat, "gif") == 0) { + av_opt_set(encoder->context->priv_data, "loop", encoder->loop ? "0" : "-1", 0); + } else if (strcmp(encoder->containerFormat, "apng") == 0) { + av_opt_set(encoder->context->priv_data, "plays", encoder->loop ? "0" : "1", 0); + } + AVDictionary* opts = 0; av_dict_set(&opts, "strict", "-2", 0); bool res = avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0 || avformat_write_header(encoder->context, &opts) < 0; diff --git a/src/feature/ffmpeg/ffmpeg-encoder.h b/src/feature/ffmpeg/ffmpeg-encoder.h index 49d386cdc..9c2366277 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.h +++ b/src/feature/ffmpeg/ffmpeg-encoder.h @@ -80,6 +80,7 @@ struct FFmpegEncoder { int iheight; int frameskip; int skipResidue; + bool loop; int64_t currentVideoFrame; struct SwsContext* scaleContext; struct AVStream* videoStream; @@ -96,6 +97,7 @@ bool FFmpegEncoderSetAudio(struct FFmpegEncoder*, const char* acodec, unsigned a bool FFmpegEncoderSetVideo(struct FFmpegEncoder*, const char* vcodec, unsigned vbr, int frameskip); bool FFmpegEncoderSetContainer(struct FFmpegEncoder*, const char* container); void FFmpegEncoderSetDimensions(struct FFmpegEncoder*, int width, int height); +void FFmpegEncoderSetLooping(struct FFmpegEncoder*, bool loop); bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder*); bool FFmpegEncoderOpen(struct FFmpegEncoder*, const char* outfile); void FFmpegEncoderClose(struct FFmpegEncoder*); diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index eda022538..2ef882741 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -28,7 +28,6 @@ GIFView::GIFView(QWidget* parent) FFmpegEncoderInit(&m_encoder); FFmpegEncoderSetAudio(&m_encoder, nullptr, 0); - FFmpegEncoderSetContainer(&m_encoder, "gif"); } GIFView::~GIFView() { @@ -44,9 +43,16 @@ void GIFView::setController(std::shared_ptr controller) { } void GIFView::startRecording() { - FFmpegEncoderSetVideo(&m_encoder, "gif", 0, m_ui.frameskip->value()); + if (m_ui.fmtApng->isChecked()) { + FFmpegEncoderSetContainer(&m_encoder, "apng"); + FFmpegEncoderSetVideo(&m_encoder, "apng", 0, m_ui.frameskip->value()); + } else { + FFmpegEncoderSetContainer(&m_encoder, "gif"); + FFmpegEncoderSetVideo(&m_encoder, "gif", 0, m_ui.frameskip->value()); + } + FFmpegEncoderSetLooping(&m_encoder, m_ui.loop->isChecked()); if (!FFmpegEncoderOpen(&m_encoder, m_filename.toUtf8().constData())) { - LOG(QT, ERROR) << tr("Failed to open output GIF file: %1").arg(m_filename); + LOG(QT, ERROR) << tr("Failed to open output GIF or APNG file: %1").arg(m_filename); return; } m_ui.start->setEnabled(false); @@ -64,7 +70,7 @@ void GIFView::stopRecording() { } void GIFView::selectFile() { - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif)")); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select output file"), tr("Graphics Interchange Format (*.gif);;Animated Portable Network Graphics (*.png *.apng)")); m_ui.filename->setText(filename); } diff --git a/src/platform/qt/GIFView.ui b/src/platform/qt/GIFView.ui index 57dab1cd7..7c43319a2 100644 --- a/src/platform/qt/GIFView.ui +++ b/src/platform/qt/GIFView.ui @@ -7,50 +7,42 @@ 0 0 392 - 220 + 262 - Record GIF + Record GIF/APNG QLayout::SetFixedSize - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + - Frameskip + APNG + + format + - + + + + 0 + 0 + + + + 9 + 2 - - - - QDialogButtonBox::Close - - - @@ -123,8 +115,55 @@ + + + + Frameskip + + + + + + + QDialogButtonBox::Close + + + + + + + GIF + + + true + + + format + + + + + + + Loop + + + true + + + + + filename + start + stop + selectFile + fmtGif + fmtApng + loop + frameskip + @@ -144,4 +183,7 @@ + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 201c4cc28..ce74ccf5a 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1455,7 +1455,7 @@ void Window::setupMenu(QMenuBar* menubar) { #ifdef USE_FFMPEG addGameAction(tr("Record A/V..."), "recordOutput", this, &Window::openVideoWindow, "av"); - addGameAction(tr("Record GIF..."), "recordGIF", this, &Window::openGIFWindow, "av"); + addGameAction(tr("Record GIF/APNG..."), "recordGIF", this, &Window::openGIFWindow, "av"); #endif m_actions.addSeparator("av"); From 3201c984e8d62d72125263b743d59e95aa4a1649 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Feb 2020 15:56:42 -0800 Subject: [PATCH 19/40] Qt: Fix non-GB build (fixes #1664) --- CHANGES | 1 + src/platform/qt/MultiplayerController.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 642e2cf5f..6bf0dcf9f 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Other fixes: - Qt: Fix extraneous dialog (fixes mgba.io/i/1654) - Qt: Fix window title not updating after shutting down game - Qt: Fix GIF view not allowing manual filename entry + - Qt: Fix non-GB build (fixes mgba.io/i/1664) - Util: Fix crash reading invalid ELFs - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: diff --git a/src/platform/qt/MultiplayerController.cpp b/src/platform/qt/MultiplayerController.cpp index ca2f048d3..352e9d325 100644 --- a/src/platform/qt/MultiplayerController.cpp +++ b/src/platform/qt/MultiplayerController.cpp @@ -16,11 +16,13 @@ using namespace QGBA; +#ifdef M_CORE_GB MultiplayerController::Player::Player(CoreController* coreController, GBSIOLockstepNode* node) : controller(coreController) , gbNode(node) { } +#endif #ifdef M_CORE_GBA MultiplayerController::Player::Player(CoreController* coreController, GBASIOLockstepNode* node) From ce400fd827c32ae88113b6d30b54087318b4623c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Feb 2020 22:05:02 -0800 Subject: [PATCH 20/40] Qt: GIF view consistency --- src/platform/qt/GIFView.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index 2ef882741..0662bfdeb 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -58,6 +58,9 @@ void GIFView::startRecording() { m_ui.start->setEnabled(false); m_ui.stop->setEnabled(true); m_ui.frameskip->setEnabled(false); + m_ui.loop->setEnabled(false); + m_ui.fmtApng->setEnabled(false); + m_ui.fmtGif->setEnabled(false); emit recordingStarted(&m_encoder.d); } @@ -67,6 +70,9 @@ void GIFView::stopRecording() { m_ui.stop->setEnabled(false); m_ui.start->setEnabled(!m_filename.isEmpty()); m_ui.frameskip->setEnabled(true); + m_ui.loop->setEnabled(true); + m_ui.fmtApng->setEnabled(true); + m_ui.fmtGif->setEnabled(true); } void GIFView::selectFile() { From f5f1cbf037e94c665a698eaa21be7311a75f3f83 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2020 18:03:48 -0800 Subject: [PATCH 21/40] GBA BIOS: Fix undefined instruction HLE behavior --- CHANGES | 1 + src/gba/hle-bios.c | 7 ++++--- src/gba/hle-bios.s | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 6bf0dcf9f..684444f5f 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation - GB Serialize: Fix timing bug loading channel 4 timing + - GBA BIOS: Fix undefined instruction HLE behavior - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing diff --git a/src/gba/hle-bios.c b/src/gba/hle-bios.c index 776c3d550..8903ca0ac 100644 --- a/src/gba/hle-bios.c +++ b/src/gba/hle-bios.c @@ -3,10 +3,10 @@ #include const uint8_t hleBios[SIZE_BIOS] = { - 0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x0b, 0x00, 0x00, 0xea, + 0x06, 0x00, 0x00, 0xea, 0x88, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1, 0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, - 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0xf8, 0x01, 0x9f, 0x15, + 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x04, 0x02, 0x9f, 0x15, 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3, @@ -49,5 +49,6 @@ const uint8_t hleBios[SIZE_BIOS] = { 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, - 0xf0, 0x87, 0xbd, 0xe8, 0xc0, 0x00, 0x00, 0x02 + 0xf0, 0x87, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xe0, 0xa0, 0x03, 0xc0, 0x00, 0x00, 0x02 }; diff --git a/src/gba/hle-bios.s b/src/gba/hle-bios.s index 96de3ad61..bb7eb0c43 100644 --- a/src/gba/hle-bios.s +++ b/src/gba/hle-bios.s @@ -187,4 +187,9 @@ blt 0b 2: ldmfd sp!, {r4-r10, pc} +undefBase: +subs pc, lr, #4 +.word 0 +.word 0x03A0E004 + .ltorg From 75e67aee17067a1a58bf8a3fc65926fcada68f2c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2020 18:06:06 -0800 Subject: [PATCH 22/40] Debugger: Don't skip undefined instructions when debugger attached --- CHANGES | 1 + src/gba/gba.c | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 684444f5f..444c0a8af 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Other fixes: - Core: Fix race condition initializing thread proxy - Core: Ensure ELF regions can be written before trying - Core: Fix integer overflow in ELF loading + - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container - FFmpeg: Disallow recording video with no audio nor video - Qt: Only dynamically reset video scale if a game is running diff --git a/src/gba/gba.c b/src/gba/gba.c index d145ce214..8dd40d492 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -742,11 +742,9 @@ void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { .type.bp.opcode = opcode }; mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info); - } else -#endif - { - ARMRaiseUndefined(cpu); } +#endif + ARMRaiseUndefined(cpu); } void GBABreakpoint(struct ARMCore* cpu, int immediate) { From 0670eebe15083c4a58ae7f181598ddeba3a0d5d2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2020 18:06:57 -0800 Subject: [PATCH 23/40] GBA: Fix multiboot entry point while skipping BIOS --- CHANGES | 1 + src/gba/gba.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 444c0a8af..d3122f5c6 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation - GB Serialize: Fix timing bug loading channel 4 timing + - GBA: Fix multiboot entry point while skipping BIOS - GBA BIOS: Fix undefined instruction HLE behavior - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Misaligned SRAM writes are ignored diff --git a/src/gba/gba.c b/src/gba/gba.c index 8dd40d492..2e9e3ec65 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -253,7 +253,7 @@ void GBASkipBIOS(struct GBA* gba) { if (gba->memory.rom) { cpu->gprs[ARM_PC] = BASE_CART0; } else { - cpu->gprs[ARM_PC] = BASE_WORKING_RAM; + cpu->gprs[ARM_PC] = BASE_WORKING_RAM + 0xC0; } gba->video.vcount = 0x7D; gba->memory.io[REG_VCOUNT >> 1] = 0x7D; From fb12372ae3e5b71b9c2fc07657bd2601f842709e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2020 18:08:07 -0800 Subject: [PATCH 24/40] GBA: Automatically skip BIOS for multiboot ROMs --- CHANGES | 1 + src/gba/core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d3122f5c6..234cffb8c 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,7 @@ Other fixes: - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container - FFmpeg: Disallow recording video with no audio nor video + - GBA: Automatically skip BIOS for multiboot ROMs - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/src/gba/core.c b/src/gba/core.c index ab64241a9..46cf7f5e5 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -636,7 +636,7 @@ static void _GBACoreReset(struct mCore* core) { #endif ARMReset(core->cpu); - if (core->opts.skipBios && (gba->romVf || gba->memory.rom)) { + if ((core->opts.skipBios && (gba->romVf || gba->memory.rom)) || (gba->romVf && GBAIsMB(gba->romVf))) { GBASkipBIOS(core->board); } } From afbf3f8e34c9bf21ef5daa0b4ba4800b40e0602f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 10 Feb 2020 18:13:19 -0800 Subject: [PATCH 25/40] Qt: Minor GIF view UX improvement --- src/platform/qt/GIFView.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index 0662bfdeb..02c3b0f02 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -84,6 +84,11 @@ void GIFView::setFilename(const QString& filename) { m_filename = filename; if (!FFmpegEncoderIsOpen(&m_encoder)) { m_ui.start->setEnabled(!filename.isEmpty()); + if (filename.endsWith(".gif")) { + m_ui.fmtGif->setChecked(Qt::Checked); + } else if (filename.endsWith(".png") || filename.endsWith(".apng")) { + m_ui.fmtApng->setChecked(Qt::Checked); + } } } From 00b46d704121e5b19afd31719ea7d5176cfd68f1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 11 Feb 2020 02:14:39 +0000 Subject: [PATCH 26/40] SDL: Use DirectSound audio driver by default on Windows --- CHANGES | 1 + src/platform/sdl/sdl-audio.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index 234cffb8c..30d404918 100644 --- a/CHANGES +++ b/CHANGES @@ -44,6 +44,7 @@ Misc: - FFmpeg: Add looping option for GIF/APNG - Qt: Renderer can be changed while a game is running - Qt: Fix non-SDL build (fixes mgba.io/i/1656) + - SDL: Use DirectSound audio driver by default on Windows - Switch: Make OpenGL scale adjustable while running 0.8.0: (2020-01-21) diff --git a/src/platform/sdl/sdl-audio.c b/src/platform/sdl/sdl-audio.c index ab0bd830b..f1666aa4e 100644 --- a/src/platform/sdl/sdl-audio.c +++ b/src/platform/sdl/sdl-audio.c @@ -19,6 +19,11 @@ mLOG_DEFINE_CATEGORY(SDL_AUDIO, "SDL Audio", "platform.sdl.audio"); static void _mSDLAudioCallback(void* context, Uint8* data, int len); bool mSDLInitAudio(struct mSDLAudio* context, struct mCoreThread* threadContext) { +#if defined(_WIN32) && SDL_VERSION_ATLEAST(2, 0, 8) + if (!getenv("SDL_AUDIODRIVER")) { + _putenv_s("SDL_AUDIODRIVER", "directsound"); + } +#endif if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { mLOG(SDL_AUDIO, ERROR, "Could not initialize SDL sound system: %s", SDL_GetError()); return false; From 7ea3728165d15c4442ac9bed5510e91ae148fd5c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Feb 2020 23:41:25 -0800 Subject: [PATCH 27/40] GBA BIOS: Implement dummy sound driver calls --- CHANGES | 1 + include/mgba/internal/gba/bios.h | 46 +++++++++++ src/gba/bios.c | 63 ++++++++------- src/gba/hle-bios.c | 92 +++++++++++++--------- src/gba/hle-bios.s | 129 ++++++++++++++++++++++++++----- 5 files changed, 245 insertions(+), 86 deletions(-) diff --git a/CHANGES b/CHANGES index 30d404918..4a1b780b7 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Emulation fixes: - GB Serialize: Fix timing bug loading channel 4 timing - GBA: Fix multiboot entry point while skipping BIOS - GBA BIOS: Fix undefined instruction HLE behavior + - GBA BIOS: Implement dummy sound driver calls - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing diff --git a/include/mgba/internal/gba/bios.h b/include/mgba/internal/gba/bios.h index a89edfd68..40bbf3237 100644 --- a/include/mgba/internal/gba/bios.h +++ b/include/mgba/internal/gba/bios.h @@ -14,6 +14,52 @@ CXX_GUARD_START mLOG_DECLARE_CATEGORY(GBA_BIOS); +enum GBASwi { + GBA_SWI_SOFT_RESET = 0x00, + GBA_SWI_REGISTER_RAM_RESET = 0x01, + GBA_SWI_HALT = 0x02, + GBA_SWI_STOP = 0x03, + GBA_SWI_INTR_WAIT = 0x04, + GBA_SWI_VBLANK_INTR_WAIT = 0x05, + GBA_SWI_DIV = 0x06, + GBA_SWI_DIV_ARM = 0x07, + GBA_SWI_SQRT = 0x08, + GBA_SWI_ARCTAN = 0x09, + GBA_SWI_ARCTAN2 = 0x0A, + GBA_SWI_CPU_SET = 0x0B, + GBA_SWI_CPU_FAST_SET = 0x0C, + GBA_SWI_GET_BIOS_CHECKSUM = 0x0D, + GBA_SWI_BG_AFFINE_SET = 0x0E, + GBA_SWI_OBJ_AFFINE_SET = 0x0F, + GBA_SWI_BIT_UNPACK = 0x10, + GBA_SWI_LZ77_UNCOMP_WRAM = 0x11, + GBA_SWI_LZ77_UNCOMP_VRAM = 0x12, + GBA_SWI_HUFFMAN_UNCOMP = 0x13, + GBA_SWI_RL_UNCOMP_WRAM = 0x14, + GBA_SWI_RL_UNCOMP_VRAM = 0x15, + GBA_SWI_DIFF_8BIT_UNFILTER_WRAM = 0x16, + GBA_SWI_DIFF_8BIT_UNFILTER_VRAM = 0x17, + GBA_SWI_DIFF_16BIT_UNFILTER = 0x18, + GBA_SWI_SOUND_BIAS = 0x19, + GBA_SWI_SOUND_DRIVER_INIT = 0x1A, + GBA_SWI_SOUND_DRIVER_MODE = 0x1B, + GBA_SWI_SOUND_DRIVER_MAIN = 0x1C, + GBA_SWI_SOUND_DRIVER_VSYNC = 0x1D, + GBA_SWI_SOUND_CHANNEL_CLEAR = 0x1E, + GBA_SWI_MIDI_KEY_2_FREQ = 0x1F, + GBA_SWI_MUSIC_PLAYER_OPEN = 0x20, + GBA_SWI_MUSIC_PLAYER_START = 0x21, + GBA_SWI_MUSIC_PLAYER_STOP = 0x22, + GBA_SWI_MUSIC_PLAYER_CONTINUE = 0x23, + GBA_SWI_MUSIC_PLAYER_FADE_OUT = 0x24, + GBA_SWI_MULTI_BOOT = 0x25, + GBA_SWI_HARD_RESET = 0x26, + GBA_SWI_CUSTOM_HALT = 0x27, + GBA_SWI_SOUND_DRIVER_VSYNC_OFF = 0x28, + GBA_SWI_SOUND_DRIVER_VSYNC_ON = 0x29, + GBA_SWI_SOUND_DRIVER_GET_JUMP_LIST = 0x2A, +}; + struct ARMCore; void GBASwi16(struct ARMCore* cpu, int immediate); void GBASwi32(struct ARMCore* cpu, int immediate); diff --git a/src/gba/bios.c b/src/gba/bios.c index a264354eb..f85b9c525 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -424,43 +424,43 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { return; } switch (immediate) { - case 0x0: + case GBA_SWI_SOFT_RESET: _SoftReset(gba); break; - case 0x1: + case GBA_SWI_REGISTER_RAM_RESET: _RegisterRamReset(gba); break; - case 0x2: + case GBA_SWI_HALT: GBAHalt(gba); break; - case 0x3: + case GBA_SWI_STOP: GBAStop(gba); break; - case 0x05: + case GBA_SWI_VBLANK_INTR_WAIT: // VBlankIntrWait // Fall through: - case 0x04: + case GBA_SWI_INTR_WAIT: // IntrWait ARMRaiseSWI(cpu); break; - case 0x6: + case GBA_SWI_DIV: _Div(gba, cpu->gprs[0], cpu->gprs[1]); break; - case 0x7: + case GBA_SWI_DIV_ARM: _Div(gba, cpu->gprs[1], cpu->gprs[0]); break; - case 0x8: + case GBA_SWI_SQRT: cpu->gprs[0] = _Sqrt(cpu->gprs[0], &cpu->cycles); break; - case 0x9: + case GBA_SWI_ARCTAN: cpu->gprs[0] = _ArcTan(cpu->gprs[0], &cpu->gprs[1], &cpu->gprs[3], &cpu->cycles); break; - case 0xA: + case GBA_SWI_ARCTAN2: cpu->gprs[0] = (uint16_t) _ArcTan2(cpu->gprs[0], cpu->gprs[1], &cpu->gprs[1], &cpu->cycles); cpu->gprs[3] = 0x170; break; - case 0xB: - case 0xC: + case GBA_SWI_CPU_SET: + case GBA_SWI_CPU_FAST_SET: if (cpu->gprs[0] >> BASE_OFFSET < REGION_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Cannot CpuSet from BIOS"); break; @@ -473,18 +473,18 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { } ARMRaiseSWI(cpu); break; - case 0xD: + case GBA_SWI_GET_BIOS_CHECKSUM: cpu->gprs[0] = GBA_BIOS_CHECKSUM; cpu->gprs[1] = 1; cpu->gprs[3] = SIZE_BIOS; break; - case 0xE: + case GBA_SWI_BG_AFFINE_SET: _BgAffineSet(gba); break; - case 0xF: + case GBA_SWI_OBJ_AFFINE_SET: _ObjAffineSet(gba); break; - case 0x10: + case GBA_SWI_BIT_UNPACK: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source"); break; @@ -500,8 +500,8 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; } break; - case 0x11: - case 0x12: + case GBA_SWI_LZ77_UNCOMP_WRAM: + case GBA_SWI_LZ77_UNCOMP_VRAM: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad LZ77 source"); break; @@ -513,11 +513,11 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unLz77(gba, immediate == 0x11 ? 1 : 2); + _unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2); break; } break; - case 0x13: + case GBA_SWI_HUFFMAN_UNCOMP: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad Huffman source"); break; @@ -533,8 +533,8 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; } break; - case 0x14: - case 0x15: + case GBA_SWI_RL_UNCOMP_WRAM: + case GBA_SWI_RL_UNCOMP_VRAM: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad RL source"); break; @@ -546,13 +546,13 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unRl(gba, immediate == 0x14 ? 1 : 2); + _unRl(gba, immediate == GBA_SWI_RL_UNCOMP_WRAM ? 1 : 2); break; } break; - case 0x16: - case 0x17: - case 0x18: + case GBA_SWI_DIFF_8BIT_UNFILTER_WRAM: + case GBA_SWI_DIFF_8BIT_UNFILTER_VRAM: + case GBA_SWI_DIFF_16BIT_UNFILTER: if (cpu->gprs[0] < BASE_WORKING_RAM) { mLOG(GBA_BIOS, GAME_ERROR, "Bad UnFilter source"); break; @@ -564,17 +564,20 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { case REGION_WORKING_RAM: case REGION_WORKING_IRAM: case REGION_VRAM: - _unFilter(gba, immediate == 0x18 ? 2 : 1, immediate == 0x16 ? 1 : 2); + _unFilter(gba, immediate == GBA_SWI_DIFF_16BIT_UNFILTER ? 2 : 1, immediate == GBA_SWI_DIFF_8BIT_UNFILTER_WRAM ? 1 : 2); break; } break; - case 0x19: + case GBA_SWI_SOUND_BIAS: // SoundBias is mostly meaningless here mLOG(GBA_BIOS, STUB, "Stub software interrupt: SoundBias (19)"); break; - case 0x1F: + case GBA_SWI_MIDI_KEY_2_FREQ: _MidiKey2Freq(gba); break; + case GBA_SWI_SOUND_DRIVER_GET_JUMP_LIST: + ARMRaiseSWI(cpu); + break; default: mLOG(GBA_BIOS, STUB, "Stub software interrupt: %02X", immediate); } diff --git a/src/gba/hle-bios.c b/src/gba/hle-bios.c index 8903ca0ac..20ce6648b 100644 --- a/src/gba/hle-bios.c +++ b/src/gba/hle-bios.c @@ -3,10 +3,10 @@ #include const uint8_t hleBios[SIZE_BIOS] = { - 0x06, 0x00, 0x00, 0xea, 0x88, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, + 0x06, 0x00, 0x00, 0xea, 0x58, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1, - 0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, - 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x04, 0x02, 0x9f, 0x15, + 0x4b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, + 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x14, 0x01, 0x9f, 0x15, 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3, @@ -16,39 +16,55 @@ const uint8_t hleBios[SIZE_BIOS] = { 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, 0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, - 0xd4, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, - 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, - 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, - 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, - 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, - 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, - 0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, - 0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, - 0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, - 0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9, - 0x02, 0x46, 0xa0, 0xe1, 0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, - 0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, - 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8, - 0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba, - 0x14, 0x00, 0x00, 0xea, 0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3, - 0xa4, 0x45, 0x85, 0xe0, 0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1, - 0xb2, 0x30, 0xc5, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea, - 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, - 0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8, - 0xfb, 0xff, 0xff, 0xba, 0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0, - 0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0, - 0xfb, 0xff, 0xff, 0xba, 0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8, - 0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1, - 0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5, - 0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1, - 0x03, 0x70, 0xa0, 0xe1, 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1, - 0x03, 0xa0, 0xa0, 0xe1, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, - 0xfc, 0xff, 0xff, 0xba, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, - 0xf8, 0x07, 0xb0, 0xb8, 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, - 0xf0, 0x87, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, - 0x04, 0xe0, 0xa0, 0x03, 0xc0, 0x00, 0x00, 0x02 + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, + 0x60, 0x02, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, + 0xb8, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x02, 0x0f, 0x50, 0x2d, 0xe9, + 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, + 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xc0, 0x5e, 0xe5, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xe0, 0xa0, 0x03, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x00, 0xa0, 0xe3, + 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, + 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, + 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, + 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5, 0x08, 0x02, 0xcc, 0xe5, + 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0, 0x01, 0x30, 0x23, 0x10, + 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5, 0xf7, 0xff, 0xff, 0x0a, + 0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9, 0x02, 0x46, 0xa0, 0xe1, + 0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3, + 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, + 0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8, 0x04, 0x00, 0x55, 0xe1, + 0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba, 0x14, 0x00, 0x00, 0xea, + 0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3, 0xa4, 0x45, 0x85, 0xe0, + 0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xc5, 0xb0, + 0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3, + 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1, + 0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8, 0xfb, 0xff, 0xff, 0xba, + 0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0, 0x04, 0x00, 0x55, 0xe1, + 0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0, 0xfb, 0xff, 0xff, 0xba, + 0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8, 0xf0, 0x47, 0x2d, 0xe9, + 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1, 0x23, 0x25, 0x81, 0xe0, + 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5, 0x03, 0x40, 0xa0, 0xe1, + 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1, 0x03, 0x70, 0xa0, 0xe1, + 0x03, 0x80, 0xa0, 0xe1, 0x03, 0x90, 0xa0, 0xe1, 0x03, 0xa0, 0xa0, 0xe1, + 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xa1, 0xb8, 0xfc, 0xff, 0xff, 0xba, + 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x51, 0xe1, 0xf8, 0x07, 0xb0, 0xb8, + 0xf8, 0x07, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, 0xf0, 0x87, 0xbd, 0xe8, + 0xf0, 0x07, 0x2d, 0xe9, 0x38, 0x10, 0x9f, 0xe5, 0x01, 0x30, 0xa0, 0xe1, + 0x01, 0x40, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, + 0x01, 0x70, 0xa0, 0xe1, 0x01, 0x80, 0xa0, 0xe1, 0x01, 0x90, 0xa0, 0xe1, + 0x01, 0xa0, 0xa0, 0xe1, 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, + 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0x00, 0x10, 0xa0, 0xe3, + 0xf0, 0x07, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x78, 0x01, 0x00, 0x00 }; diff --git a/src/gba/hle-bios.s b/src/gba/hle-bios.s index bb7eb0c43..9c5249c2c 100644 --- a/src/gba/hle-bios.s +++ b/src/gba/hle-bios.s @@ -52,20 +52,51 @@ movs pc, lr .word 0xE3A02004 swiTable: -.word SoftReset -.word RegisterRamReset -.word Halt -.word Stop -.word IntrWait -.word VBlankIntrWait -.word Div -.word DivArm -.word Sqrt -.word ArcTan -.word ArcTan2 -.word CpuSet -.word CpuFastSet -@ ... The rest of this table isn't needed if the rest aren't implemented +.word SoftReset @ 0x00 +.word RegisterRamReset @ 0x01 +.word Halt @ 0x02 +.word Stop @ 0x03 +.word IntrWait @ 0x04 +.word VBlankIntrWait @ 0x05 +.word Div @ 0x06 +.word DivArm @ 0x07 +.word Sqrt @ 0x08 +.word ArcTan @ 0x09 +.word ArcTan2 @ 0x0A +.word CpuSet @ 0x0B +.word CpuFastSet @ 0x0C +.word GetBiosChecksum @ 0x0D +.word BgAffineSet @ 0x0E +.word ObjAffineSet @ 0x0F +.word BitUnPack @ 0x10 +.word Lz77UnCompWram @ 0x11 +.word Lz77UnCompVram @ 0x12 +.word HuffmanUnComp @ 0x13 +.word RlUnCompWram @ 0x14 +.word RlUnCompVram @ 0x15 +.word Diff8BitUnFilterWram @ 0x16 +.word Diff8BitUnFilterVram @ 0x17 +.word Diff16BitUnFilter @ 0x18 +.word SoundBias @ 0x19 +.word SoundDriverInit @ 0x1A +.word SoundDriverMode @ 0x1B +.word SoundDriverMain @ 0x1C +.word SoundDriverVsync @ 0x1D +.word SoundChannelClear @ 0x1E +.word MidiKey2Freq @ 0x1F +.word MusicPlayerOpen @ 0x20 +.word MusicPlayerStart @ 0x21 +.word MusicPlayerStop @ 0x22 +.word MusicPlayerContinue @ 0x23 +.word MusicPlayerFadeOut @ 0x24 +.word MultiBoot @ 0x25 +.word HardReset @ 0x26 +.word CustomHalt @ 0x27 +.word SoundDriverVsyncOff @ 0x28 +.word SoundDriverVsyncOn @ 0x29 +.word SoundDriverGetJumpList @ 0x2A + +.ltorg irqBase: stmfd sp!, {r0-r3, r12, lr} @@ -77,6 +108,54 @@ subs pc, lr, #4 .word 0 .word 0xE55EC002 +undefBase: +subs pc, lr, #4 +.word 0 +.word 0x03A0E004 + +@ Unimplemented +SoftReset: +RegisterRamReset: +Halt: +Stop: +Div: +DivArm: +Sqrt: +ArcTan: +ArcTan2: +GetBiosChecksum: +BgAffineSet: +ObjAffineSet: +BitUnPack: +Lz77UnCompWram: +Lz77UnCompVram: +HuffmanUnComp: +RlUnCompWram: +RlUnCompVram: +Diff8BitUnFilterWram: +Diff8BitUnFilterVram: +Diff16BitUnFilter: +SoundBias: +SoundDriverInit: +SoundDriverMode: +SoundDriverMain: +SoundDriverVsync: +SoundChannelClear: +MidiKey2Freq: +MusicPlayerOpen: +MusicPlayerStart: +MusicPlayerStop: +MusicPlayerContinue: +MusicPlayerFadeOut: +MultiBoot: +HardReset: +CustomHalt: +SoundDriverVsyncOff: +SoundDriverVsyncOn: + +NopCall: +bx lr + VBlankIntrWait: mov r0, #1 mov r1, #1 @@ -187,9 +266,23 @@ blt 0b 2: ldmfd sp!, {r4-r10, pc} -undefBase: -subs pc, lr, #4 -.word 0 -.word 0x03A0E004 +SoundDriverGetJumpList: +stmfd sp!, {r4-r10} +ldr r1, =NopCall +mov r3, r1 +mov r4, r1 +mov r5, r1 +mov r6, r1 +mov r7, r1 +mov r8, r1 +mov r9, r1 +mov r10, r1 +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +stmia r0!, {r1, r3-r10} +mov r1, #0 +ldmfd sp!, {r4-r10} +bx lr .ltorg From 8a8b4add9172b537f041e7b1f02afee19a9b9e30 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Feb 2020 23:42:39 -0800 Subject: [PATCH 28/40] GBA BIOS: Improve HLE BIOS timing --- CHANGES | 1 + src/gba/bios.c | 10 ++++---- src/gba/hle-bios.c | 62 +++++++++++++++++++++++++--------------------- src/gba/hle-bios.s | 21 +++++++++++++++- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/CHANGES b/CHANGES index 4a1b780b7..8f12c5f95 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Emulation fixes: - GBA: Fix multiboot entry point while skipping BIOS - GBA BIOS: Fix undefined instruction HLE behavior - GBA BIOS: Implement dummy sound driver calls + - GBA BIOS: Improve HLE BIOS timing - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing diff --git a/src/gba/bios.c b/src/gba/bios.c index f85b9c525..b3c89f388 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -431,8 +431,8 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { _RegisterRamReset(gba); break; case GBA_SWI_HALT: - GBAHalt(gba); - break; + ARMRaiseSWI(cpu); + return; case GBA_SWI_STOP: GBAStop(gba); break; @@ -442,7 +442,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { case GBA_SWI_INTR_WAIT: // IntrWait ARMRaiseSWI(cpu); - break; + return; case GBA_SWI_DIV: _Div(gba, cpu->gprs[0], cpu->gprs[1]); break; @@ -472,7 +472,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { mLOG(GBA_BIOS, GAME_ERROR, "Misaligned CpuSet destination"); } ARMRaiseSWI(cpu); - break; + return; case GBA_SWI_GET_BIOS_CHECKSUM: cpu->gprs[0] = GBA_BIOS_CHECKSUM; cpu->gprs[1] = 1; @@ -577,7 +577,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; case GBA_SWI_SOUND_DRIVER_GET_JUMP_LIST: ARMRaiseSWI(cpu); - break; + return; default: mLOG(GBA_BIOS, STUB, "Stub software interrupt: %02X", immediate); } diff --git a/src/gba/hle-bios.c b/src/gba/hle-bios.c index 20ce6648b..920f7b92f 100644 --- a/src/gba/hle-bios.c +++ b/src/gba/hle-bios.c @@ -3,38 +3,44 @@ #include const uint8_t hleBios[SIZE_BIOS] = { - 0x06, 0x00, 0x00, 0xea, 0x58, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, + 0x06, 0x00, 0x00, 0xea, 0x66, 0x00, 0x00, 0xea, 0x0b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1, - 0x4b, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, - 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x14, 0x01, 0x9f, 0x15, + 0x59, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3, + 0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0x4c, 0x01, 0x9f, 0x15, 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1, 0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02, - 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3, + 0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0xd4, 0xc0, 0xa0, 0xe3, 0x0b, 0xb1, 0x9c, 0xe7, 0x00, 0x00, 0x5b, 0xe3, 0x00, 0xc0, 0x4f, 0xe1, 0x00, 0x10, 0x2d, 0xe9, 0x80, 0xc0, 0x0c, 0xe2, 0x1f, 0xc0, 0x8c, 0xe3, - 0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x0f, 0xe0, 0xa0, 0xe1, - 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, - 0x00, 0x10, 0xbd, 0xe8, 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, - 0x0e, 0xf0, 0xb0, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, - 0x60, 0x02, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, - 0xb8, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x02, 0x0f, 0x50, 0x2d, 0xe9, - 0x01, 0x03, 0xa0, 0xe3, 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, - 0x0f, 0x50, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xc0, 0x5e, 0xe5, 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, - 0x04, 0xe0, 0xa0, 0x03, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x00, 0xa0, 0xe3, + 0x0c, 0xf0, 0x29, 0xe1, 0x00, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x0f, 0xe0, 0xa0, 0xe1, 0x1b, 0xff, 0x2f, 0x11, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, + 0x00, 0x40, 0xbd, 0xe8, 0x93, 0xf0, 0x29, 0xe3, 0x00, 0x10, 0xbd, 0xe8, + 0x0c, 0xf0, 0x69, 0xe1, 0x00, 0x58, 0xbd, 0xe8, 0x0e, 0xf0, 0xb0, 0xe1, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0xa0, 0xe3, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xcc, 0x01, 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x02, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3, + 0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8, + 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5, + 0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe0, 0xa0, 0x03, + 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x20, 0xa0, 0xe3, 0x01, 0xc3, 0xa0, 0xe3, + 0x01, 0x23, 0xcc, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9, 0x01, 0xc3, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x20, 0xa0, 0xe3, 0x03, 0x00, 0x00, 0x0a, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0xc3, 0xe1, @@ -66,5 +72,5 @@ const uint8_t hleBios[SIZE_BIOS] = { 0x01, 0x70, 0xa0, 0xe1, 0x01, 0x80, 0xa0, 0xe1, 0x01, 0x90, 0xa0, 0xe1, 0x01, 0xa0, 0xa0, 0xe1, 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0xfa, 0x07, 0xa0, 0xe8, 0x00, 0x10, 0xa0, 0xe3, - 0xf0, 0x07, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x78, 0x01, 0x00, 0x00 + 0xf0, 0x07, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0xb0, 0x01, 0x00, 0x00 }; diff --git a/src/gba/hle-bios.s b/src/gba/hle-bios.s index 9c5249c2c..e8902cc69 100644 --- a/src/gba/hle-bios.s +++ b/src/gba/hle-bios.s @@ -40,8 +40,22 @@ and r12, #0x80 orr r12, #0x1F msr cpsr, r12 stmfd sp!, {lr} +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop mov lr, pc bxne r11 +nop +nop +nop +nop ldmfd sp!, {lr} msr cpsr, #0x93 ldmfd sp!, {r12} @@ -116,7 +130,6 @@ subs pc, lr, #4 @ Unimplemented SoftReset: RegisterRamReset: -Halt: Stop: Div: DivArm: @@ -156,6 +169,12 @@ SoundDriverVsyncOn: NopCall: bx lr +Halt: +mov r2, #0 +mov r12, #0x04000000 +strb r2, [r12, #0x301] +bx lr + VBlankIntrWait: mov r0, #1 mov r1, #1 From 07f6c6c7e2fc82422c9c6a19ea5459117bdf3335 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Feb 2020 23:53:12 -0800 Subject: [PATCH 29/40] SDL: Fix Windows build on static 2.0.10 --- src/platform/sdl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index 67b4df479..f5e003b7f 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -46,7 +46,7 @@ if(USE_PIXMAN) endif() if(WIN32) - list(APPEND SDL_LIBRARY imm32 version winmm) + list(APPEND SDL_LIBRARY imm32 setupapi version winmm) elseif(APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AppKit -framework AudioUnit -framework Carbon -framework CoreAudio -framework AudioToolbox -framework ForceFeedback -framework IOKit") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE) From fd352d7cacdcd1f2542a2b707f35a23f8e7f1b41 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Feb 2020 23:56:12 -0800 Subject: [PATCH 30/40] GBA Video: Fix fallthrough in deserializing --- src/gba/video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gba/video.c b/src/gba/video.c index b1b404fd7..fdd5d8115 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -348,6 +348,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState } else { video->event.callback = _startHblank; } + break; case 1: video->event.callback = _startHdraw; break; From 458a95e11f5c0d23b477328ad31cd5d43be1e149 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 14 Feb 2020 19:20:10 -0800 Subject: [PATCH 31/40] Qt: Fix pausing Qt Multimedia audio (fixes #1643) --- CHANGES | 1 + src/platform/qt/Window.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 8f12c5f95..a645427b7 100644 --- a/CHANGES +++ b/CHANGES @@ -39,6 +39,7 @@ Other fixes: - Qt: Fix window title not updating after shutting down game - Qt: Fix GIF view not allowing manual filename entry - Qt: Fix non-GB build (fixes mgba.io/i/1664) + - Qt: Fix pausing Qt Multimedia audio (fixes mgba.io/i/1643) - Util: Fix crash reading invalid ELFs - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index ce74ccf5a..0682bb2c3 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -949,6 +949,8 @@ void Window::reloadAudioDriver() { m_audioProcessor->start(); connect(m_controller.get(), &CoreController::stopping, m_audioProcessor.get(), &AudioProcessor::stop); connect(m_controller.get(), &CoreController::fastForwardChanged, m_audioProcessor.get(), &AudioProcessor::inputParametersChanged); + connect(m_controller.get(), &CoreController::paused, m_audioProcessor.get(), &AudioProcessor::pause); + connect(m_controller.get(), &CoreController::unpaused, m_audioProcessor.get(), &AudioProcessor::start); } void Window::changeRenderer() { From a5fc8429eba86c2cf75546f8520e8e9cb2e6449f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 14 Feb 2020 19:21:37 -0800 Subject: [PATCH 32/40] Qt: More GIF view UX fixes --- src/platform/qt/GIFView.cpp | 19 +++++++++++++++++++ src/platform/qt/GIFView.h | 1 + 2 files changed, 20 insertions(+) diff --git a/src/platform/qt/GIFView.cpp b/src/platform/qt/GIFView.cpp index 02c3b0f02..a71a4b81b 100644 --- a/src/platform/qt/GIFView.cpp +++ b/src/platform/qt/GIFView.cpp @@ -25,6 +25,8 @@ GIFView::GIFView(QWidget* parent) connect(m_ui.selectFile, &QAbstractButton::clicked, this, &GIFView::selectFile); connect(m_ui.filename, &QLineEdit::textChanged, this, &GIFView::setFilename); + connect(m_ui.fmtGif, &QAbstractButton::clicked, this, &GIFView::changeExtension); + connect(m_ui.fmtApng, &QAbstractButton::clicked, this, &GIFView::changeExtension); FFmpegEncoderInit(&m_encoder); FFmpegEncoderSetAudio(&m_encoder, nullptr, 0); @@ -92,4 +94,21 @@ void GIFView::setFilename(const QString& filename) { } } +void GIFView::changeExtension() { + if (m_filename.isEmpty()) { + return; + } + QString filename = m_filename; + int index = m_filename.lastIndexOf("."); + if (index >= 0) { + filename.truncate(index); + } + if (m_ui.fmtGif->isChecked()) { + filename += ".gif"; + } else if (m_ui.fmtApng->isChecked()) { + filename += ".png"; + } + m_ui.filename->setText(filename); +} + #endif diff --git a/src/platform/qt/GIFView.h b/src/platform/qt/GIFView.h index fc4ebd1a3..37f71fd93 100644 --- a/src/platform/qt/GIFView.h +++ b/src/platform/qt/GIFView.h @@ -41,6 +41,7 @@ signals: private slots: void selectFile(); void setFilename(const QString&); + void changeExtension(); private: Ui::GIFView m_ui; From f0ff8d5f825f77d726d09fd33b75659c84dff970 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 14 Feb 2020 20:38:56 -0800 Subject: [PATCH 33/40] Qt: Fix invalid names for modifier keys (fixes #525) --- CHANGES | 1 + src/platform/qt/KeyEditor.cpp | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index a645427b7..28bf0a790 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,7 @@ Other fixes: - Qt: Fix GIF view not allowing manual filename entry - Qt: Fix non-GB build (fixes mgba.io/i/1664) - Qt: Fix pausing Qt Multimedia audio (fixes mgba.io/i/1643) + - Qt: Fix invalid names for modifier keys (fixes mgba.io/i/525) - Util: Fix crash reading invalid ELFs - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: diff --git a/src/platform/qt/KeyEditor.cpp b/src/platform/qt/KeyEditor.cpp index f77dceb9b..38a1f48b5 100644 --- a/src/platform/qt/KeyEditor.cpp +++ b/src/platform/qt/KeyEditor.cpp @@ -9,6 +9,7 @@ #include "GamepadButtonEvent.h" #include "ShortcutController.h" +#include #include #include @@ -32,7 +33,35 @@ void KeyEditor::setValue(int key) { if (key < 0) { setText(tr("---")); } else { - setText(QKeySequence(key).toString(QKeySequence::NativeText)); + QKeySequence seq(key); + switch (key) { +#ifndef Q_OS_MAC + case Qt::Key_Shift: + setText(QCoreApplication::translate("QShortcut", "Shift")); + break; + case Qt::Key_Control: + setText(QCoreApplication::translate("QShortcut", "Control")); + break; + case Qt::Key_Alt: + setText(QCoreApplication::translate("QShortcut", "Alt")); + break; + case Qt::Key_Meta: + setText(QCoreApplication::translate("QShortcut", "Meta")); + break; +#endif + case Qt::Key_Super_L: + setText(tr("Super (L)")); + break; + case Qt::Key_Super_R: + setText(tr("Super (R)")); + break; + case Qt::Key_Menu: + setText(tr("Menu")); + break; + default: + setText(QKeySequence(key).toString(QKeySequence::NativeText)); + break; + } } } emit valueChanged(key); From 52a4cbcb81fc9aff4c0588bd5e70653bc5042932 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 15 Feb 2020 13:43:50 -0800 Subject: [PATCH 34/40] GBA DMA: Fix invalid audio DMA parameters --- CHANGES | 1 + src/gba/audio.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 28bf0a790..a3bba7a0c 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Emulation fixes: - GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Improve HLE BIOS timing - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) + - GBA DMA: Fix invalid audio DMA parameters - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing - GBA Serialize: Fix serializing DMA transfer register diff --git a/src/gba/audio.c b/src/gba/audio.c index 23b5a475e..c0a275834 100644 --- a/src/gba/audio.c +++ b/src/gba/audio.c @@ -104,6 +104,8 @@ void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) { } void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) { + info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED); + info->reg = GBADMARegisterSetWidth(info->reg, 1); switch (info->dest) { case BASE_IO | REG_FIFO_A_LO: audio->chA.dmaSource = number; @@ -129,8 +131,6 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* audio->externalMixing = false; } } - info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED); - info->reg = GBADMARegisterSetWidth(info->reg, 1); } void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) { From 743d5603d1e8ccda69f3205c9e4500b6d296877f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 15 Feb 2020 17:08:31 -0800 Subject: [PATCH 35/40] SDL: Refresh stale pointers after adding a joystick (fixes #1622) --- CHANGES | 1 + src/platform/sdl/sdl-events.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index a3bba7a0c..c22505937 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,7 @@ Other fixes: - Qt: Fix non-GB build (fixes mgba.io/i/1664) - Qt: Fix pausing Qt Multimedia audio (fixes mgba.io/i/1643) - Qt: Fix invalid names for modifier keys (fixes mgba.io/i/525) + - SDL: Refresh stale pointers after adding a joystick (fixes mgba.io/i/1622) - Util: Fix crash reading invalid ELFs - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index d29bfb378..a372119c6 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -351,6 +351,13 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* if (!sdlJoystick) { continue; } + ssize_t joysticks[MAX_PLAYERS]; + size_t i; + // Pointers can get invalidated, so we'll need to refresh them + for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) { + joysticks[i] = events->players[i]->joystick ? SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : SIZE_MAX; + events->players[i]->joystick = NULL; + } struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks); joystick->joystick = sdlJoystick; joystick->id = SDL_JoystickInstanceID(joystick->joystick); @@ -358,8 +365,12 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration* #if SDL_VERSION_ATLEAST(2, 0, 0) joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick); #endif + for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) { + if (joysticks[i] != SIZE_MAX) { + events->players[i]->joystick = SDL_JoystickListGetPointer(&events->joysticks, joysticks[i]); + } + } - size_t i; #if SDL_VERSION_ATLEAST(2, 0, 0) char joystickName[34] = {0}; SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick->joystick), joystickName, sizeof(joystickName)); From 9c88d4880623cebb3fea297173ee1b471a639095 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 16 Feb 2020 15:48:23 -0800 Subject: [PATCH 36/40] CHANGES: Update for 0.8.1 --- CHANGES | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index c22505937..f398c6d5a 100644 --- a/CHANGES +++ b/CHANGES @@ -4,34 +4,40 @@ Features: Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation - - GB Serialize: Fix timing bug loading channel 4 timing - - GBA: Fix multiboot entry point while skipping BIOS - - GBA BIOS: Fix undefined instruction HLE behavior - GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Improve HLE BIOS timing - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - - GBA DMA: Fix invalid audio DMA parameters - - GBA Memory: Misaligned SRAM writes are ignored - GBA Memory: Improve gamepak prefetch timing - - GBA Serialize: Fix serializing DMA transfer register - - GBA Serialize: Fix audio serialization for desynced FIFOs - - GBA Serialize: Fix audio DMA timing deserialization - - GBA Video: Fix OAM not invalidating after reset (fixes mgba.io/i/1630) - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing +Other fixes: + - Core: Ensure ELF regions can be written before trying + - Debugger: Don't skip undefined instructions when debugger attached + - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) +Misc: + - FFmpeg: Add looping option for GIF/APNG + - Qt: Renderer can be changed while a game is running + +0.8.1: (2020-02-16) +Emulation fixes: + - GB Serialize: Fix timing bug loading channel 4 timing + - GBA: Fix multiboot entry point while skipping BIOS + - GBA BIOS: Fix undefined instruction HLE behavior + - GBA DMA: Fix invalid audio DMA parameters + - GBA Memory: Misaligned SRAM writes are ignored + - GBA Serialize: Fix serializing DMA transfer register + - GBA Serialize: Fix audio DMA timing deserialization + - GBA Video: Fix OAM not invalidating after reset (fixes mgba.io/i/1630) - GBA Video: Fix backdrop blending on lines without sprites (fixes mgba.io/i/1647) - GBA Video: Fix OpenGL sprite flag priority Other fixes: - Core: Fix race condition initializing thread proxy - - Core: Ensure ELF regions can be written before trying - Core: Fix integer overflow in ELF loading - - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix crash when -strict -2 is needed for vcodec or container - FFmpeg: Disallow recording video with no audio nor video - GBA: Automatically skip BIOS for multiboot ROMs - Qt: Only dynamically reset video scale if a game is running - Qt: Fix race condition with proxied video events - - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix color selection in asset view (fixes mgba.io/i/1648) - Qt: Fix missing OSD messages - Qt: Fix crash unloading shaders @@ -47,8 +53,6 @@ Other fixes: - VFS: Fix handle leak when double-mapping (fixes mgba.io/i/1659) Misc: - FFmpeg: Add more presets - - FFmpeg: Add looping option for GIF/APNG - - Qt: Renderer can be changed while a game is running - Qt: Fix non-SDL build (fixes mgba.io/i/1656) - SDL: Use DirectSound audio driver by default on Windows - Switch: Make OpenGL scale adjustable while running From 7d382e82a6306f378ac0c8e4861504f7e60b386a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 16 Feb 2020 20:52:02 -0800 Subject: [PATCH 37/40] Core: Fix ELF loading regression (fixes #1669) --- CHANGES | 1 + src/core/core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index f398c6d5a..a9db55df4 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,7 @@ Emulation fixes: - GBA Video: Fix Hblank timing Other fixes: - Core: Ensure ELF regions can be written before trying + - Core: Fix ELF loading regression (fixes mgba.io/i/1669) - Debugger: Don't skip undefined instructions when debugger attached - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) Misc: diff --git a/src/core/core.c b/src/core/core.c index 569a6a983..6688bef51 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -377,7 +377,7 @@ bool mCoreLoadELF(struct mCore* core, struct ELF* elf) { Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i); void* block = mCoreGetMemoryBlockMasked(core, phdr->p_paddr, &bsize, mCORE_MEMORY_WRITE | mCORE_MEMORY_WORM); char* bytes = ELFBytes(elf, &esize); - if (block && bsize >= phdr->p_filesz && bsize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) { + if (block && bsize >= phdr->p_filesz && esize > phdr->p_offset && esize >= phdr->p_filesz + phdr->p_offset) { memcpy(block, &bytes[phdr->p_offset], phdr->p_filesz); } else { return false; From c0ac5e35c06fe3a30efb444808d8e09f1dc28330 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 17 Feb 2020 14:24:51 -0800 Subject: [PATCH 38/40] Qt: Add hex index to palette view --- CHANGES | 1 + src/platform/qt/PaletteView.cpp | 2 +- src/platform/qt/PaletteView.ui | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index a9db55df4..721660b17 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Other fixes: Misc: - FFmpeg: Add looping option for GIF/APNG - Qt: Renderer can be changed while a game is running + - Qt: Add hex index to palette view 0.8.1: (2020-02-16) Emulation fixes: diff --git a/src/platform/qt/PaletteView.cpp b/src/platform/qt/PaletteView.cpp index 394a54e7e..9a7a1206b 100644 --- a/src/platform/qt/PaletteView.cpp +++ b/src/platform/qt/PaletteView.cpp @@ -120,7 +120,7 @@ void PaletteView::selectIndex(int index) { hexcode |= (hexcode >> 5) & 0x070707; m_ui.hexcode->setText(tr("#%0").arg(hexcode, 6, 16, QChar('0'))); m_ui.value->setText(tr("0x%0").arg(color, 4, 16, QChar('0'))); - m_ui.index->setText(tr("%0").arg(index, 3, 10, QChar('0'))); + m_ui.index->setText(tr("0x%0 (%1)").arg(index, 3, 16, QChar('0')).arg(index, 3, 10, QChar('0'))); m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0'))); m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0'))); diff --git a/src/platform/qt/PaletteView.ui b/src/platform/qt/PaletteView.ui index 030c028e8..d8ae48601 100644 --- a/src/platform/qt/PaletteView.ui +++ b/src/platform/qt/PaletteView.ui @@ -6,7 +6,7 @@ 0 0 - 443 + 500 397 @@ -289,7 +289,7 @@ - 000 + 0x000 (000) Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter From e758f232fa9751b47fb72f79bf1cfa4fdac75622 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 17 Feb 2020 15:02:07 -0800 Subject: [PATCH 39/40] Qt: Add transformation matrix info to sprite view --- CHANGES | 1 + src/platform/qt/ObjView.cpp | 24 ++- src/platform/qt/ObjView.ui | 343 ++++++++++++++++++++++-------------- 3 files changed, 231 insertions(+), 137 deletions(-) diff --git a/CHANGES b/CHANGES index 721660b17..16c20e19e 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Misc: - FFmpeg: Add looping option for GIF/APNG - 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 0.8.1: (2020-02-16) Emulation fixes: diff --git a/src/platform/qt/ObjView.cpp b/src/platform/qt/ObjView.cpp index b3623a799..3044f9259 100644 --- a/src/platform/qt/ObjView.cpp +++ b/src/platform/qt/ObjView.cpp @@ -44,6 +44,10 @@ ObjView::ObjView(std::shared_ptr controller, QWidget* parent) m_ui.priority->setFont(font); m_ui.palette->setFont(font); m_ui.transform->setFont(font); + m_ui.xformPA->setFont(font); + m_ui.xformPB->setFont(font); + m_ui.xformPC->setFont(font); + m_ui.xformPD->setFont(font); m_ui.mode->setFont(font); connect(m_ui.tiles, &TilePainter::indexPressed, this, &ObjView::translateIndex); @@ -157,9 +161,23 @@ void ObjView::updateTilesGBA(bool force) { m_ui.mosaic->setChecked(GBAObjAttributesAIsMosaic(obj->a)); if (GBAObjAttributesAIsTransformed(obj->a)) { - m_ui.transform->setText(QString::number(GBAObjAttributesBGetMatIndex(obj->b))); + int mtxId = GBAObjAttributesBGetMatIndex(obj->b); + struct GBAOAMMatrix mat; + LOAD_16LE(mat.a, 0, &gba->video.oam.mat[mtxId].a); + LOAD_16LE(mat.b, 0, &gba->video.oam.mat[mtxId].b); + LOAD_16LE(mat.c, 0, &gba->video.oam.mat[mtxId].c); + LOAD_16LE(mat.d, 0, &gba->video.oam.mat[mtxId].d); + m_ui.transform->setText(QString::number(mtxId)); + m_ui.xformPA->setText(QString("%0").arg(mat.a / 256., 5, 'f', 2)); + m_ui.xformPB->setText(QString("%0").arg(mat.b / 256., 5, 'f', 2)); + m_ui.xformPC->setText(QString("%0").arg(mat.c / 256., 5, 'f', 2)); + m_ui.xformPD->setText(QString("%0").arg(mat.d / 256., 5, 'f', 2)); } else { m_ui.transform->setText(tr("Off")); + m_ui.xformPA->setText(tr("---")); + m_ui.xformPB->setText(tr("---")); + m_ui.xformPC->setText(tr("---")); + m_ui.xformPD->setText(tr("---")); } switch (GBAObjAttributesAGetMode(obj->a)) { @@ -230,6 +248,10 @@ void ObjView::updateTilesGB(bool force) { m_ui.doubleSize->setChecked(false); m_ui.mosaic->setChecked(false); m_ui.transform->setText(tr("N/A")); + m_ui.xformPA->setText(tr("---")); + m_ui.xformPB->setText(tr("---")); + m_ui.xformPC->setText(tr("---")); + m_ui.xformPD->setText(tr("---")); m_ui.mode->setText(tr("N/A")); } #endif diff --git a/src/platform/qt/ObjView.ui b/src/platform/qt/ObjView.ui index 7584deff6..bac5eac66 100644 --- a/src/platform/qt/ObjView.ui +++ b/src/platform/qt/ObjView.ui @@ -13,7 +13,81 @@ Sprites - + + + + + QFrame::StyledPanel + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 8 + 8 + + + + + + + + + + + + + + 0 + 0 + + + + 127 + + + + + + + Address + + + + + + + 0x07000000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + @@ -21,13 +95,49 @@ + + + + + + + 0 + 0 + + + + × + + + 1 + + + 8 + + + + + + + Magnification + + + + + + + + 0 + 0 + + Geometry - - + + @@ -93,7 +203,14 @@ - + + + + Qt::Vertical + + + + @@ -159,50 +276,86 @@ - - - - - - - QFrame::StyledPanel - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 8 - 8 - - - + + + + + + +0.00 + + + + + + + +1.00 + + + + + + + Matrix + + + + + + + +1.00 + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + +0.00 + + + + - - - - Tile + + + + + 64 + 64 + + + + QListView::LeftToRight + + + QListView::Adjust + + + + 64 + 96 + + + + QListView::IconMode + + + true @@ -215,6 +368,12 @@ + + + 0 + 0 + + Attributes @@ -517,98 +676,10 @@ - - - - - - - 0 - 0 - - - - 127 - - - - - - - Address - - - - - - - 0x07000000 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - - - 0 - 0 - - - - × - - - 1 - - - 8 - - - - - - - Magnification - - - - - - - - - - 64 - 64 - - - - QListView::LeftToRight - - - QListView::Adjust - - - - 64 - 96 - - - - QListView::IconMode - - - true + + + + Tile From 7611913d65a6fb9eb448c97eacdc31616599b65e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 17 Feb 2020 16:18:22 -0800 Subject: [PATCH 40/40] GB: Add input description file --- include/mgba/internal/gb/input.h | 29 +++++++++++++++++++++++++++++ src/gb/CMakeLists.txt | 1 + src/gb/input.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 include/mgba/internal/gb/input.h create mode 100644 src/gb/input.c diff --git a/include/mgba/internal/gb/input.h b/include/mgba/internal/gb/input.h new file mode 100644 index 000000000..585104e22 --- /dev/null +++ b/include/mgba/internal/gb/input.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2013-2019 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GB_INPUT_H +#define GB_INPUT_H + +#include + +CXX_GUARD_START + +#include + +enum GBKey { + GB_KEY_A = 0, + GB_KEY_B = 1, + GB_KEY_SELECT = 2, + GB_KEY_START = 3, + GB_KEY_RIGHT = 4, + GB_KEY_LEFT = 5, + GB_KEY_UP = 6, + GB_KEY_DOWN = 7, + GB_KEY_MAX, +}; + +CXX_GUARD_END + +#endif diff --git a/src/gb/CMakeLists.txt b/src/gb/CMakeLists.txt index 948cca747..0dc642803 100644 --- a/src/gb/CMakeLists.txt +++ b/src/gb/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCE_FILES cheats.c core.c gb.c + input.c io.c mbc.c memory.c diff --git a/src/gb/input.c b/src/gb/input.c new file mode 100644 index 000000000..e1f975c6b --- /dev/null +++ b/src/gb/input.c @@ -0,0 +1,29 @@ +/* Copyright (c) 2013-2019 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 + +const struct mInputPlatformInfo GBInputInfo = { + .platformName = "gb", + .keyId = (const char*[]) { + "A", + "B", + "Select", + "Start", + "Right", + "Left", + "Up", + "Down", + }, + .nKeys = GB_KEY_MAX, + .hat = { + .up = GB_KEY_UP, + .left = GB_KEY_LEFT, + .down = GB_KEY_DOWN, + .right = GB_KEY_RIGHT + } +};