Use string buffers for mobjs and states

This commit is contained in:
GenericHeroGuy 2025-05-14 15:35:26 +02:00
parent 536075b00a
commit 1793c2ea95
10 changed files with 121 additions and 163 deletions

View file

@ -83,23 +83,14 @@ static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
word += 3;
}
for (int i = 0; i < NUMMOBJFREESLOTS; i++)
for (int i = 0; i < NUMMOBJTYPES; i++)
{
if (!FREE_MOBJS[i])
if (!mobjinfo[i].nameofs)
{
break;
}
if (fastcmp(word, FREE_MOBJS[i]))
{
*type = static_cast<mobjtype_t>(static_cast<int>(MT_FIRSTFREESLOT) + i);
return true;
}
}
for (int i = 0; i < MT_FIRSTFREESLOT; i++)
{
if (fastcmp(word, MOBJTYPE_LIST[i] + 3))
if (fastcmp(word, strbuf_get(mobjnames, mobjinfo[i].nameofs)))
{
*type = static_cast<mobjtype_t>(i);
return true;
@ -234,23 +225,14 @@ static bool ACS_GetStateFromString(const char *word, statenum_t *type)
word += 2;
}
for (int i = 0; i < NUMMOBJFREESLOTS; i++)
for (int i = 0; i < NUMSTATES; i++)
{
if (!FREE_STATES[i])
if (!states[i].nameofs)
{
break;
}
if (fastcmp(word, FREE_STATES[i]))
{
*type = static_cast<statenum_t>(static_cast<int>(S_FIRSTFREESLOT) + i);
return true;
}
}
for (int i = 0; i < S_FIRSTFREESLOT; i++)
{
if (fastcmp(word, STATE_LIST[i] + 2))
if (fastcmp(word, strbuf_get(statenames, states[i].nameofs)))
{
*type = static_cast<statenum_t>(i);
return true;
@ -2336,16 +2318,9 @@ bool CallFunc_GetObjectClass(ACSVM::Thread *thread, const ACSVM::Word *argV, ACS
mobj_t *mobj = P_FindMobjFromTID(argV[0], NULL, info->mo);
if (mobj != NULL && P_MobjWasRemoved(mobj) == false)
{
if (mobj->type >= MT_FIRSTFREESLOT)
{
std::string prefix = "MT_";
std::string full = prefix + FREE_MOBJS[mobj->type - MT_FIRSTFREESLOT];
mobjClass = static_cast<INT32>( ~env->getString( full.c_str() )->idx );
}
else
{
mobjClass = static_cast<INT32>( ~env->getString( MOBJTYPE_LIST[ mobj->type ] )->idx );
}
std::string prefix = "MT_";
std::string full = prefix + (strbuf_get(mobjnames, mobjinfo[mobj->type].nameofs));
mobjClass = static_cast<INT32>( ~env->getString( full.c_str() )->idx );
}
thread->dataStk.push(mobjClass);
@ -4397,16 +4372,9 @@ bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
#define PROP_TYPE(x, y) \
case x: \
{ \
if (mobj->y >= MT_FIRSTFREESLOT) \
{ \
std::string prefix = "MT_"; \
std::string full = prefix + FREE_MOBJS[mobj->y - MT_FIRSTFREESLOT]; \
value = static_cast<INT32>( ~env->getString( full.c_str() )->idx ); \
} \
else \
{ \
value = static_cast<INT32>( ~env->getString( MOBJTYPE_LIST[ mobj->y ] )->idx ); \
} \
std::string prefix = "MT_"; \
std::string full = prefix + (strbuf_get(mobjnames, mobjinfo[mobj->y].nameofs)); \
value = static_cast<INT32>( ~env->getString( full.c_str() )->idx ); \
break; \
}
@ -4430,16 +4398,9 @@ bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
case x: \
{ \
statenum_t stateID = static_cast<statenum_t>(mobj->y - states); \
if (stateID >= S_FIRSTFREESLOT) \
{ \
std::string prefix = "S_"; \
std::string full = prefix + FREE_STATES[stateID - S_FIRSTFREESLOT]; \
value = static_cast<INT32>( ~env->getString( full.c_str() )->idx ); \
} \
else \
{ \
value = static_cast<INT32>( ~env->getString( STATE_LIST[ stateID ] )->idx ); \
} \
std::string prefix = "S_"; \
std::string full = prefix + strbuf_get(statenames, states[stateID].nameofs); \
value = static_cast<INT32>( ~env->getString( full.c_str() )->idx ); \
break; \
}

View file

@ -4872,10 +4872,10 @@ static void Command_ListDoomednums_f(void)
CONS_Printf(" doomednum \x82""%d""\x80 is \x85""double-defined\x80 by ", j+1);
if (i < MT_FIRSTFREESLOT)
{
CONS_Printf("\x87""hardcode %s <-- MAJOR ERROR\n", MOBJTYPE_LIST[i]);
CONS_Printf("\x87""hardcode MT_%s <-- MAJOR ERROR\n", strbuf_get(mobjnames, mobjinfo[i].nameofs));
continue;
}
CONS_Printf("\x81""freeslot MT_""%s\n", FREE_MOBJS[i-MT_FIRSTFREESLOT]);
CONS_Printf("\x81""freeslot MT_""%s\n", strbuf_get(mobjnames, mobjinfo[i].nameofs));
continue;
}
table[j] = i;
@ -4908,10 +4908,10 @@ static void Command_ListDoomednums_f(void)
CONS_Printf(" doomednum \x82""%d""\x80 is used by ", i+1);
if (table[i] < MT_FIRSTFREESLOT)
{
CONS_Printf("\x87""hardcode %s\n", MOBJTYPE_LIST[table[i]]);
CONS_Printf("\x87""hardcode MT_%s\n", strbuf_get(mobjnames, mobjinfo[i].nameofs));
continue;
}
CONS_Printf("\x81""freeslot MT_""%s\n", FREE_MOBJS[table[i]-MT_FIRSTFREESLOT]);
CONS_Printf("\x81""freeslot MT_""%s\n", strbuf_get(mobjnames, mobjinfo[i].nameofs));
}
}

View file

@ -81,33 +81,31 @@ static inline int lib_freeslot(lua_State *L)
else if (fastcmp(type, "S"))
{
statenum_t i;
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
for (i = S_FIRSTFREESLOT; i < NUMSTATES; i++)
if (!states[i].nameofs) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
states[i].nameofs = strbuf_append(&statenames, word);
freeslotusage[0][0]++;
lua_pushinteger(L, S_FIRSTFREESLOT + i);
lua_pushinteger(L, i);
r++;
break;
}
if (i == NUMSTATEFREESLOTS)
if (i == NUMSTATES)
CONS_Alert(CONS_WARNING, "Ran out of free State slots!\n");
}
else if (fastcmp(type, "MT"))
{
mobjtype_t i;
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
for (i = MT_FIRSTFREESLOT; i < NUMMOBJTYPES; i++)
if (!mobjinfo[i].nameofs) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
mobjinfo[i].nameofs = strbuf_append(&mobjnames, word);
freeslotusage[1][0]++;
lua_pushinteger(L, MT_FIRSTFREESLOT + i);
lua_pushinteger(L, i);
r++;
break;
}
if (i == NUMMOBJFREESLOTS)
if (i == NUMMOBJTYPES)
CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n");
}
else if (fastcmp(type, "SKINCOLOR"))
@ -426,19 +424,14 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
lua_pushinteger(L, S_FIRSTFREESLOT);
return 1;
}
for (i = 0; i < NUMSTATEFREESLOTS; i++) {
if (!FREE_STATES[i])
for (i = 0; i < NUMSTATES; i++) {
if (!states[i].nameofs)
break;
if (fastcmp(p, FREE_STATES[i])) {
CacheAndPushConstant(L, word, S_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(p, STATE_LIST[i]+2)) {
if (fastcmp(p, strbuf_get(statenames, states[i].nameofs))) {
CacheAndPushConstant(L, word, i);
return 1;
}
}
if (lua_compatmode)
for (i = 0; STATE_ALIASES[i].n; i++)
if (fastcmp(p, STATE_ALIASES[i].n)) {
@ -454,20 +447,14 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
lua_pushinteger(L, MT_FIRSTFREESLOT);
return 1;
}
for (i = 0; i < NUMMOBJFREESLOTS; i++) {
if (!FREE_MOBJS[i])
for (i = 0; i < NUMMOBJTYPES; i++) {
if (!mobjinfo[i].nameofs)
break;
if (fastcmp(p, FREE_MOBJS[i])) {
CacheAndPushConstant(L, word, MT_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(p, MOBJTYPE_LIST[i]+3)) {
if (fastcmp(p, strbuf_get(mobjnames, mobjinfo[i].nameofs))) {
CacheAndPushConstant(L, word, i);
return 1;
}
}
if (lua_compatmode)
for (i = 0; MOBJ_ALIASES[i].n; i++)
if (fastcmp(p, MOBJ_ALIASES[i].n)) {

View file

@ -444,22 +444,20 @@ void readfreeslots(MYFILE *f)
}
else if (fastcmp(type, "S"))
{
for (i = 0; i < NUMSTATEFREESLOTS; i++)
if (!FREE_STATES[i]) {
for (i = S_FIRSTFREESLOT; i < NUMSTATES; i++)
if (!states[i].nameofs) {
CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word);
states[i].nameofs = strbuf_append(&statenames, word);
freeslotusage[0][0]++;
break;
}
}
else if (fastcmp(type, "MT"))
{
for (i = 0; i < NUMMOBJFREESLOTS; i++)
if (!FREE_MOBJS[i]) {
for (i = MT_FIRSTFREESLOT; i < NUMMOBJFREESLOTS; i++)
if (!mobjinfo[i].nameofs) {
CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word);
mobjinfo[i].nameofs = strbuf_append(&mobjnames, word);
freeslotusage[1][0]++;
break;
}
@ -4266,15 +4264,12 @@ mobjtype_t get_mobjtype(const char *word)
return atoi(word);
if (fastncmp("MT_",word,3))
word += 3; // take off the MT_
for (i = 0; i < NUMMOBJFREESLOTS; i++) {
if (!FREE_MOBJS[i])
for (i = 0; i < NUMMOBJTYPES; i++) {
if (!mobjinfo[i].nameofs)
break;
if (fastcmp(word, FREE_MOBJS[i]))
return MT_FIRSTFREESLOT+i;
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(word, MOBJTYPE_LIST[i]+3))
if (fastcmp(word, strbuf_get(mobjnames, mobjinfo[i].nameofs)))
return i;
}
deh_warning("Couldn't find mobjtype named 'MT_%s'",word);
return -1;
}
@ -4286,15 +4281,12 @@ statenum_t get_state(const char *word)
return atoi(word);
if (fastncmp("S_",word,2))
word += 2; // take off the S_
for (i = 0; i < NUMSTATEFREESLOTS; i++) {
if (!FREE_STATES[i])
for (i = 0; i < NUMSTATES; i++) {
if (!states[i].nameofs)
break;
if (fastcmp(word, FREE_STATES[i]))
return S_FIRSTFREESLOT+i;
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(word, STATE_LIST[i]+2))
if (fastcmp(word, strbuf_get(statenames, states[i].nameofs)))
return i;
}
deh_warning("Couldn't find state named 'S_%s'",word);
return -1;
}

View file

@ -32,8 +32,8 @@
#include "deh_tables.h"
char *FREE_STATES[NUMSTATEFREESLOTS];
char *FREE_MOBJS[NUMMOBJFREESLOTS];
strbuf_t *statenames;
strbuf_t *mobjnames;
char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
char *FREE_MENUS[NUMMENUFREESLOTS];
UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
@ -83,12 +83,6 @@ actionpointer_t actionpointers[] =
// TODO: Make the lists public so we can start using actual mobj
// and state names in warning and error messages! :D
const char *const STATE_LIST[] = { // array length left dynamic for sanity testing later.
#define _(name, ...) "S_"#name,
#include "info/states.h"
#undef _
};
struct int_const_s const STATE_ALIASES[] = {
{"KART_STND1", S_KART_STILL},
{"KART_STND2" , S_KART_STILL},
@ -123,12 +117,6 @@ struct int_const_s const STATE_ALIASES[] = {
{ NULL, 0 }
};
const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity testing later.
#define _(name, ...) "MT_"#name,
#include "info/mobjs.h"
#undef _
};
struct int_const_s const MOBJ_ALIASES[] = {
{"BIRD", MT_FLICKY_01},
{"BUNNY" , MT_FLICKY_02},
@ -1529,16 +1517,8 @@ struct int_const_s const INT_CONST[] = {
void DEH_TableCheck(void)
{
#if defined(_DEBUG) || defined(PARANOIA)
const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*);
const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*);
const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*);
if (dehstates != S_FIRSTFREESLOT)
I_Error("You forgot to update the Dehacked states list, you dolt!\n(%d states defined, versus %s in the Dehacked list)\n", S_FIRSTFREESLOT, sizeu1(dehstates));
if (dehmobjs != MT_FIRSTFREESLOT)
I_Error("You forgot to update the Dehacked mobjtype list, you dolt!\n(%d mobj types defined, versus %s in the Dehacked list)\n", MT_FIRSTFREESLOT, sizeu1(dehmobjs));
if (dehcolors != SKINCOLOR_FIRSTFREESLOT)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", SKINCOLOR_FIRSTFREESLOT, sizeu1(dehcolors));
#endif

View file

@ -18,6 +18,7 @@
#include "info.h" // Mobj, state, sprite, etc constants
#include "m_menu.h" // NUMMENUFREESLOTS
#include "lua_script.h"
#include "strbuf.h"
#ifdef __cplusplus
extern "C" {
@ -25,15 +26,15 @@ extern "C" {
// Free slot names
// The crazy word-reading stuff uses these.
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern strbuf_t *statenames;
extern strbuf_t *mobjnames;
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
extern char *FREE_MENUS[NUMMENUFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
statenames = strbuf_alloc();\
mobjnames = strbuf_alloc();\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
@ -71,9 +72,7 @@ struct int_const_s {
extern struct flickytypes_s FLICKYTYPES[];
extern actionpointer_t actionpointers[]; // Array mapping action names to action functions.
extern const char *const STATE_LIST[];
extern struct int_const_s const STATE_ALIASES[];
extern const char *const MOBJTYPE_LIST[];
extern struct int_const_s const MOBJ_ALIASES[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2

View file

@ -176,6 +176,18 @@ static void ignorelines(MYFILE *f)
Z_Free(s);
}
static const char *hardcodemobjs =
#define _(name, ...) #name "\0"
#include "info/mobjs.h"
#undef _
;
static const char *hardcodestates =
#define _(name, ...) #name "\0"
#include "info/states.h"
#undef _
;
static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@ -185,7 +197,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
INT32 i;
if (!deh_loaded)
{
initfreeslots();
const char *name;
name = hardcodemobjs;
for (i = 0; i < MT_FIRSTFREESLOT; i++, name += strlen(name)+1)
mobjinfo[i].nameofs = strbuf_append(&mobjnames, name);
name = hardcodestates;
for (i = 0; i < S_FIRSTFREESLOT; i++, name += strlen(name)+1)
states[i].nameofs = strbuf_append(&statenames, name);
}
deh_num_warning = 0;

View file

@ -79,6 +79,8 @@ typedef enum state
struct state_t
{
UINT32 nameofs;
spritenum_t sprite;
UINT32 frame; // we use the upper 16 bits for translucency and other shade effects
INT32 tics;
@ -107,6 +109,8 @@ typedef enum mobj_type
struct mobjinfo_t
{
UINT32 nameofs;
INT32 doomednum;
statenum_t spawnstate;
INT32 spawnhealth;

View file

@ -752,8 +752,13 @@ static int lib_setState(lua_State *L)
return luaL_error(L, "Do not alter states in CMD building code!");
// clear the state to start with, in case of missing table elements
memset(state,0,sizeof(state_t));
state->sprite = SPR_NULL;
state->frame = 0;
state->tics = -1;
state->action.acp1 = NULL;
state->var1 = 0;
state->var2 = 0;
state->nextstate = S_NULL;
lua_pushnil(L);
while (lua_next(L, 1)) {
@ -975,16 +980,9 @@ static int state_get(lua_State *L)
else if (fastcmp(field,"string"))
{
statenum_t id = st-states;
if (id < S_FIRSTFREESLOT)
if (id < NUMSTATES)
{
lua_pushstring(L, STATE_LIST[id]+2);
return 1;
}
id -= S_FIRSTFREESLOT;
if (id < NUMSTATEFREESLOTS && FREE_STATES[id])
{
lua_pushstring(L, FREE_STATES[id]);
lua_pushstring(L, strbuf_get(statenames, states[id].nameofs));
return 1;
}
@ -1114,9 +1112,30 @@ static int lib_setMobjInfo(lua_State *L)
return luaL_error(L, "Do not alter mobjinfo in CMD building code!");
// clear the mobjinfo to start with, in case of missing table elements
memset(info,0,sizeof(mobjinfo_t));
info->doomednum = -1; // default to no editor value
info->spawnstate = S_NULL;
info->spawnhealth = 1; // avoid 'dead' noclip behaviors
info->seestate = S_NULL;
info->seesound = sfx_None;
info->reactiontime = 0;
info->attacksound = sfx_None;
info->painstate = S_NULL;
info->painchance = 0;
info->painsound = sfx_None;
info->meleestate = S_NULL;
info->missilestate = S_NULL;
info->deathstate = S_NULL;
info->xdeathstate = S_NULL;
info->deathsound = sfx_None;
info->speed = 0;
info->radius = 0;
info->height = 0;
info->dispoffset = 0;
info->mass = 0;
info->damage = 0;
info->activesound = sfx_None;
info->flags = 0U;
info->raisestate = S_NULL;
lua_pushnil(L);
while (lua_next(L, 1)) {
@ -1257,16 +1276,9 @@ static int mobjinfo_get(lua_State *L)
lua_pushinteger(L, info->raisestate);
else if (fastcmp(field,"string")) {
mobjtype_t id = info-mobjinfo;
if (id < MT_FIRSTFREESLOT)
if (id < NUMMOBJTYPES)
{
lua_pushstring(L, MOBJTYPE_LIST[id]+3);
return 1;
}
id -= MT_FIRSTFREESLOT;
if (id < NUMMOBJFREESLOTS && FREE_MOBJS[id])
{
lua_pushstring(L, FREE_MOBJS[id]);
lua_pushstring(L, strbuf_get(mobjnames, mobjinfo[id].nameofs));
return 1;
}

View file

@ -263,13 +263,13 @@ static const char *MobjTypeName(const mobj_t *mobj)
if (p1 == (actionf_p1)P_MobjThinker)
{
return MOBJTYPE_LIST[mobj->type];
return strbuf_get(mobjnames, mobjinfo[mobj->type].nameofs);
}
else if (p1 == (actionf_p1)P_RemoveThinkerDelayed)
{
if (mobj->thinker.debug_mobjtype != MT_NULL)
{
return MOBJTYPE_LIST[mobj->thinker.debug_mobjtype];
return strbuf_get(mobjnames, mobjinfo[mobj->thinker.debug_mobjtype].nameofs);
}
}
@ -331,7 +331,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
else if ((thinker->debug_time + delay) <= leveltime)
{
CONS_Printf(
"PARANOIA/P_RemoveThinkerDelayed: %p %s references=%d\n",
"PARANOIA/P_RemoveThinkerDelayed: %p MT_%s references=%d\n",
(void*)thinker,
MobjTypeName((mobj_t*)thinker),
thinker->references
@ -423,7 +423,7 @@ mobj_t *P_SetTarget2(mobj_t **mop, mobj_t *targ
if ((*mop)->thinker.references < 0)
{
CONS_Printf(
"PARANOIA/P_SetTarget: %p %s %s references=%d, references go negative! (%s:%d)\n",
"PARANOIA/P_SetTarget: %p MT_%s %s references=%d, references go negative! (%s:%d)\n",
(void*)*mop,
MobjTypeName(*mop),
MobjThinkerName(*mop),