- cleanup

This commit is contained in:
Christoph Oelckers 2019-10-15 23:56:29 +02:00
parent 57c221644a
commit 4dc69620b7
5 changed files with 155 additions and 705 deletions

View file

@ -1032,23 +1032,6 @@ int32_t engineLoadClipMaps(void);
#endif
int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);
void tileSetupDummy(int32_t tile);
void tileSetData(int32_t tile, int32_t tsiz, char const *buffer);
void tileSetSize(int32_t picnum, int16_t dasizx, int16_t dasizy);
int32_t artReadHeader(buildvfs_kfd fil, char const *fn, artheader_t *local);
int32_t artReadHeaderFromBuffer(uint8_t const *buf, artheader_t *local);
int32_t artCheckUnitFileHeader(uint8_t const *buf, int32_t length);
void artReadManifest(buildvfs_kfd fil, artheader_t const *local);
void artPreloadFile(buildvfs_kfd fil, artheader_t const *local);
void artClearMapArt(void);
void artSetupMapArt(const char *filename);
bool tileCache(int tilenume);
const uint8_t* tilePtr(int num); // read-only
uint8_t* tileData(int num); // writable.
bool tileLoad(int16_t tilenume);
void tileLoadData(int16_t tilenume, int32_t dasiz, char *buffer);
void tileUpdatePicSiz(int32_t picnum);
int32_t qloadkvx(int32_t voxindex, const char *filename);
void vox_undefine(int32_t const);
void tileCopySection(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, int32_t tilenume2, int32_t sx2, int32_t sy2);

View file

@ -1621,17 +1621,6 @@ static int get_screen_coords(const vec2_t &p1, const vec2_t &p2,
}
static inline int findUnusedTile(void)
{
static int lastUnusedTile = MAXUSERTILES-1;
for (; lastUnusedTile >= 0; --lastUnusedTile)
if ((tilesiz[lastUnusedTile].x|tilesiz[lastUnusedTile].y) == 0)
return lastUnusedTile;
return -1;
}
//
// scansector (internal)
//
@ -8258,7 +8247,7 @@ void engineUnInit(void)
# endif
#endif
//TileFiles.CloseAll();
TileFiles.CloseAll();
DO_FREE_AND_NULL(lookups);
for (bssize_t i=0; i<DISTRECIPCACHESIZE; i++)
@ -8463,19 +8452,18 @@ int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
if (wall[i].cstat & CSTAT_WALL_ROTATE_90)
{
auto &w = wall[i];
auto &tile = rottile[w.picnum+animateoffs(w.picnum,16384)];
auto &tile = RotTile(w.picnum+animateoffs(w.picnum,16384));
if (tile.newtile == -1 && tile.owner == -1)
{
tile.newtile = findUnusedTile();
auto owner = w.picnum + animateoffs(w.picnum, 16384);
tile.newtile = TileFiles.tileCreateRotated(owner);
Bassert(tile.newtile != -1);
rottile[tile.newtile].owner = w.picnum+animateoffs(w.picnum,16384);
RotTile(tile.newtile).owner = w.picnum+animateoffs(w.picnum,16384);
auto &siz = tilesiz[w.picnum+animateoffs(w.picnum,16384)];
tileSetSize(tile.newtile, siz.x, siz.y);
tileLoad(tile.newtile);
}
}
}

View file

