From 5d8e80e2d7ec13e2d2719557ddeb4506682ba377 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Sat, 17 Mar 2018 18:25:13 +0100 Subject: [PATCH 01/10] Doc: Add 'libelf' package to msys2/mingw-w64 dependencies --- README.md | 4 ++-- README_DE.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f9fab7b63..a32acc878 100644 --- a/README.md +++ b/README.md @@ -136,11 +136,11 @@ To build on Windows for development, using MSYS2 is recommended. Follow the inst For x86 (32 bit) builds: - pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} For x86_64 (64 bit) builds: - pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Check out the source code by running this command: diff --git a/README_DE.md b/README_DE.md index f5b7affe3..b366af757 100644 --- a/README_DE.md +++ b/README_DE.md @@ -136,11 +136,11 @@ Um mGBA auf Windows zu kompilieren, wird MSYS2 empfohlen. Befolge die Installati Für x86 (32 Bit): - pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-i686-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Für x86_64 (64 Bit): - pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} + pacman -Sy mingw-w64-x86_64-{cmake,ffmpeg,gcc,gdb,imagemagick,libelf,libepoxy,libzip,pkg-config,qt5,SDL2,ntldd-git} Lade den aktuellen mGBA-Quellcode mithilfe des folgenden Kommandos herunter: From 35716a08956db30db67237d477aa4d50e3c056bb Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Sun, 18 Mar 2018 20:22:09 +0100 Subject: [PATCH 02/10] CMake: Disable 'editline' for Win32 (#1017) * CMake: Disable 'editline' for Win32 Because editline seems to be unsupported in Win32 GUI applications, enabling the CLI debugger is only enabled if the target platform is not Win32. * CMake: Disable editline status log line for Win32 --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62ea0e10f..3c2abdc07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,9 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146") endif() set(USE_DEBUGGERS ON CACHE BOOL "Whether or not to enable the debugging infrastructure") -set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger") +if (NOT WIN32) + set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger") +endif() set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger") set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support") set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support") @@ -991,7 +993,9 @@ if(NOT QUIET) message(STATUS " Game Boy: ${M_CORE_GB}") message(STATUS "Features:") message(STATUS " Debuggers: ${USE_DEBUGGERS}") - message(STATUS " CLI debugger: ${USE_EDITLINE}") + if(NOT WIN32) + message(STATUS " CLI debugger: ${USE_EDITLINE}") + endif() message(STATUS " GDB stub: ${USE_GDB_STUB}") message(STATUS " Video recording: ${USE_FFMPEG}") message(STATUS " GIF recording: ${USE_MAGICK}") From fac10eae96d38c4a4f78b4d06eb23022263fff75 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 21 Mar 2018 09:11:24 -0700 Subject: [PATCH 03/10] GB Memory: Fix OAM DMA blocking regions (fixes #1013) --- CHANGES | 1 + include/mgba/internal/gb/video.h | 1 - src/gb/memory.c | 58 +++++++++++++++++--------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/CHANGES b/CHANGES index 6313f9097..547e9dcd3 100644 --- a/CHANGES +++ b/CHANGES @@ -53,6 +53,7 @@ Bugfixes: - GBA: Fix SharkPort saves for EEPROM games - Qt: Fix opening in fullscreen (fixes mgba.io/i/993) - Python: Fix package directory + - GB Memory: Fix OAM DMA blocking regions (fixes mgba.io/i/1013) Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/include/mgba/internal/gb/video.h b/include/mgba/internal/gb/video.h index 90cfd7bbb..7fd731be6 100644 --- a/include/mgba/internal/gb/video.h +++ b/include/mgba/internal/gb/video.h @@ -26,7 +26,6 @@ enum { GB_VIDEO_HORIZONTAL_LENGTH = 456, - GB_VIDEO_MODE_1_LENGTH = 65664, GB_VIDEO_TOTAL_LENGTH = 70224, GB_BASE_MAP = 0x1800, diff --git a/src/gb/memory.c b/src/gb/memory.c index 1dae0b988..089558011 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -16,31 +16,33 @@ mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory"); -struct OAMBlock { - uint16_t low; - uint16_t high; +enum GBBus { + GB_BUS_CPU, + GB_BUS_MAIN, + GB_BUS_VRAM, + GB_BUS_RAM }; -static const struct OAMBlock _oamBlockDMG[] = { - { 0xA000, 0xFE00 }, - { 0xA000, 0xFE00 }, - { 0xA000, 0xFE00 }, - { 0xA000, 0xFE00 }, - { 0x8000, 0xA000 }, - { 0xA000, 0xFE00 }, - { 0xA000, 0xFE00 }, - { 0xA000, 0xFE00 }, +static const enum GBBus _oamBlockDMG[] = { + GB_BUS_MAIN, // 0x0000 + GB_BUS_MAIN, // 0x2000 + GB_BUS_MAIN, // 0x4000 + GB_BUS_MAIN, // 0x6000 + GB_BUS_VRAM, // 0x8000 + GB_BUS_MAIN, // 0xA000 + GB_BUS_MAIN, // 0xC000 + GB_BUS_CPU, // 0xE000 }; -static const struct OAMBlock _oamBlockCGB[] = { - { 0xA000, 0xC000 }, - { 0xA000, 0xC000 }, - { 0xA000, 0xC000 }, - { 0xA000, 0xC000 }, - { 0x8000, 0xA000 }, - { 0xA000, 0xC000 }, - { 0xC000, 0xFE00 }, - { 0xA000, 0xC000 }, +static const enum GBBus _oamBlockCGB[] = { + GB_BUS_MAIN, // 0x0000 + GB_BUS_MAIN, // 0x2000 + GB_BUS_MAIN, // 0x4000 + GB_BUS_MAIN, // 0x6000 + GB_BUS_VRAM, // 0x8000 + GB_BUS_MAIN, // 0xA000 + GB_BUS_RAM, // 0xC000 + GB_BUS_CPU // 0xE000 }; static void _pristineCow(struct GB* gba); @@ -192,9 +194,10 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) { struct GB* gb = (struct GB*) cpu->master; struct GBMemory* memory = &gb->memory; if (gb->memory.dmaRemaining) { - const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB; - block = &block[memory->dmaSource >> 13]; - if (address >= block->low && address < block->high) { + const enum GBBus* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB; + enum GBBus dmaBus = block[memory->dmaSource >> 13]; + enum GBBus accessBus = block[address >> 13]; + if (dmaBus != GB_BUS_CPU && dmaBus == accessBus) { return 0xFF; } if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) { @@ -264,9 +267,10 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) { struct GB* gb = (struct GB*) cpu->master; struct GBMemory* memory = &gb->memory; if (gb->memory.dmaRemaining) { - const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB; - block = &block[memory->dmaSource >> 13]; - if (address >= block->low && address < block->high) { + const enum GBBus* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB; + enum GBBus dmaBus = block[memory->dmaSource >> 13]; + enum GBBus accessBus = block[address >> 13]; + if (dmaBus != GB_BUS_CPU && dmaBus == accessBus) { return; } if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) { From 7a53c35123f9d3033e18afc05660b017c956181c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 22 Mar 2018 20:38:30 -0700 Subject: [PATCH 04/10] Windows: Build fix --- src/platform/qt/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 9f5c78ca4..074dfb391 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -171,7 +171,7 @@ if(Qt5Multimedia_FOUND) VideoDumper.cpp) if (WIN32 AND QT_STATIC) list(APPEND QT_LIBRARIES Qt5::QWindowsAudioPlugin Qt5::DSServicePlugin - strmiids winmm mfuuid mfplat mf ksguid dxva2 evr d3d9) + strmiids mfuuid mfplat mf ksguid dxva2 evr d3d9) endif() list(APPEND QT_LIBRARIES Qt5::Multimedia) list(APPEND QT_DEFINES BUILD_QT_MULTIMEDIA) @@ -273,7 +273,7 @@ if(BUILD_GL OR BUILD_GLES2) endif() if(WIN32 AND QT_STATIC) list(APPEND QT_LIBRARIES qwindows dwmapi imm32 uxtheme Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport) - set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "qtpcre2;version;ws2_32") + set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "qtpcre2;version;winmm;ws2_32") endif() target_link_libraries(${BINARY_NAME}-qt ${PLATFORM_LIBRARY} ${BINARY_NAME} ${QT_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE) From ea2159d159f2ddb5514b9137a116eb74a2ed872f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 22 Mar 2018 20:38:18 -0700 Subject: [PATCH 05/10] Wii: Drawing polish (closes #988) --- CHANGES | 1 + src/platform/wii/main.c | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 547e9dcd3..6032c5f54 100644 --- a/CHANGES +++ b/CHANGES @@ -54,6 +54,7 @@ Bugfixes: - Qt: Fix opening in fullscreen (fixes mgba.io/i/993) - Python: Fix package directory - GB Memory: Fix OAM DMA blocking regions (fixes mgba.io/i/1013) + - Wii: Fix various setup and teardown drawing issues (fixes mgba.io/i/988) Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 5d8d11300..6a359a637 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -194,18 +194,20 @@ static void reconfigureScreen(struct mGUIRunner* runner) { free(framebuffer[0]); free(framebuffer[1]); - framebuffer[0] = SYS_AllocateFramebuffer(vmode); - framebuffer[1] = SYS_AllocateFramebuffer(vmode); - VIDEO_SetBlack(true); VIDEO_Configure(vmode); + + framebuffer[0] = SYS_AllocateFramebuffer(vmode); + framebuffer[1] = SYS_AllocateFramebuffer(vmode); + VIDEO_ClearFrameBuffer(vmode, framebuffer[0], COLOR_BLACK); + VIDEO_ClearFrameBuffer(vmode, framebuffer[1], COLOR_BLACK); + VIDEO_SetNextFramebuffer(framebuffer[whichFb]); VIDEO_Flush(); VIDEO_WaitVSync(); if (vmode->viTVMode & VI_NON_INTERLACE) { VIDEO_WaitVSync(); } - VIDEO_SetBlack(false); GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); f32 yscale = GX_GetYScaleFactor(vmode->efbHeight, vmode->xfbHeight); @@ -238,6 +240,9 @@ static void reconfigureScreen(struct mGUIRunner* runner) { int main(int argc, char* argv[]) { VIDEO_Init(); + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); PAD_Init(); WPAD_Init(); WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); @@ -481,6 +486,10 @@ int main(int argc, char* argv[]) { mGUIInit(&runner, "wii"); reconfigureScreen(&runner); + // Make sure screen is properly initialized by drawing a blank frame + _drawStart(); + _drawEnd(); + _mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_BUTTON_A, GUI_INPUT_SELECT); _mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_BUTTON_B, GUI_INPUT_BACK); _mapKey(&runner.params.keyMap, GCN1_INPUT, PAD_TRIGGER_Z, GUI_INPUT_CANCEL); @@ -516,6 +525,9 @@ int main(int argc, char* argv[]) { } else { mGUIRunloop(&runner); } + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); mGUIDeinit(&runner); #ifdef FIXED_ROM_BUFFER @@ -546,6 +558,8 @@ static void _audioDMA(void) { } static void _drawStart(void) { + VIDEO_SetBlack(false); + u32 level = 0; _CPU_ISR_Disable(level); if (referenceRetraceCount > retraceCount) { @@ -563,12 +577,11 @@ static void _drawStart(void) { } static void _drawEnd(void) { - whichFb = !whichFb; - GX_CopyDisp(framebuffer[whichFb], GX_TRUE); GX_DrawDone(); VIDEO_SetNextFramebuffer(framebuffer[whichFb]); VIDEO_Flush(); + whichFb = !whichFb; u32 level = 0; _CPU_ISR_Disable(level); @@ -713,6 +726,9 @@ void _gameUnloaded(struct mGUIRunner* runner) { UNUSED(runner); AUDIO_StopDMA(); frameLimiter = true; + VIDEO_SetBlack(true); + VIDEO_Flush(); + VIDEO_WaitVSync(); } void _gameLoaded(struct mGUIRunner* runner) { From eddd3851bcb05c553524956c08c5e58c3dc8fff9 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Sat, 24 Mar 2018 19:09:27 +0800 Subject: [PATCH 06/10] Libretro: Allow choosing the Game Boy model --- src/platform/libretro/libretro.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index c7c3876b4..071e19c57 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -63,6 +63,27 @@ static void _reloadSettings(void) { }; struct retro_variable var; + enum GBModel model; + const char* modelName; + + var.key = "mgba_model"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "Game Boy") == 0) { + model = GB_MODEL_DMG; + } else if (strcmp(var.value, "Super Game Boy") == 0) { + model = GB_MODEL_SGB; + } else if (strcmp(var.value, "Game Boy Color") == 0) { + model = GB_MODEL_CGB; + } else { + model = GB_MODEL_AUTODETECT; + } + + modelName = GBModelToName(model); + mCoreConfigSetDefaultValue(&core->config, "gb.model", modelName); + mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName); + mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName); + } var.key = "mgba_use_bios"; var.value = 0; @@ -119,6 +140,7 @@ void retro_set_environment(retro_environment_t env) { struct retro_variable vars[] = { { "mgba_solar_sensor_level", "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" }, { "mgba_allow_opposing_directions", "Allow opposing directional input; OFF|ON" }, + { "mgba_model", "Game Boy model (requires restart); Autodetect|Game Boy|Super Game Boy|Game Boy Color" }, { "mgba_use_bios", "Use BIOS file if found (requires restart); ON|OFF" }, { "mgba_skip_bios", "Skip BIOS intro (requires restart); OFF|ON" }, { "mgba_sgb_borders", "Use Super Game Boy borders (requires restart); ON|OFF" }, From ffbf509f5a75bec09969b454ec4eb363c3557f10 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Sat, 24 Mar 2018 19:10:07 +0800 Subject: [PATCH 07/10] Libretro: Attempt to load Game Boy BIOS --- src/platform/libretro/libretro.c | 49 ++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 071e19c57..4543a5ab7 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -455,22 +455,53 @@ bool retro_load_game(const struct retro_game_info* game) { core->loadROM(core, rom); core->loadSave(core, save); + const char* sysDir = 0; + const char* biosName = 0; + char biosPath[PATH_MAX]; + environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir); + #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux); + biosName = "gba_bios.bin"; - const char* sysDir = 0; - if (core->opts.useBios && environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) { - char biosPath[PATH_MAX]; - snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin"); - struct VFile* bios = VFileOpen(biosPath, O_RDONLY); - if (bios) { - core->loadBIOS(core, bios, 0); - } - } } #endif +#ifdef M_CORE_GB + if (core->platform(core) == PLATFORM_GB) { + const char* modelName = mCoreConfigGetValue(&core->config, "gb.model"); + struct GB* gb = core->board; + + if (modelName) { + gb->model = GBNameToModel(modelName); + } else { + GBDetectModel(gb); + } + + switch (gb->model) { + case GB_MODEL_CGB: + biosName = "gbc_bios.bin"; + break; + case GB_MODEL_SGB: + biosName = "sgb_bios.bin"; + break; + case GB_MODEL_DMG: + default: + biosName = "gb_bios.bin"; + break; + }; + } +#endif + + if (core->opts.useBios && sysDir && biosName) { + snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName); + struct VFile* bios = VFileOpen(biosPath, O_RDONLY); + if (bios) { + core->loadBIOS(core, bios, 0); + } + } + core->reset(core); _setupMaps(core); From b75b591b22226371ebc97fa56e3d4c8ddbdbdea5 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Sat, 24 Mar 2018 19:10:47 +0800 Subject: [PATCH 08/10] Libretro: Start declaration with `static` to suppress compiler warning --- src/platform/libretro/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 4543a5ab7..aecc1d9cb 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -320,7 +320,7 @@ void retro_run(void) { videoCallback(outputBuffer, width, height, BYTES_PER_PIXEL * 256); } -void static _setupMaps(struct mCore* core) { +static void _setupMaps(struct mCore* core) { #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { struct GBA* gba = core->board; From 016e1596f7a526f1f9d6b1f13a8906aa11735693 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Sun, 25 Mar 2018 16:13:25 +0800 Subject: [PATCH 09/10] GB Video: Fix SGB border transparency Make the first color of every palette transparent. This fixes Pokemon Blue's SGB border (as long as the platform has initialized its output buffer to white). --- src/gb/renderers/software.c | 34 ++++++++++++++++---------------- src/platform/libretro/libretro.c | 4 +++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 5214b3d7f..93c67b871 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -75,25 +75,25 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) { tileData[3] = renderer->d.sgbCharRam[(SGBBgAttributesGetTile(mapData) * 16 + localY) * 2 + 0x11]; size_t base = y * renderer->outputBufferStride + x; - int p = SGBBgAttributesGetPalette(mapData) * 0x10; + int paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10; + int colorSelector; + if (SGBBgAttributesIsXFlip(mapData)) { - renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)]; - renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)]; - renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)]; - renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)]; - renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)]; - renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)]; - renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)]; - renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)]; + for (i = 0; i < 8; ++i) { + colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; + // The first color of every palette is transparent + if (colorSelector) { + renderer->outputBuffer[base + i] = renderer->palette[paletteBase | colorSelector]; + } + } } else { - renderer->outputBuffer[base + 0] = renderer->palette[p | ((tileData[0] >> 7) & 0x1) | ((tileData[1] >> 6) & 0x2) | ((tileData[2] >> 5) & 0x4) | ((tileData[3] >> 4) & 0x8)]; - renderer->outputBuffer[base + 1] = renderer->palette[p | ((tileData[0] >> 6) & 0x1) | ((tileData[1] >> 5) & 0x2) | ((tileData[2] >> 4) & 0x4) | ((tileData[3] >> 3) & 0x8)]; - renderer->outputBuffer[base + 2] = renderer->palette[p | ((tileData[0] >> 5) & 0x1) | ((tileData[1] >> 4) & 0x2) | ((tileData[2] >> 3) & 0x4) | ((tileData[3] >> 2) & 0x8)]; - renderer->outputBuffer[base + 3] = renderer->palette[p | ((tileData[0] >> 4) & 0x1) | ((tileData[1] >> 3) & 0x2) | ((tileData[2] >> 2) & 0x4) | ((tileData[3] >> 1) & 0x8)]; - renderer->outputBuffer[base + 4] = renderer->palette[p | ((tileData[0] >> 3) & 0x1) | ((tileData[1] >> 2) & 0x2) | ((tileData[2] >> 1) & 0x4) | ((tileData[3] >> 0) & 0x8)]; - renderer->outputBuffer[base + 5] = renderer->palette[p | ((tileData[0] >> 2) & 0x1) | ((tileData[1] >> 1) & 0x2) | ((tileData[2] >> 0) & 0x4) | ((tileData[3] << 1) & 0x8)]; - renderer->outputBuffer[base + 6] = renderer->palette[p | ((tileData[0] >> 1) & 0x1) | ((tileData[1] >> 0) & 0x2) | ((tileData[2] << 1) & 0x4) | ((tileData[3] << 2) & 0x8)]; - renderer->outputBuffer[base + 7] = renderer->palette[p | ((tileData[0] >> 0) & 0x1) | ((tileData[1] << 1) & 0x2) | ((tileData[2] << 2) & 0x4) | ((tileData[3] << 3) & 0x8)]; + for (i = 7; i >= 0; --i) { + colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; + + if (colorSelector) { + renderer->outputBuffer[base + 7 - i] = renderer->palette[paletteBase | colorSelector]; + } + } } } } diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index aecc1d9cb..df67de786 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -438,7 +438,9 @@ bool retro_load_game(const struct retro_game_info* game) { core->init(core); core->setAVStream(core, &stream); - outputBuffer = malloc(256 * 224 * BYTES_PER_PIXEL); + size_t size = 256 * 224 * BYTES_PER_PIXEL; + outputBuffer = malloc(size); + memset(outputBuffer, 0xFF, size); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); From fc53fc9647353e3757a8538c01d6fd1e9a0ed3ca Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 27 Mar 2018 20:33:13 -0700 Subject: [PATCH 10/10] GBA Timer: Fix timers sometimes being late (fixes #1012) --- CHANGES | 1 + src/gba/timer.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 6032c5f54..61b8d113f 100644 --- a/CHANGES +++ b/CHANGES @@ -55,6 +55,7 @@ Bugfixes: - Python: Fix package directory - GB Memory: Fix OAM DMA blocking regions (fixes mgba.io/i/1013) - Wii: Fix various setup and teardown drawing issues (fixes mgba.io/i/988) + - GBA Timer: Fix timers sometimes being late (fixes mgba.io/i/1012) Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) diff --git a/src/gba/timer.c b/src/gba/timer.c index 985ef0744..282263364 100644 --- a/src/gba/timer.c +++ b/src/gba/timer.c @@ -51,7 +51,7 @@ static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) { int32_t tickMask = (1 << GBATimerFlagsGetPrescaleBits(timer->flags)) - 1; currentTime &= ~tickMask; timer->lastEvent = currentTime; - GBATimerUpdateRegister(gba, timerId, 0); + GBATimerUpdateRegister(gba, timerId, TIMER_RELOAD_DELAY + cyclesLate); if (GBATimerFlagsIsDoIrq(timer->flags)) { timer->flags = GBATimerFlagsFillIrqPending(timer->flags); @@ -155,7 +155,7 @@ void GBATimerUpdateRegister(struct GBA* gba, int timer, int32_t cyclesLate) { if (!mTimingIsScheduled(&gba->timing, ¤tTimer->event)) { tickIncrement = (0x10000 - tickIncrement) << prescaleBits; currentTime -= mTimingCurrentTime(&gba->timing) - cyclesLate; - mTimingSchedule(&gba->timing, ¤tTimer->event, TIMER_RELOAD_DELAY + tickIncrement + currentTime); + mTimingSchedule(&gba->timing, ¤tTimer->event, tickIncrement + currentTime); } }