diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index d526b991d..5472ac209 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -43,6 +43,7 @@ ENGINE_OBJS = \ crc32 \ defs \ engine \ + tiles \ clip \ 2d \ hash \ diff --git a/polymer/eduke32/Makefile.msvc b/polymer/eduke32/Makefile.msvc index 17a2e9b78..5b84efad8 100644 --- a/polymer/eduke32/Makefile.msvc +++ b/polymer/eduke32/Makefile.msvc @@ -139,6 +139,7 @@ ENGINE_OBJS= \ $(ENGINE_OBJ)\engine.$o \ $(ENGINE_OBJ)\clip.$o \ $(ENGINE_OBJ)\2d.$o \ + $(ENGINE_OBJ)\tiles.$o \ $(ENGINE_OBJ)\hash.$o \ $(ENGINE_OBJ)\palette.$o \ $(ENGINE_OBJ)\glbuild.$o \ diff --git a/polymer/eduke32/build/Makefile.deps b/polymer/eduke32/build/Makefile.deps index d6ec0e648..636782f5f 100644 --- a/polymer/eduke32/build/Makefile.deps +++ b/polymer/eduke32/build/Makefile.deps @@ -10,8 +10,9 @@ $(ENGINE_OBJ)/config.$o: $(ENGINE_SRC)/config.c $(ENGINE_INC)/compat.h $(ENGINE_ $(ENGINE_OBJ)/crc32.$o: $(ENGINE_SRC)/crc32.c $(ENGINE_INC)/crc32.h $(ENGINE_OBJ)/defs.$o: $(ENGINE_SRC)/defs.c $(ENGINE_INC)/build.h $(ENGINE_INC)/buildtypes.h $(ENGINE_INC)/baselayer.h $(ENGINE_INC)/scriptfile.h $(ENGINE_INC)/compat.h $(ENGINE_OBJ)/engine.$o: $(ENGINE_SRC)/engine.c $(ENGINE_INC)/compat.h $(ENGINE_INC)/build.h $(ENGINE_INC)/buildtypes.h $(ENGINE_INC)/pragmas.h $(ENGINE_INC)/cache1d.h $(ENGINE_INC)/a.h $(ENGINE_INC)/osd.h $(ENGINE_INC)/baselayer.h $(ENGINE_SRC)/engine_priv.h $(ENGINE_SRC)/engine_oldmap.h $(ENGINE_INC)/polymost.h $(ENGINE_INC)/hightile.h $(ENGINE_INC)/mdsprite.h $(ENGINE_INC)/polymer.h -$(ENGINE_OBJ)/2d.$o: $(ENGINE_SRC)/2d.c -$(ENGINE_OBJ)/clip.$o: $(ENGINE_SRC)/clip.c +$(ENGINE_OBJ)/2d.$o: $(ENGINE_SRC)/2d.c $(ENGINE_INC)/build.h +$(ENGINE_OBJ)/tiles.$o: $(ENGINE_SRC)/tiles.c $(ENGINE_INC)/build.h +$(ENGINE_OBJ)/clip.$o: $(ENGINE_SRC)/clip.c $(ENGINE_INC)/build.h $(ENGINE_INC)/clip.h $(ENGINE_OBJ)/screenshot.$o: $(ENGINE_SRC)/screenshot.c $(ENGINE_OBJ)/hash.$o: $(ENGINE_SRC)/hash.c $(ENGINE_INC)/hash.h $(ENGINE_OBJ)/colmatch.$o: $(ENGINE_SRC)/colmatch.c diff --git a/polymer/eduke32/build/include/build.h b/polymer/eduke32/build/include/build.h index 045cbdd21..4dfa391fe 100644 --- a/polymer/eduke32/build/include/build.h +++ b/polymer/eduke32/build/include/build.h @@ -1074,6 +1074,7 @@ int32_t printext16(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize) ATTRIBUTE((nonnull(5))); void printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize) ATTRIBUTE((nonnull(5))); +void Buninitart(void); ////////// specialized rotatesprite wrappers for (very) often used cases ////////// FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index c6d5cdc88..2f636344f 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -7,9 +7,6 @@ #define ENGINE -#if (PNG_LIBPNG_VER > 10599) -# include -#endif #include "compat.h" #include "build.h" #include "editor.h" @@ -38,11 +35,6 @@ # endif #endif -#ifdef USE_LIBPNG -//# include -# include -#endif - #include // pow #include "engine_priv.h" @@ -177,28 +169,7 @@ int32_t globalx1, globaly2, globalx3, globaly3; int32_t sloptable[16384]; static intptr_t slopalookup[16384]; // was 2048 -static 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]; static int32_t lastageclock; - -// 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_t *g_bakTileSiz; -static picanm_t *g_bakPicAnm; -// NOTE: picsiz[] is not backed up, but recalculated when necessary. - -//static int32_t artsize = 0; -static int32_t cachesize = 0; - static int32_t no_radarang2 = 0; static int16_t radarang[1280], *radarang2; @@ -1498,11 +1469,6 @@ int16_t searchsector, searchwall, searchstat; //search output // When aiming at a 2-sided wall, 1 if aiming at the bottom part, 0 else int16_t searchbottomwall, searchisbottom; -static char artfilename[20]; -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 artfil = -1, artfilnum, artfilplc; - char inpreparemirror = 0; static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2; @@ -7779,11 +7745,9 @@ void uninitengine(void) polymer_uninit(); # endif #endif + + Buninitart(); - if (artfil != -1) - kclose(artfil); - - DO_FREE_AND_NULL(pic); DO_FREE_AND_NULL(lookups); ALIGNED_FREE_AND_NULL(distrecip); @@ -8931,146 +8895,6 @@ void drawmapview(int32_t dax, int32_t day, int32_t zoome, int16_t ang) setaspect(65536, divscale16(ydim*320, xdim*200)); } -////////// Per-map ART file loading ////////// - -// Some forward declarations. -static void set_picsiz(int32_t picnum); -static const char *E_GetArtFileName(int32_t tilefilei); -static int32_t E_ReadArtFileOfID(int32_t tilefilei); - -static inline void clearmapartfilename(void) -{ - Bmemset(mapartfilename, 0, sizeof(mapartfilename)); - mapartfnXXofs = 0; -} - -static inline void E_RecalcPicSiz(void) -{ - for (int i=0; i -static inline void ALLOC_MAPART_ARRAY(origar_t &origar, bakar_t &bakar) -{ - bakar = (bakar_t)Xmalloc(MAXUSERTILES*sizeof(origar[0])); - Bmemcpy(bakar, origar, MAXUSERTILES*sizeof(origar[0])); -} -#else -#define ALLOC_MAPART_ARRAY(origar, bakar) do { \ - bakar = Xmalloc(MAXUSERTILES*sizeof(origar[0])); \ - Bmemcpy(bakar, origar, MAXUSERTILES*sizeof(origar[0])); \ -} while (0) -#endif - -void E_MapArt_Clear(void) -{ - int32_t i; - - if (g_bakTileFileNum == NULL) - return; // per-map ART N/A - - clearmapartfilename(); - - if (artfilnum >= MAXARTFILES_BASE) - { - kclose(artfil); - - artfil = -1; - artfilnum = -1; - artfilplc = 0L; - } - - for (i=0; i= MAXARTFILES_BASE) - { - // XXX: OK way to free it? Better: cache1d API. CACHE1D_FREE - walock[i] = 1; - waloff[i] = 0; - } - - // Restore original per-tile arrays - RESTORE_MAPART_ARRAY(tilefilenum, g_bakTileFileNum); - RESTORE_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs); - RESTORE_MAPART_ARRAY(tilesiz, g_bakTileSiz); - RESTORE_MAPART_ARRAY(picanm, g_bakPicAnm); - - E_RecalcPicSiz(); -#ifdef USE_OPENGL - gltexinvalidatetype(INVALIDATE_ART); -# ifdef POLYMER - if (getrendermode() == REND_POLYMER) - polymer_texinvalidate(); -# endif -#endif -} - -void E_MapArt_Setup(const char *filename) -{ - int32_t i; - - E_MapArt_Clear(); - - 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. - { - int32_t fil = kopen4load(E_GetArtFileName(MAXARTFILES_BASE), 0); - - if (fil == -1) - { - clearmapartfilename(); - return; - } - - kclose(fil); - } - - // Allocate backup arrays. - ALLOC_MAPART_ARRAY(tilefilenum, g_bakTileFileNum); - ALLOC_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs); - ALLOC_MAPART_ARRAY(tilesiz, g_bakTileSiz); - ALLOC_MAPART_ARRAY(picanm, g_bakPicAnm); - - for (i=MAXARTFILES_BASE; i>3] |= pow2char[tile&7]; - DO_FREE_AND_NULL(faketiledata[tile]); -} - -void E_CreateFakeTile(int32_t const tile, int32_t tsiz, char const * const buffer) -{ - faketiledata[tile] = (char *)Xrealloc(faketiledata[tile], LZ4_compressBound(tsiz)); - - if ((tsiz = LZ4_compress(buffer, faketiledata[tile], tsiz)) != -1) - { - faketiledata[tile] = (char *)Xrealloc(faketiledata[tile], tsiz); - faketile[tile>>3] |= pow2char[tile&7]; - } - else - { - DO_FREE_AND_NULL(faketiledata[tile]); - faketile[tile>>3] &= ~pow2char[tile&7]; - } -} - -void E_UndefineTile(int32_t const tile) -{ - tilesiz[tile].x = 0; - tilesiz[tile].y = 0; - picsiz[tile] = 0; - - // CACHE1D_FREE - walock[tile] = 1; - waloff[tile] = 0; - - DO_FREE_AND_NULL(faketiledata[tile]); - faketile[tile>>3] &= ~pow2char[tile&7]; - - Bmemset(&picanm[tile], 0, sizeof(picanm_t)); -} - -static void set_picsiz(int32_t picnum) -{ - int32_t j; - - j = 15; - while ((j > 1) && (pow2long[j] > tilesiz[picnum].x)) - j--; - picsiz[picnum] = j; - - j = 15; - while ((j > 1) && (pow2long[j] > tilesiz[picnum].y)) - j--; - picsiz[picnum] |= j<<4; -} - -void set_tilesiz(int32_t picnum, int16_t dasizx, int16_t dasizy) -{ - tilesiz[picnum].x = dasizx; - tilesiz[picnum].y = dasizy; - - set_picsiz(picnum); -} - -int32_t tile_exists(int32_t picnum) -{ - if (waloff[picnum] == 0) - loadtile(picnum); - - return (waloff[picnum] != 0 && tilesiz[picnum].x > 0 && tilesiz[picnum].y > 0); -} - -int32_t E_ReadArtFileHeader(int32_t const fil, char const * const fn, artheader_t * const local) -{ - int32_t artversion; - kread(fil,&artversion,4); artversion = B_LITTLE32(artversion); - 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 E_ReadArtFileHeaderFromBuffer(uint8_t const * const buf, artheader_t * const local) -{ - int32_t 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 E_CheckUnitArtFileHeader(uint8_t const * const buf, int32_t length) -{ - if (EDUKE32_PREDICT_FALSE(length <= ARTv1_UNITOFFSET)) - return -1; - - artheader_t local; - if (EDUKE32_PREDICT_FALSE(E_ReadArtFileHeaderFromBuffer(buf, &local) != 0)) - return -2; - - if (EDUKE32_PREDICT_FALSE(local.numtiles != 1)) - return -3; - - return 0; -} - -void E_ConvertARTv1picanmToMemory(int32_t const picnum) -{ - EDUKE32_STATIC_ASSERT(sizeof(picanm_t) == 4); - EDUKE32_STATIC_ASSERT(PICANM_ANIMTYPE_MASK == 192); - - picanm_t * const thispicanm = &picanm[picnum]; - - // Old on-disk format: anim type is in the 2 highest bits of the lowest byte. - thispicanm->sf &= ~192; - thispicanm->sf |= thispicanm->num&192; - thispicanm->num &= ~192; - - // don't allow setting texhitscan/nofullbright from ART - thispicanm->sf &= ~PICANM_MISC_MASK; -} - -void E_ReadArtFileTileInfo(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)); - kread(fil, &picanm[local->tilestart], local->numtiles*sizeof(picanm_t)); - - for (int32_t i=local->tilestart; i<=local->tileend; i++) - { - tilesiz[i].x = B_LITTLE16(tilesizx[i-local->tilestart]); - tilesiz[i].y = B_LITTLE16(tilesizy[i-local->tilestart]); - - E_ConvertARTv1picanmToMemory(i); - } - - DO_FREE_AND_NULL(tilesizx); - DO_FREE_AND_NULL(tilesizy); -} - -void E_ReadArtFileIntoFakeData(int32_t const fil, artheader_t const * const local) -{ - char *buffer = NULL; - int32_t buffersize = 0; - - for (int32_t i=local->tilestart; i<=local->tileend; i++) - { - int32_t dasiz = tilesiz[i].x * tilesiz[i].y; - - if (dasiz == 0) - { - E_UndefineTile(i); - continue; - } - - maybe_grow_buffer(&buffer, &buffersize, dasiz); - - kread(fil, buffer, dasiz); - - E_CreateFakeTile(i, dasiz, buffer); - } - - DO_FREE_AND_NULL(buffer); -} - -static const char *E_GetArtFileName(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 - { - artfilename[7] = '0' + tilefilei%10; - artfilename[6] = '0' + (tilefilei/10)%10; - artfilename[5] = '0' + (tilefilei/100)%10; - - 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 E_ReadArtFileOfID(int32_t tilefilei) -{ - const char *fn = E_GetArtFileName(tilefilei); - const int32_t permap = (tilefilei >= MAXARTFILES_BASE); // is it a per-map ART file? - int32_t fil; - - if ((fil = kopen4load(fn,0)) != -1) - { -#ifdef WITHKPLIB - if (permap && cache1d_file_fromzip(fil)) - { - initprintf("loadpics: per-map ART file \"%s\": can't be read from a ZIP file\n", fn); - kclose(fil); - return -2; - } -#endif - - artheader_t local; - int32_t headerval = E_ReadArtFileHeader(fil, fn, &local); - if (headerval != 0) - return headerval; - - if (permap) - { - // Check whether we can evict existing tiles to make place for - // per-map ART ones. - for (int32_t 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(&waloff[local.tilestart], 0, local.numtiles*sizeof(intptr_t)); - Bmemset(&walock[local.tilestart], 1, local.numtiles*sizeof(walock[0])); - } - - E_ReadArtFileTileInfo(fil, &local); - - if (cache1d_file_fromzip(fil)) - { - E_ReadArtFileIntoFakeData(fil, &local); - } - else - { - int32_t offscount = 4+4+4+4+(local.numtiles<<3); - - for (int32_t i=local.tilestart; i<=local.tileend; i++) - { - int32_t dasiz = tilesiz[i].x * tilesiz[i].y; - - tilefilenum[i] = tilefilei; - tilefileoffs[i] = offscount; - - offscount += dasiz; - // artsize += ((dasiz+15)&0xfffffff0); - } - } - -#ifdef DEBUGGINGAIDS - if (permap) - initprintf("Read in per-map ART file \"%s\"\n", fn); -#endif - kclose(fil); - return 0; - } - - return -1; -} - -// -// loadpics -// -int32_t loadpics(const char *filename, int32_t askedsize) -{ - int32_t tilefilei; - - Bstrncpyz(artfilename, filename, sizeof(artfilename)); - - Bmemset(&tilesiz[0], 0, sizeof(vec2_t) * MAXTILES); - Bmemset(picanm, 0, sizeof(picanm)); - -// artsize = 0; - - for (tilefilei=0; tilefilei= (unsigned)MAXTILES) return; - if ((dasiz = tilesiz[tilenume].x*tilesiz[tilenume].y) <= 0) return; - - // Allocate storage if necessary. - if (waloff[tilenume] == 0) - { - walock[tilenume] = 199; - allocache(&waloff[tilenume],dasiz,&walock[tilenume]); - } - - E_LoadTileIntoBuffer(tilenume, dasiz, (char *)waloff[tilenume]); - - postloadtile(tilenume); -} - -void E_LoadTileIntoBuffer(int16_t tilenume, int32_t dasiz, char *buffer) -{ - // 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; - } - - int32_t const i = tilefilenum[tilenume]; - - // Potentially switch open ART file. - if (i != artfilnum) - { - const char *fn; - - if (artfil != -1) - kclose(artfil); - - fn = E_GetArtFileName(i); - - artfil = kopen4load(fn, 0); - if (artfil == -1) - { - initprintf("Failed opening ART file \"%s\"!\n", fn); - uninitengine(); - Bexit(11); - } - - artfilnum = i; - 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; -} - -static void postloadtile(int16_t tilenume) -{ -#if !defined DEBUG_TILESIZY_512 && !defined DEBUG_TILEOFFSETS - UNREFERENCED_PARAMETER(tilenume); -#endif -#ifdef DEBUG_TILESIZY_512 - if (tilesizy[tilenume] >= 512) - { - int32_t i; - char *p = (char *)waloff[tilenume]; - for (i=0; i= MAXTILES) - return 0; - - dasiz = xsiz*ysiz; - - walock[tilenume] = 255; - allocache(&waloff[tilenume], dasiz, &walock[tilenume]); - - set_tilesiz(tilenume, xsiz, ysiz); - Bmemset(&picanm[tilenume], 0, sizeof(picanm_t)); - - return waloff[tilenume]; -} - -// -// copytilepiece -// -void copytilepiece(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, - int32_t tilenume2, int32_t sx2, int32_t sy2) -{ - char *ptr1, *ptr2, dat; - int32_t xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2; - - xsiz1 = tilesiz[tilenume1].x; ysiz1 = tilesiz[tilenume1].y; - xsiz2 = tilesiz[tilenume2].x; ysiz2 = tilesiz[tilenume2].y; - if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0)) - { - if (waloff[tilenume1] == 0) loadtile(tilenume1); - if (waloff[tilenume2] == 0) loadtile(tilenume2); - - x1 = sx1; - for (i=0; i= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2)) - { - ptr1 = (char *)(waloff[tilenume1] + x1*ysiz1 + y1); - ptr2 = (char *)(waloff[tilenume2] + x2*ysiz2 + y2); - dat = *ptr1; - if (dat != 255) - *ptr2 = *ptr1; - } - - y1++; if (y1 >= ysiz1) y1 = 0; - } - x1++; if (x1 >= xsiz1) x1 = 0; - } - } -} - // // qloadkvx // int32_t qloadkvx(int32_t voxindex, const char *filename) { - const int32_t fil = kopen4load(filename,0); + const int32_t fil = kopen4load(filename, 0); if (fil == -1) return -1; @@ -10669,7 +9938,7 @@ int32_t qloadkvx(int32_t voxindex, const char *filename) voxlock[voxindex][i] = 200; allocache(&voxoff[voxindex][i], dasiz, &voxlock[voxindex][i]); - char *ptr = (char *)voxoff[voxindex][i]; + char *ptr = (char *) voxoff[voxindex][i]; kread(fil, ptr, dasiz); lengcnt += dasiz+4; @@ -10694,7 +9963,6 @@ int32_t qloadkvx(int32_t voxindex, const char *filename) return 0; } - // // inside // diff --git a/polymer/eduke32/build/src/tiles.c b/polymer/eduke32/build/src/tiles.c new file mode 100644 index 000000000..4c24438b6 --- /dev/null +++ b/polymer/eduke32/build/src/tiles.c @@ -0,0 +1,738 @@ + +#include "compat.h" +#include "build.h" +#include "engine_priv.h" +#include "cache1d.h" +#include "lz4.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]; + +// 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_t *g_bakTileSiz; +static picanm_t *g_bakPicAnm; +// NOTE: picsiz[] is not backed up, but recalculated when necessary. + +//static int32_t artsize = 0; +static int32_t cachesize = 0; + +static char artfilename[20]; +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 artfil = -1, artfilnum, artfilplc; + +////////// Per-map ART file loading ////////// + +// Some forward declarations. +static void set_picsiz(int32_t picnum); +static const char *E_GetArtFileName(int32_t tilefilei); +static int32_t E_ReadArtFileOfID(int32_t tilefilei); + +static inline void clearmapartfilename(void) +{ + Bmemset(mapartfilename, 0, sizeof(mapartfilename)); + mapartfnXXofs = 0; +} + +static inline void E_RecalcPicSiz(void) +{ + for (int i=0; i +static inline void ALLOC_MAPART_ARRAY(origar_t &origar, bakar_t &bakar) +{ + bakar = (bakar_t) Xmalloc(MAXUSERTILES*sizeof(origar[0])); + Bmemcpy(bakar, origar, MAXUSERTILES*sizeof(origar[0])); +} +#else +#define ALLOC_MAPART_ARRAY(origar, bakar) \ + do \ + { \ + bakar = Xmalloc(MAXUSERTILES * sizeof(origar[0])); \ + Bmemcpy(bakar, origar, MAXUSERTILES * sizeof(origar[0])); \ + \ +} while (0) +#endif + +void E_MapArt_Clear(void) +{ + int32_t i; + + if (g_bakTileFileNum == NULL) + return; // per-map ART N/A + + clearmapartfilename(); + + if (artfilnum >= MAXARTFILES_BASE) + { + kclose(artfil); + + artfil = -1; + artfilnum = -1; + artfilplc = 0L; + } + + for (i=0; i= MAXARTFILES_BASE) + { + // XXX: OK way to free it? Better: cache1d API. CACHE1D_FREE + walock[i] = 1; + waloff[i] = 0; + } + + // Restore original per-tile arrays + RESTORE_MAPART_ARRAY(tilefilenum, g_bakTileFileNum); + RESTORE_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs); + RESTORE_MAPART_ARRAY(tilesiz, g_bakTileSiz); + RESTORE_MAPART_ARRAY(picanm, g_bakPicAnm); + + E_RecalcPicSiz(); +#ifdef USE_OPENGL + gltexinvalidatetype(INVALIDATE_ART); +# ifdef POLYMER + if (getrendermode() == REND_POLYMER) + polymer_texinvalidate(); +# endif +#endif +} + +void E_MapArt_Setup(const char *filename) +{ + int32_t i; + + E_MapArt_Clear(); + + 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. + int32_t fil = kopen4load(E_GetArtFileName(MAXARTFILES_BASE), 0); + + if (fil == -1) + { + clearmapartfilename(); + return; + } + + kclose(fil); + + // Allocate backup arrays. + ALLOC_MAPART_ARRAY(tilefilenum, g_bakTileFileNum); + ALLOC_MAPART_ARRAY(tilefileoffs, g_bakTileFileOffs); + ALLOC_MAPART_ARRAY(tilesiz, g_bakTileSiz); + ALLOC_MAPART_ARRAY(picanm, g_bakPicAnm); + + for (i=MAXARTFILES_BASE; i>3] |= pow2char[tile&7]; + DO_FREE_AND_NULL(faketiledata[tile]); +} + +void E_CreateFakeTile(int32_t const tile, int32_t tsiz, char const * const buffer) +{ + faketiledata[tile] = (char *) Xrealloc(faketiledata[tile], LZ4_compressBound(tsiz)); + + if ((tsiz = LZ4_compress(buffer, faketiledata[tile], tsiz)) != -1) + { + faketiledata[tile] = (char *) Xrealloc(faketiledata[tile], tsiz); + faketile[tile>>3] |= pow2char[tile&7]; + } + else + { + DO_FREE_AND_NULL(faketiledata[tile]); + faketile[tile>>3] &= ~pow2char[tile&7]; + } +} + +void E_UndefineTile(int32_t const tile) +{ + tilesiz[tile].x = 0; + tilesiz[tile].y = 0; + picsiz[tile] = 0; + + // CACHE1D_FREE + walock[tile] = 1; + waloff[tile] = 0; + + DO_FREE_AND_NULL(faketiledata[tile]); + faketile[tile>>3] &= ~pow2char[tile&7]; + + Bmemset(&picanm[tile], 0, sizeof(picanm_t)); +} + +static void set_picsiz(int32_t picnum) +{ + int j = 15; + + while ((j > 1) && (pow2long[j] > tilesiz[picnum].x)) + j--; + picsiz[picnum] = j; + + j = 15; + while ((j > 1) && (pow2long[j] > tilesiz[picnum].y)) + j--; + picsiz[picnum] |= j<<4; +} + +void set_tilesiz(int32_t picnum, int16_t dasizx, int16_t dasizy) +{ + tilesiz[picnum].x = dasizx; + tilesiz[picnum].y = dasizy; + + set_picsiz(picnum); +} + +int32_t tile_exists(int32_t picnum) +{ + if (waloff[picnum] == 0) + loadtile(picnum); + + return (waloff[picnum] != 0 && tilesiz[picnum].x > 0 && tilesiz[picnum].y > 0); +} + +int32_t E_ReadArtFileHeader(int32_t const fil, char const * const fn, artheader_t * const local) +{ + int32_t artversion; + kread(fil, &artversion, 4); artversion = B_LITTLE32(artversion); + 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 E_ReadArtFileHeaderFromBuffer(uint8_t const * const buf, artheader_t * const local) +{ + int32_t 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 E_CheckUnitArtFileHeader(uint8_t const * const buf, int32_t length) +{ + if (EDUKE32_PREDICT_FALSE(length <= ARTv1_UNITOFFSET)) + return -1; + + artheader_t local; + if (EDUKE32_PREDICT_FALSE(E_ReadArtFileHeaderFromBuffer(buf, &local) != 0)) + return -2; + + if (EDUKE32_PREDICT_FALSE(local.numtiles != 1)) + return -3; + + return 0; +} + +void E_ConvertARTv1picanmToMemory(int32_t const picnum) +{ + EDUKE32_STATIC_ASSERT(sizeof(picanm_t) == 4); + EDUKE32_STATIC_ASSERT(PICANM_ANIMTYPE_MASK == 192); + + picanm_t * const thispicanm = &picanm[picnum]; + + // Old on-disk format: anim type is in the 2 highest bits of the lowest byte. + thispicanm->sf &= ~192; + thispicanm->sf |= thispicanm->num&192; + thispicanm->num &= ~192; + + // don't allow setting texhitscan/nofullbright from ART + thispicanm->sf &= ~PICANM_MISC_MASK; +} + +void E_ReadArtFileTileInfo(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)); + kread(fil, &picanm[local->tilestart], local->numtiles*sizeof(picanm_t)); + + for (int32_t i=local->tilestart; i<=local->tileend; i++) + { + tilesiz[i].x = B_LITTLE16(tilesizx[i-local->tilestart]); + tilesiz[i].y = B_LITTLE16(tilesizy[i-local->tilestart]); + + E_ConvertARTv1picanmToMemory(i); + } + + DO_FREE_AND_NULL(tilesizx); + DO_FREE_AND_NULL(tilesizy); +} + +void E_ReadArtFileIntoFakeData(int32_t const fil, artheader_t const * const local) +{ + char *buffer = NULL; + int32_t buffersize = 0; + + for (int32_t i=local->tilestart; i<=local->tileend; i++) + { + int32_t dasiz = tilesiz[i].x * tilesiz[i].y; + + if (dasiz == 0) + { + E_UndefineTile(i); + continue; + } + + maybe_grow_buffer(&buffer, &buffersize, dasiz); + + kread(fil, buffer, dasiz); + + E_CreateFakeTile(i, dasiz, buffer); + } + + DO_FREE_AND_NULL(buffer); +} + +static const char *E_GetArtFileName(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 + { + artfilename[7] = '0' + tilefilei%10; + artfilename[6] = '0' + (tilefilei/10)%10; + artfilename[5] = '0' + (tilefilei/100)%10; + + 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 E_ReadArtFileOfID(int32_t tilefilei) +{ + const char *fn = E_GetArtFileName(tilefilei); + const int32_t permap = (tilefilei >= MAXARTFILES_BASE); // is it a per-map ART file? + int32_t fil; + + if ((fil = kopen4load(fn, 0)) != -1) + { +#ifdef WITHKPLIB + if (permap && cache1d_file_fromzip(fil)) + { + initprintf("loadpics: per-map ART file \"%s\": can't be read from a ZIP file\n", fn); + kclose(fil); + return -2; + } +#endif + + artheader_t local; + int32_t headerval = E_ReadArtFileHeader(fil, fn, &local); + if (headerval != 0) + return headerval; + + if (permap) + { + // Check whether we can evict existing tiles to make place for + // per-map ART ones. + for (int32_t 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(&waloff[local.tilestart], 0, local.numtiles*sizeof(intptr_t)); + Bmemset(&walock[local.tilestart], 1, local.numtiles*sizeof(walock[0])); + } + + E_ReadArtFileTileInfo(fil, &local); + + if (cache1d_file_fromzip(fil)) + { + E_ReadArtFileIntoFakeData(fil, &local); + } + else + { + int32_t offscount = 4+4+4+4+(local.numtiles<<3); + + for (int32_t i=local.tilestart; i<=local.tileend; i++) + { + int32_t dasiz = tilesiz[i].x * tilesiz[i].y; + + tilefilenum[i] = tilefilei; + tilefileoffs[i] = offscount; + + offscount += dasiz; + // artsize += ((dasiz+15)&0xfffffff0); + } + } + +#ifdef DEBUGGINGAIDS + if (permap) + initprintf("Read in per-map ART file \"%s\"\n", fn); +#endif + kclose(fil); + return 0; + } + + return -1; +} + +// +// loadpics +// +int32_t loadpics(const char *filename, int32_t askedsize) +{ + int32_t tilefilei; + + Bstrncpyz(artfilename, filename, sizeof(artfilename)); + + Bmemset(&tilesiz[0], 0, sizeof(vec2_t) * MAXTILES); + Bmemset(picanm, 0, sizeof(picanm)); + + // artsize = 0; + + for (tilefilei=0; tilefilei= (unsigned) MAXTILES) return; + if ((dasiz = tilesiz[tilenume].x*tilesiz[tilenume].y) <= 0) return; + + // Allocate storage if necessary. + if (waloff[tilenume] == 0) + { + walock[tilenume] = 199; + allocache(&waloff[tilenume], dasiz, &walock[tilenume]); + } + + E_LoadTileIntoBuffer(tilenume, dasiz, (char *) waloff[tilenume]); + + postloadtile(tilenume); +} + +void E_LoadTileIntoBuffer(int16_t tilenume, int32_t dasiz, char *buffer) +{ + // 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; + } + + int32_t const i = tilefilenum[tilenume]; + + // Potentially switch open ART file. + if (i != artfilnum) + { + const char *fn; + + if (artfil != -1) + kclose(artfil); + + fn = E_GetArtFileName(i); + + artfil = kopen4load(fn, 0); + if (artfil == -1) + { + initprintf("Failed opening ART file \"%s\"!\n", fn); + uninitengine(); + Bexit(11); + } + + artfilnum = i; + 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; +} + +static void postloadtile(int16_t tilenume) +{ +#if !defined DEBUG_TILESIZY_512 && !defined DEBUG_TILEOFFSETS + UNREFERENCED_PARAMETER(tilenume); +#endif +#ifdef DEBUG_TILESIZY_512 + if (tilesizy[tilenume] >= 512) + { + int32_t i; + char *p = (char *) waloff[tilenume]; + for (i=0; i= MAXTILES) + return 0; + + dasiz = xsiz*ysiz; + + walock[tilenume] = 255; + allocache(&waloff[tilenume], dasiz, &walock[tilenume]); + + set_tilesiz(tilenume, xsiz, ysiz); + Bmemset(&picanm[tilenume], 0, sizeof(picanm_t)); + + return waloff[tilenume]; +} + +// +// copytilepiece +// +void copytilepiece(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz, + int32_t tilenume2, int32_t sx2, int32_t sy2) +{ + char *ptr1, *ptr2, dat; + int32_t xsiz1, ysiz1, xsiz2, ysiz2, i, j, x1, y1, x2, y2; + + xsiz1 = tilesiz[tilenume1].x; ysiz1 = tilesiz[tilenume1].y; + xsiz2 = tilesiz[tilenume2].x; ysiz2 = tilesiz[tilenume2].y; + if ((xsiz1 > 0) && (ysiz1 > 0) && (xsiz2 > 0) && (ysiz2 > 0)) + { + if (waloff[tilenume1] == 0) loadtile(tilenume1); + if (waloff[tilenume2] == 0) loadtile(tilenume2); + + x1 = sx1; + for (i=0; i= 0) && (y2 >= 0) && (x2 < xsiz2) && (y2 < ysiz2)) + { + ptr1 = (char *) (waloff[tilenume1] + x1*ysiz1 + y1); + ptr2 = (char *) (waloff[tilenume2] + x2*ysiz2 + y2); + dat = *ptr1; + if (dat != 255) + *ptr2 = *ptr1; + } + + y1++; if (y1 >= ysiz1) y1 = 0; + } + x1++; if (x1 >= xsiz1) x1 = 0; + } + } +} + +void Buninitart(void) +{ + if (artfil != -1) + kclose(artfil); + + DO_FREE_AND_NULL(pic); +} diff --git a/polymer/eduke32/eduke32.vcxproj b/polymer/eduke32/eduke32.vcxproj index 6370afa95..65760b9cd 100644 --- a/polymer/eduke32/eduke32.vcxproj +++ b/polymer/eduke32/eduke32.vcxproj @@ -296,6 +296,7 @@ + diff --git a/polymer/eduke32/eduke32.vcxproj.filters b/polymer/eduke32/eduke32.vcxproj.filters index 68f748e66..520c49165 100644 --- a/polymer/eduke32/eduke32.vcxproj.filters +++ b/polymer/eduke32/eduke32.vcxproj.filters @@ -956,6 +956,9 @@ build\source + + build\source +