@ -16,14 +16,6 @@
#include "vfs.h"
void *pic = NULL;
// The tile file number (tilesXXX <- this) of each tile:
// 0 <= . < MAXARTFILES_BASE: tile is in a "base" ART file
// MAXARTFILES_BASE <= . < MAXARTFILES_TOTAL: tile is in a map-specific ART file
static uint8_t tilefilenum[MAXTILES];
EDUKE32_STATIC_ASSERT(MAXARTFILES_TOTAL <= 256);
static int32_t tilefileoffs[MAXTILES];
vec2_16_t tilesizearray[MAXTILES];
@ -34,657 +26,6 @@ const uint8_t* const picsiz = picsizearray;
static const uint8_t *tileptr[MAXTILES]; // points to tile data -. may be constant
static uint8_t* tiledata[MAXTILES]; // points to modifiable tile data - only set by tileCreate!
// Backup tilefilenum[] and tilefileoffs[]. These get allocated only when
// necessary (have per-map ART files).
static uint8_t *g_bakTileFileNum;
static int32_t *g_bakTileFileOffs;
static vec2_16_t *g_bakTileSiz;
static char *g_bakPicSiz;
static char *g_bakWalock;
static const uint8_t *g_bakWaloff;
static picanm_t *g_bakPicAnm;
static char * g_bakFakeTile;
static char ** g_bakFakeTileData;
// NOTE: picsiz[] is not backed up, but recalculated when necessary.
//static int32_t artsize = 0;
static int32_t cachesize = 0;
static char artfilename[BMAX_PATH];
static char artfilenameformat[BMAX_PATH];
static char mapartfilename[BMAX_PATH]; // map-specific ART file name
static int32_t mapartfnXXofs; // byte offset to 'XX' (the number part) in the above
static int32_t artfilnum, artfilplc;
static buildvfs_kfd artfil;
////////// Per-map ART file loading //////////
// Some forward declarations.
static const char *artGetIndexedFileName(int32_t tilefilei);
static int32_t artReadIndexedFile(int32_t tilefilei);
static inline void artClearMapArtFilename(void)
{
Bmemset(mapartfilename, 0, sizeof(mapartfilename));
mapartfnXXofs = 0;
}
static inline void artUpdateManifest(void)
{
for (bssize_t i=0; i<MAXTILES; i++)
tileUpdatePicSiz(i);
}
template <typename origar_t, typename bakar_t>
static inline void RESTORE_MAPART_ARRAY(origar_t & origar, bakar_t & bakar)
{
EDUKE32_STATIC_ASSERT(sizeof(origar[0]) == sizeof(bakar[0]));
Bmemcpy(origar, bakar, ARRAY_SIZE(origar) * sizeof(origar[0]));
DO_FREE_AND_NULL(bakar);
}
template <typename origar_t, typename bakar_t>
static inline void ALLOC_MAPART_ARRAY(origar_t & origar, bakar_t & bakar)
{
bakar = (bakar_t) Xmalloc(ARRAY_SIZE(origar) * sizeof(origar[0]));
Bmemcpy(bakar, origar, ARRAY_SIZE(origar) * sizeof(origar[0]));
}
void artClearMapArt(void)
{
if (g_bakTileFileNum == NULL)
return; // per-map ART N/A
artClearMapArtFilename();
if (artfilnum >= MAXARTFILES_BASE)
{
kclose(artfil);
artfil = buildvfs_kfd_invalid;
artfilnum = -1;
artfilplc = 0L;
}
for (bssize_t i=0; i<MAXTILES; i++)
{
if (tilefilenum[i] >= MAXARTFILES_BASE)
{
// XXX: OK way to free it? Better: cache1d API. CACHE1D_FREE
walock[i] = 1;
tileptr[i] = nullptr;
}
}
// Restore original per-tile arrays
RESTORE_MAPART_ARRAY(tilefilenum, g_bakTileFileNum);
RESTORE_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs);
RESTORE_MAPART_ARRAY(tilesizearray, g_bakTileSiz);
RESTORE_MAPART_ARRAY(picsizearray, g_bakPicSiz);
RESTORE_MAPART_ARRAY(walock, g_bakWalock);
//RESTORE_MAPART_ARRAY(tileptr, g_bakWaloff);
RESTORE_MAPART_ARRAY(picanm, g_bakPicAnm);
RESTORE_MAPART_ARRAY(faketile, g_bakFakeTile);
for (size_t i = 0; i < MAXUSERTILES; ++i)
{
if (faketiledata[i] != g_bakFakeTileData[i])
{
free(faketiledata[i]);
faketiledata[i] = g_bakFakeTileData[i];
}
}
DO_FREE_AND_NULL(g_bakFakeTileData);
artUpdateManifest();
#ifdef USE_OPENGL
//POGOTODO: review this to ensure we're not invalidating more than we have to
gltexinvalidatetype(INVALIDATE_ART);
#endif
}
void artSetupMapArt(const char *filename)
{
artClearMapArt();
if (Bstrlen(filename) + 7 >= sizeof(mapartfilename))
return;
Bstrcpy(mapartfilename, filename);
append_ext_UNSAFE(mapartfilename, "_XX.art");
mapartfnXXofs = Bstrlen(mapartfilename) - 6;
// Check for first per-map ART file: if that one doesn't exist, don't load any.
buildvfs_kfd fil = kopen4load(artGetIndexedFileName(MAXARTFILES_BASE), 0);
if (fil == buildvfs_kfd_invalid)
{
artClearMapArtFilename();
return;
}
kclose(fil);
// Allocate backup arrays.
ALLOC_MAPART_ARRAY(tilefilenum, g_bakTileFileNum);
ALLOC_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs);
ALLOC_MAPART_ARRAY(tilesizearray, g_bakTileSiz);
ALLOC_MAPART_ARRAY(picsizearray, g_bakPicSiz);
ALLOC_MAPART_ARRAY(walock, g_bakWalock);
//ALLOC_MAPART_ARRAY(tileptr, g_bakWaloff);
ALLOC_MAPART_ARRAY(picanm, g_bakPicAnm);
ALLOC_MAPART_ARRAY(faketile, g_bakFakeTile);
ALLOC_MAPART_ARRAY(faketiledata, g_bakFakeTileData);
for (bssize_t i=MAXARTFILES_BASE; i<MAXARTFILES_TOTAL; i++)
{
int ret = artReadIndexedFile(i);
if (ret != 0)
{
// NOTE: i == MAXARTFILES_BASE && ret == -1 can only have happened
// if the file was deleted between the above file existence check
// and now. Very cornerly... but I like my code to be prepared to
// any eventuality.
if (i == MAXARTFILES_BASE || ret != -1)
artClearMapArt();
break;
}
}
artUpdateManifest();
#ifdef USE_OPENGL
//POGOTODO: review this to ensure we're not invalidating more than we have to
gltexinvalidatetype(INVALIDATE_ART);
# ifdef POLYMER
if (videoGetRenderMode() == REND_POLYMER)
polymer_texinvalidate();
# endif
#endif
}
//
// ART loading
//
void tileSetupDummy(int32_t const tile)
{
faketile[tile>>3] |= pow2char[tile&7];
DO_FREE_AND_NULL(faketiledata[tile]);
}
static void tileSetDataSafe(int32_t const tile, int32_t tsiz, char const * const buffer)
{
int const compressed_tsiz = LZ4_compressBound(tsiz);
char * newtile = (char *) Xmalloc(compressed_tsiz);
if ((tsiz = LZ4_compress_default(buffer, newtile, tsiz, compressed_tsiz)) != -1)
{
faketiledata[tile] = (char *) Xrealloc(newtile, tsiz);
faketile[tile>>3] |= pow2char[tile&7];
tilefilenum[tile] = MAXARTFILES_TOTAL;
}
else
{
free(newtile);
}
}
void tileSetData(int32_t const tile, int32_t tsiz, char const * const buffer)
{
int const compressed_tsiz = LZ4_compressBound(tsiz);
faketiledata[tile] = (char *) Xrealloc(faketiledata[tile], compressed_tsiz);
if ((tsiz = LZ4_compress_default(buffer, faketiledata[tile], tsiz, compressed_tsiz)) != -1)
{
faketiledata[tile] = (char *) Xrealloc(faketiledata[tile], tsiz);
faketile[tile>>3] |= pow2char[tile&7];
tilefilenum[tile] = MAXARTFILES_TOTAL;
}
else
{
DO_FREE_AND_NULL(faketiledata[tile]);
faketile[tile>>3] &= ~pow2char[tile&7];
}
}
static void tileSoftDelete(int32_t const tile)
{
tilesizearray[tile].x = 0;
tilesizearray[tile].y = 0;
picsizearray[tile] = 0;
// CACHE1D_FREE
walock[tile] = 1;
tileptr[tile] = nullptr;
tiledata[tile] = nullptr;
faketile[tile>>3] &= ~pow2char[tile&7];
picanm[tile] = {};
}
void tileUpdatePicSiz(int32_t picnum)
{
int j = 15;
while ((j > 1) && (pow2long[j] > tilesiz[picnum].x))
j--;
picsizearray[picnum] = j;
j = 15;
while ((j > 1) && (pow2long[j] > tilesiz[picnum].y))
j--;
picsizearray[picnum] |= j<<4;
}
void tileSetSize(int32_t picnum, int16_t dasizx, int16_t dasizy)
{
tilesizearray[picnum].x = dasizx;
tilesizearray[picnum].y = dasizy;
tileUpdatePicSiz(picnum);
}
int32_t artReadHeader(buildvfs_kfd const fil, char const * const fn, artheader_t * const local)
{
int32_t artversion;
kread(fil, &artversion, 4); artversion = B_LITTLE32(artversion);
if (artversion == B_LITTLE32(0x4c495542))
{
kread(fil, &artversion, 4); artversion = B_LITTLE32(artversion);
if (artversion == B_LITTLE32(0x54524144))
{
kread(fil, &artversion, 4); artversion = B_LITTLE32(artversion);
}
else
{
initprintf("loadpics: Invalid art file, %s\n", fn);
kclose(fil);
return 1;
}
}
if (artversion != 1)
{
initprintf("loadpics: Invalid art file version in %s\n", fn);
kclose(fil);
return 1;
}
int32_t numtiles_dummy;
kread(fil, &numtiles_dummy, 4);
kread(fil, &local->tilestart, 4); local->tilestart = B_LITTLE32(local->tilestart);
kread(fil, &local->tileend, 4); local->tileend = B_LITTLE32(local->tileend);
if ((uint32_t) local->tilestart >= MAXUSERTILES || (uint32_t) local->tileend >= MAXUSERTILES)
{
initprintf("loadpics: Invalid localtilestart or localtileend in %s\n", fn);
kclose(fil);
return 1;
}
if (local->tileend < local->tilestart)
{
initprintf("loadpics: localtileend < localtilestart in %s\n", fn);
kclose(fil);
return 1;
}
local->numtiles = (local->tileend-local->tilestart+1);
return 0;
}
int32_t artReadHeaderFromBuffer(uint8_t const * const buf, artheader_t * const local)
{
int const artversion = B_LITTLE32(B_UNBUF32(&buf[0]));
if (EDUKE32_PREDICT_FALSE(artversion != 1))
{
initprintf("loadpics: Invalid art file version\n");
return 1;
}
local->tilestart = B_LITTLE32(B_UNBUF32(&buf[8]));
local->tileend = B_LITTLE32(B_UNBUF32(&buf[12]));
if (EDUKE32_PREDICT_FALSE((unsigned) local->tilestart >= MAXUSERTILES || (unsigned) local->tileend >= MAXUSERTILES))
{
initprintf("loadpics: Invalid localtilestart or localtileend\n");
return 1;
}
if (EDUKE32_PREDICT_FALSE(local->tileend < local->tilestart))
{
initprintf("loadpics: localtileend < localtilestart\n");
return 1;
}
local->numtiles = (local->tileend-local->tilestart+1);
return 0;
}
int32_t artCheckUnitFileHeader(uint8_t const * const buf, int32_t length)
{
if (EDUKE32_PREDICT_FALSE(length <= ARTv1_UNITOFFSET))
return -1;
artheader_t local;
if (EDUKE32_PREDICT_FALSE(artReadHeaderFromBuffer(buf, &local) != 0))
return -2;
if (EDUKE32_PREDICT_FALSE(local.numtiles != 1))
return -3;
return 0;
}
void artReadManifest(int32_t const fil, artheader_t const* const local)
{
int16_t* tilesizx = (int16_t*)Xmalloc(local->numtiles * sizeof(int16_t));
int16_t* tilesizy = (int16_t*)Xmalloc(local->numtiles * sizeof(int16_t));
kread(fil, tilesizx, local->numtiles * sizeof(int16_t));
kread(fil, tilesizy, local->numtiles * sizeof(int16_t));
for (bssize_t i = local->tilestart; i <= local->tileend; i++)
{
int32_t picanmdisk;
tilesizearray[i].x = B_LITTLE16(tilesizx[i - local->tilestart]);
tilesizearray[i].y = B_LITTLE16(tilesizy[i - local->tilestart]);
kread(fil, &picanmdisk, sizeof(int32_t));
picanmdisk = B_LITTLE32(picanmdisk);
picanm[i] = tileConvertAnimFormat(picanmdisk);
}
DO_FREE_AND_NULL(tilesizx);
DO_FREE_AND_NULL(tilesizy);
}
void artPreloadFile(buildvfs_kfd const fil, artheader_t const * const local)
{
char *buffer = NULL;
int32_t buffersize = 0;
for (bssize_t i=local->tilestart; i<=local->tileend; i++)
{
int const dasiz = tilesiz[i].x * tilesiz[i].y;
if (dasiz == 0)
{
tileDelete(i);
continue;
}
maybe_grow_buffer(&buffer, &buffersize, dasiz);
kread(fil, buffer, dasiz);
tileSetData(i, dasiz, buffer);
}
DO_FREE_AND_NULL(buffer);
}
static void artPreloadFileSafe(buildvfs_kfd const fil, artheader_t const * const local)
{
char *buffer = NULL;
int32_t buffersize = 0;
for (bssize_t i=local->tilestart; i<=local->tileend; i++)
{
int const dasiz = tilesiz[i].x * tilesiz[i].y;
if (dasiz == 0)
{
tileSoftDelete(i);
continue;
}
maybe_grow_buffer(&buffer, &buffersize, dasiz);
kread(fil, buffer, dasiz);
tileSetDataSafe(i, dasiz, buffer);
}
DO_FREE_AND_NULL(buffer);
}
static const char *artGetIndexedFileName(int32_t tilefilei)
{
if (tilefilei >= MAXARTFILES_BASE)
{
int32_t o = mapartfnXXofs;
tilefilei -= MAXARTFILES_BASE;
mapartfilename[o+1] = '0' + tilefilei%10;
mapartfilename[o+0] = '0' + (tilefilei/10)%10;
return mapartfilename;
}
else
{
Bsnprintf(artfilename, sizeof(artfilename), artfilenameformat, tilefilei);
return artfilename;
}
}
// Returns:
// 0: successfully read ART file
// >0: error with the ART file
// -1: ART file does not exist
//<-1: per-map ART issue
static int32_t artReadIndexedFile(int32_t tilefilei)
{
const char *fn = artGetIndexedFileName(tilefilei);
const int32_t permap = (tilefilei >= MAXARTFILES_BASE); // is it a per-map ART file?
buildvfs_kfd fil;
if ((fil = kopen4loadfrommod(fn, 0)) != buildvfs_kfd_invalid)
{
artheader_t local;
int const headerval = artReadHeader(fil, fn, &local);
if (headerval != 0)
{
kclose(fil);
return headerval;
}
if (permap)
{
// Check whether we can evict existing tiles to make place for
// per-map ART ones.
for (int i=local.tilestart; i<=local.tileend; i++)
{
// Tiles having dummytile replacements or those that are
// cache1d-locked can't be replaced.
if (faketile[i>>3] & pow2char[i&7] || walock[i] >= 200)
{
initprintf("loadpics: per-map ART file \"%s\": "
"tile %d has dummytile or is locked\n", fn, i);
kclose(fil);
return -3;
}
}
// Free existing tiles from the cache1d. CACHE1D_FREE
Bmemset(&tileptr[local.tilestart], 0, local.numtiles*sizeof(uint8_t*));
Bmemset(&tiledata[local.tilestart], 0, local.numtiles * sizeof(uint8_t*));
Bmemset(&walock[local.tilestart], 1, local.numtiles*sizeof(walock[0]));
}
artReadManifest(fil, &local);
if (cache1d_file_fromzip(fil))
{
if (permap)
artPreloadFileSafe(fil, &local);
else
artPreloadFile(fil, &local);
}
else
{
int offscount = ktell(fil);
for (bssize_t i=local.tilestart; i<=local.tileend; ++i)
{
int const dasiz = tilesiz[i].x * tilesiz[i].y;
tilefilenum[i] = tilefilei;
tilefileoffs[i] = offscount;
offscount += dasiz;
// artsize += ((dasiz+15)&0xfffffff0);
}
}
kclose(fil);
return 0;
}
return -1;
}
//
// loadpics
//
const uint8_t* tilePtr(int num)
{
auto tex = TileFiles.tiles[num];
assert(tex);
if (tex->Get8BitPixels()) return tex->Get8BitPixels();
return tileptr[num];
}
uint8_t* tileData(int num)
{
auto tex = TileFiles.tiles[num];
assert(tex);
if (tex->GetWritableBuffer()) return tex->GetWritableBuffer();
return tiledata[num];
}
//
// loadtile
//
bool tileLoad(int16_t tileNum)
{
if ((unsigned) tileNum >= (unsigned) MAXTILES) return 0;
auto tex = TileFiles.tiles[tileNum]->Get8BitPixels();
if (tex) return true;
int const dasiz = tilesiz[tileNum].x*tilesiz[tileNum].y;
if (dasiz <= 0) return 0;
// Allocate storage if necessary.
if (tileptr[tileNum] == nullptr)
{
walock[tileNum] = 199;
intptr_t handle;
cacheAllocateBlock(&handle, dasiz, &walock[tileNum]);
tileptr[tileNum] = (const uint8_t*)handle;
}
tileLoadData(tileNum, dasiz, (char *)tileptr[tileNum]);
return (tileptr[tileNum] != nullptr && tilesiz[tileNum].x > 0 && tilesiz[tileNum].y > 0);
}
bool tileCache(int tilenume)
{
if ((unsigned)tilenume >= (unsigned)MAXTILES) return false;
if (!tileptr[tilenume]) return tileLoad(tilenume);
return true;
}
void tileMaybeRotate(int16_t tilenume)
{
auto &rot = rottile[tilenume];
auto &siz = tilesiz[rot.owner];
auto src = (char *)tileptr[rot.owner];
auto dst = (char *)tileptr[tilenume];
// the engine has a squarerotatetile() we could call, but it mirrors at the same time
for (int x = 0; x < siz.x; ++x)
{
int const xofs = siz.x - x - 1;
int const yofs = siz.y * x;
for (int y = 0; y < siz.y; ++y)
*(dst + y * siz.x + xofs) = *(src + y + yofs);
}
tileSetSize(tilenume, siz.y, siz.x);
}
void tileLoadData(int16_t tilenume, int32_t dasiz, char *buffer)
{
int const owner = rottile[tilenume].owner;
if (owner != -1)
{
if (!tileptr[owner])
tileLoad(owner);
if (tileptr[tilenume])
tileMaybeRotate(tilenume);
return;
}
int const tfn = tilefilenum[tilenume];
// dummy tiles for highres replacements and tilefromtexture definitions
if (faketile[tilenume>>3] & pow2char[tilenume&7])
{
if (faketiledata[tilenume] != NULL)
LZ4_decompress_fast(faketiledata[tilenume], buffer, dasiz);
faketimerhandler();
return;
}
// Potentially switch open ART file.
if (tfn != artfilnum)
{
if (artfil != buildvfs_kfd_invalid)
kclose(artfil);
char const *fn = artGetIndexedFileName(tfn);
artfil = kopen4loadfrommod(fn, 0);
if (artfil == buildvfs_kfd_invalid)
{
initprintf("Failed opening ART file \"%s\"!\n", fn);
engineUnInit();
Bexit(11);
}
artfilnum = tfn;
artfilplc = 0L;
faketimerhandler();
}
// Seek to the right position.
if (artfilplc != tilefileoffs[tilenume])
{
klseek(artfil, tilefileoffs[tilenume], BSEEK_SET);
faketimerhandler();
}
kread(artfil, buffer, dasiz);
faketimerhandler();
artfilplc = tilefileoffs[tilenume]+dasiz;
}
//
// copytilepiece
//
void tileCopySection(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz,
@ -724,10 +65,3 @@ void tileCopySection(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz,
tileInvalidate(tilenume2, -1, -1);
}
void Buninitart(void)
{
if (artfil != buildvfs_kfd_invalid)
kclose(artfil);
ALIGNED_FREE_AND_NULL(pic);
}

View file

@ -498,6 +498,41 @@ void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags
picanm->sf = (picanm->sf & ~PICANM_MISC_MASK) | (sourceanm->sf & PICANM_MISC_MASK) | flags;
}
//==========================================================================
//
// Clear map specific ART
//
//==========================================================================
void artClearMapArt(void)
{
TileFiles.CloseAllMapArt();
memcpy(TileFiles.tiles, TileFiles.tilesbak, sizeof(TileFiles.tiles));
}
//==========================================================================
//
// Load map specfici ART
//
//==========================================================================
void artSetupMapArt(const char* filename)
{
artClearMapArt();
FStringf firstname("%s_00.art", filename);
auto fr = kopenFileReader(firstname, 0);
if (!fr.isOpen()) return;
for (bssize_t i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++)
{
FStringf fullname("%s_%02d.art", filename, i);
TileFiles.LoadArtFile(fullname, true);
}
}
//==========================================================================
//
//
//
//==========================================================================
@ -531,3 +566,80 @@ void tileSetDummy(int tile, int width, int height)
}
}
//==========================================================================
//
//
//
//==========================================================================
bool tileLoad(int tileNum)
{
if ((unsigned)tileNum >= MAXTILES) return false;
auto tex = TileFiles.tiles[tileNum];
if (!tex || tex->GetWidth() <= 0 || tex->GetHeight() <= 0) return false;
if (tex->Get8BitPixels()) return true;
tex->CacheLock = 199;
if (!tex->CacheHandle)
{
// Allocate storage if necessary.
int size = tex->GetWidth() * tex->GetHeight();
cacheAllocateBlock(&tex->CacheHandle, size, &tex->CacheLock);
tex->Create8BitPixels((uint8_t*)tex->CacheHandle);
}
return true;
}
//==========================================================================
//
//
//
//==========================================================================
int BuildFiles::findUnusedTile(void)
{
static int lastUnusedTile = MAXUSERTILES - 1;
for (; lastUnusedTile >= 0; --lastUnusedTile)
{
auto tex = TileFiles.tiles[lastUnusedTile];
if (!tex || tex->GetWidth() <= 0 || tex->GetHeight() <= 0) return lastUnusedTile;
}
return -1;
}
int BuildFiles::tileCreateRotated(int tileNum)
{
if ((unsigned)tileNum >= MAXTILES) return tileNum;
auto tex = TileFiles.tiles[tileNum];
if (!tex || tex->GetWidth() <= 0 || tex->GetHeight() <= 0) return tileNum;
TArray<uint8_t> buffer(tex->GetWidth() * tex->GetHeight(), true);
tex->Create8BitPixels(buffer.Data());
TArray<uint8_t> dbuffer(tex->GetWidth() * tex->GetHeight(), true);
auto src = buffer.Data();
auto dst = dbuffer.Data();
// the engine has a squarerotatetile() we could call, but it mirrors at the same time
auto siz = tex->GetSize();
for (int x = 0; x < siz.x; ++x)
{
int xofs = siz.x - x - 1;
int yofs = siz.y * x;
for (int y = 0; y < siz.y; ++y)
*(dst + y * siz.x + xofs) = *(src + y + yofs);
}
auto dtex = new FLooseTile(dbuffer, tex->GetHeight(), tex->GetWidth());
int index = findUnusedTile();
bool mapart = TileFiles.tiles[tileNum] != TileFiles.tilesbak[tileNum];
TileFiles.AddTile(index, dtex, mapart);
return index;
}
void tileSetAnim(int tile, const picanm_t& anm)
{
}

View file

@ -493,11 +493,20 @@ struct BuildFiles
delete Placeholder;
}
void CloseAll()
{
CloseAllMapArt();
ArtFiles.DeleteAndClear();
AllTiles.DeleteAndClear();
delete Placeholder;
Placeholder = nullptr;
}
void AddTile(int tilenum, FTexture* tex, bool permap = false);
void AddTiles(int firsttile, TArray<uint8_t>& store, bool permap);
void AddFile(BuildArtFile *bfd, bool permap)
void AddFile(BuildArtFile* bfd, bool permap)
{
if (!permap) ArtFiles.Push(bfd);
else PerMapArtFiles.Push(bfd);
@ -511,10 +520,11 @@ struct BuildFiles
void LoadArtSet(const char* filename);
FTexture* ValidateCustomTile(int tilenum, int type);
int32_t artLoadFiles(const char* filename);
uint8_t *tileMakeWritable(int num);
uint8_t *tileCreate(int tilenum, int width, int height);
uint8_t* tileMakeWritable(int num);
uint8_t* tileCreate(int tilenum, int width, int height);
void tileSetExternal(int tilenum, int width, int height, uint8_t* data);
int findUnusedTile(void);
int tileCreateRotated(int owner);
};
int tileCRC(int tileNum);
@ -522,6 +532,11 @@ 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 artClearMapArt(void);
void artSetupMapArt(const char* filename);
void tileSetAnim(int tile, const picanm_t& anm);
extern BuildFiles TileFiles;
inline bool tileCheck(int num)
{
@ -529,6 +544,24 @@ inline bool tileCheck(int num)
return tex->GetWidth() > 0 && tex->GetHeight() > 0;
}
inline const uint8_t* tilePtr(int num)
{
auto tex = TileFiles.tiles[num];
auto p = tex->Get8BitPixels();
if (p) return p;
return (const uint8_t*)tex->CacheHandle;
}
inline uint8_t* tileData(int num)
{
auto tex = TileFiles.tiles[num];
return tex->GetWritableBuffer();
}
inline rottile_t& RotTile(int tile)
{
return TileFiles.tiles[tile]->GetRotTile();
}
#endif