From 4cb132199cf0eb47254a66f9ae9d9b8cf9d0f537 Mon Sep 17 00:00:00 2001 From: spiritsnails <307422241+spiritsnails@users.noreply.github.com> Date: Sat, 1 Aug 2026 16:04:22 -0600 Subject: [PATCH] Fix ADVANCED palette pack using Gen 2 per-species palettes instead of Gen 1's pokered-gbc's palettes.asm carries two species->palette tables gated on GEN_2_GRAPHICS; data/palettes_gbc.lua had imported the per-species Gen 2 table, shaded for Gen 2 sprite art this port doesn't use, instead of Gen 1's own assignments. Bulbasaur wore PAL_BULBASAUR's red-orange, Squirtle wore PAL_SQUIRTLE's shell brown on his head. Palette values are unchanged; only which palette each species points at is corrected. --- data/palettes_gbc.lua | 316 ++++++++++++++------------ tests/engine/advanced_palette_map.lua | 81 +++++++ 2 files changed, 246 insertions(+), 151 deletions(-) create mode 100644 tests/engine/advanced_palette_map.lua diff --git a/data/palettes_gbc.lua b/data/palettes_gbc.lua index 5c98c88b..66a66e19 100644 --- a/data/palettes_gbc.lua +++ b/data/palettes_gbc.lua @@ -1683,158 +1683,172 @@ return { { 0, 0, 0 }, }, }, + -- Species -> palette NAME, taken from pokered-gbc data/pokemon/palettes.asm + -- ELSE branch -- the one that is NOT gated on GEN_2_GRAPHICS. + -- + -- That file has two tables. The IF GEN_2_GRAPHICS branch assigns a + -- PER-SPECIES palette (PAL_BULBASAUR, PAL_SQUIRTLE, ...) authored for Gen 2 + -- sprite art; the ELSE branch keeps Gen 1's own assignments (GREENMON, + -- CYANMON, ...). This port extracts Gen 1 pics from the ROM, so the Gen 1 + -- branch is the matching one. The per-species table was imported here by + -- mistake, which pointed every mon at colours shaded for different art: + -- Bulbasaur wore PAL_BULBASAUR's red-orange over a sprite that has no red + -- on it, and Squirtle wore PAL_SQUIRTLE's shell brown on his head. + -- + -- The palette VALUES below are still pokered-gbc's, so ADVANCED keeps its + -- richer colours -- only which palette each species points at changed. pokemon = { - ABRA = "ABRA", - AERODACTYL = "AERODACTYL", - ALAKAZAM = "ALAKAZAM", - ARBOK = "ARBOK", - ARCANINE = "ARCANINE", - ARTICUNO = "ARTICUNO", - BEEDRILL = "BEEDRILL", - BELLSPROUT = "BELLSPROUT", - BLASTOISE = "BLASTOISE", - BULBASAUR = "BULBASAUR", - BUTTERFREE = "BUTTERFREE", - CATERPIE = "CATERPIE", - CHANSEY = "CHANSEY", - CHARIZARD = "CHARIZARD", - CHARMANDER = "CHARMANDER", - CHARMELEON = "CHARMELEON", - CLEFABLE = "CLEFABLE", - CLEFAIRY = "CLEFAIRY", - CLOYSTER = "CLOYSTER", - CUBONE = "CUBONE", - DEWGONG = "DEWGONG", - DIGLETT = "DIGLETT", - DITTO = "DITTO", - DODRIO = "DODRIO", - DODUO = "DODUO", - DRAGONAIR = "DRAGONAIR", - DRAGONITE = "DRAGONITE", - DRATINI = "DRATINI", - DROWZEE = "DROWZEE", - DUGTRIO = "DUGTRIO", - EEVEE = "EEVEE", - EKANS = "EKANS", - ELECTABUZZ = "ELECTABUZZ", - ELECTRODE = "ELECTRODE", - EXEGGCUTE = "EXEGGCUTE", - EXEGGUTOR = "EXEGGUTOR", - FARFETCHD = "FARFETCH_D", - FEAROW = "FEAROW", - FLAREON = "FLAREON", - GASTLY = "GASTLY", - GENGAR = "GENGAR", - GEODUDE = "GEODUDE", - GLOOM = "GLOOM", - GOLBAT = "GOLBAT", - GOLDEEN = "GOLDEEN", - GOLDUCK = "GOLDUCK", - GOLEM = "GOLEM", - GRAVELER = "GRAVELER", - GRIMER = "GRIMER", - GROWLITHE = "GROWLITHE", - GYARADOS = "GYARADOS", - HAUNTER = "HAUNTER", - HITMONCHAN = "HITMONCHAN", - HITMONLEE = "HITMONLEE", - HORSEA = "HORSEA", - HYPNO = "HYPNO", - IVYSAUR = "IVYSAUR", - JIGGLYPUFF = "JIGGLYPUFF", - JOLTEON = "JOLTEON", - JYNX = "JYNX", - KABUTO = "KABUTO", - KABUTOPS = "KABUTOPS", - KADABRA = "KADABRA", - KAKUNA = "KAKUNA", - KANGASKHAN = "KANGASKHAN", - KINGLER = "KINGLER", - KOFFING = "KOFFING", - KRABBY = "KRABBY", - LAPRAS = "LAPRAS", - LICKITUNG = "LICKITUNG", - MACHAMP = "MACHAMP", - MACHOKE = "MACHOKE", - MACHOP = "MACHOP", - MAGIKARP = "MAGIKARP", - MAGMAR = "MAGMAR", - MAGNEMITE = "MAGNEMITE", - MAGNETON = "MAGNETON", - MANKEY = "MANKEY", - MAROWAK = "MAROWAK", - MEOWTH = "MEOWTH", - METAPOD = "METAPOD", - MEW = "MEW", - MEWTWO = "MEWTWO", - MOLTRES = "MOLTRES", - MR_MIME = "MR_MIME", - MUK = "MUK", - NIDOKING = "NIDOKING", - NIDOQUEEN = "NIDOQUEEN", - NIDORAN_F = "NIDORAN_F", - NIDORAN_M = "NIDORAN_M", - NIDORINA = "NIDORINA", - NIDORINO = "NIDORINO", - NINETALES = "NINETALES", - ODDISH = "ODDISH", - OMANYTE = "OMANYTE", - OMASTAR = "OMASTAR", - ONIX = "ONIX", - PARAS = "PARAS", - PARASECT = "PARASECT", - PERSIAN = "PERSIAN", - PIDGEOT = "PIDGEOT", - PIDGEOTTO = "PIDGEOTTO", - PIDGEY = "PIDGEY", - PIKACHU = "PIKACHU", - PINSIR = "PINSIR", - POLIWAG = "POLIWAG", - POLIWHIRL = "POLIWHIRL", - POLIWRATH = "POLIWRATH", - PONYTA = "PONYTA", - PORYGON = "PORYGON", - PRIMEAPE = "PRIMEAPE", - PSYDUCK = "PSYDUCK", - RAICHU = "RAICHU", - RAPIDASH = "RAPIDASH", - RATICATE = "RATICATE", - RATTATA = "RATTATA", - RHYDON = "RHYDON", - RHYHORN = "RHYHORN", - SANDSHREW = "SANDSHREW", - SANDSLASH = "SANDSLASH", - SCYTHER = "SCYTHER", - SEADRA = "SEADRA", - SEAKING = "SEAKING", - SEEL = "SEEL", - SHELLDER = "SHELLDER", - SLOWBRO = "SLOWBRO", - SLOWPOKE = "SLOWPOKE", - SNORLAX = "SNORLAX", - SPEAROW = "SPEAROW", - SQUIRTLE = "SQUIRTLE", - STARMIE = "STARMIE", - STARYU = "STARYU", - TANGELA = "TANGELA", - TAUROS = "TAUROS", - TENTACOOL = "TENTACOOL", - TENTACRUEL = "TENTACRUEL", - VAPOREON = "VAPOREON", - VENOMOTH = "VENOMOTH", - VENONAT = "VENONAT", - VENUSAUR = "VENUSAUR", - VICTREEBEL = "VICTREEBEL", - VILEPLUME = "VILEPLUME", - VOLTORB = "VOLTORB", - VULPIX = "VULPIX", - WARTORTLE = "WARTORTLE", - WEEDLE = "WEEDLE", - WEEPINBELL = "WEEPINBELL", - WEEZING = "WEEZING", - WIGGLYTUFF = "WIGGLYTUFF", - ZAPDOS = "ZAPDOS", - ZUBAT = "ZUBAT", + ABRA = "YELLOWMON", + AERODACTYL = "GRAYMON", + ALAKAZAM = "YELLOWMON", + ARBOK = "PURPLEMON", + ARCANINE = "REDMON", + ARTICUNO = "BLUEMON", + BEEDRILL = "YELLOWMON", + BELLSPROUT = "GREENMON", + BLASTOISE = "CYANMON", + BULBASAUR = "GREENMON", + BUTTERFREE = "CYANMON", + CATERPIE = "GREENMON", + CHANSEY = "PINKMON", + CHARIZARD = "REDMON", + CHARMANDER = "REDMON", + CHARMELEON = "REDMON", + CLEFABLE = "PINKMON", + CLEFAIRY = "PINKMON", + CLOYSTER = "GRAYMON", + CUBONE = "GRAYMON", + DEWGONG = "BLUEMON", + DIGLETT = "BROWNMON", + DITTO = "GRAYMON", + DODRIO = "BROWNMON", + DODUO = "BROWNMON", + DRAGONAIR = "BLUEMON", + DRAGONITE = "BROWNMON", + DRATINI = "GRAYMON", + DROWZEE = "YELLOWMON", + DUGTRIO = "BROWNMON", + EEVEE = "GRAYMON", + EKANS = "PURPLEMON", + ELECTABUZZ = "YELLOWMON", + ELECTRODE = "YELLOWMON", + EXEGGCUTE = "PINKMON", + EXEGGUTOR = "GREENMON", + FARFETCHD = "BROWNMON", + FEAROW = "BROWNMON", + FLAREON = "REDMON", + GASTLY = "PURPLEMON", + GENGAR = "PURPLEMON", + GEODUDE = "GRAYMON", + GLOOM = "REDMON", + GOLBAT = "BLUEMON", + GOLDEEN = "REDMON", + GOLDUCK = "CYANMON", + GOLEM = "GRAYMON", + GRAVELER = "GRAYMON", + GRIMER = "PURPLEMON", + GROWLITHE = "BROWNMON", + GYARADOS = "BLUEMON", + HAUNTER = "PURPLEMON", + HITMONCHAN = "BROWNMON", + HITMONLEE = "BROWNMON", + HORSEA = "CYANMON", + HYPNO = "YELLOWMON", + IVYSAUR = "GREENMON", + JIGGLYPUFF = "PINKMON", + JOLTEON = "YELLOWMON", + JYNX = "MEWMON", + KABUTO = "BROWNMON", + KABUTOPS = "BROWNMON", + KADABRA = "YELLOWMON", + KAKUNA = "YELLOWMON", + KANGASKHAN = "BROWNMON", + KINGLER = "REDMON", + KOFFING = "PURPLEMON", + KRABBY = "REDMON", + LAPRAS = "CYANMON", + LICKITUNG = "PINKMON", + MACHAMP = "GRAYMON", + MACHOKE = "GRAYMON", + MACHOP = "GRAYMON", + MAGIKARP = "REDMON", + MAGMAR = "REDMON", + MAGNEMITE = "GRAYMON", + MAGNETON = "GRAYMON", + MANKEY = "BROWNMON", + MAROWAK = "GRAYMON", + MEOWTH = "YELLOWMON", + METAPOD = "GREENMON", + MEW = "MEWMON", + MEWTWO = "MEWMON", + MOLTRES = "REDMON", + MR_MIME = "PINKMON", + MUK = "PURPLEMON", + NIDOKING = "PURPLEMON", + NIDOQUEEN = "BLUEMON", + NIDORAN_F = "BLUEMON", + NIDORAN_M = "PURPLEMON", + NIDORINA = "BLUEMON", + NIDORINO = "PURPLEMON", + NINETALES = "YELLOWMON", + ODDISH = "GREENMON", + OMANYTE = "BLUEMON", + OMASTAR = "BLUEMON", + ONIX = "GRAYMON", + PARAS = "REDMON", + PARASECT = "REDMON", + PERSIAN = "YELLOWMON", + PIDGEOT = "BROWNMON", + PIDGEOTTO = "BROWNMON", + PIDGEY = "BROWNMON", + PIKACHU = "YELLOWMON", + PINSIR = "BROWNMON", + POLIWAG = "BLUEMON", + POLIWHIRL = "BLUEMON", + POLIWRATH = "BLUEMON", + PONYTA = "REDMON", + PORYGON = "GRAYMON", + PRIMEAPE = "BROWNMON", + PSYDUCK = "YELLOWMON", + RAICHU = "YELLOWMON", + RAPIDASH = "REDMON", + RATICATE = "GRAYMON", + RATTATA = "GRAYMON", + RHYDON = "GRAYMON", + RHYHORN = "GRAYMON", + SANDSHREW = "BROWNMON", + SANDSLASH = "BROWNMON", + SCYTHER = "GREENMON", + SEADRA = "CYANMON", + SEAKING = "REDMON", + SEEL = "BLUEMON", + SHELLDER = "GRAYMON", + SLOWBRO = "PINKMON", + SLOWPOKE = "PINKMON", + SNORLAX = "PINKMON", + SPEAROW = "BROWNMON", + SQUIRTLE = "CYANMON", + STARMIE = "GRAYMON", + STARYU = "REDMON", + TANGELA = "BLUEMON", + TAUROS = "GRAYMON", + TENTACOOL = "CYANMON", + TENTACRUEL = "CYANMON", + VAPOREON = "CYANMON", + VENOMOTH = "PURPLEMON", + VENONAT = "PURPLEMON", + VENUSAUR = "GREENMON", + VICTREEBEL = "GREENMON", + VILEPLUME = "REDMON", + VOLTORB = "YELLOWMON", + VULPIX = "REDMON", + WARTORTLE = "CYANMON", + WEEDLE = "YELLOWMON", + WEEPINBELL = "GREENMON", + WEEZING = "PURPLEMON", + WIGGLYTUFF = "PINKMON", + ZAPDOS = "YELLOWMON", + ZUBAT = "BLUEMON", }, source = "pokered-gbc data/super_palettes.asm + data/mon_palettes.asm + color/**", world = { diff --git a/tests/engine/advanced_palette_map.lua b/tests/engine/advanced_palette_map.lua new file mode 100644 index 00000000..67cddd10 --- /dev/null +++ b/tests/engine/advanced_palette_map.lua @@ -0,0 +1,81 @@ +-- ADVANCED (redpp) must use pokered-gbc's GEN 1 species->palette map. +-- +-- pokered-gbc's data/pokemon/palettes.asm carries TWO tables: +-- +-- IF GEN_2_GRAPHICS db PAL_BULBASAUR / PAL_SQUIRTLE / ... (per species) +-- ELSE db PAL_GREENMON ; BULBASAUR +-- db PAL_CYANMON ; SQUIRTLE (Gen 1's own) +-- ENDC +-- +-- The per-species palettes are authored for GEN 2 sprite art, whose shading +-- puts different regions on different 2bpp shades. This port extracts Gen 1 +-- pics from the ROM, so the ELSE branch is the matching one. +-- +-- data/palettes_gbc.lua had imported the GEN_2_GRAPHICS table, which pointed +-- every species at colours shaded for art it does not use. Bulbasaur wore +-- PAL_BULBASAUR's red-orange (255,82,49) across 231 pixels of a sprite that +-- has no red on it at all, and Squirtle wore PAL_SQUIRTLE's shell brown on +-- his head instead of blue. It looked least wrong on mons whose two mid +-- tones are close in hue, which is why it survived so long. +-- +-- The palette VALUES are untouched -- ADVANCED keeps pokered-gbc's richer +-- colours. Only the species -> name mapping changed. +package.path = "./?.lua;./?/init.lua;" .. package.path + +local T = require("tests.modkit") +local pack = require("data.palettes_gbc") + +T.check(pack and pack.pokemon, "the ADVANCED pack carries a species map") + +local n = 0 +for _ in pairs(pack.pokemon) do n = n + 1 end +T.eq(n, 151, "every species is mapped") + +-- Gen 1's palette set: the ten MonsterPalettes names plus nothing else. A +-- per-species name here means the GEN_2_GRAPHICS table crept back in. +local GEN1_NAMES = { + MEWMON = true, BLUEMON = true, REDMON = true, CYANMON = true, + PURPLEMON = true, BROWNMON = true, GREENMON = true, PINKMON = true, + YELLOWMON = true, GRAYMON = true, +} + +local strays = {} +for species, name in pairs(pack.pokemon) do + if not GEN1_NAMES[name] then strays[#strays + 1] = species .. "->" .. name end +end +table.sort(strays) +T.eq(#strays, 0, + "no species points at a Gen-2-only per-species palette (" .. + table.concat(strays, ", ", 1, math.min(#strays, 6)) .. ")") + +-- the four the bug was reported on, plus their lines +local EXPECT = { + BULBASAUR = "GREENMON", IVYSAUR = "GREENMON", VENUSAUR = "GREENMON", + CHARMANDER = "REDMON", CHARMELEON = "REDMON", CHARIZARD = "REDMON", + SQUIRTLE = "CYANMON", WARTORTLE = "CYANMON", BLASTOISE = "CYANMON", + MEW = "MEWMON", MEWTWO = "MEWMON", JYNX = "MEWMON", + LAPRAS = "CYANMON", +} +for species, want in pairs(EXPECT) do + T.eq(pack.pokemon[species], want, species .. " uses " .. want) +end + +-- Bulbasaur's palette must contain no red channel dominance in either mid -- +-- the concrete symptom that was reported ("he shouldn't have red anywhere"). +local green = pack.palettes[pack.pokemon.BULBASAUR] +T.check(green ~= nil, "GREENMON resolves to colours") +for _, i in ipairs({ 2, 3 }) do + local c = green[i] + T.check(c[2] > c[1], ("GREENMON mid %d is green-dominant, not red (%d,%d,%d)") + :format(i - 1, c[1], c[2], c[3])) +end + +-- and Squirtle's mids must be blue-dominant +local cyan = pack.palettes[pack.pokemon.SQUIRTLE] +for _, i in ipairs({ 2, 3 }) do + local c = cyan[i] + T.check(c[3] >= c[1], ("CYANMON mid %d is blue-dominant (%d,%d,%d)") + :format(i - 1, c[1], c[2], c[3])) +end + +T.finish("advanced palette map")