From 6dcf016d207a5f0484c94dba5d82ac979afca1f9 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 18 Jul 2019 10:41:59 +0800 Subject: [PATCH] GB: Allow support for colorizer patched games - a new core option is provided since enabling this support means allowing invalid access to vram and palette - works in GBC/GBA hardware mode only --- src/gb/GB.cpp | 72 ++++++++++++++++++++-------- src/gb/gb.h | 4 ++ src/libretro/libretro.cpp | 17 +++++++ src/libretro/libretro_core_options.h | 41 ++++++++++------ 4 files changed, 100 insertions(+), 34 deletions(-) diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp index f9f9f94f..909024bc 100644 --- a/src/gb/GB.cpp +++ b/src/gb/GB.cpp @@ -200,6 +200,7 @@ int gbCaptureNumber = 0; bool gbCapture = false; bool gbCapturePrevious = false; int gbJoymask[4] = { 0, 0, 0, 0 }; +static bool allow_colorizer_hack; uint8_t gbRamFill = 0xff; @@ -776,6 +777,51 @@ static const uint16_t gbColorizationPaletteData[32][3][4] = { #define GBSAVE_GAME_VERSION_12 12 #define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_12 +void setColorizerHack(bool value) +{ + allow_colorizer_hack = value; +} + +bool allowColorizerHack(void) +{ + if (gbHardware & 0xA) + return (allow_colorizer_hack); + return false; +} + +static inline bool gbVramReadAccessValid(void) +{ + // A lot of 'ugly' checks... But only way to emulate this particular behaviour... + if (allowColorizerHack()|| + ((gbHardware & 0xa) && ((gbLcdModeDelayed != 3) || (((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))))) || + ((gbHardware & 0x5) && (gbLcdModeDelayed != 3) && ((gbLcdMode != 3) || ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))))) + return true; + return false; +} + +static inline bool gbVramWriteAccessValid(void) +{ + if (allowColorizerHack() || + // No access to Vram during mode 3 + // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer) + (gbLcdModeDelayed != 3) || + // This part is used to emulate a small difference between hardwares + // (check 8-in-1's arrow on GBA/GBC to verify it) + ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))) + return true; + return false; +} + +static inline bool gbCgbPaletteAccessValid(void) +{ + // No access to gbPalette during mode 3 (Color Panel Demo) + if (allowColorizerHack() || + ((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks >= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 1)))) && (!gbSpeed)) || + (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks > (GBLCD_MODE_3_CLOCK_TICKS - 2))) || ((gbLcdMode == 0) && (gbLcdTicks <= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 2)))))) + return true; + return false; +} + int inline gbGetValue(int min, int max, int v) { return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0))); @@ -919,12 +965,8 @@ void gbWriteMemory(uint16_t address, uint8_t value) } if (address < 0xa000) { - // No access to Vram during mode 3 - // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer) - if ((gbLcdModeDelayed != 3) || - // This part is used to emulate a small difference between hardwares - // (check 8-in-1's arrow on GBA/GBC to verify it) - ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))) + + if (gbVramWriteAccessValid()) gbMemoryMap[address >> 12][address & 0x0fff] = value; return; } @@ -1621,8 +1663,7 @@ void gbWriteMemory(uint16_t address, uint8_t value) int paletteIndex = (v & 0x3f) >> 1; int paletteHiLo = (v & 0x01); - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks >= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 1)))) && (!gbSpeed)) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks > (GBLCD_MODE_3_CLOCK_TICKS - 2))) || ((gbLcdMode == 0) && (gbLcdTicks <= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 2)))))) { + if (gbCgbPaletteAccessValid()) { gbMemory[0xff69] = value; gbPalette[paletteIndex] = (paletteHiLo ? ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; } @@ -1662,8 +1703,7 @@ void gbWriteMemory(uint16_t address, uint8_t value) paletteIndex += 32; - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks >= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 1)))) && (!gbSpeed)) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks > (GBLCD_MODE_3_CLOCK_TICKS - 2))) || ((gbLcdMode == 0) && (gbLcdTicks <= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 2)))))) { + if (gbCgbPaletteAccessValid()) { gbMemory[0xff6b] = value; gbPalette[paletteIndex] = (paletteHiLo ? ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; } @@ -1733,13 +1773,8 @@ uint8_t gbReadMemory(uint16_t address) return gbMemoryMap[address >> 12][address & 0x0fff]; if (address < 0xa000) { - // A lot of 'ugly' checks... But only way to emulate this particular behaviour... - if ( - ( - (gbHardware & 0xa) && ((gbLcdModeDelayed != 3) || (((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))))) - || ((gbHardware & 0x5) && (gbLcdModeDelayed != 3) && ((gbLcdMode != 3) || ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) && (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))))) + if (gbVramReadAccessValid()) return gbMemoryMap[address >> 12][address & 0x0fff]; - return 0xff; } @@ -1981,8 +2016,7 @@ uint8_t gbReadMemory(uint16_t address) case 0x69: case 0x6b: if (gbCgbMode) { - // No access to gbPalette during mode 3 (Color Panel Demo) - if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks >= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 1)))) && (!gbSpeed)) || (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) || ((gbLcdMode == 3) && (gbLcdTicks > (GBLCD_MODE_3_CLOCK_TICKS - 2))) || ((gbLcdMode == 0) && (gbLcdTicks <= (GBLCD_MODE_0_CLOCK_TICKS - gbSpritesTicks[299] - 2)))))) + if (gbCgbPaletteAccessValid()) return (gbMemory[address]); else return 0xff; @@ -3275,6 +3309,7 @@ void gbInit() { gbGenFilter(); gbSgbInit(); + setColorizerHack(false); gbMemory = (uint8_t*)malloc(65536); @@ -5425,7 +5460,6 @@ bool gbLoadRomData(const char* data, unsigned size) bios = NULL; } bios = (uint8_t*)calloc(1, 0x900); - return gbUpdateSizes(); } diff --git a/src/gb/gb.h b/src/gb/gb.h index 0d35c65a..527c41c4 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -50,6 +50,10 @@ bool gbReadGSASnapshot(const char*); bool gbLoadRomData(const char* data, unsigned size); +// Allows invalid vram/palette access needed for Colorizer hacked games in GBC/GBA hardware +void setColorizerHack(bool value); +bool allowColorizerHack(void); + extern int gbHardware; extern struct EmulatedSystem GBSystem; diff --git a/src/libretro/libretro.cpp b/src/libretro/libretro.cpp index b8288c06..12f90fc9 100644 --- a/src/libretro/libretro.cpp +++ b/src/libretro/libretro.cpp @@ -61,6 +61,7 @@ static unsigned height = 160; static EmulatedSystem* core = NULL; static IMAGE_TYPE type = IMAGE_UNKNOWN; static unsigned current_gbPalette; +static bool opt_colorizer_hack = false; uint16_t systemColorMap16[0x10000]; uint32_t systemColorMap32[0x10000]; @@ -866,6 +867,12 @@ static void gb_init(void) gbGetHardwareType(); + setColorizerHack(opt_colorizer_hack); + + // Disable bios loading when using Colorizer hack + if (opt_colorizer_hack) + usebios = false; + if (usebios) { snprintf(biosfile, sizeof(biosfile), "%s%c%s", retro_system_directory, SLASH, biosname[gbCgbMode]); @@ -1100,6 +1107,16 @@ static void update_variables(bool startup) gbEmulatorType = 5; } + var.key = "vbam_allowcolorizerhack"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "enabled") == 0) + opt_colorizer_hack = true; + else + opt_colorizer_hack = false; + } + var.key = "vbam_turboenable"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) diff --git a/src/libretro/libretro_core_options.h b/src/libretro/libretro_core_options.h index 958d3be4..0af471d0 100644 --- a/src/libretro/libretro_core_options.h +++ b/src/libretro/libretro_core_options.h @@ -89,21 +89,6 @@ struct retro_core_option_definition option_defs_us[] = { }, "5" }, - { - "vbam_gbHardware", - "(GB) Emulated Hardware", - "Sets the Game Boy hardware type to emulate.", - { - { "gbc", "Game Boy Color" }, - { "auto", "Automatic" }, - { "sgb", "Super Game Boy" }, - { "gb", "Game Boy" }, - { "gba", "Game Boy Advance" }, - { "sgb2", "Super Game Boy 2" }, - { NULL, NULL }, - }, - "gbc" - }, { "vbam_palettes", "(GB) Color Palette", @@ -122,6 +107,32 @@ struct retro_core_option_definition option_defs_us[] = { }, "standard" }, + { + "vbam_gbHardware", + "(GB) Emulated Hardware", + "Sets the Game Boy hardware type to emulate.", + { + { "gbc", "Game Boy Color" }, + { "auto", "Automatic" }, + { "sgb", "Super Game Boy" }, + { "gb", "Game Boy" }, + { "gba", "Game Boy Advance" }, + { "sgb2", "Super Game Boy 2" }, + { NULL, NULL }, + }, + "gbc" + }, + { + "vbam_allowcolorizerhack", + "(GB) Enable Colorizer Hack (Needs Restart)", + "Allows Colorizer hacked GB games (e.g. DX patched games) to normally run in GBC/GBA hardware type. This also disables the use of bios file. NOT RECOMMENDED for use on non-colorized games.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL }, + }, + "disabled" + }, { "vbam_showborders", "(GB) Show Borders",