diff --git a/src/d_main.cpp b/src/d_main.cpp index ae5400116..dc947187c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1506,6 +1506,8 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP + R_InitPaletteRemap(); + // now do it again for the SOC colors in main.pk3! M_InitPlayerSetupColors(); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index c8ae308e4..79fb6f4cb 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -522,12 +522,18 @@ static void HWR_GenerateTexture(GLMapTexture_t *grtex, INT32 texnum, boolean noe #endif #ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) + { + if (W_NeedPaletteRemap()) + R_DoPaletteRemapFlat(pdata, lumplength); realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + } else #endif { (void)lumplength; dealloc = false; + if (W_NeedPaletteRemap()) + R_DoPaletteRemapPatch(realpatch, lumplength); } HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); @@ -878,6 +884,11 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), PU_HWRCACHE, &grMipmap->data)); + // palette remapping + // have to do this here since the lump isn't cached + if (wadfiles[WADFILENUM(flatlumpnum)]->compatmode) + R_DoPaletteRemapFlat(grMipmap->data, size); + flat = grMipmap->data; for (steppy = 0; steppy < size; steppy++) if (flat[steppy] != HWR_PATCHES_CHROMAKEY_COLORINDEX) diff --git a/src/r_data.c b/src/r_data.c index 9ac323814..c2ba15c5f 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -292,6 +292,7 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) char colormap[9] = "COLORMAP"; lumpnum_t lump; const lumpnum_t basecolormaplump = W_GetNumForName(colormap); + boolean remap = false; if (num > 0 && num <= 10000) snprintf(colormap, 8, "CLM%04u", num-1); @@ -301,6 +302,7 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) lump = basecolormaplump; else { + remap = wadfiles[WADFILENUM(lump)]->compatmode; if (W_LumpLength(lump) != W_LumpLength(basecolormaplump)) { CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap); @@ -309,6 +311,19 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U); + if (remap) + { + lighttable_t *copy = malloc(W_LumpLength(basecolormaplump)); + memcpy(copy, colormaps, W_LumpLength(basecolormaplump)); + for (int p = 0; p < LIGHTLEVELS; p++) + { + for (int i = 0; i < 256; i++) + // 2.2 colormap index to 2.1, then 2.1 palette color to 2.2 + colormaps[p*256 + i] = R_GetPaletteRemap(copy[p*256 + R_InvPaletteRemap(i)]); + } + free(copy); + } + // Encore mode. if (newencoremap != LUMPERROR) { @@ -320,6 +335,16 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) colormap_p = colormap_p2 = colormaps; colormap_p += COLORMAP_REMAPOFFSET; + remap = wadfiles[WADFILENUM(newencoremap)]->compatmode; + if (remap) + { + UINT8 *copy = malloc(256); + memcpy(copy, encoremap, 256); + for (i = 0; i < 256; i++) + encoremap[i] = R_GetPaletteRemap(copy[R_InvPaletteRemap(i)]); + free(copy); + } + for (p = 0; p < LIGHTLEVELS; p++) { for (i = 0; i < 256; i++) diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 588c1cb99..5d6591b02 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -108,6 +108,7 @@ UINT8 r8_flatcolor; UINT8 *transtables; // translucency tables UINT8 *blendtables[NUMBLENDMAPS]; +UINT8 *palremap, *invremap; /** \brief R_DrawTransColumn uses this */ @@ -348,6 +349,24 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel) return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); } +void R_InitPaletteRemap(void) +{ + palremap = static_cast(Z_Malloc(256, PU_STATIC, NULL)); + invremap = static_cast(Z_Malloc(256, PU_STATIC, NULL)); + W_ReadLump(W_GetNumForName("PALREMAP"), palremap); + W_ReadLump(W_GetNumForName("INVREMAP"), invremap); +} + +UINT8 R_GetPaletteRemap(UINT8 color) +{ + return palremap[color]; +} + +UINT8 R_InvPaletteRemap(UINT8 color) +{ + return invremap[color]; +} + /** \brief Retrieves a translation colormap from the cache. \param skinnum number of skin, TC_DEFAULT or TC_BOSS diff --git a/src/r_draw.h b/src/r_draw.h index a7bc1bec8..0712ab852 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -167,11 +167,16 @@ enum extern UINT8 *blendtables[NUMBLENDMAPS]; +extern UINT8 *palremap, *invremap; + void R_InitTranslucencyTables(void); void R_GenerateBlendTables(void); +void R_InitPaletteRemap(void); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); +UINT8 R_GetPaletteRemap(UINT8 color); +UINT8 R_InvPaletteRemap(UINT8 color); // Color ramp modification should force a recache extern UINT8 skincolor_modified[]; diff --git a/src/r_textures.c b/src/r_textures.c index 9aa7f68ea..d7e6b77bd 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -295,6 +295,28 @@ static boolean R_CheckTextureLumpLength(texture_t *texture, size_t patch) return true; } +void R_DoPaletteRemapPatch(softwarepatch_t *patch, size_t size) +{ + (void)size; + UINT32 *columns = patch->columnofs; + for (INT16 i = 0; i < patch->width; i++) + { + UINT8 *p = (UINT8 *)patch + columns[i]; + while (*p++ != 0xff) // topdelta + { + int length = *p++; + for (length += 2; length--; p++) + *p = R_GetPaletteRemap(*p); + } + } +} + +void R_DoPaletteRemapFlat(UINT8 *data, size_t size) +{ + for (size_t i = 0; i < size; i++, data++) + *data = R_GetPaletteRemap(*data); +} + // // R_GenerateTexture // @@ -363,6 +385,9 @@ UINT8 *R_GenerateTexture(size_t texnum) goto multipatch; #endif + if (W_NeedPaletteRemap()) + R_DoPaletteRemapPatch(realpatch, lumplength); + // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) holey = true; @@ -458,12 +483,18 @@ UINT8 *R_GenerateTexture(size_t texnum) #endif #ifdef WALLFLATS if (texture->type == TEXTURETYPE_FLAT) + { + if (W_NeedPaletteRemap()) + R_DoPaletteRemapFlat(pdata, lumplength); realpatch = (softwarepatch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_DOOMPATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + } else #endif { (void)lumplength; dealloc = false; + if (W_NeedPaletteRemap()) + R_DoPaletteRemapPatch(realpatch, lumplength); } x1 = patch->originx; @@ -893,7 +924,10 @@ UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col) void *R_GetFlat(lumpnum_t flatlumpnum) { - return W_CacheLumpNum(flatlumpnum, PU_LEVEL); + void *flat = W_CacheLumpNum(flatlumpnum, PU_LEVEL); + if (W_NeedPaletteRemap()) + R_DoPaletteRemapFlat(flat, W_LumpLength(flatlumpnum)); + return flat; } // diff --git a/src/r_textures.h b/src/r_textures.h index 2559766f6..44f1b3d61 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -94,6 +94,8 @@ boolean R_TextureHasBrightmap(INT32 texnum); boolean R_TextureCanRemap(INT32 texnum); void R_CheckTextureCache(INT32 tex); void R_ClearTextureNumCache(boolean btell); +void R_DoPaletteRemapPatch(softwarepatch_t *patch, size_t size); +void R_DoPaletteRemapFlat(UINT8 *data, size_t size); // Retrieve texture data. void *R_GetLevelFlat(drawspandata_t* ds, levelflat_t *levelflat); diff --git a/src/v_video.c b/src/v_video.c index ae032b7bb..9f53cb1de 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -312,6 +312,9 @@ UINT32 V_GammaCorrect(UINT32 input, double power) static void LoadPalette(const char *lumpname) { lumpnum_t lumpnum = W_GetNumForName(lumpname); + boolean remap = wadfiles[WADFILENUM(lumpnum)]->compatmode; + if (remap) // if we're remapping, start with PLAYPAL as a base + lumpnum = W_GetNumForName("PLAYPAL"); size_t i, palsize = W_LumpLength(lumpnum)/3; UINT8 *pal; @@ -329,26 +332,51 @@ static void LoadPalette(const char *lumpname) pLocalPalette = pMasterPalette; pGammaCorrectedPalette = Z_Malloc(sizeof (*pGammaCorrectedPalette)*palsize, PU_STATIC, NULL); + // load the new palette (or PLAYPAL if remapping) pal = W_CacheLumpNum(lumpnum, PU_CACHE); for (i = 0; i < palsize; i++) { - RGBA_t pGCP; pMasterPalette[i].s.red = *pal++; pMasterPalette[i].s.green = *pal++; pMasterPalette[i].s.blue = *pal++; pMasterPalette[i].s.alpha = 0xFF; + } + RGBA_t *target = NULL; + if (remap) + { + // get the target palette we want + lumpnum = W_GetNumForName(lumpname); + pal = W_CacheLumpNum(lumpnum, PU_CACHE); + palsize = W_LumpLength(lumpnum)/3; + target = malloc(sizeof (*target)*palsize); + for (i = 0; i < palsize; i++) + { + target[i].s.red = *pal++; + target[i].s.green = *pal++; + target[i].s.blue = *pal++; + target[i].s.alpha = 0xFF; + } + } + + for (i = 0; i < palsize; i++) + { + if (remap) // now map the target palette (2.1) to master palette (2.2) + pMasterPalette[i].rgba = target[R_InvPaletteRemap(i)].rgba; pGammaCorrectedPalette[i].rgba = V_GammaDecode(pMasterPalette[i].rgba); if (!Cubeapply) continue; // Short hand this so its easier to type - pGCP = pGammaCorrectedPalette[i]; + RGBA_t pGCP = pGammaCorrectedPalette[i]; V_CubeApply(&pGCP.s.red,&pGCP.s.green,&pGCP.s.blue); pLocalPalette[i].rgba = V_GammaEncode(pGammaCorrectedPalette[i].rgba); } + + if (remap) + free(target); } void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) diff --git a/src/w_wad.c b/src/w_wad.c index e9f346746..49efb9cf2 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1485,6 +1485,18 @@ void zerr(int ret) } #endif +// only do palette swapping ONCE, when caching the whole patch +// dumb hack but it works! +static boolean dopalswap = false; + +// returns true if the most recently loaded lump is freshly cached, AND comes from a compatmode file +boolean W_NeedPaletteRemap(void) +{ + boolean r = dopalswap; + dopalswap = false; + return r; +} + /** Reads bytes from the head of a lump. * Note: If the lump is compressed, the whole thing has to be read anyway. * @@ -1673,11 +1685,15 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag) lumpcache = wadfiles[wad]->lumpcache; if (!lumpcache[lump]) { + dopalswap = wadfiles[wad]->compatmode; void *ptr = Z_Malloc(W_LumpLengthPwad(wad, lump), tag, &lumpcache[lump]); W_ReadLumpHeaderPwad(wad, lump, ptr, 0, 0); // read the lump in full } else + { + dopalswap = false; Z_ChangeTag(lumpcache[lump], tag); + } return lumpcache[lump]; } @@ -1819,6 +1835,10 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) ptr = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_DOOMPATCH, NULL, NULL, NULL, NULL, len, &len, 0); #endif + // we already know this is a patch, do palette remapping here + if (wadfiles[wad]->compatmode) + R_DoPaletteRemapPatch(ptr, wadfiles[wad]->lumpinfo[lump].size); + dest = Z_Calloc(sizeof(patch_t), tag, &lumpcache[lump]); Patch_Create(ptr, len, dest); diff --git a/src/w_wad.h b/src/w_wad.h index 27b7174ac..445fe56bc 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -196,6 +196,7 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); boolean W_IsPatchCached(lumpnum_t lump, void *ptr); +boolean W_NeedPaletteRemap(void); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag);