- rewrote the tile pixel cache to work on texture IDs instead of tile IDs.

This allows using the related checking features with other textures as well.
This commit is contained in:
Christoph Oelckers 2022-12-06 18:30:57 +01:00
parent 8b0e86e88b
commit 0869497ecb
15 changed files with 179 additions and 187 deletions

View file

@ -86,7 +86,6 @@ public:
// tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy.
TArray<uint8_t> GetPalettedPixels(int conversion);
// Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format.
FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr);

View file

@ -123,6 +123,22 @@ bool ValidateTilenum(const char* cmd, int tile, FScriptPosition pos)
//
//===========================================================================
struct TileImport
{
FString fn;
int tile = -1;
int alphacut = 128, flags = 0;
int haveextra = 0;
int xoffset = INT_MAX, yoffset = INT_MAX;
int istexture = 0, extra = INT_MAX;
int64_t crc32 = INT64_MAX;
int sizex = INT_MAX, sizey;
// Blood extensions
int surface = INT_MAX, vox = INT_MAX, shade = INT_MAX;
};
void processTileImport(const char* cmd, FScriptPosition& pos, TileImport& imp)
{
if (!ValidateTilenum(cmd, imp.tile, pos))
@ -167,6 +183,11 @@ void processTileImport(const char* cmd, FScriptPosition& pos, TileImport& imp)
//
//===========================================================================
struct SetAnim
{
int tile1, tile2, speed, type;
};
void processSetAnim(const char* cmd, FScriptPosition& pos, SetAnim& imp)
{
if (!ValidateTilenum(cmd, imp.tile1, pos) ||

View file

@ -577,10 +577,11 @@ double intersectWallSprite(DCoreActor* actor, const DVector3& start, const DVect
if (checktex)
{
int tilenum = actor->spr.picnum;
tileUpdatePicnum(&tilenum);
auto tiletexid = actor->spr.spritetexture();
auto tiletex = TexMan.GetGameTexture(tiletexid, true);
auto pixels = GetRawPixels(tiletex->GetID());
if (tileLoad(tilenum))
if (pixels && tiletex->GetScaleX() == 1 && tiletex->GetScaleY() == 1) // does not work with scaled textures.
{
double zfactor = 1. - (position - result.Z) / height;
@ -589,10 +590,10 @@ double intersectWallSprite(DCoreActor* actor, const DVector3& start, const DVect
if (actor->spr.cstat & CSTAT_SPRITE_XFLIP) factor2 = 1 - factor2;
if (actor->spr.cstat & CSTAT_SPRITE_YFLIP) zfactor = 1 - zfactor;
int xtex = int(factor2 * tileWidth(tilenum));
int ytex = int(zfactor * tileHeight(tilenum));
int xtex = int(factor2 * tiletex->GetTexelWidth());
int ytex = int(zfactor * tiletex->GetTexelHeight());
auto texel = (tilePtr(tilenum) + tileHeight(tilenum) * xtex + ytex);
auto texel = (pixels + tiletex->GetTexelHeight() * xtex + ytex);
if (*texel == TRANSPARENT_INDEX)
return -1;
}

View file

@ -110,6 +110,92 @@ TArray<uint8_t> FTileTexture::CreatePalettedPixels(int conversion)
return buffer;
}
//==========================================================================
//
// raw pixel cache. This is for accessing pixel data in the game code,
// not for rendering.
//
//==========================================================================
struct RawCacheNode
{
TArray<uint8_t> data;
uint64_t lastUseTime;
RawCacheNode() = default;
RawCacheNode(RawCacheNode& other) = default;
RawCacheNode& operator=(RawCacheNode& other) = default;
RawCacheNode(RawCacheNode&& other) noexcept
{
data = std::move(other.data);
lastUseTime = other.lastUseTime;
}
RawCacheNode& operator=(RawCacheNode&& other) noexcept
{
data = std::move(other.data);
lastUseTime = other.lastUseTime;
return *this;
}
};
//==========================================================================
//
//
//
//==========================================================================
static TMap<int, RawCacheNode> CacheNodes;
const uint8_t* GetRawPixels(FTextureID texid)
{
if (!texid.isValid()) return nullptr;
auto gtex = TexMan.GetGameTexture(texid);
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
if (!tex || !tex->GetImage()) return nullptr;
auto img = tex->GetImage();
auto timg = dynamic_cast<FTileTexture*>(img);
if (!timg || !timg->GetRawData())
{
auto cache = CacheNodes.CheckKey(texid.GetIndex());
if (cache)
{
cache->lastUseTime = I_nsTime();
return cache->data.Data();
}
RawCacheNode newnode;
newnode.data = img->GetPalettedPixels(0);
newnode.lastUseTime = I_nsTime();
auto retval =newnode.data.Data();
CacheNodes.Insert(texid.GetIndex(), std::move(newnode));
return retval;
}
else
{
return timg->GetRawData();
}
}
//==========================================================================
//
//To use this the texture must have been made writable during texture init.
//
//==========================================================================
uint8_t* GetWritablePixels(FTextureID texid)
{
if (!texid.isValid()) return nullptr;
auto gtex = TexMan.GetGameTexture(texid);
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
if (!tex || !tex->GetImage()) return nullptr;
auto timg = dynamic_cast<FWritableTile*>(tex->GetImage());
if (!timg) return nullptr;
gtex->CleanHardwareData(); // we can safely assume that this only gets called when the texture is about to be changed.
return timg->GetRawData();
}
//==========================================================================
//
//
@ -245,22 +331,6 @@ int CountTiles (const char *fn, const uint8_t *RawData)
return tileend >= tilestart ? tileend - tilestart + 1 : 0;
}
//===========================================================================
//
// InvalidateTile
//
//===========================================================================
void BuildTiles::InvalidateTile(int num)
{
if ((unsigned) num < MAXTILES)
{
auto tex = tiledata[num].texture;
tex->CleanHardwareData();
tiledata[num].rawCache.data.Clear();
}
}
//===========================================================================
//
// MakeCanvas

View file

@ -7,9 +7,6 @@
#include "intvec.h"
#include "name.h"
// picanm[].sf:
// |bit(1<<7)
// |animtype|animtype|texhitscan|nofullbright|speed|speed|speed|speed|
enum AnimFlags
{
PICANM_ANIMTYPE_NONE = 0,
@ -75,12 +72,6 @@ struct picanm_t
};
picanm_t tileConvertAnimFormat(int32_t const picanmdisk, int* lo, int* to);
struct rottile_t
{
int16_t newtile;
int16_t owner;
};
class FTileTexture : public FImageSource
{
public:
@ -262,12 +253,6 @@ struct BuildArtFile
//
//==========================================================================
struct RawCacheNode
{
TArray<uint8_t> data;
uint64_t lastUseTime;
};
struct TileOffs
{
int xsize, ysize, xoffs, yoffs;
@ -276,7 +261,6 @@ struct TileOffs
struct TileDesc
{
FGameTexture* texture; // the currently active tile
RawCacheNode rawCache; // this is needed for hitscan testing to avoid reloading the texture each time.
picanm_t picanm; // animation descriptor
ReplacementType replacement;
float alphaThreshold;
@ -302,7 +286,6 @@ struct BuildTiles
TDeletingArray<BuildArtFile*> ArtFiles;
TileDesc tiledata[MAXTILES];
TArray<FString> addedArt;
TArray<FString> maptilesadded;
TMap<FName, int> nametoindex;
TMap<int, int> textotile;
bool locked; // if this is true, no more tile modifications are allowed.
@ -375,7 +358,6 @@ struct BuildTiles
FGameTexture* ValidateCustomTile(int tilenum, ReplacementType type);
uint8_t* tileMakeWritable(int num);
uint8_t* tileCreate(int tilenum, int width, int height);
void InvalidateTile(int num);
void MakeCanvas(int tilenum, int width, int height);
};
@ -384,40 +366,8 @@ int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istextu
void tileCopy(int tile, int tempsource, int temppal, int xoffset, int yoffset, int flags);
void tileSetDummy(int tile, int width, int height);
void tileDelete(int tile);
bool tileLoad(int tileNum);
void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int tilenum2, int sx2, int sy2);
extern BuildTiles TileFiles;
inline bool tileCheck(int num)
{
auto tex = TileFiles.tiledata[num].texture;
return tex && tex->GetTexelWidth() > 0 && tex->GetTexelHeight() > 0;
}
inline const uint8_t* tilePtr(int num)
{
if (TileFiles.tiledata[num].rawCache.data.Size() == 0)
{
auto tex = TileFiles.tiledata[num].texture;
if (!tex || tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0) return nullptr;
TileFiles.tiledata[num].rawCache.data = tex->GetTexture()->Get8BitPixels(false);
}
TileFiles.tiledata[num].rawCache.lastUseTime = I_nsTime();
return TileFiles.tiledata[num].rawCache.data.Data();
}
inline bool tileLoad(int tileNum)
{
return !!tilePtr(tileNum);
}
inline uint8_t* tileData(int num)
{
auto tex = dynamic_cast<FImageTexture*>(TileFiles.tiledata[num].texture->GetTexture());
if (!tex) return nullptr;
auto p = dynamic_cast<FWritableTile*>(tex->GetImage());
return p ? p->GetRawData() : nullptr;
}
// Some hacks to allow accessing the no longer existing arrays as if they still were arrays to avoid changing hundreds of lines of code.
struct PicAnm
@ -491,25 +441,9 @@ inline int legacyTileNum(FTextureID tex)
void tileUpdateAnimations();
struct TileImport
{
FString fn;
int tile = -1;
int alphacut = 128, flags = 0;
int haveextra = 0;
int xoffset = INT_MAX, yoffset = INT_MAX;
int istexture = 0, extra = INT_MAX;
int64_t crc32 = INT64_MAX;
int sizex = INT_MAX, sizey;
// Blood extensions
int surface = INT_MAX, vox = INT_MAX, shade = INT_MAX;
};
struct SetAnim
{
int tile1, tile2, speed, type;
};
const uint8_t* GetRawPixels(FTextureID texid);
uint8_t* GetWritablePixels(FTextureID texid);
void InvalidateTexture(FTextureID num);
class FGameTexture;
bool PickTexture(FGameTexture* tex, int paletteid, TexturePick& pick, bool wantindexed = false);

View file

@ -75,7 +75,7 @@ void DoFireFrame(void)
memcpy(FrameBuffer + 16896 + i * 128, SeedBuffer[nRand], 128);
}
CellularFrame(FrameBuffer, 128, 132);
auto pData = tileData(2342);
auto pData = GetWritablePixels(tileGetTextureID(2342));
uint8_t* pSource = FrameBuffer;
int x = fireSize;
do
@ -129,7 +129,6 @@ void FireProcess(void)
{
DoFireFrame();
lastUpdate = clock;
TileFiles.InvalidateTile(2342);
}
}
}

View file

@ -272,37 +272,40 @@ int VectorScan(DBloodActor* actor, double nOffset, double nZOffset, const DVecto
if ((other->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != 0)
return SS_SPRITE;
int nPicnum = other->spr.picnum;
if (tileWidth(nPicnum) == 0 || tileHeight(nPicnum) == 0)
auto nTex = other->spr.spritetexture();
auto pTex = TexMan.GetGameTexture(nTex);
int twidth = pTex->GetTexelWidth();
int theight = pTex->GetTexelHeight();
if (twidth == 0 || theight == 0 || pTex->GetScaleX() != 1 || pTex->GetScaleY() != 1) // pixel checking does not work with scaled textures (at least not with this code...)
return SS_SPRITE;
double height = (tileHeight(nPicnum) * other->spr.scale.Y);
double height = (theight * other->spr.scale.Y);
double otherZ = other->spr.pos.Z;
if (other->spr.cstat & CSTAT_SPRITE_YCENTER)
otherZ += height / 2;
int nTopOfs = tileTopOffset(nPicnum);
int nTopOfs = pTex->GetTexelTopOffset();
if (nTopOfs)
otherZ -= (nTopOfs * other->spr.scale.Y);
assert(height > 0);
double height2 = (otherZ - gHitInfo.hitpos.Z) * tileHeight(nPicnum) / height;
double height2 = (otherZ - gHitInfo.hitpos.Z) * theight / height;
if (!(other->spr.cstat & CSTAT_SPRITE_YFLIP))
height2 = tileHeight(nPicnum) - height2;
height2 = theight - height2;
if (height2 >= 0 && height2 < tileHeight(nPicnum))
if (height2 >= 0 && height2 < theight)
{
double width = (tileWidth(nPicnum) * other->spr.scale.X) * 0.75; // should actually be 0.8 to match the renderer!
double width = (twidth * other->spr.scale.X) * 0.75; // should actually be 0.8 to match the renderer!
double check1 = ((pos.Y - other->spr.pos.Y) * vel.X - (pos.X - other->spr.pos.X) * vel.Y) / vel.XY().Length();
assert(width > 0);
double width2 = check1 * tileWidth(nPicnum) / width;
int nLeftOfs = tileLeftOffset(nPicnum);
width2 += nLeftOfs + tileWidth(nPicnum) / 2;
if (width2 >= 0 && width2 < tileWidth(nPicnum))
double width2 = check1 * twidth / width;
int nLeftOfs = pTex->GetTexelLeftOffset();
width2 += nLeftOfs + twidth / 2;
if (width2 >= 0 && width2 < twidth)
{
auto pData = tilePtr(nPicnum);
if (pData[int(width2) * tileHeight(nPicnum) + int(height2)] != TRANSPARENT_INDEX)
auto pData = GetRawPixels(nTex);
if (pData[int(width2) * theight + int(height2)] != TRANSPARENT_INDEX)
return SS_SPRITE;
}
}
@ -359,7 +362,7 @@ int VectorScan(DBloodActor* actor, double nOffset, double nZOffset, const DVecto
int nHOffset = int(pWall->xpan_ + ((fHOffset * pWall->xrepeat) * 8) / nLength) % nSizX;
nnOfs %= nSizY;
auto pData = tilePtr(pWall->overpicnum);
auto pData = GetRawPixels(pWall->overtexture());
int nPixel = nHOffset * nSizY + nnOfs;
if (pData[nPixel] == TRANSPARENT_INDEX)

View file

@ -93,8 +93,6 @@ void GameInterface::SetupSpecialTextures()
{
// set up all special tiles here, before we fully hook up with the texture manager.
tileDelete(504);
TileFiles.tileCreate(4077, kLensSize, kLensSize);
TileFiles.tileCreate(4079, 128, 128);
TileFiles.tileMakeWritable(2342);
TileFiles.lock(); // from this point on the tile<->texture associations may not change anymore.
mirrortile = tileGetTextureID(504);

View file

@ -130,9 +130,6 @@ void viewDrawAimedPlayerName(PLAYER* pPlayer)
}
}
static TArray<uint8_t> lensdata;
int* lensTable;
extern DAngle random_angles[16][3];
//---------------------------------------------------------------------------
@ -145,19 +142,6 @@ void viewInit(void)
{
Printf("Initializing status bar\n");
lensdata = fileSystem.LoadFile("lens.dat");
assert(lensdata.Size() == kLensSize * kLensSize * sizeof(int));
lensTable = (int*)lensdata.Data();
#if WORDS_BIGENDIAN
for (int i = 0; i < kLensSize * kLensSize; i++)
{
lensTable[i] = LittleLong(lensTable[i]);
}
#endif
uint8_t* data = tileData(4077);
memset(data, TRANSPARENT_INDEX, kLensSize * kLensSize);
for (int i = 0; i < 16; i++)
{
random_angles[i][0] = RandomAngle();
@ -254,15 +238,8 @@ void viewSetErrorMessage(const char* pMessage)
void DoLensEffect(void)
{
// To investigate whether this can be implemented as a shader effect.
auto d = tileData(4077);
assert(d != NULL);
auto s = tilePtr(4079);
assert(s != NULL);
for (int i = 0; i < kLensSize * kLensSize; i++, d++)
if (lensTable[i] >= 0)
*d = s[lensTable[i]];
TileFiles.InvalidateTile(4077);
// the lens effect depends on the software renderer and easy availability of the pixel data.
// If this ever gets redone for hardware rendering it needs very different handling on the GPU side.
}
//---------------------------------------------------------------------------

View file

@ -31,6 +31,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
#include "names_r.h"
#include "dukeactor.h"
#include "buildtiles.h"
#include "texturemanager.h"
BEGIN_DUKE_NS
@ -39,17 +40,15 @@ BEGIN_DUKE_NS
//
//==========================================================================
void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int tilenum2, int sx2, int sy2)
void tileCopySection(FTextureID tilenum1, int sx1, int sy1, int xsiz, int ysiz, uint8_t* p2, int xsiz2, int ysiz2, int sx2, int sy2)
{
int xsiz1 = tileWidth(tilenum1);
int ysiz1 = tileHeight(tilenum1);
int xsiz2 = tileWidth(tilenum2);
int ysiz2 = tileHeight(tilenum2);
if (xsiz1 > 0 && ysiz1 > 0 && xsiz2 > 0 && ysiz2 > 0)
auto tex = TexMan.GetGameTexture(tilenum1);
int xsiz1 = tex->GetTexelWidth();
int ysiz1 = tex->GetTexelHeight();
if (xsiz1 > 0 && ysiz1 > 0)
{
auto p1 = tilePtr(tilenum1);
auto p2 = tileData(tilenum2);
if (p2 == nullptr) return; // Error: Destination is not writable.
auto p1 = GetRawPixels(tilenum1);
if (!p1) return;
int x1 = sx1;
int x2 = sx2;
@ -81,17 +80,22 @@ void tileCopySection(int tilenum1, int sx1, int sy1, int xsiz, int ysiz, int til
void updatepindisplay(int tag, int pins)
{
if (tag < 1 || tag > 4) return;
static const char* lanepics[] = { "BOWLINGLANE1", "BOWLINGLANE2", "BOWLINGLANE3", "BOWLINGLANE4" };
auto texidbg = TexMan.CheckForTexture("LANEPICBG", ETextureType::Any);
auto texidlite = TexMan.CheckForTexture("LANEPICS", ETextureType::Any);
auto texidwork = TexMan.CheckForTexture(lanepics[tag-1], ETextureType::Any);
static const uint8_t pinx[] = { 64, 56, 72, 48, 64, 80, 40, 56, 72, 88 };
static const uint8_t piny[] = { 48, 40, 40, 32, 32, 32, 24, 24, 24, 24 };
if (tag < 1 || tag > 4) return;
tag += RTILE_BOWLINGLANE1 - 1;
if (tileData(tag))
auto pixels = GetWritablePixels(texidwork);
if (pixels)
{
tileCopySection(RTILE_LANEPICBG, 0, 0, 128, 64, tag, 0, 0);
auto tex = TexMan.GetGameTexture(texidwork);
tileCopySection(texidbg, 0, 0, 128, 64, pixels, tex->GetTexelWidth(), tex->GetTexelHeight(), 0, 0);
for (int i = 0; i < 10; i++) if (pins & (1 << i))
tileCopySection(RTILE_LANEPICS, 0, 0, 8, 8, tag, pinx[i] - 4, piny[i] - 10);
TileFiles.InvalidateTile(tag);
tileCopySection(texidlite, 0, 0, 8, 8, pixels, tex->GetTexelWidth(), tex->GetTexelHeight(), pinx[i] - 4, piny[i] - 10);
}
}

View file

@ -112,10 +112,10 @@ void menu_DoPlasma()
if (!PlasmaBuffer)
{
auto pixels = tileData(kTile4092);
auto pixels = GetWritablePixels(tileGetTextureID(kTile4092));
memset(pixels, 96, kPlasmaWidth * kPlasmaHeight);
PlasmaBuffer = tileData(kTile4093);
PlasmaBuffer = GetWritablePixels(tileGetTextureID(kTile4093));
memset(PlasmaBuffer, 96, kPlasmaWidth * kPlasmaHeight);
@ -139,9 +139,9 @@ void menu_DoPlasma()
}
}
uint8_t* plasmapix = tileData(nPlasmaTile);
uint8_t* plasmapix = GetWritablePixels(tileGetTextureID(nPlasmaTile));
uint8_t* r_ebx = plasmapix + 81;
const uint8_t* r_edx = tileData(nPlasmaTile ^ 1) + 81; // flip between value of 4092 and 4093 with xor
const uint8_t* r_edx = GetWritablePixels(tileGetTextureID(nPlasmaTile ^ 1)) + 81; // flip between value of 4092 and 4093 with xor
for (int x = 0; x < kPlasmaWidth - 2; x++)
{
@ -231,7 +231,7 @@ void menu_DoPlasma()
r_ebx += 2;
}
auto logopix = tilePtr(nLogoTile);
auto logopix = GetRawPixels(tileGetTextureID(nLogoTile));
for (int j = 0; j < 5; j++)
{
@ -292,8 +292,6 @@ void menu_DoPlasma()
v28[nSmokeOffset] = 175;
}
TileFiles.InvalidateTile(nPlasmaTile);
// flip between tile 4092 and 4093
if (nPlasmaTile == kTile4092) {
nPlasmaTile = kTile4093;
@ -439,7 +437,7 @@ static int DoStatic(int a, int b)
{
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
if (tex) tex->Reload();
auto pixels = tileData(kTileLoboLaptop);
auto pixels = GetWritablePixels(tileGetTextureID(kTileLoboLaptop));
int y = 160 - a / 2;
int left = 81 - b / 2;
@ -449,8 +447,6 @@ static int DoStatic(int a, int b)
auto pTile = (pixels + (200 * y)) + left;
TileFiles.InvalidateTile(kTileLoboLaptop);
for(;y < bottom; y++)
{
uint8_t* pixel = pTile;
@ -466,10 +462,11 @@ static int DoStatic(int a, int b)
static int UndoStatic()
{
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
if (tex) tex->Reload();
TileFiles.InvalidateTile(kTileLoboLaptop);
return tileGetTexture(kTileLoboLaptop)->GetID().GetIndex();
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
if (tex) tex->Reload();
auto texid = tileGetTextureID(kTileLoboLaptop);
GetWritablePixels(texid);
return texid.GetIndex();
}
DEFINE_ACTION_FUNCTION_NATIVE(DLastLevelCinema, DoStatic, DoStatic)

View file

@ -236,7 +236,7 @@ void DrawClock()
{
int ebp = 49;
auto pixels = tileData(kTile3603);
auto pixels = GetWritablePixels(tileGetTextureID(kTile3603));
memset(pixels, TRANSPARENT_INDEX, 4096);
@ -630,16 +630,14 @@ void CopyTileToBitmap(int nSrcTile, int nDestTile, int xPos, int yPos)
{
int nOffs = tileHeight(nDestTile) * xPos;
auto pixels = tileData(nDestTile);
auto pixels = GetWritablePixels(tileGetTextureID(nDestTile));
uint8_t *pDest = pixels + nOffs + yPos;
uint8_t *pDestB = pDest;
tileLoad(nSrcTile);
int destYSize = tileHeight(nDestTile);
int srcYSize = tileHeight(nSrcTile);
const uint8_t *pSrc = tilePtr(nSrcTile);
const uint8_t *pSrc = GetRawPixels(tileGetTextureID(nSrcTile));
for (int x = 0; x < tileWidth(nSrcTile); x++)
{
@ -659,8 +657,6 @@ void CopyTileToBitmap(int nSrcTile, int nDestTile, int xPos, int yPos)
// reset pDestB
pDestB = pDest;
}
TileFiles.InvalidateTile(nDestTile);
}
//---------------------------------------------------------------------------

View file

@ -93,8 +93,8 @@ void DoEnergyTile()
{
nButtonColor += nButtonColor < 0 ? 8 : 0;
auto energy1 = tileData(kEnergy1);
auto energy2 = tileData(kEnergy2);
auto energy1 = GetWritablePixels(tileGetTextureID(kEnergy1));
auto energy2 = GetWritablePixels(tileGetTextureID(kEnergy2));
uint8_t* ptr1 = energy1 + 1984;
uint8_t* ptr2 = energy1 + 2048;
@ -117,8 +117,6 @@ void DoEnergyTile()
}
}
TileFiles.InvalidateTile(kEnergy1);
if (nSmokeSparks)
{
uint8_t* c = &energytile[67]; // skip a line
@ -245,7 +243,6 @@ void DoEnergyTile()
energytile[val] = 175;
word_9AB5B = 1;
}
TileFiles.InvalidateTile(kEnergy2);
}
}

View file

@ -224,7 +224,7 @@ void InitPlayerInventory(int nPlayer)
PlayerList[nPlayer].nPlayerScore = 0;
auto pixels = tilePtr(kTile3571 + nPlayer);
auto pixels = GetRawPixels(tileGetTextureID(kTile3571 + nPlayer));
PlayerList[nPlayer].nPlayerColor = pixels[tileWidth(nPlayer + kTile3571) * tileHeight(nPlayer + kTile3571) / 2];
}

View file

@ -68,8 +68,6 @@ void InitSpiritHead()
nSpiritScale = pSpiritSpr->spr.scale;
tileLoad(kTileRamsesNormal); // Ramses Normal Head
ExhumedSpriteIterator it;
while (auto act = it.Next())
{
@ -79,8 +77,8 @@ void InitSpiritHead()
}
}
auto pTile = tilePtr(kTileRamsesNormal); // Ramses Normal Head
auto pGold = tilePtr(kTileRamsesGold);
auto pTile = GetRawPixels(tileGetTextureID(kTileRamsesNormal)); // Ramses Normal Head
auto pGold = GetRawPixels(tileGetTextureID(kTileRamsesGold));
for (int x = 0; x < 97; x++)
{
for (int y = 0; y < 106; y++)
@ -121,14 +119,13 @@ void InitSpiritHead()
nHeadStage = 0;
// work tile is twice as big as the normal head size
Worktile = tileData(kTileRamsesWorkTile);
Worktile = GetWritablePixels(tileGetTextureID(kTileRamsesWorkTile));
pSpiritSpr->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE;
nHeadTimeStart = PlayClock;
memset(Worktile, TRANSPARENT_INDEX, WorktileSize);
TileFiles.InvalidateTile(kTileRamsesWorkTile);
nPixelsToShow = 0;
@ -176,7 +173,7 @@ void DimSector(sectortype* pSector)
void CopyHeadToWorkTile(int nTile)
{
const uint8_t* pSrc = tilePtr(nTile);
const uint8_t* pSrc = GetRawPixels(tileGetTextureID(nTile));
uint8_t *pDest = &Worktile[212 * 49 + 53];
for (unsigned i = 0; i < kSpiritY; i++)
@ -200,7 +197,6 @@ void DoSpiritHead()
auto pSpiritSpr = pSpiritSprite;
sPlayerInput[0].actions |= SB_CENTERVIEW;
TileFiles.InvalidateTile(kTileRamsesWorkTile);
switch (nHeadStage)
{
@ -263,7 +259,7 @@ void DoSpiritHead()
if (nMouthTile != 0)
{
int srctile = nMouthTile + 598;
auto src = tilePtr(srctile);
auto src = GetRawPixels(tileGetTextureID(srctile));
int sizx = tileWidth(srctile);
int sizy = tileHeight(srctile);
int workptr = 212 * (97 - sizx / 2) + 159 - sizy;