diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp index 0982d619..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; } @@ -1270,6 +1312,7 @@ void gbWriteMemory(uint16_t address, uint8_t value) //register_STAT = (register_STAT & 0x87) | // (value & 0x7c); gbMemory[0xff41] = register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? + // TODO: // GB bug from Devrs FAQ // http://www.devrs.com/gb/files/faqs.html#GBBugs // 2018-7-26 Backported STAT register bug behavior @@ -1280,12 +1323,15 @@ void gbWriteMemory(uint16_t address, uint8_t value) // Games below relies on this bug, , and are incompatible with the GBC. // - Road Rash: crash after player screen // - Zerg no Densetsu: crash right after showing a small portion of intro + // - 2019-07-18 - Speedy Gonzalez status bar relies on this as well. if ((gbHardware & 5) && (((!gbInt48Signal) && (gbLcdMode < 2) && (register_LCDC & 0x80)) || (register_LY == register_LYC))) { - gbMemory[0xff0f] = register_IF |=2; + // send LCD interrupt only if no interrupt 48h signal... + if (!gbInt48Signal) + gbMemory[0xff0f] = register_IF |= 2; } gbInt48Signal &= ((register_STAT >> 3) & 0xF); @@ -1307,7 +1353,7 @@ void gbWriteMemory(uint16_t address, uint8_t value) if (!gbInt48Signal) { gbMemory[0xff0f] = register_IF |= 2; } - gbInt48Signal |= 4; + //gbInt48Signal |= 4; } gbCompareLYToLYC(); @@ -1617,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; } @@ -1658,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; } @@ -1729,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; } @@ -1977,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; @@ -3271,6 +3309,7 @@ void gbInit() { gbGenFilter(); gbSgbInit(); + setColorizerHack(false); gbMemory = (uint8_t*)malloc(65536); @@ -5421,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/jni/Android.mk b/src/libretro/jni/Android.mk index 2529e506..304e8042 100644 --- a/src/libretro/jni/Android.mk +++ b/src/libretro/jni/Android.mk @@ -7,9 +7,20 @@ include $(LIBRETRO_DIR)/Makefile.common COREFLAGS := -DHAVE_STDINT_H -DLSB_FIRST -D__LIBRETRO__ -DFINAL_VERSION -DC_CORE -DNO_LINK -DFRONTEND_SUPPORTS_RGB565 -DTILED_RENDERING -DNO_DEBUGGER $(INCFLAGS) -GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" -ifneq ($(GIT_VERSION)," unknown") - COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +#GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" +#ifneq ($(GIT_VERSION)," unknown") +# COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +#endif + +VBAM_VERSION := $(shell sed -En 's/.*\[([0-9]+[^]]+).*/\1/p; T; q' ../../CHANGELOG.md 2>/dev/null) + +COREFLAGS += -DVBAM_VERSION=\"$(VBAM_VERSION)\" + +TAG_COMMIT := $(shell git rev-list -n 1 v$(VBAM_VERSION) --abbrev-commit 2>/dev/null) +CURRENT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null) + +ifneq ($(CURRENT_COMMIT),$(TAG_COMMIT)) +COREFLAGS += -DGIT_COMMIT=\"$(CURRENT_COMMIT)\" endif include $(CLEAR_VARS) 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",