diff --git a/.gitignore b/.gitignore index c4850b19..b8b3090f 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,20 @@ source/iwad/doom64.c source/iwad/ .qtc_clangd/ +GBADoom +GBADoomCpp +cppbuild +cppbuild/** + +*.gif + +**/screenbuffers/*.raw +**/screenbuffers +Release/** + +*.zip +*.bcf +*.prx* +*.as + +**/.DS_Store \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..9bda6c03 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/GBADoomCpp", + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..b9bce2b8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "makefile.makefilePath": "", + "makefile.launchConfigurations": [ + { + "cwd": "/Users/brian/src/GBADoom", + "binaryPath": "/Users/brian/src/GBADoom/GBADoom", + "binaryArgs": [] + }, + { + "cwd": "/Users/brian/src/GBADoom", + "binaryPath": "/Users/brian/src/GBADoom/GBADoomCpp", + "binaryArgs": [] + } + ], + "files.associations": { + "bitset": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "__hash_table": "cpp", + "__split_buffer": "cpp", + "__tree": "cpp", + "array": "cpp", + "deque": "cpp", + "initializer_list": "cpp", + "list": "cpp", + "queue": "cpp", + "span": "cpp", + "stack": "cpp", + "string": "cpp", + "string_view": "cpp", + "vector": "cpp" + } +} \ No newline at end of file diff --git a/GBADoom.pro b/GBADoom.pro index 1a06ec63..c2cd4945 100644 --- a/GBADoom.pro +++ b/GBADoom.pro @@ -168,7 +168,7 @@ HEADERS += \ include/tables.h \ include/v_video.h \ include/version.h \ - include/w_wad.h \ + include/wi_stuff.h \ include/z_bmalloc.h \ include/z_zone.h diff --git a/Makefile b/Makefile index d896361a..0d7b42da 100644 --- a/Makefile +++ b/Makefile @@ -1,177 +1,106 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/gba_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# INCLUDES is a list of directories containing extra header files -# DATA is a list of directories containing binary data -# GRAPHICS is a list of directories containing files to be processed by grit -# -# All directories are specified relative to the project directory where -# the makefile is found -# -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := source -INCLUDES := include -DATA := data -MUSIC := music - -#--------------------------------------------------------------------------------- -# Disable LTO for IWRAM -#--------------------------------------------------------------------------------- -%.iwram.o: %.iwram.cpp - $(SILENTMSG) $(notdir $<) - $(SILENTCMD)$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.iwram.d $(CXXFLAGS) -fno-lto -marm -c $< -o $@ $(ERROR_FILTER) - -#--------------------------------------------------------------------------------- -%.iwram.o: %.iwram.c - $(SILENTMSG) $(notdir $<) - $(SILENTCMD)$(CC) -MMD -MP -MF $(DEPSDIR)/$*.iwram.d $(CFLAGS) -fno-lto -marm -c $< -o $@ $(ERROR_FILTER) - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork - -CFLAGS := -g -Wall -O3 -fgcse-after-reload -gdwarf-4\ - -mcpu=arm7tdmi -mtune=arm7tdmi -flto=8\ - -fallow-store-data-races -fpermissive\ - -DGBA\ - $(ARCH) - -CFLAGS += $(INCLUDE) -std=gnu11 - -CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions - -ASFLAGS := -g $(ARCH) -LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -#--------------------------------------------------------------------------------- -# any extra libraries we wish to link with the project -#--------------------------------------------------------------------------------- -LIBS := -lmm -lgba - - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(LIBGBA) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- - - -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -ifneq ($(strip $(MUSIC)),) - export AUDIOFILES := $(foreach dir,$(notdir $(wildcard $(MUSIC)/*.*)),$(CURDIR)/$(MUSIC)/$(dir)) - BINFILES += soundbank.bin -endif - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) - -export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) - -export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) +# Simple Makefile for GBADoom (Qt6, macOS, Apple Silicon) -export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) +# ---- Project ----------------------------------------------------- -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) +TARGET := GBADoomCpp -.PHONY: $(BUILD) clean +SRC_DIR := cppsrc +OBJ_DIR := cppbuild -#--------------------------------------------------------------------------------- -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +# Use all C sources in source/, plus the C++ ones we know about. +# (If you add more .cpp files, just drop them in $(SRC_DIR)/) +CPP_SOURCES := $(wildcard $(SRC_DIR)/*.cc) -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba +SRCS := $(CPP_SOURCES) + +# Port specific source files +SRCS += ports/qt/i_system_e32.cc +SRCS += ports/qt/wadfilereader.cc +SRCS += ports/qt/i_main.cc + + +# ---- Original Doom Sources -------------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/w_nc.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#vpath %.cc $(SRC_DIR) ../../gamedata/original + +# ---- Guardmalloc Sources ---------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#SRCS += ../../gamedata/guard/w_nc.cc +#SRCS += guardmalloc/guardmalloc.cc +#vpath %.cc guardmalloc ../../gamedata/guard ../../gamedata/original $(SRC_DIR) + +# ---- Minimem Sources ---------------------------------------- +SRCS += gamedata/minimem/w_nc.cc +SRCS += gamedata/minimem/tagheap.cc +SRCS += gamedata/minimem/z_mem_emu.cc +SRCS += gamedata/minimem/w_lumps.cc +SRCS += gamedata/minimem/gbadoom1_lumps.cc +vpath %.cc gamedata/minimem ports/qt $(SRC_DIR) + + +# ---- Objects ----------------------------------------------------- +OBJS := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(notdir $(SRCS))) +# ---- Toolchain --------------------------------------------------- -#--------------------------------------------------------------------------------- -else +CXX := clang++ +CC := clang +AR := ar +RM := rm -f +MKDIR_P := mkdir -p -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- +# QT configuration +QT_MODULE := Qt6Widgets +QT_CFLAGS := $(shell pkg-config --cflags $(QT_MODULE)) +QT_LIBS := $(shell pkg-config --libs $(QT_MODULE)) -$(OUTPUT).gba : $(OUTPUT).elf +# ---- Flags / Defines --------------------------------------------- -$(OUTPUT).elf : $(OFILES) +DEFINES := \ + -DQT_DEPRECATED_WARNINGS \ + -DRANGECHECK \ + -DRPT_MALLOC \ + -D_CRT_SECURE_NO_WARNINGS \ -$(OFILES_SOURCES) : $(HFILES) +INCLUDEPATH := \ + -Iinclude \ + -Igamedata/minimem \ + -Iports/qt -#--------------------------------------------------------------------------------- -# The bin2o rule should be copied and modified -# for each extension used in the data directories -#--------------------------------------------------------------------------------- +CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -Wno-unknown-pragmas -Os $(DEFINES) $(INCLUDEPATH) +CFLAGS += $(QT_CFLAGS) +CXXFLAGS += $(QT_CFLAGS) -#--------------------------------------------------------------------------------- -# rule to build soundbank from music files -#--------------------------------------------------------------------------------- -soundbank.bin soundbank.h : $(AUDIOFILES) -#--------------------------------------------------------------------------------- - @mmutil $^ -osoundbank.bin -hsoundbank.h +LDFLAGS := $(QT_LIBS) -#--------------------------------------------------------------------------------- -# This rule links in binary data with the .wad extension -#--------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) +# ---- Targets ----------------------------------------------------- + +.PHONY: all clean distclean run + +all: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) + $(CXX) -o $@ $(OBJS) $(LDFLAGS) + +$(OBJ_DIR): + $(MKDIR_P) $(OBJ_DIR) + + +# C++ compilation rule - works for .cc files from any directory in vpath +$(OBJ_DIR)/%.o: %.cc + $(MKDIR_P) $(OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + $(RM) $(OBJ_DIR)/*.o +distclean: clean + $(RM) $(TARGET) --include $(DEPSDIR)/*.d -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- +run: all + ./$(TARGET) diff --git a/README.md b/README.md index 257e5d15..efeb5b42 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,19 @@ ## GBADoom +This is a modified version of the original GBADoom. It is rewritten to C++11 to +allow use of a stronger type system around caching of lumps. This in turn allows +more aggressive caching strategies where objects are loaded from flash on +demand - possibly even external flash. The goal is to have a port that is very +light on RAM requirements for platforms such as microcontrollers that have +large program memory areas (typically flash) but small RAM areas. GBADoom is +the starting point as a number of memory reducing efforts had already been done. + +The memory allocation in this build only allows for compatibilty with the Doom1 +wad, so what is stated below around compatibility is no longer true. + + +Original README below: + A port of prBoom to the GBA. **What's hot?** diff --git a/source/am_map.c b/cppsrc/am_map.cc similarity index 93% rename from source/am_map.c rename to cppsrc/am_map.cc index 1923d043..2f238406 100644 --- a/source/am_map.c +++ b/cppsrc/am_map.cc @@ -41,7 +41,7 @@ #include "r_main.h" #include "p_setup.h" #include "p_maputl.h" -#include "w_wad.h" + #include "v_video.h" #include "p_spec.h" #include "am_map.h" @@ -165,15 +165,15 @@ static void AM_findMinMaxBoundaries(void) for (i=0;i<_g->numvertexes;i++) { - if (_g->vertexes[i].x < _g->min_x) - _g->min_x = _g->vertexes[i].x; - else if (_g->vertexes[i].x > _g->max_x) - _g->max_x = _g->vertexes[i].x; - - if (_g->vertexes[i].y < _g->min_y) - _g->min_y = _g->vertexes[i].y; - else if (_g->vertexes[i].y > _g->max_y) - _g->max_y = _g->vertexes[i].y; + if (_g->vertexes[i]->x < _g->min_x) + _g->min_x = _g->vertexes[i]->x; + else if (_g->vertexes[i]->x > _g->max_x) + _g->max_x = _g->vertexes[i]->x; + + if (_g->vertexes[i]->y < _g->min_y) + _g->min_y = _g->vertexes[i]->y; + else if (_g->vertexes[i]->y > _g->max_y) + _g->max_y = _g->vertexes[i]->y; } _g->max_w = (_g->max_x >>= FRACTOMAPBITS) - (_g->min_x >>= FRACTOMAPBITS);//e6y @@ -197,7 +197,8 @@ static void AM_changeWindowLoc(void) { if ( _g->m_paninc.x || _g->m_paninc.y) { - _g->automapmode &= ~am_follow; + int newautomapmode = _g->automapmode & ~am_follow; + _g->automapmode = (automapmode_e) newautomapmode; _g->f_oldloc.x = INT_MAX; } @@ -232,7 +233,8 @@ static void AM_initVariables(void) { static const event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 }; - _g->automapmode |= am_active; + int newautomapmode = _g->automapmode | am_active; + _g->automapmode = (automapmode_e) newautomapmode; _g->f_oldloc.x = INT_MAX; @@ -278,9 +280,9 @@ static void AM_LevelInit(void) // void AM_Stop (void) { - static const event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 }; + static const event_t st_notify = { (evtype_t)0, ev_keyup, AM_MSGEXITED, 0 }; - _g->automapmode = 0; + _g->automapmode = (automapmode_e) 0; ST_Responder(&st_notify); _g->stopped = true; } @@ -390,12 +392,15 @@ boolean AM_Responder { if(_g->automapmode & am_overlay) AM_Stop (); - else - _g->automapmode |= (am_overlay | am_rotate | am_follow); + else { + int newautomapmode = _g->automapmode | (am_overlay | am_rotate | am_follow); + _g->automapmode = (automapmode_e) newautomapmode; + } } else if (ch == key_map_follow && _g->gamekeydown[key_use]) { - _g->automapmode ^= am_follow; // CPhipps - put all automap mode stuff into one enum + int newautomapmode = _g->automapmode ^ am_follow; + _g->automapmode = (automapmode_e) newautomapmode; _g->f_oldloc.x = INT_MAX; // Ty 03/27/98 - externalized _g->player.message = (_g->automapmode & am_follow) ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF; @@ -566,9 +571,9 @@ static boolean AM_clipMline(mline_t* ml, fline_t* fl) TOP =8 }; - register int outcode1 = 0; - register int outcode2 = 0; - register int outside; + int outcode1 = 0; + int outcode2 = 0; + int outside; fpoint_t tmp; int dx; @@ -768,16 +773,16 @@ static void AM_drawWalls(void) // draw the unclipped visible portions of all lines for (i=0;i<_g->numlines;i++) { - l.a.x = _g->lines[i].v1.x >> FRACTOMAPBITS;//e6y - l.a.y = _g->lines[i].v1.y >> FRACTOMAPBITS;//e6y - l.b.x = _g->lines[i].v2.x >> FRACTOMAPBITS;//e6y - l.b.y = _g->lines[i].v2.y >> FRACTOMAPBITS;//e6y + l.a.x = _g->lines[i]->v1.x >> FRACTOMAPBITS;//e6y + l.a.y = _g->lines[i]->v1.y >> FRACTOMAPBITS;//e6y + l.b.x = _g->lines[i]->v2.x >> FRACTOMAPBITS;//e6y + l.b.y = _g->lines[i]->v2.y >> FRACTOMAPBITS;//e6y - const sector_t* backsector = LN_BACKSECTOR(&_g->lines[i]); - const sector_t* frontsector = LN_FRONTSECTOR(&_g->lines[i]); + const sector_t* backsector = LN_BACKSECTOR(_g->lines[i]); + const sector_t* frontsector = LN_FRONTSECTOR(_g->lines[i]); - const unsigned int line_special = LN_SPECIAL(&_g->lines[i]); + const unsigned int line_special = LN_SPECIAL(_g->lines[i]); if (_g->automapmode & am_rotate) { @@ -788,12 +793,12 @@ static void AM_drawWalls(void) // if line has been seen or IDDT has been used if (_g->linedata[i].r_flags & ML_MAPPED) { - if (_g->lines[i].flags & ML_DONTDRAW) + if (_g->lines[i]->flags & ML_DONTDRAW) continue; { /* cph - show keyed doors and lines */ int amd; - if (!(_g->lines[i].flags & ML_SECRET) && (amd = AM_DoorColor(line_special)) != -1) + if (!(_g->lines[i]->flags & ML_SECRET) && (amd = AM_DoorColor(line_special)) != -1) { { switch (amd) /* closed keyed door */ @@ -860,21 +865,21 @@ static void AM_drawWalls(void) // jff 1/10/98 add color change for all teleporter types if ( - mapcolor_tele && !(_g->lines[i].flags & ML_SECRET) && + mapcolor_tele && !(_g->lines[i]->flags & ML_SECRET) && (line_special == 39 || line_special == 97 || line_special == 125 || line_special == 126) ) { // teleporters AM_drawMline(&l, mapcolor_tele); } - else if (_g->lines[i].flags & ML_SECRET) // secret door + else if (_g->lines[i]->flags & ML_SECRET) // secret door { AM_drawMline(&l, mapcolor_wall); // wall color } else if ( mapcolor_clsd && - !(_g->lines[i].flags & ML_SECRET) && // non-secret closed door + !(_g->lines[i]->flags & ML_SECRET) && // non-secret closed door ((backsector->floorheight==backsector->ceilingheight) || (frontsector->floorheight==frontsector->ceilingheight)) ) @@ -918,7 +923,7 @@ static void AM_drawWalls(void) } // now draw the lines only visible because the player has computermap else if (_g->player.powers[pw_allmap]) // computermap visible lines { - if (!(_g->lines[i].flags & ML_DONTDRAW)) // invisible flag lines do not show + if (!(_g->lines[i]->flags & ML_DONTDRAW)) // invisible flag lines do not show { if ( @@ -1025,7 +1030,7 @@ void AM_Drawer (void) if (!(_g->automapmode & am_active)) return; if (!(_g->automapmode & am_overlay)) // cph - If not overlay mode, clear background for the automap - V_FillRect(0, 0, f_w, f_h, (byte)mapcolor_back); //jff 1/5/98 background default color + V_FillRect(0, 0, f_w, f_h, (uint8_t)mapcolor_back); //jff 1/5/98 background default color AM_drawWalls(); AM_drawPlayers(); diff --git a/source/d_client.c b/cppsrc/d_client.cc similarity index 98% rename from source/d_client.c rename to cppsrc/d_client.cc index 650934b3..9ac0ffe5 100644 --- a/source/d_client.c +++ b/cppsrc/d_client.cc @@ -39,7 +39,8 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include +//#include +#include #ifdef HAVE_UNISTD_H #include #endif diff --git a/source/d_items.c b/cppsrc/d_items.cc similarity index 100% rename from source/d_items.c rename to cppsrc/d_items.cc diff --git a/source/d_main.c b/cppsrc/d_main.cc similarity index 93% rename from source/d_main.c rename to cppsrc/d_main.cc index 48d3085b..28ee1004 100644 --- a/source/d_main.c +++ b/cppsrc/d_main.cc @@ -37,9 +37,10 @@ -#include -#include -#include +//#include +//#include +//#include +#include #include "doomdef.h" #include "doomtype.h" @@ -48,7 +49,7 @@ #include "dstrings.h" #include "sounds.h" #include "z_zone.h" -#include "w_wad.h" + #include "s_sound.h" #include "v_video.h" #include "f_finale.h" @@ -75,6 +76,10 @@ #include "doom_iwad.h" #include "global_data.h" +#ifndef TIME_ON_TITLE_SCREEN_SEC +#define TIME_ON_TITLE_SCREEN_SEC 10 +#endif + void GetFirstMap(int *ep, int *map); // Ty 08/29/98 - add "-warp x" functionality static void D_PageDrawer(void); static void D_UpdateFPS(void); @@ -103,7 +108,7 @@ static const char* timedemo = NULL;//"demo1"; * cph - in the true spirit of the Boom source, let the * short ciruit operator madness begin! */ - +extern "C" void D_PostEvent(event_t *ev) { /* cph - suppress all input events at game start @@ -128,27 +133,36 @@ void D_PostEvent(event_t *ev) // CPhipps - moved the screen wipe code from D_Display to here // The screens to wipe between are already stored, this just does the timing // and screen updating - +#define VISIBLE_WIPE 0 // SAVE CPU - something is broken with visible wipes static void D_Wipe(void) { boolean done; + #if VISIBLE_WIPE==1 int wipestart = I_GetTime () - 1; + #endif wipe_initMelt(); do { + #if VISIBLE_WIPE==1 int nowtime, tics; do { nowtime = I_GetTime(); tics = nowtime - wipestart; } while (!tics); - wipestart = nowtime; + #else + int tics = 1; + #endif done = wipe_ScreenWipe(tics); - I_UpdateNoBlit(); + #if VISIBLE_WIPE==1 + I_FinishUpdate(); + #else + I_UpdateNoBlit(); // TODO: Why no blit? + #endif M_Drawer(); // menu is drawn even on top of wipes } while (!done); @@ -361,13 +375,14 @@ void D_AdvanceDemo (void) static void D_SetPageName(const char *name) { - _g->pagelump = W_GetNumForName(name); + _g->pagelump = NC_GetNumForName(name); } static void D_DrawTitle1(const char *name) { S_StartMusic(mus_intro); - _g->pagetic = (TICRATE*30); + // NOTE: Time to display the title screen + _g->pagetic = (TICRATE*TIME_ON_TITLE_SCREEN_SEC); D_SetPageName(name); } @@ -484,7 +499,8 @@ void D_StartTitle (void) // the gamemode from it. Also note if DOOM II, whether secret levels exist // CPhipps - const char* for iwadname, made static -static void CheckIWAD2(const unsigned char* iwad_data, const unsigned int iwad_len, GameMode_t *gmode,boolean *hassec) +/* BDP: Hardcoded values below, so this is unused +static void CheckIWAD2(const unsigned char* iwad_data, const unsigned int iwad_len UNUSED, GameMode_t *gmode,boolean *hassec) { const wadinfo_t* header = (const wadinfo_t*)iwad_data; @@ -560,6 +576,8 @@ static void CheckIWAD2(const unsigned char* iwad_data, const unsigned int iwad_l *gmode = shareware; } +*/ + // // IdentifyVersion // @@ -584,8 +602,10 @@ static void CheckIWAD2(const unsigned char* iwad_data, const unsigned int iwad_l static void IdentifyVersion() { - CheckIWAD2(doom_iwad, doom_iwad_len, &_g->gamemode, &_g->haswolflevels); - + //CheckIWAD2(doom_iwad, doom_iwad_len, &_g->gamemode, &_g->haswolflevels); + // BDP: Hardcoded values corresponding to gbadoom1.wad + _g->gamemode = shareware; + _g->haswolflevels = false; /* jff 8/23/98 set gamemission global appropriately in all cases * cphipps 12/1999 - no version output here, leave that to the caller */ @@ -620,6 +640,7 @@ static void IdentifyVersion() static void D_DoomMainSetup(void) { + IdentifyVersion(); // jff 1/24/98 end of set to both working and command line value @@ -687,8 +708,7 @@ static void D_DoomMainSetup(void) D_InitNetGame(); //jff 9/3/98 use logical output routine - lprintf(LO_INFO,"W_Init: Init WADfiles."); - W_Init(); // CPhipps - handling of wadfiles init changed + lprintf(LO_INFO,"NC_Init: Init WADfiles."); //jff 9/3/98 use logical output routine lprintf(LO_INFO,"M_Init: Init misc info."); @@ -744,6 +764,8 @@ static void D_DoomMainSetup(void) void D_DoomMain(void) { + NC_Init(); + D_DoomMainSetup(); // CPhipps - setup out of main execution stack D_DoomLoop (); // never returns @@ -773,29 +795,29 @@ void GetFirstMap(int *ep, int *map) { for (i=1;!done && i<33;i++) // Ty 09/13/98 - add use of !done { - sprintf(test,"MAP%02d",i); - ix = W_CheckNumForName(test); + snprintf(test,sizeof(test),"MAP%02d",i); + ix = NC_CheckNumForName(test); if (ix != -1) // Ty 10/04/98 avoid -1 subscript { if (!*name) // found one, not pwad. First default. - strcpy(name,test); + strncpy(name,test,sizeof(name)-1); } } } else // one of the others { - strcpy(name,"E1M1"); // Ty 10/04/98 - default for display + strncpy(name,"E1M1",sizeof(name)-1); // Ty 10/04/98 - default for display for (i=1;!done && i<5;i++) // Ty 09/13/98 - add use of !done { for (j=1;!done && j<10;j++) // Ty 09/13/98 - add use of !done { - sprintf(test,"E%dM%d",i,j); - ix = W_CheckNumForName(test); + snprintf(test,sizeof(test),"E%dM%d",i,j); + ix = NC_CheckNumForName(test); if (ix != -1) // Ty 10/04/98 avoid -1 subscript { if (!*name) // found one, not pwad. First default. - strcpy(name,test); + strncpy(name,test,sizeof(name)-1); } } } diff --git a/source/f_finale.c b/cppsrc/f_finale.cc similarity index 94% rename from source/f_finale.c rename to cppsrc/f_finale.cc index de7bce7e..5ac58b8f 100644 --- a/source/f_finale.c +++ b/cppsrc/f_finale.cc @@ -35,7 +35,7 @@ #include "doomstat.h" #include "d_event.h" #include "v_video.h" -#include "w_wad.h" + #include "s_sound.h" #include "sounds.h" #include "f_finale.h" // CPhipps - hmm... @@ -71,7 +71,8 @@ void F_StartFinale (void) { _g->gameaction = ga_nothing; _g->gamestate = GS_FINALE; - _g->automapmode &= ~am_active; + int newautomapmode = _g->automapmode & ~am_active; + _g->automapmode = (automapmode_e) newautomapmode; // killough 3/28/98: clear accelerative text flags _g->acceleratestage = _g->midstage = 0; @@ -184,13 +185,19 @@ boolean F_Responder (event_t *event) // Get_TextSpeed() returns the value of the text display speed // phares // Rewritten to allow user-directed acceleration -- killough 3/28/98 -static float Get_TextSpeed(void) +static float Get_InverseTextSpeed(void) { - return _g->midstage ? NEWTEXTSPEED : (_g->midstage=_g->acceleratestage) ? - _g->acceleratestage=0, NEWTEXTSPEED : TEXTSPEED; + return _g->midstage ? (1.0f/NEWTEXTSPEED) : (_g->midstage=_g->acceleratestage) ? + _g->acceleratestage=0, (1.0f/NEWTEXTSPEED) : (1.0f/TEXTSPEED); } +static float Get_TextSpeed(void) +{ + return _g->midstage ? (NEWTEXTSPEED) : (_g->midstage=_g->acceleratestage) ? + _g->acceleratestage=0, (NEWTEXTSPEED) : (TEXTSPEED); + } + // // F_Ticker // @@ -227,7 +234,7 @@ static float Get_TextSpeed(void) { // with enough time, it's automatic _g->finalecount = 0; _g->finalestage = 1; - _g->wipegamestate = -1; // force a wipe + _g->wipegamestate = (gamestate_t)-1; // force a wipe if (_g->gameepisode == 3) S_StartMusic(mus_bunny); } @@ -264,7 +271,7 @@ static void F_TextWrite (void) int cx = 10; int cy = 10; const char* ch = _g->finaletext; // CPhipps - const - int count = (int)((float)(_g->finalecount - 10)/Get_TextSpeed()); // phares + int count = (int)((float)(_g->finalecount - 10)*Get_InverseTextSpeed()); // phares int w; if (count < 0) @@ -291,7 +298,8 @@ static void F_TextWrite (void) w = _g->hu_font[c]->width; // CPhipps - patch drawing updated - V_DrawPatchNoScale(cx, cy, _g->hu_font[c]); + auto pinned_patch = _g->hu_font[c].pin(); + V_DrawPatchNoScale(cx, cy, pinned_patch); cx+=w; } } @@ -328,7 +336,7 @@ static const castinfo_t castorder[] = { CC_SPIDER, MT_SPIDER }, { CC_CYBER, MT_CYBORG }, { CC_HERO, MT_PLAYER }, - { NULL, 0} + { NULL, (mobjtype_t)0} }; @@ -338,7 +346,7 @@ static const castinfo_t castorder[] = void F_StartCast (void) { - _g->wipegamestate = -1; // force a screen wipe + _g->wipegamestate = (gamestate_t)-1; // force a screen wipe _g->castnum = 0; _g->caststate = &states[mobjinfo[castorder[_g->castnum].type].seestate]; _g->casttics = _g->caststate->tics; @@ -527,7 +535,8 @@ static void F_CastPrint (const char* text) // CPhipps - static, const char* w = _g->hu_font[c]->width; // CPhipps - patch drawing updated - V_DrawPatchNoScale(cx, 144, _g->hu_font[c]); + auto pinned_patch = _g->hu_font[c].pin(); + V_DrawPatchNoScale(cx, 144, pinned_patch); cx+=w; } } @@ -559,7 +568,7 @@ void F_CastDrawer (void) // CPhipps - patch drawing updated V_DrawNumPatch(160, 170, 0, lump+_g->firstspritelump, CR_DEFAULT, - VPT_STRETCH | (flip ? VPT_FLIP : 0)); + (patch_translation_e)(VPT_STRETCH | (flip ? VPT_FLIP : 0))); } // @@ -609,7 +618,7 @@ static void F_BunnyScroll (void) _g->laststage = stage; } - sprintf (name,"END%i",stage); + snprintf (name,sizeof(name),"END%i",stage); // CPhipps - patch drawing updated V_DrawNamePatch((320-13*8)/2, (200-8*8)/2, 0, name, CR_DEFAULT, VPT_STRETCH); } diff --git a/source/f_wipe.c b/cppsrc/f_wipe.cc similarity index 53% rename from source/f_wipe.c rename to cppsrc/f_wipe.cc index a875c1fa..07a5f295 100644 --- a/source/f_wipe.c +++ b/cppsrc/f_wipe.cc @@ -71,69 +71,12 @@ int wipe_EndScreen(void) // oh man, why aren't you commenting anything ? // 2021-08-08 next-hack: commented and modified to use the dual buffer. -static int wipe_doMelt(int ticks) +static int wipe_doMelt(int ticks UNUSED) { - boolean done = true; + // wipe logic was broken anyway, so make this a nop + return 1; - unsigned short* backbuffer = I_GetBackBuffer(); - unsigned short* frontbuffer = I_GetFrontBuffer(); - while (ticks--) - { - for (int i = 0; i < SCREENWIDTH; i++) - { - if (wipe_y_lookup[i] < 0) - { - wipe_y_lookup[i]++; - done = false; - continue; - } - - // scroll down columns, which are still visible - if (wipe_y_lookup[i] < SCREENHEIGHT) - { - /* cph 2001/07/29 - - * The original melt rate was 8 pixels/sec, i.e. 25 frames to melt - * the whole screen, so make the melt rate depend on SCREENHEIGHT - * so it takes no longer in high res - */ - int dy = (wipe_y_lookup[i] < 16) ? wipe_y_lookup[i] + 1 : SCREENHEIGHT / 25; - // At most dy shall be so that the column is shifted by SCREENHEIGHT (i.e. just - // invisible) - if (wipe_y_lookup[i] + dy >= SCREENHEIGHT) - dy = SCREENHEIGHT - wipe_y_lookup[i]; - - unsigned short* s = &frontbuffer[i] + ((SCREENHEIGHT - dy - 1) * SCREENPITCH); - - unsigned short* d = &frontbuffer[i] + ((SCREENHEIGHT - 1) * SCREENPITCH); - - // scroll down the column. Of course we need to copy from the bottom... up to - // SCREENHEIGHT - yLookup - dy - - for (int j = SCREENHEIGHT - wipe_y_lookup[i] - dy; j; j--) - { - *d = *s; - d += -SCREENPITCH; - s += -SCREENPITCH; - } - - // copy new screen. We need to copy only between y_lookup and + dy y_lookup - s = &backbuffer[i] + wipe_y_lookup[i] * SCREENPITCH; - d = &frontbuffer[i] + wipe_y_lookup[i] * SCREENPITCH; - - for (int j = 0 ; j < dy; j++) - { - *d = *s; - d += SCREENPITCH; - s += SCREENPITCH; - } - - wipe_y_lookup[i] += dy; - done = false; - } - } - } - return done; } void wipe_initMelt() diff --git a/source/g_game.c b/cppsrc/g_game.cc similarity index 89% rename from source/g_game.c rename to cppsrc/g_game.cc index 2275c69e..beaf28f6 100644 --- a/source/g_game.c +++ b/cppsrc/g_game.cc @@ -57,7 +57,7 @@ #include "hu_stuff.h" #include "st_stuff.h" #include "am_map.h" -#include "w_wad.h" + #include "r_main.h" #include "r_draw.h" #include "p_map.h" @@ -73,8 +73,8 @@ #include "i_system.h" #include "global_data.h" - #include "gba_functions.h" +#include "z_zone.h" // // controls (have defaults) @@ -116,7 +116,7 @@ static const fixed_t sidemove[2] = {0x18, 0x28}; static const fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn static void G_DoSaveGame (boolean menu); -static const byte* G_ReadDemoHeader(const byte* demo_p, size_t size, boolean failonerror); +static CachedBuffer G_ReadDemoHeader(CachedBuffer demo_p, size_t size, boolean failonerror); typedef struct gba_save_data_t @@ -362,7 +362,7 @@ static void G_DoLoadLevel (void) /* cph 2006/07/31 - took out unused levelstarttic variable */ if (_g->wipegamestate == GS_LEVEL) - _g->wipegamestate = -1; // force a wipe + _g->wipegamestate = (gamestate_t)-1; // force a wipe _g->gamestate = GS_LEVEL; @@ -558,6 +558,9 @@ void G_Ticker (void) case GS_DEMOSCREEN: D_PageTicker (); break; + + default: + break; } } @@ -571,7 +574,7 @@ void G_Ticker (void) // Can when a player completes a level. // -static void G_PlayerFinishLevel(int player) +static void G_PlayerFinishLevel(int player UNUSED) { player_t *p = &_g->player; memset(p->powers, 0, sizeof p->powers); @@ -589,7 +592,7 @@ static void G_PlayerFinishLevel(int player) // almost everything is cleared and initialized // -void G_PlayerReborn (int player) +void G_PlayerReborn (int player UNUSED) { player_t *p; int i; @@ -627,7 +630,7 @@ void G_PlayerReborn (int player) // G_DoReborn // -void G_DoReborn (int playernum) +void G_DoReborn (int playernum UNUSED) { _g->gameaction = ga_loadlevel; // reload the level from scratch } @@ -763,7 +766,8 @@ void G_DoCompleted (void) _g->wminfo.totaltimes = (_g->totalleveltimes += (_g->leveltime - _g->leveltime%35)); _g->gamestate = GS_INTERMISSION; - _g->automapmode &= ~am_active; + int newautomatapmode = _g->automapmode & ~am_active; + _g->automapmode = (automapmode_e)newautomatapmode; // lmpwatch.pl engine-side demo testing support // print "FINISHED: " when the player exits the current map @@ -814,7 +818,12 @@ void G_DoWorldDone (void) _g->idmusnum = -1; //jff 3/17/98 allow new level's music to be loaded _g->gamestate = GS_LEVEL; _g->gamemap = _g->wminfo.next+1; + #ifdef RPT_MALLOC + Z_ReportAll(); + #endif + G_DoLoadLevel(); + _g->gameaction = ga_nothing; } @@ -836,6 +845,55 @@ void G_ForcedLoadGame(void) _g->gameaction = ga_loadgame; } +#ifndef _MSC_VER +// Supports base 2 to 36 +char* itoa(int value, char* buffer, int base) { + if (base < 2 || base > 36) { + buffer[0] = '\0'; // invalid base + return buffer; + } + + int i = 0; + int isNegative = 0; + + if (value == 0) { + buffer[i++] = '0'; + buffer[i] = '\0'; + return buffer; + } + + if (value < 0 && base == 10) { + isNegative = 1; + value = -value; + } + + while (value != 0) { + int rem = value % base; + buffer[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0'; + value = value / base; + } + + if (isNegative) { + buffer[i++] = '-'; + } + + buffer[i] = '\0'; + + // Inline reverse + int start = 0; + int end = i - 1; + while (start < end) { + char temp = buffer[start]; + buffer[start] = buffer[end]; + buffer[end] = temp; + start++; + end--; + } + + return buffer; +} +#endif + // // Update the strings displayed in the load-save menu. @@ -845,7 +903,7 @@ void G_UpdateSaveGameStrings() unsigned int savebuffersize = sizeof(gba_save_data_t) * 8; - byte* loadbuffer = Z_Malloc(savebuffersize, PU_STATIC, NULL); + uint8_t* loadbuffer = (uint8_t *)Z_Malloc(savebuffersize, PU_STATIC, NULL); LoadSRAM(loadbuffer, savebuffersize, 0); @@ -880,7 +938,7 @@ void G_UpdateSaveGameStrings() // killough 3/16/98: add slot info // killough 5/15/98: add command-line -void G_LoadGame(int slot, boolean command) +void G_LoadGame(int slot, boolean command UNUSED) { _g->savegameslot = slot; _g->demoplayback = false; @@ -893,7 +951,7 @@ void G_DoLoadGame() unsigned int savebuffersize = sizeof(gba_save_data_t) * 8; - byte* loadbuffer = Z_Malloc(savebuffersize, PU_STATIC, NULL); + uint8_t* loadbuffer = (uint8_t *)Z_Malloc(savebuffersize, PU_STATIC, NULL); LoadSRAM(loadbuffer, savebuffersize, 0); @@ -928,20 +986,20 @@ void G_DoLoadGame() // // G_SaveGame // Called by the menu task. -// Description is a 24 byte text string +// Description is a 24 uint8_t text string // -void G_SaveGame(int slot, const char *description) +void G_SaveGame(int slot, const char *description UNUSED) { _g->savegameslot = slot; G_DoSaveGame(true); } -static void G_DoSaveGame(boolean menu) +static void G_DoSaveGame(boolean menu UNUSED) { unsigned int savebuffersize = sizeof(gba_save_data_t) * 8; - byte* savebuffer = Z_Malloc(savebuffersize, PU_STATIC, NULL); + uint8_t* savebuffer = (uint8_t *)Z_Malloc(savebuffersize, PU_STATIC, NULL); LoadSRAM(savebuffer, savebuffersize, 0); @@ -985,14 +1043,14 @@ void G_SaveSettings() settings.musicVolume = _g->snd_MusicVolume; settings.soundVolume = _g->snd_SfxVolume; - SaveSRAM((byte*)&settings, sizeof(settings), settings_sram_offset); + SaveSRAM((uint8_t*)&settings, sizeof(settings), settings_sram_offset); } void G_LoadSettings() { gba_save_settings_t settings; - LoadSRAM((byte*)&settings, sizeof(settings), settings_sram_offset); + LoadSRAM((uint8_t*)&settings, sizeof(settings), settings_sram_offset); if(settings.cookie == settings_cookie) { @@ -1084,7 +1142,8 @@ void G_InitNew(skill_t skill, int episode, int map) _g->player.playerstate = PST_REBORN; _g->usergame = true; // will be set false if a demo - _g->automapmode &= ~am_active; + int newautomatapmode = _g->automapmode & ~am_active; + _g->automapmode = (automapmode_e)newautomatapmode; _g->gameepisode = episode; _g->gamemap = map; _g->gameskill = skill; @@ -1106,7 +1165,7 @@ void G_ReadDemoTiccmd (ticcmd_t* cmd) if (*_g->demo_p == DEMOMARKER) G_CheckDemoStatus(); // end of demo data stream - else if (_g->demoplayback && _g->demo_p + (_g->longtics?5:4) > _g->demobuffer + _g->demolength) + else if (_g->demoplayback && _g->demo_p.addOffset(_g->longtics?5:4).byteoffset() > _g->demobuffer.addOffset(_g->demolength).byteoffset()) { lprintf(LO_WARN, "G_ReadDemoTiccmd: missing DEMOMARKER\n"); G_CheckDemoStatus(); @@ -1127,12 +1186,12 @@ void G_ReadDemoTiccmd (ticcmd_t* cmd) /* Same, but read instead of write - * cph - const byte*'s + * cph - const uint8_t*'s */ -const byte *G_ReadOptions(const byte *demo_p) +CachedBuffer G_ReadOptions(CachedBuffer demo_p) { - const byte *target = demo_p + GAME_OPTION_SIZE; + auto target = demo_p.addOffset(GAME_OPTION_SIZE); return target; } @@ -1152,9 +1211,9 @@ void G_DeferedPlayDemo (const char* name) static int demolumpnum = -1; //e6y: Check for overrun -static boolean CheckForOverrun(const byte *start_p, const byte *current_p, size_t maxsize, size_t size, boolean failonerror) +static boolean CheckForOverrun(CachedBuffer start_p, CachedBuffer current_p, size_t maxsize, size_t size, boolean failonerror) { - size_t pos = current_p - start_p; + size_t pos = current_p.byteoffset() - start_p.byteoffset(); if (pos + size > maxsize) { if (failonerror) @@ -1165,7 +1224,7 @@ static boolean CheckForOverrun(const byte *start_p, const byte *current_p, size_ return false; } -static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean failonerror) +CachedBuffer G_ReadDemoHeader(CachedBuffer demo_p, size_t size, boolean failonerror) { skill_t skill; int episode, map; @@ -1173,7 +1232,7 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai // e6y // The local variable should be used instead of demobuffer, // because demobuffer can be uninitialized - const byte *header_p = demo_p; + auto header_p = demo_p; _g->basetic = _g->gametic; // killough 9/29/98 @@ -1183,15 +1242,15 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 1, failonerror)) - return NULL; + return CachedBuffer(); _g->demover = *demo_p++; _g->longtics = 0; // e6y // Handling of unrecognized demo formats - // Versions up to 1.2 use a 7-byte header - first byte is a skill level. - // Versions after 1.2 use a 13-byte header - first byte is a demoversion. + // Versions up to 1.2 use a 7-uint8_t header - first uint8_t is a skill level. + // Versions after 1.2 use a 13-uint8_t header - first uint8_t is a demoversion. // BOOM's demoversion starts from 200 if (!((_g->demover >= 0 && _g->demover <= 4) || (_g->demover >= 104 && _g->demover <= 111) || @@ -1209,13 +1268,13 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai // killough 3/6/98: rearrange to fix savegame bugs (moved fastparm, // respawnparm, nomonsters flags to G_LoadOptions()/G_SaveOptions()) - if ((skill=_g->demover) >= 100) // For demos from versions >= 1.4 + if ((int)(skill=(skill_t)_g->demover) >= 100) // For demos from versions >= 1.4 { //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 8, failonerror)) - return NULL; + return CachedBuffer(); - skill = *demo_p++; + skill = (skill_t)*demo_p++; episode = *demo_p++; map = *demo_p++; demo_p++; @@ -1228,7 +1287,7 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai { //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 2, failonerror)) - return NULL; + return CachedBuffer(); episode = *demo_p++; map = *demo_p++; @@ -1243,26 +1302,29 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai case 201: //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 1, failonerror)) - return NULL; + return CachedBuffer(); break; case 202: //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 1, failonerror)) - return NULL; + return CachedBuffer(); break; case 203: /* LxDoom or MBF - determine from signature * cph - load compatibility level */ - switch (*(header_p + 2)) { - case 'B': /* LxDoom */ - /* cph - DEMOSYNC - LxDoom demos recorded in compatibility modes support dropped */ - break; - case 'M': - demo_p++; + { + auto header_p2 = header_p.addOffset(2); + switch (*(header_p2)) { + case 'B': /* LxDoom */ + /* cph - DEMOSYNC - LxDoom demos recorded in compatibility modes support dropped */ + break; + case 'M': + demo_p++; + break; + } break; } - break; case 210: demo_p++; break; @@ -1282,9 +1344,9 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai } //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, 5, failonerror)) - return NULL; + return CachedBuffer(); - skill = *demo_p++; + skill = (skill_t)*demo_p++; episode = *demo_p++; map = *demo_p++; demo_p++; @@ -1292,7 +1354,7 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, GAME_OPTION_SIZE, failonerror)) - return NULL; + return CachedBuffer(); demo_p = G_ReadOptions(demo_p); // killough 3/1/98: Read game options @@ -1302,7 +1364,7 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai //e6y: check for overrun if (CheckForOverrun(header_p, demo_p, size, MAXPLAYERS, failonerror)) - return NULL; + return CachedBuffer(); _g->playeringame = *demo_p++; demo_p += MIN_MAXPLAYERS - MAXPLAYERS; @@ -1321,14 +1383,13 @@ void G_DoPlayDemo(void) { char basename[9]; - ExtractFileBase(defdemoname,basename); // killough + NC_ExtractFileBase(defdemoname,basename); // killough basename[8] = 0; /* cph - store lump number for unlocking later */ - demolumpnum = W_GetNumForName(basename); - _g->demobuffer = W_CacheLumpNum(demolumpnum); - _g->demolength = W_LumpLength(demolumpnum); - + demolumpnum = NC_GetNumForName(basename); + _g->demobuffer = CachedBuffer(demolumpnum); + _g->demolength = _g->demobuffer.size(); _g->demo_p = G_ReadDemoHeader(_g->demobuffer, _g->demolength, true); _g->gameaction = ga_nothing; @@ -1348,12 +1409,14 @@ boolean G_CheckDemoStatus (void) { if (_g->timingdemo) { - int endtime = I_GetTime(); // killough -- added fps information and made it work for longer demos: + #ifdef GBA + int endtime = I_GetTime(); unsigned realtics = endtime-_g->starttime; I_Error ("Timed %u gametics in %u realtics = %-.1f frames per second", (unsigned) _g->gametic,realtics, (unsigned) _g->gametic * (double) TICRATE / realtics); + #endif } if (_g->demoplayback) diff --git a/source/gfx/stbar.h b/cppsrc/gfx/stbar.h similarity index 98% rename from source/gfx/stbar.h rename to cppsrc/gfx/stbar.h index c30b08b0..e4b02aab 100644 --- a/source/gfx/stbar.h +++ b/cppsrc/gfx/stbar.h @@ -2,7 +2,7 @@ //const unsigned char gfx_stbar[6000] = //GBA Doom II's hud is 7680 bytes now. -const unsigned char gfx_stbar[7680] = +unsigned char gfx_stbar[7680] = { /*93, 97,99,97,98,99,100,100,100,101,99,99,97,100,100,100,101, @@ -380,6 +380,6 @@ const unsigned char gfx_stbar[7680] = 5,109,109,109,107,107,107,108,109,109,109,111,109,109,111,109, 109,5,109,109,109,109,5,109,111,5,5,5,5,5,5,5, 5,110,109,5,6,5,111,110,109,107,107,109,110,110,109,*/ -//GBA Doom II's HUD Background, funnily enough this is the same data byte for byte used as a .D2I file back when I made the GBA Doom II Modding tools, just as a table. ~Kippykip +//GBA Doom II's HUD Background, funnily enough this is the same data uint8_t for uint8_t used as a .D2I file back when I made the GBA Doom II Modding tools, just as a table. ~Kippykip 93,98,98,98,98,100,100,100,100,100,100,100,98,100,100,100,100,100,96,96,98,98,98,98,100,98,98,96,96,96,96,96,98,103,3,96,100,100,100,98,98,98,98,101,98,98,98,101,98,98,98,101,98,98,98,101,101,98,98,101,98,98,98,98,98,101,101,98,98,98,101,100,100,98,96,96,98,3,93,93,96,98,96,96,98,98,98,98,100,98,98,96,96,96,96,96,98,98,98,98,100,100,100,100,98,98,98,93,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,93,89,89,93,96,98,96,96,98,98,98,98,100,98,98,96,96,96,96,96,98,98,98,98,100,100,100,100,98,98,98,98,101,98,98,98,101,98,98,98,98,101,98,98,98,102,105,102,101,102,101,101,100,105,3,96,98,98,100,100,100,100,98,96,98,96,96,98,98,98,98,100,100,100,100,100,101,98,100,98,100,100,100,98,100,100,100,98,100,100,100,103,3,102,101,101,98,101,101,101,101,98,98,98,98,98,98,101,96,100,103,103,103,3,105,3,105,3,105,3,103,103,3,105,3,3,100,100,103,3,103,103,103,103,100,100,100,100,100,100,103,107,107,100,105,3,103,102,102,102,102,102,102,102,3,3,3,102,102,3,101,102,3,3,3,102,3,3,3,3,101,102,107,107,3,3,3,3,3,105,103,100,100,100,100,105,98,102,100,100,100,100,103,3,103,103,103,3,100,100,100,100,100,100,103,103,103,3,3,105,3,103,102,102,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,98,100,100,100,100,103,3,103,103,103,3,100,100,100,100,100,100,103,103,103,3,3,105,3,103,102,102,102,102,102,102,102,3,3,3,102,102,102,3,101,3,102,109,105,102,105,105,105,102,103,3,107,100,3,3,105,105,105,100,100,100,100,100,100,103,103,103,3,3,105,3,105,3,102,102,3,3,103,3,3,103,108,105,3,103,105,108,3,105,108,109,107,102,102,105,105,105,102,102,101,102,3,102,102,3,96,100,100,100,103,3,3,3,3,3,3,103,103,103,3,3,103,3,101,100,100,3,103,103,103,103,103,103,100,98,101,100,100,108,3,98,3,3,3,101,3,103,103,103,103,103,102,3,3,103,102,3,3,3,3,3,3,3,3,3,102,102,101,101,3,3,3,3,3,3,101,3,3,103,103,101,100,107,98,100,96,101,100,100,98,96,100,3,98,98,101,98,98,98,100,3,98,98,100,100,98,96,100,110,101,3,3,108,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,98,98,101,98,100,100,3,103,103,103,103,103,103,100,98,101,100,100,100,103,103,3,3,3,3,101,3,103,103,103,103,103,102,3,3,103,103,102,3,3,105,103,109,98,101,101,101,98,98,96,103,3,101,105,105,102,103,3,103,103,100,98,101,100,100,100,103,103,3,3,3,3,105,3,102,3,103,103,3,3,3,103,105,3,103,3,108,109,108,109,108,102,103,103,102,105,102,3,102,103,102,3,3,103,102,95,101,100,103,103,3,3,3,3,103,3,3,100,103,103,3,103,3,103,101,100,103,103,103,3,3,103,103,101,100,100,100,101,108,3,100,3,3,3,3,103,102,102,102,102,3,3,3,3,102,102,3,3,102,3,3,3,3,107,3,102,103,103,102,3,107,107,102,3,3,3,103,100,103,103,100,101,107,100,105,98,3,108,3,103,100,3,107,101,3,107,3,102,101,3,108,100,3,108,3,103,100,105,109,3,103,103,107,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,100,100,98,103,103,100,103,103,103,103,3,103,103,101,100,100,100,101,100,103,103,3,107,3,3,3,103,102,102,102,102,3,3,3,3,102,102,102,3,3,3,102,108,101,105,107,102,102,102,102,107,108,100,3,3,3,3,100,103,103,103,100,98,101,100,101,100,98,103,103,103,3,3,3,3,107,103,103,103,3,103,3,3,103,3,105,3,110,109,110,105,108,105,102,102,105,102,3,3,102,3,3,3,102,3,96,100,101,103,3,103,3,3,3,3,3,3,103,103,3,3,103,3,100,98,100,105,3,103,103,103,3,103,100,101,100,101,100,107,3,98,3,3,3,3,102,3,103,103,103,3,3,3,3,102,103,102,3,3,3,3,3,3,3,101,101,102,102,101,3,107,110,3,3,3,3,3,105,3,103,100,100,108,100,103,98,3,96,96,96,105,105,108,101,3,96,96,96,105,3,107,100,105,96,105,96,105,105,110,3,102,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,100,98,96,100,100,101,3,3,103,103,103,3,103,100,101,100,101,100,101,3,103,3,3,3,3,3,102,3,103,103,103,3,3,3,3,102,103,103,102,3,105,3,109,101,105,105,101,102,103,100,108,3,101,105,105,105,3,105,3,3,103,100,100,100,100,98,100,98,103,3,103,103,3,3,102,105,3,103,3,3,3,103,105,3,105,3,108,3,105,3,105,105,105,103,103,105,105,3,102,101,103,102,3,101,3,96,100,100,103,3,103,3,3,3,3,3,3,3,103,3,3,3,3,103,103,103,103,3,103,3,3,103,103,100,100,100,98,100,107,105,98,3,3,3,3,101,102,3,101,3,3,102,3,3,102,103,3,102,101,3,107,107,101,98,3,102,101,101,101,3,3,3,3,102,3,3,105,103,103,103,100,101,3,98,103,98,3,105,47,96,47,3,110,101,3,105,47,96,47,3,108,100,105,96,47,96,47,3,109,3,101,102,110,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,98,96,103,103,103,103,103,103,3,3,103,103,100,100,100,98,100,100,3,103,3,3,105,103,3,101,102,3,101,3,3,102,102,3,102,101,102,3,102,105,101,109,101,105,105,101,102,103,101,107,3,98,105,96,96,96,110,3,96,110,101,96,110,96,110,100,100,96,110,103,103,3,3,103,3,3,103,103,3,3,3,3,105,3,105,109,105,3,96,5,105,105,105,105,105,105,3,103,3,3,102,102,101,3,96,100,103,100,3,103,3,3,3,108,3,3,3,3,3,3,103,3,100,103,103,103,103,3,3,3,103,3,100,103,103,103,103,107,3,98,3,3,103,102,102,103,102,101,3,3,3,3,102,103,102,3,3,102,3,3,3,3,107,3,103,103,101,101,3,3,101,47,47,3,3,3,100,100,47,109,100,107,98,103,98,3,105,96,105,47,3,107,102,3,105,96,96,47,3,108,100,3,96,96,96,47,105,110,102,102,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,98,98,96,100,100,103,103,103,103,103,3,103,100,100,101,100,101,100,103,100,103,103,3,3,3,103,102,102,103,102,101,3,47,47,3,102,103,102,3,47,109,102,109,102,101,101,102,101,101,100,107,3,98,105,92,109,3,93,110,93,110,100,93,110,93,110,103,103,93,110,3,103,3,3,3,3,3,103,3,3,3,3,3,103,3,159,110,3,93,5,105,105,105,102,105,105,105,3,3,102,102,101,3,101,3,98,103,103,103,103,3,3,3,3,3,107,103,103,3,3,3,3,3,103,107,3,100,103,3,3,3,3,3,103,107,3,100,103,3,3,98,3,3,3,102,103,101,101,101,3,3,102,3,102,103,102,3,3,103,102,3,3,107,3,3,102,102,101,102,3,3,47,183,185,47,102,103,100,47,47,109,100,108,98,100,98,3,96,105,47,105,3,108,101,102,105,105,96,47,3,108,100,103,105,47,96,47,105,109,102,103,3,110,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,98,98,96,103,103,3,107,100,103,103,3,103,103,103,100,100,100,103,103,103,103,103,3,3,3,3,102,103,102,101,101,47,183,185,47,102,103,102,47,47,109,101,108,101,105,107,103,102,102,101,108,3,98,102,93,92,93,110,103,93,110,100,93,110,93,110,100,103,93,110,3,103,3,3,3,3,103,3,3,3,105,3,105,103,3,110,107,93,5,108,105,105,105,105,105,102,102,3,3,103,101,102,108,102,3,96,100,100,103,103,103,3,105,105,105,103,102,105,102,105,105,3,3,98,98,100,105,103,102,105,105,3,3,98,98,100,105,103,3,3,98,3,3,103,103,102,101,101,102,102,102,103,3,3,103,103,3,3,3,3,105,105,105,105,105,105,105,101,102,3,3,47,187,184,47,109,103,47,183,47,109,101,107,98,105,98,107,96,96,96,105,105,109,101,105,96,96,96,47,105,108,101,105,105,105,96,47,105,111,103,3,3,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,98,100,101,98,98,100,103,103,103,3,103,103,103,101,100,101,100,100,103,103,103,3,3,105,103,103,3,101,101,102,47,187,184,47,109,100,47,183,47,109,3,109,101,108,105,102,103,103,103,107,3,98,103,90,110,3,90,110,90,110,100,90,110,90,110,100,100,90,110,103,103,105,105,102,105,105,102,103,105,105,105,107,103,3,107,89,6,109,110,107,105,105,102,105,105,105,105,102,101,102,105,105,102,105,96,100,100,103,100,103,103,3,105,105,105,105,102,101,102,105,3,103,98,98,3,103,100,101,102,105,3,103,98,98,3,103,100,105,3,96,3,3,3,102,103,102,101,103,3,3,102,103,103,103,103,103,3,3,3,105,105,105,105,105,105,102,101,102,3,3,47,187,185,46,109,47,181,183,47,109,100,108,101,102,98,105,105,47,47,47,105,109,101,105,105,47,47,47,105,108,101,105,105,105,105,47,105,110,3,102,3,108,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,102,101,100,98,98,103,103,100,103,103,100,103,100,100,101,100,101,100,103,100,103,103,103,3,3,3,102,102,103,102,47,187,185,46,109,47,181,183,47,109,3,109,101,105,105,105,102,102,100,108,107,98,103,88,88,88,110,103,103,88,88,110,100,88,88,88,110,88,88,88,110,102,105,105,102,105,101,102,102,105,105,3,105,105,89,6,109,110,109,107,105,102,103,105,105,105,105,105,102,103,105,105,103,105,96,100,103,103,103,103,3,105,105,105,105,105,103,102,105,105,103,103,100,100,100,100,103,102,105,105,103,103,100,100,100,100,103,107,3,98,3,3,3,103,102,103,101,101,102,3,102,3,103,103,103,3,3,3,3,105,105,105,107,105,105,105,101,102,3,3,3,47,47,109,109,180,182,181,47,109,98,107,98,105,101,109,5,5,110,110,5,109,101,108,5,5,111,110,5,109,101,108,5,5,110,110,5,5,3,103,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,100,103,100,98,100,100,100,103,103,103,103,103,103,100,98,100,100,103,103,103,103,3,3,3,3,3,103,103,102,101,101,47,47,109,109,180,182,181,47,109,103,108,102,110,5,5,111,111,110,110,3,100,3,103,3,103,3,100,3,103,100,98,98,100,100,100,103,103,103,3,103,105,105,105,105,102,102,105,105,105,103,3,103,3,105,109,110,109,108,107,108,105,105,102,105,105,105,105,105,102,105,105,105,105,96,100,103,103,103,3,105,3,105,105,105,105,102,102,105,105,103,100,100,98,101,100,103,102,105,105,103,100,100,98,101,100,103,108,107,98,3,3,3,103,102,103,102,101,102,3,3,3,103,103,103,3,3,103,103,105,105,105,105,105,105,105,102,103,107,3,3,3,109,102,47,181,181,187,47,109,100,107,101,103,98,102,102,105,105,105,105,105,105,105,105,101,105,103,102,105,102,105,109,107,102,105,105,102,3,103,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,103,100,100,100,98,101,100,103,103,103,103,3,3,98,100,101,100,103,103,103,3,3,3,3,3,3,102,102,102,101,101,102,109,3,47,181,181,187,47,109,103,107,105,105,105,105,105,105,107,108,3,98,103,3,96,96,96,110,96,110,98,96,110,96,96,96,110,96,110,3,3,105,105,105,105,105,103,105,105,105,101,3,103,108,3,110,108,109,96,5,108,105,105,102,105,105,105,105,105,105,105,105,105,105,98,100,103,103,103,103,3,105,105,105,105,105,105,103,105,105,103,100,98,98,98,100,103,103,105,105,103,100,98,98,98,100,103,107,3,98,3,3,3,103,102,103,101,101,102,3,102,3,3,3,3,107,103,103,103,105,105,105,105,105,102,102,101,102,3,3,102,102,3,47,178,182,187,47,109,98,101,107,98,102,98,101,101,101,98,98,101,108,102,101,101,101,98,98,102,111,98,98,101,101,98,98,101,109,102,103,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,101,101,100,98,98,98,100,103,103,103,3,3,103,100,101,103,100,103,103,103,103,3,3,3,3,102,103,103,101,101,102,102,3,47,178,182,187,47,109,3,100,107,98,101,101,98,98,98,98,3,107,98,3,93,110,100,3,3,93,110,100,93,110,93,110,100,103,93,110,103,103,105,107,105,105,105,102,102,105,105,101,3,105,3,108,107,109,93,5,105,105,105,105,105,107,105,107,105,105,105,105,105,101,105,98,103,103,103,103,103,3,3,105,105,105,105,102,102,105,105,3,103,98,100,98,101,103,102,105,105,3,103,98,100,98,101,103,108,3,98,107,105,103,3,102,102,101,101,102,3,103,3,3,103,103,3,3,3,3,105,105,105,105,102,105,103,101,101,3,3,3,102,47,178,180,187,47,109,103,100,100,109,98,102,98,105,105,105,101,101,105,109,101,105,108,105,102,101,105,110,101,105,107,105,102,101,105,110,3,102,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,101,98,98,98,100,98,101,103,103,103,3,3,3,100,98,100,103,103,103,103,103,3,107,3,103,3,102,103,101,101,102,103,47,178,180,187,47,109,3,103,3,109,101,105,105,105,105,101,100,108,107,100,103,3,93,93,110,3,93,93,93,92,110,93,93,110,103,93,110,103,103,105,105,105,107,105,103,102,105,105,102,105,3,105,107,110,93,5,105,102,108,105,105,105,107,107,105,105,105,105,105,105,102,105,96,103,103,103,103,103,105,105,102,105,107,107,105,101,105,102,3,103,100,98,100,100,103,101,105,102,3,103,100,98,100,100,103,107,3,98,3,3,3,3,103,102,101,101,102,3,102,3,3,103,3,107,3,3,3,105,105,107,107,105,103,102,101,102,3,101,3,3,180,178,180,47,109,3,103,100,101,107,101,103,98,105,96,96,96,105,105,109,102,105,96,96,96,105,107,109,101,105,96,96,96,105,105,110,3,103,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,103,100,103,100,98,100,100,103,103,103,103,3,103,100,100,101,100,103,103,103,103,3,3,3,3,3,103,102,101,101,101,102,180,178,180,47,109,107,3,3,103,109,101,107,107,105,102,101,103,108,3,98,3,3,3,3,90,110,90,110,100,90,110,90,110,103,103,90,110,103,103,105,105,105,105,105,101,103,102,105,103,3,105,3,105,89,5,110,103,101,105,105,105,105,105,105,105,105,105,105,105,105,105,105,98,103,103,103,3,103,3,3,105,105,105,105,105,102,102,105,3,103,100,100,101,100,103,102,102,105,3,103,100,100,101,100,103,109,3,98,3,3,3,103,102,3,102,101,103,3,101,3,3,103,3,109,103,103,3,105,105,108,105,105,105,101,102,3,3,102,101,47,180,178,187,109,103,3,103,100,100,109,98,105,98,107,96,47,47,47,105,110,102,107,96,47,47,47,107,109,101,105,105,47,96,47,105,111,103,102,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,100,103,100,100,103,101,100,103,100,103,103,3,103,101,98,100,103,103,103,3,103,3,3,3,3,103,102,102,3,101,101,47,180,178,187,109,3,109,103,3,103,109,102,108,105,105,103,102,103,107,3,96,3,88,88,88,110,3,88,110,100,88,110,88,88,88,110,88,88,88,110,105,107,105,105,105,102,102,105,105,102,105,3,105,89,5,105,110,109,108,108,105,105,105,105,105,107,105,105,105,105,105,105,107,96,103,103,100,103,103,3,3,3,3,3,3,3,102,103,3,3,103,101,100,98,100,103,102,103,3,3,103,101,100,98,100,103,107,3,98,3,3,3,102,103,101,102,101,102,101,102,105,105,102,105,105,105,105,105,107,105,107,107,105,105,102,103,101,102,3,47,181,180,187,47,3,47,47,103,101,100,108,98,105,98,107,96,96,96,105,105,109,103,108,96,96,96,105,105,108,101,105,105,96,105,47,105,110,102,103,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,100,101,101,100,100,98,100,103,103,103,3,3,103,100,98,100,101,102,101,102,103,3,3,3,3,102,103,101,102,101,47,181,180,187,47,105,47,47,105,103,105,109,102,107,105,105,102,103,100,108,3,100,103,3,3,100,3,3,103,3,100,100,101,100,98,100,103,100,100,103,3,105,105,108,107,105,105,103,105,105,105,3,105,3,105,105,3,3,110,108,105,105,105,105,105,105,105,108,105,105,105,105,105,107,96,100,103,103,103,103,3,3,102,3,3,102,3,102,3,3,3,103,100,100,101,103,103,102,3,3,3,103,100,100,101,103,103,108,3,98,3,3,102,103,102,101,103,101,101,102,101,105,105,102,105,105,105,105,105,108,108,105,108,107,105,101,101,102,3,3,47,181,187,47,109,47,183,180,47,98,100,3,101,102,98,105,105,47,96,47,105,109,102,108,96,47,96,47,107,109,101,102,96,105,47,105,105,110,103,103,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,100,103,100,101,100,100,103,103,103,103,3,3,103,100,100,98,100,103,102,103,102,3,3,3,102,103,102,101,102,101,47,181,187,47,109,47,183,180,47,103,105,110,103,105,108,105,101,101,103,110,3,98,103,96,96,96,107,100,3,96,96,110,96,110,98,96,110,93,96,96,110,105,105,107,105,105,105,105,105,105,102,105,3,105,103,107,110,109,96,5,107,105,105,105,105,107,105,107,105,105,105,105,105,107,96,103,103,103,103,103,3,3,103,102,3,102,3,102,3,3,3,103,98,98,100,103,100,102,3,3,3,103,98,98,100,103,100,107,3,98,3,102,103,102,103,101,101,98,102,103,102,105,105,102,105,105,107,105,105,108,105,105,108,105,105,101,101,3,3,3,47,185,47,109,3,47,187,183,47,109,101,107,101,102,98,105,96,96,96,47,107,109,101,108,96,96,96,47,105,109,101,105,96,47,105,105,105,110,102,103,103,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,102,103,100,98,98,101,103,100,100,103,103,3,103,101,100,101,100,103,102,103,102,3,3,102,103,102,103,101,101,98,47,185,47,109,102,47,187,183,47,109,105,111,102,107,108,105,102,101,3,110,3,98,100,93,110,100,93,110,93,110,100,98,93,110,93,110,100,100,93,110,3,105,105,105,105,105,105,105,105,105,103,3,105,3,3,108,109,93,5,107,107,109,105,105,105,108,105,105,105,105,105,105,105,107,96,103,103,103,103,100,3,3,101,3,3,3,3,102,3,3,3,103,98,100,100,103,103,102,3,3,3,103,98,100,100,103,103,107,3,98,3,3,103,102,101,101,98,98,101,102,103,102,105,103,102,105,107,105,108,108,105,105,108,105,105,101,102,3,3,3,47,47,109,103,102,47,187,185,47,109,100,108,101,105,98,105,105,47,47,47,107,109,102,107,105,47,47,47,105,109,101,105,105,47,105,105,105,111,103,103,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,100,100,100,98,100,100,100,103,100,103,3,3,103,100,100,98,103,102,103,102,103,102,3,3,3,103,102,101,101,98,47,47,109,105,103,47,187,185,47,109,105,110,101,105,108,105,101,101,103,110,107,98,103,93,93,93,110,3,93,110,101,100,92,93,110,100,100,100,93,110,3,105,107,105,108,105,105,105,105,105,102,3,103,3,108,109,93,5,110,108,107,108,105,105,107,108,107,105,105,105,105,105,105,107,93,98,103,103,103,100,103,3,102,3,3,101,102,3,102,102,3,3,100,101,103,3,103,3,102,102,3,3,100,101,103,3,103,108,3,98,3,102,102,3,101,102,101,102,101,101,101,102,105,105,102,108,108,108,109,105,105,107,107,105,105,105,101,3,3,3,3,109,3,102,103,3,47,46,109,109,100,3,101,102,101,110,110,110,109,110,111,105,102,108,5,5,111,110,5,109,101,108,5,5,111,110,5,110,3,102,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,100,101,100,100,101,100,105,100,101,103,103,3,103,100,98,98,98,102,103,102,101,102,3,102,102,3,102,103,101,101,101,109,102,105,105,102,47,46,109,109,103,5,110,110,110,109,109,107,110,110,3,98,3,90,110,100,90,110,90,110,100,101,90,110,90,110,101,103,90,110,3,105,108,107,105,101,105,102,102,105,105,105,103,3,105,89,6,109,110,107,107,105,105,105,107,107,108,107,105,107,108,105,105,107,96,100,103,103,103,100,103,3,102,3,3,3,102,3,3,108,3,3,98,100,100,3,103,3,3,108,3,3,98,100,100,3,103,107,3,98,3,103,102,102,103,3,102,101,102,102,101,103,107,105,105,108,108,109,108,107,107,105,108,107,105,101,102,3,3,3,102,3,3,3,3,100,3,109,109,100,101,107,98,102,103,100,101,100,100,103,103,100,103,3,3,103,100,101,100,100,103,102,103,102,103,3,103,102,103,102,101,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,100,100,100,101,100,100,103,103,100,103,3,3,103,100,101,100,100,103,102,103,102,103,3,103,102,103,101,102,102,101,102,101,103,105,107,102,105,109,109,103,103,5,107,105,109,105,101,102,3,3,3,98,103,88,110,103,88,110,3,88,88,110,88,110,98,88,110,100,88,110,103,105,108,105,105,102,105,105,105,105,105,3,105,107,89,6,109,110,109,105,108,108,105,105,105,108,108,105,105,105,105,107,107,107,96,100,103,103,103,103,3,3,102,3,3,3,102,3,3,108,107,103,103,100,101,103,103,103,103,3,103,103,100,103,100,101,102,107,3,98,3,102,103,103,102,102,103,102,103,3,102,105,107,105,102,105,107,108,109,107,108,108,107,105,105,102,102,102,107,3,3,3,3,102,101,103,103,103,103,100,103,107,101,102,98,100,103,103,103,3,3,3,3,103,103,100,101,100,98,100,101,103,102,103,102,102,3,102,3,101,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,98,100,100,100,100,3,103,103,103,103,103,100,101,100,98,100,101,103,102,103,102,102,3,102,3,102,3,103,102,102,3,102,101,102,105,102,101,102,105,3,100,5,102,101,101,101,98,98,98,108,107,98,3,3,103,3,100,3,100,3,100,100,100,100,98,100,100,103,103,103,3,105,109,105,105,105,102,105,107,109,105,105,107,105,105,107,110,109,105,105,105,105,105,105,107,5,109,105,105,105,105,105,105,107,98,103,3,3,103,103,3,3,3,3,3,102,3,3,107,107,108,100,103,103,100,100,3,103,103,103,103,3,3,100,105,100,101,3,3,98,3,102,103,102,102,101,3,103,102,3,3,107,105,101,107,105,108,108,109,109,105,109,108,107,108,105,105,3,103,102,101,3,107,3,3,3,3,3,103,101,100,107,101,102,98,103,103,103,103,103,3,105,100,3,100,100,103,100,100,101,103,102,102,103,102,3,3,102,3,102,102,108,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,102,98,100,100,103,103,103,3,103,100,3,100,100,103,100,100,101,103,102,102,103,102,3,3,102,3,102,103,102,102,103,102,103,102,101,105,103,102,105,105,100,110,103,108,107,105,102,102,100,110,110,100,103,3,96,96,96,110,96,96,96,110,96,110,100,103,96,110,103,103,3,105,107,105,105,105,103,105,107,107,105,3,108,107,103,107,110,109,96,5,108,105,105,105,107,108,107,105,105,105,105,107,105,107,96,3,3,3,96,96,96,3,3,103,96,100,3,107,96,107,3,3,96,100,98,100,96,103,103,3,96,96,96,96,96,100,100,107,3,98,3,96,96,103,100,96,96,103,3,96,96,96,96,96,109,105,109,96,96,96,3,107,96,96,107,3,96,96,96,96,96,96,110,96,96,3,3,96,96,100,101,107,3,3,96,96,96,3,3,96,96,96,96,96,3,3,100,96,103,100,103,96,3,3,103,96,96,96,96,96,102,107,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,102,96,100,103,96,96,96,103,107,96,96,98,98,98,100,103,100,96,103,100,103,96,3,3,103,96,96,96,96,96,100,103,96,96,96,96,96,3,3,3,103,110,102,108,108,105,102,103,103,110,3,98,3,93,6,103,100,3,93,110,100,100,93,110,100,103,93,110,103,100,3,105,105,109,105,105,102,105,107,105,105,3,108,107,105,109,110,93,5,107,109,105,107,105,109,107,105,109,109,105,105,105,105,107,98,103,3,93,92,110,93,93,110,93,93,93,103,93,93,93,107,93,93,93,100,93,93,93,103,93,92,110,7,110,93,93,100,108,3,98,3,93,92,110,101,93,92,110,93,92,110,5,5,6,5,105,93,93,5,93,93,110,93,93,7,3,3,110,93,92,110,110,7,92,93,110,3,93,93,110,100,108,3,93,92,110,93,93,3,3,110,110,110,93,93,3,93,93,93,103,93,93,93,3,93,92,110,109,5,6,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,102,100,100,93,92,110,93,93,107,103,110,110,110,93,93,100,93,92,93,103,93,93,93,3,93,92,110,110,110,93,93,103,100,110,110,110,93,93,3,3,103,111,105,109,108,105,102,105,3,110,107,98,3,93,110,3,3,107,93,93,110,100,93,110,103,100,93,110,103,103,3,102,108,107,105,105,102,107,105,105,107,3,108,107,108,110,92,6,110,108,109,107,108,105,107,109,108,107,108,107,105,105,105,107,96,3,93,93,93,93,92,93,110,92,93,92,93,93,92,93,7,93,92,93,93,93,92,93,110,93,93,110,3,3,92,93,110,107,3,98,3,93,93,93,92,93,93,110,93,93,93,93,93,93,107,93,92,93,93,93,92,7,93,92,7,110,3,103,93,93,110,3,3,93,92,93,93,92,93,110,100,107,93,93,93,93,92,93,110,93,93,93,93,93,110,110,92,93,92,93,93,92,93,110,100,93,93,93,93,103,103,110,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,98,101,100,93,93,93,93,92,93,110,93,93,93,93,93,110,110,93,93,93,93,93,92,93,110,93,93,110,103,103,92,93,110,93,93,93,93,93,110,110,3,107,109,105,110,109,105,105,102,102,107,107,98,102,89,110,3,3,3,90,110,100,100,90,110,96,100,90,110,103,100,3,105,108,107,108,105,105,107,102,105,105,105,3,108,107,89,6,109,109,110,109,109,110,105,105,108,108,107,108,108,105,105,105,108,98,3,90,90,110,110,90,90,110,90,90,110,90,110,90,90,110,90,90,110,90,110,90,90,110,90,90,110,3,105,90,90,110,3,3,98,3,90,90,110,110,90,90,110,90,90,7,5,5,5,6,89,89,6,5,90,90,7,90,90,7,110,3,3,90,90,110,3,3,90,90,110,110,90,90,110,101,108,90,90,110,110,90,90,110,90,90,110,110,90,90,3,90,90,110,90,110,90,90,7,98,100,110,5,89,89,102,108,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,107,98,102,100,90,90,110,110,90,90,110,90,90,110,110,90,90,100,90,90,110,90,110,90,90,7,90,90,110,103,103,90,90,110,90,90,110,110,90,90,3,107,3,109,105,109,108,105,102,103,103,110,108,98,102,3,89,88,88,110,88,88,88,110,88,88,88,110,88,88,88,110,3,105,107,108,108,105,105,108,105,102,105,3,107,110,89,127,110,109,110,111,109,110,110,105,105,108,107,108,108,107,107,107,105,108,98,100,88,88,110,3,88,88,110,88,88,110,107,7,88,88,110,88,88,110,110,110,88,88,110,100,88,88,88,88,88,110,110,108,3,98,3,88,88,110,100,88,88,110,100,88,88,89,90,89,109,89,90,5,105,88,88,7,88,88,88,88,3,103,88,88,110,3,3,88,88,110,103,88,88,110,100,107,88,88,110,3,88,88,110,88,88,110,3,88,88,110,88,88,110,100,110,88,88,7,88,88,88,89,89,6,102,109,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,102,105,88,88,110,100,88,88,7,88,88,110,100,88,88,110,88,88,110,100,110,88,88,7,3,88,88,88,88,88,110,110,88,88,110,3,88,88,110,108,3,109,102,109,108,105,102,103,102,110,107,98,3,3,3,3,3,107,3,103,100,100,101,103,103,100,103,103,103,103,103,105,108,109,105,105,105,109,105,105,105,3,159,107,108,109,109,110,109,109,109,109,107,105,107,105,108,109,109,105,107,107,105,109,98,103,3,110,110,3,3,7,110,3,110,110,110,107,3,110,110,107,110,110,103,100,100,110,110,100,103,110,7,110,110,110,100,108,3,98,3,110,110,110,103,103,110,110,103,3,110,5,110,5,6,110,5,6,3,107,7,7,110,7,7,110,110,103,103,110,110,3,3,3,110,110,3,110,110,110,100,108,3,110,110,3,3,110,110,103,110,110,3,103,110,110,100,110,110,103,3,3,110,110,100,110,110,6,5,6,102,108,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,105,3,100,110,110,100,103,110,7,3,110,110,100,100,110,110,100,110,110,103,103,103,110,110,3,3,110,110,110,110,110,3,103,110,110,3,103,110,110,3,108,110,102,108,108,102,103,101,102,110,107,98,3,3,3,3,3,108,103,100,101,100,100,103,103,103,103,3,3,107,3,105,109,108,105,105,105,109,105,105,107,105,105,107,105,110,109,110,110,109,108,109,105,105,105,107,109,108,109,108,105,105,107,107,98,100,103,100,3,103,3,3,3,3,3,107,3,108,107,3,3,3,3,100,98,103,3,103,103,3,3,3,100,100,100,100,103,107,3,98,3,3,3,103,3,3,100,100,100,103,103,105,3,105,105,109,108,107,108,108,107,110,107,3,103,103,100,103,3,3,3,3,3,3,3,3,103,3,3,101,100,108,100,98,100,103,3,3,3,3,3,3,3,100,103,103,3,3,3,3,3,103,3,3,108,107,107,3,105,102,102,110,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,101,102,103,100,103,103,103,103,103,107,3,103,103,100,101,100,100,100,103,103,103,103,3,3,3,3,3,3,103,3,103,103,100,103,3,103,103,103,3,3,3,108,110,110,5,110,109,107,107,107,110,107,98,3,3,3,3,103,3,105,100,100,101,100,103,100,103,103,103,3,3,3,105,108,109,108,105,105,109,105,105,105,3,108,3,108,109,110,109,109,109,110,110,107,105,109,108,108,109,109,108,107,109,105,108,100,108,107,110,107,110,110,110,110,110,110,110,110,110,110,110,110,110,107,105,107,107,107,107,110,110,108,3,3,108,108,108,107,107,110,110,110,107,110,110,107,108,3,108,108,107,110,110,109,110,109,110,109,6,109,110,110,110,110,107,108,107,110,110,110,110,110,110,110,110,107,110,110,107,3,3,108,107,108,107,110,107,110,110,110,110,110,110,107,108,110,110,110,107,110,110,110,107,110,110,110,110,110,6,5,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,108,108,107,110,107,3,107,110,107,107,110,110,107,3,3,108,108,108,107,110,107,110,110,110,107,110,110,108,107,3,3,107,107,110,110,110,110,110,110,110,110,110,5,111,110,109,108,107,108,110,110,110,110,110,110,107,110,110,107,3,3,108,107,108,107,110,107,110,110,110,110,110,110,5,5,109,110,110,109,109,109,110,110,10,5,6,5,6,5,6,5,5,109,110,5,110,5,5,5,110,110,110,110,110,109, }; diff --git a/source/global_data.c b/cppsrc/global_data.cc similarity index 56% rename from source/global_data.c rename to cppsrc/global_data.cc index b2b9b06a..a9f57b65 100644 --- a/source/global_data.c +++ b/cppsrc/global_data.cc @@ -1,4 +1,5 @@ -#include +//#include +#include #include "global_data.h" #include "z_zone.h" @@ -8,7 +9,7 @@ globals_t* _g = NULL; void InitGlobals() { - _g = Z_Malloc(sizeof(globals_t), PU_STATIC, NULL); + _g = (globals_t *)Z_Malloc(sizeof(globals_t), PU_STATIC, NULL); memset(_g, 0, sizeof(globals_t)); diff --git a/source/hu_lib.c b/cppsrc/hu_lib.cc similarity index 94% rename from source/hu_lib.c rename to cppsrc/hu_lib.cc index 0f1dce7d..fc2a17f7 100644 --- a/source/hu_lib.c +++ b/cppsrc/hu_lib.cc @@ -72,12 +72,13 @@ void HUlib_clearTextLine(hu_textline_t* t) // Passed a hu_textline_t, and the values used to initialize // Returns nothing // -void HUlib_initTextLine(hu_textline_t* t, int x, int y, const patch_t *f, int sc) +void HUlib_initTextLine(hu_textline_t* t, int x, int y, hu_fontlist_t f, int sc) //jff 2/16/98 add color range parameter { t->x = x; t->y = y; - t->f = f; + for (int i = 0; i < HU_FONTSIZE; i++) + t->f[i] = f[i]; t->sc = sc; HUlib_clearTextLine(t); } @@ -143,7 +144,8 @@ void HUlib_drawTextLine(hu_textline_t* l) break; // killough 1/18/98 -- support multiple lines: // CPhipps - patch drawing updated - V_DrawPatchNoScale(x, y, l->f[c - l->sc]); + auto pinned_font = l->f[c - l->sc].pin(); + V_DrawPatchNoScale(x, y, pinned_font); x += w; } else @@ -185,7 +187,7 @@ void HUlib_eraseTextLine(hu_textline_t* l) // Passed a hu_stext_t, and the values used to initialize // Returns nothing // -void HUlib_initSText(hu_stext_t* s,int x,int y,int h, const patch_t* font, int startchar, boolean* on) +void HUlib_initSText(hu_stext_t* s,int x,int y,int h, hu_fontlist_t font, int startchar, boolean* on) { int i; @@ -199,7 +201,7 @@ void HUlib_initSText(hu_stext_t* s,int x,int y,int h, const patch_t* font, int s ( &s->l[i], x, - y - i*(font[0].height+1), + y - i*(font[0]->height+1), font, startchar ); diff --git a/source/hu_stuff.c b/cppsrc/hu_stuff.cc similarity index 96% rename from source/hu_stuff.c rename to cppsrc/hu_stuff.cc index 82aaa526..3c65288a 100644 --- a/source/hu_stuff.c +++ b/cppsrc/hu_stuff.cc @@ -37,7 +37,7 @@ #include "hu_stuff.h" #include "hu_lib.h" #include "st_stuff.h" /* jff 2/16/98 need loc of status bar */ -#include "w_wad.h" + #include "s_sound.h" #include "dstrings.h" #include "sounds.h" @@ -68,9 +68,9 @@ // proff - changed to SCREENWIDTH to 320 for stretching #define HU_COORDX (320 - 13*_g->hu_font['A'-HU_FONTSTART].width) //jff 3/3/98 split coord widget into three lines in upper right of screen -#define HU_COORDX_Y (1 + 0*_g->hu_font['A'-HU_FONTSTART].height) -#define HU_COORDY_Y (2 + 1*_g->hu_font['A'-HU_FONTSTART].height) -#define HU_COORDZ_Y (3 + 2*_g->hu_font['A'-HU_FONTSTART].height) +#define HU_COORDX_Y (1 + 0*_g->hu_font['A'-HU_FONTSTART]->height) +#define HU_COORDY_Y (2 + 1*_g->hu_font['A'-HU_FONTSTART]->height) +#define HU_COORDZ_Y (3 + 2*_g->hu_font['A'-HU_FONTSTART]->height) //jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap #define HU_GAPY 8 @@ -117,18 +117,19 @@ //#define HU_INPUTTOGGLE 't' // not used // phares #define HU_INPUTX HU_MSGX -#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(hu_font[0].height) +1) +#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(_g->hu_font[0]->height) +1) #define HU_INPUTWIDTH 64 #define HU_INPUTHEIGHT 1 #define key_alt KEYD_RALT #define key_shift KEYD_RSHIFT +/* //jff 2/16/98 hud supported automap colors added const int hudcolor_titl = 5; // color range of automap level title //jff 2/16/98 hud text colors, controls added const int hudcolor_mesg = 6; // color range of scrolling messages - +*/ //jff 2/26/98 hud text colors, controls added const int hud_msg_lines = 1; // number of message lines in window @@ -321,8 +322,8 @@ void HU_Init(void) j = HU_FONTSTART; for (i=0;ihu_font[i] = (const patch_t *) W_CacheLumpName(buffer); + snprintf(buffer, sizeof(buffer), "STCFN%.3d", j++); + _g->hu_font[i] = Cached(buffer); } } diff --git a/source/i_audio.c b/cppsrc/i_audio.cc similarity index 92% rename from source/i_audio.c rename to cppsrc/i_audio.cc index dbeafe6a..d0c586eb 100644 --- a/source/i_audio.c +++ b/cppsrc/i_audio.cc @@ -47,7 +47,7 @@ #include "m_swap.h" #include "i_sound.h" #include "m_misc.h" -#include "w_wad.h" + #include "lprintf.h" #include "s_sound.h" @@ -276,7 +276,8 @@ static const audio_map_t soundMap[NUMSFX] = // (eight, usually) of internal channels. // Returns a handle. // -static int addsfx(int sfxid, int channel, int volume, int sep) + +static int addsfx(int sfxid MAYBE_UNUSED, int channel, int volume MAYBE_UNUSED, int sep MAYBE_UNUSED) { #ifdef GBA @@ -333,7 +334,7 @@ void I_InitSound(void) lprintf(LO_INFO,"I_InitSound: sound ready"); } -void I_PlaySong(int handle, int looping) +void I_PlaySong(int handle, int looping MAYBE_UNUSED) { if(handle == mus_None) return; @@ -348,28 +349,28 @@ void I_PlaySong(int handle, int looping) } -void I_PauseSong (int handle) +void I_PauseSong (int handle MAYBE_UNUSED) { #ifdef GBA mmPause(); #endif } -void I_ResumeSong (int handle) +void I_ResumeSong (int handle MAYBE_UNUSED) { #ifdef GBA mmResume(); #endif } -void I_StopSong(int handle) +void I_StopSong(int handle MAYBE_UNUSED) { #ifdef GBA mmStop(); #endif } -void I_SetMusicVolume(int volume) +void I_SetMusicVolume(int volume MAYBE_UNUSED) { #ifdef GBA int mmvol = volume * 32; diff --git a/source/i_system.c b/cppsrc/i_system.cc similarity index 96% rename from source/i_system.c rename to cppsrc/i_system.cc index 20267506..6121cb97 100644 --- a/source/i_system.c +++ b/cppsrc/i_system.cc @@ -34,7 +34,7 @@ */ -#include +//#include #include #include "doomtype.h" @@ -54,6 +54,6 @@ */ const char* I_GetVersionString(char* buf, size_t sz) { - sprintf(buf,"GBADoom v%s",VERSION); + snprintf(buf,sz,"GBADoom v%s",VERSION); return buf; } diff --git a/source/i_video.c b/cppsrc/i_video.cc similarity index 92% rename from source/i_video.c rename to cppsrc/i_video.cc index fe441f0d..832806eb 100644 --- a/source/i_video.c +++ b/cppsrc/i_video.cc @@ -36,7 +36,7 @@ #include "config.h" #endif -#include +//#include #ifdef HAVE_UNISTD_H #include @@ -56,7 +56,7 @@ #include "z_zone.h" #include "s_sound.h" #include "sounds.h" -#include "w_wad.h" + #include "st_stuff.h" #include "lprintf.h" @@ -119,12 +119,12 @@ static void I_UploadNewPalette(int pal) // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes - if(!_g->pallete_lump) + if(_g->pallete_lump.isnull()) { - _g->pallete_lump = W_CacheLumpName("PLAYPAL"); + _g->pallete_lump = CachedBuffer("PLAYPAL"); } - _g->current_pallete = &_g->pallete_lump[pal*256*3]; + _g->current_pallete = _g->pallete_lump.addOffset(pal*256*3); I_SetPallete_e32(_g->current_pallete); } @@ -156,7 +156,8 @@ void I_FinishUpdate (void) _g->newpal = NO_PALETTE_CHANGE; } - I_FinishUpdate_e32(_g->screens[0].data, _g->current_pallete, SCREENWIDTH, SCREENHEIGHT); + auto pinnedpallete = _g->current_pallete.pin(); + I_FinishUpdate_e32((const uint8_t* )_g->screens[0].data, pinnedpallete, SCREENWIDTH, SCREENHEIGHT); } // diff --git a/source/info.c b/cppsrc/info.cc similarity index 60% rename from source/info.c rename to cppsrc/info.cc index 829fca37..dba5833a 100644 --- a/source/info.c +++ b/cppsrc/info.cc @@ -43,7 +43,7 @@ #include "p_mobj.h" #include "p_enemy.h" #include "p_pspr.h" -#include "w_wad.h" + #ifdef __GNUG__ #pragma implementation "info.h" @@ -101,1097 +101,1097 @@ const char * const sprnames[NUMSPRITES+1] = { // extended way a BEX file can handle this. const state_t states[NUMSTATES] = { - {SPR_TROO,0,-1,NULL,S_NULL,0,0}, // S_NULL - {SPR_SHTG,4,0,A_Light0,S_NULL,0,0}, // S_LIGHTDONE - {SPR_PUNG,0,1,A_WeaponReady,S_PUNCH,0,0}, // S_PUNCH - {SPR_PUNG,0,1,A_Lower,S_PUNCHDOWN,0,0}, // S_PUNCHDOWN - {SPR_PUNG,0,1,A_Raise,S_PUNCHUP,0,0}, // S_PUNCHUP - {SPR_PUNG,1,4,NULL,S_PUNCH2,0,0}, // S_PUNCH1 - {SPR_PUNG,2,4,A_Punch,S_PUNCH3,0,0}, // S_PUNCH2 - {SPR_PUNG,3,5,NULL,S_PUNCH4,0,0}, // S_PUNCH3 - {SPR_PUNG,2,4,NULL,S_PUNCH5,0,0}, // S_PUNCH4 - {SPR_PUNG,1,5,A_ReFire,S_PUNCH,0,0}, // S_PUNCH5 - {SPR_PISG,0,1,A_WeaponReady,S_PISTOL,0,0},// S_PISTOL - {SPR_PISG,0,1,A_Lower,S_PISTOLDOWN,0,0}, // S_PISTOLDOWN - {SPR_PISG,0,1,A_Raise,S_PISTOLUP,0,0}, // S_PISTOLUP - {SPR_PISG,0,4,NULL,S_PISTOL2,0,0}, // S_PISTOL1 - {SPR_PISG,1,6,A_FirePistol,S_PISTOL3,0,0},// S_PISTOL2 - {SPR_PISG,2,4,NULL,S_PISTOL4,0,0}, // S_PISTOL3 - {SPR_PISG,1,5,A_ReFire,S_PISTOL,0,0}, // S_PISTOL4 - {SPR_PISF,32768,7,A_Light1,S_LIGHTDONE,0,0}, // S_PISTOLFLASH - {SPR_SHTG,0,1,A_WeaponReady,S_SGUN,0,0}, // S_SGUN - {SPR_SHTG,0,1,A_Lower,S_SGUNDOWN,0,0}, // S_SGUNDOWN - {SPR_SHTG,0,1,A_Raise,S_SGUNUP,0,0}, // S_SGUNUP - {SPR_SHTG,0,3,NULL,S_SGUN2,0,0}, // S_SGUN1 - {SPR_SHTG,0,7,A_FireShotgun,S_SGUN3,0,0}, // S_SGUN2 - {SPR_SHTG,1,5,NULL,S_SGUN4,0,0}, // S_SGUN3 - {SPR_SHTG,2,5,NULL,S_SGUN5,0,0}, // S_SGUN4 - {SPR_SHTG,3,4,NULL,S_SGUN6,0,0}, // S_SGUN5 - {SPR_SHTG,2,5,NULL,S_SGUN7,0,0}, // S_SGUN6 - {SPR_SHTG,1,5,NULL,S_SGUN8,0,0}, // S_SGUN7 - {SPR_SHTG,0,3,NULL,S_SGUN9,0,0}, // S_SGUN8 - {SPR_SHTG,0,7,A_ReFire,S_SGUN,0,0}, // S_SGUN9 - {SPR_SHTF,32768,4,A_Light1,S_SGUNFLASH2,0,0}, // S_SGUNFLASH1 - {SPR_SHTF,32769,3,A_Light2,S_LIGHTDONE,0,0}, // S_SGUNFLASH2 - {SPR_SHT2,0,1,A_WeaponReady,S_DSGUN,0,0}, // S_DSGUN - {SPR_SHT2,0,1,A_Lower,S_DSGUNDOWN,0,0}, // S_DSGUNDOWN - {SPR_SHT2,0,1,A_Raise,S_DSGUNUP,0,0}, // S_DSGUNUP - {SPR_SHT2,0,3,NULL,S_DSGUN2,0,0}, // S_DSGUN1 - {SPR_SHT2,0,7,A_FireShotgun2,S_DSGUN3,0,0}, // S_DSGUN2 - {SPR_SHT2,1,7,NULL,S_DSGUN4,0,0}, // S_DSGUN3 - {SPR_SHT2,2,7,A_CheckReload,S_DSGUN5,0,0}, // S_DSGUN4 - {SPR_SHT2,3,7,A_OpenShotgun2,S_DSGUN6,0,0}, // S_DSGUN5 - {SPR_SHT2,4,7,NULL,S_DSGUN7,0,0}, // S_DSGUN6 - {SPR_SHT2,5,7,A_LoadShotgun2,S_DSGUN8,0,0}, // S_DSGUN7 - {SPR_SHT2,6,6,NULL,S_DSGUN9,0,0}, // S_DSGUN8 - {SPR_SHT2,7,6,A_CloseShotgun2,S_DSGUN10,0,0}, // S_DSGUN9 - {SPR_SHT2,0,5,A_ReFire,S_DSGUN,0,0}, // S_DSGUN10 - {SPR_SHT2,1,7,NULL,S_DSNR2,0,0}, // S_DSNR1 - {SPR_SHT2,0,3,NULL,S_DSGUNDOWN,0,0}, // S_DSNR2 - {SPR_SHT2,32776,5,A_Light1,S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1 - {SPR_SHT2,32777,4,A_Light2,S_LIGHTDONE,0,0}, // S_DSGUNFLASH2 - {SPR_CHGG,0,1,A_WeaponReady,S_CHAIN,0,0}, // S_CHAIN - {SPR_CHGG,0,1,A_Lower,S_CHAINDOWN,0,0}, // S_CHAINDOWN - {SPR_CHGG,0,1,A_Raise,S_CHAINUP,0,0}, // S_CHAINUP - {SPR_CHGG,0,4,A_FireCGun,S_CHAIN2,0,0}, // S_CHAIN1 - {SPR_CHGG,1,4,A_FireCGun,S_CHAIN3,0,0}, // S_CHAIN2 - {SPR_CHGG,1,0,A_ReFire,S_CHAIN,0,0}, // S_CHAIN3 - {SPR_CHGF,32768,5,A_Light1,S_LIGHTDONE,0,0}, // S_CHAINFLASH1 - {SPR_CHGF,32769,5,A_Light2,S_LIGHTDONE,0,0}, // S_CHAINFLASH2 - {SPR_MISG,0,1,A_WeaponReady,S_MISSILE,0,0}, // S_MISSILE - {SPR_MISG,0,1,A_Lower,S_MISSILEDOWN,0,0}, // S_MISSILEDOWN - {SPR_MISG,0,1,A_Raise,S_MISSILEUP,0,0}, // S_MISSILEUP - {SPR_MISG,1,8,A_GunFlash,S_MISSILE2,0,0}, // S_MISSILE1 - {SPR_MISG,1,12,A_FireMissile,S_MISSILE3,0,0}, // S_MISSILE2 - {SPR_MISG,1,0,A_ReFire,S_MISSILE,0,0}, // S_MISSILE3 - {SPR_MISF,32768,3,A_Light1,S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1 - {SPR_MISF,32769,4,NULL,S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2 - {SPR_MISF,32770,4,A_Light2,S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3 - {SPR_MISF,32771,4,A_Light2,S_LIGHTDONE,0,0}, // S_MISSILEFLASH4 - {SPR_SAWG,2,4,A_WeaponReady,S_SAWB,0,0}, // S_SAW - {SPR_SAWG,3,4,A_WeaponReady,S_SAW,0,0}, // S_SAWB - {SPR_SAWG,2,1,A_Lower,S_SAWDOWN,0,0}, // S_SAWDOWN - {SPR_SAWG,2,1,A_Raise,S_SAWUP,0,0}, // S_SAWUP - {SPR_SAWG,0,4,A_Saw,S_SAW2,0,0}, // S_SAW1 - {SPR_SAWG,1,4,A_Saw,S_SAW3,0,0}, // S_SAW2 - {SPR_SAWG,1,0,A_ReFire,S_SAW,0,0}, // S_SAW3 - {SPR_PLSG,0,1,A_WeaponReady,S_PLASMA,0,0}, // S_PLASMA - {SPR_PLSG,0,1,A_Lower,S_PLASMADOWN,0,0}, // S_PLASMADOWN - {SPR_PLSG,0,1,A_Raise,S_PLASMAUP,0,0}, // S_PLASMAUP - {SPR_PLSG,0,3,A_FirePlasma,S_PLASMA2,0,0}, // S_PLASMA1 - {SPR_PLSG,1,20,A_ReFire,S_PLASMA,0,0}, // S_PLASMA2 - {SPR_PLSF,32768,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH1 - {SPR_PLSF,32769,4,A_Light1,S_LIGHTDONE,0,0}, // S_PLASMAFLASH2 - {SPR_BFGG,0,1,A_WeaponReady,S_BFG,0,0}, // S_BFG - {SPR_BFGG,0,1,A_Lower,S_BFGDOWN,0,0}, // S_BFGDOWN - {SPR_BFGG,0,1,A_Raise,S_BFGUP,0,0}, // S_BFGUP - {SPR_BFGG,0,20,A_BFGsound,S_BFG2,0,0}, // S_BFG1 - {SPR_BFGG,1,10,A_GunFlash,S_BFG3,0,0}, // S_BFG2 - {SPR_BFGG,1,10,A_FireBFG,S_BFG4,0,0}, // S_BFG3 - {SPR_BFGG,1,20,A_ReFire,S_BFG,0,0}, // S_BFG4 - {SPR_BFGF,32768,11,A_Light1,S_BFGFLASH2,0,0}, // S_BFGFLASH1 - {SPR_BFGF,32769,6,A_Light2,S_LIGHTDONE,0,0}, // S_BFGFLASH2 - {SPR_BLUD,2,8,NULL,S_BLOOD2,0,0}, // S_BLOOD1 - {SPR_BLUD,1,8,NULL,S_BLOOD3,0,0}, // S_BLOOD2 - {SPR_BLUD,0,8,NULL,S_NULL,0,0}, // S_BLOOD3 - {SPR_PUFF,32768,4,NULL,S_PUFF2,0,0}, // S_PUFF1 - {SPR_PUFF,1,4,NULL,S_PUFF3,0,0}, // S_PUFF2 - {SPR_PUFF,2,4,NULL,S_PUFF4,0,0}, // S_PUFF3 - {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_PUFF4 - {SPR_BAL1,32768,4,NULL,S_TBALL2,0,0}, // S_TBALL1 - {SPR_BAL1,32769,4,NULL,S_TBALL1,0,0}, // S_TBALL2 - {SPR_BAL1,32770,6,NULL,S_TBALLX2,0,0}, // S_TBALLX1 - {SPR_BAL1,32771,6,NULL,S_TBALLX3,0,0}, // S_TBALLX2 - {SPR_BAL1,32772,6,NULL,S_NULL,0,0}, // S_TBALLX3 - {SPR_BAL2,32768,4,NULL,S_RBALL2,0,0}, // S_RBALL1 - {SPR_BAL2,32769,4,NULL,S_RBALL1,0,0}, // S_RBALL2 - {SPR_BAL2,32770,6,NULL,S_RBALLX2,0,0}, // S_RBALLX1 - {SPR_BAL2,32771,6,NULL,S_RBALLX3,0,0}, // S_RBALLX2 - {SPR_BAL2,32772,6,NULL,S_NULL,0,0}, // S_RBALLX3 - {SPR_PLSS,32768,6,NULL,S_PLASBALL2,0,0}, // S_PLASBALL - {SPR_PLSS,32769,6,NULL,S_PLASBALL,0,0}, // S_PLASBALL2 - {SPR_PLSE,32768,4,NULL,S_PLASEXP2,0,0}, // S_PLASEXP - {SPR_PLSE,32769,4,NULL,S_PLASEXP3,0,0}, // S_PLASEXP2 - {SPR_PLSE,32770,4,NULL,S_PLASEXP4,0,0}, // S_PLASEXP3 - {SPR_PLSE,32771,4,NULL,S_PLASEXP5,0,0}, // S_PLASEXP4 - {SPR_PLSE,32772,4,NULL,S_NULL,0,0}, // S_PLASEXP5 - {SPR_MISL,32768,1,NULL,S_ROCKET,0,0}, // S_ROCKET - {SPR_BFS1,32768,4,NULL,S_BFGSHOT2,0,0}, // S_BFGSHOT - {SPR_BFS1,32769,4,NULL,S_BFGSHOT,0,0}, // S_BFGSHOT2 - {SPR_BFE1,32768,8,NULL,S_BFGLAND2,0,0}, // S_BFGLAND - {SPR_BFE1,32769,8,NULL,S_BFGLAND3,0,0}, // S_BFGLAND2 - {SPR_BFE1,32770,8,A_BFGSpray,S_BFGLAND4,0,0}, // S_BFGLAND3 - {SPR_BFE1,32771,8,NULL,S_BFGLAND5,0,0}, // S_BFGLAND4 - {SPR_BFE1,32772,8,NULL,S_BFGLAND6,0,0}, // S_BFGLAND5 - {SPR_BFE1,32773,8,NULL,S_NULL,0,0}, // S_BFGLAND6 - {SPR_BFE2,32768,8,NULL,S_BFGEXP2,0,0}, // S_BFGEXP - {SPR_BFE2,32769,8,NULL,S_BFGEXP3,0,0}, // S_BFGEXP2 - {SPR_BFE2,32770,8,NULL,S_BFGEXP4,0,0}, // S_BFGEXP3 - {SPR_BFE2,32771,8,NULL,S_NULL,0,0}, // S_BFGEXP4 - {SPR_MISL,32769,8,A_Explode,S_EXPLODE2,0,0}, // S_EXPLODE1 - {SPR_MISL,32770,6,NULL,S_EXPLODE3,0,0}, // S_EXPLODE2 - {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_EXPLODE3 - {SPR_TFOG,32768,6,NULL,S_TFOG01,0,0}, // S_TFOG - {SPR_TFOG,32769,6,NULL,S_TFOG02,0,0}, // S_TFOG01 - {SPR_TFOG,32768,6,NULL,S_TFOG2,0,0}, // S_TFOG02 - {SPR_TFOG,32769,6,NULL,S_TFOG3,0,0}, // S_TFOG2 - {SPR_TFOG,32770,6,NULL,S_TFOG4,0,0}, // S_TFOG3 - {SPR_TFOG,32771,6,NULL,S_TFOG5,0,0}, // S_TFOG4 - {SPR_TFOG,32772,6,NULL,S_TFOG6,0,0}, // S_TFOG5 - {SPR_TFOG,32773,6,NULL,S_TFOG7,0,0}, // S_TFOG6 - {SPR_TFOG,32774,6,NULL,S_TFOG8,0,0}, // S_TFOG7 - {SPR_TFOG,32775,6,NULL,S_TFOG9,0,0}, // S_TFOG8 - {SPR_TFOG,32776,6,NULL,S_TFOG10,0,0}, // S_TFOG9 - {SPR_TFOG,32777,6,NULL,S_NULL,0,0}, // S_TFOG10 - {SPR_IFOG,32768,6,NULL,S_IFOG01,0,0}, // S_IFOG - {SPR_IFOG,32769,6,NULL,S_IFOG02,0,0}, // S_IFOG01 - {SPR_IFOG,32768,6,NULL,S_IFOG2,0,0}, // S_IFOG02 - {SPR_IFOG,32769,6,NULL,S_IFOG3,0,0}, // S_IFOG2 - {SPR_IFOG,32770,6,NULL,S_IFOG4,0,0}, // S_IFOG3 - {SPR_IFOG,32771,6,NULL,S_IFOG5,0,0}, // S_IFOG4 - {SPR_IFOG,32772,6,NULL,S_NULL,0,0}, // S_IFOG5 - {SPR_PLAY,0,-1,NULL,S_NULL,0,0}, // S_PLAY - {SPR_PLAY,0,4,NULL,S_PLAY_RUN2,0,0}, // S_PLAY_RUN1 - {SPR_PLAY,1,4,NULL,S_PLAY_RUN3,0,0}, // S_PLAY_RUN2 - {SPR_PLAY,2,4,NULL,S_PLAY_RUN4,0,0}, // S_PLAY_RUN3 - {SPR_PLAY,3,4,NULL,S_PLAY_RUN1,0,0}, // S_PLAY_RUN4 - {SPR_PLAY,4,12,NULL,S_PLAY,0,0}, // S_PLAY_ATK1 - {SPR_PLAY,32773,6,NULL,S_PLAY_ATK1,0,0}, // S_PLAY_ATK2 - {SPR_PLAY,6,4,NULL,S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN - {SPR_PLAY,6,4,A_Pain,S_PLAY,0,0}, // S_PLAY_PAIN2 - {SPR_PLAY,7,10,NULL,S_PLAY_DIE2,0,0}, // S_PLAY_DIE1 - {SPR_PLAY,8,10,A_PlayerScream,S_PLAY_DIE3,0,0}, // S_PLAY_DIE2 - {SPR_PLAY,9,10,A_Fall,S_PLAY_DIE4,0,0}, // S_PLAY_DIE3 - {SPR_PLAY,10,10,NULL,S_PLAY_DIE5,0,0}, // S_PLAY_DIE4 - {SPR_PLAY,11,10,NULL,S_PLAY_DIE6,0,0}, // S_PLAY_DIE5 - {SPR_PLAY,12,10,NULL,S_PLAY_DIE7,0,0}, // S_PLAY_DIE6 - {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_PLAY_DIE7 - {SPR_PLAY,14,5,NULL,S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1 - {SPR_PLAY,15,5,A_XScream,S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2 - {SPR_PLAY,16,5,A_Fall,S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3 - {SPR_PLAY,17,5,NULL,S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4 - {SPR_PLAY,18,5,NULL,S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5 - {SPR_PLAY,19,5,NULL,S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6 - {SPR_PLAY,20,5,NULL,S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7 - {SPR_PLAY,21,5,NULL,S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8 - {SPR_PLAY,22,-1,NULL,S_NULL,0,0}, // S_PLAY_XDIE9 - {SPR_POSS,0,10,A_Look,S_POSS_STND2,0,0}, // S_POSS_STND - {SPR_POSS,1,10,A_Look,S_POSS_STND,0,0}, // S_POSS_STND2 - {SPR_POSS,0,4,A_Chase,S_POSS_RUN2,0,0}, // S_POSS_RUN1 - {SPR_POSS,0,4,A_Chase,S_POSS_RUN3,0,0}, // S_POSS_RUN2 - {SPR_POSS,1,4,A_Chase,S_POSS_RUN4,0,0}, // S_POSS_RUN3 - {SPR_POSS,1,4,A_Chase,S_POSS_RUN5,0,0}, // S_POSS_RUN4 - {SPR_POSS,2,4,A_Chase,S_POSS_RUN6,0,0}, // S_POSS_RUN5 - {SPR_POSS,2,4,A_Chase,S_POSS_RUN7,0,0}, // S_POSS_RUN6 - {SPR_POSS,3,4,A_Chase,S_POSS_RUN8,0,0}, // S_POSS_RUN7 - {SPR_POSS,3,4,A_Chase,S_POSS_RUN1,0,0}, // S_POSS_RUN8 - {SPR_POSS,4,10,A_FaceTarget,S_POSS_ATK2,0,0}, // S_POSS_ATK1 - {SPR_POSS,5,8,A_PosAttack,S_POSS_ATK3,0,0}, // S_POSS_ATK2 - {SPR_POSS,4,8,NULL,S_POSS_RUN1,0,0}, // S_POSS_ATK3 - {SPR_POSS,6,3,NULL,S_POSS_PAIN2,0,0}, // S_POSS_PAIN - {SPR_POSS,6,3,A_Pain,S_POSS_RUN1,0,0}, // S_POSS_PAIN2 - {SPR_POSS,7,5,NULL,S_POSS_DIE2,0,0}, // S_POSS_DIE1 - {SPR_POSS,8,5,A_Scream,S_POSS_DIE3,0,0}, // S_POSS_DIE2 - {SPR_POSS,9,5,A_Fall,S_POSS_DIE4,0,0}, // S_POSS_DIE3 - {SPR_POSS,10,5,NULL,S_POSS_DIE5,0,0}, // S_POSS_DIE4 - {SPR_POSS,11,-1,NULL,S_NULL,0,0}, // S_POSS_DIE5 - {SPR_POSS,12,5,NULL,S_POSS_XDIE2,0,0}, // S_POSS_XDIE1 - {SPR_POSS,13,5,A_XScream,S_POSS_XDIE3,0,0}, // S_POSS_XDIE2 - {SPR_POSS,14,5,A_Fall,S_POSS_XDIE4,0,0}, // S_POSS_XDIE3 - {SPR_POSS,15,5,NULL,S_POSS_XDIE5,0,0}, // S_POSS_XDIE4 - {SPR_POSS,16,5,NULL,S_POSS_XDIE6,0,0}, // S_POSS_XDIE5 - {SPR_POSS,17,5,NULL,S_POSS_XDIE7,0,0}, // S_POSS_XDIE6 - {SPR_POSS,18,5,NULL,S_POSS_XDIE8,0,0}, // S_POSS_XDIE7 - {SPR_POSS,19,5,NULL,S_POSS_XDIE9,0,0}, // S_POSS_XDIE8 - {SPR_POSS,20,-1,NULL,S_NULL,0,0}, // S_POSS_XDIE9 - {SPR_POSS,10,5,NULL,S_POSS_RAISE2,0,0}, // S_POSS_RAISE1 - {SPR_POSS,9,5,NULL,S_POSS_RAISE3,0,0}, // S_POSS_RAISE2 - {SPR_POSS,8,5,NULL,S_POSS_RAISE4,0,0}, // S_POSS_RAISE3 - {SPR_POSS,7,5,NULL,S_POSS_RUN1,0,0}, // S_POSS_RAISE4 - {SPR_SPOS,0,10,A_Look,S_SPOS_STND2,0,0}, // S_SPOS_STND - {SPR_SPOS,1,10,A_Look,S_SPOS_STND,0,0}, // S_SPOS_STND2 - {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN2,0,0}, // S_SPOS_RUN1 - {SPR_SPOS,0,3,A_Chase,S_SPOS_RUN3,0,0}, // S_SPOS_RUN2 - {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN4,0,0}, // S_SPOS_RUN3 - {SPR_SPOS,1,3,A_Chase,S_SPOS_RUN5,0,0}, // S_SPOS_RUN4 - {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN6,0,0}, // S_SPOS_RUN5 - {SPR_SPOS,2,3,A_Chase,S_SPOS_RUN7,0,0}, // S_SPOS_RUN6 - {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN8,0,0}, // S_SPOS_RUN7 - {SPR_SPOS,3,3,A_Chase,S_SPOS_RUN1,0,0}, // S_SPOS_RUN8 - {SPR_SPOS,4,10,A_FaceTarget,S_SPOS_ATK2,0,0}, // S_SPOS_ATK1 - {SPR_SPOS,32773,10,A_SPosAttack,S_SPOS_ATK3,0,0}, // S_SPOS_ATK2 - {SPR_SPOS,4,10,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_ATK3 - {SPR_SPOS,6,3,NULL,S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN - {SPR_SPOS,6,3,A_Pain,S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2 - {SPR_SPOS,7,5,NULL,S_SPOS_DIE2,0,0}, // S_SPOS_DIE1 - {SPR_SPOS,8,5,A_Scream,S_SPOS_DIE3,0,0}, // S_SPOS_DIE2 - {SPR_SPOS,9,5,A_Fall,S_SPOS_DIE4,0,0}, // S_SPOS_DIE3 - {SPR_SPOS,10,5,NULL,S_SPOS_DIE5,0,0}, // S_SPOS_DIE4 - {SPR_SPOS,11,-1,NULL,S_NULL,0,0}, // S_SPOS_DIE5 - {SPR_SPOS,12,5,NULL,S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1 - {SPR_SPOS,13,5,A_XScream,S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2 - {SPR_SPOS,14,5,A_Fall,S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3 - {SPR_SPOS,15,5,NULL,S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4 - {SPR_SPOS,16,5,NULL,S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5 - {SPR_SPOS,17,5,NULL,S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6 - {SPR_SPOS,18,5,NULL,S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7 - {SPR_SPOS,19,5,NULL,S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8 - {SPR_SPOS,20,-1,NULL,S_NULL,0,0}, // S_SPOS_XDIE9 - {SPR_SPOS,11,5,NULL,S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1 - {SPR_SPOS,10,5,NULL,S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2 - {SPR_SPOS,9,5,NULL,S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3 - {SPR_SPOS,8,5,NULL,S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4 - {SPR_SPOS,7,5,NULL,S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5 - {SPR_VILE,0,10,A_Look,S_VILE_STND2,0,0}, // S_VILE_STND - {SPR_VILE,1,10,A_Look,S_VILE_STND,0,0}, // S_VILE_STND2 - {SPR_VILE,0,2,A_VileChase,S_VILE_RUN2,0,0}, // S_VILE_RUN1 - {SPR_VILE,0,2,A_VileChase,S_VILE_RUN3,0,0}, // S_VILE_RUN2 - {SPR_VILE,1,2,A_VileChase,S_VILE_RUN4,0,0}, // S_VILE_RUN3 - {SPR_VILE,1,2,A_VileChase,S_VILE_RUN5,0,0}, // S_VILE_RUN4 - {SPR_VILE,2,2,A_VileChase,S_VILE_RUN6,0,0}, // S_VILE_RUN5 - {SPR_VILE,2,2,A_VileChase,S_VILE_RUN7,0,0}, // S_VILE_RUN6 - {SPR_VILE,3,2,A_VileChase,S_VILE_RUN8,0,0}, // S_VILE_RUN7 - {SPR_VILE,3,2,A_VileChase,S_VILE_RUN9,0,0}, // S_VILE_RUN8 - {SPR_VILE,4,2,A_VileChase,S_VILE_RUN10,0,0}, // S_VILE_RUN9 - {SPR_VILE,4,2,A_VileChase,S_VILE_RUN11,0,0}, // S_VILE_RUN10 - {SPR_VILE,5,2,A_VileChase,S_VILE_RUN12,0,0}, // S_VILE_RUN11 - {SPR_VILE,5,2,A_VileChase,S_VILE_RUN1,0,0}, // S_VILE_RUN12 - {SPR_VILE,32774,0,A_VileStart,S_VILE_ATK2,0,0}, // S_VILE_ATK1 - {SPR_VILE,32774,10,A_FaceTarget,S_VILE_ATK3,0,0}, // S_VILE_ATK2 - {SPR_VILE,32775,8,A_VileTarget,S_VILE_ATK4,0,0}, // S_VILE_ATK3 - {SPR_VILE,32776,8,A_FaceTarget,S_VILE_ATK5,0,0}, // S_VILE_ATK4 - {SPR_VILE,32777,8,A_FaceTarget,S_VILE_ATK6,0,0}, // S_VILE_ATK5 - {SPR_VILE,32778,8,A_FaceTarget,S_VILE_ATK7,0,0}, // S_VILE_ATK6 - {SPR_VILE,32779,8,A_FaceTarget,S_VILE_ATK8,0,0}, // S_VILE_ATK7 - {SPR_VILE,32780,8,A_FaceTarget,S_VILE_ATK9,0,0}, // S_VILE_ATK8 - {SPR_VILE,32781,8,A_FaceTarget,S_VILE_ATK10,0,0}, // S_VILE_ATK9 - {SPR_VILE,32782,8,A_VileAttack,S_VILE_ATK11,0,0}, // S_VILE_ATK10 - {SPR_VILE,32783,20,NULL,S_VILE_RUN1,0,0}, // S_VILE_ATK11 - {SPR_VILE,32794,10,NULL,S_VILE_HEAL2,0,0}, // S_VILE_HEAL1 - {SPR_VILE,32795,10,NULL,S_VILE_HEAL3,0,0}, // S_VILE_HEAL2 - {SPR_VILE,32796,10,NULL,S_VILE_RUN1,0,0}, // S_VILE_HEAL3 - {SPR_VILE,16,5,NULL,S_VILE_PAIN2,0,0}, // S_VILE_PAIN - {SPR_VILE,16,5,A_Pain,S_VILE_RUN1,0,0}, // S_VILE_PAIN2 - {SPR_VILE,16,7,NULL,S_VILE_DIE2,0,0}, // S_VILE_DIE1 - {SPR_VILE,17,7,A_Scream,S_VILE_DIE3,0,0}, // S_VILE_DIE2 - {SPR_VILE,18,7,A_Fall,S_VILE_DIE4,0,0}, // S_VILE_DIE3 - {SPR_VILE,19,7,NULL,S_VILE_DIE5,0,0}, // S_VILE_DIE4 - {SPR_VILE,20,7,NULL,S_VILE_DIE6,0,0}, // S_VILE_DIE5 - {SPR_VILE,21,7,NULL,S_VILE_DIE7,0,0}, // S_VILE_DIE6 - {SPR_VILE,22,7,NULL,S_VILE_DIE8,0,0}, // S_VILE_DIE7 - {SPR_VILE,23,5,NULL,S_VILE_DIE9,0,0}, // S_VILE_DIE8 - {SPR_VILE,24,5,NULL,S_VILE_DIE10,0,0}, // S_VILE_DIE9 - {SPR_VILE,25,-1,NULL,S_NULL,0,0}, // S_VILE_DIE10 - {SPR_FIRE,32768,2,A_StartFire,S_FIRE2,0,0}, // S_FIRE1 - {SPR_FIRE,32769,2,A_Fire,S_FIRE3,0,0}, // S_FIRE2 - {SPR_FIRE,32768,2,A_Fire,S_FIRE4,0,0}, // S_FIRE3 - {SPR_FIRE,32769,2,A_Fire,S_FIRE5,0,0}, // S_FIRE4 - {SPR_FIRE,32770,2,A_FireCrackle,S_FIRE6,0,0}, // S_FIRE5 - {SPR_FIRE,32769,2,A_Fire,S_FIRE7,0,0}, // S_FIRE6 - {SPR_FIRE,32770,2,A_Fire,S_FIRE8,0,0}, // S_FIRE7 - {SPR_FIRE,32769,2,A_Fire,S_FIRE9,0,0}, // S_FIRE8 - {SPR_FIRE,32770,2,A_Fire,S_FIRE10,0,0}, // S_FIRE9 - {SPR_FIRE,32771,2,A_Fire,S_FIRE11,0,0}, // S_FIRE10 - {SPR_FIRE,32770,2,A_Fire,S_FIRE12,0,0}, // S_FIRE11 - {SPR_FIRE,32771,2,A_Fire,S_FIRE13,0,0}, // S_FIRE12 - {SPR_FIRE,32770,2,A_Fire,S_FIRE14,0,0}, // S_FIRE13 - {SPR_FIRE,32771,2,A_Fire,S_FIRE15,0,0}, // S_FIRE14 - {SPR_FIRE,32772,2,A_Fire,S_FIRE16,0,0}, // S_FIRE15 - {SPR_FIRE,32771,2,A_Fire,S_FIRE17,0,0}, // S_FIRE16 - {SPR_FIRE,32772,2,A_Fire,S_FIRE18,0,0}, // S_FIRE17 - {SPR_FIRE,32771,2,A_Fire,S_FIRE19,0,0}, // S_FIRE18 - {SPR_FIRE,32772,2,A_FireCrackle,S_FIRE20,0,0}, // S_FIRE19 - {SPR_FIRE,32773,2,A_Fire,S_FIRE21,0,0}, // S_FIRE20 - {SPR_FIRE,32772,2,A_Fire,S_FIRE22,0,0}, // S_FIRE21 - {SPR_FIRE,32773,2,A_Fire,S_FIRE23,0,0}, // S_FIRE22 - {SPR_FIRE,32772,2,A_Fire,S_FIRE24,0,0}, // S_FIRE23 - {SPR_FIRE,32773,2,A_Fire,S_FIRE25,0,0}, // S_FIRE24 - {SPR_FIRE,32774,2,A_Fire,S_FIRE26,0,0}, // S_FIRE25 - {SPR_FIRE,32775,2,A_Fire,S_FIRE27,0,0}, // S_FIRE26 - {SPR_FIRE,32774,2,A_Fire,S_FIRE28,0,0}, // S_FIRE27 - {SPR_FIRE,32775,2,A_Fire,S_FIRE29,0,0}, // S_FIRE28 - {SPR_FIRE,32774,2,A_Fire,S_FIRE30,0,0}, // S_FIRE29 - {SPR_FIRE,32775,2,A_Fire,S_NULL,0,0}, // S_FIRE30 - {SPR_PUFF,1,4,NULL,S_SMOKE2,0,0}, // S_SMOKE1 - {SPR_PUFF,2,4,NULL,S_SMOKE3,0,0}, // S_SMOKE2 - {SPR_PUFF,1,4,NULL,S_SMOKE4,0,0}, // S_SMOKE3 - {SPR_PUFF,2,4,NULL,S_SMOKE5,0,0}, // S_SMOKE4 - {SPR_PUFF,3,4,NULL,S_NULL,0,0}, // S_SMOKE5 - {SPR_FATB,32768,2,A_Tracer,S_TRACER2,0,0}, // S_TRACER - {SPR_FATB,32769,2,A_Tracer,S_TRACER,0,0}, // S_TRACER2 - {SPR_FBXP,32768,8,NULL,S_TRACEEXP2,0,0}, // S_TRACEEXP1 - {SPR_FBXP,32769,6,NULL,S_TRACEEXP3,0,0}, // S_TRACEEXP2 - {SPR_FBXP,32770,4,NULL,S_NULL,0,0}, // S_TRACEEXP3 - {SPR_SKEL,0,10,A_Look,S_SKEL_STND2,0,0}, // S_SKEL_STND - {SPR_SKEL,1,10,A_Look,S_SKEL_STND,0,0}, // S_SKEL_STND2 - {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN2,0,0}, // S_SKEL_RUN1 - {SPR_SKEL,0,2,A_Chase,S_SKEL_RUN3,0,0}, // S_SKEL_RUN2 - {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN4,0,0}, // S_SKEL_RUN3 - {SPR_SKEL,1,2,A_Chase,S_SKEL_RUN5,0,0}, // S_SKEL_RUN4 - {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN6,0,0}, // S_SKEL_RUN5 - {SPR_SKEL,2,2,A_Chase,S_SKEL_RUN7,0,0}, // S_SKEL_RUN6 - {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN8,0,0}, // S_SKEL_RUN7 - {SPR_SKEL,3,2,A_Chase,S_SKEL_RUN9,0,0}, // S_SKEL_RUN8 - {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN10,0,0}, // S_SKEL_RUN9 - {SPR_SKEL,4,2,A_Chase,S_SKEL_RUN11,0,0}, // S_SKEL_RUN10 - {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN12,0,0}, // S_SKEL_RUN11 - {SPR_SKEL,5,2,A_Chase,S_SKEL_RUN1,0,0}, // S_SKEL_RUN12 - {SPR_SKEL,6,0,A_FaceTarget,S_SKEL_FIST2,0,0}, // S_SKEL_FIST1 - {SPR_SKEL,6,6,A_SkelWhoosh,S_SKEL_FIST3,0,0}, // S_SKEL_FIST2 - {SPR_SKEL,7,6,A_FaceTarget,S_SKEL_FIST4,0,0}, // S_SKEL_FIST3 - {SPR_SKEL,8,6,A_SkelFist,S_SKEL_RUN1,0,0}, // S_SKEL_FIST4 - {SPR_SKEL,32777,0,A_FaceTarget,S_SKEL_MISS2,0,0}, // S_SKEL_MISS1 - {SPR_SKEL,32777,10,A_FaceTarget,S_SKEL_MISS3,0,0}, // S_SKEL_MISS2 - {SPR_SKEL,10,10,A_SkelMissile,S_SKEL_MISS4,0,0}, // S_SKEL_MISS3 - {SPR_SKEL,10,10,A_FaceTarget,S_SKEL_RUN1,0,0}, // S_SKEL_MISS4 - {SPR_SKEL,11,5,NULL,S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN - {SPR_SKEL,11,5,A_Pain,S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2 - {SPR_SKEL,11,7,NULL,S_SKEL_DIE2,0,0}, // S_SKEL_DIE1 - {SPR_SKEL,12,7,NULL,S_SKEL_DIE3,0,0}, // S_SKEL_DIE2 - {SPR_SKEL,13,7,A_Scream,S_SKEL_DIE4,0,0}, // S_SKEL_DIE3 - {SPR_SKEL,14,7,A_Fall,S_SKEL_DIE5,0,0}, // S_SKEL_DIE4 - {SPR_SKEL,15,7,NULL,S_SKEL_DIE6,0,0}, // S_SKEL_DIE5 - {SPR_SKEL,16,-1,NULL,S_NULL,0,0}, // S_SKEL_DIE6 - {SPR_SKEL,16,5,NULL,S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1 - {SPR_SKEL,15,5,NULL,S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2 - {SPR_SKEL,14,5,NULL,S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3 - {SPR_SKEL,13,5,NULL,S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4 - {SPR_SKEL,12,5,NULL,S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5 - {SPR_SKEL,11,5,NULL,S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6 - {SPR_MANF,32768,4,NULL,S_FATSHOT2,0,0}, // S_FATSHOT1 - {SPR_MANF,32769,4,NULL,S_FATSHOT1,0,0}, // S_FATSHOT2 - {SPR_MISL,32769,8,NULL,S_FATSHOTX2,0,0}, // S_FATSHOTX1 - {SPR_MISL,32770,6,NULL,S_FATSHOTX3,0,0}, // S_FATSHOTX2 - {SPR_MISL,32771,4,NULL,S_NULL,0,0}, // S_FATSHOTX3 - {SPR_FATT,0,15,A_Look,S_FATT_STND2,0,0}, // S_FATT_STND - {SPR_FATT,1,15,A_Look,S_FATT_STND,0,0}, // S_FATT_STND2 - {SPR_FATT,0,4,A_Chase,S_FATT_RUN2,0,0}, // S_FATT_RUN1 - {SPR_FATT,0,4,A_Chase,S_FATT_RUN3,0,0}, // S_FATT_RUN2 - {SPR_FATT,1,4,A_Chase,S_FATT_RUN4,0,0}, // S_FATT_RUN3 - {SPR_FATT,1,4,A_Chase,S_FATT_RUN5,0,0}, // S_FATT_RUN4 - {SPR_FATT,2,4,A_Chase,S_FATT_RUN6,0,0}, // S_FATT_RUN5 - {SPR_FATT,2,4,A_Chase,S_FATT_RUN7,0,0}, // S_FATT_RUN6 - {SPR_FATT,3,4,A_Chase,S_FATT_RUN8,0,0}, // S_FATT_RUN7 - {SPR_FATT,3,4,A_Chase,S_FATT_RUN9,0,0}, // S_FATT_RUN8 - {SPR_FATT,4,4,A_Chase,S_FATT_RUN10,0,0}, // S_FATT_RUN9 - {SPR_FATT,4,4,A_Chase,S_FATT_RUN11,0,0}, // S_FATT_RUN10 - {SPR_FATT,5,4,A_Chase,S_FATT_RUN12,0,0}, // S_FATT_RUN11 - {SPR_FATT,5,4,A_Chase,S_FATT_RUN1,0,0}, // S_FATT_RUN12 - {SPR_FATT,6,20,A_FatRaise,S_FATT_ATK2,0,0}, // S_FATT_ATK1 - {SPR_FATT,32775,10,A_FatAttack1,S_FATT_ATK3,0,0}, // S_FATT_ATK2 - {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK4,0,0}, // S_FATT_ATK3 - {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK5,0,0}, // S_FATT_ATK4 - {SPR_FATT,32775,10,A_FatAttack2,S_FATT_ATK6,0,0}, // S_FATT_ATK5 - {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK7,0,0}, // S_FATT_ATK6 - {SPR_FATT,6,5,A_FaceTarget,S_FATT_ATK8,0,0}, // S_FATT_ATK7 - {SPR_FATT,32775,10,A_FatAttack3,S_FATT_ATK9,0,0}, // S_FATT_ATK8 - {SPR_FATT,8,5,A_FaceTarget,S_FATT_ATK10,0,0}, // S_FATT_ATK9 - {SPR_FATT,6,5,A_FaceTarget,S_FATT_RUN1,0,0}, // S_FATT_ATK10 - {SPR_FATT,9,3,NULL,S_FATT_PAIN2,0,0}, // S_FATT_PAIN - {SPR_FATT,9,3,A_Pain,S_FATT_RUN1,0,0}, // S_FATT_PAIN2 - {SPR_FATT,10,6,NULL,S_FATT_DIE2,0,0}, // S_FATT_DIE1 - {SPR_FATT,11,6,A_Scream,S_FATT_DIE3,0,0}, // S_FATT_DIE2 - {SPR_FATT,12,6,A_Fall,S_FATT_DIE4,0,0}, // S_FATT_DIE3 - {SPR_FATT,13,6,NULL,S_FATT_DIE5,0,0}, // S_FATT_DIE4 - {SPR_FATT,14,6,NULL,S_FATT_DIE6,0,0}, // S_FATT_DIE5 - {SPR_FATT,15,6,NULL,S_FATT_DIE7,0,0}, // S_FATT_DIE6 - {SPR_FATT,16,6,NULL,S_FATT_DIE8,0,0}, // S_FATT_DIE7 - {SPR_FATT,17,6,NULL,S_FATT_DIE9,0,0}, // S_FATT_DIE8 - {SPR_FATT,18,6,NULL,S_FATT_DIE10,0,0}, // S_FATT_DIE9 - {SPR_FATT,19,-1,A_BossDeath,S_NULL,0,0}, // S_FATT_DIE10 - {SPR_FATT,17,5,NULL,S_FATT_RAISE2,0,0}, // S_FATT_RAISE1 - {SPR_FATT,16,5,NULL,S_FATT_RAISE3,0,0}, // S_FATT_RAISE2 - {SPR_FATT,15,5,NULL,S_FATT_RAISE4,0,0}, // S_FATT_RAISE3 - {SPR_FATT,14,5,NULL,S_FATT_RAISE5,0,0}, // S_FATT_RAISE4 - {SPR_FATT,13,5,NULL,S_FATT_RAISE6,0,0}, // S_FATT_RAISE5 - {SPR_FATT,12,5,NULL,S_FATT_RAISE7,0,0}, // S_FATT_RAISE6 - {SPR_FATT,11,5,NULL,S_FATT_RAISE8,0,0}, // S_FATT_RAISE7 - {SPR_FATT,10,5,NULL,S_FATT_RUN1,0,0}, // S_FATT_RAISE8 - {SPR_CPOS,0,10,A_Look,S_CPOS_STND2,0,0}, // S_CPOS_STND - {SPR_CPOS,1,10,A_Look,S_CPOS_STND,0,0}, // S_CPOS_STND2 - {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN2,0,0}, // S_CPOS_RUN1 - {SPR_CPOS,0,3,A_Chase,S_CPOS_RUN3,0,0}, // S_CPOS_RUN2 - {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN4,0,0}, // S_CPOS_RUN3 - {SPR_CPOS,1,3,A_Chase,S_CPOS_RUN5,0,0}, // S_CPOS_RUN4 - {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN6,0,0}, // S_CPOS_RUN5 - {SPR_CPOS,2,3,A_Chase,S_CPOS_RUN7,0,0}, // S_CPOS_RUN6 - {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN8,0,0}, // S_CPOS_RUN7 - {SPR_CPOS,3,3,A_Chase,S_CPOS_RUN1,0,0}, // S_CPOS_RUN8 - {SPR_CPOS,4,10,A_FaceTarget,S_CPOS_ATK2,0,0}, // S_CPOS_ATK1 - {SPR_CPOS,32773,4,A_CPosAttack,S_CPOS_ATK3,0,0}, // S_CPOS_ATK2 - {SPR_CPOS,32772,4,A_CPosAttack,S_CPOS_ATK4,0,0}, // S_CPOS_ATK3 - {SPR_CPOS,5,1,A_CPosRefire,S_CPOS_ATK2,0,0}, // S_CPOS_ATK4 - {SPR_CPOS,6,3,NULL,S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN - {SPR_CPOS,6,3,A_Pain,S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2 - {SPR_CPOS,7,5,NULL,S_CPOS_DIE2,0,0}, // S_CPOS_DIE1 - {SPR_CPOS,8,5,A_Scream,S_CPOS_DIE3,0,0}, // S_CPOS_DIE2 - {SPR_CPOS,9,5,A_Fall,S_CPOS_DIE4,0,0}, // S_CPOS_DIE3 - {SPR_CPOS,10,5,NULL,S_CPOS_DIE5,0,0}, // S_CPOS_DIE4 - {SPR_CPOS,11,5,NULL,S_CPOS_DIE6,0,0}, // S_CPOS_DIE5 - {SPR_CPOS,12,5,NULL,S_CPOS_DIE7,0,0}, // S_CPOS_DIE6 - {SPR_CPOS,13,-1,NULL,S_NULL,0,0}, // S_CPOS_DIE7 - {SPR_CPOS,14,5,NULL,S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1 - {SPR_CPOS,15,5,A_XScream,S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2 - {SPR_CPOS,16,5,A_Fall,S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3 - {SPR_CPOS,17,5,NULL,S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4 - {SPR_CPOS,18,5,NULL,S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5 - {SPR_CPOS,19,-1,NULL,S_NULL,0,0}, // S_CPOS_XDIE6 - {SPR_CPOS,13,5,NULL,S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1 - {SPR_CPOS,12,5,NULL,S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2 - {SPR_CPOS,11,5,NULL,S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3 - {SPR_CPOS,10,5,NULL,S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4 - {SPR_CPOS,9,5,NULL,S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5 - {SPR_CPOS,8,5,NULL,S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6 - {SPR_CPOS,7,5,NULL,S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7 - {SPR_TROO,0,10,A_Look,S_TROO_STND2,0,0}, // S_TROO_STND - {SPR_TROO,1,10,A_Look,S_TROO_STND,0,0}, // S_TROO_STND2 - {SPR_TROO,0,3,A_Chase,S_TROO_RUN2,0,0}, // S_TROO_RUN1 - {SPR_TROO,0,3,A_Chase,S_TROO_RUN3,0,0}, // S_TROO_RUN2 - {SPR_TROO,1,3,A_Chase,S_TROO_RUN4,0,0}, // S_TROO_RUN3 - {SPR_TROO,1,3,A_Chase,S_TROO_RUN5,0,0}, // S_TROO_RUN4 - {SPR_TROO,2,3,A_Chase,S_TROO_RUN6,0,0}, // S_TROO_RUN5 - {SPR_TROO,2,3,A_Chase,S_TROO_RUN7,0,0}, // S_TROO_RUN6 - {SPR_TROO,3,3,A_Chase,S_TROO_RUN8,0,0}, // S_TROO_RUN7 - {SPR_TROO,3,3,A_Chase,S_TROO_RUN1,0,0}, // S_TROO_RUN8 - {SPR_TROO,4,8,A_FaceTarget,S_TROO_ATK2,0,0}, // S_TROO_ATK1 - {SPR_TROO,5,8,A_FaceTarget,S_TROO_ATK3,0,0}, // S_TROO_ATK2 - {SPR_TROO,6,6,A_TroopAttack,S_TROO_RUN1,0,0}, // S_TROO_ATK3 - {SPR_TROO,7,2,NULL,S_TROO_PAIN2,0,0}, // S_TROO_PAIN - {SPR_TROO,7,2,A_Pain,S_TROO_RUN1,0,0}, // S_TROO_PAIN2 - {SPR_TROO,8,8,NULL,S_TROO_DIE2,0,0}, // S_TROO_DIE1 - {SPR_TROO,9,8,A_Scream,S_TROO_DIE3,0,0}, // S_TROO_DIE2 - {SPR_TROO,10,6,NULL,S_TROO_DIE4,0,0}, // S_TROO_DIE3 - {SPR_TROO,11,6,A_Fall,S_TROO_DIE5,0,0}, // S_TROO_DIE4 - {SPR_TROO,12,-1,NULL,S_NULL,0,0}, // S_TROO_DIE5 - {SPR_TROO,13,5,NULL,S_TROO_XDIE2,0,0}, // S_TROO_XDIE1 - {SPR_TROO,14,5,A_XScream,S_TROO_XDIE3,0,0}, // S_TROO_XDIE2 - {SPR_TROO,15,5,NULL,S_TROO_XDIE4,0,0}, // S_TROO_XDIE3 - {SPR_TROO,16,5,A_Fall,S_TROO_XDIE5,0,0}, // S_TROO_XDIE4 - {SPR_TROO,17,5,NULL,S_TROO_XDIE6,0,0}, // S_TROO_XDIE5 - {SPR_TROO,18,5,NULL,S_TROO_XDIE7,0,0}, // S_TROO_XDIE6 - {SPR_TROO,19,5,NULL,S_TROO_XDIE8,0,0}, // S_TROO_XDIE7 - {SPR_TROO,20,-1,NULL,S_NULL,0,0}, // S_TROO_XDIE8 - {SPR_TROO,12,8,NULL,S_TROO_RAISE2,0,0}, // S_TROO_RAISE1 - {SPR_TROO,11,8,NULL,S_TROO_RAISE3,0,0}, // S_TROO_RAISE2 - {SPR_TROO,10,6,NULL,S_TROO_RAISE4,0,0}, // S_TROO_RAISE3 - {SPR_TROO,9,6,NULL,S_TROO_RAISE5,0,0}, // S_TROO_RAISE4 - {SPR_TROO,8,6,NULL,S_TROO_RUN1,0,0}, // S_TROO_RAISE5 - {SPR_SARG,0,10,A_Look,S_SARG_STND2,0,0}, // S_SARG_STND - {SPR_SARG,1,10,A_Look,S_SARG_STND,0,0}, // S_SARG_STND2 - {SPR_SARG,0,2,A_Chase,S_SARG_RUN2,0,0}, // S_SARG_RUN1 - {SPR_SARG,0,2,A_Chase,S_SARG_RUN3,0,0}, // S_SARG_RUN2 - {SPR_SARG,1,2,A_Chase,S_SARG_RUN4,0,0}, // S_SARG_RUN3 - {SPR_SARG,1,2,A_Chase,S_SARG_RUN5,0,0}, // S_SARG_RUN4 - {SPR_SARG,2,2,A_Chase,S_SARG_RUN6,0,0}, // S_SARG_RUN5 - {SPR_SARG,2,2,A_Chase,S_SARG_RUN7,0,0}, // S_SARG_RUN6 - {SPR_SARG,3,2,A_Chase,S_SARG_RUN8,0,0}, // S_SARG_RUN7 - {SPR_SARG,3,2,A_Chase,S_SARG_RUN1,0,0}, // S_SARG_RUN8 - {SPR_SARG,4,8,A_FaceTarget,S_SARG_ATK2,0,0}, // S_SARG_ATK1 - {SPR_SARG,5,8,A_FaceTarget,S_SARG_ATK3,0,0}, // S_SARG_ATK2 - {SPR_SARG,6,8,A_SargAttack,S_SARG_RUN1,0,0}, // S_SARG_ATK3 - {SPR_SARG,7,2,NULL,S_SARG_PAIN2,0,0}, // S_SARG_PAIN - {SPR_SARG,7,2,A_Pain,S_SARG_RUN1,0,0}, // S_SARG_PAIN2 - {SPR_SARG,8,8,NULL,S_SARG_DIE2,0,0}, // S_SARG_DIE1 - {SPR_SARG,9,8,A_Scream,S_SARG_DIE3,0,0}, // S_SARG_DIE2 - {SPR_SARG,10,4,NULL,S_SARG_DIE4,0,0}, // S_SARG_DIE3 - {SPR_SARG,11,4,A_Fall,S_SARG_DIE5,0,0}, // S_SARG_DIE4 - {SPR_SARG,12,4,NULL,S_SARG_DIE6,0,0}, // S_SARG_DIE5 - {SPR_SARG,13,-1,NULL,S_NULL,0,0}, // S_SARG_DIE6 - {SPR_SARG,13,5,NULL,S_SARG_RAISE2,0,0}, // S_SARG_RAISE1 - {SPR_SARG,12,5,NULL,S_SARG_RAISE3,0,0}, // S_SARG_RAISE2 - {SPR_SARG,11,5,NULL,S_SARG_RAISE4,0,0}, // S_SARG_RAISE3 - {SPR_SARG,10,5,NULL,S_SARG_RAISE5,0,0}, // S_SARG_RAISE4 - {SPR_SARG,9,5,NULL,S_SARG_RAISE6,0,0}, // S_SARG_RAISE5 - {SPR_SARG,8,5,NULL,S_SARG_RUN1,0,0}, // S_SARG_RAISE6 - {SPR_HEAD,0,10,A_Look,S_HEAD_STND,0,0}, // S_HEAD_STND - {SPR_HEAD,0,3,A_Chase,S_HEAD_RUN1,0,0}, // S_HEAD_RUN1 - {SPR_HEAD,1,5,A_FaceTarget,S_HEAD_ATK2,0,0}, // S_HEAD_ATK1 - {SPR_HEAD,2,5,A_FaceTarget,S_HEAD_ATK3,0,0}, // S_HEAD_ATK2 - {SPR_HEAD,32771,5,A_HeadAttack,S_HEAD_RUN1,0,0}, // S_HEAD_ATK3 - {SPR_HEAD,4,3,NULL,S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN - {SPR_HEAD,4,3,A_Pain,S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2 - {SPR_HEAD,5,6,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3 - {SPR_HEAD,6,8,NULL,S_HEAD_DIE2,0,0}, // S_HEAD_DIE1 - {SPR_HEAD,7,8,A_Scream,S_HEAD_DIE3,0,0}, // S_HEAD_DIE2 - {SPR_HEAD,8,8,NULL,S_HEAD_DIE4,0,0}, // S_HEAD_DIE3 - {SPR_HEAD,9,8,NULL,S_HEAD_DIE5,0,0}, // S_HEAD_DIE4 - {SPR_HEAD,10,8,A_Fall,S_HEAD_DIE6,0,0}, // S_HEAD_DIE5 - {SPR_HEAD,11,-1,NULL,S_NULL,0,0}, // S_HEAD_DIE6 - {SPR_HEAD,11,8,NULL,S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1 - {SPR_HEAD,10,8,NULL,S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2 - {SPR_HEAD,9,8,NULL,S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3 - {SPR_HEAD,8,8,NULL,S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4 - {SPR_HEAD,7,8,NULL,S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5 - {SPR_HEAD,6,8,NULL,S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6 - {SPR_BAL7,32768,4,NULL,S_BRBALL2,0,0}, // S_BRBALL1 - {SPR_BAL7,32769,4,NULL,S_BRBALL1,0,0}, // S_BRBALL2 - {SPR_BAL7,32770,6,NULL,S_BRBALLX2,0,0}, // S_BRBALLX1 - {SPR_BAL7,32771,6,NULL,S_BRBALLX3,0,0}, // S_BRBALLX2 - {SPR_BAL7,32772,6,NULL,S_NULL,0,0}, // S_BRBALLX3 - {SPR_BOSS,0,10,A_Look,S_BOSS_STND2,0,0}, // S_BOSS_STND - {SPR_BOSS,1,10,A_Look,S_BOSS_STND,0,0}, // S_BOSS_STND2 - {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN2,0,0}, // S_BOSS_RUN1 - {SPR_BOSS,0,3,A_Chase,S_BOSS_RUN3,0,0}, // S_BOSS_RUN2 - {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN4,0,0}, // S_BOSS_RUN3 - {SPR_BOSS,1,3,A_Chase,S_BOSS_RUN5,0,0}, // S_BOSS_RUN4 - {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN6,0,0}, // S_BOSS_RUN5 - {SPR_BOSS,2,3,A_Chase,S_BOSS_RUN7,0,0}, // S_BOSS_RUN6 - {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN8,0,0}, // S_BOSS_RUN7 - {SPR_BOSS,3,3,A_Chase,S_BOSS_RUN1,0,0}, // S_BOSS_RUN8 - {SPR_BOSS,4,8,A_FaceTarget,S_BOSS_ATK2,0,0}, // S_BOSS_ATK1 - {SPR_BOSS,5,8,A_FaceTarget,S_BOSS_ATK3,0,0}, // S_BOSS_ATK2 - {SPR_BOSS,6,8,A_BruisAttack,S_BOSS_RUN1,0,0}, // S_BOSS_ATK3 - {SPR_BOSS,7,2,NULL,S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN - {SPR_BOSS,7,2,A_Pain,S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2 - {SPR_BOSS,8,8,NULL,S_BOSS_DIE2,0,0}, // S_BOSS_DIE1 - {SPR_BOSS,9,8,A_Scream,S_BOSS_DIE3,0,0}, // S_BOSS_DIE2 - {SPR_BOSS,10,8,NULL,S_BOSS_DIE4,0,0}, // S_BOSS_DIE3 - {SPR_BOSS,11,8,A_Fall,S_BOSS_DIE5,0,0}, // S_BOSS_DIE4 - {SPR_BOSS,12,8,NULL,S_BOSS_DIE6,0,0}, // S_BOSS_DIE5 - {SPR_BOSS,13,8,NULL,S_BOSS_DIE7,0,0}, // S_BOSS_DIE6 - {SPR_BOSS,14,-1,A_BossDeath,S_NULL,0,0}, // S_BOSS_DIE7 - {SPR_BOSS,14,8,NULL,S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1 - {SPR_BOSS,13,8,NULL,S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2 - {SPR_BOSS,12,8,NULL,S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3 - {SPR_BOSS,11,8,NULL,S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4 - {SPR_BOSS,10,8,NULL,S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5 - {SPR_BOSS,9,8,NULL,S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6 - {SPR_BOSS,8,8,NULL,S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7 - {SPR_BOS2,0,10,A_Look,S_BOS2_STND2,0,0}, // S_BOS2_STND - {SPR_BOS2,1,10,A_Look,S_BOS2_STND,0,0}, // S_BOS2_STND2 - {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN2,0,0}, // S_BOS2_RUN1 - {SPR_BOS2,0,3,A_Chase,S_BOS2_RUN3,0,0}, // S_BOS2_RUN2 - {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN4,0,0}, // S_BOS2_RUN3 - {SPR_BOS2,1,3,A_Chase,S_BOS2_RUN5,0,0}, // S_BOS2_RUN4 - {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN6,0,0}, // S_BOS2_RUN5 - {SPR_BOS2,2,3,A_Chase,S_BOS2_RUN7,0,0}, // S_BOS2_RUN6 - {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN8,0,0}, // S_BOS2_RUN7 - {SPR_BOS2,3,3,A_Chase,S_BOS2_RUN1,0,0}, // S_BOS2_RUN8 - {SPR_BOS2,4,8,A_FaceTarget,S_BOS2_ATK2,0,0}, // S_BOS2_ATK1 - {SPR_BOS2,5,8,A_FaceTarget,S_BOS2_ATK3,0,0}, // S_BOS2_ATK2 - {SPR_BOS2,6,8,A_BruisAttack,S_BOS2_RUN1,0,0}, // S_BOS2_ATK3 - {SPR_BOS2,7,2,NULL,S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN - {SPR_BOS2,7,2,A_Pain,S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2 - {SPR_BOS2,8,8,NULL,S_BOS2_DIE2,0,0}, // S_BOS2_DIE1 - {SPR_BOS2,9,8,A_Scream,S_BOS2_DIE3,0,0}, // S_BOS2_DIE2 - {SPR_BOS2,10,8,NULL,S_BOS2_DIE4,0,0}, // S_BOS2_DIE3 - {SPR_BOS2,11,8,A_Fall,S_BOS2_DIE5,0,0}, // S_BOS2_DIE4 - {SPR_BOS2,12,8,NULL,S_BOS2_DIE6,0,0}, // S_BOS2_DIE5 - {SPR_BOS2,13,8,NULL,S_BOS2_DIE7,0,0}, // S_BOS2_DIE6 - {SPR_BOS2,14,-1,NULL,S_NULL,0,0}, // S_BOS2_DIE7 - {SPR_BOS2,14,8,NULL,S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1 - {SPR_BOS2,13,8,NULL,S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2 - {SPR_BOS2,12,8,NULL,S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3 - {SPR_BOS2,11,8,NULL,S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4 - {SPR_BOS2,10,8,NULL,S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5 - {SPR_BOS2,9,8,NULL,S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6 - {SPR_BOS2,8,8,NULL,S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7 - {SPR_SKUL,32768,10,A_Look,S_SKULL_STND2,0,0}, // S_SKULL_STND - {SPR_SKUL,32769,10,A_Look,S_SKULL_STND,0,0}, // S_SKULL_STND2 - {SPR_SKUL,32768,6,A_Chase,S_SKULL_RUN2,0,0}, // S_SKULL_RUN1 - {SPR_SKUL,32769,6,A_Chase,S_SKULL_RUN1,0,0}, // S_SKULL_RUN2 - {SPR_SKUL,32770,10,A_FaceTarget,S_SKULL_ATK2,0,0}, // S_SKULL_ATK1 - {SPR_SKUL,32771,4,A_SkullAttack,S_SKULL_ATK3,0,0}, // S_SKULL_ATK2 - {SPR_SKUL,32770,4,NULL,S_SKULL_ATK4,0,0}, // S_SKULL_ATK3 - {SPR_SKUL,32771,4,NULL,S_SKULL_ATK3,0,0}, // S_SKULL_ATK4 - {SPR_SKUL,32772,3,NULL,S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN - {SPR_SKUL,32772,3,A_Pain,S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2 - {SPR_SKUL,32773,6,NULL,S_SKULL_DIE2,0,0}, // S_SKULL_DIE1 - {SPR_SKUL,32774,6,A_Scream,S_SKULL_DIE3,0,0}, // S_SKULL_DIE2 - {SPR_SKUL,32775,6,NULL,S_SKULL_DIE4,0,0}, // S_SKULL_DIE3 - {SPR_SKUL,32776,6,A_Fall,S_SKULL_DIE5,0,0}, // S_SKULL_DIE4 - {SPR_SKUL,9,6,NULL,S_SKULL_DIE6,0,0}, // S_SKULL_DIE5 - {SPR_SKUL,10,6,NULL,S_NULL,0,0}, // S_SKULL_DIE6 - {SPR_SPID,0,10,A_Look,S_SPID_STND2,0,0}, // S_SPID_STND - {SPR_SPID,1,10,A_Look,S_SPID_STND,0,0}, // S_SPID_STND2 - {SPR_SPID,0,3,A_Metal,S_SPID_RUN2,0,0}, // S_SPID_RUN1 - {SPR_SPID,0,3,A_Chase,S_SPID_RUN3,0,0}, // S_SPID_RUN2 - {SPR_SPID,1,3,A_Chase,S_SPID_RUN4,0,0}, // S_SPID_RUN3 - {SPR_SPID,1,3,A_Chase,S_SPID_RUN5,0,0}, // S_SPID_RUN4 - {SPR_SPID,2,3,A_Metal,S_SPID_RUN6,0,0}, // S_SPID_RUN5 - {SPR_SPID,2,3,A_Chase,S_SPID_RUN7,0,0}, // S_SPID_RUN6 - {SPR_SPID,3,3,A_Chase,S_SPID_RUN8,0,0}, // S_SPID_RUN7 - {SPR_SPID,3,3,A_Chase,S_SPID_RUN9,0,0}, // S_SPID_RUN8 - {SPR_SPID,4,3,A_Metal,S_SPID_RUN10,0,0}, // S_SPID_RUN9 - {SPR_SPID,4,3,A_Chase,S_SPID_RUN11,0,0}, // S_SPID_RUN10 - {SPR_SPID,5,3,A_Chase,S_SPID_RUN12,0,0}, // S_SPID_RUN11 - {SPR_SPID,5,3,A_Chase,S_SPID_RUN1,0,0}, // S_SPID_RUN12 - {SPR_SPID,32768,20,A_FaceTarget,S_SPID_ATK2,0,0}, // S_SPID_ATK1 - {SPR_SPID,32774,4,A_SPosAttack,S_SPID_ATK3,0,0}, // S_SPID_ATK2 - {SPR_SPID,32775,4,A_SPosAttack,S_SPID_ATK4,0,0}, // S_SPID_ATK3 - {SPR_SPID,32775,1,A_SpidRefire,S_SPID_ATK2,0,0}, // S_SPID_ATK4 - {SPR_SPID,8,3,NULL,S_SPID_PAIN2,0,0}, // S_SPID_PAIN - {SPR_SPID,8,3,A_Pain,S_SPID_RUN1,0,0}, // S_SPID_PAIN2 - {SPR_SPID,9,20,A_Scream,S_SPID_DIE2,0,0}, // S_SPID_DIE1 - {SPR_SPID,10,10,A_Fall,S_SPID_DIE3,0,0}, // S_SPID_DIE2 - {SPR_SPID,11,10,NULL,S_SPID_DIE4,0,0}, // S_SPID_DIE3 - {SPR_SPID,12,10,NULL,S_SPID_DIE5,0,0}, // S_SPID_DIE4 - {SPR_SPID,13,10,NULL,S_SPID_DIE6,0,0}, // S_SPID_DIE5 - {SPR_SPID,14,10,NULL,S_SPID_DIE7,0,0}, // S_SPID_DIE6 - {SPR_SPID,15,10,NULL,S_SPID_DIE8,0,0}, // S_SPID_DIE7 - {SPR_SPID,16,10,NULL,S_SPID_DIE9,0,0}, // S_SPID_DIE8 - {SPR_SPID,17,10,NULL,S_SPID_DIE10,0,0}, // S_SPID_DIE9 - {SPR_SPID,18,30,NULL,S_SPID_DIE11,0,0}, // S_SPID_DIE10 - {SPR_SPID,18,-1,A_BossDeath,S_NULL,0,0}, // S_SPID_DIE11 - {SPR_BSPI,0,10,A_Look,S_BSPI_STND2,0,0}, // S_BSPI_STND - {SPR_BSPI,1,10,A_Look,S_BSPI_STND,0,0}, // S_BSPI_STND2 - {SPR_BSPI,0,20,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT - {SPR_BSPI,0,3,A_BabyMetal,S_BSPI_RUN2,0,0}, // S_BSPI_RUN1 - {SPR_BSPI,0,3,A_Chase,S_BSPI_RUN3,0,0}, // S_BSPI_RUN2 - {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN4,0,0}, // S_BSPI_RUN3 - {SPR_BSPI,1,3,A_Chase,S_BSPI_RUN5,0,0}, // S_BSPI_RUN4 - {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN6,0,0}, // S_BSPI_RUN5 - {SPR_BSPI,2,3,A_Chase,S_BSPI_RUN7,0,0}, // S_BSPI_RUN6 - {SPR_BSPI,3,3,A_BabyMetal,S_BSPI_RUN8,0,0}, // S_BSPI_RUN7 - {SPR_BSPI,3,3,A_Chase,S_BSPI_RUN9,0,0}, // S_BSPI_RUN8 - {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN10,0,0}, // S_BSPI_RUN9 - {SPR_BSPI,4,3,A_Chase,S_BSPI_RUN11,0,0}, // S_BSPI_RUN10 - {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN12,0,0}, // S_BSPI_RUN11 - {SPR_BSPI,5,3,A_Chase,S_BSPI_RUN1,0,0}, // S_BSPI_RUN12 - {SPR_BSPI,32768,20,A_FaceTarget,S_BSPI_ATK2,0,0}, // S_BSPI_ATK1 - {SPR_BSPI,32774,4,A_BspiAttack,S_BSPI_ATK3,0,0}, // S_BSPI_ATK2 - {SPR_BSPI,32775,4,NULL,S_BSPI_ATK4,0,0}, // S_BSPI_ATK3 - {SPR_BSPI,32775,1,A_SpidRefire,S_BSPI_ATK2,0,0}, // S_BSPI_ATK4 - {SPR_BSPI,8,3,NULL,S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN - {SPR_BSPI,8,3,A_Pain,S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2 - {SPR_BSPI,9,20,A_Scream,S_BSPI_DIE2,0,0}, // S_BSPI_DIE1 - {SPR_BSPI,10,7,A_Fall,S_BSPI_DIE3,0,0}, // S_BSPI_DIE2 - {SPR_BSPI,11,7,NULL,S_BSPI_DIE4,0,0}, // S_BSPI_DIE3 - {SPR_BSPI,12,7,NULL,S_BSPI_DIE5,0,0}, // S_BSPI_DIE4 - {SPR_BSPI,13,7,NULL,S_BSPI_DIE6,0,0}, // S_BSPI_DIE5 - {SPR_BSPI,14,7,NULL,S_BSPI_DIE7,0,0}, // S_BSPI_DIE6 - {SPR_BSPI,15,-1,A_BossDeath,S_NULL,0,0}, // S_BSPI_DIE7 - {SPR_BSPI,15,5,NULL,S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1 - {SPR_BSPI,14,5,NULL,S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2 - {SPR_BSPI,13,5,NULL,S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3 - {SPR_BSPI,12,5,NULL,S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4 - {SPR_BSPI,11,5,NULL,S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5 - {SPR_BSPI,10,5,NULL,S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6 - {SPR_BSPI,9,5,NULL,S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7 - {SPR_APLS,32768,5,NULL,S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ - {SPR_APLS,32769,5,NULL,S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2 - {SPR_APBX,32768,5,NULL,S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX - {SPR_APBX,32769,5,NULL,S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2 - {SPR_APBX,32770,5,NULL,S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3 - {SPR_APBX,32771,5,NULL,S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4 - {SPR_APBX,32772,5,NULL,S_NULL,0,0}, // S_ARACH_PLEX5 - {SPR_CYBR,0,10,A_Look,S_CYBER_STND2,0,0}, // S_CYBER_STND - {SPR_CYBR,1,10,A_Look,S_CYBER_STND,0,0}, // S_CYBER_STND2 - {SPR_CYBR,0,3,A_Hoof,S_CYBER_RUN2,0,0}, // S_CYBER_RUN1 - {SPR_CYBR,0,3,A_Chase,S_CYBER_RUN3,0,0}, // S_CYBER_RUN2 - {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN4,0,0}, // S_CYBER_RUN3 - {SPR_CYBR,1,3,A_Chase,S_CYBER_RUN5,0,0}, // S_CYBER_RUN4 - {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN6,0,0}, // S_CYBER_RUN5 - {SPR_CYBR,2,3,A_Chase,S_CYBER_RUN7,0,0}, // S_CYBER_RUN6 - {SPR_CYBR,3,3,A_Metal,S_CYBER_RUN8,0,0}, // S_CYBER_RUN7 - {SPR_CYBR,3,3,A_Chase,S_CYBER_RUN1,0,0}, // S_CYBER_RUN8 - {SPR_CYBR,4,6,A_FaceTarget,S_CYBER_ATK2,0,0}, // S_CYBER_ATK1 - {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK3,0,0}, // S_CYBER_ATK2 - {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK4,0,0}, // S_CYBER_ATK3 - {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_ATK5,0,0}, // S_CYBER_ATK4 - {SPR_CYBR,4,12,A_FaceTarget,S_CYBER_ATK6,0,0}, // S_CYBER_ATK5 - {SPR_CYBR,5,12,A_CyberAttack,S_CYBER_RUN1,0,0}, // S_CYBER_ATK6 - {SPR_CYBR,6,10,A_Pain,S_CYBER_RUN1,0,0}, // S_CYBER_PAIN - {SPR_CYBR,7,10,NULL,S_CYBER_DIE2,0,0}, // S_CYBER_DIE1 - {SPR_CYBR,8,10,A_Scream,S_CYBER_DIE3,0,0}, // S_CYBER_DIE2 - {SPR_CYBR,9,10,NULL,S_CYBER_DIE4,0,0}, // S_CYBER_DIE3 - {SPR_CYBR,10,10,NULL,S_CYBER_DIE5,0,0}, // S_CYBER_DIE4 - {SPR_CYBR,11,10,NULL,S_CYBER_DIE6,0,0}, // S_CYBER_DIE5 - {SPR_CYBR,12,10,A_Fall,S_CYBER_DIE7,0,0}, // S_CYBER_DIE6 - {SPR_CYBR,13,10,NULL,S_CYBER_DIE8,0,0}, // S_CYBER_DIE7 - {SPR_CYBR,14,10,NULL,S_CYBER_DIE9,0,0}, // S_CYBER_DIE8 - {SPR_CYBR,15,30,NULL,S_CYBER_DIE10,0,0}, // S_CYBER_DIE9 - {SPR_CYBR,15,-1,A_BossDeath,S_NULL,0,0}, // S_CYBER_DIE10 - {SPR_PAIN,0,10,A_Look,S_PAIN_STND,0,0}, // S_PAIN_STND - {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN2,0,0}, // S_PAIN_RUN1 - {SPR_PAIN,0,3,A_Chase,S_PAIN_RUN3,0,0}, // S_PAIN_RUN2 - {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN4,0,0}, // S_PAIN_RUN3 - {SPR_PAIN,1,3,A_Chase,S_PAIN_RUN5,0,0}, // S_PAIN_RUN4 - {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN6,0,0}, // S_PAIN_RUN5 - {SPR_PAIN,2,3,A_Chase,S_PAIN_RUN1,0,0}, // S_PAIN_RUN6 - {SPR_PAIN,3,5,A_FaceTarget,S_PAIN_ATK2,0,0}, // S_PAIN_ATK1 - {SPR_PAIN,4,5,A_FaceTarget,S_PAIN_ATK3,0,0}, // S_PAIN_ATK2 - {SPR_PAIN,32773,5,A_FaceTarget,S_PAIN_ATK4,0,0}, // S_PAIN_ATK3 - {SPR_PAIN,32773,0,A_PainAttack,S_PAIN_RUN1,0,0}, // S_PAIN_ATK4 - {SPR_PAIN,6,6,NULL,S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN - {SPR_PAIN,6,6,A_Pain,S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2 - {SPR_PAIN,32775,8,NULL,S_PAIN_DIE2,0,0}, // S_PAIN_DIE1 - {SPR_PAIN,32776,8,A_Scream,S_PAIN_DIE3,0,0}, // S_PAIN_DIE2 - {SPR_PAIN,32777,8,NULL,S_PAIN_DIE4,0,0}, // S_PAIN_DIE3 - {SPR_PAIN,32778,8,NULL,S_PAIN_DIE5,0,0}, // S_PAIN_DIE4 - {SPR_PAIN,32779,8,A_PainDie,S_PAIN_DIE6,0,0}, // S_PAIN_DIE5 - {SPR_PAIN,32780,8,NULL,S_NULL,0,0}, // S_PAIN_DIE6 - {SPR_PAIN,12,8,NULL,S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1 - {SPR_PAIN,11,8,NULL,S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2 - {SPR_PAIN,10,8,NULL,S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3 - {SPR_PAIN,9,8,NULL,S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4 - {SPR_PAIN,8,8,NULL,S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5 - {SPR_PAIN,7,8,NULL,S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6 - {SPR_SSWV,0,10,A_Look,S_SSWV_STND2,0,0}, // S_SSWV_STND - {SPR_SSWV,1,10,A_Look,S_SSWV_STND,0,0}, // S_SSWV_STND2 - {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN2,0,0}, // S_SSWV_RUN1 - {SPR_SSWV,0,3,A_Chase,S_SSWV_RUN3,0,0}, // S_SSWV_RUN2 - {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN4,0,0}, // S_SSWV_RUN3 - {SPR_SSWV,1,3,A_Chase,S_SSWV_RUN5,0,0}, // S_SSWV_RUN4 - {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN6,0,0}, // S_SSWV_RUN5 - {SPR_SSWV,2,3,A_Chase,S_SSWV_RUN7,0,0}, // S_SSWV_RUN6 - {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN8,0,0}, // S_SSWV_RUN7 - {SPR_SSWV,3,3,A_Chase,S_SSWV_RUN1,0,0}, // S_SSWV_RUN8 - {SPR_SSWV,4,10,A_FaceTarget,S_SSWV_ATK2,0,0}, // S_SSWV_ATK1 - {SPR_SSWV,5,10,A_FaceTarget,S_SSWV_ATK3,0,0}, // S_SSWV_ATK2 - {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK4,0,0}, // S_SSWV_ATK3 - {SPR_SSWV,5,6,A_FaceTarget,S_SSWV_ATK5,0,0}, // S_SSWV_ATK4 - {SPR_SSWV,32774,4,A_CPosAttack,S_SSWV_ATK6,0,0}, // S_SSWV_ATK5 - {SPR_SSWV,5,1,A_CPosRefire,S_SSWV_ATK2,0,0}, // S_SSWV_ATK6 - {SPR_SSWV,7,3,NULL,S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN - {SPR_SSWV,7,3,A_Pain,S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2 - {SPR_SSWV,8,5,NULL,S_SSWV_DIE2,0,0}, // S_SSWV_DIE1 - {SPR_SSWV,9,5,A_Scream,S_SSWV_DIE3,0,0}, // S_SSWV_DIE2 - {SPR_SSWV,10,5,A_Fall,S_SSWV_DIE4,0,0}, // S_SSWV_DIE3 - {SPR_SSWV,11,5,NULL,S_SSWV_DIE5,0,0}, // S_SSWV_DIE4 - {SPR_SSWV,12,-1,NULL,S_NULL,0,0}, // S_SSWV_DIE5 - {SPR_SSWV,13,5,NULL,S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1 - {SPR_SSWV,14,5,A_XScream,S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2 - {SPR_SSWV,15,5,A_Fall,S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3 - {SPR_SSWV,16,5,NULL,S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4 - {SPR_SSWV,17,5,NULL,S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5 - {SPR_SSWV,18,5,NULL,S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6 - {SPR_SSWV,19,5,NULL,S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7 - {SPR_SSWV,20,5,NULL,S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8 - {SPR_SSWV,21,-1,NULL,S_NULL,0,0}, // S_SSWV_XDIE9 - {SPR_SSWV,12,5,NULL,S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1 - {SPR_SSWV,11,5,NULL,S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2 - {SPR_SSWV,10,5,NULL,S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3 - {SPR_SSWV,9,5,NULL,S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4 - {SPR_SSWV,8,5,NULL,S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5 - {SPR_KEEN,0,-1,NULL,S_KEENSTND,0,0}, // S_KEENSTND - {SPR_KEEN,0,6,NULL,S_COMMKEEN2,0,0}, // S_COMMKEEN - {SPR_KEEN,1,6,NULL,S_COMMKEEN3,0,0}, // S_COMMKEEN2 - {SPR_KEEN,2,6,A_Scream,S_COMMKEEN4,0,0}, // S_COMMKEEN3 - {SPR_KEEN,3,6,NULL,S_COMMKEEN5,0,0}, // S_COMMKEEN4 - {SPR_KEEN,4,6,NULL,S_COMMKEEN6,0,0}, // S_COMMKEEN5 - {SPR_KEEN,5,6,NULL,S_COMMKEEN7,0,0}, // S_COMMKEEN6 - {SPR_KEEN,6,6,NULL,S_COMMKEEN8,0,0}, // S_COMMKEEN7 - {SPR_KEEN,7,6,NULL,S_COMMKEEN9,0,0}, // S_COMMKEEN8 - {SPR_KEEN,8,6,NULL,S_COMMKEEN10,0,0}, // S_COMMKEEN9 - {SPR_KEEN,9,6,NULL,S_COMMKEEN11,0,0}, // S_COMMKEEN10 - {SPR_KEEN,10,6,A_KeenDie,S_COMMKEEN12,0,0},// S_COMMKEEN11 - {SPR_KEEN,11,-1,NULL,S_NULL,0,0}, // S_COMMKEEN12 - {SPR_KEEN,12,4,NULL,S_KEENPAIN2,0,0}, // S_KEENPAIN - {SPR_KEEN,12,8,A_Pain,S_KEENSTND,0,0}, // S_KEENPAIN2 - {SPR_BBRN,0,-1,NULL,S_NULL,0,0}, // S_BRAIN - {SPR_BBRN,1,36,A_BrainPain,S_BRAIN,0,0}, // S_BRAIN_PAIN - {SPR_BBRN,0,100,A_BrainScream,S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1 - {SPR_BBRN,0,10,NULL,S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2 - {SPR_BBRN,0,10,NULL,S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3 - {SPR_BBRN,0,-1,A_BrainDie,S_NULL,0,0}, // S_BRAIN_DIE4 - {SPR_SSWV,0,10,A_Look,S_BRAINEYE,0,0}, // S_BRAINEYE - {SPR_SSWV,0,181,A_BrainAwake,S_BRAINEYE1,0,0}, // S_BRAINEYESEE - {SPR_SSWV,0,150,A_BrainSpit,S_BRAINEYE1,0,0}, // S_BRAINEYE1 - {SPR_BOSF,32768,3,A_SpawnSound,S_SPAWN2,0,0}, // S_SPAWN1 - {SPR_BOSF,32769,3,A_SpawnFly,S_SPAWN3,0,0}, // S_SPAWN2 - {SPR_BOSF,32770,3,A_SpawnFly,S_SPAWN4,0,0}, // S_SPAWN3 - {SPR_BOSF,32771,3,A_SpawnFly,S_SPAWN1,0,0}, // S_SPAWN4 - {SPR_FIRE,32768,4,A_Fire,S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1 - {SPR_FIRE,32769,4,A_Fire,S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2 - {SPR_FIRE,32770,4,A_Fire,S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3 - {SPR_FIRE,32771,4,A_Fire,S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4 - {SPR_FIRE,32772,4,A_Fire,S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5 - {SPR_FIRE,32773,4,A_Fire,S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6 - {SPR_FIRE,32774,4,A_Fire,S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7 - {SPR_FIRE,32775,4,A_Fire,S_NULL,0,0}, // S_SPAWNFIRE8 - {SPR_MISL,32769,10,NULL,S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1 - {SPR_MISL,32770,10,NULL,S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2 - {SPR_MISL,32771,10,A_BrainExplode,S_NULL,0,0}, // S_BRAINEXPLODE3 - {SPR_ARM1,0,6,NULL,S_ARM1A,0,0}, // S_ARM1 - {SPR_ARM1,32769,7,NULL,S_ARM1,0,0}, // S_ARM1A - {SPR_ARM2,0,6,NULL,S_ARM2A,0,0}, // S_ARM2 - {SPR_ARM2,32769,6,NULL,S_ARM2,0,0}, // S_ARM2A - {SPR_BAR1,0,6,NULL,S_BAR2,0,0}, // S_BAR1 - {SPR_BAR1,1,6,NULL,S_BAR1,0,0}, // S_BAR2 - {SPR_BEXP,32768,5,NULL,S_BEXP2,0,0}, // S_BEXP - {SPR_BEXP,32769,5,A_Scream,S_BEXP3,0,0}, // S_BEXP2 - {SPR_BEXP,32770,5,NULL,S_BEXP4,0,0}, // S_BEXP3 - {SPR_BEXP,32771,10,A_Explode,S_BEXP5,0,0}, // S_BEXP4 - {SPR_BEXP,32772,10,NULL,S_NULL,0,0}, // S_BEXP5 - {SPR_FCAN,32768,4,NULL,S_BBAR2,0,0}, // S_BBAR1 - {SPR_FCAN,32769,4,NULL,S_BBAR3,0,0}, // S_BBAR2 - {SPR_FCAN,32770,4,NULL,S_BBAR1,0,0}, // S_BBAR3 - {SPR_BON1,0,6,NULL,S_BON1A,0,0}, // S_BON1 - {SPR_BON1,1,6,NULL,S_BON1B,0,0}, // S_BON1A - {SPR_BON1,2,6,NULL,S_BON1C,0,0}, // S_BON1B - {SPR_BON1,3,6,NULL,S_BON1D,0,0}, // S_BON1C - {SPR_BON1,2,6,NULL,S_BON1E,0,0}, // S_BON1D - {SPR_BON1,1,6,NULL,S_BON1,0,0}, // S_BON1E - {SPR_BON2,0,6,NULL,S_BON2A,0,0}, // S_BON2 - {SPR_BON2,1,6,NULL,S_BON2B,0,0}, // S_BON2A - {SPR_BON2,2,6,NULL,S_BON2C,0,0}, // S_BON2B - {SPR_BON2,3,6,NULL,S_BON2D,0,0}, // S_BON2C - {SPR_BON2,2,6,NULL,S_BON2E,0,0}, // S_BON2D - {SPR_BON2,1,6,NULL,S_BON2,0,0}, // S_BON2E - {SPR_BKEY,0,10,NULL,S_BKEY2,0,0}, // S_BKEY - {SPR_BKEY,32769,10,NULL,S_BKEY,0,0}, // S_BKEY2 - {SPR_RKEY,0,10,NULL,S_RKEY2,0,0}, // S_RKEY - {SPR_RKEY,32769,10,NULL,S_RKEY,0,0}, // S_RKEY2 - {SPR_YKEY,0,10,NULL,S_YKEY2,0,0}, // S_YKEY - {SPR_YKEY,32769,10,NULL,S_YKEY,0,0}, // S_YKEY2 - {SPR_BSKU,0,10,NULL,S_BSKULL2,0,0}, // S_BSKULL - {SPR_BSKU,32769,10,NULL,S_BSKULL,0,0}, // S_BSKULL2 - {SPR_RSKU,0,10,NULL,S_RSKULL2,0,0}, // S_RSKULL - {SPR_RSKU,32769,10,NULL,S_RSKULL,0,0}, // S_RSKULL2 - {SPR_YSKU,0,10,NULL,S_YSKULL2,0,0}, // S_YSKULL - {SPR_YSKU,32769,10,NULL,S_YSKULL,0,0}, // S_YSKULL2 - {SPR_STIM,0,-1,NULL,S_NULL,0,0}, // S_STIM - {SPR_MEDI,0,-1,NULL,S_NULL,0,0}, // S_MEDI - {SPR_SOUL,32768,6,NULL,S_SOUL2,0,0}, // S_SOUL - {SPR_SOUL,32769,6,NULL,S_SOUL3,0,0}, // S_SOUL2 - {SPR_SOUL,32770,6,NULL,S_SOUL4,0,0}, // S_SOUL3 - {SPR_SOUL,32771,6,NULL,S_SOUL5,0,0}, // S_SOUL4 - {SPR_SOUL,32770,6,NULL,S_SOUL6,0,0}, // S_SOUL5 - {SPR_SOUL,32769,6,NULL,S_SOUL,0,0}, // S_SOUL6 - {SPR_PINV,32768,6,NULL,S_PINV2,0,0}, // S_PINV - {SPR_PINV,32769,6,NULL,S_PINV3,0,0}, // S_PINV2 - {SPR_PINV,32770,6,NULL,S_PINV4,0,0}, // S_PINV3 - {SPR_PINV,32771,6,NULL,S_PINV,0,0}, // S_PINV4 - {SPR_PSTR,32768,-1,NULL,S_NULL,0,0}, // S_PSTR - {SPR_PINS,32768,6,NULL,S_PINS2,0,0}, // S_PINS - {SPR_PINS,32769,6,NULL,S_PINS3,0,0}, // S_PINS2 - {SPR_PINS,32770,6,NULL,S_PINS4,0,0}, // S_PINS3 - {SPR_PINS,32771,6,NULL,S_PINS,0,0}, // S_PINS4 - {SPR_MEGA,32768,6,NULL,S_MEGA2,0,0}, // S_MEGA - {SPR_MEGA,32769,6,NULL,S_MEGA3,0,0}, // S_MEGA2 - {SPR_MEGA,32770,6,NULL,S_MEGA4,0,0}, // S_MEGA3 - {SPR_MEGA,32771,6,NULL,S_MEGA,0,0}, // S_MEGA4 - {SPR_SUIT,32768,-1,NULL,S_NULL,0,0}, // S_SUIT - {SPR_PMAP,32768,6,NULL,S_PMAP2,0,0}, // S_PMAP - {SPR_PMAP,32769,6,NULL,S_PMAP3,0,0}, // S_PMAP2 - {SPR_PMAP,32770,6,NULL,S_PMAP4,0,0}, // S_PMAP3 - {SPR_PMAP,32771,6,NULL,S_PMAP5,0,0}, // S_PMAP4 - {SPR_PMAP,32770,6,NULL,S_PMAP6,0,0}, // S_PMAP5 - {SPR_PMAP,32769,6,NULL,S_PMAP,0,0}, // S_PMAP6 - {SPR_PVIS,32768,6,NULL,S_PVIS2,0,0}, // S_PVIS - {SPR_PVIS,1,6,NULL,S_PVIS,0,0}, // S_PVIS2 - {SPR_CLIP,0,-1,NULL,S_NULL,0,0}, // S_CLIP - {SPR_AMMO,0,-1,NULL,S_NULL,0,0}, // S_AMMO - {SPR_ROCK,0,-1,NULL,S_NULL,0,0}, // S_ROCK - {SPR_BROK,0,-1,NULL,S_NULL,0,0}, // S_BROK - {SPR_CELL,0,-1,NULL,S_NULL,0,0}, // S_CELL - {SPR_CELP,0,-1,NULL,S_NULL,0,0}, // S_CELP - {SPR_SHEL,0,-1,NULL,S_NULL,0,0}, // S_SHEL - {SPR_SBOX,0,-1,NULL,S_NULL,0,0}, // S_SBOX - {SPR_BPAK,0,-1,NULL,S_NULL,0,0}, // S_BPAK - {SPR_BFUG,0,-1,NULL,S_NULL,0,0}, // S_BFUG - {SPR_MGUN,0,-1,NULL,S_NULL,0,0}, // S_MGUN - {SPR_CSAW,0,-1,NULL,S_NULL,0,0}, // S_CSAW - {SPR_LAUN,0,-1,NULL,S_NULL,0,0}, // S_LAUN - {SPR_PLAS,0,-1,NULL,S_NULL,0,0}, // S_PLAS - {SPR_SHOT,0,-1,NULL,S_NULL,0,0}, // S_SHOT - {SPR_SGN2,0,-1,NULL,S_NULL,0,0}, // S_SHOT2 - {SPR_COLU,32768,-1,NULL,S_NULL,0,0}, // S_COLU - {SPR_SMT2,0,-1,NULL,S_NULL,0,0}, // S_STALAG - {SPR_GOR1,0,10,NULL,S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH - {SPR_GOR1,1,15,NULL,S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2 - {SPR_GOR1,2,8,NULL,S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3 - {SPR_GOR1,1,6,NULL,S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4 - {SPR_PLAY,13,-1,NULL,S_NULL,0,0}, // S_DEADTORSO - {SPR_PLAY,18,-1,NULL,S_NULL,0,0}, // S_DEADBOTTOM - {SPR_POL2,0,-1,NULL,S_NULL,0,0}, // S_HEADSONSTICK - {SPR_POL5,0,-1,NULL,S_NULL,0,0}, // S_GIBS - {SPR_POL4,0,-1,NULL,S_NULL,0,0}, // S_HEADONASTICK - {SPR_POL3,32768,6,NULL,S_HEADCANDLES2,0,0}, // S_HEADCANDLES - {SPR_POL3,32769,6,NULL,S_HEADCANDLES,0,0}, // S_HEADCANDLES2 - {SPR_POL1,0,-1,NULL,S_NULL,0,0}, // S_DEADSTICK - {SPR_POL6,0,6,NULL,S_LIVESTICK2,0,0}, // S_LIVESTICK - {SPR_POL6,1,8,NULL,S_LIVESTICK,0,0}, // S_LIVESTICK2 - {SPR_GOR2,0,-1,NULL,S_NULL,0,0}, // S_MEAT2 - {SPR_GOR3,0,-1,NULL,S_NULL,0,0}, // S_MEAT3 - {SPR_GOR4,0,-1,NULL,S_NULL,0,0}, // S_MEAT4 - {SPR_GOR5,0,-1,NULL,S_NULL,0,0}, // S_MEAT5 - {SPR_SMIT,0,-1,NULL,S_NULL,0,0}, // S_STALAGTITE - {SPR_COL1,0,-1,NULL,S_NULL,0,0}, // S_TALLGRNCOL - {SPR_COL2,0,-1,NULL,S_NULL,0,0}, // S_SHRTGRNCOL - {SPR_COL3,0,-1,NULL,S_NULL,0,0}, // S_TALLREDCOL - {SPR_COL4,0,-1,NULL,S_NULL,0,0}, // S_SHRTREDCOL - {SPR_CAND,32768,-1,NULL,S_NULL,0,0}, // S_CANDLESTIK - {SPR_CBRA,32768,-1,NULL,S_NULL,0,0}, // S_CANDELABRA - {SPR_COL6,0,-1,NULL,S_NULL,0,0}, // S_SKULLCOL - {SPR_TRE1,0,-1,NULL,S_NULL,0,0}, // S_TORCHTREE - {SPR_TRE2,0,-1,NULL,S_NULL,0,0}, // S_BIGTREE - {SPR_ELEC,0,-1,NULL,S_NULL,0,0}, // S_TECHPILLAR - {SPR_CEYE,32768,6,NULL,S_EVILEYE2,0,0}, // S_EVILEYE - {SPR_CEYE,32769,6,NULL,S_EVILEYE3,0,0}, // S_EVILEYE2 - {SPR_CEYE,32770,6,NULL,S_EVILEYE4,0,0}, // S_EVILEYE3 - {SPR_CEYE,32769,6,NULL,S_EVILEYE,0,0}, // S_EVILEYE4 - {SPR_FSKU,32768,6,NULL,S_FLOATSKULL2,0,0}, // S_FLOATSKULL - {SPR_FSKU,32769,6,NULL,S_FLOATSKULL3,0,0}, // S_FLOATSKULL2 - {SPR_FSKU,32770,6,NULL,S_FLOATSKULL,0,0}, // S_FLOATSKULL3 - {SPR_COL5,0,14,NULL,S_HEARTCOL2,0,0}, // S_HEARTCOL - {SPR_COL5,1,14,NULL,S_HEARTCOL,0,0}, // S_HEARTCOL2 - {SPR_TBLU,32768,4,NULL,S_BLUETORCH2,0,0}, // S_BLUETORCH - {SPR_TBLU,32769,4,NULL,S_BLUETORCH3,0,0}, // S_BLUETORCH2 - {SPR_TBLU,32770,4,NULL,S_BLUETORCH4,0,0}, // S_BLUETORCH3 - {SPR_TBLU,32771,4,NULL,S_BLUETORCH,0,0}, // S_BLUETORCH4 - {SPR_TGRN,32768,4,NULL,S_GREENTORCH2,0,0}, // S_GREENTORCH - {SPR_TGRN,32769,4,NULL,S_GREENTORCH3,0,0}, // S_GREENTORCH2 - {SPR_TGRN,32770,4,NULL,S_GREENTORCH4,0,0}, // S_GREENTORCH3 - {SPR_TGRN,32771,4,NULL,S_GREENTORCH,0,0}, // S_GREENTORCH4 - {SPR_TRED,32768,4,NULL,S_REDTORCH2,0,0}, // S_REDTORCH - {SPR_TRED,32769,4,NULL,S_REDTORCH3,0,0}, // S_REDTORCH2 - {SPR_TRED,32770,4,NULL,S_REDTORCH4,0,0}, // S_REDTORCH3 - {SPR_TRED,32771,4,NULL,S_REDTORCH,0,0}, // S_REDTORCH4 - {SPR_SMBT,32768,4,NULL,S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT - {SPR_SMBT,32769,4,NULL,S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2 - {SPR_SMBT,32770,4,NULL,S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3 - {SPR_SMBT,32771,4,NULL,S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4 - {SPR_SMGT,32768,4,NULL,S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT - {SPR_SMGT,32769,4,NULL,S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2 - {SPR_SMGT,32770,4,NULL,S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3 - {SPR_SMGT,32771,4,NULL,S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4 - {SPR_SMRT,32768,4,NULL,S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT - {SPR_SMRT,32769,4,NULL,S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2 - {SPR_SMRT,32770,4,NULL,S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3 - {SPR_SMRT,32771,4,NULL,S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4 - {SPR_HDB1,0,-1,NULL,S_NULL,0,0}, // S_HANGNOGUTS - {SPR_HDB2,0,-1,NULL,S_NULL,0,0}, // S_HANGBNOBRAIN - {SPR_HDB3,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKDN - {SPR_HDB4,0,-1,NULL,S_NULL,0,0}, // S_HANGTSKULL - {SPR_HDB5,0,-1,NULL,S_NULL,0,0}, // S_HANGTLOOKUP - {SPR_HDB6,0,-1,NULL,S_NULL,0,0}, // S_HANGTNOBRAIN - {SPR_POB1,0,-1,NULL,S_NULL,0,0}, // S_COLONGIBS - {SPR_POB2,0,-1,NULL,S_NULL,0,0}, // S_SMALLPOOL - {SPR_BRS1,0,-1,NULL,S_NULL,0,0}, // S_BRAINSTEM - {SPR_TLMP,32768,4,NULL,S_TECHLAMP2,0,0}, // S_TECHLAMP - {SPR_TLMP,32769,4,NULL,S_TECHLAMP3,0,0}, // S_TECHLAMP2 - {SPR_TLMP,32770,4,NULL,S_TECHLAMP4,0,0}, // S_TECHLAMP3 - {SPR_TLMP,32771,4,NULL,S_TECHLAMP,0,0}, // S_TECHLAMP4 - {SPR_TLP2,32768,4,NULL,S_TECH2LAMP2,0,0}, // S_TECH2LAMP - {SPR_TLP2,32769,4,NULL,S_TECH2LAMP3,0,0}, // S_TECH2LAMP2 - {SPR_TLP2,32770,4,NULL,S_TECH2LAMP4,0,0}, // S_TECH2LAMP3 - {SPR_TLP2,32771,4,NULL,S_TECH2LAMP,0,0}, // S_TECH2LAMP4 - {SPR_TNT1,0,-1,NULL,S_TNT1,0,0}, // S_TNT1 // phares 3/8/98 + {SPR_TROO,0,-1,{NULL},S_NULL,0,0}, // S_NULL + {SPR_SHTG,4,0,{.acp2=A_Light0},S_NULL,0,0}, // S_LIGHTDONE + {SPR_PUNG,0,1,{.acp2=A_WeaponReady},S_PUNCH,0,0}, // S_PUNCH + {SPR_PUNG,0,1,{.acp2=A_Lower},S_PUNCHDOWN,0,0}, // S_PUNCHDOWN + {SPR_PUNG,0,1,{.acp2=A_Raise},S_PUNCHUP,0,0}, // S_PUNCHUP + {SPR_PUNG,1,4,{NULL},S_PUNCH2,0,0}, // S_PUNCH1 + {SPR_PUNG,2,4,{.acp2=A_Punch},S_PUNCH3,0,0}, // S_PUNCH2 + {SPR_PUNG,3,5,{NULL},S_PUNCH4,0,0}, // S_PUNCH3 + {SPR_PUNG,2,4,{NULL},S_PUNCH5,0,0}, // S_PUNCH4 + {SPR_PUNG,1,5,{.acp2=A_ReFire},S_PUNCH,0,0}, // S_PUNCH5 + {SPR_PISG,0,1,{.acp2=A_WeaponReady},S_PISTOL,0,0},// S_PISTOL + {SPR_PISG,0,1,{.acp2=A_Lower},S_PISTOLDOWN,0,0}, // S_PISTOLDOWN + {SPR_PISG,0,1,{.acp2=A_Raise},S_PISTOLUP,0,0}, // S_PISTOLUP + {SPR_PISG,0,4,{NULL},S_PISTOL2,0,0}, // S_PISTOL1 + {SPR_PISG,1,6,{.acp2=A_FirePistol},S_PISTOL3,0,0},// S_PISTOL2 + {SPR_PISG,2,4,{NULL},S_PISTOL4,0,0}, // S_PISTOL3 + {SPR_PISG,1,5,{.acp2=A_ReFire},S_PISTOL,0,0}, // S_PISTOL4 + {SPR_PISF,32768,7,{.acp2=A_Light1},S_LIGHTDONE,0,0}, // S_PISTOLFLASH + {SPR_SHTG,0,1,{.acp2=A_WeaponReady},S_SGUN,0,0}, // S_SGUN + {SPR_SHTG,0,1,{.acp2=A_Lower},S_SGUNDOWN,0,0}, // S_SGUNDOWN + {SPR_SHTG,0,1,{.acp2=A_Raise},S_SGUNUP,0,0}, // S_SGUNUP + {SPR_SHTG,0,3,{NULL},S_SGUN2,0,0}, // S_SGUN1 + {SPR_SHTG,0,7,{.acp2=A_FireShotgun},S_SGUN3,0,0}, // S_SGUN2 + {SPR_SHTG,1,5,{NULL},S_SGUN4,0,0}, // S_SGUN3 + {SPR_SHTG,2,5,{NULL},S_SGUN5,0,0}, // S_SGUN4 + {SPR_SHTG,3,4,{NULL},S_SGUN6,0,0}, // S_SGUN5 + {SPR_SHTG,2,5,{NULL},S_SGUN7,0,0}, // S_SGUN6 + {SPR_SHTG,1,5,{NULL},S_SGUN8,0,0}, // S_SGUN7 + {SPR_SHTG,0,3,{NULL},S_SGUN9,0,0}, // S_SGUN8 + {SPR_SHTG,0,7,{.acp2=A_ReFire},S_SGUN,0,0}, // S_SGUN9 + {SPR_SHTF,32768,4,{.acp2=A_Light1},S_SGUNFLASH2,0,0}, // S_SGUNFLASH1 + {SPR_SHTF,32769,3,{.acp2=A_Light2},S_LIGHTDONE,0,0}, // S_SGUNFLASH2 + {SPR_SHT2,0,1,{.acp2=A_WeaponReady},S_DSGUN,0,0}, // S_DSGUN + {SPR_SHT2,0,1,{.acp2=A_Lower},S_DSGUNDOWN,0,0}, // S_DSGUNDOWN + {SPR_SHT2,0,1,{.acp2=A_Raise},S_DSGUNUP,0,0}, // S_DSGUNUP + {SPR_SHT2,0,3,{NULL},S_DSGUN2,0,0}, // S_DSGUN1 + {SPR_SHT2,0,7,{.acp2=A_FireShotgun2},S_DSGUN3,0,0}, // S_DSGUN2 + {SPR_SHT2,1,7,{NULL},S_DSGUN4,0,0}, // S_DSGUN3 + {SPR_SHT2,2,7,{.acp2=A_CheckReload},S_DSGUN5,0,0}, // S_DSGUN4 + {SPR_SHT2,3,7,{.acp2=A_OpenShotgun2},S_DSGUN6,0,0}, // S_DSGUN5 + {SPR_SHT2,4,7,{NULL},S_DSGUN7,0,0}, // S_DSGUN6 + {SPR_SHT2,5,7,{.acp2=A_LoadShotgun2},S_DSGUN8,0,0}, // S_DSGUN7 + {SPR_SHT2,6,6,{NULL},S_DSGUN9,0,0}, // S_DSGUN8 + {SPR_SHT2,7,6,{.acp2=A_CloseShotgun2},S_DSGUN10,0,0}, // S_DSGUN9 + {SPR_SHT2,0,5,{.acp2=A_ReFire},S_DSGUN,0,0}, // S_DSGUN10 + {SPR_SHT2,1,7,{NULL},S_DSNR2,0,0}, // S_DSNR1 + {SPR_SHT2,0,3,{NULL},S_DSGUNDOWN,0,0}, // S_DSNR2 + {SPR_SHT2,32776,5,{.acp2=A_Light1},S_DSGUNFLASH2,0,0}, // S_DSGUNFLASH1 + {SPR_SHT2,32777,4,{.acp2=A_Light2},S_LIGHTDONE,0,0}, // S_DSGUNFLASH2 + {SPR_CHGG,0,1,{.acp2=A_WeaponReady},S_CHAIN,0,0}, // S_CHAIN + {SPR_CHGG,0,1,{.acp2=A_Lower},S_CHAINDOWN,0,0}, // S_CHAINDOWN + {SPR_CHGG,0,1,{.acp2=A_Raise},S_CHAINUP,0,0}, // S_CHAINUP + {SPR_CHGG,0,4,{.acp2=A_FireCGun},S_CHAIN2,0,0}, // S_CHAIN1 + {SPR_CHGG,1,4,{.acp2=A_FireCGun},S_CHAIN3,0,0}, // S_CHAIN2 + {SPR_CHGG,1,0,{.acp2=A_ReFire},S_CHAIN,0,0}, // S_CHAIN3 + {SPR_CHGF,32768,5,{.acp2=A_Light1},S_LIGHTDONE,0,0}, // S_CHAINFLASH1 + {SPR_CHGF,32769,5,{.acp2=A_Light2},S_LIGHTDONE,0,0}, // S_CHAINFLASH2 + {SPR_MISG,0,1,{.acp2=A_WeaponReady},S_MISSILE,0,0}, // S_MISSILE + {SPR_MISG,0,1,{.acp2=A_Lower},S_MISSILEDOWN,0,0}, // S_MISSILEDOWN + {SPR_MISG,0,1,{.acp2=A_Raise},S_MISSILEUP,0,0}, // S_MISSILEUP + {SPR_MISG,1,8,{.acp2=A_GunFlash},S_MISSILE2,0,0}, // S_MISSILE1 + {SPR_MISG,1,12,{.acp2=A_FireMissile},S_MISSILE3,0,0}, // S_MISSILE2 + {SPR_MISG,1,0,{.acp2=A_ReFire},S_MISSILE,0,0}, // S_MISSILE3 + {SPR_MISF,32768,3,{.acp2=A_Light1},S_MISSILEFLASH2,0,0}, // S_MISSILEFLASH1 + {SPR_MISF,32769,4,{NULL},S_MISSILEFLASH3,0,0}, // S_MISSILEFLASH2 + {SPR_MISF,32770,4,{.acp2=A_Light2},S_MISSILEFLASH4,0,0}, // S_MISSILEFLASH3 + {SPR_MISF,32771,4,{.acp2=A_Light2},S_LIGHTDONE,0,0}, // S_MISSILEFLASH4 + {SPR_SAWG,2,4,{.acp2=A_WeaponReady},S_SAWB,0,0}, // S_SAW + {SPR_SAWG,3,4,{.acp2=A_WeaponReady},S_SAW,0,0}, // S_SAWB + {SPR_SAWG,2,1,{.acp2=A_Lower},S_SAWDOWN,0,0}, // S_SAWDOWN + {SPR_SAWG,2,1,{.acp2=A_Raise},S_SAWUP,0,0}, // S_SAWUP + {SPR_SAWG,0,4,{.acp2=A_Saw},S_SAW2,0,0}, // S_SAW1 + {SPR_SAWG,1,4,{.acp2=A_Saw},S_SAW3,0,0}, // S_SAW2 + {SPR_SAWG,1,0,{.acp2=A_ReFire},S_SAW,0,0}, // S_SAW3 + {SPR_PLSG,0,1,{.acp2=A_WeaponReady},S_PLASMA,0,0}, // S_PLASMA + {SPR_PLSG,0,1,{.acp2=A_Lower},S_PLASMADOWN,0,0}, // S_PLASMADOWN + {SPR_PLSG,0,1,{.acp2=A_Raise},S_PLASMAUP,0,0}, // S_PLASMAUP + {SPR_PLSG,0,3,{.acp2=A_FirePlasma},S_PLASMA2,0,0}, // S_PLASMA1 + {SPR_PLSG,1,20,{.acp2=A_ReFire},S_PLASMA,0,0}, // S_PLASMA2 + {SPR_PLSF,32768,4,{.acp2=A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH1 + {SPR_PLSF,32769,4,{.acp2=A_Light1},S_LIGHTDONE,0,0}, // S_PLASMAFLASH2 + {SPR_BFGG,0,1,{.acp2=A_WeaponReady},S_BFG,0,0}, // S_BFG + {SPR_BFGG,0,1,{.acp2=A_Lower},S_BFGDOWN,0,0}, // S_BFGDOWN + {SPR_BFGG,0,1,{.acp2=A_Raise},S_BFGUP,0,0}, // S_BFGUP + {SPR_BFGG,0,20,{.acp2=A_BFGsound},S_BFG2,0,0}, // S_BFG1 + {SPR_BFGG,1,10,{.acp2=A_GunFlash},S_BFG3,0,0}, // S_BFG2 + {SPR_BFGG,1,10,{.acp2=A_FireBFG},S_BFG4,0,0}, // S_BFG3 + {SPR_BFGG,1,20,{.acp2=A_ReFire},S_BFG,0,0}, // S_BFG4 + {SPR_BFGF,32768,11,{.acp2=A_Light1},S_BFGFLASH2,0,0}, // S_BFGFLASH1 + {SPR_BFGF,32769,6,{.acp2=A_Light2},S_LIGHTDONE,0,0}, // S_BFGFLASH2 + {SPR_BLUD,2,8,{NULL},S_BLOOD2,0,0}, // S_BLOOD1 + {SPR_BLUD,1,8,{NULL},S_BLOOD3,0,0}, // S_BLOOD2 + {SPR_BLUD,0,8,{NULL},S_NULL,0,0}, // S_BLOOD3 + {SPR_PUFF,32768,4,{NULL},S_PUFF2,0,0}, // S_PUFF1 + {SPR_PUFF,1,4,{NULL},S_PUFF3,0,0}, // S_PUFF2 + {SPR_PUFF,2,4,{NULL},S_PUFF4,0,0}, // S_PUFF3 + {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_PUFF4 + {SPR_BAL1,32768,4,{NULL},S_TBALL2,0,0}, // S_TBALL1 + {SPR_BAL1,32769,4,{NULL},S_TBALL1,0,0}, // S_TBALL2 + {SPR_BAL1,32770,6,{NULL},S_TBALLX2,0,0}, // S_TBALLX1 + {SPR_BAL1,32771,6,{NULL},S_TBALLX3,0,0}, // S_TBALLX2 + {SPR_BAL1,32772,6,{NULL},S_NULL,0,0}, // S_TBALLX3 + {SPR_BAL2,32768,4,{NULL},S_RBALL2,0,0}, // S_RBALL1 + {SPR_BAL2,32769,4,{NULL},S_RBALL1,0,0}, // S_RBALL2 + {SPR_BAL2,32770,6,{NULL},S_RBALLX2,0,0}, // S_RBALLX1 + {SPR_BAL2,32771,6,{NULL},S_RBALLX3,0,0}, // S_RBALLX2 + {SPR_BAL2,32772,6,{NULL},S_NULL,0,0}, // S_RBALLX3 + {SPR_PLSS,32768,6,{NULL},S_PLASBALL2,0,0}, // S_PLASBALL + {SPR_PLSS,32769,6,{NULL},S_PLASBALL,0,0}, // S_PLASBALL2 + {SPR_PLSE,32768,4,{NULL},S_PLASEXP2,0,0}, // S_PLASEXP + {SPR_PLSE,32769,4,{NULL},S_PLASEXP3,0,0}, // S_PLASEXP2 + {SPR_PLSE,32770,4,{NULL},S_PLASEXP4,0,0}, // S_PLASEXP3 + {SPR_PLSE,32771,4,{NULL},S_PLASEXP5,0,0}, // S_PLASEXP4 + {SPR_PLSE,32772,4,{NULL},S_NULL,0,0}, // S_PLASEXP5 + {SPR_MISL,32768,1,{NULL},S_ROCKET,0,0}, // S_ROCKET + {SPR_BFS1,32768,4,{NULL},S_BFGSHOT2,0,0}, // S_BFGSHOT + {SPR_BFS1,32769,4,{NULL},S_BFGSHOT,0,0}, // S_BFGSHOT2 + {SPR_BFE1,32768,8,{NULL},S_BFGLAND2,0,0}, // S_BFGLAND + {SPR_BFE1,32769,8,{NULL},S_BFGLAND3,0,0}, // S_BFGLAND2 + {SPR_BFE1,32770,8,{.acm1=A_BFGSpray},S_BFGLAND4,0,0}, // S_BFGLAND3 + {SPR_BFE1,32771,8,{NULL},S_BFGLAND5,0,0}, // S_BFGLAND4 + {SPR_BFE1,32772,8,{NULL},S_BFGLAND6,0,0}, // S_BFGLAND5 + {SPR_BFE1,32773,8,{NULL},S_NULL,0,0}, // S_BFGLAND6 + {SPR_BFE2,32768,8,{NULL},S_BFGEXP2,0,0}, // S_BFGEXP + {SPR_BFE2,32769,8,{NULL},S_BFGEXP3,0,0}, // S_BFGEXP2 + {SPR_BFE2,32770,8,{NULL},S_BFGEXP4,0,0}, // S_BFGEXP3 + {SPR_BFE2,32771,8,{NULL},S_NULL,0,0}, // S_BFGEXP4 + {SPR_MISL,32769,8,{.acm1=A_Explode},S_EXPLODE2,0,0}, // S_EXPLODE1 + {SPR_MISL,32770,6,{NULL},S_EXPLODE3,0,0}, // S_EXPLODE2 + {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_EXPLODE3 + {SPR_TFOG,32768,6,{NULL},S_TFOG01,0,0}, // S_TFOG + {SPR_TFOG,32769,6,{NULL},S_TFOG02,0,0}, // S_TFOG01 + {SPR_TFOG,32768,6,{NULL},S_TFOG2,0,0}, // S_TFOG02 + {SPR_TFOG,32769,6,{NULL},S_TFOG3,0,0}, // S_TFOG2 + {SPR_TFOG,32770,6,{NULL},S_TFOG4,0,0}, // S_TFOG3 + {SPR_TFOG,32771,6,{NULL},S_TFOG5,0,0}, // S_TFOG4 + {SPR_TFOG,32772,6,{NULL},S_TFOG6,0,0}, // S_TFOG5 + {SPR_TFOG,32773,6,{NULL},S_TFOG7,0,0}, // S_TFOG6 + {SPR_TFOG,32774,6,{NULL},S_TFOG8,0,0}, // S_TFOG7 + {SPR_TFOG,32775,6,{NULL},S_TFOG9,0,0}, // S_TFOG8 + {SPR_TFOG,32776,6,{NULL},S_TFOG10,0,0}, // S_TFOG9 + {SPR_TFOG,32777,6,{NULL},S_NULL,0,0}, // S_TFOG10 + {SPR_IFOG,32768,6,{NULL},S_IFOG01,0,0}, // S_IFOG + {SPR_IFOG,32769,6,{NULL},S_IFOG02,0,0}, // S_IFOG01 + {SPR_IFOG,32768,6,{NULL},S_IFOG2,0,0}, // S_IFOG02 + {SPR_IFOG,32769,6,{NULL},S_IFOG3,0,0}, // S_IFOG2 + {SPR_IFOG,32770,6,{NULL},S_IFOG4,0,0}, // S_IFOG3 + {SPR_IFOG,32771,6,{NULL},S_IFOG5,0,0}, // S_IFOG4 + {SPR_IFOG,32772,6,{NULL},S_NULL,0,0}, // S_IFOG5 + {SPR_PLAY,0,-1,{NULL},S_NULL,0,0}, // S_PLAY + {SPR_PLAY,0,4,{NULL},S_PLAY_RUN2,0,0}, // S_PLAY_RUN1 + {SPR_PLAY,1,4,{NULL},S_PLAY_RUN3,0,0}, // S_PLAY_RUN2 + {SPR_PLAY,2,4,{NULL},S_PLAY_RUN4,0,0}, // S_PLAY_RUN3 + {SPR_PLAY,3,4,{NULL},S_PLAY_RUN1,0,0}, // S_PLAY_RUN4 + {SPR_PLAY,4,12,{NULL},S_PLAY,0,0}, // S_PLAY_ATK1 + {SPR_PLAY,32773,6,{NULL},S_PLAY_ATK1,0,0}, // S_PLAY_ATK2 + {SPR_PLAY,6,4,{NULL},S_PLAY_PAIN2,0,0}, // S_PLAY_PAIN + {SPR_PLAY,6,4,{.acm1=A_Pain},S_PLAY,0,0}, // S_PLAY_PAIN2 + {SPR_PLAY,7,10,{NULL},S_PLAY_DIE2,0,0}, // S_PLAY_DIE1 + {SPR_PLAY,8,10,{.acm1=A_PlayerScream},S_PLAY_DIE3,0,0}, // S_PLAY_DIE2 + {SPR_PLAY,9,10,{.acm1=A_Fall},S_PLAY_DIE4,0,0}, // S_PLAY_DIE3 + {SPR_PLAY,10,10,{NULL},S_PLAY_DIE5,0,0}, // S_PLAY_DIE4 + {SPR_PLAY,11,10,{NULL},S_PLAY_DIE6,0,0}, // S_PLAY_DIE5 + {SPR_PLAY,12,10,{NULL},S_PLAY_DIE7,0,0}, // S_PLAY_DIE6 + {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_PLAY_DIE7 + {SPR_PLAY,14,5,{NULL},S_PLAY_XDIE2,0,0}, // S_PLAY_XDIE1 + {SPR_PLAY,15,5,{.acm1=A_XScream},S_PLAY_XDIE3,0,0}, // S_PLAY_XDIE2 + {SPR_PLAY,16,5,{.acm1=A_Fall},S_PLAY_XDIE4,0,0}, // S_PLAY_XDIE3 + {SPR_PLAY,17,5,{NULL},S_PLAY_XDIE5,0,0}, // S_PLAY_XDIE4 + {SPR_PLAY,18,5,{NULL},S_PLAY_XDIE6,0,0}, // S_PLAY_XDIE5 + {SPR_PLAY,19,5,{NULL},S_PLAY_XDIE7,0,0}, // S_PLAY_XDIE6 + {SPR_PLAY,20,5,{NULL},S_PLAY_XDIE8,0,0}, // S_PLAY_XDIE7 + {SPR_PLAY,21,5,{NULL},S_PLAY_XDIE9,0,0}, // S_PLAY_XDIE8 + {SPR_PLAY,22,-1,{NULL},S_NULL,0,0}, // S_PLAY_XDIE9 + {SPR_POSS,0,10,{.acm1=A_Look},S_POSS_STND2,0,0}, // S_POSS_STND + {SPR_POSS,1,10,{.acm1=A_Look},S_POSS_STND,0,0}, // S_POSS_STND2 + {SPR_POSS,0,4,{.acm1=A_Chase},S_POSS_RUN2,0,0}, // S_POSS_RUN1 + {SPR_POSS,0,4,{.acm1=A_Chase},S_POSS_RUN3,0,0}, // S_POSS_RUN2 + {SPR_POSS,1,4,{.acm1=A_Chase},S_POSS_RUN4,0,0}, // S_POSS_RUN3 + {SPR_POSS,1,4,{.acm1=A_Chase},S_POSS_RUN5,0,0}, // S_POSS_RUN4 + {SPR_POSS,2,4,{.acm1=A_Chase},S_POSS_RUN6,0,0}, // S_POSS_RUN5 + {SPR_POSS,2,4,{.acm1=A_Chase},S_POSS_RUN7,0,0}, // S_POSS_RUN6 + {SPR_POSS,3,4,{.acm1=A_Chase},S_POSS_RUN8,0,0}, // S_POSS_RUN7 + {SPR_POSS,3,4,{.acm1=A_Chase},S_POSS_RUN1,0,0}, // S_POSS_RUN8 + {SPR_POSS,4,10,{.acm1=A_FaceTarget},S_POSS_ATK2,0,0}, // S_POSS_ATK1 + {SPR_POSS,5,8,{.acm1=A_PosAttack},S_POSS_ATK3,0,0}, // S_POSS_ATK2 + {SPR_POSS,4,8,{NULL},S_POSS_RUN1,0,0}, // S_POSS_ATK3 + {SPR_POSS,6,3,{NULL},S_POSS_PAIN2,0,0}, // S_POSS_PAIN + {SPR_POSS,6,3,{.acm1=A_Pain},S_POSS_RUN1,0,0}, // S_POSS_PAIN2 + {SPR_POSS,7,5,{NULL},S_POSS_DIE2,0,0}, // S_POSS_DIE1 + {SPR_POSS,8,5,{.acm1=A_Scream},S_POSS_DIE3,0,0}, // S_POSS_DIE2 + {SPR_POSS,9,5,{.acm1=A_Fall},S_POSS_DIE4,0,0}, // S_POSS_DIE3 + {SPR_POSS,10,5,{NULL},S_POSS_DIE5,0,0}, // S_POSS_DIE4 + {SPR_POSS,11,-1,{NULL},S_NULL,0,0}, // S_POSS_DIE5 + {SPR_POSS,12,5,{NULL},S_POSS_XDIE2,0,0}, // S_POSS_XDIE1 + {SPR_POSS,13,5,{.acm1=A_XScream},S_POSS_XDIE3,0,0}, // S_POSS_XDIE2 + {SPR_POSS,14,5,{.acm1=A_Fall},S_POSS_XDIE4,0,0}, // S_POSS_XDIE3 + {SPR_POSS,15,5,{NULL},S_POSS_XDIE5,0,0}, // S_POSS_XDIE4 + {SPR_POSS,16,5,{NULL},S_POSS_XDIE6,0,0}, // S_POSS_XDIE5 + {SPR_POSS,17,5,{NULL},S_POSS_XDIE7,0,0}, // S_POSS_XDIE6 + {SPR_POSS,18,5,{NULL},S_POSS_XDIE8,0,0}, // S_POSS_XDIE7 + {SPR_POSS,19,5,{NULL},S_POSS_XDIE9,0,0}, // S_POSS_XDIE8 + {SPR_POSS,20,-1,{NULL},S_NULL,0,0}, // S_POSS_XDIE9 + {SPR_POSS,10,5,{NULL},S_POSS_RAISE2,0,0}, // S_POSS_RAISE1 + {SPR_POSS,9,5,{NULL},S_POSS_RAISE3,0,0}, // S_POSS_RAISE2 + {SPR_POSS,8,5,{NULL},S_POSS_RAISE4,0,0}, // S_POSS_RAISE3 + {SPR_POSS,7,5,{NULL},S_POSS_RUN1,0,0}, // S_POSS_RAISE4 + {SPR_SPOS,0,10,{.acm1=A_Look},S_SPOS_STND2,0,0}, // S_SPOS_STND + {SPR_SPOS,1,10,{.acm1=A_Look},S_SPOS_STND,0,0}, // S_SPOS_STND2 + {SPR_SPOS,0,3,{.acm1=A_Chase},S_SPOS_RUN2,0,0}, // S_SPOS_RUN1 + {SPR_SPOS,0,3,{.acm1=A_Chase},S_SPOS_RUN3,0,0}, // S_SPOS_RUN2 + {SPR_SPOS,1,3,{.acm1=A_Chase},S_SPOS_RUN4,0,0}, // S_SPOS_RUN3 + {SPR_SPOS,1,3,{.acm1=A_Chase},S_SPOS_RUN5,0,0}, // S_SPOS_RUN4 + {SPR_SPOS,2,3,{.acm1=A_Chase},S_SPOS_RUN6,0,0}, // S_SPOS_RUN5 + {SPR_SPOS,2,3,{.acm1=A_Chase},S_SPOS_RUN7,0,0}, // S_SPOS_RUN6 + {SPR_SPOS,3,3,{.acm1=A_Chase},S_SPOS_RUN8,0,0}, // S_SPOS_RUN7 + {SPR_SPOS,3,3,{.acm1=A_Chase},S_SPOS_RUN1,0,0}, // S_SPOS_RUN8 + {SPR_SPOS,4,10,{.acm1=A_FaceTarget},S_SPOS_ATK2,0,0}, // S_SPOS_ATK1 + {SPR_SPOS,32773,10,{.acm1=A_SPosAttack},S_SPOS_ATK3,0,0}, // S_SPOS_ATK2 + {SPR_SPOS,4,10,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_ATK3 + {SPR_SPOS,6,3,{NULL},S_SPOS_PAIN2,0,0}, // S_SPOS_PAIN + {SPR_SPOS,6,3,{.acm1=A_Pain},S_SPOS_RUN1,0,0}, // S_SPOS_PAIN2 + {SPR_SPOS,7,5,{NULL},S_SPOS_DIE2,0,0}, // S_SPOS_DIE1 + {SPR_SPOS,8,5,{.acm1=A_Scream},S_SPOS_DIE3,0,0}, // S_SPOS_DIE2 + {SPR_SPOS,9,5,{.acm1=A_Fall},S_SPOS_DIE4,0,0}, // S_SPOS_DIE3 + {SPR_SPOS,10,5,{NULL},S_SPOS_DIE5,0,0}, // S_SPOS_DIE4 + {SPR_SPOS,11,-1,{NULL},S_NULL,0,0}, // S_SPOS_DIE5 + {SPR_SPOS,12,5,{NULL},S_SPOS_XDIE2,0,0}, // S_SPOS_XDIE1 + {SPR_SPOS,13,5,{.acm1=A_XScream},S_SPOS_XDIE3,0,0}, // S_SPOS_XDIE2 + {SPR_SPOS,14,5,{.acm1=A_Fall},S_SPOS_XDIE4,0,0}, // S_SPOS_XDIE3 + {SPR_SPOS,15,5,{NULL},S_SPOS_XDIE5,0,0}, // S_SPOS_XDIE4 + {SPR_SPOS,16,5,{NULL},S_SPOS_XDIE6,0,0}, // S_SPOS_XDIE5 + {SPR_SPOS,17,5,{NULL},S_SPOS_XDIE7,0,0}, // S_SPOS_XDIE6 + {SPR_SPOS,18,5,{NULL},S_SPOS_XDIE8,0,0}, // S_SPOS_XDIE7 + {SPR_SPOS,19,5,{NULL},S_SPOS_XDIE9,0,0}, // S_SPOS_XDIE8 + {SPR_SPOS,20,-1,{NULL},S_NULL,0,0}, // S_SPOS_XDIE9 + {SPR_SPOS,11,5,{NULL},S_SPOS_RAISE2,0,0}, // S_SPOS_RAISE1 + {SPR_SPOS,10,5,{NULL},S_SPOS_RAISE3,0,0}, // S_SPOS_RAISE2 + {SPR_SPOS,9,5,{NULL},S_SPOS_RAISE4,0,0}, // S_SPOS_RAISE3 + {SPR_SPOS,8,5,{NULL},S_SPOS_RAISE5,0,0}, // S_SPOS_RAISE4 + {SPR_SPOS,7,5,{NULL},S_SPOS_RUN1,0,0}, // S_SPOS_RAISE5 + {SPR_VILE,0,10,{.acm1=A_Look},S_VILE_STND2,0,0}, // S_VILE_STND + {SPR_VILE,1,10,{.acm1=A_Look},S_VILE_STND,0,0}, // S_VILE_STND2 + {SPR_VILE,0,2,{.acm1=A_VileChase},S_VILE_RUN2,0,0}, // S_VILE_RUN1 + {SPR_VILE,0,2,{.acm1=A_VileChase},S_VILE_RUN3,0,0}, // S_VILE_RUN2 + {SPR_VILE,1,2,{.acm1=A_VileChase},S_VILE_RUN4,0,0}, // S_VILE_RUN3 + {SPR_VILE,1,2,{.acm1=A_VileChase},S_VILE_RUN5,0,0}, // S_VILE_RUN4 + {SPR_VILE,2,2,{.acm1=A_VileChase},S_VILE_RUN6,0,0}, // S_VILE_RUN5 + {SPR_VILE,2,2,{.acm1=A_VileChase},S_VILE_RUN7,0,0}, // S_VILE_RUN6 + {SPR_VILE,3,2,{.acm1=A_VileChase},S_VILE_RUN8,0,0}, // S_VILE_RUN7 + {SPR_VILE,3,2,{.acm1=A_VileChase},S_VILE_RUN9,0,0}, // S_VILE_RUN8 + {SPR_VILE,4,2,{.acm1=A_VileChase},S_VILE_RUN10,0,0}, // S_VILE_RUN9 + {SPR_VILE,4,2,{.acm1=A_VileChase},S_VILE_RUN11,0,0}, // S_VILE_RUN10 + {SPR_VILE,5,2,{.acm1=A_VileChase},S_VILE_RUN12,0,0}, // S_VILE_RUN11 + {SPR_VILE,5,2,{.acm1=A_VileChase},S_VILE_RUN1,0,0}, // S_VILE_RUN12 + {SPR_VILE,32774,0,{.acm1=A_VileStart},S_VILE_ATK2,0,0}, // S_VILE_ATK1 + {SPR_VILE,32774,10,{.acm1=A_FaceTarget},S_VILE_ATK3,0,0}, // S_VILE_ATK2 + {SPR_VILE,32775,8,{.acm1=A_VileTarget},S_VILE_ATK4,0,0}, // S_VILE_ATK3 + {SPR_VILE,32776,8,{.acm1=A_FaceTarget},S_VILE_ATK5,0,0}, // S_VILE_ATK4 + {SPR_VILE,32777,8,{.acm1=A_FaceTarget},S_VILE_ATK6,0,0}, // S_VILE_ATK5 + {SPR_VILE,32778,8,{.acm1=A_FaceTarget},S_VILE_ATK7,0,0}, // S_VILE_ATK6 + {SPR_VILE,32779,8,{.acm1=A_FaceTarget},S_VILE_ATK8,0,0}, // S_VILE_ATK7 + {SPR_VILE,32780,8,{.acm1=A_FaceTarget},S_VILE_ATK9,0,0}, // S_VILE_ATK8 + {SPR_VILE,32781,8,{.acm1=A_FaceTarget},S_VILE_ATK10,0,0}, // S_VILE_ATK9 + {SPR_VILE,32782,8,{.acm1=A_VileAttack},S_VILE_ATK11,0,0}, // S_VILE_ATK10 + {SPR_VILE,32783,20,{NULL},S_VILE_RUN1,0,0}, // S_VILE_ATK11 + {SPR_VILE,32794,10,{NULL},S_VILE_HEAL2,0,0}, // S_VILE_HEAL1 + {SPR_VILE,32795,10,{NULL},S_VILE_HEAL3,0,0}, // S_VILE_HEAL2 + {SPR_VILE,32796,10,{NULL},S_VILE_RUN1,0,0}, // S_VILE_HEAL3 + {SPR_VILE,16,5,{NULL},S_VILE_PAIN2,0,0}, // S_VILE_PAIN + {SPR_VILE,16,5,{.acm1=A_Pain},S_VILE_RUN1,0,0}, // S_VILE_PAIN2 + {SPR_VILE,16,7,{NULL},S_VILE_DIE2,0,0}, // S_VILE_DIE1 + {SPR_VILE,17,7,{.acm1=A_Scream},S_VILE_DIE3,0,0}, // S_VILE_DIE2 + {SPR_VILE,18,7,{.acm1=A_Fall},S_VILE_DIE4,0,0}, // S_VILE_DIE3 + {SPR_VILE,19,7,{NULL},S_VILE_DIE5,0,0}, // S_VILE_DIE4 + {SPR_VILE,20,7,{NULL},S_VILE_DIE6,0,0}, // S_VILE_DIE5 + {SPR_VILE,21,7,{NULL},S_VILE_DIE7,0,0}, // S_VILE_DIE6 + {SPR_VILE,22,7,{NULL},S_VILE_DIE8,0,0}, // S_VILE_DIE7 + {SPR_VILE,23,5,{NULL},S_VILE_DIE9,0,0}, // S_VILE_DIE8 + {SPR_VILE,24,5,{NULL},S_VILE_DIE10,0,0}, // S_VILE_DIE9 + {SPR_VILE,25,-1,{NULL},S_NULL,0,0}, // S_VILE_DIE10 + {SPR_FIRE,32768,2,{.acm1=A_StartFire},S_FIRE2,0,0}, // S_FIRE1 + {SPR_FIRE,32769,2,{.acm1=A_Fire},S_FIRE3,0,0}, // S_FIRE2 + {SPR_FIRE,32768,2,{.acm1=A_Fire},S_FIRE4,0,0}, // S_FIRE3 + {SPR_FIRE,32769,2,{.acm1=A_Fire},S_FIRE5,0,0}, // S_FIRE4 + {SPR_FIRE,32770,2,{.acm1=A_FireCrackle},S_FIRE6,0,0}, // S_FIRE5 + {SPR_FIRE,32769,2,{.acm1=A_Fire},S_FIRE7,0,0}, // S_FIRE6 + {SPR_FIRE,32770,2,{.acm1=A_Fire},S_FIRE8,0,0}, // S_FIRE7 + {SPR_FIRE,32769,2,{.acm1=A_Fire},S_FIRE9,0,0}, // S_FIRE8 + {SPR_FIRE,32770,2,{.acm1=A_Fire},S_FIRE10,0,0}, // S_FIRE9 + {SPR_FIRE,32771,2,{.acm1=A_Fire},S_FIRE11,0,0}, // S_FIRE10 + {SPR_FIRE,32770,2,{.acm1=A_Fire},S_FIRE12,0,0}, // S_FIRE11 + {SPR_FIRE,32771,2,{.acm1=A_Fire},S_FIRE13,0,0}, // S_FIRE12 + {SPR_FIRE,32770,2,{.acm1=A_Fire},S_FIRE14,0,0}, // S_FIRE13 + {SPR_FIRE,32771,2,{.acm1=A_Fire},S_FIRE15,0,0}, // S_FIRE14 + {SPR_FIRE,32772,2,{.acm1=A_Fire},S_FIRE16,0,0}, // S_FIRE15 + {SPR_FIRE,32771,2,{.acm1=A_Fire},S_FIRE17,0,0}, // S_FIRE16 + {SPR_FIRE,32772,2,{.acm1=A_Fire},S_FIRE18,0,0}, // S_FIRE17 + {SPR_FIRE,32771,2,{.acm1=A_Fire},S_FIRE19,0,0}, // S_FIRE18 + {SPR_FIRE,32772,2,{.acm1=A_FireCrackle},S_FIRE20,0,0}, // S_FIRE19 + {SPR_FIRE,32773,2,{.acm1=A_Fire},S_FIRE21,0,0}, // S_FIRE20 + {SPR_FIRE,32772,2,{.acm1=A_Fire},S_FIRE22,0,0}, // S_FIRE21 + {SPR_FIRE,32773,2,{.acm1=A_Fire},S_FIRE23,0,0}, // S_FIRE22 + {SPR_FIRE,32772,2,{.acm1=A_Fire},S_FIRE24,0,0}, // S_FIRE23 + {SPR_FIRE,32773,2,{.acm1=A_Fire},S_FIRE25,0,0}, // S_FIRE24 + {SPR_FIRE,32774,2,{.acm1=A_Fire},S_FIRE26,0,0}, // S_FIRE25 + {SPR_FIRE,32775,2,{.acm1=A_Fire},S_FIRE27,0,0}, // S_FIRE26 + {SPR_FIRE,32774,2,{.acm1=A_Fire},S_FIRE28,0,0}, // S_FIRE27 + {SPR_FIRE,32775,2,{.acm1=A_Fire},S_FIRE29,0,0}, // S_FIRE28 + {SPR_FIRE,32774,2,{.acm1=A_Fire},S_FIRE30,0,0}, // S_FIRE29 + {SPR_FIRE,32775,2,{.acm1=A_Fire},S_NULL,0,0}, // S_FIRE30 + {SPR_PUFF,1,4,{NULL},S_SMOKE2,0,0}, // S_SMOKE1 + {SPR_PUFF,2,4,{NULL},S_SMOKE3,0,0}, // S_SMOKE2 + {SPR_PUFF,1,4,{NULL},S_SMOKE4,0,0}, // S_SMOKE3 + {SPR_PUFF,2,4,{NULL},S_SMOKE5,0,0}, // S_SMOKE4 + {SPR_PUFF,3,4,{NULL},S_NULL,0,0}, // S_SMOKE5 + {SPR_FATB,32768,2,{.acm1=A_Tracer},S_TRACER2,0,0}, // S_TRACER + {SPR_FATB,32769,2,{.acm1=A_Tracer},S_TRACER,0,0}, // S_TRACER2 + {SPR_FBXP,32768,8,{NULL},S_TRACEEXP2,0,0}, // S_TRACEEXP1 + {SPR_FBXP,32769,6,{NULL},S_TRACEEXP3,0,0}, // S_TRACEEXP2 + {SPR_FBXP,32770,4,{NULL},S_NULL,0,0}, // S_TRACEEXP3 + {SPR_SKEL,0,10,{.acm1=A_Look},S_SKEL_STND2,0,0}, // S_SKEL_STND + {SPR_SKEL,1,10,{.acm1=A_Look},S_SKEL_STND,0,0}, // S_SKEL_STND2 + {SPR_SKEL,0,2,{.acm1=A_Chase},S_SKEL_RUN2,0,0}, // S_SKEL_RUN1 + {SPR_SKEL,0,2,{.acm1=A_Chase},S_SKEL_RUN3,0,0}, // S_SKEL_RUN2 + {SPR_SKEL,1,2,{.acm1=A_Chase},S_SKEL_RUN4,0,0}, // S_SKEL_RUN3 + {SPR_SKEL,1,2,{.acm1=A_Chase},S_SKEL_RUN5,0,0}, // S_SKEL_RUN4 + {SPR_SKEL,2,2,{.acm1=A_Chase},S_SKEL_RUN6,0,0}, // S_SKEL_RUN5 + {SPR_SKEL,2,2,{.acm1=A_Chase},S_SKEL_RUN7,0,0}, // S_SKEL_RUN6 + {SPR_SKEL,3,2,{.acm1=A_Chase},S_SKEL_RUN8,0,0}, // S_SKEL_RUN7 + {SPR_SKEL,3,2,{.acm1=A_Chase},S_SKEL_RUN9,0,0}, // S_SKEL_RUN8 + {SPR_SKEL,4,2,{.acm1=A_Chase},S_SKEL_RUN10,0,0}, // S_SKEL_RUN9 + {SPR_SKEL,4,2,{.acm1=A_Chase},S_SKEL_RUN11,0,0}, // S_SKEL_RUN10 + {SPR_SKEL,5,2,{.acm1=A_Chase},S_SKEL_RUN12,0,0}, // S_SKEL_RUN11 + {SPR_SKEL,5,2,{.acm1=A_Chase},S_SKEL_RUN1,0,0}, // S_SKEL_RUN12 + {SPR_SKEL,6,0,{.acm1=A_FaceTarget},S_SKEL_FIST2,0,0}, // S_SKEL_FIST1 + {SPR_SKEL,6,6,{.acm1=A_SkelWhoosh},S_SKEL_FIST3,0,0}, // S_SKEL_FIST2 + {SPR_SKEL,7,6,{.acm1=A_FaceTarget},S_SKEL_FIST4,0,0}, // S_SKEL_FIST3 + {SPR_SKEL,8,6,{.acm1=A_SkelFist},S_SKEL_RUN1,0,0}, // S_SKEL_FIST4 + {SPR_SKEL,32777,0,{.acm1=A_FaceTarget},S_SKEL_MISS2,0,0}, // S_SKEL_MISS1 + {SPR_SKEL,32777,10,{.acm1=A_FaceTarget},S_SKEL_MISS3,0,0}, // S_SKEL_MISS2 + {SPR_SKEL,10,10,{.acm1=A_SkelMissile},S_SKEL_MISS4,0,0}, // S_SKEL_MISS3 + {SPR_SKEL,10,10,{.acm1=A_FaceTarget},S_SKEL_RUN1,0,0}, // S_SKEL_MISS4 + {SPR_SKEL,11,5,{NULL},S_SKEL_PAIN2,0,0}, // S_SKEL_PAIN + {SPR_SKEL,11,5,{.acm1=A_Pain},S_SKEL_RUN1,0,0}, // S_SKEL_PAIN2 + {SPR_SKEL,11,7,{NULL},S_SKEL_DIE2,0,0}, // S_SKEL_DIE1 + {SPR_SKEL,12,7,{NULL},S_SKEL_DIE3,0,0}, // S_SKEL_DIE2 + {SPR_SKEL,13,7,{.acm1=A_Scream},S_SKEL_DIE4,0,0}, // S_SKEL_DIE3 + {SPR_SKEL,14,7,{.acm1=A_Fall},S_SKEL_DIE5,0,0}, // S_SKEL_DIE4 + {SPR_SKEL,15,7,{NULL},S_SKEL_DIE6,0,0}, // S_SKEL_DIE5 + {SPR_SKEL,16,-1,{NULL},S_NULL,0,0}, // S_SKEL_DIE6 + {SPR_SKEL,16,5,{NULL},S_SKEL_RAISE2,0,0}, // S_SKEL_RAISE1 + {SPR_SKEL,15,5,{NULL},S_SKEL_RAISE3,0,0}, // S_SKEL_RAISE2 + {SPR_SKEL,14,5,{NULL},S_SKEL_RAISE4,0,0}, // S_SKEL_RAISE3 + {SPR_SKEL,13,5,{NULL},S_SKEL_RAISE5,0,0}, // S_SKEL_RAISE4 + {SPR_SKEL,12,5,{NULL},S_SKEL_RAISE6,0,0}, // S_SKEL_RAISE5 + {SPR_SKEL,11,5,{NULL},S_SKEL_RUN1,0,0}, // S_SKEL_RAISE6 + {SPR_MANF,32768,4,{NULL},S_FATSHOT2,0,0}, // S_FATSHOT1 + {SPR_MANF,32769,4,{NULL},S_FATSHOT1,0,0}, // S_FATSHOT2 + {SPR_MISL,32769,8,{NULL},S_FATSHOTX2,0,0}, // S_FATSHOTX1 + {SPR_MISL,32770,6,{NULL},S_FATSHOTX3,0,0}, // S_FATSHOTX2 + {SPR_MISL,32771,4,{NULL},S_NULL,0,0}, // S_FATSHOTX3 + {SPR_FATT,0,15,{.acm1=A_Look},S_FATT_STND2,0,0}, // S_FATT_STND + {SPR_FATT,1,15,{.acm1=A_Look},S_FATT_STND,0,0}, // S_FATT_STND2 + {SPR_FATT,0,4,{.acm1=A_Chase},S_FATT_RUN2,0,0}, // S_FATT_RUN1 + {SPR_FATT,0,4,{.acm1=A_Chase},S_FATT_RUN3,0,0}, // S_FATT_RUN2 + {SPR_FATT,1,4,{.acm1=A_Chase},S_FATT_RUN4,0,0}, // S_FATT_RUN3 + {SPR_FATT,1,4,{.acm1=A_Chase},S_FATT_RUN5,0,0}, // S_FATT_RUN4 + {SPR_FATT,2,4,{.acm1=A_Chase},S_FATT_RUN6,0,0}, // S_FATT_RUN5 + {SPR_FATT,2,4,{.acm1=A_Chase},S_FATT_RUN7,0,0}, // S_FATT_RUN6 + {SPR_FATT,3,4,{.acm1=A_Chase},S_FATT_RUN8,0,0}, // S_FATT_RUN7 + {SPR_FATT,3,4,{.acm1=A_Chase},S_FATT_RUN9,0,0}, // S_FATT_RUN8 + {SPR_FATT,4,4,{.acm1=A_Chase},S_FATT_RUN10,0,0}, // S_FATT_RUN9 + {SPR_FATT,4,4,{.acm1=A_Chase},S_FATT_RUN11,0,0}, // S_FATT_RUN10 + {SPR_FATT,5,4,{.acm1=A_Chase},S_FATT_RUN12,0,0}, // S_FATT_RUN11 + {SPR_FATT,5,4,{.acm1=A_Chase},S_FATT_RUN1,0,0}, // S_FATT_RUN12 + {SPR_FATT,6,20,{.acm1=A_FatRaise},S_FATT_ATK2,0,0}, // S_FATT_ATK1 + {SPR_FATT,32775,10,{.acm1=A_FatAttack1},S_FATT_ATK3,0,0}, // S_FATT_ATK2 + {SPR_FATT,8,5,{.acm1=A_FaceTarget},S_FATT_ATK4,0,0}, // S_FATT_ATK3 + {SPR_FATT,6,5,{.acm1=A_FaceTarget},S_FATT_ATK5,0,0}, // S_FATT_ATK4 + {SPR_FATT,32775,10,{.acm1=A_FatAttack2},S_FATT_ATK6,0,0}, // S_FATT_ATK5 + {SPR_FATT,8,5,{.acm1=A_FaceTarget},S_FATT_ATK7,0,0}, // S_FATT_ATK6 + {SPR_FATT,6,5,{.acm1=A_FaceTarget},S_FATT_ATK8,0,0}, // S_FATT_ATK7 + {SPR_FATT,32775,10,{.acm1=A_FatAttack3},S_FATT_ATK9,0,0}, // S_FATT_ATK8 + {SPR_FATT,8,5,{.acm1=A_FaceTarget},S_FATT_ATK10,0,0}, // S_FATT_ATK9 + {SPR_FATT,6,5,{.acm1=A_FaceTarget},S_FATT_RUN1,0,0}, // S_FATT_ATK10 + {SPR_FATT,9,3,{NULL},S_FATT_PAIN2,0,0}, // S_FATT_PAIN + {SPR_FATT,9,3,{.acm1=A_Pain},S_FATT_RUN1,0,0}, // S_FATT_PAIN2 + {SPR_FATT,10,6,{NULL},S_FATT_DIE2,0,0}, // S_FATT_DIE1 + {SPR_FATT,11,6,{.acm1=A_Scream},S_FATT_DIE3,0,0}, // S_FATT_DIE2 + {SPR_FATT,12,6,{.acm1=A_Fall},S_FATT_DIE4,0,0}, // S_FATT_DIE3 + {SPR_FATT,13,6,{NULL},S_FATT_DIE5,0,0}, // S_FATT_DIE4 + {SPR_FATT,14,6,{NULL},S_FATT_DIE6,0,0}, // S_FATT_DIE5 + {SPR_FATT,15,6,{NULL},S_FATT_DIE7,0,0}, // S_FATT_DIE6 + {SPR_FATT,16,6,{NULL},S_FATT_DIE8,0,0}, // S_FATT_DIE7 + {SPR_FATT,17,6,{NULL},S_FATT_DIE9,0,0}, // S_FATT_DIE8 + {SPR_FATT,18,6,{NULL},S_FATT_DIE10,0,0}, // S_FATT_DIE9 + {SPR_FATT,19,-1,{.acm1=A_BossDeath},S_NULL,0,0}, // S_FATT_DIE10 + {SPR_FATT,17,5,{NULL},S_FATT_RAISE2,0,0}, // S_FATT_RAISE1 + {SPR_FATT,16,5,{NULL},S_FATT_RAISE3,0,0}, // S_FATT_RAISE2 + {SPR_FATT,15,5,{NULL},S_FATT_RAISE4,0,0}, // S_FATT_RAISE3 + {SPR_FATT,14,5,{NULL},S_FATT_RAISE5,0,0}, // S_FATT_RAISE4 + {SPR_FATT,13,5,{NULL},S_FATT_RAISE6,0,0}, // S_FATT_RAISE5 + {SPR_FATT,12,5,{NULL},S_FATT_RAISE7,0,0}, // S_FATT_RAISE6 + {SPR_FATT,11,5,{NULL},S_FATT_RAISE8,0,0}, // S_FATT_RAISE7 + {SPR_FATT,10,5,{NULL},S_FATT_RUN1,0,0}, // S_FATT_RAISE8 + {SPR_CPOS,0,10,{.acm1=A_Look},S_CPOS_STND2,0,0}, // S_CPOS_STND + {SPR_CPOS,1,10,{.acm1=A_Look},S_CPOS_STND,0,0}, // S_CPOS_STND2 + {SPR_CPOS,0,3,{.acm1=A_Chase},S_CPOS_RUN2,0,0}, // S_CPOS_RUN1 + {SPR_CPOS,0,3,{.acm1=A_Chase},S_CPOS_RUN3,0,0}, // S_CPOS_RUN2 + {SPR_CPOS,1,3,{.acm1=A_Chase},S_CPOS_RUN4,0,0}, // S_CPOS_RUN3 + {SPR_CPOS,1,3,{.acm1=A_Chase},S_CPOS_RUN5,0,0}, // S_CPOS_RUN4 + {SPR_CPOS,2,3,{.acm1=A_Chase},S_CPOS_RUN6,0,0}, // S_CPOS_RUN5 + {SPR_CPOS,2,3,{.acm1=A_Chase},S_CPOS_RUN7,0,0}, // S_CPOS_RUN6 + {SPR_CPOS,3,3,{.acm1=A_Chase},S_CPOS_RUN8,0,0}, // S_CPOS_RUN7 + {SPR_CPOS,3,3,{.acm1=A_Chase},S_CPOS_RUN1,0,0}, // S_CPOS_RUN8 + {SPR_CPOS,4,10,{.acm1=A_FaceTarget},S_CPOS_ATK2,0,0}, // S_CPOS_ATK1 + {SPR_CPOS,32773,4,{.acm1=A_CPosAttack},S_CPOS_ATK3,0,0}, // S_CPOS_ATK2 + {SPR_CPOS,32772,4,{.acm1=A_CPosAttack},S_CPOS_ATK4,0,0}, // S_CPOS_ATK3 + {SPR_CPOS,5,1,{.acm1=A_CPosRefire},S_CPOS_ATK2,0,0}, // S_CPOS_ATK4 + {SPR_CPOS,6,3,{NULL},S_CPOS_PAIN2,0,0}, // S_CPOS_PAIN + {SPR_CPOS,6,3,{.acm1=A_Pain},S_CPOS_RUN1,0,0}, // S_CPOS_PAIN2 + {SPR_CPOS,7,5,{NULL},S_CPOS_DIE2,0,0}, // S_CPOS_DIE1 + {SPR_CPOS,8,5,{.acm1=A_Scream},S_CPOS_DIE3,0,0}, // S_CPOS_DIE2 + {SPR_CPOS,9,5,{.acm1=A_Fall},S_CPOS_DIE4,0,0}, // S_CPOS_DIE3 + {SPR_CPOS,10,5,{NULL},S_CPOS_DIE5,0,0}, // S_CPOS_DIE4 + {SPR_CPOS,11,5,{NULL},S_CPOS_DIE6,0,0}, // S_CPOS_DIE5 + {SPR_CPOS,12,5,{NULL},S_CPOS_DIE7,0,0}, // S_CPOS_DIE6 + {SPR_CPOS,13,-1,{NULL},S_NULL,0,0}, // S_CPOS_DIE7 + {SPR_CPOS,14,5,{NULL},S_CPOS_XDIE2,0,0}, // S_CPOS_XDIE1 + {SPR_CPOS,15,5,{.acm1=A_XScream},S_CPOS_XDIE3,0,0}, // S_CPOS_XDIE2 + {SPR_CPOS,16,5,{.acm1=A_Fall},S_CPOS_XDIE4,0,0}, // S_CPOS_XDIE3 + {SPR_CPOS,17,5,{NULL},S_CPOS_XDIE5,0,0}, // S_CPOS_XDIE4 + {SPR_CPOS,18,5,{NULL},S_CPOS_XDIE6,0,0}, // S_CPOS_XDIE5 + {SPR_CPOS,19,-1,{NULL},S_NULL,0,0}, // S_CPOS_XDIE6 + {SPR_CPOS,13,5,{NULL},S_CPOS_RAISE2,0,0}, // S_CPOS_RAISE1 + {SPR_CPOS,12,5,{NULL},S_CPOS_RAISE3,0,0}, // S_CPOS_RAISE2 + {SPR_CPOS,11,5,{NULL},S_CPOS_RAISE4,0,0}, // S_CPOS_RAISE3 + {SPR_CPOS,10,5,{NULL},S_CPOS_RAISE5,0,0}, // S_CPOS_RAISE4 + {SPR_CPOS,9,5,{NULL},S_CPOS_RAISE6,0,0}, // S_CPOS_RAISE5 + {SPR_CPOS,8,5,{NULL},S_CPOS_RAISE7,0,0}, // S_CPOS_RAISE6 + {SPR_CPOS,7,5,{NULL},S_CPOS_RUN1,0,0}, // S_CPOS_RAISE7 + {SPR_TROO,0,10,{.acm1=A_Look},S_TROO_STND2,0,0}, // S_TROO_STND + {SPR_TROO,1,10,{.acm1=A_Look},S_TROO_STND,0,0}, // S_TROO_STND2 + {SPR_TROO,0,3,{.acm1=A_Chase},S_TROO_RUN2,0,0}, // S_TROO_RUN1 + {SPR_TROO,0,3,{.acm1=A_Chase},S_TROO_RUN3,0,0}, // S_TROO_RUN2 + {SPR_TROO,1,3,{.acm1=A_Chase},S_TROO_RUN4,0,0}, // S_TROO_RUN3 + {SPR_TROO,1,3,{.acm1=A_Chase},S_TROO_RUN5,0,0}, // S_TROO_RUN4 + {SPR_TROO,2,3,{.acm1=A_Chase},S_TROO_RUN6,0,0}, // S_TROO_RUN5 + {SPR_TROO,2,3,{.acm1=A_Chase},S_TROO_RUN7,0,0}, // S_TROO_RUN6 + {SPR_TROO,3,3,{.acm1=A_Chase},S_TROO_RUN8,0,0}, // S_TROO_RUN7 + {SPR_TROO,3,3,{.acm1=A_Chase},S_TROO_RUN1,0,0}, // S_TROO_RUN8 + {SPR_TROO,4,8,{.acm1=A_FaceTarget},S_TROO_ATK2,0,0}, // S_TROO_ATK1 + {SPR_TROO,5,8,{.acm1=A_FaceTarget},S_TROO_ATK3,0,0}, // S_TROO_ATK2 + {SPR_TROO,6,6,{.acm1=A_TroopAttack},S_TROO_RUN1,0,0}, // S_TROO_ATK3 + {SPR_TROO,7,2,{NULL},S_TROO_PAIN2,0,0}, // S_TROO_PAIN + {SPR_TROO,7,2,{.acm1=A_Pain},S_TROO_RUN1,0,0}, // S_TROO_PAIN2 + {SPR_TROO,8,8,{NULL},S_TROO_DIE2,0,0}, // S_TROO_DIE1 + {SPR_TROO,9,8,{.acm1=A_Scream},S_TROO_DIE3,0,0}, // S_TROO_DIE2 + {SPR_TROO,10,6,{NULL},S_TROO_DIE4,0,0}, // S_TROO_DIE3 + {SPR_TROO,11,6,{.acm1=A_Fall},S_TROO_DIE5,0,0}, // S_TROO_DIE4 + {SPR_TROO,12,-1,{NULL},S_NULL,0,0}, // S_TROO_DIE5 + {SPR_TROO,13,5,{NULL},S_TROO_XDIE2,0,0}, // S_TROO_XDIE1 + {SPR_TROO,14,5,{.acm1=A_XScream},S_TROO_XDIE3,0,0}, // S_TROO_XDIE2 + {SPR_TROO,15,5,{NULL},S_TROO_XDIE4,0,0}, // S_TROO_XDIE3 + {SPR_TROO,16,5,{.acm1=A_Fall},S_TROO_XDIE5,0,0}, // S_TROO_XDIE4 + {SPR_TROO,17,5,{NULL},S_TROO_XDIE6,0,0}, // S_TROO_XDIE5 + {SPR_TROO,18,5,{NULL},S_TROO_XDIE7,0,0}, // S_TROO_XDIE6 + {SPR_TROO,19,5,{NULL},S_TROO_XDIE8,0,0}, // S_TROO_XDIE7 + {SPR_TROO,20,-1,{NULL},S_NULL,0,0}, // S_TROO_XDIE8 + {SPR_TROO,12,8,{NULL},S_TROO_RAISE2,0,0}, // S_TROO_RAISE1 + {SPR_TROO,11,8,{NULL},S_TROO_RAISE3,0,0}, // S_TROO_RAISE2 + {SPR_TROO,10,6,{NULL},S_TROO_RAISE4,0,0}, // S_TROO_RAISE3 + {SPR_TROO,9,6,{NULL},S_TROO_RAISE5,0,0}, // S_TROO_RAISE4 + {SPR_TROO,8,6,{NULL},S_TROO_RUN1,0,0}, // S_TROO_RAISE5 + {SPR_SARG,0,10,{.acm1=A_Look},S_SARG_STND2,0,0}, // S_SARG_STND + {SPR_SARG,1,10,{.acm1=A_Look},S_SARG_STND,0,0}, // S_SARG_STND2 + {SPR_SARG,0,2,{.acm1=A_Chase},S_SARG_RUN2,0,0}, // S_SARG_RUN1 + {SPR_SARG,0,2,{.acm1=A_Chase},S_SARG_RUN3,0,0}, // S_SARG_RUN2 + {SPR_SARG,1,2,{.acm1=A_Chase},S_SARG_RUN4,0,0}, // S_SARG_RUN3 + {SPR_SARG,1,2,{.acm1=A_Chase},S_SARG_RUN5,0,0}, // S_SARG_RUN4 + {SPR_SARG,2,2,{.acm1=A_Chase},S_SARG_RUN6,0,0}, // S_SARG_RUN5 + {SPR_SARG,2,2,{.acm1=A_Chase},S_SARG_RUN7,0,0}, // S_SARG_RUN6 + {SPR_SARG,3,2,{.acm1=A_Chase},S_SARG_RUN8,0,0}, // S_SARG_RUN7 + {SPR_SARG,3,2,{.acm1=A_Chase},S_SARG_RUN1,0,0}, // S_SARG_RUN8 + {SPR_SARG,4,8,{.acm1=A_FaceTarget},S_SARG_ATK2,0,0}, // S_SARG_ATK1 + {SPR_SARG,5,8,{.acm1=A_FaceTarget},S_SARG_ATK3,0,0}, // S_SARG_ATK2 + {SPR_SARG,6,8,{.acm1=A_SargAttack},S_SARG_RUN1,0,0}, // S_SARG_ATK3 + {SPR_SARG,7,2,{NULL},S_SARG_PAIN2,0,0}, // S_SARG_PAIN + {SPR_SARG,7,2,{.acm1=A_Pain},S_SARG_RUN1,0,0}, // S_SARG_PAIN2 + {SPR_SARG,8,8,{NULL},S_SARG_DIE2,0,0}, // S_SARG_DIE1 + {SPR_SARG,9,8,{.acm1=A_Scream},S_SARG_DIE3,0,0}, // S_SARG_DIE2 + {SPR_SARG,10,4,{NULL},S_SARG_DIE4,0,0}, // S_SARG_DIE3 + {SPR_SARG,11,4,{.acm1=A_Fall},S_SARG_DIE5,0,0}, // S_SARG_DIE4 + {SPR_SARG,12,4,{NULL},S_SARG_DIE6,0,0}, // S_SARG_DIE5 + {SPR_SARG,13,-1,{NULL},S_NULL,0,0}, // S_SARG_DIE6 + {SPR_SARG,13,5,{NULL},S_SARG_RAISE2,0,0}, // S_SARG_RAISE1 + {SPR_SARG,12,5,{NULL},S_SARG_RAISE3,0,0}, // S_SARG_RAISE2 + {SPR_SARG,11,5,{NULL},S_SARG_RAISE4,0,0}, // S_SARG_RAISE3 + {SPR_SARG,10,5,{NULL},S_SARG_RAISE5,0,0}, // S_SARG_RAISE4 + {SPR_SARG,9,5,{NULL},S_SARG_RAISE6,0,0}, // S_SARG_RAISE5 + {SPR_SARG,8,5,{NULL},S_SARG_RUN1,0,0}, // S_SARG_RAISE6 + {SPR_HEAD,0,10,{.acm1=A_Look},S_HEAD_STND,0,0}, // S_HEAD_STND + {SPR_HEAD,0,3,{.acm1=A_Chase},S_HEAD_RUN1,0,0}, // S_HEAD_RUN1 + {SPR_HEAD,1,5,{.acm1=A_FaceTarget},S_HEAD_ATK2,0,0}, // S_HEAD_ATK1 + {SPR_HEAD,2,5,{.acm1=A_FaceTarget},S_HEAD_ATK3,0,0}, // S_HEAD_ATK2 + {SPR_HEAD,32771,5,{.acm1=A_HeadAttack},S_HEAD_RUN1,0,0}, // S_HEAD_ATK3 + {SPR_HEAD,4,3,{NULL},S_HEAD_PAIN2,0,0}, // S_HEAD_PAIN + {SPR_HEAD,4,3,{.acm1=A_Pain},S_HEAD_PAIN3,0,0}, // S_HEAD_PAIN2 + {SPR_HEAD,5,6,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_PAIN3 + {SPR_HEAD,6,8,{NULL},S_HEAD_DIE2,0,0}, // S_HEAD_DIE1 + {SPR_HEAD,7,8,{.acm1=A_Scream},S_HEAD_DIE3,0,0}, // S_HEAD_DIE2 + {SPR_HEAD,8,8,{NULL},S_HEAD_DIE4,0,0}, // S_HEAD_DIE3 + {SPR_HEAD,9,8,{NULL},S_HEAD_DIE5,0,0}, // S_HEAD_DIE4 + {SPR_HEAD,10,8,{.acm1=A_Fall},S_HEAD_DIE6,0,0}, // S_HEAD_DIE5 + {SPR_HEAD,11,-1,{NULL},S_NULL,0,0}, // S_HEAD_DIE6 + {SPR_HEAD,11,8,{NULL},S_HEAD_RAISE2,0,0}, // S_HEAD_RAISE1 + {SPR_HEAD,10,8,{NULL},S_HEAD_RAISE3,0,0}, // S_HEAD_RAISE2 + {SPR_HEAD,9,8,{NULL},S_HEAD_RAISE4,0,0}, // S_HEAD_RAISE3 + {SPR_HEAD,8,8,{NULL},S_HEAD_RAISE5,0,0}, // S_HEAD_RAISE4 + {SPR_HEAD,7,8,{NULL},S_HEAD_RAISE6,0,0}, // S_HEAD_RAISE5 + {SPR_HEAD,6,8,{NULL},S_HEAD_RUN1,0,0}, // S_HEAD_RAISE6 + {SPR_BAL7,32768,4,{NULL},S_BRBALL2,0,0}, // S_BRBALL1 + {SPR_BAL7,32769,4,{NULL},S_BRBALL1,0,0}, // S_BRBALL2 + {SPR_BAL7,32770,6,{NULL},S_BRBALLX2,0,0}, // S_BRBALLX1 + {SPR_BAL7,32771,6,{NULL},S_BRBALLX3,0,0}, // S_BRBALLX2 + {SPR_BAL7,32772,6,{NULL},S_NULL,0,0}, // S_BRBALLX3 + {SPR_BOSS,0,10,{.acm1=A_Look},S_BOSS_STND2,0,0}, // S_BOSS_STND + {SPR_BOSS,1,10,{.acm1=A_Look},S_BOSS_STND,0,0}, // S_BOSS_STND2 + {SPR_BOSS,0,3,{.acm1=A_Chase},S_BOSS_RUN2,0,0}, // S_BOSS_RUN1 + {SPR_BOSS,0,3,{.acm1=A_Chase},S_BOSS_RUN3,0,0}, // S_BOSS_RUN2 + {SPR_BOSS,1,3,{.acm1=A_Chase},S_BOSS_RUN4,0,0}, // S_BOSS_RUN3 + {SPR_BOSS,1,3,{.acm1=A_Chase},S_BOSS_RUN5,0,0}, // S_BOSS_RUN4 + {SPR_BOSS,2,3,{.acm1=A_Chase},S_BOSS_RUN6,0,0}, // S_BOSS_RUN5 + {SPR_BOSS,2,3,{.acm1=A_Chase},S_BOSS_RUN7,0,0}, // S_BOSS_RUN6 + {SPR_BOSS,3,3,{.acm1=A_Chase},S_BOSS_RUN8,0,0}, // S_BOSS_RUN7 + {SPR_BOSS,3,3,{.acm1=A_Chase},S_BOSS_RUN1,0,0}, // S_BOSS_RUN8 + {SPR_BOSS,4,8,{.acm1=A_FaceTarget},S_BOSS_ATK2,0,0}, // S_BOSS_ATK1 + {SPR_BOSS,5,8,{.acm1=A_FaceTarget},S_BOSS_ATK3,0,0}, // S_BOSS_ATK2 + {SPR_BOSS,6,8,{.acm1=A_BruisAttack},S_BOSS_RUN1,0,0}, // S_BOSS_ATK3 + {SPR_BOSS,7,2,{NULL},S_BOSS_PAIN2,0,0}, // S_BOSS_PAIN + {SPR_BOSS,7,2,{.acm1=A_Pain},S_BOSS_RUN1,0,0}, // S_BOSS_PAIN2 + {SPR_BOSS,8,8,{NULL},S_BOSS_DIE2,0,0}, // S_BOSS_DIE1 + {SPR_BOSS,9,8,{.acm1=A_Scream},S_BOSS_DIE3,0,0}, // S_BOSS_DIE2 + {SPR_BOSS,10,8,{NULL},S_BOSS_DIE4,0,0}, // S_BOSS_DIE3 + {SPR_BOSS,11,8,{.acm1=A_Fall},S_BOSS_DIE5,0,0}, // S_BOSS_DIE4 + {SPR_BOSS,12,8,{NULL},S_BOSS_DIE6,0,0}, // S_BOSS_DIE5 + {SPR_BOSS,13,8,{NULL},S_BOSS_DIE7,0,0}, // S_BOSS_DIE6 + {SPR_BOSS,14,-1,{.acm1=A_BossDeath},S_NULL,0,0}, // S_BOSS_DIE7 + {SPR_BOSS,14,8,{NULL},S_BOSS_RAISE2,0,0}, // S_BOSS_RAISE1 + {SPR_BOSS,13,8,{NULL},S_BOSS_RAISE3,0,0}, // S_BOSS_RAISE2 + {SPR_BOSS,12,8,{NULL},S_BOSS_RAISE4,0,0}, // S_BOSS_RAISE3 + {SPR_BOSS,11,8,{NULL},S_BOSS_RAISE5,0,0}, // S_BOSS_RAISE4 + {SPR_BOSS,10,8,{NULL},S_BOSS_RAISE6,0,0}, // S_BOSS_RAISE5 + {SPR_BOSS,9,8,{NULL},S_BOSS_RAISE7,0,0}, // S_BOSS_RAISE6 + {SPR_BOSS,8,8,{NULL},S_BOSS_RUN1,0,0}, // S_BOSS_RAISE7 + {SPR_BOS2,0,10,{.acm1=A_Look},S_BOS2_STND2,0,0}, // S_BOS2_STND + {SPR_BOS2,1,10,{.acm1=A_Look},S_BOS2_STND,0,0}, // S_BOS2_STND2 + {SPR_BOS2,0,3,{.acm1=A_Chase},S_BOS2_RUN2,0,0}, // S_BOS2_RUN1 + {SPR_BOS2,0,3,{.acm1=A_Chase},S_BOS2_RUN3,0,0}, // S_BOS2_RUN2 + {SPR_BOS2,1,3,{.acm1=A_Chase},S_BOS2_RUN4,0,0}, // S_BOS2_RUN3 + {SPR_BOS2,1,3,{.acm1=A_Chase},S_BOS2_RUN5,0,0}, // S_BOS2_RUN4 + {SPR_BOS2,2,3,{.acm1=A_Chase},S_BOS2_RUN6,0,0}, // S_BOS2_RUN5 + {SPR_BOS2,2,3,{.acm1=A_Chase},S_BOS2_RUN7,0,0}, // S_BOS2_RUN6 + {SPR_BOS2,3,3,{.acm1=A_Chase},S_BOS2_RUN8,0,0}, // S_BOS2_RUN7 + {SPR_BOS2,3,3,{.acm1=A_Chase},S_BOS2_RUN1,0,0}, // S_BOS2_RUN8 + {SPR_BOS2,4,8,{.acm1=A_FaceTarget},S_BOS2_ATK2,0,0}, // S_BOS2_ATK1 + {SPR_BOS2,5,8,{.acm1=A_FaceTarget},S_BOS2_ATK3,0,0}, // S_BOS2_ATK2 + {SPR_BOS2,6,8,{.acm1=A_BruisAttack},S_BOS2_RUN1,0,0}, // S_BOS2_ATK3 + {SPR_BOS2,7,2,{NULL},S_BOS2_PAIN2,0,0}, // S_BOS2_PAIN + {SPR_BOS2,7,2,{.acm1=A_Pain},S_BOS2_RUN1,0,0}, // S_BOS2_PAIN2 + {SPR_BOS2,8,8,{NULL},S_BOS2_DIE2,0,0}, // S_BOS2_DIE1 + {SPR_BOS2,9,8,{.acm1=A_Scream},S_BOS2_DIE3,0,0}, // S_BOS2_DIE2 + {SPR_BOS2,10,8,{NULL},S_BOS2_DIE4,0,0}, // S_BOS2_DIE3 + {SPR_BOS2,11,8,{.acm1=A_Fall},S_BOS2_DIE5,0,0}, // S_BOS2_DIE4 + {SPR_BOS2,12,8,{NULL},S_BOS2_DIE6,0,0}, // S_BOS2_DIE5 + {SPR_BOS2,13,8,{NULL},S_BOS2_DIE7,0,0}, // S_BOS2_DIE6 + {SPR_BOS2,14,-1,{NULL},S_NULL,0,0}, // S_BOS2_DIE7 + {SPR_BOS2,14,8,{NULL},S_BOS2_RAISE2,0,0}, // S_BOS2_RAISE1 + {SPR_BOS2,13,8,{NULL},S_BOS2_RAISE3,0,0}, // S_BOS2_RAISE2 + {SPR_BOS2,12,8,{NULL},S_BOS2_RAISE4,0,0}, // S_BOS2_RAISE3 + {SPR_BOS2,11,8,{NULL},S_BOS2_RAISE5,0,0}, // S_BOS2_RAISE4 + {SPR_BOS2,10,8,{NULL},S_BOS2_RAISE6,0,0}, // S_BOS2_RAISE5 + {SPR_BOS2,9,8,{NULL},S_BOS2_RAISE7,0,0}, // S_BOS2_RAISE6 + {SPR_BOS2,8,8,{NULL},S_BOS2_RUN1,0,0}, // S_BOS2_RAISE7 + {SPR_SKUL,32768,10,{.acm1=A_Look},S_SKULL_STND2,0,0}, // S_SKULL_STND + {SPR_SKUL,32769,10,{.acm1=A_Look},S_SKULL_STND,0,0}, // S_SKULL_STND2 + {SPR_SKUL,32768,6,{.acm1=A_Chase},S_SKULL_RUN2,0,0}, // S_SKULL_RUN1 + {SPR_SKUL,32769,6,{.acm1=A_Chase},S_SKULL_RUN1,0,0}, // S_SKULL_RUN2 + {SPR_SKUL,32770,10,{.acm1=A_FaceTarget},S_SKULL_ATK2,0,0}, // S_SKULL_ATK1 + {SPR_SKUL,32771,4,{.acm1=A_SkullAttack},S_SKULL_ATK3,0,0}, // S_SKULL_ATK2 + {SPR_SKUL,32770,4,{NULL},S_SKULL_ATK4,0,0}, // S_SKULL_ATK3 + {SPR_SKUL,32771,4,{NULL},S_SKULL_ATK3,0,0}, // S_SKULL_ATK4 + {SPR_SKUL,32772,3,{NULL},S_SKULL_PAIN2,0,0}, // S_SKULL_PAIN + {SPR_SKUL,32772,3,{.acm1=A_Pain},S_SKULL_RUN1,0,0}, // S_SKULL_PAIN2 + {SPR_SKUL,32773,6,{NULL},S_SKULL_DIE2,0,0}, // S_SKULL_DIE1 + {SPR_SKUL,32774,6,{.acm1=A_Scream},S_SKULL_DIE3,0,0}, // S_SKULL_DIE2 + {SPR_SKUL,32775,6,{NULL},S_SKULL_DIE4,0,0}, // S_SKULL_DIE3 + {SPR_SKUL,32776,6,{.acm1=A_Fall},S_SKULL_DIE5,0,0}, // S_SKULL_DIE4 + {SPR_SKUL,9,6,{NULL},S_SKULL_DIE6,0,0}, // S_SKULL_DIE5 + {SPR_SKUL,10,6,{NULL},S_NULL,0,0}, // S_SKULL_DIE6 + {SPR_SPID,0,10,{.acm1=A_Look},S_SPID_STND2,0,0}, // S_SPID_STND + {SPR_SPID,1,10,{.acm1=A_Look},S_SPID_STND,0,0}, // S_SPID_STND2 + {SPR_SPID,0,3,{.acm1=A_Metal},S_SPID_RUN2,0,0}, // S_SPID_RUN1 + {SPR_SPID,0,3,{.acm1=A_Chase},S_SPID_RUN3,0,0}, // S_SPID_RUN2 + {SPR_SPID,1,3,{.acm1=A_Chase},S_SPID_RUN4,0,0}, // S_SPID_RUN3 + {SPR_SPID,1,3,{.acm1=A_Chase},S_SPID_RUN5,0,0}, // S_SPID_RUN4 + {SPR_SPID,2,3,{.acm1=A_Metal},S_SPID_RUN6,0,0}, // S_SPID_RUN5 + {SPR_SPID,2,3,{.acm1=A_Chase},S_SPID_RUN7,0,0}, // S_SPID_RUN6 + {SPR_SPID,3,3,{.acm1=A_Chase},S_SPID_RUN8,0,0}, // S_SPID_RUN7 + {SPR_SPID,3,3,{.acm1=A_Chase},S_SPID_RUN9,0,0}, // S_SPID_RUN8 + {SPR_SPID,4,3,{.acm1=A_Metal},S_SPID_RUN10,0,0}, // S_SPID_RUN9 + {SPR_SPID,4,3,{.acm1=A_Chase},S_SPID_RUN11,0,0}, // S_SPID_RUN10 + {SPR_SPID,5,3,{.acm1=A_Chase},S_SPID_RUN12,0,0}, // S_SPID_RUN11 + {SPR_SPID,5,3,{.acm1=A_Chase},S_SPID_RUN1,0,0}, // S_SPID_RUN12 + {SPR_SPID,32768,20,{.acm1=A_FaceTarget},S_SPID_ATK2,0,0}, // S_SPID_ATK1 + {SPR_SPID,32774,4,{.acm1=A_SPosAttack},S_SPID_ATK3,0,0}, // S_SPID_ATK2 + {SPR_SPID,32775,4,{.acm1=A_SPosAttack},S_SPID_ATK4,0,0}, // S_SPID_ATK3 + {SPR_SPID,32775,1,{.acm1=A_SpidRefire},S_SPID_ATK2,0,0}, // S_SPID_ATK4 + {SPR_SPID,8,3,{NULL},S_SPID_PAIN2,0,0}, // S_SPID_PAIN + {SPR_SPID,8,3,{.acm1=A_Pain},S_SPID_RUN1,0,0}, // S_SPID_PAIN2 + {SPR_SPID,9,20,{.acm1=A_Scream},S_SPID_DIE2,0,0}, // S_SPID_DIE1 + {SPR_SPID,10,10,{.acm1=A_Fall},S_SPID_DIE3,0,0}, // S_SPID_DIE2 + {SPR_SPID,11,10,{NULL},S_SPID_DIE4,0,0}, // S_SPID_DIE3 + {SPR_SPID,12,10,{NULL},S_SPID_DIE5,0,0}, // S_SPID_DIE4 + {SPR_SPID,13,10,{NULL},S_SPID_DIE6,0,0}, // S_SPID_DIE5 + {SPR_SPID,14,10,{NULL},S_SPID_DIE7,0,0}, // S_SPID_DIE6 + {SPR_SPID,15,10,{NULL},S_SPID_DIE8,0,0}, // S_SPID_DIE7 + {SPR_SPID,16,10,{NULL},S_SPID_DIE9,0,0}, // S_SPID_DIE8 + {SPR_SPID,17,10,{NULL},S_SPID_DIE10,0,0}, // S_SPID_DIE9 + {SPR_SPID,18,30,{NULL},S_SPID_DIE11,0,0}, // S_SPID_DIE10 + {SPR_SPID,18,-1,{.acm1=A_BossDeath},S_NULL,0,0}, // S_SPID_DIE11 + {SPR_BSPI,0,10,{.acm1=A_Look},S_BSPI_STND2,0,0}, // S_BSPI_STND + {SPR_BSPI,1,10,{.acm1=A_Look},S_BSPI_STND,0,0}, // S_BSPI_STND2 + {SPR_BSPI,0,20,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_SIGHT + {SPR_BSPI,0,3,{.acm1=A_BabyMetal},S_BSPI_RUN2,0,0}, // S_BSPI_RUN1 + {SPR_BSPI,0,3,{.acm1=A_Chase},S_BSPI_RUN3,0,0}, // S_BSPI_RUN2 + {SPR_BSPI,1,3,{.acm1=A_Chase},S_BSPI_RUN4,0,0}, // S_BSPI_RUN3 + {SPR_BSPI,1,3,{.acm1=A_Chase},S_BSPI_RUN5,0,0}, // S_BSPI_RUN4 + {SPR_BSPI,2,3,{.acm1=A_Chase},S_BSPI_RUN6,0,0}, // S_BSPI_RUN5 + {SPR_BSPI,2,3,{.acm1=A_Chase},S_BSPI_RUN7,0,0}, // S_BSPI_RUN6 + {SPR_BSPI,3,3,{.acm1=A_BabyMetal},S_BSPI_RUN8,0,0}, // S_BSPI_RUN7 + {SPR_BSPI,3,3,{.acm1=A_Chase},S_BSPI_RUN9,0,0}, // S_BSPI_RUN8 + {SPR_BSPI,4,3,{.acm1=A_Chase},S_BSPI_RUN10,0,0}, // S_BSPI_RUN9 + {SPR_BSPI,4,3,{.acm1=A_Chase},S_BSPI_RUN11,0,0}, // S_BSPI_RUN10 + {SPR_BSPI,5,3,{.acm1=A_Chase},S_BSPI_RUN12,0,0}, // S_BSPI_RUN11 + {SPR_BSPI,5,3,{.acm1=A_Chase},S_BSPI_RUN1,0,0}, // S_BSPI_RUN12 + {SPR_BSPI,32768,20,{.acm1=A_FaceTarget},S_BSPI_ATK2,0,0}, // S_BSPI_ATK1 + {SPR_BSPI,32774,4,{.acm1=A_BspiAttack},S_BSPI_ATK3,0,0}, // S_BSPI_ATK2 + {SPR_BSPI,32775,4,{NULL},S_BSPI_ATK4,0,0}, // S_BSPI_ATK3 + {SPR_BSPI,32775,1,{.acm1=A_SpidRefire},S_BSPI_ATK2,0,0}, // S_BSPI_ATK4 + {SPR_BSPI,8,3,{NULL},S_BSPI_PAIN2,0,0}, // S_BSPI_PAIN + {SPR_BSPI,8,3,{.acm1=A_Pain},S_BSPI_RUN1,0,0}, // S_BSPI_PAIN2 + {SPR_BSPI,9,20,{.acm1=A_Scream},S_BSPI_DIE2,0,0}, // S_BSPI_DIE1 + {SPR_BSPI,10,7,{.acm1=A_Fall},S_BSPI_DIE3,0,0}, // S_BSPI_DIE2 + {SPR_BSPI,11,7,{NULL},S_BSPI_DIE4,0,0}, // S_BSPI_DIE3 + {SPR_BSPI,12,7,{NULL},S_BSPI_DIE5,0,0}, // S_BSPI_DIE4 + {SPR_BSPI,13,7,{NULL},S_BSPI_DIE6,0,0}, // S_BSPI_DIE5 + {SPR_BSPI,14,7,{NULL},S_BSPI_DIE7,0,0}, // S_BSPI_DIE6 + {SPR_BSPI,15,-1,{.acm1=A_BossDeath},S_NULL,0,0}, // S_BSPI_DIE7 + {SPR_BSPI,15,5,{NULL},S_BSPI_RAISE2,0,0}, // S_BSPI_RAISE1 + {SPR_BSPI,14,5,{NULL},S_BSPI_RAISE3,0,0}, // S_BSPI_RAISE2 + {SPR_BSPI,13,5,{NULL},S_BSPI_RAISE4,0,0}, // S_BSPI_RAISE3 + {SPR_BSPI,12,5,{NULL},S_BSPI_RAISE5,0,0}, // S_BSPI_RAISE4 + {SPR_BSPI,11,5,{NULL},S_BSPI_RAISE6,0,0}, // S_BSPI_RAISE5 + {SPR_BSPI,10,5,{NULL},S_BSPI_RAISE7,0,0}, // S_BSPI_RAISE6 + {SPR_BSPI,9,5,{NULL},S_BSPI_RUN1,0,0}, // S_BSPI_RAISE7 + {SPR_APLS,32768,5,{NULL},S_ARACH_PLAZ2,0,0}, // S_ARACH_PLAZ + {SPR_APLS,32769,5,{NULL},S_ARACH_PLAZ,0,0}, // S_ARACH_PLAZ2 + {SPR_APBX,32768,5,{NULL},S_ARACH_PLEX2,0,0}, // S_ARACH_PLEX + {SPR_APBX,32769,5,{NULL},S_ARACH_PLEX3,0,0}, // S_ARACH_PLEX2 + {SPR_APBX,32770,5,{NULL},S_ARACH_PLEX4,0,0}, // S_ARACH_PLEX3 + {SPR_APBX,32771,5,{NULL},S_ARACH_PLEX5,0,0}, // S_ARACH_PLEX4 + {SPR_APBX,32772,5,{NULL},S_NULL,0,0}, // S_ARACH_PLEX5 + {SPR_CYBR,0,10,{.acm1=A_Look},S_CYBER_STND2,0,0}, // S_CYBER_STND + {SPR_CYBR,1,10,{.acm1=A_Look},S_CYBER_STND,0,0}, // S_CYBER_STND2 + {SPR_CYBR,0,3,{.acm1=A_Hoof},S_CYBER_RUN2,0,0}, // S_CYBER_RUN1 + {SPR_CYBR,0,3,{.acm1=A_Chase},S_CYBER_RUN3,0,0}, // S_CYBER_RUN2 + {SPR_CYBR,1,3,{.acm1=A_Chase},S_CYBER_RUN4,0,0}, // S_CYBER_RUN3 + {SPR_CYBR,1,3,{.acm1=A_Chase},S_CYBER_RUN5,0,0}, // S_CYBER_RUN4 + {SPR_CYBR,2,3,{.acm1=A_Chase},S_CYBER_RUN6,0,0}, // S_CYBER_RUN5 + {SPR_CYBR,2,3,{.acm1=A_Chase},S_CYBER_RUN7,0,0}, // S_CYBER_RUN6 + {SPR_CYBR,3,3,{.acm1=A_Metal},S_CYBER_RUN8,0,0}, // S_CYBER_RUN7 + {SPR_CYBR,3,3,{.acm1=A_Chase},S_CYBER_RUN1,0,0}, // S_CYBER_RUN8 + {SPR_CYBR,4,6,{.acm1=A_FaceTarget},S_CYBER_ATK2,0,0}, // S_CYBER_ATK1 + {SPR_CYBR,5,12,{.acm1=A_CyberAttack},S_CYBER_ATK3,0,0}, // S_CYBER_ATK2 + {SPR_CYBR,4,12,{.acm1=A_FaceTarget},S_CYBER_ATK4,0,0}, // S_CYBER_ATK3 + {SPR_CYBR,5,12,{.acm1=A_CyberAttack},S_CYBER_ATK5,0,0}, // S_CYBER_ATK4 + {SPR_CYBR,4,12,{.acm1=A_FaceTarget},S_CYBER_ATK6,0,0}, // S_CYBER_ATK5 + {SPR_CYBR,5,12,{.acm1=A_CyberAttack},S_CYBER_RUN1,0,0}, // S_CYBER_ATK6 + {SPR_CYBR,6,10,{.acm1=A_Pain},S_CYBER_RUN1,0,0}, // S_CYBER_PAIN + {SPR_CYBR,7,10,{NULL},S_CYBER_DIE2,0,0}, // S_CYBER_DIE1 + {SPR_CYBR,8,10,{.acm1=A_Scream},S_CYBER_DIE3,0,0}, // S_CYBER_DIE2 + {SPR_CYBR,9,10,{NULL},S_CYBER_DIE4,0,0}, // S_CYBER_DIE3 + {SPR_CYBR,10,10,{NULL},S_CYBER_DIE5,0,0}, // S_CYBER_DIE4 + {SPR_CYBR,11,10,{NULL},S_CYBER_DIE6,0,0}, // S_CYBER_DIE5 + {SPR_CYBR,12,10,{.acm1=A_Fall},S_CYBER_DIE7,0,0}, // S_CYBER_DIE6 + {SPR_CYBR,13,10,{NULL},S_CYBER_DIE8,0,0}, // S_CYBER_DIE7 + {SPR_CYBR,14,10,{NULL},S_CYBER_DIE9,0,0}, // S_CYBER_DIE8 + {SPR_CYBR,15,30,{NULL},S_CYBER_DIE10,0,0}, // S_CYBER_DIE9 + {SPR_CYBR,15,-1,{.acm1=A_BossDeath},S_NULL,0,0}, // S_CYBER_DIE10 + {SPR_PAIN,0,10,{.acm1=A_Look},S_PAIN_STND,0,0}, // S_PAIN_STND + {SPR_PAIN,0,3,{.acm1=A_Chase},S_PAIN_RUN2,0,0}, // S_PAIN_RUN1 + {SPR_PAIN,0,3,{.acm1=A_Chase},S_PAIN_RUN3,0,0}, // S_PAIN_RUN2 + {SPR_PAIN,1,3,{.acm1=A_Chase},S_PAIN_RUN4,0,0}, // S_PAIN_RUN3 + {SPR_PAIN,1,3,{.acm1=A_Chase},S_PAIN_RUN5,0,0}, // S_PAIN_RUN4 + {SPR_PAIN,2,3,{.acm1=A_Chase},S_PAIN_RUN6,0,0}, // S_PAIN_RUN5 + {SPR_PAIN,2,3,{.acm1=A_Chase},S_PAIN_RUN1,0,0}, // S_PAIN_RUN6 + {SPR_PAIN,3,5,{.acm1=A_FaceTarget},S_PAIN_ATK2,0,0}, // S_PAIN_ATK1 + {SPR_PAIN,4,5,{.acm1=A_FaceTarget},S_PAIN_ATK3,0,0}, // S_PAIN_ATK2 + {SPR_PAIN,32773,5,{.acm1=A_FaceTarget},S_PAIN_ATK4,0,0}, // S_PAIN_ATK3 + {SPR_PAIN,32773,0,{.acm1=A_PainAttack},S_PAIN_RUN1,0,0}, // S_PAIN_ATK4 + {SPR_PAIN,6,6,{NULL},S_PAIN_PAIN2,0,0}, // S_PAIN_PAIN + {SPR_PAIN,6,6,{.acm1=A_Pain},S_PAIN_RUN1,0,0}, // S_PAIN_PAIN2 + {SPR_PAIN,32775,8,{NULL},S_PAIN_DIE2,0,0}, // S_PAIN_DIE1 + {SPR_PAIN,32776,8,{.acm1=A_Scream},S_PAIN_DIE3,0,0}, // S_PAIN_DIE2 + {SPR_PAIN,32777,8,{NULL},S_PAIN_DIE4,0,0}, // S_PAIN_DIE3 + {SPR_PAIN,32778,8,{NULL},S_PAIN_DIE5,0,0}, // S_PAIN_DIE4 + {SPR_PAIN,32779,8,{.acm1=A_PainDie},S_PAIN_DIE6,0,0}, // S_PAIN_DIE5 + {SPR_PAIN,32780,8,{NULL},S_NULL,0,0}, // S_PAIN_DIE6 + {SPR_PAIN,12,8,{NULL},S_PAIN_RAISE2,0,0}, // S_PAIN_RAISE1 + {SPR_PAIN,11,8,{NULL},S_PAIN_RAISE3,0,0}, // S_PAIN_RAISE2 + {SPR_PAIN,10,8,{NULL},S_PAIN_RAISE4,0,0}, // S_PAIN_RAISE3 + {SPR_PAIN,9,8,{NULL},S_PAIN_RAISE5,0,0}, // S_PAIN_RAISE4 + {SPR_PAIN,8,8,{NULL},S_PAIN_RAISE6,0,0}, // S_PAIN_RAISE5 + {SPR_PAIN,7,8,{NULL},S_PAIN_RUN1,0,0}, // S_PAIN_RAISE6 + {SPR_SSWV,0,10,{.acm1=A_Look},S_SSWV_STND2,0,0}, // S_SSWV_STND + {SPR_SSWV,1,10,{.acm1=A_Look},S_SSWV_STND,0,0}, // S_SSWV_STND2 + {SPR_SSWV,0,3,{.acm1=A_Chase},S_SSWV_RUN2,0,0}, // S_SSWV_RUN1 + {SPR_SSWV,0,3,{.acm1=A_Chase},S_SSWV_RUN3,0,0}, // S_SSWV_RUN2 + {SPR_SSWV,1,3,{.acm1=A_Chase},S_SSWV_RUN4,0,0}, // S_SSWV_RUN3 + {SPR_SSWV,1,3,{.acm1=A_Chase},S_SSWV_RUN5,0,0}, // S_SSWV_RUN4 + {SPR_SSWV,2,3,{.acm1=A_Chase},S_SSWV_RUN6,0,0}, // S_SSWV_RUN5 + {SPR_SSWV,2,3,{.acm1=A_Chase},S_SSWV_RUN7,0,0}, // S_SSWV_RUN6 + {SPR_SSWV,3,3,{.acm1=A_Chase},S_SSWV_RUN8,0,0}, // S_SSWV_RUN7 + {SPR_SSWV,3,3,{.acm1=A_Chase},S_SSWV_RUN1,0,0}, // S_SSWV_RUN8 + {SPR_SSWV,4,10,{.acm1=A_FaceTarget},S_SSWV_ATK2,0,0}, // S_SSWV_ATK1 + {SPR_SSWV,5,10,{.acm1=A_FaceTarget},S_SSWV_ATK3,0,0}, // S_SSWV_ATK2 + {SPR_SSWV,32774,4,{.acm1=A_CPosAttack},S_SSWV_ATK4,0,0}, // S_SSWV_ATK3 + {SPR_SSWV,5,6,{.acm1=A_FaceTarget},S_SSWV_ATK5,0,0}, // S_SSWV_ATK4 + {SPR_SSWV,32774,4,{.acm1=A_CPosAttack},S_SSWV_ATK6,0,0}, // S_SSWV_ATK5 + {SPR_SSWV,5,1,{.acm1=A_CPosRefire},S_SSWV_ATK2,0,0}, // S_SSWV_ATK6 + {SPR_SSWV,7,3,{NULL},S_SSWV_PAIN2,0,0}, // S_SSWV_PAIN + {SPR_SSWV,7,3,{.acm1=A_Pain},S_SSWV_RUN1,0,0}, // S_SSWV_PAIN2 + {SPR_SSWV,8,5,{NULL},S_SSWV_DIE2,0,0}, // S_SSWV_DIE1 + {SPR_SSWV,9,5,{.acm1=A_Scream},S_SSWV_DIE3,0,0}, // S_SSWV_DIE2 + {SPR_SSWV,10,5,{.acm1=A_Fall},S_SSWV_DIE4,0,0}, // S_SSWV_DIE3 + {SPR_SSWV,11,5,{NULL},S_SSWV_DIE5,0,0}, // S_SSWV_DIE4 + {SPR_SSWV,12,-1,{NULL},S_NULL,0,0}, // S_SSWV_DIE5 + {SPR_SSWV,13,5,{NULL},S_SSWV_XDIE2,0,0}, // S_SSWV_XDIE1 + {SPR_SSWV,14,5,{.acm1=A_XScream},S_SSWV_XDIE3,0,0}, // S_SSWV_XDIE2 + {SPR_SSWV,15,5,{.acm1=A_Fall},S_SSWV_XDIE4,0,0}, // S_SSWV_XDIE3 + {SPR_SSWV,16,5,{NULL},S_SSWV_XDIE5,0,0}, // S_SSWV_XDIE4 + {SPR_SSWV,17,5,{NULL},S_SSWV_XDIE6,0,0}, // S_SSWV_XDIE5 + {SPR_SSWV,18,5,{NULL},S_SSWV_XDIE7,0,0}, // S_SSWV_XDIE6 + {SPR_SSWV,19,5,{NULL},S_SSWV_XDIE8,0,0}, // S_SSWV_XDIE7 + {SPR_SSWV,20,5,{NULL},S_SSWV_XDIE9,0,0}, // S_SSWV_XDIE8 + {SPR_SSWV,21,-1,{NULL},S_NULL,0,0}, // S_SSWV_XDIE9 + {SPR_SSWV,12,5,{NULL},S_SSWV_RAISE2,0,0}, // S_SSWV_RAISE1 + {SPR_SSWV,11,5,{NULL},S_SSWV_RAISE3,0,0}, // S_SSWV_RAISE2 + {SPR_SSWV,10,5,{NULL},S_SSWV_RAISE4,0,0}, // S_SSWV_RAISE3 + {SPR_SSWV,9,5,{NULL},S_SSWV_RAISE5,0,0}, // S_SSWV_RAISE4 + {SPR_SSWV,8,5,{NULL},S_SSWV_RUN1,0,0}, // S_SSWV_RAISE5 + {SPR_KEEN,0,-1,{NULL},S_KEENSTND,0,0}, // S_KEENSTND + {SPR_KEEN,0,6,{NULL},S_COMMKEEN2,0,0}, // S_COMMKEEN + {SPR_KEEN,1,6,{NULL},S_COMMKEEN3,0,0}, // S_COMMKEEN2 + {SPR_KEEN,2,6,{.acm1=A_Scream},S_COMMKEEN4,0,0}, // S_COMMKEEN3 + {SPR_KEEN,3,6,{NULL},S_COMMKEEN5,0,0}, // S_COMMKEEN4 + {SPR_KEEN,4,6,{NULL},S_COMMKEEN6,0,0}, // S_COMMKEEN5 + {SPR_KEEN,5,6,{NULL},S_COMMKEEN7,0,0}, // S_COMMKEEN6 + {SPR_KEEN,6,6,{NULL},S_COMMKEEN8,0,0}, // S_COMMKEEN7 + {SPR_KEEN,7,6,{NULL},S_COMMKEEN9,0,0}, // S_COMMKEEN8 + {SPR_KEEN,8,6,{NULL},S_COMMKEEN10,0,0}, // S_COMMKEEN9 + {SPR_KEEN,9,6,{NULL},S_COMMKEEN11,0,0}, // S_COMMKEEN10 + {SPR_KEEN,10,6,{.acm1=A_KeenDie},S_COMMKEEN12,0,0},// S_COMMKEEN11 + {SPR_KEEN,11,-1,{NULL},S_NULL,0,0}, // S_COMMKEEN12 + {SPR_KEEN,12,4,{NULL},S_KEENPAIN2,0,0}, // S_KEENPAIN + {SPR_KEEN,12,8,{.acm1=A_Pain},S_KEENSTND,0,0}, // S_KEENPAIN2 + {SPR_BBRN,0,-1,{NULL},S_NULL,0,0}, // S_BRAIN + {SPR_BBRN,1,36,{.acm1=A_BrainPain},S_BRAIN,0,0}, // S_BRAIN_PAIN + {SPR_BBRN,0,100,{.acm1=A_BrainScream},S_BRAIN_DIE2,0,0}, // S_BRAIN_DIE1 + {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE3,0,0}, // S_BRAIN_DIE2 + {SPR_BBRN,0,10,{NULL},S_BRAIN_DIE4,0,0}, // S_BRAIN_DIE3 + {SPR_BBRN,0,-1,{.acm1=A_BrainDie},S_NULL,0,0}, // S_BRAIN_DIE4 + {SPR_SSWV,0,10,{.acm1=A_Look},S_BRAINEYE,0,0}, // S_BRAINEYE + {SPR_SSWV,0,181,{.acm1=A_BrainAwake},S_BRAINEYE1,0,0}, // S_BRAINEYESEE + {SPR_SSWV,0,150,{.acm1=A_BrainSpit},S_BRAINEYE1,0,0}, // S_BRAINEYE1 + {SPR_BOSF,32768,3,{.acm1=A_SpawnSound},S_SPAWN2,0,0}, // S_SPAWN1 + {SPR_BOSF,32769,3,{.acm1=A_SpawnFly},S_SPAWN3,0,0}, // S_SPAWN2 + {SPR_BOSF,32770,3,{.acm1=A_SpawnFly},S_SPAWN4,0,0}, // S_SPAWN3 + {SPR_BOSF,32771,3,{.acm1=A_SpawnFly},S_SPAWN1,0,0}, // S_SPAWN4 + {SPR_FIRE,32768,4,{.acm1=A_Fire},S_SPAWNFIRE2,0,0}, // S_SPAWNFIRE1 + {SPR_FIRE,32769,4,{.acm1=A_Fire},S_SPAWNFIRE3,0,0}, // S_SPAWNFIRE2 + {SPR_FIRE,32770,4,{.acm1=A_Fire},S_SPAWNFIRE4,0,0}, // S_SPAWNFIRE3 + {SPR_FIRE,32771,4,{.acm1=A_Fire},S_SPAWNFIRE5,0,0}, // S_SPAWNFIRE4 + {SPR_FIRE,32772,4,{.acm1=A_Fire},S_SPAWNFIRE6,0,0}, // S_SPAWNFIRE5 + {SPR_FIRE,32773,4,{.acm1=A_Fire},S_SPAWNFIRE7,0,0}, // S_SPAWNFIRE6 + {SPR_FIRE,32774,4,{.acm1=A_Fire},S_SPAWNFIRE8,0,0}, // S_SPAWNFIRE7 + {SPR_FIRE,32775,4,{.acm1=A_Fire},S_NULL,0,0}, // S_SPAWNFIRE8 + {SPR_MISL,32769,10,{NULL},S_BRAINEXPLODE2,0,0}, // S_BRAINEXPLODE1 + {SPR_MISL,32770,10,{NULL},S_BRAINEXPLODE3,0,0}, // S_BRAINEXPLODE2 + {SPR_MISL,32771,10,{.acm1=A_BrainExplode},S_NULL,0,0}, // S_BRAINEXPLODE3 + {SPR_ARM1,0,6,{NULL},S_ARM1A,0,0}, // S_ARM1 + {SPR_ARM1,32769,7,{NULL},S_ARM1,0,0}, // S_ARM1A + {SPR_ARM2,0,6,{NULL},S_ARM2A,0,0}, // S_ARM2 + {SPR_ARM2,32769,6,{NULL},S_ARM2,0,0}, // S_ARM2A + {SPR_BAR1,0,6,{NULL},S_BAR2,0,0}, // S_BAR1 + {SPR_BAR1,1,6,{NULL},S_BAR1,0,0}, // S_BAR2 + {SPR_BEXP,32768,5,{NULL},S_BEXP2,0,0}, // S_BEXP + {SPR_BEXP,32769,5,{.acm1=A_Scream},S_BEXP3,0,0}, // S_BEXP2 + {SPR_BEXP,32770,5,{NULL},S_BEXP4,0,0}, // S_BEXP3 + {SPR_BEXP,32771,10,{.acm1=A_Explode},S_BEXP5,0,0}, // S_BEXP4 + {SPR_BEXP,32772,10,{NULL},S_NULL,0,0}, // S_BEXP5 + {SPR_FCAN,32768,4,{NULL},S_BBAR2,0,0}, // S_BBAR1 + {SPR_FCAN,32769,4,{NULL},S_BBAR3,0,0}, // S_BBAR2 + {SPR_FCAN,32770,4,{NULL},S_BBAR1,0,0}, // S_BBAR3 + {SPR_BON1,0,6,{NULL},S_BON1A,0,0}, // S_BON1 + {SPR_BON1,1,6,{NULL},S_BON1B,0,0}, // S_BON1A + {SPR_BON1,2,6,{NULL},S_BON1C,0,0}, // S_BON1B + {SPR_BON1,3,6,{NULL},S_BON1D,0,0}, // S_BON1C + {SPR_BON1,2,6,{NULL},S_BON1E,0,0}, // S_BON1D + {SPR_BON1,1,6,{NULL},S_BON1,0,0}, // S_BON1E + {SPR_BON2,0,6,{NULL},S_BON2A,0,0}, // S_BON2 + {SPR_BON2,1,6,{NULL},S_BON2B,0,0}, // S_BON2A + {SPR_BON2,2,6,{NULL},S_BON2C,0,0}, // S_BON2B + {SPR_BON2,3,6,{NULL},S_BON2D,0,0}, // S_BON2C + {SPR_BON2,2,6,{NULL},S_BON2E,0,0}, // S_BON2D + {SPR_BON2,1,6,{NULL},S_BON2,0,0}, // S_BON2E + {SPR_BKEY,0,10,{NULL},S_BKEY2,0,0}, // S_BKEY + {SPR_BKEY,32769,10,{NULL},S_BKEY,0,0}, // S_BKEY2 + {SPR_RKEY,0,10,{NULL},S_RKEY2,0,0}, // S_RKEY + {SPR_RKEY,32769,10,{NULL},S_RKEY,0,0}, // S_RKEY2 + {SPR_YKEY,0,10,{NULL},S_YKEY2,0,0}, // S_YKEY + {SPR_YKEY,32769,10,{NULL},S_YKEY,0,0}, // S_YKEY2 + {SPR_BSKU,0,10,{NULL},S_BSKULL2,0,0}, // S_BSKULL + {SPR_BSKU,32769,10,{NULL},S_BSKULL,0,0}, // S_BSKULL2 + {SPR_RSKU,0,10,{NULL},S_RSKULL2,0,0}, // S_RSKULL + {SPR_RSKU,32769,10,{NULL},S_RSKULL,0,0}, // S_RSKULL2 + {SPR_YSKU,0,10,{NULL},S_YSKULL2,0,0}, // S_YSKULL + {SPR_YSKU,32769,10,{NULL},S_YSKULL,0,0}, // S_YSKULL2 + {SPR_STIM,0,-1,{NULL},S_NULL,0,0}, // S_STIM + {SPR_MEDI,0,-1,{NULL},S_NULL,0,0}, // S_MEDI + {SPR_SOUL,32768,6,{NULL},S_SOUL2,0,0}, // S_SOUL + {SPR_SOUL,32769,6,{NULL},S_SOUL3,0,0}, // S_SOUL2 + {SPR_SOUL,32770,6,{NULL},S_SOUL4,0,0}, // S_SOUL3 + {SPR_SOUL,32771,6,{NULL},S_SOUL5,0,0}, // S_SOUL4 + {SPR_SOUL,32770,6,{NULL},S_SOUL6,0,0}, // S_SOUL5 + {SPR_SOUL,32769,6,{NULL},S_SOUL,0,0}, // S_SOUL6 + {SPR_PINV,32768,6,{NULL},S_PINV2,0,0}, // S_PINV + {SPR_PINV,32769,6,{NULL},S_PINV3,0,0}, // S_PINV2 + {SPR_PINV,32770,6,{NULL},S_PINV4,0,0}, // S_PINV3 + {SPR_PINV,32771,6,{NULL},S_PINV,0,0}, // S_PINV4 + {SPR_PSTR,32768,-1,{NULL},S_NULL,0,0}, // S_PSTR + {SPR_PINS,32768,6,{NULL},S_PINS2,0,0}, // S_PINS + {SPR_PINS,32769,6,{NULL},S_PINS3,0,0}, // S_PINS2 + {SPR_PINS,32770,6,{NULL},S_PINS4,0,0}, // S_PINS3 + {SPR_PINS,32771,6,{NULL},S_PINS,0,0}, // S_PINS4 + {SPR_MEGA,32768,6,{NULL},S_MEGA2,0,0}, // S_MEGA + {SPR_MEGA,32769,6,{NULL},S_MEGA3,0,0}, // S_MEGA2 + {SPR_MEGA,32770,6,{NULL},S_MEGA4,0,0}, // S_MEGA3 + {SPR_MEGA,32771,6,{NULL},S_MEGA,0,0}, // S_MEGA4 + {SPR_SUIT,32768,-1,{NULL},S_NULL,0,0}, // S_SUIT + {SPR_PMAP,32768,6,{NULL},S_PMAP2,0,0}, // S_PMAP + {SPR_PMAP,32769,6,{NULL},S_PMAP3,0,0}, // S_PMAP2 + {SPR_PMAP,32770,6,{NULL},S_PMAP4,0,0}, // S_PMAP3 + {SPR_PMAP,32771,6,{NULL},S_PMAP5,0,0}, // S_PMAP4 + {SPR_PMAP,32770,6,{NULL},S_PMAP6,0,0}, // S_PMAP5 + {SPR_PMAP,32769,6,{NULL},S_PMAP,0,0}, // S_PMAP6 + {SPR_PVIS,32768,6,{NULL},S_PVIS2,0,0}, // S_PVIS + {SPR_PVIS,1,6,{NULL},S_PVIS,0,0}, // S_PVIS2 + {SPR_CLIP,0,-1,{NULL},S_NULL,0,0}, // S_CLIP + {SPR_AMMO,0,-1,{NULL},S_NULL,0,0}, // S_AMMO + {SPR_ROCK,0,-1,{NULL},S_NULL,0,0}, // S_ROCK + {SPR_BROK,0,-1,{NULL},S_NULL,0,0}, // S_BROK + {SPR_CELL,0,-1,{NULL},S_NULL,0,0}, // S_CELL + {SPR_CELP,0,-1,{NULL},S_NULL,0,0}, // S_CELP + {SPR_SHEL,0,-1,{NULL},S_NULL,0,0}, // S_SHEL + {SPR_SBOX,0,-1,{NULL},S_NULL,0,0}, // S_SBOX + {SPR_BPAK,0,-1,{NULL},S_NULL,0,0}, // S_BPAK + {SPR_BFUG,0,-1,{NULL},S_NULL,0,0}, // S_BFUG + {SPR_MGUN,0,-1,{NULL},S_NULL,0,0}, // S_MGUN + {SPR_CSAW,0,-1,{NULL},S_NULL,0,0}, // S_CSAW + {SPR_LAUN,0,-1,{NULL},S_NULL,0,0}, // S_LAUN + {SPR_PLAS,0,-1,{NULL},S_NULL,0,0}, // S_PLAS + {SPR_SHOT,0,-1,{NULL},S_NULL,0,0}, // S_SHOT + {SPR_SGN2,0,-1,{NULL},S_NULL,0,0}, // S_SHOT2 + {SPR_COLU,32768,-1,{NULL},S_NULL,0,0}, // S_COLU + {SPR_SMT2,0,-1,{NULL},S_NULL,0,0}, // S_STALAG + {SPR_GOR1,0,10,{NULL},S_BLOODYTWITCH2,0,0}, // S_BLOODYTWITCH + {SPR_GOR1,1,15,{NULL},S_BLOODYTWITCH3,0,0}, // S_BLOODYTWITCH2 + {SPR_GOR1,2,8,{NULL},S_BLOODYTWITCH4,0,0}, // S_BLOODYTWITCH3 + {SPR_GOR1,1,6,{NULL},S_BLOODYTWITCH,0,0}, // S_BLOODYTWITCH4 + {SPR_PLAY,13,-1,{NULL},S_NULL,0,0}, // S_DEADTORSO + {SPR_PLAY,18,-1,{NULL},S_NULL,0,0}, // S_DEADBOTTOM + {SPR_POL2,0,-1,{NULL},S_NULL,0,0}, // S_HEADSONSTICK + {SPR_POL5,0,-1,{NULL},S_NULL,0,0}, // S_GIBS + {SPR_POL4,0,-1,{NULL},S_NULL,0,0}, // S_HEADONASTICK + {SPR_POL3,32768,6,{NULL},S_HEADCANDLES2,0,0}, // S_HEADCANDLES + {SPR_POL3,32769,6,{NULL},S_HEADCANDLES,0,0}, // S_HEADCANDLES2 + {SPR_POL1,0,-1,{NULL},S_NULL,0,0}, // S_DEADSTICK + {SPR_POL6,0,6,{NULL},S_LIVESTICK2,0,0}, // S_LIVESTICK + {SPR_POL6,1,8,{NULL},S_LIVESTICK,0,0}, // S_LIVESTICK2 + {SPR_GOR2,0,-1,{NULL},S_NULL,0,0}, // S_MEAT2 + {SPR_GOR3,0,-1,{NULL},S_NULL,0,0}, // S_MEAT3 + {SPR_GOR4,0,-1,{NULL},S_NULL,0,0}, // S_MEAT4 + {SPR_GOR5,0,-1,{NULL},S_NULL,0,0}, // S_MEAT5 + {SPR_SMIT,0,-1,{NULL},S_NULL,0,0}, // S_STALAGTITE + {SPR_COL1,0,-1,{NULL},S_NULL,0,0}, // S_TALLGRNCOL + {SPR_COL2,0,-1,{NULL},S_NULL,0,0}, // S_SHRTGRNCOL + {SPR_COL3,0,-1,{NULL},S_NULL,0,0}, // S_TALLREDCOL + {SPR_COL4,0,-1,{NULL},S_NULL,0,0}, // S_SHRTREDCOL + {SPR_CAND,32768,-1,{NULL},S_NULL,0,0}, // S_CANDLESTIK + {SPR_CBRA,32768,-1,{NULL},S_NULL,0,0}, // S_CANDELABRA + {SPR_COL6,0,-1,{NULL},S_NULL,0,0}, // S_SKULLCOL + {SPR_TRE1,0,-1,{NULL},S_NULL,0,0}, // S_TORCHTREE + {SPR_TRE2,0,-1,{NULL},S_NULL,0,0}, // S_BIGTREE + {SPR_ELEC,0,-1,{NULL},S_NULL,0,0}, // S_TECHPILLAR + {SPR_CEYE,32768,6,{NULL},S_EVILEYE2,0,0}, // S_EVILEYE + {SPR_CEYE,32769,6,{NULL},S_EVILEYE3,0,0}, // S_EVILEYE2 + {SPR_CEYE,32770,6,{NULL},S_EVILEYE4,0,0}, // S_EVILEYE3 + {SPR_CEYE,32769,6,{NULL},S_EVILEYE,0,0}, // S_EVILEYE4 + {SPR_FSKU,32768,6,{NULL},S_FLOATSKULL2,0,0}, // S_FLOATSKULL + {SPR_FSKU,32769,6,{NULL},S_FLOATSKULL3,0,0}, // S_FLOATSKULL2 + {SPR_FSKU,32770,6,{NULL},S_FLOATSKULL,0,0}, // S_FLOATSKULL3 + {SPR_COL5,0,14,{NULL},S_HEARTCOL2,0,0}, // S_HEARTCOL + {SPR_COL5,1,14,{NULL},S_HEARTCOL,0,0}, // S_HEARTCOL2 + {SPR_TBLU,32768,4,{NULL},S_BLUETORCH2,0,0}, // S_BLUETORCH + {SPR_TBLU,32769,4,{NULL},S_BLUETORCH3,0,0}, // S_BLUETORCH2 + {SPR_TBLU,32770,4,{NULL},S_BLUETORCH4,0,0}, // S_BLUETORCH3 + {SPR_TBLU,32771,4,{NULL},S_BLUETORCH,0,0}, // S_BLUETORCH4 + {SPR_TGRN,32768,4,{NULL},S_GREENTORCH2,0,0}, // S_GREENTORCH + {SPR_TGRN,32769,4,{NULL},S_GREENTORCH3,0,0}, // S_GREENTORCH2 + {SPR_TGRN,32770,4,{NULL},S_GREENTORCH4,0,0}, // S_GREENTORCH3 + {SPR_TGRN,32771,4,{NULL},S_GREENTORCH,0,0}, // S_GREENTORCH4 + {SPR_TRED,32768,4,{NULL},S_REDTORCH2,0,0}, // S_REDTORCH + {SPR_TRED,32769,4,{NULL},S_REDTORCH3,0,0}, // S_REDTORCH2 + {SPR_TRED,32770,4,{NULL},S_REDTORCH4,0,0}, // S_REDTORCH3 + {SPR_TRED,32771,4,{NULL},S_REDTORCH,0,0}, // S_REDTORCH4 + {SPR_SMBT,32768,4,{NULL},S_BTORCHSHRT2,0,0}, // S_BTORCHSHRT + {SPR_SMBT,32769,4,{NULL},S_BTORCHSHRT3,0,0}, // S_BTORCHSHRT2 + {SPR_SMBT,32770,4,{NULL},S_BTORCHSHRT4,0,0}, // S_BTORCHSHRT3 + {SPR_SMBT,32771,4,{NULL},S_BTORCHSHRT,0,0}, // S_BTORCHSHRT4 + {SPR_SMGT,32768,4,{NULL},S_GTORCHSHRT2,0,0}, // S_GTORCHSHRT + {SPR_SMGT,32769,4,{NULL},S_GTORCHSHRT3,0,0}, // S_GTORCHSHRT2 + {SPR_SMGT,32770,4,{NULL},S_GTORCHSHRT4,0,0}, // S_GTORCHSHRT3 + {SPR_SMGT,32771,4,{NULL},S_GTORCHSHRT,0,0}, // S_GTORCHSHRT4 + {SPR_SMRT,32768,4,{NULL},S_RTORCHSHRT2,0,0}, // S_RTORCHSHRT + {SPR_SMRT,32769,4,{NULL},S_RTORCHSHRT3,0,0}, // S_RTORCHSHRT2 + {SPR_SMRT,32770,4,{NULL},S_RTORCHSHRT4,0,0}, // S_RTORCHSHRT3 + {SPR_SMRT,32771,4,{NULL},S_RTORCHSHRT,0,0}, // S_RTORCHSHRT4 + {SPR_HDB1,0,-1,{NULL},S_NULL,0,0}, // S_HANGNOGUTS + {SPR_HDB2,0,-1,{NULL},S_NULL,0,0}, // S_HANGBNOBRAIN + {SPR_HDB3,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKDN + {SPR_HDB4,0,-1,{NULL},S_NULL,0,0}, // S_HANGTSKULL + {SPR_HDB5,0,-1,{NULL},S_NULL,0,0}, // S_HANGTLOOKUP + {SPR_HDB6,0,-1,{NULL},S_NULL,0,0}, // S_HANGTNOBRAIN + {SPR_POB1,0,-1,{NULL},S_NULL,0,0}, // S_COLONGIBS + {SPR_POB2,0,-1,{NULL},S_NULL,0,0}, // S_SMALLPOOL + {SPR_BRS1,0,-1,{NULL},S_NULL,0,0}, // S_BRAINSTEM + {SPR_TLMP,32768,4,{NULL},S_TECHLAMP2,0,0}, // S_TECHLAMP + {SPR_TLMP,32769,4,{NULL},S_TECHLAMP3,0,0}, // S_TECHLAMP2 + {SPR_TLMP,32770,4,{NULL},S_TECHLAMP4,0,0}, // S_TECHLAMP3 + {SPR_TLMP,32771,4,{NULL},S_TECHLAMP,0,0}, // S_TECHLAMP4 + {SPR_TLP2,32768,4,{NULL},S_TECH2LAMP2,0,0}, // S_TECH2LAMP + {SPR_TLP2,32769,4,{NULL},S_TECH2LAMP3,0,0}, // S_TECH2LAMP2 + {SPR_TLP2,32770,4,{NULL},S_TECH2LAMP4,0,0}, // S_TECH2LAMP3 + {SPR_TLP2,32771,4,{NULL},S_TECH2LAMP,0,0}, // S_TECH2LAMP4 + {SPR_TNT1,0,-1,{NULL},S_TNT1,0,0}, // S_TNT1 // phares 3/8/98 // killough 8/9/98: grenade - {SPR_MISL,32768,1000,A_Die,S_GRENADE}, // S_GRENADE + {SPR_MISL,32768,1000,{.acm1=A_Die},S_GRENADE,0,0}, // S_GRENADE // killough 8/10/98: variable damage explosion - {SPR_MISL,32769,4,A_Scream,S_DETONATE2}, // S_DETONATE - {SPR_MISL,32770,6,A_Detonate,S_DETONATE3}, // S_DETONATE2 - {SPR_MISL,32771,10,NULL,S_NULL}, // S_DETONATE3 + {SPR_MISL,32769,4,{.acm1=A_Scream},S_DETONATE2,0,0}, // S_DETONATE + {SPR_MISL,32770,6,{.acm1=A_Detonate},S_DETONATE3,0,0}, // S_DETONATE2 + {SPR_MISL,32771,10,{NULL},S_NULL,0,0}, // S_DETONATE3 // if dogs are disabled, dummy states are required for dehacked compatibility - {0,0,-1,NULL,S_NULL}, // S_DOGS_STND - {0,0,-1,NULL,S_NULL}, // S_DOGS_STND2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN6 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN7 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN8 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_PAIN - {0,0,-1,NULL,S_NULL}, // S_DOGS_PAIN2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE6 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE6 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_STND + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_STND2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN5 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN6 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN7 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RUN8 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_ATK1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_ATK2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_ATK3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_PAIN + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_PAIN2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE5 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_DIE6 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE5 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_DOGS_RAISE6 // add dummy beta bfg / lost soul frames for dehacked compatibility // fixes bug #1576151 (part 2) - {0,0,-1,NULL,S_NULL}, // S_OLDBFG1 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG2 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG3 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG4 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG5 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG6 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG7 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG8 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG9 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG10 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG11 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG12 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG13 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG14 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG15 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG16 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG17 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG18 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG19 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG20 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG21 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG22 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG23 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG24 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG25 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG26 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG27 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG28 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG29 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG30 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG31 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG32 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG33 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG34 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG35 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG36 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG37 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG38 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG39 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG40 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG41 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG42 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG43 - - {0,0,-1,NULL,S_NULL}, // S_PLS1BALL - {0,0,-1,NULL,S_NULL}, // S_PLS1BALL2 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP2 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP3 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP4 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP5 - - {0,0,-1,NULL,S_NULL}, // S_PLS2BALL - {0,0,-1,NULL,S_NULL}, // S_PLS2BALL2 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX1 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX2 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX3 - - {0,0,-1,NULL,S_NULL}, // S_BON3 - {0,0,-1,NULL,S_NULL}, // S_BON4 - - {0,0,-1,NULL,S_NULL}, // S_BSKUL_STND - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN4 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE4 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE5 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE6 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE7 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE8 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG5 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG6 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG7 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG8 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG9 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG10 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG11 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG12 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG13 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG14 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG15 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG16 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG17 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG18 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG19 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG20 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG21 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG22 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG23 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG24 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG25 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG26 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG27 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG28 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG29 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG30 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG31 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG32 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG33 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG34 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG35 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG36 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG37 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG38 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG39 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG40 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG41 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG42 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_OLDBFG43 + + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1BALL + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1BALL2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1EXP + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1EXP2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1EXP3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1EXP4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS1EXP5 + + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS2BALL + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS2BALL2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS2BALLX1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS2BALLX2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_PLS2BALLX3 + + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BON3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BON4 + + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_STND + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_RUN1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_RUN2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_RUN3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_RUN4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_ATK1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_ATK2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_ATK3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_PAIN1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_PAIN2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_PAIN3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE1 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE2 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE3 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE4 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE5 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE6 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE7 + {(spritenum_t)0,0,-1,{NULL},S_NULL,0,0}, // S_BSKUL_DIE8 // killough 10/98: mushroom effect - {SPR_MISL,32769,8,A_Mushroom,S_EXPLODE2}, // S_MUSHROOM + {SPR_MISL,32769,8,{.acm1=A_Mushroom},S_EXPLODE2,0,0}, // S_MUSHROOM }; // ******************************************************************** diff --git a/source/lprintf.c b/cppsrc/lprintf.cc similarity index 90% rename from source/lprintf.c rename to cppsrc/lprintf.cc index d5ef6bc2..b2f7b2e2 100644 --- a/source/lprintf.c +++ b/cppsrc/lprintf.cc @@ -39,30 +39,33 @@ #include -#include +//#include #include #include "doomtype.h" #include "lprintf.h" #include "i_main.h" +#include + +#include "annotations.h" /* cphipps - enlarged message buffer and made non-static * We still have to be careful here, this function can be called after exit */ #define MAX_MESSAGE_SIZE 128 -int lprintf(OutputLevels pri, const char *s, ...) +int lprintf(OutputLevels pri UNUSED, const char *s, ...) { char msg[MAX_MESSAGE_SIZE]; va_list v; va_start(v,s); - vsprintf(msg,s,v); + vsnprintf(msg,MAX_MESSAGE_SIZE-1,s,v); va_end(v); - int len = strlen(msg); + //int len = strlen(msg); printf("%s\n", msg); diff --git a/source/m_bbox.c b/cppsrc/m_bbox.cc similarity index 100% rename from source/m_bbox.c rename to cppsrc/m_bbox.cc diff --git a/source/m_cheat.c b/cppsrc/m_cheat.cc similarity index 95% rename from source/m_cheat.c rename to cppsrc/m_cheat.cc index 975f0614..b4884745 100644 --- a/source/m_cheat.c +++ b/cppsrc/m_cheat.cc @@ -24,8 +24,8 @@ static void cheat_fps(void); typedef struct c_cheat { - char* name; - byte sequence[8]; + const char* name; + uint8_t sequence[8]; unsigned int packed_sequence; void (*cheat_function)(void); } c_cheat; @@ -53,7 +53,7 @@ static const c_cheat cheat_def[] = {"FPS Counter Ammo",CHEAT_SEQ(KEYD_A, KEYD_B, KEYD_L, KEYD_UP, KEYD_DOWN, KEYD_B, KEYD_LEFT, KEYD_LEFT), cheat_fps}, }; -static const unsigned int num_cheats = sizeof(cheat_def) / sizeof (c_cheat); +static const int num_cheats = sizeof(cheat_def) / sizeof (c_cheat); static boolean CheckCheats(unsigned int keybuff) { diff --git a/source/m_menu.c b/cppsrc/m_menu.cc similarity index 95% rename from source/m_menu.c rename to cppsrc/m_menu.cc index 156c6961..ad038cdc 100644 --- a/source/m_menu.c +++ b/cppsrc/m_menu.cc @@ -36,14 +36,14 @@ *-----------------------------------------------------------------------------*/ #include -#include +//#include #include "doomdef.h" #include "doomstat.h" #include "dstrings.h" #include "d_main.h" #include "v_video.h" -#include "w_wad.h" + #include "r_main.h" #include "hu_stuff.h" #include "g_game.h" @@ -59,6 +59,7 @@ #include "i_sound.h" #include "global_data.h" +#include "annotations.h" static void (*messageRoutine)(int response); @@ -315,7 +316,7 @@ void M_DrawNewGame(void) V_DrawNamePatch(54, 38, 0, "M_SKILL",CR_DEFAULT, VPT_STRETCH); } -void M_NewGame(int choice) +void M_NewGame(int choice UNUSED) { if ( _g->gamemode == commercial ) { @@ -333,19 +334,19 @@ static void M_VerifyNightmare(int ch) if (ch != key_enter) return; - G_DeferedInitNew(nightmare,_g->epi+1,1); + G_DeferedInitNew((skill_t)nightmare,_g->epi+1,1); } void M_ChooseSkill(int choice) { if (choice == nightmare) { // Ty 03/27/98 - externalized - M_StartMessage(NIGHTMARE,M_VerifyNightmare,true); + M_StartMessage(NIGHTMARE,(void *)M_VerifyNightmare,true); _g->itemOn = 0; } else { - G_DeferedInitNew(choice,_g->epi+1,1); + G_DeferedInitNew((skill_t)choice,_g->epi+1,1); M_ClearMenus (); } } @@ -422,19 +423,25 @@ void M_DrawSaveLoadBorder(int x,int y) { int i; - const patch_t* lpatch = W_CacheLumpName("M_LSLEFT"); - const patch_t* mpatch = W_CacheLumpName("M_LSCNTR"); - const patch_t* rpatch = W_CacheLumpName("M_LSRGHT"); - - V_DrawPatchNoScale(x-8, y+7, lpatch); + { + auto lpatch = Cached("M_LSLEFT").pin(); + V_DrawPatchNoScale(x-8, y+7, lpatch); + } - for (i = 0 ; i < 12 ; i++) { - V_DrawPatchNoScale(x, y+7, mpatch); - x += 8; + auto mpatch = Cached("M_LSCNTR").pin(); + + for (i = 0 ; i < 12 ; i++) + { + V_DrawPatchNoScale(x, y+7, mpatch); + x += 8; + } } - V_DrawPatchNoScale(x, y+7, rpatch); + { + auto rpatch = Cached("M_LSRGHT").pin(); + V_DrawPatchNoScale(x, y+7, rpatch); + } } // @@ -455,7 +462,7 @@ void M_LoadSelect(int choice) // Selected from DOOM menu // -void M_LoadGame (int choice) +void M_LoadGame (int choice UNUSED) { /* killough 5/26/98: exclude during demo recordings * cph - unless a new demo */ @@ -541,7 +548,7 @@ void M_SaveSelect(int choice) // // Selected from DOOM menu // -void M_SaveGame (int choice) +void M_SaveGame (int choice UNUSED) { // killough 10/6/98: allow savegames during single-player demo playback if (!_g->usergame && (!_g->demoplayback)) @@ -622,7 +629,7 @@ void M_DrawOptions(void) M_DrawThermo(OptionsDef.x + 158, OptionsDef.y+LINEHEIGHT*gamma+2,6,_g->gamma); } -void M_Options(int choice) +void M_Options(int choice UNUSED) { M_SetupNextMenu(&OptionsDef); } @@ -677,7 +684,7 @@ void M_DrawSound(void) M_DrawThermo(SoundDef.x,SoundDef.y+LINEHEIGHT*(music_vol+1),16,_g->snd_MusicVolume); } -void M_Sound(int choice) +void M_Sound(int choice UNUSED) { M_SetupNextMenu(&SoundDef); } @@ -738,9 +745,9 @@ static void M_EndGameResponse(int ch) D_StartTitle (); } -void M_EndGame(int choice) +void M_EndGame(int choice UNUSED) { - M_StartMessage(ENDGAME,M_EndGameResponse,true); // Ty 03/27/98 - externalized + M_StartMessage(ENDGAME,(void *)M_EndGameResponse,true); // Ty 03/27/98 - externalized } ///////////////////////////// @@ -748,7 +755,7 @@ void M_EndGame(int choice) // Toggle messages on/off // -void M_ChangeMessages(int choice) +void M_ChangeMessages(int choice UNUSED) { // warning: unused parameter `int choice' choice = 0; @@ -765,7 +772,7 @@ void M_ChangeMessages(int choice) } -void M_ChangeAlwaysRun(int choice) +void M_ChangeAlwaysRun(int choice UNUSED) { // warning: unused parameter `int choice' choice = 0; @@ -779,7 +786,7 @@ void M_ChangeAlwaysRun(int choice) G_SaveSettings(); } -void M_ChangeDetail(int choice) +void M_ChangeDetail(int choice UNUSED) { // warning: unused parameter `int choice' choice = 0; @@ -1139,7 +1146,7 @@ void M_StartMessage (const char* string,void* routine,boolean input) _g->messageLastMenuActive = _g->menuactive; _g->messageToPrint = 1; _g->messageString = string; - messageRoutine = routine; + messageRoutine = (void(*)(int))routine; _g->messageNeedsInput = input; _g->menuactive = true; return; @@ -1175,7 +1182,7 @@ void M_DrawThermo(int x,int y,int thermWidth,int thermDot ) horizScaler = (thermWidth > 23) ? (200 / thermWidth) : 8; //Dynamic range xx = x; - int thermm_lump = W_GetNumForName("M_THERMM"); + int thermm_lump = NC_GetNumForName("M_THERMM"); V_DrawNamePatch(xx, y, 0, "M_THERML", CR_DEFAULT, VPT_STRETCH); @@ -1256,7 +1263,8 @@ void M_WriteText (int x,int y,const char* string) } w = _g->hu_font[c]->width; - V_DrawPatchNoScale(cx, cy, _g->hu_font[c]); + auto pinned_font = Cached(_g->hu_font[c]).pin(); + V_DrawPatchNoScale(cx, cy, pinned_font); cx+=w; } } diff --git a/source/m_random.c b/cppsrc/m_random.cc similarity index 100% rename from source/m_random.c rename to cppsrc/m_random.cc diff --git a/source/m_recip.c b/cppsrc/m_recip.cc similarity index 92% rename from source/m_recip.c rename to cppsrc/m_recip.cc index 273190c5..69d539df 100644 --- a/source/m_recip.c +++ b/cppsrc/m_recip.cc @@ -1,4 +1,6 @@ -const extern unsigned int reciprocalTable[65537] = { +#include "m_recip.h" + +const unsigned int CONSTMEM _reciprocalTable[65537] = { 0, 4294967295, 2147483648, @@ -65537,3 +65539,5 @@ const extern unsigned int reciprocalTable[65537] = { 65537, 65536 }; + +ConstMemArray reciprocalTable(_reciprocalTable); diff --git a/source/p_ceilng.c b/cppsrc/p_ceilng.cc similarity index 96% rename from source/p_ceilng.c rename to cppsrc/p_ceilng.cc index 445deab3..a17e5377 100644 --- a/source/p_ceilng.c +++ b/cppsrc/p_ceilng.cc @@ -244,7 +244,7 @@ void T_MoveCeiling (ceiling_t* ceiling) // returns true if a thinker started // int EV_DoCeiling -( const line_t* line, +( Cached line, ceiling_e type ) { int secnum; @@ -279,11 +279,11 @@ int EV_DoCeiling // create a new ceiling thinker rtn = 1; - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + ceiling = (ceiling_t *)Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); memset(ceiling, 0, sizeof(*ceiling)); P_AddThinker (&ceiling->thinker); sec->ceilingdata = ceiling; //jff 2/22/98 - ceiling->thinker.function = T_MoveCeiling; + ceiling->thinker.function.acc1 = T_MoveCeiling; ceiling->sector = sec; ceiling->crush = false; @@ -366,7 +366,7 @@ int EV_DoCeiling // Returns true if a ceiling reactivated // //jff 4/5/98 return if activated -int P_ActivateInStasisCeiling(const line_t *line) +int P_ActivateInStasisCeiling(Cached line) { ceilinglist_t *cl; int rtn=0; @@ -377,7 +377,7 @@ int P_ActivateInStasisCeiling(const line_t *line) if (ceiling->tag == line->tag && ceiling->direction == 0) { ceiling->direction = ceiling->olddirection; - ceiling->thinker.function = T_MoveCeiling; + ceiling->thinker.function.acc1 = T_MoveCeiling; //jff 4/5/98 return if activated rtn=1; } @@ -393,7 +393,7 @@ int P_ActivateInStasisCeiling(const line_t *line) // Passed the linedef stopping the ceilings // Returns true if a ceiling put in stasis // -int EV_CeilingCrushStop(const line_t* line) +int EV_CeilingCrushStop(Cached line) { int rtn=0; @@ -405,7 +405,7 @@ int EV_CeilingCrushStop(const line_t* line) { ceiling->olddirection = ceiling->direction; ceiling->direction = 0; - ceiling->thinker.function = NULL; + ceiling->thinker.function.acc1 = NULL; rtn=1; } } @@ -424,14 +424,14 @@ void P_AddActiveCeiling(ceiling_t* ceiling) { ceilinglist_t *old_head = _g->activeceilings; - ceilinglist_t *list = Z_Malloc(sizeof *list, PU_LEVEL, &_g->activeceilings); + ceilinglist_t *list = (ceilinglist_t *)Z_Malloc(sizeof *list, PU_LEVEL, (void **)&_g->activeceilings); list->ceiling = ceiling; ceiling->list = list; if ((list->next = old_head)) list->next->prev = &list->next; - list->prev = old_head; + list->prev = &_g->activeceilings; } // diff --git a/source/p_doors.c b/cppsrc/p_doors.cc similarity index 94% rename from source/p_doors.c rename to cppsrc/p_doors.cc index be4e8040..282cb10c 100644 --- a/source/p_doors.c +++ b/cppsrc/p_doors.cc @@ -42,6 +42,8 @@ #include "global_data.h" +#include "annotations.h" + /////////////////////////////////////////////////////////////// // // Door action routines, called once per tick @@ -278,7 +280,7 @@ void T_VerticalDoor (vldoor_t* door) // Returns true if a thinker created // int EV_DoLockedDoor -( const line_t* line, +( Cached line, vldoor_e type, mobj_t* thing ) { @@ -338,7 +340,7 @@ int EV_DoLockedDoor // Returns true if a thinker created // int EV_DoDoor -( const line_t* line, +( Cached line, vldoor_e type ) { int secnum,rtn; @@ -358,12 +360,12 @@ int EV_DoDoor // new door thinker rtn = 1; - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); sec->ceilingdata = door; //jff 2/22/98 - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; door->type = type; door->topwait = VDOORWAIT; @@ -433,7 +435,7 @@ int EV_DoDoor // jff 2/12/98 added int return value, fixed all returns // int EV_VerticalDoor -( const line_t* line, +( Cached line, mobj_t* thing ) { player_t* player; @@ -503,7 +505,7 @@ int EV_VerticalDoor * Secondly, original Doom didn't distinguish floor/lighting/ceiling * actions, so we need to do the same in demo compatibility mode. */ - door = sec->ceilingdata; + door = (vldoor_t *)sec->ceilingdata; /* If this is a repeatable line, and the door is already moving, then we can just reverse the current action. Note that in prboom 2.3.0 I erroneously removed the if-this-is-repeatable check, hence the prboom_4_compatibility clause below (foolishly assumed that already moving implies repeatable - but it could be moving due to another switch, e.g. lv19-509) */ if (door && @@ -514,7 +516,7 @@ int EV_VerticalDoor /* For old demos we have to emulate the old buggy behavior and * mess up non-T_VerticalDoor actions. */ - if (door->thinker.function == T_VerticalDoor) + if (door->thinker.function.acd1 == T_VerticalDoor) { /* cph - we are writing outval to door->direction iff it is non-zero */ signed int outval = 0; @@ -523,7 +525,7 @@ int EV_VerticalDoor * monster is trying to open a closing door - so change direction * DEMOSYNC: we only read door->direction now if it really is a door. */ - if (door->thinker.function == T_VerticalDoor && door->direction == -1) { + if (door->thinker.function.acd1 == T_VerticalDoor && door->direction == -1) { outval = 1; /* go back up */ } else if (player) { outval = -1; /* go back down */ @@ -535,9 +537,9 @@ int EV_VerticalDoor * being corrupted by this. */ if (outval) { - if (door->thinker.function == T_VerticalDoor) { + if (door->thinker.function.acd1 == T_VerticalDoor) { door->direction = outval; - } else if (door->thinker.function == T_PlatRaise) { + } else if (door->thinker.function.acl1 == T_PlatRaise) { plat_t* p = (plat_t*)door; p->wait = outval; } else { @@ -567,11 +569,11 @@ int EV_VerticalDoor } // new door thinker - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); sec->ceilingdata = door; //jff 2/22/98 - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; door->direction = 1; door->speed = VDOORSPEED; @@ -639,7 +641,7 @@ void P_SpawnDoorCloseIn30 (sector_t* sec) { vldoor_t* door; - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); @@ -647,13 +649,13 @@ void P_SpawnDoorCloseIn30 (sector_t* sec) sec->ceilingdata = door; //jff 2/22/98 sec->special = 0; - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; door->direction = 0; door->type = normal; door->speed = VDOORSPEED; door->topcountdown = 30 * 35; - door->line = NULL; // jff 1/31/98 remember line that triggered us + door->line = Cached(); // jff 1/31/98 remember line that triggered us door->lighttag = 0; /* killough 10/98: no lighting changes */ } @@ -667,11 +669,11 @@ void P_SpawnDoorCloseIn30 (sector_t* sec) // void P_SpawnDoorRaiseIn5Mins ( sector_t* sec, - int secnum ) + int secnum UNUSED) { vldoor_t* door; - door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); @@ -679,7 +681,7 @@ void P_SpawnDoorRaiseIn5Mins sec->ceilingdata = door; //jff 2/22/98 sec->special = 0; - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; door->direction = 2; door->type = raiseIn5Mins; @@ -688,6 +690,6 @@ void P_SpawnDoorRaiseIn5Mins door->topheight -= 4*FRACUNIT; door->topwait = VDOORWAIT; door->topcountdown = 5 * 60 * 35; - door->line = NULL; // jff 1/31/98 remember line that triggered us + door->line = Cached(); // jff 1/31/98 remember line that triggered us door->lighttag = 0; /* killough 10/98: no lighting changes */ } diff --git a/source/p_enemy.c b/cppsrc/p_enemy.cc similarity index 95% rename from source/p_enemy.c rename to cppsrc/p_enemy.cc index 5433fde5..2621bc4b 100644 --- a/source/p_enemy.c +++ b/cppsrc/p_enemy.cc @@ -50,9 +50,10 @@ #include "lprintf.h" #include "global_data.h" +#include "annotations.h" const int distfriend = 128; - +line_t junk; typedef enum { DI_EAST, DI_NORTHEAST, @@ -100,7 +101,7 @@ static void P_RecursiveSound(sector_t *sec, int soundblocks, for (i=0; ilinecount; i++) { sector_t *other; - const line_t *check = sec->lines[i]; + auto check = sec->lines[i]; if (!(check->flags & ML_TWOSIDED)) continue; @@ -256,7 +257,7 @@ static boolean P_IsOnLift(const mobj_t *actor) const sector_t *sec = actor->subsector->sector; // Short-circuit: it's on a lift which is active. - if (sec->floordata && ((thinker_t *) sec->floordata)->function==T_PlatRaise) + if (sec->floordata && ((thinker_t *) sec->floordata)->function.acl1==T_PlatRaise) return true; return false; @@ -278,8 +279,8 @@ static int P_IsUnderDamage(mobj_t *actor) const ceiling_t *cl; // Crushing ceiling int dir = 0; for (seclist=actor->touching_sectorlist; seclist; seclist=seclist->m_tnext) - if ((cl = seclist->m_sector->ceilingdata) && - cl->thinker.function == T_MoveCeiling) + if ((cl = (const ceiling_t *)seclist->m_sector->ceilingdata) && + cl->thinker.function.acc1 == T_MoveCeiling) dir |= cl->direction; return dir; } @@ -354,7 +355,7 @@ static boolean P_Move(mobj_t *actor, boolean dropoff) /* killough 9/12/98 */ for (good = false; _g->numspechit--; ) if (P_UseSpecialLine(actor, _g->spechit[_g->numspechit], 0)) - good |= _g->spechit[_g->numspechit] == _g->blockline ? 1 : 2; + good |= _g->spechit[_g->numspechit]->lineno == _g->blockline->lineno ? 1 : 2; /* cph - compatibility maze here * Boom v2.01 and orig. Doom return "good" @@ -508,7 +509,7 @@ static void P_DoNewChaseDir(mobj_t *actor, fixed_t deltax, fixed_t deltay) // monsters to free themselves without making them tend to // hang over dropoffs. -static boolean PIT_AvoidDropoff(const line_t *line) +static boolean PIT_AvoidDropoff(Cached line) { if (LN_BACKSECTOR(line) && // Ignore one-sided linedefs _g->tmbbox[BOXRIGHT] > line->bbox[BOXLEFT] && @@ -694,14 +695,14 @@ static boolean P_LookForTargets(mobj_t *actor, int allaround) void A_KeenDie(mobj_t* mo) { thinker_t *th; - line_t junk; + A_Fall(mo); // scan the remaining thinkers to see if all Keens are dead for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - if (th->function == P_MobjThinker) + if (th->function.acm1 == P_MobjThinker) { mobj_t *mo2 = (mobj_t *) th; if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) @@ -709,7 +710,8 @@ void A_KeenDie(mobj_t* mo) } junk.tag = 666; - EV_DoDoor(&junk,dopen); + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoDoor(cjunk,dopen); } @@ -791,7 +793,7 @@ void A_Look(mobj_t *actor) else S_StartSound(actor, sound); } - P_SetMobjState(actor, mobjinfo[actor->type].seestate); + P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].seestate); } // @@ -830,7 +832,7 @@ void A_Chase(mobj_t *actor) if (!actor->target || !(actor->target->flags&MF_SHOOTABLE)) { if (!P_LookForTargets(actor,true)) // look for a new target - P_SetMobjState(actor, mobjinfo[actor->type].spawnstate); // no new target + P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].spawnstate); // no new target return; } @@ -849,7 +851,7 @@ void A_Chase(mobj_t *actor) if (mobjinfo[actor->type].attacksound) S_StartSound(actor, mobjinfo[actor->type].attacksound); - P_SetMobjState(actor, mobjinfo[actor->type].meleestate); + P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].meleestate); /* killough 8/98: remember an attack * cph - DEMOSYNC? */ if (!mobjinfo[actor->type].missilestate) @@ -864,7 +866,7 @@ void A_Chase(mobj_t *actor) { if (P_CheckMissileRange(actor)) { - P_SetMobjState(actor, mobjinfo[actor->type].missilestate); + P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].missilestate); actor->flags |= MF_JUSTATTACKED; return; } @@ -1015,7 +1017,7 @@ void A_CPosRefire(mobj_t *actor) if (!actor->target || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) -stop: P_SetMobjState(actor, mobjinfo[actor->type].seestate); +stop: P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].seestate); } void A_SpidRefire(mobj_t* actor) @@ -1034,7 +1036,7 @@ void A_SpidRefire(mobj_t* actor) if (!actor->target || actor->target->health <= 0 || actor->flags & actor->target->flags & MF_FRIEND || !P_CheckSight(actor, actor->target)) - stop: P_SetMobjState(actor, mobjinfo[actor->type].seestate); + stop: P_SetMobjState(actor, (statenum_t)mobjinfo[actor->type].seestate); } void A_BspiAttack(mobj_t *actor) @@ -1346,7 +1348,7 @@ void A_VileChase(mobj_t* actor) S_StartSound(_g->corpsehit, sfx_slop); info = &mobjinfo[_g->corpsehit->type]; - P_SetMobjState(_g->corpsehit,info->raisestate); + P_SetMobjState(_g->corpsehit,(statenum_t)info->raisestate); _g->corpsehit->height = info->height; // fix Ghost bug _g->corpsehit->radius = info->radius; // fix Ghost bug @@ -1748,7 +1750,6 @@ void A_Explode(mobj_t *thingy) void A_BossDeath(mobj_t *mo) { thinker_t *th; - line_t junk; if (_g->gamemode == commercial) { @@ -1822,7 +1823,7 @@ void A_BossDeath(mobj_t *mo) // scan the remaining thinkers to see // if all bosses are dead for (th = thinkercap.next ; th != &thinkercap ; th=th->next) - if (th->function == P_MobjThinker) + if (th->function.acm1 == P_MobjThinker) { mobj_t *mo2 = (mobj_t *) th; if (mo2 != mo && mo2->type == mo->type && mo2->health > 0) @@ -1837,14 +1838,16 @@ void A_BossDeath(mobj_t *mo) if (mo->type == MT_FATSO) { junk.tag = 666; - EV_DoFloor(&junk,lowerFloorToLowest); + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoFloor(cjunk,lowerFloorToLowest); return; } if (mo->type == MT_BABY) { junk.tag = 667; - EV_DoFloor(&junk,raiseToTexture); + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoFloor(cjunk,raiseToTexture); return; } } @@ -1854,23 +1857,30 @@ void A_BossDeath(mobj_t *mo) switch(_g->gameepisode) { case 1: + { junk.tag = 666; - EV_DoFloor(&junk, lowerFloorToLowest); + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoFloor(cjunk, lowerFloorToLowest); return; - + } case 4: switch(_g->gamemap) { case 6: + { junk.tag = 666; - EV_DoDoor(&junk, blazeOpen); + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoDoor(cjunk, blazeOpen); return; - + } case 8: - junk.tag = 666; - EV_DoFloor(&junk, lowerFloorToLowest); + { + junk.tag = 666; + auto cjunk = Cached(JUNK_LUMP_NUM); + EV_DoFloor(cjunk, lowerFloorToLowest); return; } + } } } G_ExitLevel(); @@ -1895,12 +1905,12 @@ void A_BabyMetal(mobj_t *mo) A_Chase(mo); } -void A_OpenShotgun2(player_t *player, pspdef_t *psp) +void A_OpenShotgun2(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_dbopn); } -void A_LoadShotgun2(player_t *player, pspdef_t *psp) +void A_LoadShotgun2(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_dbload); } @@ -1927,27 +1937,27 @@ void P_SpawnBrainTargets(void) // killough 3/26/98: renamed old function for (thinker = thinkercap.next ; thinker != &thinkercap ; thinker = thinker->next) - if (thinker->function == P_MobjThinker) + if (thinker->function.acm1 == P_MobjThinker) { mobj_t *m = (mobj_t *) thinker; if (m->type == MT_BOSSTARGET ) { // killough 2/7/98: remove limit on icon landings: if (_g->numbraintargets >= _g->numbraintargets_alloc) - _g->braintargets = Z_Realloc(_g->braintargets, + _g->braintargets = (mobj_t **)Z_Realloc(_g->braintargets, (_g->numbraintargets_alloc = _g->numbraintargets_alloc ? - _g->numbraintargets_alloc*2 : 32) *sizeof *_g->braintargets, PU_STATIC, NULL); + _g->numbraintargets_alloc*2 : 32) *sizeof *_g->braintargets, PU_LEVEL, NULL); _g->braintargets[_g->numbraintargets++] = m; } } } -void A_BrainAwake(mobj_t *mo) +void A_BrainAwake(mobj_t *mo UNUSED) { S_StartSound(NULL,sfx_bossit); // killough 3/26/98: only generates sound now } -void A_BrainPain(mobj_t *mo) +void A_BrainPain(mobj_t *mo UNUSED) { S_StartSound(NULL,sfx_bospn); } @@ -1983,7 +1993,7 @@ void A_BrainExplode(mobj_t *mo) th->tics = 1; } -void A_BrainDie(mobj_t *mo) +void A_BrainDie(mobj_t *mo UNUSED) { G_ExitLevel(); } @@ -2073,7 +2083,7 @@ void A_SpawnFly(mobj_t *mo) if (P_LookForTargets(newmobj,true)) /* killough 9/4/98 */ - P_SetMobjState(newmobj, mobjinfo[newmobj->type].seestate); + P_SetMobjState(newmobj, (statenum_t)mobjinfo[newmobj->type].seestate); // telefrag anything in this spot P_TeleportMove(newmobj, newmobj->x, newmobj->y, true); /* killough 8/9/98 */ @@ -2148,7 +2158,7 @@ void A_Spawn(mobj_t *mo) if (mo->state->misc1) { P_SpawnMobj(mo->x, mo->y, (mo->state->misc2 << FRACBITS) + mo->z, - mo->state->misc1 - 1); + (mobjtype_t)(mo->state->misc1 - 1)); } } @@ -2177,6 +2187,6 @@ void A_PlaySound(mobj_t *mo) void A_RandomJump(mobj_t *mo) { if (P_Random() < mo->state->misc2) - P_SetMobjState(mo, mo->state->misc1); + P_SetMobjState(mo, (statenum_t)mo->state->misc1); } diff --git a/source/p_floor.c b/cppsrc/p_floor.cc similarity index 96% rename from source/p_floor.c rename to cppsrc/p_floor.cc index b005a9b4..75950b9e 100644 --- a/source/p_floor.c +++ b/cppsrc/p_floor.cc @@ -388,7 +388,7 @@ void T_MoveElevator(elevator_t* elevator) // Returns true if a thinker was created. // int EV_DoFloor -( const line_t* line, +( Cached line, floor_e floortype ) { int secnum; @@ -410,11 +410,11 @@ int EV_DoFloor // new floor thinker rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; //jff 2/22/98 - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->type = floortype; floor->crush = false; @@ -608,7 +608,7 @@ int EV_DoFloor // jff 3/15/98 added to better support generalized sector types // int EV_DoChange -( const line_t* line, +( Cached line, change_e changetype ) { int secnum; @@ -673,7 +673,7 @@ int EV_DoChange * - Boom fixed the bug, and MBF/PrBoom without comp_stairs work right */ static inline int P_FindSectorFromLineTagWithLowerBound -(const line_t* l, int start, int min) +(Cached l, int start, int min) { /* Emulate original Doom's linear lower-bounded P_FindSectorFromLineTag * as needed */ @@ -684,7 +684,7 @@ static inline int P_FindSectorFromLineTagWithLowerBound } int EV_BuildStairs -( const line_t* line, +( Cached line, stair_e type ) { /* cph 2001/09/22 - cleaned up this function to save my sanity. A separate @@ -710,11 +710,11 @@ int EV_BuildStairs // create new floor thinker for first step rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->direction = 1; floor->sector = sec; floor->type = buildStair; //jff 3/31/98 do not leave uninited @@ -779,12 +779,12 @@ int EV_BuildStairs secnum = newsecnum; // create and initialize a thinker for the next step - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; //jff 2/22/98 - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->direction = 1; floor->sector = sec; floor->speed = speed; @@ -811,7 +811,7 @@ int EV_BuildStairs // Passed the linedef that triggered the donut // Returns whether a thinker was created // -int EV_DoDonut(const line_t* line) +int EV_DoDonut(Cached line) { sector_t* s1; sector_t* s2; @@ -854,11 +854,11 @@ int EV_DoDonut(const line_t* line) s3 = LN_BACKSECTOR((s2->lines[i])); // s3 is model sector for changes // Spawn rising slime - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); s2->floordata = floor; //jff 2/22/98 - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->type = donutRaise; floor->crush = false; floor->direction = 1; @@ -869,11 +869,11 @@ int EV_DoDonut(const line_t* line) floor->floordestheight = s3->floorheight; // Spawn lowering donut-hole pillar - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); s1->floordata = floor; //jff 2/22/98 - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->type = lowerFloor; floor->crush = false; floor->direction = -1; @@ -896,7 +896,7 @@ int EV_DoDonut(const line_t* line) // jff 2/22/98 new type to move floor and ceiling in parallel // int EV_DoElevator -( const line_t* line, +( Cached line, elevator_e elevtype ) { int secnum; @@ -917,12 +917,12 @@ int EV_DoElevator // create and initialize new elevator thinker rtn = 1; - elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0); + elevator = (elevator_t *)Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0); memset(elevator, 0, sizeof(*elevator)); P_AddThinker (&elevator->thinker); sec->floordata = elevator; //jff 2/22/98 sec->ceilingdata = elevator; //jff 2/22/98 - elevator->thinker.function = T_MoveElevator; + elevator->thinker.function.ace1 = T_MoveElevator; elevator->type = elevtype; // set up the fields according to the type of elevator action diff --git a/source/p_genlin.c b/cppsrc/p_genlin.cc similarity index 96% rename from source/p_genlin.c rename to cppsrc/p_genlin.cc index ddf6dfc9..890b0fbc 100644 --- a/source/p_genlin.c +++ b/cppsrc/p_genlin.cc @@ -60,7 +60,7 @@ // floor movers using bit fields in the line special type. // int EV_DoGenFloor -( const line_t* line ) +( Cached line ) { int secnum; int rtn; @@ -110,11 +110,11 @@ int EV_DoGenFloor // new floor thinker rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->crush = Crsh; floor->direction = Dirn? 1 : -1; floor->sector = sec; @@ -263,7 +263,7 @@ int EV_DoGenFloor // floor movers using bit fields in the line special type. // int EV_DoGenCeiling -( const line_t* line ) +( Cached line ) { int secnum; int rtn; @@ -314,11 +314,11 @@ int EV_DoGenCeiling // new ceiling thinker rtn = 1; - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + ceiling = (ceiling_t *)Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); memset(ceiling, 0, sizeof(*ceiling)); P_AddThinker (&ceiling->thinker); sec->ceilingdata = ceiling; //jff 2/22/98 - ceiling->thinker.function = T_MoveCeiling; + ceiling->thinker.function.acc1 = T_MoveCeiling; ceiling->crush = Crsh; ceiling->direction = Dirn? 1 : -1; ceiling->sector = sec; @@ -469,7 +469,7 @@ int EV_DoGenCeiling // Returns true if a thinker is created // int EV_DoGenLift -( const line_t* line ) +( Cached line ) { plat_t* plat; int secnum; @@ -521,13 +521,13 @@ int EV_DoGenLift // Setup the plat thinker rtn = 1; - plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); + plat = (plat_t *)Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); memset(plat, 0, sizeof(*plat)); P_AddThinker(&plat->thinker); plat->sector = sec; plat->sector->floordata = plat; - plat->thinker.function = T_PlatRaise; + plat->thinker.function.acl1 = T_PlatRaise; plat->crush = false; plat->tag = line->tag; @@ -559,7 +559,7 @@ int EV_DoGenLift plat->high = P_FindHighestFloorSurrounding(sec); if (plat->high < sec->floorheight) plat->high = sec->floorheight; - plat->status = P_Random()&1; + plat->status = (plat_e)(P_Random()&1); break; default: break; @@ -619,7 +619,7 @@ int EV_DoGenLift // Returns true if a thinker is created // int EV_DoGenStairs -( const line_t* line ) +( Cached line ) { int secnum; int osecnum; //jff 3/4/98 preserve loop index @@ -682,11 +682,11 @@ int EV_DoGenStairs // new floor thinker rtn = 1; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->direction = Dirn? 1 : -1; floor->sector = sec; @@ -768,13 +768,13 @@ int EV_DoGenStairs sec = tsec; secnum = newsecnum; - floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + floor = (floormove_t *)Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); memset(floor, 0, sizeof(*floor)); P_AddThinker (&floor->thinker); sec->floordata = floor; - floor->thinker.function = T_MoveFloor; + floor->thinker.function.acf1 = T_MoveFloor; floor->direction = Dirn? 1 : -1; floor->sector = sec; floor->speed = speed; @@ -805,7 +805,7 @@ int EV_DoGenStairs // Returns true if a thinker created // int EV_DoGenCrusher -( const line_t* line ) +( Cached line ) { int secnum; int rtn; @@ -853,11 +853,11 @@ int EV_DoGenCrusher // new ceiling thinker rtn = 1; - ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + ceiling = (ceiling_t *)Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); memset(ceiling, 0, sizeof(*ceiling)); P_AddThinker (&ceiling->thinker); sec->ceilingdata = ceiling; //jff 2/22/98 - ceiling->thinker.function = T_MoveCeiling; + ceiling->thinker.function.acc1 = T_MoveCeiling; ceiling->crush = true; ceiling->direction = -1; ceiling->sector = sec; @@ -903,7 +903,7 @@ int EV_DoGenCrusher // Returns true if a thinker created // int EV_DoGenLockedDoor -( const line_t* line ) +( Cached line ) { int secnum,rtn; sector_t* sec; @@ -949,12 +949,12 @@ int EV_DoGenLockedDoor // new door thinker rtn = 1; - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); sec->ceilingdata = door; //jff 2/22/98 - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; door->topwait = VDOORWAIT; door->line = line; @@ -1010,7 +1010,7 @@ int EV_DoGenLockedDoor // Returns true if a thinker created // int EV_DoGenDoor -( const line_t* line ) +( Cached line ) { int secnum,rtn; sector_t* sec; @@ -1058,12 +1058,12 @@ int EV_DoGenDoor // new door thinker rtn = 1; - door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + door = (vldoor_t *)Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); memset(door, 0, sizeof(*door)); P_AddThinker (&door->thinker); sec->ceilingdata = door; //jff 2/22/98 - door->thinker.function = T_VerticalDoor; + door->thinker.function.acd1 = T_VerticalDoor; door->sector = sec; // setup delay for door remaining open/closed switch(Dely) diff --git a/source/p_inter.c b/cppsrc/p_inter.cc similarity index 98% rename from source/p_inter.c rename to cppsrc/p_inter.cc index b4093b1b..a986627f 100644 --- a/source/p_inter.c +++ b/cppsrc/p_inter.cc @@ -512,7 +512,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher) player->backpack = true; } for (i=0 ; imessage = GOTBACKPACK; // Ty 03/22/98 - externalized break; @@ -629,9 +629,9 @@ static void P_KillMobj(mobj_t *source, mobj_t *target) } if (target->health < -mobjinfo[target->type].spawnhealth && mobjinfo[target->type].xdeathstate) - P_SetMobjState (target, mobjinfo[target->type].xdeathstate); + P_SetMobjState (target, (statenum_t)mobjinfo[target->type].xdeathstate); else - P_SetMobjState (target, mobjinfo[target->type].deathstate); + P_SetMobjState (target, (statenum_t)mobjinfo[target->type].deathstate); target->tics -= P_Random()&3; @@ -788,7 +788,7 @@ void P_DamageMobj(mobj_t *target,mobj_t *inflictor, mobj_t *source, int damage) { //killough 11/98: see below justhit = true; - P_SetMobjState(target, mobjinfo[target->type].painstate); + P_SetMobjState(target, (statenum_t)mobjinfo[target->type].painstate); } target->reactiontime = 0; // we're awake now... @@ -815,7 +815,7 @@ void P_DamageMobj(mobj_t *target,mobj_t *inflictor, mobj_t *source, int damage) target->threshold = BASETHRESHOLD; if (target->state == &states[mobjinfo[target->type].spawnstate] && mobjinfo[target->type].seestate != S_NULL) - P_SetMobjState (target, mobjinfo[target->type].seestate); + P_SetMobjState (target, (statenum_t)mobjinfo[target->type].seestate); } /* killough 11/98: Don't attack a friend, unless hit by that friend. diff --git a/source/p_lights.c b/cppsrc/p_lights.cc similarity index 94% rename from source/p_lights.c rename to cppsrc/p_lights.cc index 3ca6c1fc..e0a34fff 100644 --- a/source/p_lights.c +++ b/cppsrc/p_lights.cc @@ -184,12 +184,12 @@ void P_SpawnFireFlicker (sector_t* sector) // Nothing special about it during gameplay. sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type - flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); + flick = (fireflicker_t *)Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0); memset(flick, 0, sizeof(*flick)); P_AddThinker (&flick->thinker); - flick->thinker.function = T_FireFlicker; + flick->thinker.function.acr1 = T_FireFlicker; flick->sector = sector; flick->maxlight = sector->lightlevel; flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16; @@ -211,12 +211,12 @@ void P_SpawnLightFlash (sector_t* sector) // nothing special about it during gameplay sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + flash = (lightflash_t *)Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); memset(flash, 0, sizeof(*flash)); P_AddThinker (&flash->thinker); - flash->thinker.function = T_LightFlash; + flash->thinker.function.aci1 = T_LightFlash; flash->sector = sector; flash->maxlight = sector->lightlevel; @@ -243,7 +243,7 @@ void P_SpawnStrobeFlash { strobe_t* flash; - flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + flash = (strobe_t *)Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); memset(flash, 0, sizeof(*flash)); P_AddThinker (&flash->thinker); @@ -251,7 +251,7 @@ void P_SpawnStrobeFlash flash->sector = sector; flash->darktime = fastOrSlow; flash->brighttime = STROBEBRIGHT; - flash->thinker.function = T_StrobeFlash; + flash->thinker.function.aco1 = T_StrobeFlash; flash->maxlight = sector->lightlevel; flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel); @@ -279,7 +279,7 @@ void P_SpawnGlowingLight(sector_t* sector) { glow_t* g; - g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); + g = (glow_t *)Z_Malloc( sizeof(*g), PU_LEVSPEC, 0); memset(g, 0, sizeof(*g)); P_AddThinker(&g->thinker); @@ -287,7 +287,7 @@ void P_SpawnGlowingLight(sector_t* sector) g->sector = sector; g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel); g->maxlight = sector->lightlevel; - g->thinker.function = T_Glow; + g->thinker.function.acg1 = T_Glow; g->direction = -1; sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type @@ -309,7 +309,7 @@ void P_SpawnGlowingLight(sector_t* sector) // // jff 2/12/98 added int return value, fixed return // -int EV_StartLightStrobing(const line_t* line) +int EV_StartLightStrobing(Cached line) { int secnum; sector_t* sec; @@ -338,7 +338,7 @@ int EV_StartLightStrobing(const line_t* line) // // jff 2/12/98 added int return value, fixed return // -int EV_TurnTagLightsOff(const line_t* line) +int EV_TurnTagLightsOff(Cached line) { int j; @@ -370,7 +370,7 @@ int EV_TurnTagLightsOff(const line_t* line) // // jff 2/12/98 added int return value, fixed return // -int EV_LightTurnOn(const line_t *line, int bright) +int EV_LightTurnOn(Cached line, int bright) { int i; @@ -408,7 +408,7 @@ int EV_LightTurnOn(const line_t *line, int bright) * Returns true */ -int EV_LightTurnOnPartway(const line_t *line, fixed_t level) +int EV_LightTurnOnPartway(Cached line, fixed_t level) { int i; diff --git a/source/p_map.c b/cppsrc/p_map.cc similarity index 98% rename from source/p_map.c rename to cppsrc/p_map.cc index eeb1effc..8956ff97 100644 --- a/source/p_map.c +++ b/cppsrc/p_map.cc @@ -120,7 +120,7 @@ boolean P_TeleportMove (mobj_t* thing,fixed_t x,fixed_t y, boolean boss) _g->tmbbox[BOXLEFT] = x - _g->tmthing->radius; newsubsec = R_PointInSubsector (x,y); - _g->ceilingline = NULL; + _g->ceilingline = Cached(); // The base floor/ceiling is from the subsector // that contains the point. @@ -190,7 +190,7 @@ boolean P_TeleportMove (mobj_t* thing,fixed_t x,fixed_t y, boolean boss) // static // killough 3/26/98: make static -boolean PIT_CrossLine (const line_t* ld) +boolean PIT_CrossLine (Cached ld) { if (!(ld->flags & ML_TWOSIDED) || (ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS))) @@ -208,7 +208,7 @@ boolean PIT_CrossLine (const line_t* ld) * assuming NO movement occurs -- used to avoid sticky situations. */ -static int untouched(const line_t *ld) +static int untouched(Cached ld) { fixed_t x, y, tmbbox[4]; return @@ -225,7 +225,7 @@ static int untouched(const line_t *ld) // static // killough 3/26/98: make static -boolean PIT_CheckLine (const line_t* ld) +boolean PIT_CheckLine (Cached ld) { if (_g->tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || _g->tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] @@ -346,7 +346,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static _g->tmthing->flags &= ~MF_SKULLFLY; _g->tmthing->momx = _g->tmthing->momy = _g->tmthing->momz = 0; - P_SetMobjState (_g->tmthing, mobjinfo[_g->tmthing->type].spawnstate); + P_SetMobjState (_g->tmthing, (statenum_t)mobjinfo[_g->tmthing->type].spawnstate); return false; // stop moving } @@ -523,7 +523,7 @@ boolean P_CheckPosition (mobj_t* thing,fixed_t x,fixed_t y) _g->tmbbox[BOXLEFT] = x - _g->tmthing->radius; newsubsec = R_PointInSubsector (x,y); - _g->floorline = _g->blockline = _g->ceilingline = NULL; // killough 8/1/98 + _g->floorline = _g->blockline = _g->ceilingline = Cached(); // killough 8/1/98 // Whether object can get out of a sticky situation: _g->tmunstuck = P_MobjIsPlayer(thing) && /* only players */ @@ -604,8 +604,8 @@ boolean P_TryMove(mobj_t* thing,fixed_t x,fixed_t y, (!(thing->flags & MF_TELEPORT) && _g->tmfloorz - thing->z > 24*FRACUNIT)) return _g->tmunstuck - && !(_g->ceilingline && untouched(_g->ceilingline)) - && !( _g->floorline && untouched( _g->floorline)); + && !(_g->ceilingline.isvalid() && untouched(_g->ceilingline)) + && !( _g->floorline.isvalid() && untouched( _g->floorline)); /* killough 3/15/98: Allow certain objects to drop off * killough 7/24/98, 8/1/98: @@ -615,7 +615,7 @@ boolean P_TryMove(mobj_t* thing,fixed_t x,fixed_t y, */ if (!(thing->flags & (MF_DROPOFF|MF_FLOAT))) { - if (!dropoff || (dropoff==2 && // large jump down (e.g. dogs) + if (!dropoff || (/*dropoff==2 &&*/ // large jump down (e.g. dogs) (_g->tmfloorz-_g->tmdropoffz > 128*FRACUNIT || !thing->target || thing->target->z >_g->tmdropoffz))) { @@ -720,7 +720,7 @@ boolean P_ThingHeightClip (mobj_t* thing) // If the floor is icy, then you can bounce off a wall. // phares // -void P_HitSlideLine (const line_t* ld) +void P_HitSlideLine (Cached ld) { int side; angle_t lineangle; @@ -792,7 +792,7 @@ void P_HitSlideLine (const line_t* ld) boolean PTR_SlideTraverse (intercept_t* in) { - const line_t* li; + Cached li; if (!in->isaline) I_Error ("PTR_SlideTraverse: not a line?"); @@ -967,7 +967,7 @@ void P_SlideMove(mobj_t *mo) // boolean PTR_AimTraverse (intercept_t* in) { - const line_t* li; + Cached li; mobj_t* th; fixed_t slope; fixed_t thingtopslope; @@ -1075,7 +1075,7 @@ boolean PTR_ShootTraverse (intercept_t* in) if (in->isaline) { - const line_t *li = in->d.line; + auto li = in->d.line; if (LN_SPECIAL(li)) P_ShootSpecialLine (_g->shootthing, li); @@ -1293,7 +1293,7 @@ boolean PTR_UseTraverse (intercept_t* in) boolean PTR_NoWayTraverse(intercept_t* in) { - const line_t *ld = in->d.line; + auto ld = in->d.line; // This linedef return LN_SPECIAL(ld) || !( // Ignore specials ld->flags & ML_BLOCKING || ( // Always blocking @@ -1675,7 +1675,7 @@ void P_DelSeclist(msecnode_t* node) // at this location, so don't bother with checking impassable or // blocking lines. -boolean PIT_GetSectors(const line_t* ld) +boolean PIT_GetSectors(Cached ld) { if (_g->tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || _g->tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || diff --git a/source/p_maputl.c b/cppsrc/p_maputl.cc similarity index 96% rename from source/p_maputl.c rename to cppsrc/p_maputl.cc index bf2fd8e2..dd5dd49a 100644 --- a/source/p_maputl.c +++ b/cppsrc/p_maputl.cc @@ -63,7 +63,7 @@ fixed_t CONSTFUNC P_AproxDistance(fixed_t dx, fixed_t dy) // // killough 5/3/98: reformatted, cleaned up -int PUREFUNC P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line) +int PUREFUNC P_PointOnLineSide(fixed_t x, fixed_t y, Cached line) { return !line->dx ? x <= line->v1.x ? line->dy > 0 : line->dy < 0 : @@ -79,7 +79,7 @@ int PUREFUNC P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line) // // killough 5/3/98: reformatted, cleaned up -int PUREFUNC P_BoxOnLineSide(const fixed_t *tmbox, const line_t *ld) +int PUREFUNC P_BoxOnLineSide(const fixed_t *tmbox, Cached ld) { int p; switch (ld->slopetype) @@ -124,7 +124,7 @@ static int PUREFUNC P_PointOnDivlineSide(fixed_t x, fixed_t y, const divline_t * // P_MakeDivline // -static void P_MakeDivline(const line_t *li, divline_t *dl) +static void P_MakeDivline(Cached li, divline_t *dl) { dl->x = li->v1.x; dl->y = li->v1.y; @@ -159,7 +159,7 @@ fixed_t PUREFUNC P_InterceptVector2(const divline_t *v2, const divline_t *v1) // -void P_LineOpening(const line_t *linedef) +void P_LineOpening(Cached linedef) { if (linedef->sidenum[1] == NO_INDEX) // single sided line { @@ -336,14 +336,14 @@ void P_SetThingPosition(mobj_t *thing) // // killough 5/3/98: reformatted, cleaned up -boolean P_BlockLinesIterator(int x, int y, boolean func(const line_t*)) +boolean P_BlockLinesIterator(int x, int y, boolean func(Cached)) { if (x<0 || y<0 || x>=_g->bmapwidth || y>=_g->bmapheight) return true; - const int offset = _g->blockmap[y*_g->bmapwidth+x]; - const short* list = _g->blockmaplump+offset; // original was reading // phares + const int offset = *_g->blockmap[y*_g->bmapwidth+x]; + auto list = _g->blockmaplump.addOffset(offset); // original was reading // phares // delmiting 0 as linedef 0 // phares @@ -367,9 +367,9 @@ boolean P_BlockLinesIterator(int x, int y, boolean func(const line_t*)) lt->validcount = vcount; - const line_t *ld = &_g->lines[lineno]; + auto line = _g->lines[lineno]; - if (!func(ld)) + if (!func(line)) return false; } @@ -414,7 +414,7 @@ static boolean check_intercept(void) // // killough 5/3/98: reformatted, cleaned up -boolean PIT_AddLineIntercepts(const line_t *ld) +boolean PIT_AddLineIntercepts(Cached ld) { int s1; int s2; diff --git a/source/p_mobj.c b/cppsrc/p_mobj.cc similarity index 96% rename from source/p_mobj.c rename to cppsrc/p_mobj.cc index 4dfc866c..9da1830c 100644 --- a/source/p_mobj.c +++ b/cppsrc/p_mobj.cc @@ -48,6 +48,7 @@ #include "lprintf.h" #include "global_data.h" +#include "annotations.h" @@ -60,7 +61,7 @@ void P_ExplodeMissile (mobj_t* mo) { mo->momx = mo->momy = mo->momz = 0; - P_SetMobjState (mo, mobjinfo[mo->type].deathstate); + P_SetMobjState (mo, (statenum_t)mobjinfo[mo->type].deathstate); mo->tics -= P_Random()&3; @@ -95,7 +96,7 @@ void P_XYMovement (mobj_t* mo) mo->flags &= ~MF_SKULLFLY; mo->momz = 0; - P_SetMobjState (mo, mobjinfo[mo->type].spawnstate); + P_SetMobjState (mo, (statenum_t)mobjinfo[mo->type].spawnstate); } return; } @@ -152,7 +153,7 @@ void P_XYMovement (mobj_t* mo) { // explode a missile - if (_g->ceilingline) + if (_g->ceilingline.isvalid()) { const sector_t* ceilingBackSector = LN_BACKSECTOR(_g->ceilingline); @@ -456,7 +457,7 @@ void P_NightmareRespawn(mobj_t* mobj) // inherit attributes from deceased one - mo = P_SpawnMobj (x,y,z, mobj->type); + mo = P_SpawnMobj (x,y,z, (mobjtype_t)mobj->type); mo->angle = mobj->angle; /* killough 11/98: transfer friendliness from deceased */ @@ -492,16 +493,17 @@ void P_MobjBrainlessThinker(mobj_t* mobj) static think_t P_ThinkerFunctionForType(mobjtype_t type, mobj_t* mobj) { + think_t retval = {NULL}; //Full thinking ability. - if(type < MT_MISC0) - return P_MobjThinker; - - //Just state cycles. - if(mobj->tics != -1) - return P_MobjBrainlessThinker; - + if(type < MT_MISC0){ + retval.acm1 = P_MobjThinker; + } else { + //Just state cycles. + if(mobj->tics != -1) + retval.acm1 = P_MobjBrainlessThinker; + } //No thinking at all. - return NULL; + return retval; } // @@ -526,7 +528,7 @@ static mobj_t* P_NewMobj() if(mobj == NULL) { - mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + mobj = (mobj_t *)Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); memset (mobj, 0, sizeof (*mobj)); } @@ -535,7 +537,7 @@ static mobj_t* P_NewMobj() mobj_t* P_SpawnMobj(fixed_t x,fixed_t y,fixed_t z,mobjtype_t type) { - const state_t* st; + const state_t * st; const mobjinfo_t* info; mobj_t* mobj = P_NewMobj(); @@ -637,7 +639,7 @@ void P_RemoveMobj (mobj_t* mobj) * killough 8/24/98: rewrote to use hashing */ -static PUREFUNC int P_FindDoomedNum(unsigned int type) +static PUREFUNC int P_FindDoomedNum(int type) { // find which type to spawn for (int i=0 ; i< NUMMOBJTYPES ; i++) @@ -664,7 +666,7 @@ void P_RespawnSpecials (void) // between levels. // -void P_SpawnPlayer (int n, const mapthing_t* mthing) +void P_SpawnPlayer (int n UNUSED, const mapthing_t* mthing) { player_t* p; fixed_t x; @@ -753,10 +755,10 @@ boolean P_IsDoomnumAllowed(int doomnum) // // P_SpawnMapThing // The fields of the mapthing should -// already be in host byte order. +// already be in host uint8_t order. // -void P_SpawnMapThing (const mapthing_t* mthing) +void P_SpawnMapThing (Cached mthing) { int i; mobj_t* mobj; @@ -837,7 +839,7 @@ void P_SpawnMapThing (const mapthing_t* mthing) else z = ONFLOORZ; - mobj = P_SpawnMobj (x,y,z, i); + mobj = P_SpawnMobj (x,y,z, (mobjtype_t)i); if (mobj->tics > 0) mobj->tics = 1 + (P_Random () % mobj->tics); diff --git a/source/p_plats.c b/cppsrc/p_plats.cc similarity index 96% rename from source/p_plats.c rename to cppsrc/p_plats.cc index 56418808..378f1df1 100644 --- a/source/p_plats.c +++ b/cppsrc/p_plats.cc @@ -175,7 +175,7 @@ void T_PlatRaise(plat_t* plat) // Returns true if a thinker is started, or restarted from stasis // int EV_DoPlat -( const line_t* line, +( Cached line, plattype_e type, int amount ) { @@ -215,14 +215,14 @@ int EV_DoPlat // Create a thinker rtn = 1; - plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); + plat = (plat_t *)Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); memset(plat, 0, sizeof(*plat)); P_AddThinker(&plat->thinker); plat->type = type; plat->sector = sec; plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers - plat->thinker.function = T_PlatRaise; + plat->thinker.function.acl1 = T_PlatRaise; plat->crush = false; plat->tag = line->tag; @@ -295,7 +295,7 @@ int EV_DoPlat plat->high = sec->floorheight; plat->wait = 35*PLATWAIT; - plat->status = P_Random()&1; + plat->status = (plat_e)(P_Random()&1); S_StartSound2(&sec->soundorg,sfx_pstart); break; @@ -348,7 +348,7 @@ void P_ActivateInStasis(int tag) plat->status = plat->oldstatus==up? down : up; else plat->status = plat->oldstatus; - plat->thinker.function = T_PlatRaise; + plat->thinker.function.acl1 = T_PlatRaise; } } } @@ -363,7 +363,7 @@ void P_ActivateInStasis(int tag) // // jff 2/12/98 added int return value, fixed return // -int EV_StopPlat(const line_t* line) +int EV_StopPlat(Cached line) { platlist_t *pl; for (pl=_g->activeplats; pl; pl=pl->next) // search the active plats @@ -373,7 +373,7 @@ int EV_StopPlat(const line_t* line) { plat->oldstatus = plat->status; // put it in stasis plat->status = in_stasis; - plat->thinker.function = NULL; + plat->thinker.function.acl1 = NULL; } } return 1; @@ -391,13 +391,13 @@ void P_AddActivePlat(plat_t* plat) { platlist_t* old_head = _g->activeplats; - platlist_t *list = Z_Malloc(sizeof *list, PU_LEVEL, &_g->activeplats); + platlist_t *list = (platlist_t *)Z_Malloc(sizeof *list, PU_LEVEL, (void**)&_g->activeplats); list->plat = plat; plat->list = list; if ((list->next = old_head)) list->next->prev = &list->next; - list->prev = old_head; + list->prev = &_g->activeplats; } // diff --git a/source/p_pspr.c b/cppsrc/p_pspr.cc similarity index 91% rename from source/p_pspr.c rename to cppsrc/p_pspr.cc index 92c90b6c..44d4c710 100644 --- a/source/p_pspr.c +++ b/cppsrc/p_pspr.cc @@ -44,6 +44,7 @@ #include "d_event.h" #include "global_data.h" +#include "annotations.h" #define LOWERSPEED (FRACUNIT*6) #define RAISESPEED (FRACUNIT*6) @@ -86,9 +87,9 @@ static void P_SetPsprite(player_t *player, int position, statenum_t stnum) // Call action routine. // Modified handling. - if (state->action) + if (state->action.acp2) { - state->action(player, psp); + state->action.acp2(player, psp); if (!psp->state) break; } @@ -114,7 +115,7 @@ static void P_BringUpWeapon(player_t *player) if (player->pendingweapon == wp_chainsaw) S_StartSound (player->mo, sfx_sawup); - newstate = weaponinfo[player->pendingweapon].upstate; + newstate = (statenum_t)weaponinfo[player->pendingweapon].upstate; player->pendingweapon = wp_nochange; // killough 12/98: prevent pistol from starting visibly at bottom of screen: @@ -277,6 +278,9 @@ int P_CheckCanSwitchWeapon(weapontype_t weapon, player_t* player) return wp_supershotgun; } break; + + default: + break; } return wp_nochange; @@ -326,7 +330,7 @@ int P_WeaponCycleUp(player_t *player) if(!player->weaponowned[w]) continue; - if(P_CheckCanSwitchWeapon(w, player) != wp_nochange) + if(P_CheckCanSwitchWeapon((weapontype_t)w, player) != wp_nochange) return w; } @@ -348,36 +352,38 @@ int P_WeaponCycleDown(player_t *player) switch(w) { case wp_shotgun: - { - w = wp_supershotgun; - } - break; + { + w = wp_supershotgun; + } + break; case wp_chainsaw: - { - w = wp_shotgun; - } - break; + { + w = wp_shotgun; + } + break; case wp_fist: - { - w = wp_chainsaw; - } - break; + { + w = wp_chainsaw; + } + break; case wp_bfg: - { - w = wp_fist; - } - break; + { + w = wp_fist; + } + break; case wp_supershotgun: - { - w = wp_bfg; - } - break; + { + w = wp_bfg; + } + break; + default: + break; } if(!player->weaponowned[w]) continue; - if(P_CheckCanSwitchWeapon(w, player) != wp_nochange) + if(P_CheckCanSwitchWeapon((weapontype_t)w, player) != wp_nochange) return w; } @@ -423,7 +429,7 @@ static void P_FireWeapon(player_t *player) return; P_SetMobjState(player->mo, S_PLAY_ATK1); - newstate = weaponinfo[player->readyweapon].atkstate; + newstate = (statenum_t)weaponinfo[player->readyweapon].atkstate; P_SetPsprite(player, ps_weapon, newstate); P_NoiseAlert(player->mo, player->mo); } @@ -435,7 +441,7 @@ static void P_FireWeapon(player_t *player) void P_DropWeapon(player_t *player) { - P_SetPsprite(player, ps_weapon, weaponinfo[player->readyweapon].downstate); + P_SetPsprite(player, ps_weapon, (statenum_t)weaponinfo[player->readyweapon].downstate); } // @@ -462,7 +468,7 @@ void A_WeaponReady(player_t *player, pspdef_t *psp) if (player->pendingweapon != wp_nochange || !player->health) { // change weapon (pending weapon should already be validated) - statenum_t newstate = weaponinfo[player->readyweapon].downstate; + statenum_t newstate = (statenum_t)weaponinfo[player->readyweapon].downstate; P_SetPsprite(player, ps_weapon, newstate); return; } @@ -498,7 +504,7 @@ void A_WeaponReady(player_t *player, pspdef_t *psp) // without lowering it entirely. // -void A_ReFire(player_t *player, pspdef_t *psp) +void A_ReFire(player_t *player, pspdef_t *psp UNUSED) { // check for fire // (if a weaponchange is pending, let it go through instead) @@ -516,7 +522,7 @@ void A_ReFire(player_t *player, pspdef_t *psp) } } -void A_CheckReload(player_t *player, pspdef_t *psp) +void A_CheckReload(player_t *player, pspdef_t *psp UNUSED) { if (!P_CheckAmmo(player)) { @@ -525,7 +531,7 @@ void A_CheckReload(player_t *player, pspdef_t *psp) * rewritten. But we must tell Doom that we don't need to complete the * reload frames for the weapon here. G_BuildTiccmd will set ->pendingweapon * for us later on. */ - P_SetPsprite(player,ps_weapon,weaponinfo[player->readyweapon].downstate); + P_SetPsprite(player,ps_weapon,(statenum_t)weaponinfo[player->readyweapon].downstate); } } @@ -582,7 +588,7 @@ void A_Raise(player_t *player, pspdef_t *psp) // The weapon has been raised all the way, // so change to the ready state. - newstate = weaponinfo[player->readyweapon].readystate; + newstate = (statenum_t)weaponinfo[player->readyweapon].readystate; P_SetPsprite(player, ps_weapon, newstate); } @@ -598,14 +604,14 @@ void A_Raise(player_t *player, pspdef_t *psp) static void A_FireSomething(player_t* player,int adder) { P_SetPsprite(player, ps_flash, - weaponinfo[player->readyweapon].flashstate+adder); + (statenum_t)(weaponinfo[player->readyweapon].flashstate+adder)); } // // A_GunFlash // -void A_GunFlash(player_t *player, pspdef_t *psp) +void A_GunFlash(player_t *player, pspdef_t *psp UNUSED) { P_SetMobjState(player->mo, S_PLAY_ATK2); @@ -620,7 +626,7 @@ void A_GunFlash(player_t *player, pspdef_t *psp) // A_Punch // -void A_Punch(player_t *player, pspdef_t *psp) +void A_Punch(player_t *player, pspdef_t *psp UNUSED) { angle_t angle; int t, slope, damage = (P_Random()%10+1)<<1; @@ -657,7 +663,7 @@ void A_Punch(player_t *player, pspdef_t *psp) // A_Saw // -void A_Saw(player_t *player, pspdef_t *psp) +void A_Saw(player_t *player, pspdef_t *psp UNUSED) { int slope, damage = 2*(P_Random()%10+1); angle_t angle = player->mo->angle; @@ -687,7 +693,7 @@ void A_Saw(player_t *player, pspdef_t *psp) _g->linetarget->x, _g->linetarget->y); if (angle - player->mo->angle > ANG180) { - if (angle - player->mo->angle < -ANG90/20) + if (angle - player->mo->angle < (unsigned)(-ANG90/20)) player->mo->angle = angle + ANG90/21; else player->mo->angle -= ANG90/20; @@ -705,7 +711,7 @@ void A_Saw(player_t *player, pspdef_t *psp) // A_FireMissile // -void A_FireMissile(player_t *player, pspdef_t *psp) +void A_FireMissile(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_rlaunc); player->ammo[weaponinfo[player->readyweapon].ammo]--; @@ -716,7 +722,7 @@ void A_FireMissile(player_t *player, pspdef_t *psp) // A_FireBFG // -void A_FireBFG(player_t *player, pspdef_t *psp) +void A_FireBFG(player_t *player, pspdef_t *psp UNUSED) { player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; P_SpawnPlayerMissile(player->mo, MT_BFG); @@ -726,7 +732,7 @@ void A_FireBFG(player_t *player, pspdef_t *psp) // A_FirePlasma // -void A_FirePlasma(player_t *player, pspdef_t *psp) +void A_FirePlasma(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_plasma); player->ammo[weaponinfo[player->readyweapon].ammo]--; @@ -781,7 +787,7 @@ static void P_GunShot(mobj_t *mo, boolean accurate) // A_FirePistol // -void A_FirePistol(player_t *player, pspdef_t *psp) +void A_FirePistol(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_pistol); @@ -797,7 +803,7 @@ void A_FirePistol(player_t *player, pspdef_t *psp) // A_FireShotgun // -void A_FireShotgun(player_t *player, pspdef_t *psp) +void A_FireShotgun(player_t *player, pspdef_t *psp UNUSED) { int i; @@ -818,7 +824,7 @@ void A_FireShotgun(player_t *player, pspdef_t *psp) // A_FireShotgun2 // -void A_FireShotgun2(player_t *player, pspdef_t *psp) +void A_FireShotgun2(player_t *player, pspdef_t *psp UNUSED) { int i; @@ -865,17 +871,17 @@ void A_FireCGun(player_t *player, pspdef_t *psp) P_GunShot(player->mo, !player->refire); } -void A_Light0(player_t *player, pspdef_t *psp) +void A_Light0(player_t *player, pspdef_t *psp UNUSED) { player->extralight = 0; } -void A_Light1 (player_t *player, pspdef_t *psp) +void A_Light1 (player_t *player, pspdef_t *psp UNUSED) { player->extralight = 1; } -void A_Light2 (player_t *player, pspdef_t *psp) +void A_Light2 (player_t *player, pspdef_t *psp UNUSED) { player->extralight = 2; } @@ -919,7 +925,7 @@ void A_BFGSpray(mobj_t *mo) // A_BFGsound // -void A_BFGsound(player_t *player, pspdef_t *psp) +void A_BFGsound(player_t *player, pspdef_t *psp UNUSED) { S_StartSound(player->mo, sfx_bfg); } diff --git a/source/p_setup.c b/cppsrc/p_setup.cc similarity index 78% rename from source/p_setup.c rename to cppsrc/p_setup.cc index a95a8f00..0f8ef854 100644 --- a/source/p_setup.c +++ b/cppsrc/p_setup.cc @@ -37,7 +37,7 @@ #include "doomstat.h" #include "m_bbox.h" #include "g_game.h" -#include "w_wad.h" + #include "r_main.h" #include "r_things.h" #include "p_maputl.h" @@ -51,6 +51,7 @@ #include "v_video.h" #include "global_data.h" +#include "annotations.h" // // P_LoadVertexes @@ -60,11 +61,9 @@ static void P_LoadVertexes (int lump) { // Determine number of lumps: - // total lump length / vertex record length. - _g->numvertexes = W_LumpLength(lump) / sizeof(vertex_t); - // Allocate zone memory for buffer. - _g->vertexes = W_CacheLumpNum(lump); + _g->vertexes = CachedBuffer(lump); + _g->numvertexes = _g->vertexes.size(); } @@ -75,8 +74,9 @@ static void P_LoadVertexes (int lump) static void P_LoadSegs (int lump) { - int numsegs = W_LumpLength(lump) / sizeof(seg_t); - _g->segs = (const seg_t *)W_CacheLumpNum(lump); + // int numsegs = W_LumpLength(lump) / sizeof(seg_t); + _g->segs = CachedBuffer(lump); + int numsegs = _g->segs.size(); if (!numsegs) I_Error("P_LoadSegs: no segs in level"); @@ -90,20 +90,20 @@ static void P_LoadSegs (int lump) static void P_LoadSubsectors (int lump) { /* cph 2006/07/29 - make data a const mapsubsector_t *, so the loop below is simpler & gives no constness warnings */ - const mapsubsector_t *data; + int i; - _g->numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t); - _g->subsectors = Z_Calloc(_g->numsubsectors,sizeof(subsector_t),PU_LEVEL,0); - data = (const mapsubsector_t *)W_CacheLumpNum(lump); + auto data = CachedBuffer(lump); + _g->numsubsectors = data.size(); + _g->subsectors = (subsector_t *)Z_Calloc(_g->numsubsectors,sizeof(subsector_t),PU_LEVEL,0); - if ((!data) || (!_g->numsubsectors)) + if ((data.isnull()) || (!_g->numsubsectors)) I_Error("P_LoadSubsectors: no subsectors in level"); for (i=0; i<_g->numsubsectors; i++) { - _g->subsectors[i].numlines = (unsigned short)SHORT(data[i].numsegs ); - _g->subsectors[i].firstline = (unsigned short)SHORT(data[i].firstseg); + _g->subsectors[i].numlines = (unsigned short)SHORT(data[i]->numsegs ); + _g->subsectors[i].firstline = (unsigned short)SHORT(data[i]->firstseg); } } @@ -114,12 +114,14 @@ static void P_LoadSubsectors (int lump) static void P_LoadSectors (int lump) { - const byte *data; // cph - const* int i; - _g->numsectors = W_LumpLength (lump) / sizeof(mapsector_t); - _g->sectors = Z_Calloc (_g->numsectors,sizeof(sector_t),PU_LEVEL,0); - data = W_CacheLumpNum (lump); // cph - wad lump handling updated + auto sectors = CachedBuffer(lump); + _g->numsectors = sectors.size(); + _g->sectors = (sector_t *)Z_Calloc (_g->numsectors,sizeof(sector_t),PU_LEVEL,0); + auto databuffer = CachedBuffer(lump); // cph - wad lump handling updated + auto pinneddata = databuffer.pin(); + auto data = (const uint8_t *)pinneddata; for (i=0; i<_g->numsectors; i++) { @@ -149,10 +151,11 @@ static void P_LoadSectors (int lump) static void P_LoadNodes (int lump) { - numnodes = W_LumpLength (lump) / sizeof(mapnode_t); - nodes = W_CacheLumpNum (lump); // cph - wad lump handling updated + + nodes = CachedBuffer(lump); // cph - wad lump handling updated + numnodes = nodes.size(); - if ((!nodes) || (!numnodes)) + if ((nodes.isnull()) || (!numnodes)) { // allow trivial maps if (_g->numsubsectors == 1) @@ -169,18 +172,19 @@ static void P_LoadNodes (int lump) * * killough 5/3/98: reformatted, cleaned up * cph 2001/07/07 - don't write into the lump cache, especially non-idepotent - * changes like byte order reversals. Take a copy to edit. + * changes like uint8_t order reversals. Take a copy to edit. */ static void P_LoadThings (int lump) { - int i, numthings = W_LumpLength (lump) / sizeof(mapthing_t); - const mapthing_t *data = W_CacheLumpNum (lump); + int i; + auto data = CachedBuffer(lump); + int numthings = data.size(); - if ((!data) || (!numthings)) + if ((data.isnull()) || (!numthings)) I_Error("P_LoadThings: no things in level"); - _g->thingPool = Z_Calloc(numthings, sizeof(mobj_t), PU_LEVEL, NULL); + _g->thingPool = (mobj_t *)Z_Calloc(numthings, sizeof(mobj_t), PU_LEVEL, NULL); _g->thingPoolSize = numthings; for(int i = 0; i < numthings; i++) @@ -190,7 +194,7 @@ static void P_LoadThings (int lump) for (i=0; itype)) continue; @@ -215,21 +219,21 @@ static void P_LoadLineDefs (int lump) { int i; - _g->numlines = W_LumpLength (lump) / sizeof(line_t); - _g->lines = W_CacheLumpNum (lump); + _g->lines = CachedBuffer(lump); + _g->numlines = _g->lines.size(); - _g->linedata = Z_Calloc(_g->numlines,sizeof(linedata_t),PU_LEVEL,0); + _g->linedata = (linedata_t *)Z_Calloc(_g->numlines,sizeof(linedata_t),PU_LEVEL,0); for (i=0; i<_g->numlines; i++) { - _g->linedata[i].special = _g->lines[i].const_special; + _g->linedata[i].special = _g->lines[i]->const_special; } } // killough 4/4/98: delay using sidedefs until they are loaded // killough 5/3/98: reformatted, cleaned up -static void P_LoadLineDefs2(int lump) +static void P_LoadLineDefs2(int lump UNUSED) { /* int i = _g->numlines; @@ -249,8 +253,9 @@ static void P_LoadLineDefs2(int lump) static void P_LoadSideDefs (int lump) { - _g->numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); - _g->sides = Z_Calloc(_g->numsides,sizeof(side_t),PU_LEVEL,0); + auto sides = CachedBuffer(lump); + _g->numsides = sides.size(); + _g->sides = (side_t *)Z_Calloc(_g->numsides,sizeof(side_t),PU_LEVEL,0); } // killough 4/4/98: delay using texture names until @@ -259,14 +264,16 @@ static void P_LoadSideDefs (int lump) static void P_LoadSideDefs2(int lump) { - const byte *data = W_CacheLumpNum(lump); // cph - const*, wad lump handling updated + auto databuf = CachedBuffer(lump); // cph - const*, wad lump handling updated int i; + auto pinned_data = databuf.pin(); + auto data = (const uint8_t *)pinned_data; for (i=0; i<_g->numsides; i++) { - register const mapsidedef_t *msd = (const mapsidedef_t *) data + i; - register side_t *sd = _g->sides + i; - register sector_t *sec; + const mapsidedef_t *msd = (const mapsidedef_t *) data + i; + side_t *sd = _g->sides + i; + sector_t *sec; sd->textureoffset = msd->textureoffset; sd->rowoffset = msd->rowoffset; @@ -275,7 +282,7 @@ static void P_LoadSideDefs2(int lump) unsigned short sector_num = SHORT(msd->sector); if (sector_num >= _g->numsectors) { - lprintf(LO_WARN,"P_LoadSideDefs2: sidedef %i has out-of-range sector num %u\n", i, sector_num); + lprintf(LO_WARN,"P_LoadSideDefs2: sidedef %i in lump %d has out-of-range sector num %u\n", i, lump, sector_num); sector_num = 0; } sd->sector = sec = &_g->sectors[sector_num]; @@ -321,18 +328,18 @@ typedef struct linelist_t // type used to list lines in each block static void P_LoadBlockMap (int lump) { - _g->blockmaplump = W_CacheLumpNum(lump); + _g->blockmaplump = CachedBuffer(lump); - _g->bmaporgx = _g->blockmaplump[0]<bmaporgy = _g->blockmaplump[1]<bmapwidth = _g->blockmaplump[2]; - _g->bmapheight = _g->blockmaplump[3]; + _g->bmaporgx = *_g->blockmaplump[0]<bmaporgy = *_g->blockmaplump[1]<bmapwidth = *_g->blockmaplump[2]; + _g->bmapheight = *_g->blockmaplump[3]; // clear out mobj chains - CPhipps - use calloc - _g->blocklinks = Z_Calloc (_g->bmapwidth*_g->bmapheight,sizeof(*_g->blocklinks),PU_LEVEL,0); + _g->blocklinks = (mobj_t **)Z_Calloc (_g->bmapwidth*_g->bmapheight,sizeof(*_g->blocklinks),PU_LEVEL,0); - _g->blockmap = _g->blockmaplump+4; + _g->blockmap = _g->blockmaplump.addOffset(4); } // @@ -349,7 +356,7 @@ static void P_LoadBlockMap (int lump) static void P_LoadReject(int lumpnum) { _g->rejectlump = lumpnum + ML_REJECT; - _g->rejectmatrix = W_CacheLumpNum(_g->rejectlump); + _g->rejectmatrix = CachedBuffer(_g->rejectlump); } // @@ -363,7 +370,7 @@ static void P_LoadReject(int lumpnum) // figgi 09/18/00 -- adapted for gl-nodes // cph - convenient sub-function -static void P_AddLineToSector(const line_t* li, sector_t* sector) +static void P_AddLineToSector(Cached li, sector_t* sector) { sector->lines[sector->linecount++] = li; } @@ -371,30 +378,29 @@ static void P_AddLineToSector(const line_t* li, sector_t* sector) // modified to return totallines (needed by P_LoadReject) static int P_GroupLines (void) { - register const line_t *li; - register sector_t *sector; + Cached li; + sector_t *sector; int i,j, total = _g->numlines; // figgi for (i=0 ; i<_g->numsubsectors ; i++) { - const seg_t *seg = &_g->segs[_g->subsectors[i].firstline]; _g->subsectors[i].sector = NULL; for(j=0; j<_g->subsectors[i].numlines; j++) { + auto seg = _g->segs[_g->subsectors[i].firstline+j]; if(seg->sidenum != NO_INDEX) { _g->subsectors[i].sector = _g->sides[seg->sidenum].sector; break; } - seg++; } if(_g->subsectors[i].sector == NULL) I_Error("P_GroupLines: Subsector a part of no sector!\n"); } // count number of lines in each sector - for (i=0,li=_g->lines; i<_g->numlines; i++, li++) + for (i=0,li=_g->lines[0]; i<_g->numlines; i++, li++) { LN_FRONTSECTOR(li)->linecount++; if (LN_BACKSECTOR(li) && LN_BACKSECTOR(li) != LN_FRONTSECTOR(li)) @@ -405,7 +411,7 @@ static int P_GroupLines (void) } { // allocate line tables for each sector - const line_t **linebuffer = Z_Malloc(total*sizeof(line_t *), PU_LEVEL, 0); + Cached *linebuffer = (Cached *)Z_Malloc(total*sizeof(Cached), PU_LEVEL, 0); // e6y: REJECT overrun emulation code // moved to P_LoadReject @@ -419,7 +425,7 @@ static int P_GroupLines (void) } // Enter those lines - for (i=0,li=_g->lines; i<_g->numlines; i++, li++) + for (i=0,li=_g->lines[0]; i<_g->numlines; i++, li++) { P_AddLineToSector(li, LN_FRONTSECTOR(li)); if (LN_BACKSECTOR(li) && LN_BACKSECTOR(li) != LN_FRONTSECTOR(li)) @@ -444,14 +450,14 @@ static int P_GroupLines (void) return total; // this value is needed by the reject overrun emulation code } - void P_FreeLevelData() { R_ResetPlanes(); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1); + NC_FlushCache(); - Z_Free(_g->braintargets); + //Z_Free(_g->braintargets); _g->braintargets = NULL; _g->numbraintargets_alloc = _g->numbraintargets = 0; } @@ -461,7 +467,7 @@ void P_FreeLevelData() // // killough 5/3/98: reformatted, cleaned up -void P_SetupLevel(int episode, int map, int playermask, skill_t skill) +void P_SetupLevel(int episode, int map, int playermask UNUSED, skill_t skill UNUSED) { int i; char lumpname[9]; @@ -497,14 +503,14 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill) // find map name if (_g->gamemode == commercial) { - sprintf(lumpname, "MAP%02d", map); // killough 1/24/98: simplify + snprintf(lumpname, sizeof(lumpname)-1, "MAP%02d", map); // killough 1/24/98: simplify } else { - sprintf(lumpname, "E%dM%d", episode, map); // killough 1/24/98: simplify + snprintf(lumpname, sizeof(lumpname)-1, "E%dM%d", episode, map); // killough 1/24/98: simplify } - lumpnum = W_GetNumForName(lumpname); + lumpnum = NC_GetNumForName(lumpname); _g->leveltime = 0; _g->totallive = 0; diff --git a/source/p_sight.c b/cppsrc/p_sight.cc similarity index 97% rename from source/p_sight.c rename to cppsrc/p_sight.cc index cc09a99f..c27feb7a 100644 --- a/source/p_sight.c +++ b/cppsrc/p_sight.cc @@ -65,7 +65,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) // // Check in REJECT table. - if (_g->rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected + if (*_g->rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected return false; /* killough 11/98: shortcut for melee situations diff --git a/source/p_spec.c b/cppsrc/p_spec.cc similarity index 98% rename from source/p_spec.c rename to cppsrc/p_spec.cc index 58679cc8..d2d59616 100644 --- a/source/p_spec.c +++ b/cppsrc/p_spec.cc @@ -45,7 +45,7 @@ #include "p_setup.h" #include "m_random.h" #include "d_englsh.h" -#include "w_wad.h" + #include "r_main.h" #include "r_data.h" #include "p_maputl.h" @@ -106,7 +106,7 @@ const animdef_t animdefs[] = {true, "WFALL4", "WFALL1", 8}, {true, "DBRAIN4", "DBRAIN1", 8}, - {-1} + {-1, "", "", 0} // end of animdefs marker }; @@ -128,7 +128,7 @@ static void P_SpawnScrollers(void); // PWAD lump called ANIMATED rather than a static table in this module to // allow wad designers to insert or modify animation sequences. // -// Lump format is an array of byte packed animdef_t structures, terminated +// Lump format is an array of uint8_t packed animdef_t structures, terminated // by a structure with istexture == -1. The lump can be generated from a // text source file using SWANTBLS.EXE, distributed with the BOOM utils. // The standard list of switches and animations is contained in the example @@ -154,7 +154,7 @@ void P_InitPicAnims (void) } else { - if (W_CheckNumForName(animdefs[i].startname) == -1) + if (NC_CheckNumForName(animdefs[i].startname) == -1) continue; _g->lastanim->picnum = R_FlatNumForName (animdefs[i].endname); @@ -246,7 +246,7 @@ int twoSided // Note: returns NULL if not two-sided line, or both sides refer to sector // sector_t* getNextSector -( const line_t* line, +( const Cached &line, sector_t* sec ) { @@ -271,13 +271,12 @@ sector_t* getNextSector fixed_t P_FindLowestFloorSurrounding(sector_t* sec) { int i; - const line_t* check; sector_t* other; fixed_t floor = sec->floorheight; for (i=0 ;i < sec->linecount ; i++) { - check = sec->lines[i]; + auto check = sec->lines[i]; other = getNextSector(check,sec); if (!other) @@ -302,7 +301,6 @@ fixed_t P_FindLowestFloorSurrounding(sector_t* sec) fixed_t P_FindHighestFloorSurrounding(sector_t *sec) { int i; - const line_t* check; sector_t* other; fixed_t floor = -500*FRACUNIT; @@ -312,7 +310,7 @@ fixed_t P_FindHighestFloorSurrounding(sector_t *sec) for (i=0 ;i < sec->linecount ; i++) { - check = sec->lines[i]; + auto check = sec->lines[i]; other = getNextSector(check,sec); if (!other) @@ -465,7 +463,6 @@ fixed_t P_FindNextHighestCeiling(sector_t *sec, int currentheight) fixed_t P_FindLowestCeilingSurrounding(sector_t* sec) { int i; - const line_t* check; sector_t* other; fixed_t height = INT_MAX; @@ -474,7 +471,7 @@ fixed_t P_FindLowestCeilingSurrounding(sector_t* sec) for (i=0 ;i < sec->linecount ; i++) { - check = sec->lines[i]; + auto check = sec->lines[i]; other = getNextSector(check,sec); if (!other) @@ -499,7 +496,6 @@ fixed_t P_FindLowestCeilingSurrounding(sector_t* sec) fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) { int i; - const line_t* check; sector_t* other; fixed_t height = 0; @@ -510,7 +506,7 @@ fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) for (i=0 ;i < sec->linecount ; i++) { - check = sec->lines[i]; + auto check = sec->lines[i]; other = getNextSector(check,sec); if (!other) @@ -684,7 +680,7 @@ sector_t *P_FindModelCeilingSector(fixed_t ceildestheight,int secnum) // // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO // -int P_FindSectorFromLineTag(const line_t* line, int start) +int P_FindSectorFromLineTag(Cached line, int start) { int i; @@ -700,14 +696,14 @@ int P_FindSectorFromLineTag(const line_t* line, int start) // killough 4/16/98: Same thing, only for linedefs -int P_FindLineFromLineTag(const line_t *line, int start) +int P_FindLineFromLineTag(Cached line, int start) { int i; for (i=start+1; i<_g->numlines; i++) { - if (_g->lines[i].tag == line->tag) + if (_g->lines[i]->tag == line->tag) return i; } @@ -733,13 +729,12 @@ int P_FindMinSurroundingLight { int i; int min; - const line_t* line; sector_t* check; min = max; for (i=0 ; i < sector->linecount ; i++) { - line = sector->lines[i]; + auto line = sector->lines[i]; check = getNextSector(line,sector); if (!check) @@ -765,7 +760,7 @@ int P_FindMinSurroundingLight // generalized locked doors // boolean P_CanUnlockGenDoor -( const line_t* line, +( Cached line, player_t* player) { // does this line special distinguish between skulls and keys? @@ -941,7 +936,7 @@ boolean PUREFUNC P_SectorActive(special_e t, const sector_t *sec) // // jff 2/27/98 Added to check for zero tag allowed for regular special types // -int P_CheckTag(const line_t *line) +int P_CheckTag(Cached line) { /* tag not zero, allowed, or * killough 11/98: compatibility option */ @@ -1062,7 +1057,7 @@ boolean PUREFUNC P_WasSecret(const sector_t *sec) // crossed. Change is qualified by demo_compatibility. // // CPhipps - take a line_t pointer instead of a line number, as in MBF -void P_CrossSpecialLine(const line_t *line, int side, mobj_t *thing) +void P_CrossSpecialLine(Cached line, int side, mobj_t *thing) { int ok; @@ -1087,7 +1082,7 @@ void P_CrossSpecialLine(const line_t *line, int side, mobj_t *thing) // pointer to line function is NULL by default, set non-null if // line special is walkover generalized linedef type - int (*linefunc)(const line_t *line)=NULL; + int (*linefunc)(Cached line)=NULL; // check each range of generalized linedefs if ((unsigned)LN_SPECIAL(line) >= GenEnd) @@ -1945,11 +1940,11 @@ void P_CrossSpecialLine(const line_t *line, int side, mobj_t *thing) // void P_ShootSpecialLine ( mobj_t* thing, - const line_t* line ) + Cached line ) { // pointer to line function is NULL by default, set non-null if // line special is gun triggered generalized linedef type - int (*linefunc)(const line_t *line)=NULL; + int (*linefunc)(Cached line)=NULL; // check each range of generalized linedefs if ((unsigned)LN_SPECIAL(line) >= GenEnd) @@ -2316,11 +2311,7 @@ void P_SpawnSpecials (void) { sector_t* sector; int i; - int episode; - episode = 1; - if (W_CheckNumForName("texture2") >= 0) - episode = 2; // Init special sectors. sector = _g->sectors; @@ -2452,8 +2443,8 @@ void T_Scroll(scroll_t *s) static void Add_Scroller(int affectee) { - scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0); - s->thinker.function = T_Scroll; + scroll_t *s = (scroll_t *)Z_Malloc(sizeof *s, PU_LEVSPEC, 0); + s->thinker.function.acs1 = T_Scroll; s->affectee = affectee; P_AddThinker(&s->thinker); } @@ -2462,7 +2453,7 @@ static void Add_Scroller(int affectee) static void P_SpawnScrollers(void) { int i; - const line_t *l = _g->lines; + auto l = _g->lines[0]; for (i=0;i<_g->numlines;i++,l++) { @@ -2471,7 +2462,7 @@ static void P_SpawnScrollers(void) switch (special) { case 48: // scroll first side - Add_Scroller(_g->lines[i].sidenum[0]); + Add_Scroller(_g->lines[i]->sidenum[0]); break; } diff --git a/source/p_switch.c b/cppsrc/p_switch.cc similarity index 99% rename from source/p_switch.c rename to cppsrc/p_switch.cc index 3b3975cb..a10dd4b4 100644 --- a/source/p_switch.c +++ b/cppsrc/p_switch.cc @@ -32,7 +32,7 @@ *-----------------------------------------------------------------------------*/ #include "doomstat.h" -#include "w_wad.h" + #include "r_main.h" #include "p_spec.h" #include "g_game.h" @@ -141,7 +141,7 @@ void P_InitSwitchList(void) // No return. // static void P_StartButton -( const line_t* line, +( Cached line, bwhere_e w, int texture, int time ) @@ -150,7 +150,7 @@ static void P_StartButton // See if button is already pressed for (i = 0;i < MAXBUTTONS;i++) - if (_g->buttonlist[i].btimer && _g->buttonlist[i].line == line) + if (_g->buttonlist[i].btimer && _g->buttonlist[i].line->lineno == line->lineno) return; for (i = 0;i < MAXBUTTONS;i++) @@ -179,7 +179,7 @@ static void P_StartButton // // No return // -void P_ChangeSwitchTexture (const line_t* line, int useAgain) +void P_ChangeSwitchTexture (Cached line, int useAgain) { /* Rearranged a bit to avoid too much code duplication */ int i, sound; @@ -198,7 +198,7 @@ void P_ChangeSwitchTexture (const line_t* line, int useAgain) /* search for a texture to change */ texture = NULL; - position = 0; + position = (bwhere_e)0; for (i = 0; i < _g->numswitches*2; i++) { @@ -263,7 +263,7 @@ void P_ChangeSwitchTexture (const line_t* line, int useAgain) boolean P_UseSpecialLine ( mobj_t* thing, - const line_t* line, + Cached line, int side ) { @@ -277,7 +277,7 @@ P_UseSpecialLine { // pointer to line function is NULL by default, set non-null if // line special is push or switch generalized linedef type - int (*linefunc)(const line_t *line)=NULL; + int (*linefunc)(Cached line)=NULL; // check each range of generalized linedefs if ((unsigned)LN_SPECIAL(line) >= GenEnd) diff --git a/source/p_telept.c b/cppsrc/p_telept.cc similarity index 95% rename from source/p_telept.c rename to cppsrc/p_telept.cc index 3f19c683..0011fdb3 100644 --- a/source/p_telept.c +++ b/cppsrc/p_telept.cc @@ -44,14 +44,14 @@ #include "global_data.h" -static mobj_t* P_TeleportDestination(const line_t* line) +static mobj_t* P_TeleportDestination(Cached line) { int i; for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) { - register thinker_t* th = NULL; + thinker_t* th = NULL; while ((th = P_NextThinker(th)) != NULL) - if (th->function == P_MobjThinker) { - register mobj_t* m = (mobj_t*)th; + if (th->function.acm1 == P_MobjThinker) { + mobj_t* m = (mobj_t*)th; if (m->type == MT_TELEPORTMAN && m->subsector->sector-_g->sectors == i) return m; @@ -64,7 +64,7 @@ static mobj_t* P_TeleportDestination(const line_t* line) // // killough 5/3/98: reformatted, cleaned up -int EV_Teleport(const line_t *line, int side, mobj_t *thing) +int EV_Teleport(Cached line, int side, mobj_t *thing) { mobj_t *m; @@ -130,7 +130,7 @@ int EV_Teleport(const line_t *line, int side, mobj_t *thing) // Primarily for rooms-over-rooms etc. // -int EV_SilentTeleport(const line_t *line, int side, mobj_t *thing) +int EV_SilentTeleport(Cached line, int side, mobj_t *thing) { mobj_t *m; @@ -212,17 +212,18 @@ int EV_SilentTeleport(const line_t *line, int side, mobj_t *thing) // maximum fixed_t units to move object to avoid hiccups #define FUDGEFACTOR 10 -int EV_SilentLineTeleport(const line_t *line, int side, mobj_t *thing, +int EV_SilentLineTeleport(Cached line, int side, mobj_t *thing, boolean reverse) { int i; - const line_t *l; + Cached l; if (side || thing->flags & MF_MISSILE) return 0; for (i = -1; (i = P_FindLineFromLineTag(line, i)) >= 0;) - if ((l=_g->lines+i) != line && LN_BACKSECTOR(l)) + // Use lineno as UUID instead of pointer comparison + if ((l=_g->lines[i])->lineno != line->lineno && LN_BACKSECTOR(l)) { // Get the thing's position along the source linedef fixed_t pos = D_abs(line->dx) > D_abs(line->dy) ? diff --git a/source/p_tick.c b/cppsrc/p_tick.cc similarity index 98% rename from source/p_tick.c rename to cppsrc/p_tick.cc index 6f394a24..a5a4471e 100644 --- a/source/p_tick.c +++ b/cppsrc/p_tick.cc @@ -136,12 +136,12 @@ void P_RemoveThingDelayed(thinker_t *thinker) void P_RemoveThinker(thinker_t *thinker) { - thinker->function = P_RemoveThinkerDelayed; + thinker->function.act1 = P_RemoveThinkerDelayed; } void P_RemoveThing(mobj_t *thing) { - thing->thinker.function = P_RemoveThingDelayed; + thing->thinker.function.act1 = P_RemoveThingDelayed; } diff --git a/source/p_user.c b/cppsrc/p_user.cc similarity index 99% rename from source/p_user.c rename to cppsrc/p_user.cc index b8e322ef..605f8d63 100644 --- a/source/p_user.c +++ b/cppsrc/p_user.cc @@ -330,7 +330,7 @@ void P_PlayerThink (player_t* player) // when the weapon psprite can do it // (read: not in the middle of an attack). - newweapon = (cmd->buttons & BT_WEAPONMASK)>>BT_WEAPONSHIFT; + newweapon = (weapontype_t)((cmd->buttons & BT_WEAPONMASK)>>BT_WEAPONSHIFT); // killough 2/8/98, 3/22/98 -- end of weapon selection changes diff --git a/source/r_data.c b/cppsrc/r_data.cc similarity index 69% rename from source/r_data.c rename to cppsrc/r_data.cc index 1aa36f91..716399ee 100644 --- a/source/r_data.c +++ b/cppsrc/r_data.cc @@ -33,7 +33,7 @@ *-----------------------------------------------------------------------------*/ #include "doomstat.h" -#include "w_wad.h" + #include "r_draw.h" #include "r_main.h" #include "r_sky.h" @@ -89,62 +89,66 @@ typedef struct static const texture_t* R_LoadTexture(int texture_num) { - const byte* pnames = W_CacheLumpName("PNAMES"); + auto pnames = CachedBuffer("PNAMES"); //Skip to list of names. pnames += 4; - const int *maptex1, *maptex2; int numtextures1, numtextures2; - const int *directory1, *directory2; - maptex1 = W_CacheLumpName("TEXTURE1"); + auto maptex1 = CachedBuffer("TEXTURE1"); numtextures1 = *maptex1; - directory1 = maptex1+1; + auto directory1 = maptex1.addOffset(1); + CachedBuffer maptex2, directory2; - if (W_CheckNumForName("TEXTURE2") != -1) + if (NC_CheckNumForName("TEXTURE2") != -1) { - maptex2 = W_CacheLumpName("TEXTURE2"); + maptex2 = CachedBuffer("TEXTURE2"); numtextures2 = *maptex2; - directory2 = maptex2+1; + directory2 = maptex2.addOffset(1); } else { - maptex2 = NULL; + maptex2 = CachedBuffer(); numtextures2 = 0; - directory2 = NULL; + directory2 = CachedBuffer(); } int offset = 0; - const int *maptex = maptex1; + auto maptex = maptex1; if(texture_num < numtextures1) { - offset = directory1[texture_num]; + offset = *directory1[texture_num]; } - else if(maptex2 && ((texture_num-numtextures1) < numtextures2) ) + else if(maptex2.isvalid() && ((texture_num-numtextures1) < numtextures2) ) { maptex = maptex2; - offset = directory2[texture_num-numtextures1]; + offset = *directory2[texture_num-numtextures1]; } else { I_Error("R_LoadTexture: Texture %d not in range.", texture_num); } - const maptexture_t *mtexture = (const maptexture_t *) ((const byte *)maptex + offset); + //const maptexture_t *mtexture = (const maptexture_t *) ((const uint8_t *)maptex + offset); + auto mtexture = maptex[0].transmuteToObjectAtByteOffset(offset); - texture_t* texture = Z_Malloc(sizeof(const texture_t) + sizeof(const texpatch_t)*(mtexture->patchcount-1), PU_LEVEL, (void**)&textures[texture_num]); + texture_t* texture = (texture_t *)Z_Calloc(sizeof(const texture_t) + sizeof(const texpatch_t)*(mtexture->patchcount-1),1, PU_LEVEL, (void**)&textures[texture_num]); texture->width = mtexture->width; texture->height = mtexture->height; texture->patchcount = mtexture->patchcount; - texture->name = mtexture->name; + //texture->name = mtexture->name; // TODO: This is stealing pointer - fix later + //texture->name = (const char *)Z_Calloc(9,1,PU_LEVEL,(void **)&texture->name); + strncpy((char*)texture->name, mtexture->name,8); + ((char*)texture->name)[8] = 0; + texpatch_t* patch = texture->patches; - const mappatch_t* mpatch = mtexture->patches; + auto mpatch = mtexture->patches; texture->overlapped = 0; @@ -156,9 +160,11 @@ static const texture_t* R_LoadTexture(int texture_num) patch->originy = mpatch->originy; char pname[8]; - strncpy(pname, (const char*)&pnames[mpatch->patch * 8], 8); + auto pnames_pin = pnames.pin(); + const uint8_t* pnames_data = (const uint8_t*)pnames_pin; + strncpy(pname, (const char*)&pnames_data[mpatch->patch * 8], 8); - patch->patch = (const patch_t*)W_CacheLumpName(pname); + patch->patch = Cached(pname); } for (int j=0 ; j < texture->patchcount ; j++) @@ -211,7 +217,8 @@ const texture_t* R_GetTexture(int texture) if(texture >= _g->numtextures) return NULL; - if(textures[texture]) + auto tex = textures[texture]; + if(tex) return textures[texture]; const texture_t* t = R_LoadTexture(texture); @@ -221,11 +228,24 @@ const texture_t* R_GetTexture(int texture) return t; } +#ifndef _MSC_VER +#include + +char* strupr(char* str) { + char* p = str; + while (*p) { + *p = toupper((unsigned char)*p); + p++; + } + return str; +} +#endif + static int R_GetTextureNumForName(const char* tex_name) { - const int *maptex1, *maptex2; + CachedBuffer maptex1, maptex2; int numtextures1; - const int *directory1, *directory2; + CachedBuffer directory1, directory2; //Convert name to uppercase for comparison. @@ -236,29 +256,29 @@ static int R_GetTextureNumForName(const char* tex_name) strupr(tex_name_upper); - if(_g->tex_lookup_last_name && (!strncmp(_g->tex_lookup_last_name, tex_name_upper, 8))) + if(/*_g->tex_lookup_last_name &&*/ (!strncmp(_g->tex_lookup_last_name, tex_name_upper, 8))) { return _g->tex_lookup_last_num; } - maptex1 = W_CacheLumpName("TEXTURE1"); + maptex1 = CachedBuffer("TEXTURE1"); numtextures1 = *maptex1; - directory1 = maptex1+1; + directory1 = maptex1.addOffset(1); - if (W_CheckNumForName("TEXTURE2") != -1) + if (NC_CheckNumForName("TEXTURE2") != -1) { - maptex2 = W_CacheLumpName("TEXTURE2"); - directory2 = maptex2+1; + maptex2 = CachedBuffer("TEXTURE2"); + directory2 = maptex2.addOffset(1); } else { - maptex2 = NULL; - directory2 = NULL; + maptex2 = CachedBuffer(); + directory2 = CachedBuffer(); } - const int *directory = directory1; - const int *maptex = maptex1; + auto directory = directory1; + auto maptex = maptex1; for (int i=0 ; i<_g->numtextures ; i++, directory++) { @@ -271,11 +291,13 @@ static int R_GetTextureNumForName(const char* tex_name) int offset = *directory; - const maptexture_t* mtexture = (const maptexture_t *) ( (const byte *)maptex + offset); + //const maptexture_t* mtexture = (const maptexture_t *) ( (const uint8_t *)maptex + offset); + auto mtexture = maptex[0].transmuteToObjectAtByteOffset(offset); if(!strncmp(tex_name_upper, mtexture->name, 8)) { - _g->tex_lookup_last_name = mtexture->name; + strncpy(&_g->tex_lookup_last_name[0],mtexture->name,8); + //_g->tex_lookup_last_name = mtexture->name; _g->tex_lookup_last_num = i; return i; } @@ -312,29 +334,29 @@ int R_LoadTextureByName(const char* tex_name) static void R_InitTextures() { - const int* mtex1 = W_CacheLumpName("TEXTURE1"); + auto mtex1 = CachedBuffer("TEXTURE1"); int numtextures1 = *mtex1; int numtextures2 = 0; - if (W_CheckNumForName("TEXTURE2") != -1) + if (NC_CheckNumForName("TEXTURE2") != -1) { - const int* mtex2 = W_CacheLumpName("TEXTURE2"); + auto mtex2 = CachedBuffer("TEXTURE2"); numtextures2 = *mtex2; } _g->numtextures = numtextures1 + numtextures2; - textures = Z_Malloc(_g->numtextures*sizeof*textures, PU_STATIC, 0); - memset(textures, 0, _g->numtextures*sizeof*textures); + textures = (const texture_t **)Z_Calloc(_g->numtextures,sizeof(texture_t *), PU_STATIC, 0); + //memset(textures, 0, _g->numtextures*sizeof*textures); - textureheight = Z_Malloc(_g->numtextures*sizeof*textureheight, PU_STATIC, 0); - memset(textureheight, 0, _g->numtextures*sizeof*textureheight); + textureheight = (fixed_t *)Z_Calloc(_g->numtextures,sizeof(fixed_t), PU_STATIC, 0); + //memset(textureheight, 0, _g->numtextures*sizeof*textureheight); - texturetranslation = Z_Malloc((_g->numtextures+1)*sizeof*texturetranslation, PU_STATIC, 0); + texturetranslation = (short *)Z_Calloc((_g->numtextures+1),sizeof(short), PU_STATIC, 0); - for (int i=0 ; i<_g->numtextures ; i++) - texturetranslation[i] = i; + //for (int i=0 ; i<_g->numtextures ; i++) + // texturetranslation[i] = i; } // @@ -344,8 +366,8 @@ static void R_InitFlats(void) { int i; - _g->firstflat = W_GetNumForName("F_START") + 1; - int lastflat = W_GetNumForName("F_END") - 1; + _g->firstflat = NC_GetNumForName("F_START") + 1; + int lastflat = NC_GetNumForName("F_END") - 1; _g->numflats = lastflat - _g->firstflat + 1; // Create translation table for global animation. @@ -353,7 +375,7 @@ static void R_InitFlats(void) // clean up malloc-ing to use sizeof flattranslation = - Z_Malloc((_g->numflats+1)*sizeof(*flattranslation), PU_STATIC, 0); + (short *)Z_Malloc((_g->numflats+1)*sizeof(*flattranslation), PU_STATIC, 0); for (i=0 ; i<_g->numflats ; i++) flattranslation[i] = i; @@ -367,8 +389,9 @@ static void R_InitFlats(void) // static void R_InitSpriteLumps(void) { - _g->firstspritelump = W_GetNumForName("S_START") + 1; - _g->lastspritelump = W_GetNumForName("S_END") - 1; + _g->firstspritelump = NC_GetNumForName("S_START") + 1; + _g->lastspritelump = NC_GetNumForName("S_END") - 1; + printf("sprites can be found between %d and %d\n", _g->firstspritelump, _g->lastspritelump); _g->numspritelumps = _g->lastspritelump - _g->firstspritelump + 1; } @@ -377,8 +400,8 @@ static void R_InitSpriteLumps(void) // void R_InitColormaps (void) { - int lump = W_GetNumForName("COLORMAP"); - colormaps = W_CacheLumpNum(lump); + int lump = NC_GetNumForName("COLORMAP"); + colormaps = CachedBuffer(lump); } // @@ -409,7 +432,7 @@ void R_InitData(void) int R_FlatNumForName(const char *name) // killough -- const added { - int i = W_CheckNumForName(name); + int i = NC_CheckNumForName(name); if (i == -1) I_Error("R_FlatNumForName: %.8s not found", name); diff --git a/source/r_draw.c b/cppsrc/r_draw.cc similarity index 98% rename from source/r_draw.c rename to cppsrc/r_draw.cc index acb99d6c..0a7405b6 100644 --- a/source/r_draw.c +++ b/cppsrc/r_draw.cc @@ -34,7 +34,7 @@ *-----------------------------------------------------------------------------*/ #include "doomstat.h" -#include "w_wad.h" + #include "r_main.h" #include "r_draw.h" #include "v_video.h" @@ -69,6 +69,7 @@ void R_SetDefaultDrawColumnVars(draw_column_vars_t *dcvars) dcvars->x = dcvars->yl = dcvars->yh = 0; dcvars->iscale = dcvars->texturemid = 0; dcvars->source = NULL; + dcvars->sourcecache = CachedBuffer(); dcvars->colormap = colormaps; dcvars->translation = NULL; } diff --git a/source/r_hotpath.iwram.c b/cppsrc/r_hotpath.iwram.cc similarity index 86% rename from source/r_hotpath.iwram.c rename to cppsrc/r_hotpath.iwram.cc index 2f532ea1..03bd73df 100644 --- a/source/r_hotpath.iwram.c +++ b/cppsrc/r_hotpath.iwram.cc @@ -35,20 +35,20 @@ //This is to keep the codesize under control. //This whole file needs to fit within IWRAM. -#pragma GCC optimize ("Os") #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifndef GBA +#if !defined(GBA)&& !defined(__chess__) + #include #endif #include "doomstat.h" #include "d_net.h" -#include "w_wad.h" + #include "r_main.h" #include "r_things.h" #include "r_plane.h" @@ -67,6 +67,9 @@ #include "gba_functions.h" +#include +#include + //#define static @@ -77,13 +80,13 @@ //***************************************** #ifndef GBA -static byte vram1_spare[2560]; -static byte vram2_spare[2560]; -static byte vram3_spare[1024]; +static uint8_t vram1_spare[2560]; +static uint8_t vram2_spare[2560]; +static uint8_t vram3_spare[1024]; #else - #define vram1_spare ((byte*)0x6000000+0x9600) - #define vram2_spare ((byte*)0x600A000+0x9600) - #define vram3_spare ((byte*)0x7000000) + #define vram1_spare ((uint8_t*)0x6000000+0x9600) + #define vram2_spare ((uint8_t*)0x600A000+0x9600) + #define vram3_spare ((uint8_t*)0x7000000) #endif //Stuff alloc'd in OAM memory. @@ -104,13 +107,13 @@ short* ceilingclip = (short*)&vram3_spare[512+240]; //Stuff alloc'd in VRAM1 memory. //580 bytes -const fixed_t* yslope_vram = (const fixed_t*)&vram1_spare[0]; +const fixed_t * yslope_vram = (const fixed_t *)&vram1_spare[0]; //480 bytes -const fixed_t* distscale_vram = (const fixed_t*)&vram1_spare[580]; +const fixed_t * distscale_vram = (const fixed_t *)&vram1_spare[580]; //484 bytes. -const angle_t* xtoviewangle_vram = (const angle_t*)&vram1_spare[580+480]; +const angle_t * xtoviewangle_vram = (const angle_t *)&vram1_spare[580+480]; //240 Bytes. short* wipe_y_lookup = (short*)&vram1_spare[580+480+484]; @@ -140,9 +143,9 @@ short* negonearray = (short*)&vram2_spare[240]; //***************************************** #ifndef GBA -static byte columnCache[128*128]; +static uint8_t columnCache[128*128]; #else - #define columnCache ((byte*)0x6014000) + #define columnCache ((uint8_t*)0x6014000) #endif @@ -152,20 +155,20 @@ static byte columnCache[128*128]; //***************************************** int numnodes; -const mapnode_t *nodes; +CachedBuffer nodes; fixed_t viewx, viewy, viewz; angle_t viewangle; -static byte solidcol[MAX_SCREENWIDTH]; +static uint8_t solidcol[MAX_SCREENWIDTH]; -static byte spanstart[MAX_SCREENHEIGHT]; // killough 2/8/98 +static uint8_t spanstart[MAX_SCREENHEIGHT]; // killough 2/8/98 -static const seg_t *curline; +static Cached curline; static side_t *sidedef; -static const line_t *linedef; +Cached linedef; static sector_t *frontsector; static sector_t *backsector; static drawseg_t *ds_p; @@ -199,10 +202,10 @@ static fixed_t rw_midtexturemid; static fixed_t rw_toptexturemid; static fixed_t rw_bottomtexturemid; -const lighttable_t *fullcolormap; -const lighttable_t *colormaps; +CachedBuffer fullcolormap; +CachedBuffer colormaps; -const lighttable_t* fixedcolormap; +CachedBuffer fixedcolormap; int extralight; // bumped light from gun blasts draw_vars_t drawvars; @@ -242,8 +245,8 @@ static fixed_t pixlowstep; static int worldhigh; static int worldlow; -static lighttable_t current_colormap[256]; -static const lighttable_t* current_colormap_ptr; +//static lighttable_t current_colormap[256]; +CachedBuffer current_colormap_ptr; static fixed_t planeheight; @@ -285,7 +288,7 @@ static const fixed_t skyiscale = (FRACUNIT*200)/((SCREENHEIGHT-ST_HEIGHT)+16); // it saves an OR and Shift per pixel. //******************************************** #ifdef GBA - typedef byte pixel; + typedef uint8_t pixel; #else typedef unsigned short pixel; #endif @@ -294,10 +297,7 @@ static const fixed_t skyiscale = (FRACUNIT*200)/((SCREENHEIGHT-ST_HEIGHT)+16); // This goes here as we want the Thumb code // to BX to ARM as Thumb long mul is very slow. //******************************************** -inline fixed_t CONSTFUNC FixedMul(fixed_t a, fixed_t b) -{ - return (fixed_t)((int_64_t) a*b >> FRACBITS); -} + // killough 5/3/98: reformatted @@ -359,8 +359,11 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) if (numnodes == 0) return _g->subsectors; - while (!(nodenum & NF_SUBSECTOR)) - nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)]; + while (!(nodenum & NF_SUBSECTOR)){ + auto bsp = nodes[nodenum]; + auto pinnedbsp = bsp.pin(); + nodenum = nodes[nodenum]->children[R_PointOnSide(x, y, pinnedbsp)]; + } return &_g->subsectors[nodenum & ~NF_SUBSECTOR]; } @@ -479,13 +482,13 @@ static CONSTFUNC fixed_t R_PointToDist(fixed_t x, fixed_t y) return FixedApproxDiv(dx, finesine[(tantoangle[FixedApproxDiv(dy,dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT]); } -static const lighttable_t* R_ColourMap(int lightlevel) +CachedBuffer R_ColourMap(int lightlevel) { - if (fixedcolormap) + if (!fixedcolormap.isnull()) return fixedcolormap; else { - if (curline) + if (curline.isvalid()) { if (curline->v1.y == curline->v2.y) lightlevel -= 1 << LIGHTSEGSHIFT; @@ -502,23 +505,26 @@ static const lighttable_t* R_ColourMap(int lightlevel) else if(cm < 0) cm = 0; - return fullcolormap + cm*256; + return fullcolormap.addOffset(cm*256); } } //Load a colormap into IWRAM. -static const lighttable_t* R_LoadColorMap(int lightlevel) +static CachedBuffer R_LoadColorMap(int lightlevel) { - const lighttable_t* lm = R_ColourMap(lightlevel); + current_colormap_ptr = R_ColourMap(lightlevel); + // Now - we may do this more than necessary as the colormap now can move around in RAM + /* if(current_colormap_ptr != lm) { BlockCopy(current_colormap, lm, 256); current_colormap_ptr = lm; } + */ - return current_colormap; + return current_colormap_ptr; } // @@ -529,13 +535,11 @@ static const lighttable_t* R_LoadColorMap(int lightlevel) // be used. It has also been used with Wolfenstein 3D. // -#pragma GCC push_options -#pragma GCC optimize ("Ofast") #define COLEXTRABITS 9 #define COLBITS (FRACBITS + COLEXTRABITS) -inline static void R_DrawColumnPixel(unsigned short* dest, const byte* source, const byte* colormap, unsigned int frac) +inline static void R_DrawColumnPixel(unsigned short* dest, const uint8_t* source, const uint8_t* colormap, unsigned int frac) { pixel* d = (pixel*)dest; @@ -556,8 +560,12 @@ static void R_DrawColumn (const draw_column_vars_t *dcvars) if (count <= 0) return; - const byte *source = dcvars->source; - const byte *colormap = dcvars->colormap; + auto pin = dcvars->sourcecache.pin(); + + const uint8_t *source = (pin.isnull()) ? dcvars->source : (const uint8_t*)pin; + assert(source!=NULL); + auto pinnedcolormap = dcvars->colormap.pin(); + const uint8_t *colormap = pinnedcolormap; unsigned short* dest = drawvars.byte_topleft + ScreenYToOffset(dcvars->yl) + dcvars->x; @@ -622,9 +630,13 @@ static void R_DrawColumnHiRes(const draw_column_vars_t *dcvars) // Zero length, column does not exceed a pixel. if (count <= 0) return; + + auto pin = dcvars->sourcecache.pin(); - const byte *source = dcvars->source; - const byte *colormap = dcvars->colormap; + const uint8_t *source = (pin.isnull()) ? dcvars->source : (const uint8_t*)pin; + assert(source!=NULL); + auto pinnedcolormap = dcvars->colormap.pin(); + const uint8_t *colormap = pinnedcolormap; volatile unsigned short* dest = drawvars.byte_topleft + ScreenYToOffset(dcvars->yl) + dcvars->x; @@ -702,7 +714,8 @@ static void R_DrawFuzzColumn (const draw_column_vars_t *dcvars) if (count <= 0) return; - const byte* colormap = &fullcolormap[6*256]; + auto pinnedcolormap = fullcolormap.addOffset(6*256).pin(); + const uint8_t* colormap = pinnedcolormap; //&fullcolormap[6*256]; unsigned short* dest = drawvars.byte_topleft + ScreenYToOffset(dc_yl) + dcvars->x; @@ -710,7 +723,7 @@ static void R_DrawFuzzColumn (const draw_column_vars_t *dcvars) do { - R_DrawColumnPixel(dest, (const byte*)&dest[fuzzoffset[fuzzpos]], colormap, 0); dest += SCREENWIDTH; fuzzpos++; + R_DrawColumnPixel(dest, (const uint8_t*)&dest[fuzzoffset[fuzzpos]], colormap, 0); dest += SCREENWIDTH; fuzzpos++; if(fuzzpos >= 50) fuzzpos = 0; @@ -720,7 +733,6 @@ static void R_DrawFuzzColumn (const draw_column_vars_t *dcvars) _g->fuzzpos = fuzzpos; } -#pragma GCC pop_options @@ -753,9 +765,11 @@ static void R_DrawMaskedColumn(R_DrawColumn_f colfunc, draw_column_vars_t *dcvar yl = cclip_x + 1; // killough 3/2/98, 3/27/98: Failsafe against overflow/crash: + if (yh < viewheight && yl <= yh) { - dcvars->source = (const byte*)column + 3; + dcvars->source = (const uint8_t*)column + 3; + dcvars->sourcecache = CachedBuffer(); dcvars->texturemid = basetexturemid - (column->topdelta<length + 4); + column = (const column_t *)((const uint8_t *)column + column->length + 4); } dcvars->texturemid = basetexturemid; } +// Overload for cached columns +static void R_DrawMaskedColumn(R_DrawColumn_f colfunc, draw_column_vars_t *dcvars, Cached column) +{ + const fixed_t basetexturemid = dcvars->texturemid; + + const int fclip_x = mfloorclip[dcvars->x]; + const int cclip_x = mceilingclip[dcvars->x]; + + while (column->topdelta != 0xff) + { + // calculate unclipped screen coordinates for post + const int topscreen = sprtopscreen + spryscale*column->topdelta; + const int bottomscreen = topscreen + spryscale*column->length; + + int yh = (bottomscreen-1)>>FRACBITS; + int yl = (topscreen+FRACUNIT-1)>>FRACBITS; + + if(yh >= fclip_x) + yh = fclip_x - 1; + + if(yl <= cclip_x) + yl = cclip_x + 1; + + // killough 3/2/98, 3/27/98: Failsafe against overflow/crash: + if (yh < viewheight && yl <= yh) + { + dcvars->source = NULL; // (const uint8_t*)column + 3; + dcvars->sourcecache = column.bytebuffer().addOffset(3); + + dcvars->texturemid = basetexturemid - (column->topdelta<yh = yh; + dcvars->yl = yl; + + // Drawn by either R_DrawColumn + // or (SHADOW) R_DrawFuzzColumn. + colfunc (dcvars); + } + + // column = (const column_t *)((const uint8_t *)column + column->length + 4); + column = column.transmuteToObjectAtByteOffset(column->length + 4); + } + + dcvars->texturemid = basetexturemid; +} + + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -793,7 +854,7 @@ static void R_DrawVisSprite(const vissprite_t *vis) // killough 4/11/98: rearrange and handle translucent sprites // mixed with translucent/non-translucenct 2s normals - if (!dcvars.colormap) // NULL colormap = shadow draw + if (dcvars.colormap.isnull()) // NULL colormap = shadow draw colfunc = R_DrawFuzzColumn; // killough 3/14/98 else { @@ -812,7 +873,7 @@ static void R_DrawVisSprite(const vissprite_t *vis) sprtopscreen = centeryfrac - FixedMul(dcvars.texturemid, spryscale); - const patch_t *patch = vis->patch; + auto patch = vis->patch; fixed_t xiscale = vis->xiscale; @@ -822,9 +883,11 @@ static void R_DrawVisSprite(const vissprite_t *vis) dcvars.x = vis->x1; dcvars.odd_pixel = false; + while(dcvars.x < SCREENWIDTH) { - const column_t* column = (const column_t *) ((const byte *)patch + patch->columnofs[frac >> FRACBITS]); + //const column_t* column = (const column_t *) ((const uint8_t *)pinnedpatchptr + patch->columnofs[frac >> FRACBITS]); + auto column = patch.transmuteToObjectAtByteOffset(patch->columnofs[frac >> FRACBITS]); R_DrawMaskedColumn(colfunc, &dcvars, column); frac += xiscale; @@ -841,7 +904,8 @@ static void R_DrawVisSprite(const vissprite_t *vis) break; - const column_t* column2 = (const column_t *) ((const byte *)patch + patch->columnofs[frac >> FRACBITS]); + //const column_t* column2 = (const column_t *) ((const uint8_t *)pinnedpatchptr + patch->columnofs[frac >> FRACBITS]); + auto column2 = patch.transmuteToObjectAtByteOffset(patch->columnofs[frac >> FRACBITS]); R_DrawMaskedColumn(colfunc, &dcvars, column2); frac += xiscale; @@ -854,7 +918,7 @@ static void R_DrawVisSprite(const vissprite_t *vis) } } -static const column_t* R_GetColumn(const texture_t* texture, int texcolumn) +static Cached R_GetColumn(const texture_t* texture, int texcolumn) { const unsigned int patchcount = texture->patchcount; const unsigned int widthmask = texture->widthmask; @@ -864,9 +928,10 @@ static const column_t* R_GetColumn(const texture_t* texture, int texcolumn) if(patchcount == 1) { //simple texture. - const patch_t* patch = texture->patches[0].patch; - - return (const column_t *) ((const byte *)patch + patch->columnofs[xc]); + auto patch = texture->patches[0].patch; + assert(patch.isvalid()); + return patch.transmuteToObjectAtByteOffset(patch->columnofs[xc]); + //return (const column_t *) ((const uint8_t *)patch + patch->columnofs[xc]); } else { @@ -876,7 +941,9 @@ static const column_t* R_GetColumn(const texture_t* texture, int texcolumn) { const texpatch_t* patch = &texture->patches[i]; - const patch_t* realpatch = patch->patch; + auto realpatch = patch->patch; + assert(realpatch.isvalid()); + const int x1 = patch->originx; @@ -886,12 +953,13 @@ static const column_t* R_GetColumn(const texture_t* texture, int texcolumn) const int x2 = x1 + realpatch->width; if(xc < x2) - return (const column_t *)((const byte *)realpatch + realpatch->columnofs[xc-x1]); + return realpatch.transmuteToObjectAtByteOffset(realpatch->columnofs[xc - x1]); + // return (const column_t *)((const uint8_t *)realpatch + realpatch->columnofs[xc-x1]); } while(++i < patchcount); } - return NULL; + return Cached(); } @@ -902,6 +970,7 @@ static const texture_t* R_GetOrLoadTexture(int tex_num) if(!tex) tex = R_GetTexture(tex_num); + assert(tex->patchcount > 0); return tex; } @@ -940,7 +1009,7 @@ static void R_RenderMaskedSegRange(const drawseg_t *ds, int x1, int x2) mceilingclip = ds->sprtopclip; // find positioning - if (_g->lines[curline->linenum].flags & ML_DONTPEGBOTTOM) + if (_g->lines[curline->linenum]->flags & ML_DONTPEGBOTTOM) { dcvars.texturemid = frontsector->floorheight > backsector->floorheight ? frontsector->floorheight : backsector->floorheight; @@ -971,21 +1040,22 @@ static void R_RenderMaskedSegRange(const drawseg_t *ds, int x1, int x2) dcvars.iscale = FixedReciprocal((unsigned)spryscale); // draw the texture - const column_t* column = R_GetColumn(texture, xc); + auto column = R_GetColumn(texture, xc); + auto pinnedcolumn = column.pin(); - R_DrawMaskedColumn(R_DrawColumn, &dcvars, column); + R_DrawMaskedColumn(R_DrawColumn, &dcvars, pinnedcolumn); maskedtexturecol[dcvars.x] = SHRT_MAX; // dropoff overflow } } - curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ + curline = Cached(); /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ } // killough 5/2/98: reformatted -static PUREFUNC int R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line) +static PUREFUNC int R_PointOnSegSide(fixed_t x, fixed_t y, Cached line) { const fixed_t lx = line->v1.x; const fixed_t ly = line->v1.y; @@ -1119,7 +1189,7 @@ static void R_DrawPSprite (pspdef_t *psp, int lightlevel) flip = (boolean) SPR_FLIPPED(sprframe, 0); - const patch_t* patch = W_CacheLumpNum(sprframe->lump[0]+_g->firstspritelump); + auto patch = Cached(sprframe->lump[0]+_g->firstspritelump); // calculate edges of the shape fixed_t tx; tx = psp->sx-160*FRACUNIT; @@ -1168,8 +1238,8 @@ static void R_DrawPSprite (pspdef_t *psp, int lightlevel) vis->patch = patch; if (_g->player.powers[pw_invisibility] > 4*32 || _g->player.powers[pw_invisibility] & 8) - vis->colormap = NULL; // shadow draw - else if (fixedcolormap) + vis->colormap = CachedBuffer(); // shadow draw + else if (!fixedcolormap.isnull()) vis->colormap = fixedcolormap; // fixed color else if (psp->state->frame & FF_FULLBRIGHT) vis->colormap = fullcolormap; // full bright // killough 3/20/98 @@ -1272,10 +1342,7 @@ static void R_DrawMasked(void) // and the inner loop has to step in texture space u and v. // -#pragma GCC push_options -#pragma GCC optimize ("Ofast") - -inline static void R_DrawSpanPixel(unsigned short* dest, const byte* source, const byte* colormap, unsigned int position) +inline static void R_DrawSpanPixel(unsigned short* dest, const uint8_t* source, const uint8_t* colormap, unsigned int position) { pixel* d = (pixel*)dest; @@ -1293,8 +1360,10 @@ static void R_DrawSpan(unsigned int y, unsigned int x1, unsigned int x2, const d { unsigned int count = (x2 - x1); - const byte *source = dsvars->source; - const byte *colormap = dsvars->colormap; + auto pinnedsource = dsvars->source.pin(); + const uint8_t *source = pinnedsource; + auto pinnedcolormap = dsvars->colormap.pin(); + const uint8_t *colormap = pinnedcolormap; unsigned short* dest = drawvars.byte_topleft + ScreenYToOffset(y) + x1; @@ -1348,7 +1417,6 @@ static void R_DrawSpan(unsigned int y, unsigned int x1, unsigned int x2, const d } } -#pragma GCC pop_options static void R_MapPlane(unsigned int y, unsigned int x1, unsigned int x2, draw_span_vars_t *dsvars) { @@ -1392,7 +1460,7 @@ static void R_MakeSpans(int x, unsigned int t1, unsigned int b1, unsigned int t2 static void R_DoDrawPlane(visplane_t *pl) { - register int x; + int x; draw_column_vars_t dcvars; R_SetDefaultDrawColumnVars(&dcvars); @@ -1409,13 +1477,14 @@ static void R_DoDrawPlane(visplane_t *pl) * Because of this hack, sky is not affected by INVUL inverse mapping. * Until Boom fixed this. Compat option added in MBF. */ - if (!(dcvars.colormap = fixedcolormap)) + if ((dcvars.colormap = fixedcolormap).isnull()) dcvars.colormap = fullcolormap; // killough 3/20/98 // proff 09/21/98: Changed for high-res dcvars.iscale = skyiscale; const texture_t* tex = R_GetOrLoadTexture(_g->skytexture); + assert(tex->patchcount >= 1); // sky texture is always simple // killough 10/98: Use sky scrolling offset for (x = pl->minx; (dcvars.x = x) <= pl->maxx; x++) @@ -1424,9 +1493,12 @@ static void R_DoDrawPlane(visplane_t *pl) { int xc = ((viewangle + xtoviewangle[x]) >> ANGLETOSKYSHIFT); - const column_t* column = R_GetColumn(tex, xc); + auto column = R_GetColumn(tex, xc); + auto columnptr = column.bytebuffer(); + columnptr += 3; + dcvars.sourcecache = columnptr; - dcvars.source = (const byte*)column + 3; + dcvars.source = NULL; R_DrawColumn(&dcvars); } } @@ -1436,7 +1508,7 @@ static void R_DoDrawPlane(visplane_t *pl) draw_span_vars_t dsvars; - dsvars.source = W_CacheLumpNum(_g->firstflat + flattranslation[pl->picnum]); + dsvars.source = CachedBuffer(_g->firstflat + flattranslation[pl->picnum]); dsvars.colormap = R_LoadColorMap(pl->lightlevel); planeheight = D_abs(pl->height-viewz); @@ -1544,7 +1616,7 @@ static void R_ProjectSprite (mobj_t* thing, int lightlevel) } const boolean flip = (boolean)SPR_FLIPPED(sprframe, rot); - const patch_t* patch = W_CacheLumpNum(sprframe->lump[rot] + _g->firstspritelump); + auto patch = Cached(sprframe->lump[rot] + _g->firstspritelump); /* calculate edges of the shape * cph 2003/08/1 - fraggle points out that this offset must be flipped @@ -1615,8 +1687,8 @@ static void R_ProjectSprite (mobj_t* thing, int lightlevel) // get light level if (thing->flags & MF_SHADOW) - vis->colormap = NULL; // shadow draw - else if (fixedcolormap) + vis->colormap = CachedBuffer(); // shadow draw + else if (!fixedcolormap.isnull()) vis->colormap = fixedcolormap; // fixed map else if (thing->frame & FF_FULLBRIGHT) vis->colormap = fullcolormap; // full bright // killough 3/20/98 @@ -1666,7 +1738,7 @@ static visplane_t *new_visplane(unsigned hash) visplane_t *check = _g->freetail; if (!check) - check = Z_Calloc(1, sizeof(visplane_t), PU_LEVEL, NULL); + check = (visplane_t *)Z_Calloc(1, sizeof(visplane_t), PU_LEVEL, NULL); else { if (!(_g->freetail = _g->freetail->next)) @@ -1762,11 +1834,11 @@ static visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) return R_DupPlane(pl,start,stop); } -static void R_DrawColumnInCache(const column_t* patch, byte* cache, int originy, int cacheheight) +static void R_DrawColumnInCache(const column_t* patch, uint8_t* cache, int originy, int cacheheight) { while (patch->topdelta != 0xff) { - const byte* source = (const byte *)patch + 3; + const uint8_t* source = (const uint8_t *)patch + 3; int count = patch->length; int position = originy + patch->topdelta; @@ -1782,7 +1854,7 @@ static void R_DrawColumnInCache(const column_t* patch, byte* cache, int originy, if (count > 0) ByteCopy(cache + position, source, count); - patch = (const column_t *)( (const byte *)patch + patch->length + 4); + patch = (const column_t *)( (const uint8_t *)patch + patch->length + 4); } } @@ -1834,7 +1906,7 @@ static unsigned int FindColumnCacheItem(unsigned int texture, unsigned int colum } -static const byte* R_ComposeColumn(const unsigned int texture, const texture_t* tex, int texcolumn, unsigned int iscale) +static const uint8_t* R_ComposeColumn(const unsigned int texture, const texture_t* tex, int texcolumn, unsigned int iscale) { //static int total, misses; int colmask; @@ -1861,7 +1933,7 @@ static const byte* R_ComposeColumn(const unsigned int texture, const texture_t* unsigned int cachekey = FindColumnCacheItem(texture, xc); - byte* colcache = &columnCache[cachekey*128]; + uint8_t* colcache = &columnCache[cachekey*128]; unsigned int cacheEntry = columnCacheEntries[cachekey]; //total++; @@ -1869,7 +1941,7 @@ static const byte* R_ComposeColumn(const unsigned int texture, const texture_t* if(cacheEntry != CACHE_ENTRY(xc, texture)) { //misses++; - byte tmpCache[128]; + uint8_t tmpCache[128]; columnCacheEntries[cachekey] = CACHE_ENTRY(xc, texture); @@ -1881,7 +1953,7 @@ static const byte* R_ComposeColumn(const unsigned int texture, const texture_t* { const texpatch_t* patch = &tex->patches[i]; - const patch_t* realpatch = patch->patch; + auto realpatch = patch->patch; const int x1 = patch->originx; @@ -1892,7 +1964,10 @@ static const byte* R_ComposeColumn(const unsigned int texture, const texture_t* if(xc < x2) { - const column_t* patchcol = (const column_t *)((const byte *)realpatch + realpatch->columnofs[xc-x1]); + auto pinnedpatch = realpatch.pin(); + const patch_t* pinnedpatchptr = (const patch_t *)pinnedpatch; + + const column_t* patchcol = (const column_t *)((const uint8_t *)pinnedpatchptr + realpatch->columnofs[xc-x1]); R_DrawColumnInCache (patchcol, tmpCache, @@ -1916,13 +1991,19 @@ static void R_DrawSegTextureColumn(unsigned int texture, int texcolumn, draw_col if(tex->overlapped == 0) { - const column_t* column = R_GetColumn(tex, texcolumn); - - dcvars->source = (const byte*)column + 3; + auto column = R_GetColumn(tex, texcolumn); + auto columnbytes = column.bytebuffer(); + columnbytes += 3; + assert(column.isvalid()); + dcvars->sourcecache = columnbytes; + dcvars->source = NULL; + } else { + dcvars->sourcecache = CachedBuffer(); dcvars->source = R_ComposeColumn(texture, tex, texcolumn, dcvars->iscale); + assert(dcvars->source!=NULL); } R_DrawColumn (dcvars); @@ -2150,7 +2231,7 @@ static void R_StoreWallRange(const int start, const int stop) linedata->r_flags |= ML_MAPPED; sidedef = &_g->sides[curline->sidenum]; - linedef = &_g->lines[curline->linenum]; + linedef = _g->lines[curline->linenum]; // calculate rw_distance for scale calculation rw_normalangle = curline->angle + ANG90; @@ -2409,14 +2490,14 @@ static void R_StoreWallRange(const int start, const int stop) // save sprite clipping info if ((ds_p->silhouette & SIL_TOP || maskedtexture) && !ds_p->sprtopclip) { - ByteCopy((byte*)_g->lastopening, (const byte*)(ceilingclip+start), sizeof(short)*(rw_stopx-start)); + ByteCopy((uint8_t*)_g->lastopening, (const uint8_t*)(ceilingclip+start), sizeof(short)*(rw_stopx-start)); ds_p->sprtopclip = _g->lastopening - start; _g->lastopening += rw_stopx - start; } if ((ds_p->silhouette & SIL_BOTTOM || maskedtexture) && !ds_p->sprbottomclip) { - ByteCopy((byte*)_g->lastopening, (const byte*)(floorclip+start), sizeof(short)*(rw_stopx-start)); + ByteCopy((uint8_t*)_g->lastopening, (const uint8_t*)(floorclip+start), sizeof(short)*(rw_stopx-start)); ds_p->sprbottomclip = _g->lastopening - start; _g->lastopening += rw_stopx - start; } @@ -2503,12 +2584,12 @@ static void R_RecalcLineFlags(void) static void R_ClipWallSegment(int first, int last, boolean solid) { - byte *p; + uint8_t *p; while (first < last) { if (solidcol[first]) { - if (!(p = ByteFind(solidcol+first, 0, last-first))) + if (!(p = (uint8_t *)ByteFind(solidcol+first, 0, last-first))) return; // All solid first = p - solidcol; @@ -2516,7 +2597,7 @@ static void R_ClipWallSegment(int first, int last, boolean solid) else { int to; - if (!(p = ByteFind(solidcol+first, 1, last-first))) + if (!(p = (uint8_t *)ByteFind(solidcol+first, 1, last-first))) to = last; else to = p - solidcol; @@ -2544,7 +2625,7 @@ static void R_ClipWallSegment(int first, int last, boolean solid) // and adds any visible pieces to the line list. // -static void R_AddLine (const seg_t *line) +static void R_AddLine (Cached line) { int x1; int x2; @@ -2610,7 +2691,7 @@ static void R_AddLine (const seg_t *line) backsector = SG_BACKSECTOR(line); /* cph - roll up linedef properties in flags */ - linedef = &_g->lines[curline->linenum]; + linedef = _g->lines[curline->linenum]; linedata_t* linedata = &_g->linedata[linedef->lineno]; if (linedata->r_validcount != (_g->gametic & 0xffff)) @@ -2635,13 +2716,13 @@ static void R_AddLine (const seg_t *line) static void R_Subsector(int num) { int count; - const seg_t *line; + Cached line; subsector_t *sub; sub = &_g->subsectors[num]; frontsector = sub->sector; count = sub->numlines; - line = &_g->segs[sub->firstline]; + line = _g->segs[sub->firstline]; if(frontsector->floorheight < viewz) { @@ -2671,9 +2752,10 @@ static void R_Subsector(int num) R_AddSprites(sub, frontsector->lightlevel); while (count--) { + // TODO: Line is stolen further down, so we need to fix this R_AddLine (line); line++; - curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ + curline = Cached(); /* cph 2001/11/18 - must clear curline now we're done with it, so R_ColourMap doesn't try using it for other things */ } } @@ -2684,7 +2766,7 @@ static void R_Subsector(int num) // if some part of the bbox might be visible. // -static const byte checkcoord[12][4] = // killough -- static const +static const uint8_t checkcoord[12][4] = // killough -- static const { {3,0,2,1}, {3,0,2,0}, @@ -2706,7 +2788,7 @@ static boolean R_CheckBBox(const short *bspcoord) { int boxpos; - const byte* check; + const uint8_t* check; // Find the corners of the box // that define the edges from current viewpoint. @@ -2798,7 +2880,6 @@ static void R_RenderBSPNode(int bspnum) int stack[MAX_BSP_DEPTH]; int sp = 0; - const mapnode_t* bsp; int side = 0; while(true) @@ -2809,8 +2890,9 @@ static void R_RenderBSPNode(int bspnum) if(sp == MAX_BSP_DEPTH) break; - bsp = &nodes[bspnum]; - side = R_PointOnSide (viewx, viewy, bsp); + auto bsp = nodes[bspnum]; + auto pinnedbsp = bsp.pin(); + side = R_PointOnSide (viewx, viewy, pinnedbsp); stack[sp++] = bspnum; stack[sp++] = side; @@ -2827,7 +2909,7 @@ static void R_RenderBSPNode(int bspnum) //Back sides. side = stack[--sp]; bspnum = stack[--sp]; - bsp = &nodes[bspnum]; + auto bsp = nodes[bspnum]; // Possibly divide back space. //Walk back up the tree until we find @@ -2844,7 +2926,7 @@ static void R_RenderBSPNode(int bspnum) side = stack[--sp]; bspnum = stack[--sp]; - bsp = &nodes[bspnum]; + bsp = nodes[bspnum]; } bspnum = bsp->children[side^1]; @@ -2943,24 +3025,24 @@ void V_DrawPatchNoScale(int x, int y, const patch_t* patch) y -= patch->topoffset; x -= patch->leftoffset; - byte* desttop = (byte*)_g->screens[0].data; + uint8_t* desttop = (uint8_t*)_g->screens[0].data; desttop += (ScreenYToOffset(y) << 1) + x; unsigned int width = patch->width; for (unsigned int col = 0; col < width; col++, desttop++) { - const column_t* column = (const column_t*)((const byte*)patch + patch->columnofs[col]); + const column_t* column = (const column_t*)((const uint8_t*)patch + patch->columnofs[col]); unsigned int odd_addr = (size_t)desttop & 1; - byte* desttop_even = (byte*)((size_t)desttop & ~1); + uint8_t* desttop_even = (uint8_t*)((size_t)desttop & ~1); // step through the posts in a column while (column->topdelta != 0xff) { - const byte* source = (const byte*)column + 3; - byte* dest = desttop_even + (ScreenYToOffset(column->topdelta) << 1); + const uint8_t* source = (const uint8_t*)column + 3; + uint8_t* dest = desttop_even + (ScreenYToOffset(column->topdelta) << 1); unsigned int count = column->length; @@ -2980,7 +3062,7 @@ void V_DrawPatchNoScale(int x, int y, const patch_t* patch) dest += 240; } - column = (const column_t*)((const byte*)column + column->length + 4); + column = (const column_t*)((const uint8_t*)column + column->length + 4); } } } @@ -3011,7 +3093,7 @@ static int P_DivlineSide(fixed_t x, fixed_t y, const divline_t *node) static boolean P_CrossSubsector(int num) { - const seg_t *seg = _g->segs + _g->subsectors[num].firstline; + auto seg = _g->segs[_g->subsectors[num].firstline]; int count; fixed_t opentop = 0, openbottom = 0; const sector_t *front = NULL, *back = NULL; @@ -3020,7 +3102,7 @@ static boolean P_CrossSubsector(int num) { // check lines int linenum = seg->linenum; - const line_t *line = &_g->lines[linenum]; + auto line = _g->lines[linenum]; divline_t divl; // allready checked other side? @@ -3111,7 +3193,7 @@ boolean P_CrossBSPNode(int bspnum) { while (!(bspnum & NF_SUBSECTOR)) { - const mapnode_t *bsp = nodes + bspnum; + auto bsp = nodes[bspnum]; divline_t dl; dl.x = ((fixed_t)bsp->x << FRACBITS); @@ -3171,18 +3253,18 @@ boolean P_SetMobjState(mobj_t* mobj, statenum_t state) // Modified handling. // Call action functions when the state is set - if(st->action) + if(st->action.acm1) { if(!(_g->player.cheats & CF_ENEMY_ROCKETS)) { - st->action(mobj); + st->action.acm1(mobj); } else { - if(mobjinfo[mobj->type].missilestate && (state >= mobjinfo[mobj->type].missilestate) && (state < mobjinfo[mobj->type].painstate)) + if(mobjinfo[mobj->type].missilestate && ((int)state >= mobjinfo[mobj->type].missilestate) && ((int)state < mobjinfo[mobj->type].painstate)) A_CyberAttack(mobj); else - st->action(mobj); + st->action.acm1(mobj); } } @@ -3205,14 +3287,14 @@ void P_MobjThinker (mobj_t* mobj) if (mobj->momx | mobj->momy || mobj->flags & MF_SKULLFLY) { P_XYMovement(mobj); - if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed + if (mobj->thinker.function.acm1 != P_MobjThinker) // cph - Must've been removed return; // killough - mobj was removed } if (mobj->z != mobj->floorz || mobj->momz) { P_ZMovement(mobj); - if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed + if (mobj->thinker.function.acm1 != P_MobjThinker) // cph - Must've been removed return; // killough - mobj was removed } @@ -3288,8 +3370,8 @@ void P_RunThinkers (void) while(th != th_end) { thinker_t* th_next = th->next; - if(th->function) - th->function(th); + if(th->function.act1) + th->function.act1(th); th = th_next; } @@ -3297,47 +3379,6 @@ void P_RunThinkers (void) -static int I_GetTime_e32(void) -{ - int thistimereply = *((unsigned short*)(0x400010C)); - - return thistimereply; -} -int I_GetTime(void) -{ - int thistimereply; - -#ifndef GBA - - clock_t now = clock(); - - thistimereply = (int)((double)now / ((double)CLOCKS_PER_SEC / (double)TICRATE)); -#else - thistimereply = I_GetTime_e32(); -#endif - - if (thistimereply < _g->lasttimereply) - { - _g->basetime -= 0xffff; - } - - _g->lasttimereply = thistimereply; - - - /* Fix for time problem */ - if (!_g->basetime) - { - _g->basetime = thistimereply; - thistimereply = 0; - } - else - { - thistimereply -= _g->basetime; - } - - return thistimereply; -} - diff --git a/source/r_main.c b/cppsrc/r_main.cc similarity index 91% rename from source/r_main.c rename to cppsrc/r_main.cc index 2f0fb1fd..d9e68074 100644 --- a/source/r_main.c +++ b/cppsrc/r_main.cc @@ -40,7 +40,7 @@ #include "doomstat.h" #include "d_net.h" -#include "w_wad.h" + #include "r_main.h" #include "r_things.h" #include "r_plane.h" @@ -91,15 +91,15 @@ void R_SetupFrame (player_t *player) viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; - fullcolormap = &colormaps[0]; + fullcolormap = colormaps.addOffset(0); if (player->fixedcolormap) { - fixedcolormap = fullcolormap // killough 3/20/98: use fullcolormap - + player->fixedcolormap*256*sizeof(lighttable_t); + fixedcolormap = fullcolormap.addOffset( // killough 3/20/98: use fullcolormap + player->fixedcolormap*256*sizeof(lighttable_t)); } else - fixedcolormap = 0; + fixedcolormap = CachedBuffer(); _g->validcount++; diff --git a/source/r_patch.c b/cppsrc/r_patch.cc similarity index 94% rename from source/r_patch.c rename to cppsrc/r_patch.cc index bf9075a1..24c93460 100644 --- a/source/r_patch.c +++ b/cppsrc/r_patch.cc @@ -30,7 +30,7 @@ #include "z_zone.h" #include "doomstat.h" -#include "w_wad.h" + #include "r_main.h" #include "r_sky.h" #include "r_things.h" @@ -46,7 +46,7 @@ //--------------------------------------------------------------------------- int R_NumPatchWidth(int lump) { - const patch_t* patch = W_CacheLumpNum(lump); + auto patch = Cached(lump); return patch->width; } @@ -54,7 +54,7 @@ int R_NumPatchWidth(int lump) //--------------------------------------------------------------------------- int R_NumPatchHeight(int lump) { - const patch_t* patch = W_CacheLumpNum(lump); + auto patch = Cached(lump); return patch->height; } diff --git a/source/r_plane.c b/cppsrc/r_plane.cc similarity index 99% rename from source/r_plane.c rename to cppsrc/r_plane.cc index aed61cb2..6a5ee6b2 100644 --- a/source/r_plane.c +++ b/cppsrc/r_plane.cc @@ -51,7 +51,7 @@ #include "z_zone.h" /* memory allocation wrappers -- killough */ #include "doomstat.h" -#include "w_wad.h" + #include "r_main.h" #include "r_draw.h" #include "r_things.h" diff --git a/source/r_things.c b/cppsrc/r_things.cc similarity index 92% rename from source/r_things.c rename to cppsrc/r_things.cc index 5caa3fab..9116d4a0 100644 --- a/source/r_things.c +++ b/cppsrc/r_things.cc @@ -32,7 +32,7 @@ *-----------------------------------------------------------------------------*/ #include "doomstat.h" -#include "w_wad.h" + #include "r_main.h" #include "r_segs.h" #include "r_draw.h" @@ -138,7 +138,7 @@ static void R_InstallSpriteLump(int lump, unsigned frame, static void R_InitSpriteDefs(const char * const * namelist) { size_t numentries = _g->lastspritelump-_g->firstspritelump+1; - struct { int index, next; } *hash; + struct hash_s { int index, next; } *hash; int i; if (!numentries || !*namelist) @@ -150,21 +150,22 @@ static void R_InitSpriteDefs(const char * const * namelist) _g->numsprites = i; - _g->sprites = Z_Malloc(_g->numsprites *sizeof(*_g->sprites), PU_STATIC, NULL); + _g->sprites = (spritedef_t *)Z_Malloc(_g->numsprites *sizeof(*_g->sprites), PU_STATIC, NULL); memset(_g->sprites, 0, _g->numsprites *sizeof(*_g->sprites)); // Create hash table based on just the first four letters of each sprite // killough 1/31/98 - hash = Z_Malloc(sizeof(*hash)*numentries, PU_STATIC, NULL); // allocate hash table + hash = (hash_s *)Z_Malloc(sizeof(*hash)*numentries, PU_STATIC, NULL); // allocate hash table for (i=0; (size_t)ifirstspritelump); + { + char buffer[8]; // prepend so that later ones win + const char* sn = NC_GetNameForNum(i+_g->firstspritelump,buffer); int j = R_SpriteNameHash(sn) % numentries; hash[i].next = hash[j].index; @@ -185,7 +186,8 @@ static void R_InitSpriteDefs(const char * const * namelist) _g->maxframe = -1; do { - const char* sn = W_GetNameForNum(j + _g->firstspritelump); + char buffer[8]; + const char* sn = NC_GetNameForNum(j + _g->firstspritelump,buffer); // Fast portable comparison -- killough // (using int pointer cast is nonportable): @@ -239,7 +241,7 @@ static void R_InitSpriteDefs(const char * const * namelist) } // allocate space for the frames present and copy sprtemp to it _g->sprites[i].spriteframes = - Z_Malloc (_g->maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + (spriteframe_t *)Z_Malloc (_g->maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); memcpy (_g->sprites[i].spriteframes, _g->sprtemp, _g->maxframe*sizeof(spriteframe_t)); } diff --git a/source/s_sound.c b/cppsrc/s_sound.cc similarity index 94% rename from source/s_sound.c rename to cppsrc/s_sound.cc index 34805219..bf7bc71f 100644 --- a/source/s_sound.c +++ b/cppsrc/s_sound.cc @@ -33,6 +33,11 @@ // killough 3/7/98: modified to allow arbitrary listeners in spy mode // killough 5/2/98: reindented, removed useless code, beautified +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wunused-function" +#pragma clang diagnostic ignored "-Wunused-variable" + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -44,10 +49,11 @@ #include "d_main.h" #include "r_main.h" #include "m_random.h" -#include "w_wad.h" + #include "lprintf.h" #include "global_data.h" +#include "annotations.h" // when to clip out sounds // Does not fit the large outdoor areas. @@ -76,7 +82,7 @@ static const unsigned int numChannels = 8; // Internals. // -void S_StopChannel(int cnum); +void S_StopChannel(unsigned cnum); int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep); @@ -89,11 +95,10 @@ static int S_getChannel(void *origin, const sfxinfo_t *sfxinfo, int is_pickup); void S_Init(int sfxVolume, int musicVolume) { +#ifdef GBA //jff 1/22/98 skip sound init if sound not enabled if (!nosfxparm) { - int i; - lprintf(LO_CONFIRM, "S_Init: default sfx volume %d", sfxVolume); S_SetSfxVolume(sfxVolume); @@ -113,10 +118,12 @@ void S_Init(int sfxVolume, int musicVolume) // no sounds are playing, and they are not mus_paused _g->mus_paused = 0; } +#endif } void S_Stop(void) { +#ifdef GBA unsigned int cnum; //jff 1/22/98 skip sound init if sound not enabled @@ -124,6 +131,7 @@ void S_Stop(void) for (cnum=0 ; cnumchannels[cnum].sfxinfo) S_StopChannel(cnum); +#endif } // @@ -133,6 +141,7 @@ void S_Stop(void) // void S_Start(void) { + #ifdef GBA int mnum; // kill all playing sounds at start of level @@ -173,11 +182,14 @@ void S_Start(void) mnum = spmus[_g->gamemap-1]; } S_ChangeMusic(mnum, true); + #endif } void S_StartSoundAtVolume(mobj_t *origin, int sfx_id, int volume) { - int priority, cnum, is_pickup; + #ifdef GBA + unsigned cnum; + int is_pickup; const sfxinfo_t *sfx; int sep = NORM_SEP; @@ -198,7 +210,6 @@ void S_StartSoundAtVolume(mobj_t *origin, int sfx_id, int volume) // Initialize sound parameters if (sfx->link) { - priority = sfx->priority; volume += sfx->volume; if (volume < 1) @@ -207,10 +218,7 @@ void S_StartSoundAtVolume(mobj_t *origin, int sfx_id, int volume) if (volume > _g->snd_SfxVolume) volume = _g->snd_SfxVolume; } - else - { - priority = NORM_PRIORITY; - } + // Check to see if it is audible, modify the params // killough 3/7/98, 4/25/98: code rearranged slightly @@ -244,6 +252,7 @@ void S_StartSoundAtVolume(mobj_t *origin, int sfx_id, int volume) _g->channels[cnum].handle = h; _g->channels[cnum].tickend = (_g->gametic + sfx->ticks); } + #endif } @@ -254,6 +263,7 @@ void S_StartSound(mobj_t *origin, int sfx_id) void S_StartSound2(degenmobj_t* origin, int sfx_id) { + #ifdef GBA //Look at this mess. //Originally, the degenmobj_t had @@ -279,11 +289,13 @@ void S_StartSound2(degenmobj_t* origin, int sfx_id) fm.origin.y = origin->y; S_StartSoundAtVolume((mobj_t*) &fm, sfx_id, _g->snd_SfxVolume); + #endif } void S_StopSound(void *origin) { - int cnum; + #ifdef GBA + unsigned cnum; //jff 1/22/98 return if sound is not enabled if (nosfxparm) @@ -295,6 +307,7 @@ void S_StopSound(void *origin) S_StopChannel(cnum); break; } + #endif } @@ -303,6 +316,7 @@ void S_StopSound(void *origin) // void S_PauseSound(void) { + #ifdef GBA //jff 1/22/98 return if music is not enabled if (nomusicparm) return; @@ -312,10 +326,12 @@ void S_PauseSound(void) I_PauseSong(0); _g->mus_paused = true; } + #endif } void S_ResumeSound(void) { + #ifdef GBA //jff 1/22/98 return if music is not enabled if (nomusicparm) return; @@ -325,10 +341,12 @@ void S_ResumeSound(void) I_ResumeSong(0); _g->mus_paused = false; } + #endif } static boolean S_SoundIsPlaying(int cnum) { + #ifdef GBA const channel_t* channel = &_g->channels[cnum]; if(channel->sfxinfo) @@ -338,17 +356,17 @@ static boolean S_SoundIsPlaying(int cnum) return (channel->tickend < ticknow); } + #endif return false; } // // Updates music & sounds // -void S_UpdateSounds(void* listener_p) +void S_UpdateSounds(void* listener_p UNUSED) { - mobj_t *listener = (mobj_t*) listener_p; - int cnum; - int sep = NORM_SEP; + #ifdef GBA + unsigned cnum; //jff 1/22/98 return if sound is not enabled if (nosfxparm) @@ -387,10 +405,12 @@ void S_UpdateSounds(void* listener_p) S_StopChannel(cnum); } } + #endif } void S_SetMusicVolume(int volume) { + #ifdef GBA //jff 1/22/98 return if music is not enabled if (nomusicparm) return; @@ -398,18 +418,21 @@ void S_SetMusicVolume(int volume) I_Error("S_SetMusicVolume: Attempt to set music volume at %d", volume); I_SetMusicVolume(volume); _g->snd_MusicVolume = volume; + #endif } void S_SetSfxVolume(int volume) { + #ifdef GBA //jff 1/22/98 return if sound is not enabled if (nosfxparm) return; if (volume < 0 || volume > 127) I_Error("S_SetSfxVolume: Attempt to set sfx volume at %d", volume); _g->snd_SfxVolume = volume; + #endif } @@ -426,6 +449,7 @@ void S_StartMusic(int m_id) void S_ChangeMusic(int musicnum, int looping) { + #ifdef GBA //jff 1/22/98 return if music is not enabled if (nomusicparm) return; @@ -443,11 +467,13 @@ void S_ChangeMusic(int musicnum, int looping) I_PlaySong(musicnum, looping); _g->mus_playing = musicnum; + #endif } void S_StopMusic(void) { + #ifdef GBA //jff 1/22/98 return if music is not enabled if (nomusicparm) return; @@ -461,13 +487,15 @@ void S_StopMusic(void) _g->mus_playing = 0; } + #endif } -void S_StopChannel(int cnum) +void S_StopChannel(unsigned cnum) { - int i; + #ifdef GBA + unsigned i; channel_t *c = &_g->channels[cnum]; //jff 1/22/98 return if sound is not enabled @@ -486,6 +514,7 @@ void S_StopChannel(int cnum) c->sfxinfo = 0; c->tickend = 0; } + #endif } // @@ -497,6 +526,7 @@ void S_StopChannel(int cnum) int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep) { + #ifdef GBA fixed_t adx, ady,approx_dist; //jff 1/22/98 return if sound is not enabled @@ -559,6 +589,9 @@ int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep) *vol = (_g->snd_SfxVolume * ((S_CLIPPING_DIST-approx_dist)>>FRACBITS) * 8) / S_ATTENUATOR; return (*vol > 0); + #else + return 0; + #endif } // @@ -569,8 +602,9 @@ int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep) static int S_getChannel(void *origin, const sfxinfo_t *sfxinfo, int is_pickup) { + #ifdef GBA // channel number to use - int cnum; + unsigned cnum; channel_t *c; //jff 1/22/98 return if sound is not enabled @@ -603,6 +637,9 @@ static int S_getChannel(void *origin, const sfxinfo_t *sfxinfo, int is_pickup) c->origin = origin; c->is_pickup = is_pickup; // killough 4/25/98 return cnum; + #else + return -1; + #endif } - +#pragma clang diagnostic pop diff --git a/source/sounds.c b/cppsrc/sounds.cc similarity index 100% rename from source/sounds.c rename to cppsrc/sounds.cc diff --git a/cppsrc/st_gfx.cc b/cppsrc/st_gfx.cc new file mode 100644 index 00000000..82652419 --- /dev/null +++ b/cppsrc/st_gfx.cc @@ -0,0 +1,5 @@ +#include "gfx/stbar.h" + +#include "st_gfx.h" + +unsigned int gfx_stbar_len = sizeof(gfx_stbar); diff --git a/source/st_lib.c b/cppsrc/st_lib.cc similarity index 91% rename from source/st_lib.c rename to cppsrc/st_lib.cc index c55c474d..dcc42454 100644 --- a/source/st_lib.c +++ b/cppsrc/st_lib.cc @@ -34,7 +34,7 @@ #include "doomdef.h" #include "doomstat.h" #include "v_video.h" -#include "w_wad.h" + #include "st_stuff.h" #include "st_lib.h" #include "r_main.h" @@ -42,6 +42,7 @@ #include "global_data.h" #include "gba_functions.h" +#include "annotations.h" // // STlib_init() @@ -64,7 +65,7 @@ void STlib_initNum (st_number_t* n, int x, int y, - const patch_t **pl, + Cached *pl, int* num, boolean* on, int width ) @@ -93,8 +94,8 @@ void STlib_initNum */ static void STlib_drawNum ( st_number_t* n, - int cm, - boolean refresh ) + int cm UNUSED, + boolean refresh UNUSED) { int numdigits = n->width; @@ -127,9 +128,11 @@ static void STlib_drawNum //jff 2/16/98 add color translation to digit output // in the special case of 0, you draw 0 - if (!num) + if (!num) { // CPhipps - patch drawing updated, reformatted - V_DrawPatchNoScale(x - w, n->y, n->p[0]); + auto pinned_num = n->p[0].pin(); + V_DrawPatchNoScale(x - w, n->y, pinned_num); + } // draw the new number //jff 2/16/98 add color translation to digit output @@ -137,7 +140,8 @@ static void STlib_drawNum { // CPhipps - patch drawing updated, reformatted x -= w; - V_DrawPatchNoScale(x, n->y, n->p[num % 10]); + auto pinned_num = n->p[num % 10].pin(); + V_DrawPatchNoScale(x, n->y, pinned_num); num /= 10; } } @@ -175,10 +179,10 @@ void STlib_initPercent (st_percent_t* p, int x, int y, - const patch_t** pl, + Cached *pl, int* num, boolean* on, - const patch_t *percent ) + Cached percent ) { STlib_initNum(&p->n, x, y, pl, num, on, 3); p->p = percent; @@ -216,7 +220,7 @@ void STlib_initMultIcon (st_multicon_t* i, int x, int y, - const patch_t **il, + const Cached *il, int* inum, boolean* on ) { @@ -240,13 +244,16 @@ void STlib_initMultIcon // void STlib_updateMultIcon ( st_multicon_t* mi, - boolean refresh ) + boolean refresh UNUSED) { if(!mi->p) return; if (*mi->inum != -1) // killough 2/16/98: redraw only if != -1 - V_DrawPatchNoScale(mi->x, mi->y, mi->p[*mi->inum]); + { + auto pinned_icon = mi->p[*mi->inum].pin(); + V_DrawPatchNoScale(mi->x, mi->y, pinned_icon); + } mi->oldinum = *mi->inum; @@ -309,7 +316,7 @@ void ST_refreshBackground(void) if (_g->st_statusbaron) { const unsigned int st_offset = ((SCREENHEIGHT-ST_SCALED_HEIGHT)*120); - - CpuBlockCopy(&_g->screens[0].data[st_offset], _g->stbarbg, _g->stbar_len); + auto pinned_stbarbg = _g->stbarbg.pin(); + CpuBlockCopy(&_g->screens[0].data[st_offset], pinned_stbarbg, _g->stbar_len); } } diff --git a/source/st_stuff.c b/cppsrc/st_stuff.cc similarity index 89% rename from source/st_stuff.c rename to cppsrc/st_stuff.cc index 75182942..09f80d71 100644 --- a/source/st_stuff.c +++ b/cppsrc/st_stuff.cc @@ -37,7 +37,7 @@ #include "doomstat.h" #include "m_random.h" #include "i_video.h" -#include "w_wad.h" + #include "st_stuff.h" #include "st_lib.h" #include "r_main.h" @@ -127,7 +127,7 @@ static void ST_updateFaceWidget(void) for (i=0;ioldweaponsowned[i] != _g->player.weaponowned[i]) + if ((int)_g->oldweaponsowned[i] != _g->player.weaponowned[i]) { doevilgrin = true; _g->oldweaponsowned[i] = _g->player.weaponowned[i]; @@ -275,11 +275,11 @@ static void ST_updateFaceWidget(void) static void ST_updateWidgets(void) { - const static int largeammo = 1994; // means "n/a" + static int largeammo = 1994; // means "n/a" int i; if(_g->fps_show) - _g->w_ready.num = &_g->fps_framerate; + _g->w_ready.num = (int *)&_g->fps_framerate; else if (weaponinfo[_g->player.readyweapon].ammo == am_noammo) _g->w_ready.num = &largeammo; else @@ -473,7 +473,7 @@ void ST_Drawer(boolean statusbaron, boolean refresh) // CPhipps - Loads graphics needed for status bar if doload is true, // unloads them otherwise // -static void ST_loadGraphics(boolean doload) +static void ST_loadGraphics(boolean doload UNUSED) { int i, facenum; char namebuf[9]; @@ -482,38 +482,38 @@ static void ST_loadGraphics(boolean doload) for (i=0;i<10;i++) { //sprintf(namebuf, "STTNUM%d", i); - sprintf(namebuf, "STGANUM%d", i); //Special GBA Doom II Red Numbers ~Kippykip - _g->tallnum[i] = (const patch_t *) W_CacheLumpName(namebuf); + snprintf(namebuf, sizeof(namebuf),"STGANUM%d", i); //Special GBA Doom II Red Numbers ~Kippykip + _g->tallnum[i] = Cached(namebuf); - sprintf(namebuf, "STYSNUM%d", i); - _g->shortnum[i] = (const patch_t *) W_CacheLumpName(namebuf); + snprintf(namebuf, sizeof(namebuf), "STYSNUM%d", i); + _g->shortnum[i] = Cached(namebuf); } // Load percent key. //Note: why not load STMINUS here, too? - _g->tallpercent = (const patch_t*) W_CacheLumpName("STTPRCNT"); + _g->tallpercent = Cached("STTPRCNT"); // key cards for (i=0;ikeys[i] = (const patch_t *) W_CacheLumpName(namebuf); + snprintf(namebuf, sizeof(namebuf), "STKEYS%d", i); + _g->keys[i] = Cached(namebuf); } // arms ownership widgets for (i=0;i<6;i++) { - sprintf(namebuf, "STGNUM%d", i+2); + snprintf(namebuf, sizeof(namebuf), "STGNUM%d", i+2); // gray # - _g->arms[i][0] = (const patch_t *) W_CacheLumpName(namebuf); + _g->arms[i][0] = Cached(namebuf); // yellow # - _g->arms[i][1] = (const patch_t *) _g->shortnum[i+2]; + _g->arms[i][1] = _g->shortnum[i+2]; } // status bar background bits - _g->stbarbg = (const patch_t *) gfx_stbar; + _g->stbarbg = Cached(STBAR_LUMP_NUM); // HACK special lump for status bar bg _g->stbar_len = gfx_stbar_len; // face states @@ -523,22 +523,22 @@ static void ST_loadGraphics(boolean doload) { for (int j=0;jfaces[facenum++] = W_CacheLumpName(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFST%d%d", i, j); + _g->faces[facenum++] = Cached(namebuf); } - sprintf(namebuf, "STFTR%d0", i); // turn right - _g->faces[facenum++] = W_CacheLumpName(namebuf); - sprintf(namebuf, "STFTL%d0", i); // turn left - _g->faces[facenum++] = W_CacheLumpName(namebuf); - sprintf(namebuf, "STFOUCH%d", i); // ouch! - _g->faces[facenum++] = W_CacheLumpName(namebuf); - sprintf(namebuf, "STFEVL%d", i); // evil grin ;) - _g->faces[facenum++] = W_CacheLumpName(namebuf); - sprintf(namebuf, "STFKILL%d", i); // pissed off - _g->faces[facenum++] = W_CacheLumpName(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFTR%d0", i); // turn right + _g->faces[facenum++] = Cached(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFTL%d0", i); // turn left + _g->faces[facenum++] = Cached(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFOUCH%d", i); // ouch! + _g->faces[facenum++] = Cached(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFEVL%d", i); // evil grin ;) + _g->faces[facenum++] = Cached(namebuf); + snprintf(namebuf, sizeof(namebuf), "STFKILL%d", i); // pissed off + _g->faces[facenum++] = Cached(namebuf); } - _g->faces[facenum++] = W_CacheLumpName("STFGOD0"); - _g->faces[facenum++] = W_CacheLumpName("STFDEAD0"); + _g->faces[facenum++] = Cached("STFGOD0"); + _g->faces[facenum++] = Cached("STFDEAD0"); } static void ST_loadData(void) diff --git a/source/tables.c b/cppsrc/tables.cc similarity index 99% rename from source/tables.c rename to cppsrc/tables.cc index feb8d473..20ee08f0 100644 --- a/source/tables.c +++ b/cppsrc/tables.cc @@ -50,12 +50,12 @@ #endif #include -#include "w_wad.h" + #include "tables.h" -const fixed_t finetangent[4096] = +const fixed_t CONSTMEM _finetangent[4096] = { -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683, -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368, @@ -571,9 +571,11 @@ const fixed_t finetangent[4096] = 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304 }; -//const fixed_t *const finecosine = &finesine[FINEANGLES/4]; +ConstMemArray finetangent(_finetangent); + +//const fixed_t CONSTMEM *const finecosine = &finesine[FINEANGLES/4]; -const fixed_t finesine[10240] = +const fixed_t CONSTMEM _finesine[10240] = { 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, @@ -1857,7 +1859,10 @@ const fixed_t finesine[10240] = 65534,65535,65535,65535,65535,65535,65535,65535 }; -const angle_t tantoangle[2049] = +ConstMemArray finesine(_finesine); +ConstMemArray finecosine(_finesine + FINEANGLES/4); + +const angle_t CONSTMEM _tantoangle[2049] = { 0,333772,667544,1001315,1335086,1668857,2002626,2336395, 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, @@ -2118,7 +2123,9 @@ const angle_t tantoangle[2049] = 536870912 }; -const int viewangletox[4096] = +ConstMemArray tantoangle(_tantoangle); + +const int CONSTMEM _viewangletox[4096] = { 120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -2379,6 +2386,8 @@ const int viewangletox[4096] = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; +ConstMemArray viewangletox(_viewangletox); + const angle_t xtoviewangle[121] = { 537395200,531628032,525336576,519569408,513802240,507510784,501219328,494927872,488636416, diff --git a/source/v_video.c b/cppsrc/v_video.cc similarity index 86% rename from source/v_video.c rename to cppsrc/v_video.cc index 9a8cd047..c3bb339b 100644 --- a/source/v_video.c +++ b/cppsrc/v_video.cc @@ -39,13 +39,14 @@ #include "r_main.h" #include "r_draw.h" #include "m_bbox.h" -#include "w_wad.h" /* needed for color translation lump lookup */ + #include "v_video.h" #include "i_video.h" #include "lprintf.h" #include "global_data.h" #include "gba_functions.h" +#include "annotations.h" /* * V_DrawBackground tiles a 64x64 patch over the entire screen, providing the @@ -56,20 +57,21 @@ void V_DrawBackground(const char* flatname) { /* erase the entire screen to a tiled background */ - const byte *src; + int lump; unsigned short *dest = _g->screens[0].data; // killough 4/17/98: - src = W_CacheLumpNum(lump = _g->firstflat + R_FlatNumForName(flatname)); + auto src = CachedBuffer(lump = _g->firstflat + R_FlatNumForName(flatname)); + auto pinsrc = src.pin(); for(unsigned int y = 0; y < SCREENHEIGHT; y++) { for(unsigned int x = 0; x < 240; x+=64) { unsigned short* d = &dest[ ScreenYToOffset(y) + (x >> 1)]; - const byte* s = &src[((y&63) * 64) + (x&63)]; + const uint8_t* s = &pinsrc[((y&63) * 64) + (x&63)]; unsigned int len = 64; @@ -100,7 +102,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) const int DY = ((SCREENHEIGHT<screens[scrn].data; + uint8_t* byte_topleft = (uint8_t*)_g->screens[scrn].data; const int byte_pitch = (SCREENPITCH * 2); const int left = ( x * DX ) >> FRACBITS; @@ -114,7 +116,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) if(dc_x < 0) continue; - const column_t* column = (const column_t *)((const byte*)patch + patch->columnofs[colindex]); + const column_t* column = (const column_t *)((const uint8_t*)patch + patch->columnofs[colindex]); if (dc_x >= 240) break; @@ -122,7 +124,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) // step through the posts in a column while (column->topdelta != 0xff) { - const byte* source = (const byte*)column + 3; + const uint8_t* source = (const uint8_t*)column + 3; const int topdelta = column->topdelta; int dc_yl = (((y + topdelta) * DY) >> FRACBITS); @@ -133,7 +135,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) int count = (dc_yh - dc_yl); - byte* dest = byte_topleft + (dc_yl*byte_pitch) + dc_x; + uint8_t* dest = byte_topleft + (dc_yl*byte_pitch) + dc_x; const fixed_t fracstep = DYI; fixed_t frac = 0; @@ -146,7 +148,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) unsigned short color = source[frac >> FRACBITS]; //The GBA must write in 16bits. - if((unsigned int)dest & 1) + if((uintptr_t)dest & 1) { //Odd addreses, we combine existing pixel with new one. unsigned short* dest16 = (unsigned short*)(dest - 1); @@ -169,7 +171,7 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) frac += fracstep; } - column = (const column_t *)((const byte *)column + column->length + 4 ); + column = (const column_t *)((const uint8_t *)column + column->length + 4 ); } } } @@ -182,9 +184,10 @@ void V_DrawPatch(int x, int y, int scrn, const patch_t* patch) // This inline is _only_ for the function below void V_DrawNumPatch(int x, int y, int scrn, int lump, - int cm, enum patch_translation_e flags) + int cm UNUSED, enum patch_translation_e flags UNUSED) { - V_DrawPatch(x, y, scrn, W_CacheLumpNum(lump)); + auto patch = CachedBuffer(lump).pin(); + V_DrawPatch(x, y, scrn, patch); } // @@ -213,18 +216,18 @@ void V_SetPalLump(int index) else lumpName[7] = '0' + index; - _g->pallete_lump = W_CacheLumpName(lumpName); + _g->pallete_lump = CachedBuffer(lumpName); } // // V_FillRect // // CPhipps - New function to fill a rectangle with a given colour -void V_FillRect(int x, int y, int width, int height, byte colour) +void V_FillRect(int x, int y, int width, int height, uint8_t colour) { - byte* fb = (byte*)_g->screens[0].data; + uint8_t* fb = (uint8_t*)_g->screens[0].data; - byte* dest = &fb[(ScreenYToOffset(y) << 1) + x]; + uint8_t* dest = &fb[(ScreenYToOffset(y) << 1) + x]; while (height--) { @@ -237,12 +240,12 @@ void V_FillRect(int x, int y, int width, int height, byte colour) static void V_PlotPixel(int x, int y, int color) { - byte* fb = (byte*)_g->screens[0].data; + uint8_t* fb = (uint8_t*)_g->screens[0].data; - byte* dest = &fb[(ScreenYToOffset(y) << 1) + x]; + uint8_t* dest = &fb[(ScreenYToOffset(y) << 1) + x]; //The GBA must write in 16bits. - if((unsigned int)dest & 1) + if((uintptr_t)dest & 1) { //Odd addreses, we combine existing pixel with new one. unsigned short* dest16 = (unsigned short*)(dest - 1); diff --git a/source/version.c b/cppsrc/version.cc similarity index 100% rename from source/version.c rename to cppsrc/version.cc diff --git a/source/wi_stuff.c b/cppsrc/wi_stuff.cc similarity index 98% rename from source/wi_stuff.c rename to cppsrc/wi_stuff.cc index 392ab4d2..f058514e 100644 --- a/source/wi_stuff.c +++ b/cppsrc/wi_stuff.cc @@ -34,7 +34,7 @@ #include "doomstat.h" #include "m_random.h" -#include "w_wad.h" + #include "g_game.h" #include "r_main.h" #include "v_video.h" @@ -45,6 +45,7 @@ #include "r_draw.h" #include "global_data.h" +#include "annotations.h" // // Data needed to add patches to full screen intermission pics. @@ -256,11 +257,11 @@ void WI_levelNameLump(int epis, int map, char* buf) { if (_g->gamemode == commercial) { - sprintf(buf, "CWILV%2.2d", map); + snprintf(buf, sizeof(buf), "CWILV%2.2d", map); } else { - sprintf(buf, "WILV%d%d", epis, map); + snprintf(buf, sizeof(buf), "WILV%d%d", epis, map); } } @@ -275,9 +276,9 @@ static void WI_slamBackground(void) char name[9]; // limited to 8 characters if (_g->gamemode == commercial || (_g->gamemode == retail && _g->wbs->epsd == 3)) - strcpy(name, "INTERPIC"); + strncpy(name, "INTERPIC",sizeof(name)); else - sprintf(name, "WIMAP%d", _g->wbs->epsd); + snprintf(name, sizeof(name), "WIMAP%d", _g->wbs->epsd); // background V_DrawNamePatch(0, 0, FB, name, CR_DEFAULT, VPT_STRETCH); @@ -292,7 +293,7 @@ static void WI_slamBackground(void) // // The ticker is used to detect keys // because of timing issues in netgames. -boolean WI_Responder(event_t* ev) +boolean WI_Responder(event_t* ev UNUSED) { return false; } @@ -375,7 +376,7 @@ WI_drawOnLnode // draw stuff at a location by episode/map# int top; int right; int bottom; - const patch_t* patch = W_CacheLumpName(c[i]); + auto patch = Cached(c[i]); left = lnodes[_g->wbs->epsd][n].x - patch->leftoffset; top = lnodes[_g->wbs->epsd][n].y - patch->topoffset; @@ -495,7 +496,8 @@ static int WI_drawNum (int x, int y, int n, int digits) { x -= fontwidth; // CPhipps - patch drawing updated - V_DrawPatch(x, y, FB, _g->num[ n % 10 ]); + auto pinned_patch = _g->num[ n % 10 ].pin(); + V_DrawPatch(x, y, FB, pinned_patch); n /= 10; } @@ -1017,9 +1019,9 @@ void WI_loadData(void) for (i=0;i<10;i++) { // numbers 0-9 - sprintf(name, "WINUM%d", i); + snprintf(name, sizeof(name), "WINUM%d", i); - _g->num[i] = W_CacheLumpName(name); + _g->num[i] = Cached(name); } } diff --git a/cppsrc/z_zone_rpt.cc b/cppsrc/z_zone_rpt.cc new file mode 100644 index 00000000..403d4941 --- /dev/null +++ b/cppsrc/z_zone_rpt.cc @@ -0,0 +1,113 @@ +#include "../include/z_zone.h" +#include + +#ifdef RPT_MALLOC +#undef Z_Malloc +#undef Z_Free +#undef Z_Realloc +#undef Z_Calloc +#endif + +static const char *redtext = "\033[31m"; +static const char *yellowtext = "\033[33m"; +static const char *greentext = "\033[32m"; +static const char *bluetext = "\033[34m"; +static const char *normaltext = "\033[0m"; + +static const char *tags[] = { + "", + "PU_STATIC", + "PU_LEVEL", + "PU_LEVSPEC", + "PU_CACHE" +}; + +static const char *tagcolors[] = { + normaltext, + redtext, + yellowtext, + greentext, + bluetext +}; + +typedef struct memblock_s +{ + unsigned int size:24; // including the header and possibly tiny fragments + unsigned int tag:4; // purgelevel + void** user; // NULL if a free block + struct memblock_s* next; + struct memblock_s* prev; +} memblock_t; + +static int tagcount[] = { + 0, 0, 0, 0, 0 +}; + +static int maxtagcount[] = { + 0, 0, 0, 0, 0 +}; + +static int tagcount_nofree[] = { + 0, 0, 0, 0, 0 +}; + +static int Z_GetSize(void *ptr) { + if(ptr == NULL) + return 0; + memblock_t *block = (memblock_t *)ptr; + block--; + + return block->size; +} + +static int Z_GetTag(void *ptr) { + if(ptr == NULL) + return 0; + memblock_t *block = (memblock_t *)ptr; + block--; + return block->tag; +} + +void* Z_MallocRpt(int size, int tag, void **ptr, const char* file, int line) { + tagcount[tag] += size; + tagcount_nofree[tag] += size; + + if(tagcount[tag] > maxtagcount[tag]) + maxtagcount[tag] = tagcount[tag]; + + printf("%s:%d: %sAllocated %d bytes (%s=%d)%s\n", file, line, tagcolors[tag], size, tags[tag], tagcount[tag], normaltext); + return Z_Malloc(size, tag, ptr); +} +void Z_FreeRpt(void *ptr, const char* file, int line) { + int tag = Z_GetTag(ptr); + int size = Z_GetSize(ptr); + tagcount[tag] -= size; + printf("%s:%d: %sFreed %d bytes (%s=%d)%s\n", file, line, tagcolors[tag], size, tags[tag], tagcount[tag], normaltext); + Z_Free(ptr); +} +void *Z_ReallocRpt(void *ptr, size_t n, int tag, void **user, const char* file, int line){ + int size_old = Z_GetSize(ptr); + tagcount[tag] -= size_old; + tagcount[tag] += n; + + if(tagcount[tag] > maxtagcount[tag]) + maxtagcount[tag] = tagcount[tag]; + if(tagcount[tag] > tagcount_nofree[tag]) + tagcount_nofree[tag] = tagcount[tag]; + + printf("%s:%d: %sREALLOCATED from %d to %zu bytes (%s=%d)%s\n", file, line, tagcolors[tag], size_old, n, tags[tag], tagcount[tag], normaltext); + return Z_Realloc(ptr, n, tag, user); +} +void *Z_CallocRpt(size_t count, size_t size, int tag, void **user, const char* file, int line) { + tagcount[tag] += count * size; + tagcount_nofree[tag] += count * size; + printf("%s:%d: %sAllocated %zu bytes (%s=%d) with Calloc%s\n", file, line, tagcolors[tag], count * size, tags[tag], tagcount[tag], normaltext); + return Z_Calloc(count, size, tag, user); +} + +void Z_ReportAll() { + printf("Z_ReportAll: Current and maximum memory usage by tag:\n"); + for(int i = 0; i < 5; i++) { + printf("%s%s: Current=%d bytes, Maximum=%d bytes, Without free=%d bytes\n%s", tagcolors[i],tags[i], tagcount[i], maxtagcount[i],tagcount_nofree[i],normaltext); + } +} diff --git a/gamedata/guard/w_nc.cc b/gamedata/guard/w_nc.cc new file mode 100644 index 00000000..26089ee7 --- /dev/null +++ b/gamedata/guard/w_nc.cc @@ -0,0 +1,156 @@ +#include "../newcache/newcache.h" +#include "../guardmalloc/guardmalloc.h" +#include "../include/r_defs.h" + +#include +#include +#include + +extern unsigned char gfx_stbar[]; +extern line_t junk; + +/** + * This file contains a simple cache that uses guardmalloc to allocate memory and + * agressively disposes memory to trigger guardmalloc's leak detection in case some + * pointers are stolen from the cache functions. + */ + +const void * W_CacheLumpNum(int lumpnum); +int W_LumpLength(int lumpnum); +int W_GetNumForName (const char* name); +int W_CheckNumForName(const char *name); +const char *W_GetNameForNum(int lumpnum); +void W_Init(void); +void ExtractFileBase(const char* path, char* dest); + +int cachedlump = -1; +const uint8_t *cacheddata = nullptr; + +std::map pinned_allocations; +std::map pincount; + +// Simple wrappers mapping to W_ functions in the newcache namespace +const uint8_t * NC_CacheLumpNum(int lumpnum) +{ + if (lumpnum == STBAR_LUMP_NUM){ + return (const uint8_t *)gfx_stbar; // Violent hack ! + } + + if (cachedlump != lumpnum){ + // Free previous cache + if (cacheddata){ + // Don't free pinned allocations + if (pinned_allocations.count(cachedlump) == 0){ + GFREE((void *)cacheddata); + } + cacheddata = nullptr; + cachedlump = -1; + } + // Allocate new cache + int len = W_LumpLength(lumpnum); + uint8_t *data = (uint8_t *)GMALLOC(len); + if (!data){ + printf("NC_CacheLumpNum: Failed to allocate %d bytes for lump %d\n", len, lumpnum); + assert(false);exit(-1); + } + const uint8_t *lumpdata = (const uint8_t *)W_CacheLumpNum(lumpnum); + memcpy(data, lumpdata, len); + cacheddata = data; + cachedlump = lumpnum; + //printf("."); + //fflush(stdout); + } + return cacheddata; +} + +int NC_LumpLength(int lumpnum) +{ + return W_LumpLength(lumpnum); +} + +int NC_GetNumForName (const char* name) +{ + return W_GetNumForName(name); +} + +int NC_CheckNumForName(const char *name) +{ + return W_CheckNumForName(name); +} + +const char* NC_GetNameForNum(int lump, char buffer[8]) +{ + const char* name = W_GetNameForNum(lump); + strncpy(buffer,name,8); + return buffer; +} + +void NC_Init(void) +{ + W_Init(); + // Permanently pin lumps that are allocated in normal RAM + pinned_allocations[STBAR_LUMP_NUM]=gfx_stbar; + pincount[STBAR_LUMP_NUM]=1; + pinned_allocations[JUNK_LUMP_NUM]=(const uint8_t *)&junk; + pincount[JUNK_LUMP_NUM]=1; +} + +void NC_ExtractFileBase(const char* path, char* dest) +{ + ExtractFileBase(path, dest); +} + +const uint8_t * NC_Pin(int lumpnum) +{ + if (lumpnum==-1) return nullptr; + + if (pincount.count(lumpnum)){ + pincount[lumpnum]+=1; + return pinned_allocations[lumpnum]; + } + + // Pin the current cached data if it matches + if (cachedlump == lumpnum && cacheddata){ + pinned_allocations[lumpnum] = cacheddata; + pincount[lumpnum]=1; + return cacheddata; + } + + // Else cache it anew + auto data = NC_CacheLumpNum(lumpnum); + pinned_allocations[lumpnum] = data; + pincount[lumpnum]=1; + return data; +} + +void NC_Unpin(int lumpnum) +{ + if (lumpnum == -1) return; + if (pincount.count(lumpnum) == 0){ + printf("Error: Lump %d is not pinned\n", lumpnum); + assert(false);exit(-1); + } + + if (--pincount[lumpnum]) return; // Nested pin - not time to unpin yet + + // If the pinned allocation is not the cached one, free it + if (cachedlump != lumpnum && lumpnum > -2){ + GFREE((void *)pinned_allocations[lumpnum]); + } + + pinned_allocations.erase(lumpnum); + pincount.erase(lumpnum); +} + +void NC_FlushCache(void) +{ + // Free cached data if it is not pinned + if (cacheddata){ + if (pinned_allocations.count(cachedlump) == 0){ + GFREE((void *)cacheddata); + } + cacheddata = nullptr; + cachedlump = -1; + } +} + diff --git a/gamedata/minimem/gbadoom1.wad b/gamedata/minimem/gbadoom1.wad new file mode 100644 index 00000000..bc250b6c Binary files /dev/null and b/gamedata/minimem/gbadoom1.wad differ diff --git a/gamedata/minimem/gbadoom1_lumps.cc b/gamedata/minimem/gbadoom1_lumps.cc new file mode 100644 index 00000000..517e5677 --- /dev/null +++ b/gamedata/minimem/gbadoom1_lumps.cc @@ -0,0 +1,4652 @@ +#include "gbadoom1_lumps.h" +#include "annotations.h" + +int32_t CONSTMEM _filepos[WADLUMPS] = { + 18540, + 29292, + 37996, + 41996, + 62116, + 77476, + 0, + 86028, + 87408, + 114008, + 121784, + 125520, + 148944, + 149892, + 156500, + 158712, + 159616, + 0, + 166540, + 169160, + 227008, + 242884, + 250420, + 297236, + 299028, + 311544, + 316744, + 321744, + 0, + 333616, + 337416, + 394872, + 410784, + 418352, + 464592, + 466436, + 479316, + 483920, + 487840, + 0, + 496736, + 499276, + 545756, + 558404, + 564644, + 602148, + 603568, + 613480, + 617096, + 619512, + 0, + 626732, + 629664, + 675864, + 688500, + 694468, + 730980, + 732516, + 743240, + 746960, + 749520, + 0, + 757552, + 762184, + 837896, + 858620, + 868276, + 927860, + 930284, + 947224, + 953724, + 961540, + 0, + 977344, + 980924, + 1034572, + 1049248, + 1056416, + 1100288, + 1102156, + 1115204, + 1119624, + 1123240, + 0, + 1132088, + 1133348, + 1151996, + 1158128, + 1160752, + 1179504, + 1180212, + 1185140, + 1187064, + 1187752, + 0, + 1207152, + 1209524, + 1246092, + 1256916, + 1261564, + 1292860, + 1294012, + 1302048, + 1305872, + 1308576, + 1315356, + 1324592, + 1327396, + 1332740, + 1400908, + 1469076, + 1537244, + 1605412, + 1605460, + 1605492, + 1605552, + 1605612, + 1605656, + 1605716, + 1605772, + 1605824, + 1605884, + 1605936, + 1619064, + 1619132, + 1619196, + 1619272, + 1619344, + 1619404, + 1619476, + 1619548, + 1619620, + 1619696, + 1619768, + 1619896, + 1620216, + 1620460, + 1620796, + 1621132, + 1621448, + 1621796, + 1622136, + 1622412, + 1622760, + 1623096, + 1623424, + 1623492, + 1623556, + 1623632, + 1623704, + 1623764, + 1623836, + 1623908, + 1623980, + 1624056, + 1624128, + 1624232, + 1624336, + 1624440, + 1624560, + 1624680, + 1624800, + 1625192, + 1625520, + 1627168, + 1627240, + 1627340, + 1627456, + 1627584, + 1627728, + 1627860, + 1627920, + 1628040, + 1628160, + 1628256, + 1628332, + 1628392, + 1628472, + 1628528, + 1628628, + 1628760, + 1628844, + 1628984, + 1629116, + 1629232, + 1629356, + 1629488, + 1629608, + 1629748, + 1629880, + 1629964, + 1630036, + 1630116, + 1630196, + 1630276, + 1630404, + 1630560, + 1630692, + 1630832, + 1630972, + 1631104, + 1631236, + 1631364, + 1631496, + 1631632, + 1631704, + 1631824, + 1631964, + 1632084, + 1632232, + 1632368, + 1632492, + 1632620, + 1632756, + 1632896, + 1633016, + 1633136, + 1633268, + 1633376, + 1633524, + 1633684, + 1633808, + 1633936, + 1634028, + 1634128, + 1634220, + 1634316, + 1634420, + 1634492, + 1635900, + 1637308, + 1638716, + 1640124, + 1641604, + 1643084, + 1644564, + 1646044, + 1646852, + 1647660, + 1648468, + 1649352, + 1650232, + 1651076, + 1651892, + 1652716, + 1653524, + 1654332, + 1655132, + 1656016, + 1656904, + 1657748, + 1658564, + 1659388, + 1660216, + 1661040, + 1661864, + 1662760, + 1663656, + 1664500, + 1665316, + 1666140, + 1666976, + 1667816, + 1668648, + 1669592, + 1670500, + 1671344, + 1672160, + 1672984, + 1673820, + 1674664, + 1675508, + 1676492, + 1677400, + 1678244, + 1679060, + 1679884, + 1680692, + 1681528, + 1688300, + 1690612, + 1692468, + 1694688, + 1696816, + 1697320, + 1697824, + 1697932, + 1698072, + 1698280, + 1698420, + 1700600, + 1702008, + 1704456, + 1705084, + 1705812, + 1709216, + 1714124, + 1718344, + 1720128, + 1723360, + 1727608, + 1731928, + 1736324, + 1738776, + 1742408, + 1745044, + 1748236, + 1750400, + 1752764, + 1755096, + 1756788, + 1760708, + 1761704, + 1762504, + 1765804, + 1770072, + 1772924, + 1775720, + 1778516, + 1781036, + 1784012, + 1784204, + 1784396, + 1784588, + 1784632, + 1784736, + 1784780, + 1784840, + 1784900, + 1784944, + 1785048, + 1785092, + 1853260, + 1853404, + 1853548, + 1853692, + 1853900, + 1854108, + 1854316, + 1854524, + 1854732, + 1854940, + 1855084, + 1855228, + 1855372, + 1855516, + 1855660, + 1855804, + 1855948, + 1856092, + 1856236, + 1856444, + 1856652, + 1856860, + 1857068, + 1857276, + 1857484, + 1857900, + 1858316, + 1858732, + 1858876, + 1859020, + 1859164, + 1860244, + 1861324, + 1861968, + 1863052, + 1864236, + 1866080, + 1867236, + 1868312, + 1868584, + 1869464, + 1870272, + 1871132, + 1871212, + 1871476, + 1871704, + 1871840, + 1872084, + 1872320, + 1872532, + 1872776, + 1873012, + 1873200, + 1873432, + 1873664, + 1873772, + 1875232, + 1876368, + 1878080, + 1881144, + 1884296, + 1888192, + 1890748, + 1895304, + 1899264, + 1902924, + 1905844, + 1909808, + 1911768, + 1915396, + 1919732, + 1922940, + 1926228, + 1930884, + 1932964, + 1937028, + 1939972, + 1942976, + 1946916, + 1949220, + 1952128, + 1952880, + 1954864, + 1957280, + 1960788, + 1961192, + 1961704, + 1962204, + 1962684, + 1963088, + 1963600, + 1964100, + 1964580, + 1965112, + 1966016, + 1967608, + 0, + 1969644, + 1977824, + 1986028, + 1988712, + 1991020, + 1997712, + 2004404, + 2012256, + 2020236, + 2022868, + 2026636, + 2030300, + 2033916, + 2038808, + 2040216, + 2040536, + 2040856, + 2042172, + 2043796, + 2045860, + 2045936, + 2046080, + 2046336, + 2046712, + 2046788, + 2046920, + 2047136, + 2047476, + 2047792, + 2049676, + 2052036, + 2054264, + 2058052, + 2064028, + 2068288, + 2070472, + 2072168, + 2073564, + 2074584, + 2074976, + 2075128, + 2075172, + 2075260, + 2075436, + 2075696, + 2077092, + 2078144, + 2078532, + 2078676, + 2078720, + 2078964, + 2079220, + 2079848, + 2081084, + 2081956, + 2082416, + 2082524, + 2083628, + 2084956, + 2086544, + 2087888, + 2088832, + 2089924, + 2091256, + 2092844, + 2094076, + 2094832, + 2096228, + 2097672, + 2098980, + 2100348, + 2103460, + 2106056, + 2110208, + 2116924, + 2122900, + 2129488, + 2131112, + 2134320, + 2139112, + 2143608, + 2143872, + 2144472, + 2145364, + 2145848, + 2146112, + 2149512, + 2158372, + 2168740, + 2179408, + 2180564, + 2182232, + 2184232, + 2186616, + 2189004, + 2191164, + 2192804, + 2194884, + 2196924, + 2199088, + 2201144, + 2202992, + 2204988, + 2207160, + 2209448, + 2211436, + 2213076, + 2215156, + 2217300, + 2219476, + 2221308, + 2223156, + 2225300, + 2227220, + 2229452, + 2231480, + 2233324, + 2235140, + 2237476, + 2239692, + 2241840, + 2243964, + 2246524, + 2248668, + 2250644, + 2252608, + 2255268, + 2257724, + 2259896, + 2261908, + 2264344, + 2266432, + 2268468, + 2270404, + 2272932, + 2275224, + 2277312, + 2279284, + 2281456, + 2283456, + 2285016, + 2286712, + 2288868, + 2290976, + 2293316, + 2295564, + 2297464, + 2299372, + 2301208, + 2302936, + 2304568, + 2306132, + 2307276, + 2308324, + 2309532, + 2311132, + 2312552, + 2313856, + 2315084, + 2316236, + 2317848, + 2319376, + 2320524, + 2321584, + 2322796, + 2324324, + 2325976, + 2327296, + 2328308, + 2329456, + 2331136, + 2332396, + 2333680, + 2334932, + 2336108, + 2337696, + 2339172, + 2340552, + 2341732, + 2342896, + 2344224, + 2345868, + 2347568, + 2348948, + 2350060, + 2351512, + 2352656, + 2353984, + 2355320, + 2356724, + 2358316, + 2359820, + 2361120, + 2362412, + 2363644, + 2365856, + 2368404, + 2371256, + 2373832, + 2375840, + 2377664, + 2379120, + 2380360, + 2382648, + 2384828, + 2387284, + 2389468, + 2391616, + 2394408, + 2396820, + 2398820, + 2400976, + 2403508, + 2405796, + 2408276, + 2410676, + 2412700, + 2414848, + 2417636, + 2420016, + 2422036, + 2424260, + 2426792, + 2429584, + 2431620, + 2434128, + 2436860, + 2439400, + 2441524, + 2443904, + 2446888, + 2449956, + 2452560, + 2454876, + 2457412, + 2459956, + 2462424, + 2464536, + 2467128, + 2469528, + 2472252, + 2474560, + 2476776, + 2478992, + 2481324, + 2483524, + 2485876, + 2488568, + 2490940, + 2493448, + 2495772, + 2498148, + 2500348, + 2502620, + 2505056, + 2507748, + 2510324, + 2512828, + 2514860, + 2516620, + 2518404, + 2520188, + 2520612, + 2521188, + 2521936, + 2522444, + 2522904, + 2523472, + 2524240, + 2524760, + 2525780, + 2527088, + 2528864, + 2530284, + 2531616, + 2533040, + 2534428, + 2535648, + 2537100, + 2538388, + 2539688, + 2541076, + 2542388, + 2543820, + 2545256, + 2546560, + 2547912, + 2549256, + 2550696, + 2552096, + 2553324, + 2554624, + 2555972, + 2557248, + 2558616, + 2560216, + 2561636, + 2562808, + 2564088, + 2565500, + 2567148, + 2568644, + 2569764, + 2571256, + 2572572, + 2574056, + 2575552, + 2576948, + 2578584, + 2580012, + 2581544, + 2582956, + 2584004, + 2585056, + 2586116, + 2587784, + 2590088, + 2592520, + 2594824, + 2596792, + 2598540, + 2600144, + 2601528, + 2602892, + 2604284, + 2605600, + 2607008, + 2608360, + 2609580, + 2610996, + 2612256, + 2613540, + 2614896, + 2616196, + 2617600, + 2619012, + 2620316, + 2621652, + 2622988, + 2624416, + 2625788, + 2626996, + 2628288, + 2629600, + 2630848, + 2632204, + 2633788, + 2635208, + 2636364, + 2637612, + 2639028, + 2640672, + 2642152, + 2643264, + 2644748, + 2646036, + 2647460, + 2648932, + 2650316, + 2651920, + 2653196, + 2654420, + 2655548, + 2656536, + 2658360, + 2660768, + 2663292, + 2665660, + 2667652, + 2669424, + 2671064, + 2672528, + 2673880, + 2675196, + 2676420, + 2677740, + 2679060, + 2680272, + 2681656, + 2682760, + 2683896, + 2685208, + 2686508, + 2687844, + 2689072, + 2690328, + 2691592, + 2692924, + 2694288, + 2695528, + 2696656, + 2697884, + 2699208, + 2700448, + 2701656, + 2703084, + 2704444, + 2705600, + 2706832, + 2708128, + 2709680, + 2711156, + 2712272, + 2713628, + 2714812, + 2716208, + 2717680, + 2719012, + 2720508, + 2721828, + 2723072, + 2724216, + 2725272, + 2726996, + 2729372, + 2731896, + 2734264, + 2736256, + 2738028, + 2739668, + 2741132, + 2742484, + 2743320, + 2743564, + 2744664, + 2745568, + 2746692, + 2747816, + 2749340, + 2749528, + 2749744, + 2750108, + 2750448, + 2751228, + 2751884, + 2752540, + 2753196, + 2753852, + 2754796, + 2755740, + 2756572, + 2757368, + 2758984, + 2759688, + 2760352, + 2764624, + 2764956, + 2765288, + 2765620, + 2765952, + 2766284, + 2766616, + 2767728, + 2768332, + 2768936, + 2769880, + 2770804, + 2772388, + 2775084, + 2778504, + 2779508, + 2780512, + 2781516, + 2782520, + 2783244, + 2783968, + 2784692, + 2785416, + 2785708, + 2786000, + 2786292, + 2786584, + 2787308, + 2788032, + 2788756, + 2789480, + 2789836, + 2790192, + 2790548, + 2790904, + 2792024, + 2793084, + 2794132, + 0, + 0, + 0, + 2795220, + 2805276, + 2807796, + 2810316, + 2812836, + 2815356, + 2817876, + 2820396, + 2821700, + 2823004, + 2824308, + 2825612, + 2826916, + 2828220, + 2829524, + 2830828, + 2832132, + 2833436, + 2834740, + 2836044, + 2841236, + 2846428, + 2848380, + 2853572, + 2858764, + 2863444, + 2864748, + 2866052, + 2867356, + 2868660, + 2869964, + 2874132, + 2879324, + 2880628, + 2881932, + 2887124, + 2892316, + 2920396, + 2957356, + 2962036, + 2966716, + 2971396, + 2976076, + 2980756, + 2985436, + 2990116, + 2994796, + 2999476, + 3000572, + 3000780, + 3000988, + 3001196, + 3009972, + 3018748, + 3027524, + 3036300, + 3053844, + 3062620, + 3080164, + 3084148, + 3088132, + 3092072, + 3094172, + 3096392, + 3110704, + 3114980, + 3119192, + 3123584, + 3127976, + 3132368, + 3136760, + 3141152, + 3145544, + 3149936, + 3154328, + 3163104, + 3171880, + 3180656, + 3189432, + 3193824, + 3198216, + 3202608, + 3207000, + 3211392, + 3212696, + 3221472, + 3230248, + 3231352, + 3240128, + 3242080, + 3252456, + 3262832, + 3263384, + 3263936, + 3264488, + 3265040, + 3265592, + 3266144, + 3266696, + 3267248, + 3268056, + 3268264, + 3285808, + 3286912, + 3304456, + 3322000, + 3325648, + 3329296, + 3332944, + 3336592, + 3340240, + 3344408, + 3348576, + 3352744, + 3356912, + 3361080, + 3365248, + 3369416, + 3373584, + 3378264, + 3380608, + 3385288, + 3387632, + 3389976, + 3392320, + 3397000, + 3401680, + 3406360, + 3411040, + 3415720, + 3420400, + 3425080, + 3435168, + 3452712, + 3457904, + 3459856, + 3461808, + 3467000, + 3468104, + 3485648, + 3486200, + 3486752, + 3486896, + 3487040, + 3487184, + 3487328, + 3487472, + 3487616, + 3489736, + 3491452, + 3494928, + 3498404, + 3501880, + 3505356, + 3508832, + 3512308, + 3514232, + 3515552, + 3516872, + 3518192, + 3519512, + 3520832, + 3522152, + 3522952, + 3523752, + 0, + 0, + 0, + 0, + 3558832, + 3562928, + 3567024, + 3571120, + 3575216, + 3579312, + 3583408, + 3587504, + 3591600, + 3595696, + 3599792, + 3603888, + 3607984, + 3612080, + 3616176, + 3620272, + 3624368, + 3628464, + 3632560, + 3636656, + 3640752, + 3644848, + 3648944, + 3653040, + 3657136, + 3661232, + 3665328, + 3669424, + 3673520, + 3677616, + 3681712, + 3685808, + 3689904, + 3694000, + 3698096, + 3702192, + 3706288, + 3710384, + 3714480, + 3718576, + 3722672, + 3726768, + 3730864, + 3734960, + 3739056, + 3743152, + 3747248, + 3751344, + 3755440, + 3759536, + 3763632, + 3767728, + 3771824, + 3775920, + 0, + 0, + 3780016, + 3780148, + 3782852, + 3785908, + 3786140, + 3786340, + 3786600, + 3786848, + 3787072, + 3787332, + 3787580, + 3787792, + 3788044, + 3788284, + 3799036, + 3809788, + 3820540, + 3831292, +}; + +int32_t CONSTMEM _lumpsize[WADLUMPS] = { + 10752, + 8704, + 4000, + 20118, + 15358, + 8550, + 0, + 1380, + 26600, + 7776, + 3736, + 23424, + 948, + 6608, + 2210, + 904, + 6922, + 0, + 2620, + 57848, + 15876, + 7536, + 46816, + 1792, + 12516, + 5200, + 5000, + 11870, + 0, + 3800, + 57456, + 15912, + 7568, + 46240, + 1844, + 12880, + 4602, + 3917, + 8894, + 0, + 2540, + 46480, + 12648, + 6240, + 37504, + 1420, + 9912, + 3614, + 2416, + 7218, + 0, + 2930, + 46200, + 12636, + 5968, + 36512, + 1536, + 10724, + 3718, + 2557, + 8032, + 0, + 4630, + 75712, + 20724, + 9656, + 59584, + 2424, + 16940, + 6500, + 7813, + 15804, + 0, + 3580, + 53648, + 14676, + 7168, + 43872, + 1868, + 13048, + 4420, + 3613, + 8846, + 0, + 1260, + 18648, + 6132, + 2624, + 18752, + 708, + 4928, + 1924, + 685, + 19400, + 0, + 2370, + 36568, + 10824, + 4648, + 31296, + 1152, + 8036, + 3822, + 2702, + 6780, + 9234, + 2804, + 5342, + 68168, + 68168, + 68168, + 68168, + 48, + 32, + 60, + 60, + 44, + 60, + 56, + 52, + 60, + 52, + 13128, + 68, + 64, + 76, + 72, + 60, + 72, + 72, + 72, + 76, + 72, + 128, + 320, + 244, + 336, + 336, + 316, + 348, + 340, + 276, + 348, + 336, + 328, + 68, + 64, + 76, + 72, + 60, + 72, + 72, + 72, + 76, + 72, + 104, + 104, + 104, + 120, + 120, + 120, + 392, + 328, + 1648, + 72, + 100, + 116, + 128, + 144, + 132, + 60, + 120, + 120, + 96, + 76, + 60, + 80, + 56, + 100, + 132, + 84, + 140, + 132, + 116, + 124, + 132, + 120, + 140, + 132, + 84, + 72, + 80, + 80, + 80, + 128, + 156, + 132, + 140, + 140, + 132, + 132, + 128, + 132, + 136, + 72, + 120, + 140, + 120, + 148, + 136, + 124, + 128, + 136, + 140, + 120, + 120, + 132, + 108, + 148, + 160, + 124, + 128, + 92, + 100, + 92, + 96, + 104, + 72, + 1408, + 1408, + 1408, + 1408, + 1480, + 1480, + 1480, + 1480, + 808, + 808, + 808, + 884, + 880, + 844, + 816, + 824, + 808, + 808, + 800, + 884, + 888, + 844, + 816, + 824, + 828, + 824, + 824, + 896, + 896, + 844, + 816, + 824, + 836, + 840, + 832, + 944, + 908, + 844, + 816, + 824, + 836, + 844, + 844, + 984, + 908, + 844, + 816, + 824, + 808, + 836, + 6772, + 2312, + 1856, + 2220, + 2128, + 504, + 504, + 108, + 140, + 208, + 140, + 2180, + 1408, + 2448, + 628, + 728, + 3404, + 4908, + 4220, + 1784, + 3232, + 4248, + 4320, + 4396, + 2452, + 3632, + 2636, + 3192, + 2164, + 2364, + 2332, + 1692, + 3920, + 996, + 800, + 3300, + 4268, + 2852, + 2796, + 2796, + 2520, + 2976, + 192, + 192, + 192, + 44, + 104, + 44, + 60, + 60, + 44, + 104, + 44, + 68168, + 144, + 144, + 144, + 208, + 208, + 208, + 208, + 208, + 208, + 144, + 144, + 144, + 144, + 144, + 144, + 144, + 144, + 144, + 208, + 208, + 208, + 208, + 208, + 208, + 416, + 416, + 416, + 144, + 144, + 144, + 1080, + 1080, + 644, + 1084, + 1184, + 1844, + 1156, + 1076, + 272, + 880, + 808, + 860, + 80, + 264, + 228, + 136, + 244, + 236, + 212, + 244, + 236, + 188, + 232, + 232, + 108, + 1460, + 1136, + 1712, + 3064, + 3152, + 3896, + 2556, + 4556, + 3960, + 3660, + 2920, + 3964, + 1960, + 3628, + 4336, + 3208, + 3288, + 4656, + 2080, + 4064, + 2944, + 3004, + 3940, + 2304, + 2908, + 752, + 1984, + 2416, + 3508, + 404, + 512, + 500, + 480, + 404, + 512, + 500, + 480, + 532, + 904, + 1592, + 2036, + 0, + 8180, + 8204, + 2684, + 2308, + 6692, + 6692, + 7852, + 7980, + 2632, + 3768, + 3664, + 3616, + 4892, + 1408, + 320, + 320, + 1316, + 1624, + 2064, + 76, + 144, + 256, + 376, + 76, + 132, + 216, + 340, + 316, + 1884, + 2360, + 2228, + 3788, + 5976, + 4260, + 2184, + 1696, + 1396, + 1020, + 392, + 152, + 44, + 88, + 176, + 260, + 1396, + 1052, + 388, + 144, + 44, + 244, + 256, + 628, + 1236, + 872, + 460, + 108, + 1104, + 1328, + 1588, + 1344, + 944, + 1092, + 1332, + 1588, + 1232, + 756, + 1396, + 1444, + 1308, + 1368, + 3112, + 2596, + 4152, + 6716, + 5976, + 6588, + 1624, + 3208, + 4792, + 4496, + 264, + 600, + 892, + 484, + 264, + 3400, + 8860, + 10368, + 10668, + 1156, + 1668, + 2000, + 2384, + 2388, + 2160, + 1640, + 2080, + 2040, + 2164, + 2056, + 1848, + 1996, + 2172, + 2288, + 1988, + 1640, + 2080, + 2144, + 2176, + 1832, + 1848, + 2144, + 1920, + 2232, + 2028, + 1844, + 1816, + 2336, + 2216, + 2148, + 2124, + 2560, + 2144, + 1976, + 1964, + 2660, + 2456, + 2172, + 2012, + 2436, + 2088, + 2036, + 1936, + 2528, + 2292, + 2088, + 1972, + 2172, + 2000, + 1560, + 1696, + 2156, + 2108, + 2340, + 2248, + 1900, + 1908, + 1836, + 1728, + 1632, + 1564, + 1144, + 1048, + 1208, + 1600, + 1420, + 1304, + 1228, + 1152, + 1612, + 1528, + 1148, + 1060, + 1212, + 1528, + 1652, + 1320, + 1012, + 1148, + 1680, + 1260, + 1284, + 1252, + 1176, + 1588, + 1476, + 1380, + 1180, + 1164, + 1328, + 1644, + 1700, + 1380, + 1112, + 1452, + 1144, + 1328, + 1336, + 1404, + 1592, + 1504, + 1300, + 1292, + 1232, + 2212, + 2548, + 2852, + 2576, + 2008, + 1824, + 1456, + 1240, + 2288, + 2180, + 2456, + 2184, + 2148, + 2792, + 2412, + 2000, + 2156, + 2532, + 2288, + 2480, + 2400, + 2024, + 2148, + 2788, + 2380, + 2020, + 2224, + 2532, + 2792, + 2036, + 2508, + 2732, + 2540, + 2124, + 2380, + 2984, + 3068, + 2604, + 2316, + 2536, + 2544, + 2468, + 2112, + 2592, + 2400, + 2724, + 2308, + 2216, + 2216, + 2332, + 2200, + 2352, + 2692, + 2372, + 2508, + 2324, + 2376, + 2200, + 2272, + 2436, + 2692, + 2576, + 2504, + 2032, + 1760, + 1784, + 1784, + 424, + 576, + 748, + 508, + 460, + 568, + 768, + 520, + 1020, + 1308, + 1776, + 1420, + 1332, + 1424, + 1388, + 1220, + 1452, + 1288, + 1300, + 1388, + 1312, + 1432, + 1436, + 1304, + 1352, + 1344, + 1440, + 1400, + 1228, + 1300, + 1348, + 1276, + 1368, + 1600, + 1420, + 1172, + 1280, + 1412, + 1648, + 1496, + 1120, + 1492, + 1316, + 1484, + 1496, + 1396, + 1636, + 1428, + 1532, + 1412, + 1048, + 1052, + 1060, + 1668, + 2304, + 2432, + 2304, + 1968, + 1748, + 1604, + 1384, + 1364, + 1392, + 1316, + 1408, + 1352, + 1220, + 1416, + 1260, + 1284, + 1356, + 1300, + 1404, + 1412, + 1304, + 1336, + 1336, + 1428, + 1372, + 1208, + 1292, + 1312, + 1248, + 1356, + 1584, + 1420, + 1156, + 1248, + 1416, + 1644, + 1480, + 1112, + 1484, + 1288, + 1424, + 1472, + 1384, + 1604, + 1276, + 1224, + 1128, + 988, + 1824, + 2408, + 2524, + 2368, + 1992, + 1772, + 1640, + 1464, + 1352, + 1316, + 1224, + 1320, + 1320, + 1212, + 1384, + 1104, + 1136, + 1312, + 1300, + 1336, + 1228, + 1256, + 1264, + 1332, + 1364, + 1240, + 1128, + 1228, + 1324, + 1240, + 1208, + 1428, + 1360, + 1156, + 1232, + 1296, + 1552, + 1476, + 1116, + 1356, + 1184, + 1396, + 1472, + 1332, + 1496, + 1320, + 1244, + 1144, + 1056, + 1724, + 2376, + 2524, + 2368, + 1992, + 1772, + 1640, + 1464, + 1352, + 836, + 244, + 1100, + 904, + 1124, + 1124, + 1524, + 188, + 216, + 364, + 340, + 780, + 656, + 656, + 656, + 656, + 944, + 944, + 832, + 796, + 1616, + 704, + 664, + 4272, + 332, + 332, + 332, + 332, + 332, + 332, + 1112, + 604, + 604, + 944, + 924, + 1584, + 2696, + 3420, + 1004, + 1004, + 1004, + 1004, + 724, + 724, + 724, + 724, + 292, + 292, + 292, + 292, + 724, + 724, + 724, + 724, + 356, + 356, + 356, + 356, + 1120, + 1060, + 1048, + 1088, + 0, + 0, + 0, + 10056, + 2520, + 2520, + 2520, + 2520, + 2520, + 2520, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 1304, + 5192, + 5192, + 1952, + 5192, + 5192, + 4680, + 1304, + 1304, + 1304, + 1304, + 1304, + 4168, + 5192, + 1304, + 1304, + 5192, + 5192, + 28080, + 36960, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 1096, + 208, + 208, + 208, + 8776, + 8776, + 8776, + 8776, + 17544, + 8776, + 17544, + 3984, + 3984, + 3940, + 2100, + 2220, + 14312, + 4276, + 4212, + 4392, + 4392, + 4392, + 4392, + 4392, + 4392, + 4392, + 4392, + 8776, + 8776, + 8776, + 8776, + 4392, + 4392, + 4392, + 4392, + 4392, + 1304, + 8776, + 8776, + 1104, + 8776, + 1952, + 10376, + 10376, + 552, + 552, + 552, + 552, + 552, + 552, + 552, + 552, + 808, + 208, + 17544, + 1104, + 17544, + 17544, + 3648, + 3648, + 3648, + 3648, + 3648, + 4168, + 4168, + 4168, + 4168, + 4168, + 4168, + 4168, + 4168, + 4680, + 2344, + 4680, + 2344, + 2344, + 2344, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 4680, + 10088, + 17544, + 5192, + 1952, + 1952, + 5192, + 1104, + 17544, + 552, + 552, + 144, + 144, + 144, + 144, + 144, + 144, + 2120, + 1716, + 3476, + 3476, + 3476, + 3476, + 3476, + 3476, + 1924, + 1320, + 1320, + 1320, + 1320, + 1320, + 1320, + 800, + 800, + 35080, + 0, + 0, + 0, + 0, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 4096, + 0, + 0, + 130, + 2702, + 3056, + 232, + 200, + 259, + 246, + 224, + 257, + 246, + 211, + 249, + 237, + 10752, + 10752, + 10752, + 10752, + 10752, +}; + +uint32_t CONSTMEM _lumpname_high[WADLUMPS] = { + 0x004c4150, + 0x50414d52, + 0x00004d4f, + 0x00000031, + 0x00000032, + 0x00000033, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x00000000, + 0x00005347, + 0x53464544, + 0x53464544, + 0x53455845, + 0x00000000, + 0x53524f54, + 0x00000053, + 0x0053524f, + 0x00005443, + 0x50414d4b, + 0x31455255, + 0x00005345, + 0x00005355, + 0x00000031, + 0x00000032, + 0x00005449, + 0x43495045, + 0x00304d55, + 0x00314d55, + 0x00324d55, + 0x00334d55, + 0x00344d55, + 0x00354d55, + 0x00364d55, + 0x00374d55, + 0x00384d55, + 0x00394d55, + 0x00000052, + 0x00304d55, + 0x00314d55, + 0x00324d55, + 0x00334d55, + 0x00344d55, + 0x00354d55, + 0x00364d55, + 0x00374d55, + 0x00384d55, + 0x00394d55, + 0x53554e49, + 0x00304d55, + 0x00314d55, + 0x00324d55, + 0x00334d55, + 0x00344d55, + 0x00354d55, + 0x00364d55, + 0x00374d55, + 0x00384d55, + 0x00394d55, + 0x544e4352, + 0x304d554e, + 0x314d554e, + 0x324d554e, + 0x334d554e, + 0x344d554e, + 0x354d554e, + 0x364d554e, + 0x374d554e, + 0x384d554e, + 0x394d554e, + 0x00305359, + 0x00315359, + 0x00325359, + 0x00335359, + 0x00345359, + 0x00355359, + 0x00004b53, + 0x004d4f52, + 0x0000534d, + 0x3333304e, + 0x3433304e, + 0x3533304e, + 0x3633304e, + 0x3733304e, + 0x3833304e, + 0x3933304e, + 0x3034304e, + 0x3134304e, + 0x3234304e, + 0x3334304e, + 0x3434304e, + 0x3534304e, + 0x3634304e, + 0x3734304e, + 0x3834304e, + 0x3934304e, + 0x3035304e, + 0x3135304e, + 0x3235304e, + 0x3335304e, + 0x3435304e, + 0x3535304e, + 0x3635304e, + 0x3735304e, + 0x3835304e, + 0x3935304e, + 0x3036304e, + 0x3136304e, + 0x3236304e, + 0x3336304e, + 0x3436304e, + 0x3536304e, + 0x3636304e, + 0x3736304e, + 0x3836304e, + 0x3936304e, + 0x3037304e, + 0x3137304e, + 0x3237304e, + 0x3337304e, + 0x3437304e, + 0x3537304e, + 0x3637304e, + 0x3737304e, + 0x3837304e, + 0x3937304e, + 0x3038304e, + 0x3138304e, + 0x3238304e, + 0x3338304e, + 0x3438304e, + 0x3538304e, + 0x3638304e, + 0x3738304e, + 0x3838304e, + 0x3938304e, + 0x3039304e, + 0x3139304e, + 0x3239304e, + 0x3339304e, + 0x3439304e, + 0x3539304e, + 0x3132314e, + 0x00000031, + 0x00000030, + 0x00000032, + 0x00000033, + 0x00000031, + 0x00000030, + 0x00000032, + 0x00000033, + 0x00313054, + 0x00303054, + 0x00323054, + 0x0030304c, + 0x00303052, + 0x30484355, + 0x00304c56, + 0x304c4c49, + 0x00313154, + 0x00303154, + 0x00323154, + 0x0030314c, + 0x00303152, + 0x31484355, + 0x00314c56, + 0x314c4c49, + 0x00313254, + 0x00303254, + 0x00323254, + 0x0030324c, + 0x00303252, + 0x32484355, + 0x00324c56, + 0x324c4c49, + 0x00313354, + 0x00303354, + 0x00323354, + 0x0030334c, + 0x00303352, + 0x33484355, + 0x00334c56, + 0x334c4c49, + 0x00313454, + 0x00303454, + 0x00323454, + 0x0030344c, + 0x00303452, + 0x34484355, + 0x00344c56, + 0x344c4c49, + 0x0030444f, + 0x30444145, + 0x00004d4f, + 0x53494854, + 0x4e4f4954, + 0x00475449, + 0x00454d41, + 0x314c4c55, + 0x324c4c55, + 0x4f4d5245, + 0x524d5245, + 0x4d4d5245, + 0x4c4d5245, + 0x4d414744, + 0x00455355, + 0x00475353, + 0x004e4f47, + 0x46464f47, + 0x444f5349, + 0x00003149, + 0x00003249, + 0x00003349, + 0x00005452, + 0x004c4c49, + 0x00484755, + 0x004c4c49, + 0x00004757, + 0x00415254, + 0x00455241, + 0x00004c4f, + 0x4c545454, + 0x00474556, + 0x00474441, + 0x00005053, + 0x00534e45, + 0x48474948, + 0x00574f4c, + 0x4c494154, + 0x54504f53, + 0x5a534e52, + 0x004c5454, + 0x004c5454, + 0x4c4f5658, + 0x4c4f5653, + 0x5446454c, + 0x52544e43, + 0x54484752, + 0x004c545f, + 0x0000545f, + 0x0052545f, + 0x00004c5f, + 0x0000525f, + 0x004c425f, + 0x0000425f, + 0x0052425f, + 0x00003050, + 0x30303930, + 0x31303930, + 0x32303930, + 0x30303830, + 0x31303830, + 0x32303830, + 0x30303730, + 0x31303730, + 0x32303730, + 0x30303630, + 0x31303630, + 0x32303630, + 0x30303530, + 0x31303530, + 0x32303530, + 0x30303430, + 0x31303430, + 0x32303430, + 0x30303330, + 0x31303330, + 0x32303330, + 0x30303230, + 0x31303230, + 0x32303230, + 0x30303130, + 0x31303130, + 0x32303130, + 0x30303030, + 0x31303030, + 0x32303030, + 0x00003048, + 0x00003148, + 0x0054414c, + 0x00004b54, + 0x00004954, + 0x00000000, + 0x00005454, + 0x00005354, + 0x00004654, + 0x0000454d, + 0x00000052, + 0x00524154, + 0x0053554e, + 0x0000544e, + 0x0000304d, + 0x0000314d, + 0x0000324d, + 0x0000334d, + 0x0000344d, + 0x0000354d, + 0x0000364d, + 0x0000374d, + 0x0000384d, + 0x0000394d, + 0x004e4f4c, + 0x00534b43, + 0x00005347, + 0x00003030, + 0x00003130, + 0x00003230, + 0x00003330, + 0x00003430, + 0x00003530, + 0x00003630, + 0x00003730, + 0x00003830, + 0x00003131, + 0x00003231, + 0x00003431, + 0x00003531, + 0x00003631, + 0x00003731, + 0x00003831, + 0x00003032, + 0x00003132, + 0x00003232, + 0x00003332, + 0x00003432, + 0x00003532, + 0x00003632, + 0x00003732, + 0x00003832, + 0x00003331, + 0x00003031, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000031, + 0x00000032, + 0x00000033, + 0x00000034, + 0x0053524c, + 0x00534d54, + 0x00325452, + 0x00524554, + 0x00545241, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003041, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003046, + 0x00003047, + 0x00003048, + 0x00003049, + 0x0000304a, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003141, + 0x32413841, + 0x33413741, + 0x34413641, + 0x00003541, + 0x00003142, + 0x32423842, + 0x33423742, + 0x34423642, + 0x00003542, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003141, + 0x32413841, + 0x33413741, + 0x34413641, + 0x00003541, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x00003245, + 0x00003345, + 0x00003445, + 0x00003545, + 0x00003645, + 0x00003745, + 0x00003845, + 0x00003146, + 0x00003246, + 0x00003346, + 0x00003446, + 0x00003546, + 0x00003646, + 0x00003746, + 0x00003846, + 0x00003147, + 0x00003247, + 0x00003347, + 0x00003447, + 0x00003547, + 0x00003647, + 0x00003747, + 0x00003847, + 0x00003148, + 0x00003248, + 0x00003348, + 0x00003448, + 0x00003548, + 0x00003648, + 0x00003748, + 0x00003848, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x38453245, + 0x37453345, + 0x36453445, + 0x00003545, + 0x00003146, + 0x38463246, + 0x37463346, + 0x36463446, + 0x00003546, + 0x00003147, + 0x38473247, + 0x37473347, + 0x36473447, + 0x00003547, + 0x00003148, + 0x38483248, + 0x37483348, + 0x36483448, + 0x00003548, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x0000304f, + 0x00003050, + 0x00003051, + 0x00003052, + 0x00003053, + 0x00003054, + 0x00003055, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x00003245, + 0x00003345, + 0x00003445, + 0x00003545, + 0x00003645, + 0x00003745, + 0x00003845, + 0x00003146, + 0x00003246, + 0x00003346, + 0x00003446, + 0x00003546, + 0x00003646, + 0x00003746, + 0x00003846, + 0x00003147, + 0x00003247, + 0x00003347, + 0x00003447, + 0x00003547, + 0x00003647, + 0x00003747, + 0x00003847, + 0x00003148, + 0x00003248, + 0x00003348, + 0x00003448, + 0x00003548, + 0x00003648, + 0x00003748, + 0x00003848, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x0000304f, + 0x35413141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x35423142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x38453245, + 0x37453345, + 0x36453445, + 0x00003545, + 0x00003146, + 0x38463246, + 0x37463346, + 0x36463446, + 0x00003546, + 0x00003147, + 0x38473247, + 0x37473347, + 0x36473447, + 0x00003547, + 0x00003048, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x0000304f, + 0x00003050, + 0x00003051, + 0x00003052, + 0x00003053, + 0x00003054, + 0x00003055, + 0x00003056, + 0x00003057, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x38453245, + 0x37453345, + 0x36453445, + 0x00003545, + 0x00003146, + 0x38463246, + 0x37463346, + 0x36463446, + 0x00003546, + 0x00003147, + 0x38473247, + 0x37473347, + 0x36473447, + 0x00003547, + 0x00003048, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x0000304f, + 0x00003050, + 0x00003051, + 0x00003052, + 0x00003053, + 0x00003054, + 0x00003055, + 0x00003141, + 0x38413241, + 0x37413341, + 0x36413441, + 0x00003541, + 0x00003142, + 0x38423242, + 0x37423342, + 0x36423442, + 0x00003542, + 0x00003143, + 0x38433243, + 0x37433343, + 0x36433443, + 0x00003543, + 0x00003144, + 0x38443244, + 0x37443344, + 0x36443444, + 0x00003544, + 0x00003145, + 0x38453245, + 0x37453345, + 0x36453445, + 0x00003545, + 0x00003146, + 0x38463246, + 0x37463346, + 0x36463446, + 0x00003546, + 0x00003147, + 0x38473247, + 0x37473347, + 0x36473447, + 0x00003547, + 0x00003048, + 0x00003049, + 0x0000304a, + 0x0000304b, + 0x0000304c, + 0x0000304d, + 0x0000304e, + 0x0000304f, + 0x00003050, + 0x00003051, + 0x00003052, + 0x00003053, + 0x00003054, + 0x00003055, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003045, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003044, + 0x00000044, + 0x00545241, + 0x54524154, + 0x315f3030, + 0x325f3030, + 0x335f3030, + 0x355f3030, + 0x365f3030, + 0x375f3030, + 0x385f3030, + 0x315f3130, + 0x325f3130, + 0x335f3130, + 0x345f3130, + 0x355f3130, + 0x365f3130, + 0x375f3130, + 0x385f3130, + 0x395f3130, + 0x415f3130, + 0x425f3130, + 0x435f3130, + 0x315f3230, + 0x325f3230, + 0x335f3230, + 0x315f3330, + 0x345f3330, + 0x375f3330, + 0x325f3430, + 0x335f3430, + 0x345f3430, + 0x355f3430, + 0x375f3430, + 0x325f3530, + 0x00000031, + 0x00000038, + 0x00000041, + 0x00000034, + 0x00000035, + 0x00000031, + 0x315f3432, + 0x00000035, + 0x00000036, + 0x00000037, + 0x00000038, + 0x00000031, + 0x00000031, + 0x00000034, + 0x00000035, + 0x00000037, + 0x00000038, + 0x00003733, + 0x00003833, + 0x00003933, + 0x315f3735, + 0x325f3735, + 0x335f3735, + 0x345f3735, + 0x315f3236, + 0x325f3236, + 0x00000031, + 0x0000325f, + 0x0000335f, + 0x0000315f, + 0x0000325f, + 0x0000335f, + 0x0000315f, + 0x0000325f, + 0x0000335f, + 0x0000315f, + 0x0000325f, + 0x0000345f, + 0x0000355f, + 0x0000315f, + 0x0000325f, + 0x0000345f, + 0x0000355f, + 0x0000315f, + 0x0000325f, + 0x0000335f, + 0x0000345f, + 0x0000345f, + 0x0000355f, + 0x0000365f, + 0x0000375f, + 0x0000375f, + 0x00000035, + 0x00315f38, + 0x00325f38, + 0x315f3832, + 0x315f3832, + 0x3254524f, + 0x00315f32, + 0x00325f32, + 0x00003330, + 0x00003430, + 0x00003530, + 0x00003630, + 0x00003730, + 0x00003830, + 0x00003930, + 0x00003031, + 0x00000031, + 0x00000032, + 0x00315f32, + 0x325f314c, + 0x00000031, + 0x00000032, + 0x315f3130, + 0x355f3130, + 0x365f3130, + 0x345f4231, + 0x365f4331, + 0x315f3230, + 0x325f3230, + 0x335f3230, + 0x345f3230, + 0x355f3230, + 0x365f3230, + 0x375f3230, + 0x385f3230, + 0x315f3330, + 0x345f3330, + 0x355f3330, + 0x365f3330, + 0x375f3330, + 0x385f3330, + 0x395f3330, + 0x315f3430, + 0x325f3430, + 0x355f3430, + 0x365f3430, + 0x375f3430, + 0x385f3430, + 0x00315f32, + 0x00345f32, + 0x00355f32, + 0x00345f33, + 0x00355f33, + 0x00365f33, + 0x4b415254, + 0x00315f39, + 0x00003041, + 0x00003042, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00003041, + 0x00003042, + 0x00003043, + 0x00454744, + 0x00000050, + 0x0000324e, + 0x0000334e, + 0x0000344e, + 0x0000354e, + 0x0000364e, + 0x0000384e, + 0x00003041, + 0x00000030, + 0x00000031, + 0x00000030, + 0x00000031, + 0x00000030, + 0x00000031, + 0x00000030, + 0x00000031, + 0x00000000, + 0x0000444e, + 0x00000044, + 0x00545241, + 0x54524154, + 0x315f3052, + 0x335f3052, + 0x365f3052, + 0x315f3152, + 0x375f3152, + 0x335f3352, + 0x315f3452, + 0x355f3452, + 0x365f3452, + 0x385f3452, + 0x315f3552, + 0x325f3552, + 0x335f3552, + 0x345f3552, + 0x00000031, + 0x00000032, + 0x315f3652, + 0x325f3652, + 0x315f3645, + 0x345f3645, + 0x355f3645, + 0x365f3645, + 0x315f3752, + 0x325f3752, + 0x00315f38, + 0x0000315f, + 0x0000325f, + 0x0000335f, + 0x0000345f, + 0x00315f33, + 0x00325f33, + 0x00355f33, + 0x00325f34, + 0x00335f34, + 0x00315f35, + 0x00325f35, + 0x00000031, + 0x00000032, + 0x00000035, + 0x00003031, + 0x00003431, + 0x00003831, + 0x00003032, + 0x00003232, + 0x00003332, + 0x00345f35, + 0x00355f35, + 0x00315f31, + 0x00355f31, + 0x00375f31, + 0x00314547, + 0x00324547, + 0x00334547, + 0x00003159, + 0x0000444e, + 0x00000044, + 0x00535449, + 0x00004e55, + 0x00414d4d, + 0x304d554e, + 0x314d554e, + 0x324d554e, + 0x334d554e, + 0x344d554e, + 0x354d554e, + 0x364d554e, + 0x374d554e, + 0x384d554e, + 0x394d554e, + 0x314c4150, + 0x324c4150, + 0x334c4150, + 0x344c4150, + 0x354c4150, +}; + +uint32_t CONSTMEM _lumpname_low[WADLUMPS] = { + 0x59414c50, + 0x4f4c4f43, + 0x4f444e45, + 0x4f4d4544, + 0x4f4d4544, + 0x4f4d4544, + 0x314d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x324d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x334d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x344d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x354d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x364d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x374d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x384d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x394d3145, + 0x4e494854, + 0x454e494c, + 0x45444953, + 0x54524556, + 0x53474553, + 0x43455353, + 0x45444f4e, + 0x54434553, + 0x454a4552, + 0x434f4c42, + 0x54584554, + 0x4d414e50, + 0x47584d44, + 0x504c4548, + 0x504c4548, + 0x44455243, + 0x4c544954, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x4e4d4d41, + 0x41425453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4e475453, + 0x4d545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x4e545453, + 0x50545453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x53595453, + 0x454b5453, + 0x454b5453, + 0x454b5453, + 0x454b5453, + 0x454b5453, + 0x454b5453, + 0x49445453, + 0x44435453, + 0x52415453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x46435453, + 0x42465453, + 0x42465453, + 0x42465453, + 0x42465453, + 0x42505453, + 0x42505453, + 0x42505453, + 0x42505453, + 0x53465453, + 0x53465453, + 0x53465453, + 0x54465453, + 0x54465453, + 0x4f465453, + 0x45465453, + 0x4b465453, + 0x53465453, + 0x53465453, + 0x53465453, + 0x54465453, + 0x54465453, + 0x4f465453, + 0x45465453, + 0x4b465453, + 0x53465453, + 0x53465453, + 0x53465453, + 0x54465453, + 0x54465453, + 0x4f465453, + 0x45465453, + 0x4b465453, + 0x53465453, + 0x53465453, + 0x53465453, + 0x54465453, + 0x54465453, + 0x4f465453, + 0x45465453, + 0x4b465453, + 0x53465453, + 0x53465453, + 0x53465453, + 0x54465453, + 0x54465453, + 0x4f465453, + 0x45465453, + 0x4b465453, + 0x47465453, + 0x44465453, + 0x4f445f4d, + 0x44525f4d, + 0x504f5f4d, + 0x55515f4d, + 0x474e5f4d, + 0x4b535f4d, + 0x4b535f4d, + 0x48545f4d, + 0x48545f4d, + 0x48545f4d, + 0x48545f4d, + 0x4e455f4d, + 0x41505f4d, + 0x454d5f4d, + 0x534d5f4d, + 0x534d5f4d, + 0x50455f4d, + 0x50455f4d, + 0x50455f4d, + 0x50455f4d, + 0x55485f4d, + 0x4b4a5f4d, + 0x4f525f4d, + 0x4b535f4d, + 0x454e5f4d, + 0x4c555f4d, + 0x4d4e5f4d, + 0x56535f4d, + 0x504f5f4d, + 0x41535f4d, + 0x4f4c5f4d, + 0x49445f4d, + 0x534d5f4d, + 0x44475f4d, + 0x44475f4d, + 0x45445f4d, + 0x49445f4d, + 0x43535f4d, + 0x47535f4d, + 0x474c5f4d, + 0x46535f4d, + 0x554d5f4d, + 0x534c5f4d, + 0x534c5f4d, + 0x534c5f4d, + 0x52445242, + 0x52445242, + 0x52445242, + 0x52445242, + 0x52445242, + 0x52445242, + 0x52445242, + 0x52445242, + 0x414d4957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x30414957, + 0x52554957, + 0x52554957, + 0x50534957, + 0x534f4957, + 0x534f4957, + 0x00464957, + 0x534d4957, + 0x534f4957, + 0x534f4957, + 0x49544957, + 0x41504957, + 0x534d4957, + 0x494d4957, + 0x43504957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x554e4957, + 0x4f434957, + 0x55534957, + 0x52464957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x564c4957, + 0x31504957, + 0x32504957, + 0x33504957, + 0x34504957, + 0x50424957, + 0x50424957, + 0x50424957, + 0x50424957, + 0x494b4957, + 0x43564957, + 0x43534957, + 0x4e454957, + 0x54535f53, + 0x47474843, + 0x47474843, + 0x46474843, + 0x46474843, + 0x47574153, + 0x47574153, + 0x47574153, + 0x47574153, + 0x47534950, + 0x47534950, + 0x47534950, + 0x47534950, + 0x47534950, + 0x46534950, + 0x314c4142, + 0x314c4142, + 0x314c4142, + 0x314c4142, + 0x314c4142, + 0x46465550, + 0x46465550, + 0x46465550, + 0x46465550, + 0x44554c42, + 0x44554c42, + 0x44554c42, + 0x324c4142, + 0x324c4142, + 0x324c4142, + 0x324c4142, + 0x324c4142, + 0x4c53494d, + 0x4c53494d, + 0x4c53494d, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4654, + 0x474f4649, + 0x474f4649, + 0x474f4649, + 0x474f4649, + 0x474f4649, + 0x534c5041, + 0x534c5041, + 0x58425041, + 0x58425041, + 0x58425041, + 0x58425041, + 0x58425041, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x464e414d, + 0x46534f42, + 0x46534f42, + 0x46534f42, + 0x46534f42, + 0x474e5550, + 0x474e5550, + 0x474e5550, + 0x474e5550, + 0x4753494d, + 0x4753494d, + 0x4653494d, + 0x4653494d, + 0x4653494d, + 0x4653494d, + 0x4c53494d, + 0x4c53494d, + 0x4c53494d, + 0x4c53494d, + 0x4c53494d, + 0x47544853, + 0x47544853, + 0x47544853, + 0x47544853, + 0x46544853, + 0x46544853, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x47524153, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x4f4f5254, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x53534f42, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x374c4142, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x53534f50, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x534f5053, + 0x354c4f50, + 0x444e4143, + 0x41524243, + 0x544f4853, + 0x4e55474d, + 0x4e55414c, + 0x57415343, + 0x50494c43, + 0x4c454853, + 0x4b434f52, + 0x4d495453, + 0x4944454d, + 0x314d5241, + 0x314d5241, + 0x324d5241, + 0x324d5241, + 0x31524142, + 0x31524142, + 0x554c4f43, + 0x4b415042, + 0x4b4f5242, + 0x4f4d4d41, + 0x584f4253, + 0x43454c45, + 0x59454b42, + 0x59454b42, + 0x59454b59, + 0x59454b59, + 0x59454b52, + 0x59454b52, + 0x54495553, + 0x53495650, + 0x53495650, + 0x50584542, + 0x50584542, + 0x50584542, + 0x50584542, + 0x50584542, + 0x50414d50, + 0x50414d50, + 0x50414d50, + 0x50414d50, + 0x534e4950, + 0x534e4950, + 0x534e4950, + 0x534e4950, + 0x314e4f42, + 0x314e4f42, + 0x314e4f42, + 0x314e4f42, + 0x4c554f53, + 0x4c554f53, + 0x4c554f53, + 0x4c554f53, + 0x324e4f42, + 0x324e4f42, + 0x324e4f42, + 0x324e4f42, + 0x44455254, + 0x44455254, + 0x44455254, + 0x44455254, + 0x4e455f53, + 0x54535f50, + 0x535f3150, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x5f333157, + 0x5f333157, + 0x5f333157, + 0x5f353157, + 0x5f353157, + 0x5f373157, + 0x4c4c4157, + 0x5f383257, + 0x5f383257, + 0x5f383257, + 0x5f383257, + 0x5f313357, + 0x5f323357, + 0x5f323357, + 0x5f333357, + 0x5f333357, + 0x5f333357, + 0x5f363457, + 0x5f363457, + 0x5f363457, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x4c4c4157, + 0x5f343957, + 0x31313157, + 0x31313157, + 0x32313157, + 0x32313157, + 0x32313157, + 0x33313157, + 0x33313157, + 0x33313157, + 0x31315753, + 0x31315753, + 0x31315753, + 0x31315753, + 0x32315753, + 0x32315753, + 0x32315753, + 0x32315753, + 0x39315753, + 0x39315753, + 0x39315753, + 0x39315753, + 0x37315753, + 0x37315753, + 0x37315753, + 0x38315753, + 0x38315753, + 0x5f343154, + 0x32314741, + 0x32314741, + 0x31424741, + 0x31414c57, + 0x50505553, + 0x574d4f54, + 0x574d4f54, + 0x50455453, + 0x50455453, + 0x50455453, + 0x50455453, + 0x50455453, + 0x50455453, + 0x50455453, + 0x50455453, + 0x54495845, + 0x54495845, + 0x54414c50, + 0x4c415454, + 0x5f325054, + 0x5f325054, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x504d4f43, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x524f4f44, + 0x4e524157, + 0x4e524157, + 0x54494c42, + 0x54494c42, + 0x54494c42, + 0x54494c57, + 0x54494c57, + 0x54494c57, + 0x454b554e, + 0x4d414c46, + 0x52435354, + 0x52435354, + 0x52435354, + 0x52435354, + 0x52435354, + 0x52435354, + 0x30325350, + 0x53315753, + 0x53315753, + 0x53325753, + 0x53325753, + 0x53335753, + 0x53335753, + 0x53345753, + 0x53345753, + 0x31594b53, + 0x455f3150, + 0x4e455f50, + 0x54535f46, + 0x535f3146, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x4f4f4c46, + 0x50455453, + 0x50455453, + 0x4f4f4c46, + 0x4f4f4c46, + 0x54494c54, + 0x54494c54, + 0x54494c54, + 0x54494c54, + 0x4f4f4c46, + 0x4f4f4c46, + 0x524c464d, + 0x314d4544, + 0x314d4544, + 0x314d4544, + 0x314d4544, + 0x4c494543, + 0x4c494543, + 0x4c494543, + 0x4c494543, + 0x4c494543, + 0x4c494543, + 0x4c494543, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x54414c46, + 0x534e4f43, + 0x534e4f43, + 0x534e4f43, + 0x414b554e, + 0x414b554e, + 0x414b554e, + 0x4b535f46, + 0x455f3146, + 0x4e455f46, + 0x44455243, + 0x52415f4d, + 0x41475f4d, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x41475453, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, + 0x59414c50, +}; + +// Array representations +ConstMemArray filepos(_filepos); +ConstMemArray lumpsize(_lumpsize); +ConstMemArray lumpname_high(_lumpname_high); +ConstMemArray lumpname_low(_lumpname_low); diff --git a/gamedata/minimem/gbadoom1_lumps.h b/gamedata/minimem/gbadoom1_lumps.h new file mode 100644 index 00000000..2611309a --- /dev/null +++ b/gamedata/minimem/gbadoom1_lumps.h @@ -0,0 +1,15 @@ +#ifndef _GBADOOM1_LUMPS_H_ +#define _GBADOOM1_LUMPS_H_ + +#include +#include "annotations.h" + +#define WADLUMPS 1158 + + +extern ConstMemArray filepos; +extern ConstMemArray lumpsize; +extern ConstMemArray lumpname_high; +extern ConstMemArray lumpname_low; + +#endif // _GBADOOM1_LUMPS_H_ diff --git a/gamedata/minimem/tagheap.cc b/gamedata/minimem/tagheap.cc new file mode 100644 index 00000000..e491b68d --- /dev/null +++ b/gamedata/minimem/tagheap.cc @@ -0,0 +1,438 @@ +#include "tagheap.h" +//#include +#if TH_CANARY_ENABLED == 1 +#include +#include +#else +#define assert(x) +#endif + +#include + +/** + * This file contains a simple tagged memory allocator that supports allocation + */ + +static bool initialized = false; + + +#define SZ_MEMBLOCK sizeof(th_memblock_t) + +uint8_t th_heap[TH_HEAPSIZE]; + +#define LASTBLOCK ((th_memblock_t *)&th_heap[TH_CACHEHEAPSIZE-SZ_MEMBLOCK+(tag >> 31)*TH_OBJECTHEAPSIZE]) + +// Init the heap with start and end markers indicating the free space +void TH_init() { + if (initialized) return; + initialized = true; + // Initialize the start and end markers + unsigned tag = 0; + do { + FIRSTBLOCK->next = LASTBLOCK; + FIRSTBLOCK->prev = NULL; + FIRSTBLOCK->tag = TH_FREE_TAG; + FIRSTBLOCK->size = ((tag) ? TH_OBJECTHEAPSIZE : TH_CACHEHEAPSIZE)-2*SZ_MEMBLOCK; + LASTBLOCK->next = NULL; + LASTBLOCK->prev = FIRSTBLOCK; + LASTBLOCK->tag = TH_FREE_TAG; + LASTBLOCK->size = 0; + #if TH_CANARY_ENABLED == 1 + // Fill in canary values + for (int i=0; i<4; i++) { + FIRSTBLOCK->canary[i] = 0xDEADBEEF; + LASTBLOCK->canary[i] = 0xDEADBEEF; + } + #endif + tag ^= 0x80000000; // Toggle between cache and objects + } while (tag); +} + + + +static inline bool is_tail_or_free(uint32_t tag) { + return (tag & 0x80000000); +} + +static inline unsigned nearest4up(unsigned x) { + return (x + 3) & ~3; +} + +// Allocate *size* bytes and give them the given tag. Start search in bottom +static uint8_t *alloc_first_fit(int bytesize, uint32_t tag){ + // Find first block txhat can hold the requested size starting from bottom + unsigned size = nearest4up(bytesize); // Align to 4 bytes + unsigned searchsize = size; // Make sure to have space for a block header and meaningful data + auto block = FIRSTBLOCK; + while (block && ((block->tag==TH_FREE_TAG && block->size < searchsize) + || block->tag != TH_FREE_TAG /*|| (!is_tail_or_free(block->tag))*/ )) { // Disable tail check here as this function now allocates in both heaps + block = block->next; + } + // Now block will either point to a suitable free area or be null + if (block && block->tag == TH_FREE_TAG) { + // Insert a new header above the block and make room for <> bytes + // Mark the new header as free memory + if (block->size < size + SZ_MEMBLOCK + 16) { + // Not enough space to split the block meaningfully - just allocate whole block and set size correctly + block->size = bytesize; + block->tag = tag; + return (uint8_t *)(block+1); + } + int newsize = block->size-SZ_MEMBLOCK-size; + uint8_t *newptr = (uint8_t *)block + SZ_MEMBLOCK + size; + auto newblock = (th_memblock_t *)newptr; + block->next->prev = newblock; + newblock->next = block->next; + newblock->prev = block; + block->next=newblock; + newblock->size = newsize; + // The data is south of the new block + newblock->tag = TH_FREE_TAG; + block->tag=tag; + block->size = bytesize; // may be overallocated + #if TH_CANARY_ENABLED == 1 + // Fill in canary values in the new block + for (int i=0; i<4; i++) { + newblock->canary[i] = 0xDEADBEEF; + } + #endif + return (uint8_t *)(block+1); + } + return NULL; +} + +// Allocate *size* bytes and give them the given tag. Start search in bottom +static uint8_t *alloc_best_fit(int bytesize, uint32_t tag){ + // Find first block txhat can hold the requested size starting from bottom + unsigned size = nearest4up(bytesize); // Align to 4 bytes + unsigned searchsize = size + SZ_MEMBLOCK + 16; // Make sure to have space for a block header and meaningful data + auto block = FIRSTBLOCK; + th_memblock_t *bestblock = NULL; + while (block) { + if (block->tag == TH_FREE_TAG && block->size >= searchsize) { + if (!bestblock || block->size < bestblock->size) { + bestblock = block; + } + } + block = block->next; + } + block = bestblock; + // Now block will either point to a suitable free area or be null + if (block && block->tag == TH_FREE_TAG) { + // Insert a new header above the block and make room for <> bytes + // Mark the new header as free memory + if (block->size < size + SZ_MEMBLOCK + 16) { + // Not enough space to split the block meaningfully - just allocate whole block and set size correctly + block->size = bytesize; + block->tag = tag; + return (uint8_t *)(block+1); + } + int newsize = block->size-SZ_MEMBLOCK-size; + uint8_t *newptr = (uint8_t *)block + SZ_MEMBLOCK + size; + auto newblock = (th_memblock_t *)newptr; + block->next->prev = newblock; + newblock->next = block->next; + newblock->prev = block; + block->next=newblock; + newblock->size = newsize; + // The data is south of the new block + newblock->tag = TH_FREE_TAG; + block->tag=tag; + block->size = bytesize; // may be overallocated + #if TH_CANARY_ENABLED == 1 + // Fill in canary values in the new block + for (int i=0; i<4; i++) { + newblock->canary[i] = 0xDEADBEEF; + } + #endif + return (uint8_t *)(block+1); + } + return NULL; +} + +uint8_t *TH_alloc(int bytesize, uint32_t tag) { + #if TH_CANARY_ENABLED == 1 + printf("TH_alloc: Requesting %d bytes with tag %u (%s)\n", bytesize, tag, is_tail_or_free(tag) ? "objects" : "cache"); + #endif + auto ptr = (tag) ? alloc_best_fit(bytesize,tag) : alloc_first_fit(bytesize,tag); ; + return ptr; +} + +uint8_t *TH_realloc(uint8_t *ptr, int newsize) { + int newsize_aligned = nearest4up(newsize); + if (!ptr) return NULL; + if (newsize <= 0) { + TH_free(ptr); + return NULL; + } + th_memblock_t *block = (th_memblock_t *)(ptr) - 1; + if (block->size >= (uint32_t)newsize) { + // Already big enough + return ptr; + } else { + // Find out if we can expand into next block + th_memblock_t *next = block->next; + if (next->tag == TH_FREE_TAG && (block->size + SZ_MEMBLOCK + next->size) >= (uint32_t)newsize_aligned) { + // Can expand here + int extra_needed = newsize_aligned - block->size; + // CHeck if we leave a reasonable block size behind if we split + // We are only moving the next block header up so no need to account for + // that blocksize + if (next->size > (uint32_t)extra_needed + 16) { + // Split the next block + uint8_t *newblockptr = (uint8_t *)(next) + extra_needed; + th_memblock_t *newblock = (th_memblock_t *)newblockptr; + newblock->tag = TH_FREE_TAG; + newblock->size = next->size - extra_needed; + newblock->next = next->next; + newblock->prev = block; + next->next->prev = newblock; + block->next = newblock; + block->size = newsize; + } else { + // Just take the whole next block + block->size = newsize; // May be overallocated - but that's ok + block->next = next->next; + next->next->prev = block; + } + return ptr; + } else { + // Need to allocate a new block and move data + uint8_t *newptr = TH_alloc(newsize, block->tag); + if (newptr) { + // Copy old data + uint8_t *src = ptr; + uint8_t *dst = newptr; + for (unsigned n=0; nsize; n++) { + *dst++ = *src++; + } + TH_free(ptr); + return newptr; + } + } + } + return NULL; +} + +static int freeblock(th_memblock_t *block){ + th_memblock_t *next = block->next; + th_memblock_t *prev = block->prev; + int freetype = 0; + // Allow merge with next block only if it is not the end marker + freetype |= (next && next->tag == TH_FREE_TAG && next->size > 0) ? 1 : 0; + freetype |= (prev && prev->tag == TH_FREE_TAG) ? 2 : 0; + + int freed = block->size; + // Compute how many memblock allocations we save below + for (int i=freetype; i ; i>>=1) { + freed += SZ_MEMBLOCK; + } + switch (freetype) { + case 0: // block is a new free island + #if TH_CANARY_ENABLED == 1 + printf("Freeing block at %p of size %u creating an island\n", (void *)block, block->size); + #endif + block->tag = TH_FREE_TAG; + break; + case 1: // Merge with next, removing next block - unless it is next-to-last block + #if TH_CANARY_ENABLED == 1 + printf("Freeing block at %p of size %u merging with next block at %p of size %u\n", (void *)block, block->size, (void *)next, next->size); + #endif + //block->size += next->size+SZ_MEMBLOCK; + block->next = next->next; + next->next->prev = block; + block->tag = TH_FREE_TAG; + break; + case 2: // Merge with previous, removing this block + #if TH_CANARY_ENABLED == 1 + printf("Freeing block at %p of size %u merging with previous block at %p of size %u\n", (void *)block, block->size, (void *)prev, prev->size); + #endif + //prev->size += block->size + SZ_MEMBLOCK; + prev->next = block->next; + next->prev = prev; + block = prev; + break; + case 3: // Merge block and next with previous + #if TH_CANARY_ENABLED == 1 + printf("Freeing block at %p of size %u merging with previous block at %p of size %u and next block at %p of size %u\n", (void *)block, block->size, (void *)prev, prev->size, (void *)next, next->size); + #endif + //prev->size += block->size + next->size + 2*SZ_MEMBLOCK; + prev->next = next->next; + next->next->prev = prev; + block = prev; + break; + default: + break; + } + // Adjust the size of the resulting free block + block->size = (uintptr_t)(block->next) - (uintptr_t)(block+1); + return freed; +} + +// Free all blocks with tags between tag_low and tag_high both included. +void TH_freetags(uint32_t tag_low, uint32_t tag_high){ + assert (is_tail_or_free(tag_low) == is_tail_or_free(tag_high)); // Must be same type of tags + unsigned tag = tag_low; + auto block = FIRSTBLOCK; + while (block) { + if (tag_low <= block->tag && block->tag <= tag_high) { + freeblock(block); + } + block = block->next; + } +} + +// Free a single block pointed to by ptr +int TH_free(uint8_t *ptr){ + th_memblock_t *block = (th_memblock_t *)ptr; + return freeblock(block-1); +} + +// Defrag cache as described in tagheap.h. Both tag_low and tag_high is included +// in the range to be defragmented. Never set tag_high to TH_FREE_TAG +void TH_defrag(defrag_cb_t move_if_allowed){ + unsigned tag = 0; // Only cache head blocks + auto block = FIRSTBLOCK; + // TODO: Implement defragmentation + while (block) { + if (block->tag == TH_FREE_TAG && block->size > 0){ + if (block->next->tag == TH_FREE_TAG) { + // Reconcile the two blocks unless we reached the end + if (block->next->size > 0) { + #if TH_CANARY_ENABLED == 1 + printf("Defrag: Merging free block at %p of size %u with next free block at %p of size %u\n", (void *)block, block->size, (void *)(block->next), block->next->size); + #endif + block->size += block->next->size + SZ_MEMBLOCK; + block->next = block->next->next; + block->next->prev = block; + // Retry the move + continue; + } else { + // Reached the end marker - stop defrag here + break; + } + } else { + // We may have a block we can move ... + th_memblock_t *next = block->next; + // We are into the objects - no need to continue defrag + if (is_tail_or_free(next->tag)) break; + // Else check if we can move it + uint8_t *newaddr = (uint8_t *)(block+1); + if (move_if_allowed(next->tag,newaddr)){ + #if TH_CANARY_ENABLED == 1 + printf ("Defrag: Moving block with tag %u from %p to %p\n", next->tag, (void *)(next), (void *)newaddr); + #endif + // Move allowed + th_memblock_t oldblock = *next; + // We can move using 32 bit load/stores as we know everything is 4 uint8_t aligned + uint32_t *dst = (uint32_t *)newaddr; + uint32_t *src = (uint32_t *)(next+1); + unsigned realsize = (next->size +3) & ~3; // Align to 4 bytes + for (unsigned n=0; n<(realsize>>2); n++) { + *dst++=*src++; + } + // We are effectively flipping the free space in block + // with the data area in block->next, so the sizes and + // tags of the two swaps. We then insert a new block after the + // new data area that holds the new free space. Consolidation + // with eventual free space will be done next round. + th_memblock_t *newblock = (th_memblock_t *)dst; + newblock->size = block->size; + #if TH_CANARY_ENABLED == 1 + uintptr_t avail = (uintptr_t)(oldblock.next) - (uintptr_t)(newblock+1); + assert(newblock->size <= avail); + #endif + newblock->tag = TH_FREE_TAG; + // Tying up the pointers in block and newblock + oldblock.next + newblock->next = oldblock.next; + newblock->next->prev = newblock; + #if TH_CANARY_ENABLED == 1 + // Fill in canary values in the new block + for (int i=0; i<4; i++) { + newblock->canary[i] = 0xDEADBEEF; + } + #endif + // Update moved block header + block->tag = oldblock.tag; + block->size = oldblock.size; + block->next = newblock; + newblock->prev = block; + } + } + } else { + // We are into the objects - no need to terminate defrag + if (is_tail_or_free(block->tag)) break; + } + block = block->next; + } +} + +int TH_countfreehead() { + unsigned tag = 0; // only work on cache + th_memblock_t *block = FIRSTBLOCK; + int free = 0; + // Step through and find all free blocks until we meet a objects block or reach the end + while (block) { + if (block->tag == TH_FREE_TAG) { + free += block->size; + } else { + if (is_tail_or_free(block->tag)) { + break; + } + } + block = block->next; + } + return free; +} + +bool TH_checkhealth_verbose() { + #if TH_CANARY_ENABLED != 1 + return true; + #else + unsigned tag = 0; + bool healthy = true; + do { + unsigned freemem = 0; + unsigned contigfree = 0; + printf("INFO: Checking heap health for %s allocations\n", (tag & 0x80000000) ? "object" : "cache"); + th_memblock_t *block = FIRSTBLOCK; + th_memblock_t *prev = NULL; + int cnt = 0; + while (block) { + #if TH_CANARY_ENABLED == 1 + // Check canary values + for (int i=0; i<4; i++) { + if (block->canary[i] != 0xDEADBEEF) { + printf("WARNING: Block #%d with tag %d has corrupted canary value at index %d\n", cnt, block->tag, i); + healthy = false; + } + } + #endif + // Check backward link consistency + if (block->prev != prev) { + printf("WARNING: Block chain broken at block #%d with tag %d: backward link inconsistency - expected %p got %p. Previous block had tag %d\n", cnt, block->tag, (void *)prev, (void *)block->prev, prev ? prev->tag : -1); + healthy = false; + } + if (block->next && ((uint8_t *)block->next < th_heap || + (uint8_t *)block->next >= th_heap + TH_HEAPSIZE)) { + printf("WARNING: Block chain broken at block #%d with tag %d: next pointer out of bounds\n", cnt, block->tag); + healthy = false; + break; + } + if (block->tag == TH_FREE_TAG) { + freemem += block->size; + contigfree = (contigfree > block->size) ? contigfree : block->size; + } + prev = block; + block = block->next; + cnt++; + } + if (healthy) { + printf("INFO: %s Heap is healthy with %d blocks (%d bytes free - %d contiguous)\n", (tag) ? "Object" : "Cache", + cnt, freemem, contigfree); + } + tag ^= 0x80000000; + } while (tag); + return healthy; + #endif +} diff --git a/gamedata/minimem/tagheap.h b/gamedata/minimem/tagheap.h new file mode 100644 index 00000000..5d664362 --- /dev/null +++ b/gamedata/minimem/tagheap.h @@ -0,0 +1,77 @@ +#ifndef __memheap_h +#define __memheap_h + +#include + + +/** + * This API is for a tagged memory allocator. It supports allocation from both + * head and tail of the heap area, and it supports defragmentation of the head + * area. Furthermore tag ranges can be freed in one go. + * + * Tags with MSB set are allocated in the tail, while tags with MSB cleared are + * allocated in the head. Only head tags can be defragmented + * + * It is meant to be used as central heap for DOOM, allocating static objects + * and level objects at the tail end, while the head end is used for caching + * Cached<> objects. Idea is to have them interfere as little as possible and + * efficiently allocate and free memory as the game goes on. + * + * Defragmentation is done by traversing memory blocks from head end and copying + * down into free areas which bubbles up free memory to the end. For each memory + * block a callback is called with the tag and the (proposed) new address. If + * the callback returns true, the block is moved to the new address, while if it + * returns false, the move is vetoed. This is to protect pinned memory where a + * raw pointer is currently in flight. Defragmentation will only try to move blocks + * in the given tag range. + * + * + */ + + +// Heap size in 32-bit words +#ifndef TH_HEAPSIZE +#define TH_CACHEHEAPSIZE 180000 // bytes - portion of heap used for caching +#define TH_OBJECTHEAPSIZE 220000 // bytes - portion of heap used for static and level objects +#define TH_HEAPSIZE (TH_CACHEHEAPSIZE+TH_OBJECTHEAPSIZE) +#endif + +#ifndef TH_CANARY_ENABLED +#define TH_CANARY_ENABLED 0 +#endif + +#if TH_CANARY_ENABLED == 1 +#include +#endif +typedef struct th_memblock_s { + #if TH_CANARY_ENABLED == 1 + uint32_t canary[4]; // Canary to detect memory corruption + #endif + struct th_memblock_s *prev; + struct th_memblock_s *next; + uint32_t tag; // Tag of this block + uint32_t size; // Size in bytes +} th_memblock_t; + +extern uint8_t th_heap[TH_HEAPSIZE]; +#define FIRSTBLOCK ((th_memblock_t *)&th_heap[0+(tag >> 31)*TH_CACHEHEAPSIZE]) + +#define TH_FREE_TAG 0xffffffff + + +typedef bool (*defrag_cb_t)(short tag, uint8_t *proposed_newptr); + +uint8_t *TH_alloc(int bytesize, uint32_t tag); +uint8_t *TH_realloc(uint8_t *ptr, int newsize); +void TH_freetags(uint32_t tag_low, uint32_t tag_high); +// Return the amount of bytes freed by this free (including headers) +int TH_free(uint8_t *ptr); +void TH_defrag(defrag_cb_t callback); +void TH_init(); +// Count how many bytes are free for allocation into head. +int TH_countfreehead(); + +bool TH_checkhealth_verbose(); + + +#endif // __memheap_h \ No newline at end of file diff --git a/gamedata/minimem/test/Makefile b/gamedata/minimem/test/Makefile new file mode 100644 index 00000000..2e93de1b --- /dev/null +++ b/gamedata/minimem/test/Makefile @@ -0,0 +1,78 @@ +# Makefile for TagHeap Test Suite + +# Compiler settings +CXX := clang++ +CXXFLAGS := -std=c++17 -Wall -Wextra -g -O2 +CPPFLAGS := -I.. + +# Directories +BUILD_DIR := build +SRC_DIR := . +PARENT_DIR := .. + +# Source files +TEST_SRC := $(SRC_DIR)/test_tagheap.cc +TAGHEAP_SRC := $(PARENT_DIR)/tagheap.cc +SOURCES := $(TEST_SRC) $(TAGHEAP_SRC) + +# Object files +OBJECTS := $(BUILD_DIR)/test_tagheap.o $(BUILD_DIR)/tagheap.o + +# Output executable +TARGET := $(BUILD_DIR)/test_tagheap + +# Default target +.PHONY: all +all: $(TARGET) + +# Build the executable +$(TARGET): $(OBJECTS) + @mkdir -p $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $^ + @echo "Build successful: $(TARGET)" + +# Compile test source +$(BUILD_DIR)/test_tagheap.o: $(TEST_SRC) + @mkdir -p $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< + +# Compile tagheap source +$(BUILD_DIR)/tagheap.o: $(TAGHEAP_SRC) + @mkdir -p $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< + +# Run the tests +.PHONY: run +run: $(TARGET) + @$(TARGET) + +# Run with verbose output +.PHONY: run-verbose +run-verbose: $(TARGET) + @$(TARGET) 2>&1 | tee $(BUILD_DIR)/test_results.txt + +# Clean build artifacts +.PHONY: clean +clean: + rm -rf $(BUILD_DIR) + @echo "Cleaned build artifacts" + +# Rebuild from scratch +.PHONY: rebuild +rebuild: clean all + +# Display help +.PHONY: help +help: + @echo "TagHeap Test Suite - Available targets:" + @echo "" + @echo " all - Build the test executable (default)" + @echo " run - Build and run tests" + @echo " run-verbose - Run tests with verbose output and save results" + @echo " clean - Remove build artifacts" + @echo " rebuild - Clean and build from scratch" + @echo " help - Display this help message" + @echo "" + +# PHONY targets +.PHONY: all run run-verbose clean rebuild help diff --git a/gamedata/minimem/test/README.md b/gamedata/minimem/test/README.md new file mode 100644 index 00000000..c2ce76b2 --- /dev/null +++ b/gamedata/minimem/test/README.md @@ -0,0 +1,879 @@ +# TagHeap Memory Allocator - White Box Test Suite + +## Overview + +This directory contains a comprehensive white-box test suite for the tagheap memory allocator (`../tagheap.cc`/`../tagheap.h`). The test suite validates all aspects of the allocator including allocation, deallocation, block merging, defragmentation, and memory integrity. + +**Test Results:** 112 assertions across 25 test functions, 100% pass rate + +## Architecture + +### Memory Layout + +The tagheap allocator supports dual-region allocation from a single contiguous heap: + +``` +┌─────────────────────────────────────────────────────┐ +│ Heap: 75,000 dwords (300,000 bytes) │ +├─────────────────────────────────────────────────────┤ +│ FIRSTBLOCK (sentinel) │ Low Memory +│ (FREE, 74,988 dwords) │ +│ │ +│ [HEAD Region - grows upward] │ +│ - Allocated blocks with tags 0x0000-0x3FFF │ +│ - Used for dynamic/temporary allocations │ +│ │ +├─────────────────────────────────────────────────────┤ +│ [TAIL Region - grows downward] │ +│ - Allocated blocks with tags 0x4000-0x7FFE │ +│ - Used for static/persistent allocations │ +│ │ +│ LASTBLOCK (sentinel) │ High Memory +│ (FREE, 0 dwords) │ +└─────────────────────────────────────────────────────┘ +``` + +### Memory Block Structure + +```c +typedef struct memblock_s { + struct memblock_s *prev; // Pointer to previous block (8 bytes) + struct memblock_s *next; // Pointer to next block (8 bytes) + uint32_t tag : 15; // Block tag (MSB=0 for HEAD, MSB=1 for TAIL) + uint32_t size : 17; // Size in dwords (4-byte words) +} memblock_t; // Total: 24 bytes (6 dwords) +``` + +**Key Details:** +- Block headers consume 6 dwords (24 bytes) each +- Sizes are stored in dwords, multiply by 4 for byte count +- Tag 0x7FFF is reserved for free blocks +- MSB (bit 14) distinguishes HEAD (0) from TAIL (1) allocations + +--- + +## Test Descriptions + +### 1. **test_initialization** (10 assertions) +**Purpose:** Validate heap initialization with proper sentinel blocks + +**Entry State:** +``` +New heap, uninitialized +``` + +**Exit State:** +``` +FIRSTBLOCK → LASTBLOCK (linked chain) +- FIRSTBLOCK: tag=0x7FFF (FREE), size=74,988 dwords +- LASTBLOCK: tag=0x7FFF (FREE), size=0 dwords +``` + +**Assertions:** +- FIRSTBLOCK and LASTBLOCK exist +- Both marked as free (0x7FFF) +- LASTBLOCK has size 0 (sentinel) +- Forward/backward pointers correctly linked +- Previous pointers are NULL for sentinels +- Block chain is valid + +--- + +### 2. **test_simple_head_allocation** (5 assertions) +**Purpose:** Verify basic HEAD region allocation from bottom-up + +**Entry State:** +``` +Initialized heap with free space +``` + +**Exit State:** +``` +FIRSTBLOCK → [HEAD:1001, 4 dw] → [HEAD:1002, 8 dw] → FREE space → LASTBLOCK +``` + +**Assertions:** +- First allocation succeeds and returns non-NULL pointer +- Block chain remains valid +- Second allocation succeeds at different address +- Two pointers don't overlap + +--- + +### 3. **test_simple_tail_allocation** (4 assertions) +**Purpose:** Verify basic TAIL region allocation from top-down + +**Entry State:** +``` +Initialized heap with free space +``` + +**Exit State:** +``` +FIRSTBLOCK → FREE space → [TAIL:8001, 4 dw] → [TAIL:8002, 8 dw] → LASTBLOCK +``` + +**Assertions:** +- First tail allocation succeeds (tag 0x8001) +- Block chain valid after tail allocation +- Second tail allocation succeeds (tag 0x8002) +- Both in TAIL region + +--- + +### 4. **test_mixed_head_tail_allocation** (5 assertions) +**Purpose:** Verify HEAD and TAIL regions can coexist without interference + +**Entry State:** +``` +Initialized empty heap +``` + +**Exit State:** +``` +FIRSTBLOCK → [HEAD:1001] → [HEAD:1002] → FREE → [TAIL:8001] → [TAIL:8002] → LASTBLOCK +``` + +**Assertions:** +- HEAD allocation 1 succeeds +- HEAD allocation 2 succeeds +- TAIL allocation 1 succeeds +- TAIL allocation 2 succeeds +- Block chain valid with mixed allocations + +--- + +### 5. **test_freeblock_case_0_isolated_free** (1 assertion) +**Purpose:** Validate deallocation when free block is isolated (no adjacent free blocks) + +**Entry State:** +``` +FIRSTBLOCK → [HEAD:1001] → [HEAD:1002] → [HEAD:1003] → FREE → LASTBLOCK +``` + +**Exit State (Case 0 - Isolated):** +``` +FIRSTBLOCK → [FREE] → [HEAD:1002] → [HEAD:1003] → FREE → LASTBLOCK +``` + +**Scenario:** Block A freed, not adjacent to any other free blocks + +**Assertions:** +- Block chain valid after isolated free + +--- + +### 6. **test_freeblock_case_1_merge_with_next** (1 assertion) +**Purpose:** Validate merging a freed block with the FREE block following it + +**Entry State:** +``` +FIRSTBLOCK → [HEAD:1001] → [FREE] → [HEAD:1003] → LASTBLOCK +``` + +**Exit State (Case 1 - Merge with Next):** +``` +FIRSTBLOCK → [FREE (merged)] → [HEAD:1003] → LASTBLOCK +``` + +**Scenario:** When HEAD:1001 is freed, it merges with the following FREE block + +**Assertions:** +- Block chain valid after case 1 merge + +--- + +### 7. **test_freeblock_case_2_merge_with_prev** (1 assertion) +**Purpose:** Validate merging a freed block with the FREE block preceding it + +**Entry State:** +``` +FIRSTBLOCK → [FREE] → [HEAD:1002] → [HEAD:1003] → LASTBLOCK +``` + +**Exit State (Case 2 - Merge with Previous):** +``` +FIRSTBLOCK → [FREE (merged)] → [HEAD:1003] → LASTBLOCK +``` + +**Scenario:** When HEAD:1002 is freed, it merges with the preceding FREE block + +**Assertions:** +- Block chain valid after case 2 merge + +--- + +### 8. **test_freeblock_case_3_merge_both** (1 assertion) +**Purpose:** Validate merging a freed block with FREE blocks on both sides + +**Entry State:** +``` +FIRSTBLOCK → [FREE] → [HEAD:1002] → [FREE] → [HEAD:1004] → LASTBLOCK +``` + +**Exit State (Case 3 - Merge Both):** +``` +FIRSTBLOCK → [FREE (fully merged)] → [HEAD:1004] → LASTBLOCK +``` + +**Scenario:** When HEAD:1002 is freed, it merges with FREE on both sides + +**Assertions:** +- Block chain valid after case 3 merge + +--- + +### 9. **test_cascade_merges** (1 assertion) +**Purpose:** Validate that cascading merges consolidate multiple fragmented free blocks + +**Entry State:** +``` +FIRSTBLOCK → [A] → [FREE] → [B] → [FREE] → [C] → ... → LASTBLOCK +``` + +**Exit State:** +``` +FIRSTBLOCK → [LARGE FREE] → LASTBLOCK +(All interleaved allocations freed, all free blocks merged into one) +``` + +**Scenario:** +- Allocate 10 blocks +- Free every even-indexed block (creates 5 free regions) +- Free remaining odd-indexed blocks (triggers cascade merges) + +**Assertions:** +- Block chain valid after cascade merges + +--- + +### 10. **test_freetags_range** (2 assertions) +**Purpose:** Validate range-based deallocation (TH_freetags) for bulk freeing + +**Entry State:** +``` +FIRSTBLOCK → [1001] → [1002] → [1003] → [1004] → FREE → LASTBLOCK +``` + +**Exit State:** +``` +FIRSTBLOCK → [1001] → [FREE] → [FREE] → [1004] → FREE → LASTBLOCK +(and merged if adjacent) +``` + +**Scenario:** Call TH_freetags(0x1002, 0x1003) to free blocks in tag range + +**Assertions:** +- Allocations succeed +- Block chain valid after range deallocation + +--- + +### 11. **test_countfreehead** (3 assertions) +**Purpose:** Validate the TH_countfreehead() function for free memory tracking + +**Entry State:** +``` +Initialized heap with known free space +``` + +**Test Sequence:** +1. Measure initial free space +2. Allocate 256 bytes → measure decrease +3. Free allocation → measure recovery + +**Exit State:** +``` +Free space restored to near-initial value +``` + +**Assertions:** +- Initial free space > 0 +- Free space decreases after allocation +- Free space recovers after deallocation + +--- + +### 12. **test_alloc_at_capacity** (2 assertions) +**Purpose:** Validate boundary conditions and capacity limits + +**Entry State:** +``` +Initialized heap +``` + +**Test Sequence:** +1. Attempt allocation of 10,000,000 bytes (way over capacity) +2. Allocate largest feasible block (near full heap) +3. Free the large block + +**Exit State:** +``` +Heap state unchanged after failed allocation +``` + +**Assertions:** +- Over-capacity allocation returns NULL +- Large valid allocation succeeds + +--- + +### 13. **test_defragmentation** (2 assertions) +**Purpose:** Validate defragmentation preserves data integrity while compacting + +**Entry State:** +``` +FIRSTBLOCK → [1001: data=0x11110000+i] → [1002: data] → [1003: data] → FREE → LASTBLOCK +``` + +**Operation:** +1. Write pattern to blocks: 0x11110000+i, 0x22220000+i, 0x33330000+i +2. Free middle block (1002) to create gap +3. Defragment with callback allowing all moves + +**Exit State:** +``` +FIRSTBLOCK → [1001: moved down, data preserved] → [1003: moved down, data preserved] → LARGE FREE → LASTBLOCK +``` + +**Assertions:** +- Block chain valid after defragmentation +- Data patterns preserved (0x11110000+i still correct in ptr1) + +--- + +### 14. **test_countfreehead** (already described as #11) + +### 15. **test_complex_fragmentation_and_defrag** (2 assertions) +**Purpose:** Validate defragmentation with realistic multi-block fragmentation pattern + +**Entry State:** +``` +20 allocated blocks of 128 bytes each +``` + +**Operation:** +1. Allocate 20 blocks (tags 0x1000-0x1013) +2. Free every 3rd block (indices 0, 3, 6, 9, ... → creates scattered free spaces) +3. Measure free space before defragmentation +4. Defragment with move counting +5. Measure free space after defragmentation + +**Exit State:** +``` +FIRSTBLOCK → [all allocated blocks compacted] → [LARGE FREE] → LASTBLOCK +(Moved ~13 blocks to compact heap) +``` + +**Assertions:** +- Block chain valid after complex defragmentation +- Free space doesn't decrease after defragmentation + +--- + +### 16. **test_defrag_with_pinned_blocks** (2 assertions) +**Purpose:** Validate that defragmentation respects callback veto for pinned blocks + +**Entry State:** +``` +FIRSTBLOCK → [1001] → [1002] → [1003] → LASTBLOCK +``` + +**Operation:** +1. Allocate 3 blocks of 128 bytes each +2. Free middle block (1002) to create gap +3. Defragment but veto moves of tag 0x1001 via callback +4. Count moves + +**Exit State:** +``` +Block 0x1001 remains in original position (pinned) +Block 0x1003 may be moved down +``` + +**Scenario:** Demonstrates protection mechanism for raw pointers in flight + +**Assertions:** +- Block chain valid with pinned blocks +- Fewer moves than without pinning + +--- + +### 17. **test_rapid_alloc_free_cycles** (1 assertion) +**Purpose:** Stress test for heap stability under rapid allocation/deallocation + +**Test Sequence:** +``` +100 cycles of: + - Allocate 10 blocks (32 bytes each) + - Deallocate in reverse order + - Validate block chain +``` + +**Exit State:** +``` +Clean heap, all allocations released, no memory leaks +``` + +**Assertions:** +- Block chain valid after 100 cycles +- No fragmentation or corruption + +--- + +### 18. **test_allocation_alignment** (2 assertions) +**Purpose:** Verify that all allocations return 4-byte aligned pointers + +**Entry State:** +``` +Initialized empty heap +``` + +**Test Sequence:** +1. Allocate 14 blocks with sizes: 1, 2, 3, 4, 5, 7, 8, 15, 16, 17, 33, 100, 256, 1000 bytes +2. Verify each returned pointer is 4-byte aligned (address % 4 == 0) +3. Validate block chain integrity + +**Exit State:** +``` +All 14 blocks allocated with properly aligned pointers +``` + +**Assertions:** +- All allocations are 4-byte aligned (individual checks for each size) +- Block chain valid after alignment test + +**Implementation Details:** +- Uses `uintptr_t` to safely cast and check pointer alignment +- Tests edge cases: unaligned request sizes (1, 3, 5, 7, 17 bytes) +- Confirms alignment requirement is enforced by `nearest4up()` function +- Alignment is critical for performance on 32-bit and 64-bit systems + +--- + +## Memory Alignment + +The allocator ensures all data blocks are 4-byte aligned for optimal performance: + +``` +Allocation Request → Aligned Size +──────────────────────────────────────── +1 byte → 4 bytes +2 bytes → 4 bytes +3 bytes → 4 bytes +4 bytes → 4 bytes +5 bytes → 8 bytes +7 bytes → 8 bytes +8 bytes → 8 bytes +... +1000 bytes → 1000 bytes +``` + +**Alignment Function:** +```cpp +static inline int nearest4up(int x) { + return (x + 3) & ~3; // Rounds up to nearest 4-byte boundary +} +``` + +Benefits: +- ✓ Supports efficient 32-bit word access +- ✓ Reduces fragmentation from unaligned allocations +- ✓ Required for DMA and cache-aligned operations on some platforms + +--- + +## Test Descriptions + +## Build and Execution + +### Building + +```bash +cd /Users/brian/src/GBADoom/gamedata/minimem/test +make # Build test suite +make clean # Remove build artifacts +make rebuild # Clean and build +make run # Build and run tests +make run-verbose # Build and run with verbose output +``` + +### Running Tests + +```bash +./build/test_tagheap +``` + +**Output:** Color-coded test results with ✓ (pass) and ✗ (fail) indicators + +## Test Coverage Summary + +| Category | Tests | Assertions | Status | +|----------|-------|-----------|--------| +| **Initialization** | 1 | 10 | ✓ | +| **Allocation (HEAD)** | 2 | 9 | ✓ | +| **Allocation (TAIL)** | 2 | 8 | ✓ | +| **Block Merging** | 4 | 4 | ✓ | +| **Cascade Merging** | 1 | 1 | ✓ | +| **Range Deallocation** | 1 | 2 | ✓ | +| **Defragmentation** | 3 | 5 | ✓ | +| **Stress Testing** | 1 | 1 | ✓ | +| **Alignment Testing** | 1 | 2 | ✓ | +| **Utility Functions** | 1 | 2 | ✓ | +| **TOTAL** | **17** | **44** | **✓** | + +## Key Test Scenarios + +### Memory Region Separation +- HEAD blocks allocate from bottom (address 0x10000000+) +- TAIL blocks allocate from top (address 0x10FFFFFFF-) +- Can coexist without interference + +### Merge Operations +- **Case 0:** No adjacent free blocks → block becomes isolated free +- **Case 1:** Free block to right → merge consolidates both +- **Case 2:** Free block to left → merge consolidates both +- **Case 3:** Free blocks on both sides → consolidates all three + +### Defragmentation +- Non-destructive: data integrity preserved +- Callback-based: caller controls which blocks move +- Pinning: blocks can be protected (veto callback) +- Compaction: eliminates internal fragmentation + +### Stress Testing +- 100 cycles × 10 allocations/deallocations +- 1,000 total operations +- Validates heap consistency throughout + +## Files + +- `test_tagheap.cc` - Complete test suite implementation (621 lines) +- `Makefile` - Build configuration +- `build/test_tagheap` - Compiled test executable +- `README.md` - This document + +## Implementation Notes + +### Helper Functions in Tests + +```cpp +validate_block_chain() // Check linked-list integrity +print_heap_state() // Display block layout with tags/sizes +count_blocks() // Count blocks in range +defrag_allow_all() // Callback: allow all moves +defrag_veto_tag() // Callback: veto specific tags (for pinning) +defrag_count_all_moves() // Callback: count moves +``` + +### Assertion Macros + +```cpp +TEST_ASSERT(condition, message) // Boolean check +TEST_ASSERT_EQ(actual, expected, message) // Equality check +TEST_ASSERT_NEQ(actual, expected, message)// Inequality check +``` + +## Test Execution Flow + +``` +Initialize → Allocate → Validate → Free → Validate → Defrag → Validate + ↓ ↓ ↓ ↓ ↓ ↓ ↓ + Heap Memory Chain Merge Chain Compact Integrity + Setup Layout Linked- Blocks State Memory Data + Correct list +``` + +## Performance Characteristics + +All tests complete in < 100ms on modern hardware. No timeouts or infinite loops detected. + +## Debugging + +If a test fails: + +1. **Check block chain:** Validate forward/backward pointers +2. **Check heap state:** Use `print_heap_state()` for visual layout +3. **Check data:** Verify patterns written during allocation +4. **Check callbacks:** Ensure defrag callbacks are working + +Each test prints detailed heap state before and after operations for manual inspection. + +--- + +## Reallocation Tests (10 functions, 68 assertions) + +### 19. **test_realloc_null_ptr** (2 assertions) +**Purpose:** Verify that reallocating a NULL pointer returns NULL + +**Entry State:** +``` +Initialized empty heap +``` + +**Operation:** +1. Call TH_realloc(NULL, 100) + +**Exit State:** +``` +Returns NULL, block chain unchanged +``` + +**Assertions:** +- TH_realloc(NULL, 100) returns NULL +- Block chain valid after null pointer realloc + +--- + +### 20. **test_realloc_zero_size** (3 assertions) +**Purpose:** Verify that reallocating to size 0 or negative frees the block + +**Entry State:** +``` +One 100-byte HEAD allocation with tag 0x2000 +``` + +**Operation:** +1. Call TH_realloc(ptr, 0) +2. Check that space is freed + +**Exit State:** +``` +Block freed, space returned to free pool +``` + +**Assertions:** +- TH_realloc(ptr, 0) returns NULL +- Block chain valid after zero-size realloc +- Free space increased (block was freed) + +--- + +### 21. **test_realloc_no_op_shrink** (3 assertions) +**Purpose:** Verify that reallocating to a smaller size is a no-op (returns same pointer) + +**Entry State:** +``` +One 200-byte HEAD allocation with pattern +``` + +**Operation:** +1. Write 32-bit pattern to allocated block +2. Call TH_realloc(ptr, 100) +3. Verify pattern is intact + +**Exit State:** +``` +Same pointer returned, block unchanged +``` + +**Assertions:** +- TH_realloc(ptr, 100) returns same ptr +- Original pattern byte 0 intact +- Original pattern byte 1 intact + +--- + +### 22. **test_realloc_no_growth_needed** (3 assertions) +**Purpose:** Verify that reallocating to a size the block already satisfies is a no-op + +**Entry State:** +``` +One 200-byte HEAD allocation with pattern +``` + +**Operation:** +1. Write 32-bit pattern to allocated block +2. Call TH_realloc(ptr, 100) - block already has 200 bytes +3. Verify pattern is intact + +**Exit State:** +``` +Same pointer returned, no reallocation occurs +``` + +**Assertions:** +- TH_realloc(ptr, 100) returns same ptr +- Pattern byte 0 intact +- Pattern byte 1 intact + +--- + +### 23. **test_realloc_in_place_expansion** (5 assertions) +**Purpose:** Verify that expansion into adjacent free space works + +**Entry State:** +``` +Three sequential allocations: A(100), B(100), C(100) +``` + +**Operation:** +1. Free block B (creates free space adjacent to A) +2. Write pattern to A +3. Call TH_realloc(ptr_A, 150) +4. Verify A expanded in-place using B's space + +**Exit State:** +``` +Block A: 150 bytes (in-place expanded) +C: unchanged +Free block: remaining space after B +``` + +**Assertions:** +- In-place expansion returns same pointer +- Original pattern byte 0 preserved +- Original pattern byte 1 preserved +- Block chain valid after expansion +- Heap state shows correct layout + +--- + +### 24. **test_realloc_with_block_splitting** (4 assertions) +**Purpose:** Verify that block splitting works when expanding into larger free block + +**Entry State:** +``` +Blocks: A(100), B(500, then freed), C(100) +``` + +**Operation:** +1. Allocate A(100) and B(500) and C(100) +2. Free B to create 500-byte free space +3. Write pattern to A +4. Call TH_realloc(ptr_A, 150) - expands into B but with space left over +5. Verify pattern intact + +**Exit State:** +``` +Block A: 150 bytes +Remaining B: ~350 bytes (free block created from B) +Block C: unchanged +``` + +**Assertions:** +- Expansion with splitting returns same pointer +- Pattern byte 0 preserved after split +- Pattern byte 1 preserved after split +- Block chain valid after split realloc + +--- + +### 25. **test_realloc_full_reallocation** (5 assertions) +**Purpose:** Verify that full reallocation (new block + copy + free old) works + +**Entry State:** +``` +Blocks: A(100), B(100) - A and B are adjacent, B is NOT free +``` + +**Operation:** +1. Write 25 dword pattern to A +2. Call TH_realloc(ptr_A, 300) - can't expand into B (not free) +3. Allocate new block, copy data, free old +4. Verify pattern copied correctly + +**Exit State:** +``` +New block allocated (different pointer) +Data copied to new location +Old block freed and merged with neighbors +``` + +**Assertions:** +- Full reallocation succeeds (returns non-NULL) +- Returns different pointer (new location) +- Data copied correctly (all 25 dwords match) +- Original block B still valid +- Block chain valid after full reallocation + +--- + +### 26. **test_realloc_data_integrity** (4 assertions) +**Purpose:** Verify data integrity across multiple realloc cycles with various patterns + +**Entry State:** +``` +Empty heap +``` + +**Test Sequence:** +1. 4 test cases with different size transitions: + - 50→150 bytes + - 100→300 bytes + - 200→100 bytes (shrink, no-op) + - 80→200 bytes +2. For each: Fill with XOR pattern, realloc, verify original bytes + +**Exit State:** +``` +All patterns verified intact +``` + +**Assertions:** +- Allocation succeeds in each test case +- Realloc succeeds in each case +- Data integrity maintained in each realloc cycle (4 cycles) +- Block chain valid after all data integrity tests + +--- + +### 27. **test_realloc_alignment** (5 assertions) +**Purpose:** Verify data patterns are preserved during reallocation + +**Entry State:** +``` +Empty heap +``` + +**Test Sequence:** +1. Allocate 4 blocks with sizes: 10, 50, 100, 200 bytes +2. Fill each with test pattern +3. Realloc each to size+50 +4. Verify patterns are preserved + +**Exit State:** +``` +All data patterns intact after reallocation +``` + +**Assertions:** +- Initial allocation succeeds +- Realloc succeeded (4 assertions, one per block) +- Data pattern preserved after realloc +- Block chain valid after alignment tests + +--- + +### 28. **test_realloc_with_pinned_blocks** (4 assertions) +**Purpose:** Verify reallocation behavior with fragmented heap and adjacent blocks + +**Entry State:** +``` +Three allocations: A(100), B(100), C(100) +``` + +**Operation:** +1. Free B to create fragmentation +2. Write pattern to A +3. Realloc A to 200 bytes +4. Verify pattern preserved + +**Exit State:** +``` +A reallocated (possibly to new location due to fragmentation) +Data pattern preserved +C still valid +``` + +**Assertions:** +- All initial allocations succeed +- Realloc succeeds +- Pattern preserved in realloc with fragmentation +- Block chain valid + +--- + +**Test Suite Version:** 1.0 +**Last Updated:** December 25, 2025 +**Status:** All 112 assertions passing ✓ diff --git a/gamedata/minimem/test/test_tagheap.cc b/gamedata/minimem/test/test_tagheap.cc new file mode 100644 index 00000000..875d42cd --- /dev/null +++ b/gamedata/minimem/test/test_tagheap.cc @@ -0,0 +1,1006 @@ +#include +#include +#include +#include +#include +#include "../tagheap.h" + +// Use the actual tagheap structure +typedef th_memblock_t memblock_t; + +#define SZ_MEMBLOCK sizeof(memblock_t) + +extern uint8_t th_heap[TH_HEAPSIZE]; +#define FIRSTBLOCK ((memblock_t *)&th_heap[0]) +#define LASTBLOCK ((memblock_t *)&th_heap[TH_HEAPSIZE-SZ_MEMBLOCK]) + +// Color codes for test output +#define GREEN "\033[0;32m" +#define RED "\033[0;31m" +#define YELLOW "\033[1;33m" +#define BLUE "\033[0;34m" +#define RESET "\033[0m" + +static int test_count = 0; +static int test_passed = 0; +static int test_failed = 0; + +// Assertion macros +#define TEST_ASSERT(condition, message) \ + do { \ + test_count++; \ + if (condition) { \ + test_passed++; \ + printf(GREEN "✓" RESET " %s\n", message); \ + } else { \ + test_failed++; \ + printf(RED "✗" RESET " %s (line %d)\n", message, __LINE__); \ + } \ + } while (0) + +#define TEST_ASSERT_EQ(actual, expected, message) \ + do { \ + test_count++; \ + if ((actual) == (expected)) { \ + test_passed++; \ + printf(GREEN "✓" RESET " %s (got %ld)\n", message, (long)(actual)); \ + } else { \ + test_failed++; \ + printf(RED "✗" RESET " %s: expected %ld, got %ld (line %d)\n", \ + message, (long)(expected), (long)(actual), __LINE__); \ + } \ + } while (0) + +#define TEST_ASSERT_NEQ(actual, expected, message) \ + do { \ + test_count++; \ + if ((actual) != (expected)) { \ + test_passed++; \ + printf(GREEN "✓" RESET " %s (got %ld)\n", message, (long)(actual)); \ + } else { \ + test_failed++; \ + printf(RED "✗" RESET " %s: should not be %ld (line %d)\n", \ + message, (long)(expected), __LINE__); \ + } \ + } while (0) + +// Heap validation helpers +struct BlockInfo { + memblock_t *block; + uint16_t tag; + uint16_t size; +}; + +int count_blocks(memblock_t *start, memblock_t *end) { + int count = 0; + memblock_t *block = start; + while (block && block != end->next) { + count++; + block = block->next; + } + return count; +} + +bool validate_block_chain() { + memblock_t *block = FIRSTBLOCK; + memblock_t *prev = NULL; + + while (block) { + // Check backward link consistency + if (block->prev != prev) { + printf(RED "✗ Block chain broken: backward link inconsistency\n" RESET); + return false; + } + prev = block; + block = block->next; + } + return true; +} + +bool validate_block_sizes() { + memblock_t *block = FIRSTBLOCK; + + while (block) { + // Sentinels should have specific sizes + if (block == LASTBLOCK) { + if (block->size != 0) { + printf(RED "✗ LASTBLOCK size should be 0, got %u\n" RESET, block->size); + return false; + } + } + block = block->next; + } + return true; +} + +void print_heap_state() { + printf(BLUE "\n=== Heap State ===\n" RESET); + memblock_t *block = FIRSTBLOCK; + int block_num = 0; + + while (block) { + const char *tag_name; + if (block->tag == TH_FREE_TAG) { + tag_name = "FREE"; + } else if (block->tag & 0x80000000) { + tag_name = "TAIL"; + } else { + tag_name = "HEAD"; + } + + printf("Block %d: tag=0x%08x (%s), size=%u bytes, addr=%p\n", + block_num, block->tag, tag_name, block->size, (void *)block); + + if (block == LASTBLOCK) { + printf(" (LASTBLOCK sentinel)\n"); + } + + block_num++; + block = block->next; + } + printf(BLUE "==================\n\n" RESET); +} + +// Forward declare the actual implementation signature (different from header) +extern int TH_free(uint8_t *ptr); + +// Helper to cast uint32_t* to call the actual TH_free +inline int free_block(uint8_t *ptr) { + return TH_free(ptr); +} + +// Global state for defrag callbacks +struct DefragState { + static int moves_count; +}; + +int DefragState::moves_count = 0; + +// Defrag callback that counts all moves +bool defrag_count_all_moves(short tag, uint8_t *proposed_newptr) { + (void)tag; + (void)proposed_newptr; + DefragState::moves_count++; + return true; +} + +// Defrag callback that allows all moves +bool defrag_allow_all(short tag, uint8_t *proposed_newptr) { + (void)tag; + (void)proposed_newptr; + return true; +} + +// Defrag callback that vetos moves of specific tag +uint16_t veto_tag = 0; +bool defrag_veto_tag(short tag, uint8_t *proposed_newptr) { + (void)proposed_newptr; + if ((uint16_t)tag == veto_tag) { + return false; + } + DefragState::moves_count++; + return true; +} + +// Test Cases + +void test_initialization() { + printf(YELLOW "\n--- Test: Initialization ---\n" RESET); + TH_init(); + + TEST_ASSERT(FIRSTBLOCK != NULL, "FIRSTBLOCK exists"); + TEST_ASSERT(LASTBLOCK != NULL, "LASTBLOCK exists"); + TEST_ASSERT_EQ(FIRSTBLOCK->tag, TH_FREE_TAG, "FIRSTBLOCK is marked free"); + TEST_ASSERT_EQ(LASTBLOCK->tag, TH_FREE_TAG, "LASTBLOCK is marked free"); + TEST_ASSERT_EQ(LASTBLOCK->size, 0, "LASTBLOCK has size 0"); + TEST_ASSERT(FIRSTBLOCK->next == LASTBLOCK, "FIRSTBLOCK->next points to LASTBLOCK"); + TEST_ASSERT(LASTBLOCK->prev == FIRSTBLOCK, "LASTBLOCK->prev points to FIRSTBLOCK"); + TEST_ASSERT(FIRSTBLOCK->prev == NULL, "FIRSTBLOCK->prev is NULL"); + TEST_ASSERT(LASTBLOCK->next == NULL, "LASTBLOCK->next is NULL"); + TEST_ASSERT(validate_block_chain(), "Block chain is valid"); +} + +void test_simple_head_allocation() { + printf(YELLOW "\n--- Test: Simple Head Allocation ---\n" RESET); + TH_init(); + + // Allocate a small block + uint8_t *ptr1 = TH_alloc(16, 0x1001); + TEST_ASSERT_NEQ(ptr1, NULL, "First head allocation succeeds"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after allocation"); + + // Allocate another block + uint8_t *ptr2 = TH_alloc(32, 0x1002); + TEST_ASSERT_NEQ(ptr2, NULL, "Second head allocation succeeds"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after second allocation"); + + // Verify memory separation + TEST_ASSERT(ptr1 != ptr2, "Two allocations have different addresses"); + print_heap_state(); +} + +void test_simple_tail_allocation() { + printf(YELLOW "\n--- Test: Simple Tail Allocation ---\n" RESET); + TH_init(); + + uint8_t *ptr1 = TH_alloc(16, 0x80000001); // Tail tag (MSB set) + TEST_ASSERT_NEQ(ptr1, NULL, "First tail allocation succeeds"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after tail allocation"); + + uint8_t *ptr2 = TH_alloc(32, 0x80000002); + TEST_ASSERT_NEQ(ptr2, NULL, "Second tail allocation succeeds"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after second tail allocation"); + + print_heap_state(); +} + +void test_mixed_head_tail_allocation() { + printf(YELLOW "\n--- Test: Mixed Head and Tail Allocation ---\n" RESET); + TH_init(); + + uint8_t *head1 = TH_alloc(16, 0x1001); + uint8_t *head2 = TH_alloc(16, 0x1002); + uint8_t *tail1 = TH_alloc(16, 0x80000001); + uint8_t *tail2 = TH_alloc(16, 0x80000002); + + TEST_ASSERT_NEQ(head1, NULL, "Head allocation 1 succeeds"); + TEST_ASSERT_NEQ(head2, NULL, "Head allocation 2 succeeds"); + TEST_ASSERT_NEQ(tail1, NULL, "Tail allocation 1 succeeds"); + TEST_ASSERT_NEQ(tail2, NULL, "Tail allocation 2 succeeds"); + TEST_ASSERT(validate_block_chain(), "Block chain valid with mixed allocations"); + + print_heap_state(); +} + +void test_freeblock_case_0_isolated_free() { + printf(YELLOW "\n--- Test: Freeblock Case 0 (Isolated Free) ---\n" RESET); + TH_init(); + + // Allocate three blocks: A (free) B (allocated) C (free) + uint8_t *ptrA = TH_alloc(16, 0x1001); + uint8_t *ptrB = TH_alloc(16, 0x1002); + uint8_t *ptrC = TH_alloc(16, 0x1003); + (void)ptrB; (void)ptrC; // Not used in this test, just for heap setup + + // Free A - should be case 0 (no adjacent free blocks) + TH_free((ptrA)); + TEST_ASSERT(validate_block_chain(), "Block chain valid after freeing isolated block"); + + print_heap_state(); +} + +void test_freeblock_case_1_merge_with_next() { + printf(YELLOW "\n--- Test: Freeblock Case 1 (Merge with Next) ---\n" RESET); + TH_init(); + + // Allocate: A (free) B (allocated) C (free) + uint8_t *ptrA = TH_alloc(16, 0x1001); + uint8_t *ptrB = TH_alloc(16, 0x1002); + (void)ptrB; // Not used in this test, just for heap setup + + // Free A to create a free block + TH_free((ptrA)); + + // Free B - should merge with the free block after it (case 1) + // This requires some careful setup; let's allocate then free strategically + TH_init(); // Reset + + uint8_t *ptr1 = TH_alloc(16, 0x1001); + uint8_t *ptr2 = TH_alloc(16, 0x1002); + uint8_t *ptr3 = TH_alloc(16, 0x1003); + (void)ptr3; // Not used in this test, just for heap setup + + // Free ptr2 first (case 0 - isolated) + TH_free((ptr2)); + print_heap_state(); + + // Free ptr1, which is adjacent to the free block from ptr2 + // This should be case 1 (merge with next) + TH_free((ptr1)); + TEST_ASSERT(validate_block_chain(), "Block chain valid after case 1 merge"); + + print_heap_state(); +} + +void test_freeblock_case_2_merge_with_prev() { + printf(YELLOW "\n--- Test: Freeblock Case 2 (Merge with Previous) ---\n" RESET); + TH_init(); + + uint8_t *ptr1 = TH_alloc(16, 0x1001); + uint8_t *ptr2 = TH_alloc(16, 0x1002); + uint8_t *ptr3 = TH_alloc(16, 0x1003); + (void)ptr3; // Not used in this test, just for heap setup + + // Free ptr1 first (case 0 - isolated) + TH_free((ptr1)); + print_heap_state(); + + // Free ptr2, which is adjacent to the free block before it + // This should be case 2 (merge with previous) + TH_free((ptr2)); + TEST_ASSERT(validate_block_chain(), "Block chain valid after case 2 merge"); + + print_heap_state(); +} + +void test_freeblock_case_3_merge_both() { + printf(YELLOW "\n--- Test: Freeblock Case 3 (Merge Both Directions) ---\n" RESET); + TH_init(); + + uint8_t *ptr1 = TH_alloc(16, 0x1001); + uint8_t *ptr2 = TH_alloc(16, 0x1002); + uint8_t *ptr3 = TH_alloc(16, 0x1003); + uint8_t *ptr4 = TH_alloc(16, 0x1004); + (void)ptr4; // Not used in this test, just for heap setup + + // Free ptr1 and ptr3 to create free blocks on both sides of ptr2 + TH_free((ptr1)); + TH_free((ptr3)); + print_heap_state(); + + // Free ptr2, which should merge with both neighbors (case 3) + TH_free((ptr2)); + TEST_ASSERT(validate_block_chain(), "Block chain valid after case 3 merge"); + + print_heap_state(); +} + +void test_cascade_merges() { + printf(YELLOW "\n--- Test: Cascade Merges ---\n" RESET); + TH_init(); + + // Create a series of allocations + uint8_t *ptrs[10]; + for (int i = 0; i < 10; i++) { + ptrs[i] = TH_alloc(16, 0x1001 + i); + } + + // Free alternating blocks to create multiple small free regions + for (int i = 0; i < 10; i += 2) { + TH_free((ptrs[i])); + } + print_heap_state(); + + // Now free the remaining blocks, which should trigger cascading merges + for (int i = 1; i < 10; i += 2) { + TH_free((ptrs[i])); + } + TEST_ASSERT(validate_block_chain(), "Block chain valid after cascade merges"); + + print_heap_state(); +} + +void test_freetags_range() { + printf(YELLOW "\n--- Test: TH_freetags Range Deallocation ---\n" RESET); + TH_init(); + + // Allocate blocks with various tags + uint8_t *ptr1 = TH_alloc(16, 0x1001); + uint8_t *ptr2 = TH_alloc(16, 0x1002); + uint8_t *ptr3 = TH_alloc(16, 0x1003); + uint8_t *ptr4 = TH_alloc(16, 0x1004); + (void)ptr1; (void)ptr2; (void)ptr3; (void)ptr4; // Not used in this test, just for heap setup + + TEST_ASSERT_NEQ(ptr1, NULL, "Allocations succeed"); + + // Free a range of tags + TH_freetags(0x1002, 0x1003); + TEST_ASSERT(validate_block_chain(), "Block chain valid after freetags"); + + print_heap_state(); +} + +void test_defragmentation() { + printf(YELLOW "\n--- Test: Defragmentation ---\n" RESET); + TH_init(); + + // Allocate and fragment the heap + uint8_t *ptr1 = TH_alloc(64, 0x1001); + uint8_t *ptr2 = TH_alloc(64, 0x1002); + uint8_t *ptr3 = TH_alloc(64, 0x1003); + + // Write pattern to verify data preservation + if (ptr1 && ptr2 && ptr3) { + uint32_t *data1 = (uint32_t*)ptr1; + uint32_t *data2 = (uint32_t*)ptr2; + uint32_t *data3 = (uint32_t*)ptr3; + for (int i = 0; i < 4; i++) { // 16 bytes = 4 dwords + data1[i] = 0x11110000 + i; + data2[i] = 0x22220000 + i; + data3[i] = 0x33330000 + i; + } + } + + print_heap_state(); + + // Create fragmentation by freeing middle block + TH_free((ptr2)); + printf(BLUE "\n--- After freeing ptr2 ---\n" RESET); + print_heap_state(); + + // Defragment with a simple callback that allows all moves + TH_defrag(defrag_allow_all); + TEST_ASSERT(validate_block_chain(), "Block chain valid after defragmentation"); + + printf(BLUE "\n--- After defragmentation ---\n" RESET); + print_heap_state(); + + // Verify data integrity + if (ptr1) { + bool data_ok = true; + uint32_t *data1 = (uint32_t*)ptr1; + for (int i = 0; i < 4; i++) { // 16 bytes = 4 dwords + if (data1[i] != (uint32_t)(0x11110000 + i)) { + data_ok = false; + break; + } + } + TEST_ASSERT(data_ok, "Data integrity preserved in ptr1 after defrag"); + } +} + +void test_countfreehead() { + printf(YELLOW "\n--- Test: TH_countfreehead ---\n" RESET); + TH_init(); + + int initial_free = TH_countfreehead(); + TEST_ASSERT(initial_free > 0, "Initial heap has free space"); + printf(BLUE "Initial free: %d bytes\n" RESET, initial_free); + + // Allocate some memory + uint8_t *ptr1 = TH_alloc(256, 0x1001); + int after_alloc = TH_countfreehead(); + TEST_ASSERT(after_alloc < initial_free, "Free space decreases after allocation"); + printf(BLUE "After allocating 256 bytes: %d bytes free\n" RESET, after_alloc); + + // Free the memory + TH_free((ptr1)); + int after_free = TH_countfreehead(); + TEST_ASSERT(after_free >= initial_free - 256, "Free space increases after deallocation"); + printf(BLUE "After freeing: %d bytes free\n" RESET, after_free); +} + +void test_alloc_at_capacity() { + printf(YELLOW "\n--- Test: Allocation at Capacity ---\n" RESET); + TH_init(); + + // Try to allocate extremely large block + uint8_t *ptr = TH_alloc(10000000, 0x1001); + TEST_ASSERT(ptr == NULL, "Over-capacity allocation returns NULL"); + + // Allocate a very large but valid block + int free_space = TH_countfreehead(); + uint8_t *large_ptr = TH_alloc(free_space - 1024, 0x1002); // Leave some margin + TEST_ASSERT_NEQ(large_ptr, NULL, "Large valid allocation succeeds"); + + TH_free((large_ptr)); +} + +void test_rapid_alloc_free_cycles() { + printf(YELLOW "\n--- Test: Rapid Allocation/Deallocation Cycles ---\n" RESET); + TH_init(); + + const int CYCLES = 100; + const int ALLOCS_PER_CYCLE = 10; + + for (int cycle = 0; cycle < CYCLES; cycle++) { + uint8_t *ptrs[ALLOCS_PER_CYCLE]; + + // Allocate + for (int i = 0; i < ALLOCS_PER_CYCLE; i++) { + ptrs[i] = TH_alloc(32, 0x1000 + (cycle * ALLOCS_PER_CYCLE + i) % 0x1000); + } + + // Free in random order + for (int i = ALLOCS_PER_CYCLE - 1; i >= 0; i--) { + if (ptrs[i]) { + TH_free((ptrs[i])); + } + } + + // Validate after each cycle + if (!validate_block_chain()) { + printf(RED "✗ Block chain corrupted at cycle %d\n" RESET, cycle); + break; + } + } + + TEST_ASSERT(validate_block_chain(), "Block chain valid after rapid cycles"); + printf(GREEN "Completed %d cycles of allocation/deallocation\n" RESET, CYCLES); +} + +void test_complex_fragmentation_and_defrag() { + printf(YELLOW "\n--- Test: Complex Fragmentation and Defragmentation ---\n" RESET); + TH_init(); + + // Create a complex fragmentation pattern + uint8_t *ptrs[20]; + for (int i = 0; i < 20; i++) { + ptrs[i] = TH_alloc(128, 0x1000 + i); + } + + // Free every 3rd block to create scattered free space + for (int i = 0; i < 20; i += 3) { + if (ptrs[i]) { + TH_free((ptrs[i])); + } + } + + int free_before = TH_countfreehead(); + printf(BLUE "Free space before defrag: %d bytes\n" RESET, free_before); + print_heap_state(); + + // Defragment + DefragState::moves_count = 0; + TH_defrag(defrag_count_all_moves); + + int free_after = TH_countfreehead(); + printf(BLUE "Free space after defrag: %d bytes (moved %d blocks)\n" RESET, free_after, DefragState::moves_count); + + TEST_ASSERT(validate_block_chain(), "Block chain valid after complex defrag"); + TEST_ASSERT(free_after >= free_before, "Defragmentation doesn't lose memory"); + + print_heap_state(); + + // Clean up + for (int i = 0; i < 20; i++) { + if (ptrs[i]) { + TH_free((ptrs[i])); + } + } +} + +void test_defrag_with_pinned_blocks() { + printf(YELLOW "\n--- Test: Defragmentation with Pinned Blocks ---\n" RESET); + TH_init(); + + uint8_t *ptr1 = TH_alloc(128, 0x1001); + uint8_t *ptr2 = TH_alloc(128, 0x1002); + uint8_t *ptr3 = TH_alloc(128, 0x1003); + (void)ptr1; (void)ptr3; // Not used in this test, just for heap setup + + // Free ptr2 to create fragmentation + TH_free((ptr2)); + print_heap_state(); + + // Defragment but veto moves of tag 0x1001 (pinned) + DefragState::moves_count = 0; + veto_tag = 0x1001; + TH_defrag(defrag_veto_tag); + TEST_ASSERT(validate_block_chain(), "Block chain valid with pinned blocks"); + printf(BLUE "Moves: %d (ptr1 should have been pinned)\n" RESET, DefragState::moves_count); + + print_heap_state(); +} + +void test_allocation_alignment() { + printf(YELLOW "\n--- Test: Allocation 4-uint8_t Alignment ---\n" RESET); + TH_init(); + + // Test various allocation sizes to ensure all return 4-uint8_t aligned pointers + int test_sizes[] = {1, 2, 3, 4, 5, 7, 8, 15, 16, 17, 33, 100, 256, 1000}; + int num_sizes = sizeof(test_sizes) / sizeof(test_sizes[0]); + + uint8_t *ptrs[14]; + bool all_aligned = true; + + for (int i = 0; i < num_sizes; i++) { + ptrs[i] = TH_alloc(test_sizes[i], 0x1000 + i); + + // Check if pointer is 4-uint8_t aligned + if (ptrs[i]) { + uintptr_t addr = (uintptr_t)ptrs[i]; + if (addr % 4 != 0) { + printf(RED "✗" RESET " Allocation of %d bytes returned unaligned pointer: %p\n", + test_sizes[i], (void*)ptrs[i]); + all_aligned = false; + } else { + printf(GREEN "✓" RESET " Allocation of %d bytes: %p (aligned)\n", + test_sizes[i], (void*)ptrs[i]); + } + } else { + printf(RED "✗" RESET " Allocation of %d bytes returned NULL\n", test_sizes[i]); + all_aligned = false; + } + } + + TEST_ASSERT(all_aligned, "All allocations are 4-uint8_t aligned"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after alignment test"); + + print_heap_state(); +} + +void test_realloc_null_ptr() { + printf(YELLOW "\n--- Test: Realloc with NULL Pointer ---\n" RESET); + TH_init(); + + // Try to realloc NULL pointer - should return NULL + uint8_t *result = TH_realloc(NULL, 100); + TEST_ASSERT(result == NULL, "TH_realloc(NULL, 100) returns NULL"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after NULL realloc"); + + print_heap_state(); +} + +void test_realloc_zero_size() { + printf(YELLOW "\n--- Test: Realloc with Zero/Negative Size ---\n" RESET); + TH_init(); + + // Allocate a block + uint8_t *ptr = TH_alloc(100, 0x2000); + TEST_ASSERT(ptr != NULL, "Initial allocation succeeds"); + + // Try to realloc to size 0 - should free and return NULL + uint8_t *result = TH_realloc(ptr, 0); + TEST_ASSERT(result == NULL, "TH_realloc(ptr, 0) returns NULL and frees block"); + TEST_ASSERT(validate_block_chain(), "Block chain valid after zero-size realloc"); + + // Verify the block was actually freed by checking free space + int free_after = TH_countfreehead(); + printf(BLUE "Free HEAD space after zero-size realloc: %d bytes\n" RESET, free_after); + TEST_ASSERT(free_after > 0, "Space was freed after zero-size realloc"); + + print_heap_state(); +} + +void test_realloc_no_op_shrink() { + printf(YELLOW "\n--- Test: Realloc to Smaller Size (No-Op) ---\n" RESET); + TH_init(); + + // Allocate a block of 200 bytes + uint8_t *ptr = TH_alloc(200, 0x2000); + TEST_ASSERT(ptr != NULL, "Initial allocation succeeds"); + + // Write pattern + uint32_t *pattern_ptr = (uint32_t *)ptr; + pattern_ptr[0] = 0xDEADBEEF; + pattern_ptr[1] = 0xCAFEBABE; + + // Try to realloc to smaller size (100 bytes) - implementation returns ptr as-is + uint8_t *result = TH_realloc(ptr, 100); + TEST_ASSERT(result == ptr, "TH_realloc to smaller size returns same ptr"); + + // Verify pattern is intact + TEST_ASSERT(pattern_ptr[0] == 0xDEADBEEF, "Pattern uint8_t 0 intact after shrink"); + TEST_ASSERT(pattern_ptr[1] == 0xCAFEBABE, "Pattern uint8_t 1 intact after shrink"); + + print_heap_state(); +} + +void test_realloc_no_growth_needed() { + printf(YELLOW "\n--- Test: Realloc When Block Already Large Enough ---\n" RESET); + TH_init(); + + // Allocate 200 bytes + uint8_t *ptr = TH_alloc(200, 0x2000); + TEST_ASSERT(ptr != NULL, "Initial allocation succeeds"); + + // Write pattern + uint32_t *pattern_ptr = (uint32_t *)ptr; + pattern_ptr[0] = 0x11111111; + pattern_ptr[1] = 0x22222222; + + // Try to realloc to same/smaller size (100 bytes) + uint8_t *result = TH_realloc(ptr, 100); + TEST_ASSERT(result == ptr, "TH_realloc(200-uint8_t block, 100) returns same ptr"); + + // Verify pattern is intact + TEST_ASSERT(pattern_ptr[0] == 0x11111111, "Pattern uint8_t 0 intact"); + TEST_ASSERT(pattern_ptr[1] == 0x22222222, "Pattern uint8_t 1 intact"); + + TEST_ASSERT(validate_block_chain(), "Block chain valid"); + + print_heap_state(); +} + +void test_realloc_in_place_expansion() { + printf(YELLOW "\n--- Test: Realloc with In-Place Expansion (Next Block Free) ---\n" RESET); + TH_init(); + + // Allocate A (100 bytes) + uint8_t *ptrA = TH_alloc(100, 0x2000); + TEST_ASSERT(ptrA != NULL, "Block A allocation succeeds"); + + // Allocate B (100 bytes) + uint8_t *ptrB = TH_alloc(100, 0x2001); + TEST_ASSERT(ptrB != NULL, "Block B allocation succeeds"); + + // Allocate C (100 bytes) + uint8_t *ptrC = TH_alloc(100, 0x2002); + TEST_ASSERT(ptrC != NULL, "Block C allocation succeeds"); + + printf(BLUE "Before realloc: A=%p, B=%p, C=%p\n" RESET, (void*)ptrA, (void*)ptrB, (void*)ptrC); + + // Free B - now A is adjacent to free block + TH_free(ptrB); + TEST_ASSERT(validate_block_chain(), "Block chain valid after freeing B"); + + // Write pattern to A + uint32_t *pattern = (uint32_t *)ptrA; + pattern[0] = 0xAAAAAAAA; + pattern[1] = 0xBBBBBBBB; + + // Realloc A to 150 bytes - should expand into freed B space in-place + uint8_t *result = TH_realloc(ptrA, 150); + TEST_ASSERT(result == ptrA, "In-place expansion returns same pointer"); + + // Verify pattern is intact in same location + uint32_t *check_pattern = (uint32_t *)result; + TEST_ASSERT(check_pattern[0] == 0xAAAAAAAA, "Original pattern uint8_t 0 preserved"); + TEST_ASSERT(check_pattern[1] == 0xBBBBBBBB, "Original pattern uint8_t 1 preserved"); + + TEST_ASSERT(validate_block_chain(), "Block chain valid after in-place expansion"); + + printf(BLUE "After realloc: Result=%p (same=%d)\n" RESET, (void*)result, result == ptrA); + + print_heap_state(); +} + +void test_realloc_with_block_splitting() { + printf(YELLOW "\n--- Test: Realloc with In-Place Expansion + Block Splitting ---\n" RESET); + TH_init(); + + // Allocate A (100 bytes) + uint8_t *ptrA = TH_alloc(100, 0x3000); + TEST_ASSERT(ptrA != NULL, "Block A allocation succeeds"); + + // Allocate B (500 bytes) - large block to free later + uint8_t *ptrB = TH_alloc(500, 0x3001); + TEST_ASSERT(ptrB != NULL, "Block B allocation succeeds"); + + // Allocate C (100 bytes) - to keep B from being tail-adjacent + uint8_t *ptrC = TH_alloc(100, 0x3002); + TEST_ASSERT(ptrC != NULL, "Block C allocation succeeds"); + + // Free B - creates a 500-uint8_t free block + TH_free(ptrB); + TEST_ASSERT(validate_block_chain(), "Block chain valid after freeing large B"); + + // Write pattern to A + uint32_t *pattern = (uint32_t *)ptrA; + pattern[0] = 0xCCCCCCCC; + pattern[1] = 0xDDDDDDDD; + + // Realloc A to 150 bytes - should expand into B, splitting it + // (A needs 150, next free block is 500, so will split into 150 and remaining) + uint8_t *result = TH_realloc(ptrA, 150); + TEST_ASSERT(result == ptrA, "Expansion with splitting returns same pointer"); + + // Verify pattern is intact + uint32_t *check = (uint32_t *)result; + TEST_ASSERT(check[0] == 0xCCCCCCCC, "Pattern uint8_t 0 preserved after split"); + TEST_ASSERT(check[1] == 0xDDDDDDDD, "Pattern uint8_t 1 preserved after split"); + + TEST_ASSERT(validate_block_chain(), "Block chain valid after split realloc"); + + print_heap_state(); +} + +void test_realloc_full_reallocation() { + printf(YELLOW "\n--- Test: Realloc Requiring Full Reallocation (New Block) ---\n" RESET); + TH_init(); + + // Allocate A (100 bytes) + uint8_t *ptrA = TH_alloc(100, 0x4000); + TEST_ASSERT(ptrA != NULL, "Block A allocation succeeds"); + + // Allocate B (100 bytes) - next to A + uint8_t *ptrB = TH_alloc(100, 0x4001); + TEST_ASSERT(ptrB != NULL, "Block B allocation succeeds"); + + printf(BLUE "Before full realloc: A=%p, B=%p\n" RESET, (void*)ptrA, (void*)ptrB); + + // Write pattern to A + uint32_t *pattern = (uint32_t *)ptrA; + for (int i = 0; i < 25; i++) { + pattern[i] = 0x12340000 + i; + } + + // Try to realloc A to 300 bytes + // Since B is adjacent and not free, can't expand in-place + // Should allocate new block, copy data, free old block + uint8_t *result = TH_realloc(ptrA, 300); + TEST_ASSERT(result != NULL, "Full reallocation succeeds"); + TEST_ASSERT(result != ptrA, "Full reallocation returns different pointer"); + + // Verify pattern was copied correctly + uint32_t *check = (uint32_t *)result; + bool data_intact = true; + for (int i = 0; i < 25; i++) { + if (check[i] != (0x12340000 + i)) { + printf(RED "✗ Pattern mismatch at offset %d: %p got 0x%x, expected 0x%x\n" RESET, + i * 4, (void*)(result + i*4), check[i], 0x12340000 + i); + data_intact = false; + } + } + TEST_ASSERT(data_intact, "Data copied correctly on full reallocation"); + + // Verify B is still accessible + TEST_ASSERT(ptrB != NULL, "Original block B still valid"); + + TEST_ASSERT(validate_block_chain(), "Block chain valid after full reallocation"); + + printf(BLUE "After full realloc: New=%p (different=%d)\n" RESET, (void*)result, result != ptrA); + + print_heap_state(); +} + +void test_realloc_data_integrity() { + printf(YELLOW "\n--- Test: Realloc Data Integrity with Various Patterns ---\n" RESET); + TH_init(); + + // Test with multiple allocation+realloc cycles + struct { + int initial_size; + int realloc_size; + } test_cases[] = { + {50, 150}, + {100, 300}, + {200, 100}, // Shrink (no-op) + {80, 200}, + }; + + int num_cases = sizeof(test_cases) / sizeof(test_cases[0]); + + for (int tc = 0; tc < num_cases; tc++) { + int init_sz = test_cases[tc].initial_size; + int realloc_sz = test_cases[tc].realloc_size; + + uint8_t *ptr = TH_alloc(init_sz, 0x5000 + tc); + TEST_ASSERT(ptr != NULL, "Allocation succeeds in test case"); + + // Fill with pattern + uint8_t *byte_ptr = ptr; + for (int i = 0; i < init_sz; i++) { + byte_ptr[i] = (uint8_t)((0xAA + tc) ^ (i & 0xFF)); + } + + // Realloc + uint8_t *result = TH_realloc(ptr, realloc_sz); + TEST_ASSERT(result != NULL, "Realloc succeeds"); + + // Verify original bytes are intact + bool match = true; + int check_sz = (init_sz < realloc_sz) ? init_sz : realloc_sz; + for (int i = 0; i < check_sz; i++) { + uint8_t expected = (uint8_t)((0xAA + tc) ^ (i & 0xFF)); + if (result[i] != expected) { + printf(RED "✗ Data mismatch in test case %d at uint8_t %d\n" RESET, tc, i); + match = false; + break; + } + } + TEST_ASSERT(match, "Data integrity maintained in realloc cycle"); + } + + TEST_ASSERT(validate_block_chain(), "Block chain valid after data integrity tests"); + + print_heap_state(); +} + +void test_realloc_alignment() { + printf(YELLOW "\n--- Test: Realloc Maintains Data Alignment ---\n" RESET); + TH_init(); + + // Test that data from reallocated blocks is preserved correctly + // (We don't test pointer alignment since block headers may not be aligned) + int test_sizes[] = {10, 50, 100, 200}; + int num_tests = sizeof(test_sizes) / sizeof(test_sizes[0]); + + for (int i = 0; i < num_tests; i++) { + uint8_t *ptr = TH_alloc(test_sizes[i], 0x6000 + i); + TEST_ASSERT(ptr != NULL, "Initial allocation succeeds"); + + // Fill with test pattern + for (int j = 0; j < test_sizes[i]; j++) { + ptr[j] = (uint8_t)(0x55 + j); + } + + // Realloc to different size + int new_size = test_sizes[i] + 50; + uint8_t *result = TH_realloc(ptr, new_size); + + TEST_ASSERT(result != NULL, "Realloc succeeded"); + + // Verify pattern is preserved + bool pattern_ok = true; + for (int j = 0; j < test_sizes[i]; j++) { + if (result[j] != (uint8_t)(0x55 + j)) { + pattern_ok = false; + break; + } + } + TEST_ASSERT(pattern_ok, "Data pattern preserved in realloc"); + } + + TEST_ASSERT(validate_block_chain(), "Block chain valid after alignment tests"); + + print_heap_state(); +} + +void test_realloc_with_pinned_blocks() { + printf(YELLOW "\n--- Test: Realloc Behavior with Pinned Blocks ---\n" RESET); + TH_init(); + + // Allocate some blocks + uint8_t *ptrA = TH_alloc(100, 0x7000); + uint8_t *ptrB = TH_alloc(100, 0x7001); + uint8_t *ptrC = TH_alloc(100, 0x7002); + + TEST_ASSERT(ptrA && ptrB && ptrC, "All initial allocations succeed"); + + // Free B to create fragmentation + TH_free(ptrB); + + // Write pattern to A + uint32_t *pattern = (uint32_t *)ptrA; + pattern[0] = 0x77777777; + + // Realloc A - this might involve block movement via defrag indirectly + uint8_t *result = TH_realloc(ptrA, 200); + TEST_ASSERT(result != NULL, "Realloc succeeds"); + + // Verify pattern is intact + uint32_t *check = (uint32_t *)result; + TEST_ASSERT(check[0] == 0x77777777, "Pattern preserved in realloc with fragmentation"); + + TEST_ASSERT(validate_block_chain(), "Block chain valid"); + + print_heap_state(); +} + +void run_all_tests() { + printf(BLUE "\n╔════════════════════════════════════════════╗\n"); + printf("║ TagHeap White Box Test Suite ║\n"); + printf("╚════════════════════════════════════════════╝\n" RESET); + + test_initialization(); + test_simple_head_allocation(); + test_simple_tail_allocation(); + test_mixed_head_tail_allocation(); + test_freeblock_case_0_isolated_free(); + test_freeblock_case_1_merge_with_next(); + test_freeblock_case_2_merge_with_prev(); + test_freeblock_case_3_merge_both(); + test_cascade_merges(); + test_freetags_range(); + test_countfreehead(); + test_alloc_at_capacity(); + test_defragmentation(); + test_defrag_with_pinned_blocks(); + test_complex_fragmentation_and_defrag(); + test_rapid_alloc_free_cycles(); + test_allocation_alignment(); + test_realloc_null_ptr(); + test_realloc_zero_size(); + test_realloc_no_op_shrink(); + test_realloc_no_growth_needed(); + test_realloc_in_place_expansion(); + test_realloc_with_block_splitting(); + test_realloc_full_reallocation(); + test_realloc_data_integrity(); + test_realloc_alignment(); + test_realloc_with_pinned_blocks(); + + // Print summary + printf(BLUE "\n╔════════════════════════════════════════════╗\n"); + printf("║ Test Summary ║\n"); + printf("╚════════════════════════════════════════════╝\n" RESET); + printf("Total tests: %d\n", test_count); + printf(GREEN "Passed: %d\n" RESET, test_passed); + printf("%s", test_failed > 0 ? RED : GREEN); + printf("Failed: %d\n" RESET, test_failed); + + if (test_failed == 0) { + printf(GREEN "\n✓ All tests passed!\n\n" RESET); + exit(EXIT_SUCCESS); + } else { + printf(RED "\n✗ Some tests failed.\n\n" RESET); + exit(EXIT_FAILURE); + } +} + +int main() { + run_all_tests(); + return 0; +} diff --git a/gamedata/minimem/w_lumps.cc b/gamedata/minimem/w_lumps.cc new file mode 100644 index 00000000..79aa8beb --- /dev/null +++ b/gamedata/minimem/w_lumps.cc @@ -0,0 +1,146 @@ +#include "w_lumps.h" +#include +#include + +#define CACHESIZE 16 + + +static struct fl_cache_s { + filelump_t lump; + short index; +} _named_cache[CACHESIZE]; +static struct fl_cache_s* named_cache = _named_cache - 1; // 1-based + +#define LASTENTRY (CACHESIZE + 1) + +static struct +{ + uint8_t next; + union + { + uint8_t prev; + uint8_t free; + }; +} lru[CACHESIZE + 2]; + +static void RemoveEntryFromLRU(uint8_t entry) +{ + auto prev = lru[entry].prev; + auto next = lru[entry].next; + + lru[prev].next = lru[entry].next; + lru[next].prev = lru[entry].prev; +} + +static void InsertInFrontOfLRU(uint8_t entry) +{ + // 0 -> entry -> end + // 0 <- <- end + lru[entry].prev = 0; + lru[entry].next = lru[0].next; + lru[lru[0].next].prev = entry; + lru[0].next = entry; +} + +static uint8_t GetFreeLRUEntry() +{ + uint8_t entry = lru[0].free; + if (!entry) + { + // Remove least recently used + entry = lru[LASTENTRY].prev; + RemoveEntryFromLRU(entry); + } else { + // Take it out of the free list + lru[0].free = lru[entry].free; + } + return entry; +} + +int LC_CheckNumForName(const char *name) +{ + uint64_t nname = 0; + strncpy((char *)&nname, name, 8); + //check the named cache first + uint8_t next_entry = lru[0].next; + while (next_entry!= LASTENTRY) + { + if (named_cache[next_entry].lump.nname - nname == 0) + { + //printf("Found in named cache: %s\n",name); + // Mark this as most recently used + RemoveEntryFromLRU(next_entry); + InsertInFrontOfLRU(next_entry); + return named_cache[next_entry].index; + } + next_entry = lru[next_entry].next; + } + //printf("Cache miss: %s\n",name); + //not found in named cache - do full search + uint32_t name_low = nname; + uint32_t name_high = nname >> 32; + for (int i = 0; i < WADLUMPS; i++) + { + if (lumpname_low[i] == name_low && lumpname_high[i] == name_high) + { + //insert into named cache + uint8_t entry = GetFreeLRUEntry(); + named_cache[entry].lump.filepos = filepos[i]; + named_cache[entry].lump.size = lumpsize[i]; + named_cache[entry].lump.nname = nname; + named_cache[entry].index = i; + InsertInFrontOfLRU(entry); + //printf("Caching lump %s at entry %d\n",name,entry); + return i; + } + } + // Now this is not found - we still need to register this + // in the named cache as a missing entry to fail faster next time: + uint8_t entry = GetFreeLRUEntry(); + named_cache[entry].lump.filepos = 0; + named_cache[entry].lump.size = 0; + named_cache[entry].lump.nname = nname; + named_cache[entry].index = -1; + InsertInFrontOfLRU(entry); + //printf("Caching missing lump %s at entry %d\n",name,entry); + return -1; +} + +const char *LC_GetNameForNum(int lump, char buffer[8]) +{ + uint32_t name_low = lumpname_low[lump]; + uint32_t name_high = lumpname_high[lump]; + uint64_t nname = ((uint64_t)name_high << 32) | name_low; + strncpy(buffer, (char *)&nname, 8); + return buffer; +} + +int LC_LumpLength(int lumpnum) +{ + return lumpsize[lumpnum]; +} + +filelump_t LC_LumpForNum(int lumpnum) +{ + filelump_t lump; + lump.filepos = filepos[lumpnum]; + lump.size = lumpsize[lumpnum]; + uint32_t name_low = lumpname_low[lumpnum]; + uint32_t name_high = lumpname_high[lumpnum]; + uint64_t nname = ((uint64_t)name_high << 32) | name_low; + lump.nname = nname; + return lump; +} + +void LC_Init(void) +{ + // Initialize LRU + lru[0].next = LASTENTRY; + lru[LASTENTRY].prev = 0; + lru[LASTENTRY].next = 0; + for (uint8_t i = 0; i < LASTENTRY-1; i++) + { + lru[i].free = i + 1; + } + lru[LASTENTRY-1].free = 0; +} diff --git a/gamedata/minimem/w_lumps.h b/gamedata/minimem/w_lumps.h new file mode 100644 index 00000000..18989735 --- /dev/null +++ b/gamedata/minimem/w_lumps.h @@ -0,0 +1,15 @@ +#ifndef __W_LUMPS_H__ +#define __W_LUMPS_H__ +#include +#include "gbadoom1_lumps.h" +#include "../newcache/newcache.h" + +int LC_CheckNumForName(const char *name); +const char* LC_GetNameForNum(int lump, char buffer[8]); +int LC_LumpLength(int lumpnum); +filelump_t LC_LumpForNum(int lumpnum); +void LC_Init(void); + + + +#endif /* __W_LUMPS_H__ */ \ No newline at end of file diff --git a/gamedata/minimem/w_nc.cc b/gamedata/minimem/w_nc.cc new file mode 100644 index 00000000..69a1659e --- /dev/null +++ b/gamedata/minimem/w_nc.cc @@ -0,0 +1,561 @@ +#include "../newcache/newcache.h" +#include "../guardmalloc/guardmalloc.h" +#include "../include/r_defs.h" +#include "wadreader.h" +#include "tagheap.h" +#include "w_lumps.h" + +#include +#if TH_CANARY_ENABLED == 1 +#include +#include +#endif + + +extern unsigned char gfx_stbar[]; +extern line_t junk; + +#define ASSERT_PTR_IN_HEAP(ptr) assert((uint8_t *)(ptr) >= &th_heap[0] && (uint8_t *)(ptr) < &th_heap[TH_HEAPSIZE]) +#define ASSERT_VALID_LUMPNUM(lumpnum) assert(lumpnum >= 0 && lumpnum < MAXLUMPS) +#define ASSERT_VALID_LUMPNUM_OR_MINUS1(lumpnum) assert((lumpnum >= -1 && lumpnum < MAXLUMPS)) +#define ASSERT_VALID_CACHE_ENTRY(entry) assert(entry >= 1 && entry <= 254) + + +/** + * This file contains a simple cache that uses TH_malloc to allocate memory and + * just keep it in memory until flushed. + */ + + /** + * The LUT for indexing into the actual cache. 0 means that nothing is cached for this + * 1-254 are valid cache indices. The last three has special meaning: + * 252 : junk line_t + * 253 : gfx_stbar + * 254 : nullptr (used for the -1 index) + */ +static uint8_t _cache[MAXLUMPS+1]; +static uint8_t *cache = _cache+1; // Allow -1 index + + + +/** + * The pointers that map cache indices to objects, either allocated on the heap using TH_alloc or by static mapping set up in InitCache() + */ +static uint8_t *pointers[256]; + +/** + * The number of times an object has been pinned. Pinned objects can't be moved during a defrag, and they can't be evicted. Static mappings + * are always pinned so that we never try to move or evict them. Pinning happens when a proxy object is converted to a pointer, either by + * means of operator T*() on a Pnned (produced by .pin()) or by means of a Sentinel implementing operator->() + */ +static uint8_t pincount[256]; + +/** + * A doubly linked list implemented as an array. Start is index 0 and end is index 255, which is why cache indices can only be 1-254. + * It serves two purposes: + * 1) Track free entries by means of the .free singly linked list + * 2) Track least recently used entries, by pushing an entry to the front each time it is pinned. + */ +static struct { + uint8_t next; + union { + uint8_t prev; + uint8_t free; + }; +} lru[256]; + +/** + * The header for the WAD file. This is set up by WR_Init() + */ +static wadinfo_t header; + +/** + * Loosely tracking how much memory is allocated - for debug purposes + */ +static int allocated = 0; + +/** + * Cache initialization function. It: + * - Sets all entries to 0 (unmapped) + * - Prefills the special entries (-1 mapping to nullptr, STBAR_LUMP_NUM mapping to gfx_stbar and JUNK_LUMP_NUM mapping to junk) + * These objects are always pinned by setting pincount to 1 and thereby never have it 0 (pin and unpin is always symmetric) + * - Initialize the free list to map to 1-251 + */ +static void InitCache() { + // Set all entries to 0 (unmapped) + for (int i=-1;itag; + ASSERT_VALID_LUMPNUM(lumpnum); + return lumpnum; +} + +/** + * Helper function that can fetch the size in bytes associated with ptr during TH_alloc() + */ +static uint32_t size_for_ptr(const uint8_t *ptr){ + ASSERT_PTR_IN_HEAP(ptr); + auto block = (const th_memblock_t *)ptr; + block -= 1; + ASSERT_VALID_LUMPNUM(block->tag); // At least check that the tag is a valid lumpnum + return block->size; + +} + +/** + * Debug functin that prints the health of the heap in case of a fatal error. + */ +static void PrintHeapStatus() { + #if TH_CANARY_ENABLED == 1 + uint8_t entry = 0; + printf("\nHeap:\n"); + while (entry != 255) { + uint8_t next_entry = lru[entry].next; + const char* status = (lru[next_entry].prev==entry) ? "OK" : "Broken"; + const char* pinned = (pincount[next_entry]) ? "Pinned" : "Unpin"; + printf("%d %s %s(%d)\n",next_entry,pinned,status,lru[next_entry].prev); + entry = next_entry; + } + printf("\nFreelist\n"); + entry=lru[0].free; + while(entry) { + printf("%d\n",entry); + entry=lru[entry].free; + } + #endif +} + +/** + * Helper function that removes entry from the LRU by linking the preceding and proceeding + * entries together + */ +static void RemoveEntryFromLRU(uint8_t entry) { + ASSERT_VALID_CACHE_ENTRY(entry); + auto prev = lru[entry].prev; + auto next = lru[entry].next; + + lru[prev].next = lru[entry].next; + lru[next].prev = lru[entry].prev; +} + +/** + * Helper function that inserts the entry at the front of the LRU + */ +static void InsertInFrontOfLRU(uint8_t entry) { + ASSERT_VALID_CACHE_ENTRY(entry); + // 0 -> entry -> end + // 0 <- <- end + lru[entry].prev=0; + lru[entry].next=lru[0].next; + lru[lru[0].next].prev=entry; + lru[0].next = entry; +} + +/** Evict the least used non-pinned block. Return 0 if nothing can be evicted, + * otherwise the number of bytes made available will be returned. + */ +static int EvictOne() { + #if TH_CANARY_ENABLED == 1 + printf("INFO: Tryingn to evict one... "); + #endif + uint8_t entry = lru[255].prev; + while (entry && pincount[entry]) { + entry = lru[entry].prev; + } + // If prev is 0, then we have nothing to evict - otherwise evict the least + // recently used + if (!entry) return 0; + ASSERT_VALID_CACHE_ENTRY(entry); + // Take it out of the LRU list and free it + RemoveEntryFromLRU(entry); + // Insert in free list + lru[entry].free = lru[0].free; + lru[0].free = entry; + auto ptr = pointers[entry]; + auto lumpnum = lumpnum_for_ptr(ptr); + cache[lumpnum]=0; // Clear that entry from the cache + allocated -= size_for_ptr(ptr); + auto freed = TH_free(ptr); + pointers[entry]=nullptr; + #if TH_CANARY_ENABLED == 1 + printf(" lump %d from cache freeing %d bytes at entry %d\n",lumpnum,freed,entry); + if (TH_checkhealth_verbose()==false) { + printf("FATAL: Heap corrupted during eviction of lump %d\n",lumpnum); + assert(false);exit(-1); + } else { + printf("INFO: Heap healthy after eviction - %d bytes are allocated\n",allocated); + } + #endif + return freed; +} + +/** + * Callback function for defragmentation + */ +static bool defrag_cb(short lumpnum, uint8_t *proposed_newptr){ + ASSERT_VALID_LUMPNUM(lumpnum); + auto entry = cache[lumpnum]; + if (!entry) { + #if TH_CANARY_ENABLED == 1 + printf("WARNING: Defrag found an allocation that isn't mapped in the cache (lump=%d). This is a leak, and we will allow it to move\n",lumpnum); + #endif + return true; + } + ASSERT_VALID_CACHE_ENTRY(entry); + if (pincount[entry]) return false; // Can't move pinned objects + // Register the new pointer and give OK to move. + pointers[entry]=proposed_newptr; + return true; +} + +bool NC_FreeSomeMemoryForTail(){ + #if TH_CANARY_ENABLED == 1 + printf("INFO: Trying to free some memory for tail\n"); + #endif + while (EvictOne()) { + // Keep evicting until we can't evict any more + } + TH_defrag(defrag_cb); + return true; +} + +/** + * Allocate a new area in the cache and push it to the front of the LRU + * Note that this fuction by design will exit the program if it can't allocate thus + * always returning a valid pointer. + */ +static uint8_t AllocateIntoCache(int bytes, int lumpnum) { + ASSERT_VALID_LUMPNUM(lumpnum); + #if TH_CANARY_ENABLED == 1 + printf("\nINFO: Trying to allocate %d bytes for lump %d\n",bytes,lumpnum); + #endif + // Try to allocate bytes from the heap + uint8_t *data = TH_alloc(bytes,lumpnum); + if (!data) { + // We need to try harder - find out how much we have free + int freemem = TH_countfreehead(); + // Then evict data until we have enough + while (freemem < bytes){ + auto freed = EvictOne(); + freemem += freed; + if (!freed) { + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Couldn't evict any useful amount..\n"); + #endif + PrintHeapStatus(); + assert(false);exit(-1); + } + } + // Try allocating again + data = TH_alloc(bytes,lumpnum); + while (!data) { + // We have enough free data but it is not contiguous - try defrag + #if TH_CANARY_ENABLED == 1 + printf("INFO: Not enough contiguous memory - trying defragmentation\n"); + #endif + TH_defrag(defrag_cb); + if (!TH_checkhealth_verbose()) { + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Heap corrupted during defragmentation\n"); + #endif + assert(false);exit(-1); + } + data = TH_alloc(bytes,lumpnum); + if (!data) { + // Still not working - try to evict one and then try defrag and alloc again + // (since data is null) + if (!EvictOne()) { + // Now this is bad - we cant evict any more and we can't allocate. + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Can't allocate %d bytes for lumpnum=%d\n",bytes,lumpnum); + PrintHeapStatus(); + #endif + assert(false);exit(-1); + } + } + } + } + // Get a free cache entry + auto entry = lru[0].free; + if (!entry) { + // We need a free entry so kick something out if we don't have one + #if TH_CANARY_ENABLED == 1 + printf("INFO: Needs to evict a lump to free up a cache entry\n"); + #endif + if (!EvictOne()){ + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Cant evict an entry to free up - can't be true that all memory is pinned\n"); + #endif + PrintHeapStatus(); + assert(false);exit(-1); + } + entry = lru[0].free; + } + // Take it out of the free list + lru[0].free = lru[entry].free; + // Put it into pointers + pointers[entry]=data; + // Insert in front in the LRU. + InsertInFrontOfLRU(entry); + cache[lumpnum]=entry; + allocated += bytes; + #if TH_CANARY_ENABLED == 1 + printf("INFO: Inserted %d bytes for lump %d into heap and cache structures at entry %d (@ 0x%lx)\n",bytes,lumpnum,entry,(uintptr_t)data); + #endif + return entry; +} + +/** + * Read a filelump_t from the wad file + */ +static filelump_t LumpForNum(int lumpnum){ + ASSERT_VALID_LUMPNUM(lumpnum); + /* + int offset = header.infotableofs+lumpnum*sizeof(filelump_t); + filelump_t data; + WR_Read((uint8_t*)&data,offset,sizeof(filelump_t)); + */ + auto data = LC_LumpForNum(lumpnum); + return data; +} + +/** + * Make sure that lumpnum is mapped and loaded in the cache and return the pointer to the lump data. + */ +const uint8_t * NC_CacheLumpNum(int lumpnum) +{ + ASSERT_VALID_LUMPNUM_OR_MINUS1(lumpnum); + if (cache[lumpnum]==0){ + // Allocate new cache entry and load it from file + auto lump = LumpForNum(lumpnum); + uint8_t entry = AllocateIntoCache(lump.size,lumpnum); + auto ptr = pointers[entry]; + // Read the header + WR_Read(ptr,lump.filepos,lump.size); + #if TH_CANARY_ENABLED == 1 + if (TH_checkhealth_verbose()==false) { + printf("FATAL: Heap corrupted after loading lump %d\n",lumpnum); + assert(false);exit(-1); + } else { + printf("INFO: Heap healthy after loading lump %d - %d bytes are allocated\n",lumpnum,allocated); + } + #endif + //printf("!"); + //fflush(stdout); + } + auto entry = cache[lumpnum]; + ASSERT_VALID_CACHE_ENTRY(entry); + auto ptr = pointers[entry]; + return ptr; +} + +/** + * Return the size of the lump indexed by lumpnum, either by looking in the cache or by loading the + * lump descriptor from the WAD file using LumpForNum and get the size from there. + */ +int NC_LumpLength(int lumpnum) +{ + ASSERT_VALID_LUMPNUM(lumpnum); + /* + // Grab length from cache if the element is already cached. + uint8_t entry = cache[lumpnum]; + if (entry) { + return size_for_ptr(pointers[entry]); + } + + auto data = LumpForNum(lumpnum); + return data.size; + */ + return LC_LumpLength(lumpnum); +} + +/** + * Lookup a lump by name and get its index, or -1 if not found + */ +int NC_GetNumForName (const char* name) +{ + int i = NC_CheckNumForName(name); + #if TH_CANARY_ENABLED == 1 + if (i==-1) { + + printf("lump %s not found\n",name); + } + #endif + return i; +} + +/** + * Lookup a lump by name and get its index, or -1 if not found + */ +int NC_CheckNumForName(const char *name) +{ + /* + uint64_t nname=0; + strncpy((char *)&nname,name,8); + int n = 0; + while (n < header.numlumps) { + int remaining_lumps = header.numlumps-n; + int maxlumps = (remaining_lumps > 16) ? 16 : remaining_lumps; + filelump_t lumps[16]; // 256 bytes + // Read the lumps + WR_Read((uint8_t *)lumps,header.infotableofs+n*sizeof(filelump_t),maxlumps*sizeof(filelump_t)); + for (int j=0; j < maxlumps; j++) { + if (nname == lumps[j].nname) { + return n+j; + } + } + n+=16; + } + return -1; + */ + return LC_CheckNumForName(name); +} + +/** + * Get the name of a given lump - return in buffer + */ +const char* NC_GetNameForNum(int lump, char buffer[8]) +{ + ASSERT_VALID_LUMPNUM(lump); + /* + // This is never cached so ... + uint64_t *nbuf = (uint64_t *)buffer; + auto thelump = LumpForNum(lump); + *nbuf = thelump.nname; + return buffer; + */ + return LC_GetNameForNum(lump,buffer); +} + +/** + * Initialize newcache by initializing tagheap, wadreader and cache, and then reading the wad header + */ +void NC_Init(void) +{ + WR_Init(); + TH_init(); + LC_Init(); + // Permanently pin lumps that are allocated in normal RAM + InitCache(); + // Read the header + WR_Read((uint8_t *)&header,0,sizeof(header)); +} + +/** + * Helper function normally implemented by w_wad - we implement here instead + */ +void NC_ExtractFileBase(const char* path, char* dest) +{ + // BDP: Lifted directly from w_wad + const char *src = path + strlen(path) - 1; + int length; + + // back up until a \ or the start + while (src != path && src[-1] != ':' // killough 3/22/98: allow c:filename + && *(src-1) != '\\' + && *(src-1) != '/') + { + src--; + } + + // copy up to eight characters + memset(dest,0,8); + length = 0; + + while ((*src) && (*src != '.') && (++length<9)) + { + *dest++ = toupper(*src); + src++; + } + /* cph - length check removed, just truncate at 8 chars. + * If there are 8 or more chars, we'll copy 8, and no zero termination + */ +} + +/** + * Pin a lump in memory and return the (now stable) address. Also mark it as most recently used + */ +const uint8_t * NC_Pin(int lumpnum) +{ + ASSERT_VALID_LUMPNUM_OR_MINUS1(lumpnum); + auto data = NC_CacheLumpNum(lumpnum); + auto entry = cache[lumpnum]; + ASSERT_VALID_CACHE_ENTRY(entry); + //printf("Pinning lump %d from entry %d at address 0x%lx\n",lumpnum_for_ptr(data),entry,(uintptr_t)data); + pincount[entry]+=1; + // Move entry up front in the LRU + RemoveEntryFromLRU(entry); + InsertInFrontOfLRU(entry); + return data; +} + +/** + * Unpin the lump by decreasing its pincount + */ +void NC_Unpin(int lumpnum) +{ + ASSERT_VALID_LUMPNUM_OR_MINUS1(lumpnum); + //printf("Unpin lump %d\n",lumpnum); + auto entry = cache[lumpnum]; + ASSERT_VALID_CACHE_ENTRY(entry); + assert(pincount[entry]>0); + pincount[entry]-=1; +} + +/** + * Flush the cache by evicting all objects (could be done faster and more brute force, but this is easier to debug) + */ +void NC_FlushCache(void) +{ + #if TH_CANARY_ENABLED == 1 + printf("******************\n"); + printf("*** FLUSH ***\n"); + printf("******************\n"); + printf("Flushing cache with %d bytes in it\n",allocated); + #endif + + while (EvictOne()); + + #if TH_CANARY_ENABLED == 1 + printf("Flushed cache now has %d bytes in it\n",allocated); + if (TH_checkhealth_verbose()==false) { + printf("FATAL: Heap corrupted during cache flush\n"); + assert(false);exit(-1); + } + #endif +} + + diff --git a/gamedata/minimem/wadreader.h b/gamedata/minimem/wadreader.h new file mode 100644 index 00000000..cd4fbe15 --- /dev/null +++ b/gamedata/minimem/wadreader.h @@ -0,0 +1,9 @@ +#ifndef __wadreader_h +#define __wadreader_h + +#include + +void WR_Init(); +void WR_Read(uint8_t *dst, int offset, int len); + +#endif //__wadreader_h \ No newline at end of file diff --git a/gamedata/minimem/z_mem_emu.cc b/gamedata/minimem/z_mem_emu.cc new file mode 100644 index 00000000..040b293b --- /dev/null +++ b/gamedata/minimem/z_mem_emu.cc @@ -0,0 +1,166 @@ +/** + * Memory emulation for z_zone and z_bmalloc functions using tagheap + */ + +#include "tagheap.h" +#include +#include +#include +#include +#include + +#undef Z_Malloc +#undef Z_Free +#undef Z_Realloc +#undef Z_Calloc +#undef Z_FreeTags + +bool NC_FreeSomeMemoryForTail(); + + /// Z_BMalloc replacement + void * Z_BMalloc(block_memory_alloc_s *zone) { + unsigned tag = zone->tag | 0x80000000; // Ensure MSB is set for tail allocation + auto ptr = TH_alloc(zone->size, tag); + if (!ptr) { + // Out of memory - this is fatal + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Z_BMalloc: Out of memory trying to allocate %zu bytes with tag %u\n", zone->size, tag); + #endif + assert(false);exit(-1); + } + return ptr; + } + + void Z_BFree(struct block_memory_alloc_s *pzone UNUSED, void* p){ + TH_free((uint8_t *)p); +} + +/** + * Z_Malloc replacement + */ +void * Z_Malloc(int size, int tag, void **user) { + tag |= 0x80000000; // Ensure MSB is set for tail allocation + // We need to also allocate space for the user pointer + auto ptr = TH_alloc(size+sizeof(void**),tag); + if (ptr) { + auto userptr = (void **)ptr; + ptr += sizeof(void**); + if (user) { + *userptr=user; + *user = ptr; + } else { + *((void **)userptr)=(void **)2; // Mark as in use but unowned + } + } else { + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Z_Malloc: Out of memory trying to allocate %d bytes with tag %u\n", size, tag); + #endif + assert(false);exit(-1); + } + #if TH_CANARY_ENABLED == 1 + if (TH_checkhealth_verbose()==false) { + printf("FATAL: Heap corrupted after Z_Malloc of %d bytes with tag %u\n",size,tag); + assert(false);exit(-1); + } + #endif + return ptr; +} + +/** + * Z_Free replacement + */ +void Z_Free(void *ptr) { + auto userptr = (void **)((uint8_t *)ptr - sizeof(void**)); + if (userptr > (void**)0x100) { + void **user = (void **)(*userptr); + if (user && user > (void **)0x100) + *user = nullptr; + } + + TH_free((uint8_t *)ptr-sizeof(void**)); +} + + + +/** + * Z_Realloc replacement + */ +void * Z_Realloc(void *ptr, size_t n, int tag UNUSED, void **user UNUSED) { + auto newptr = TH_realloc((uint8_t *)ptr,n); + if (!newptr) { + // Out of memory - this is fatal + #if TH_CANARY_ENABLED == 1 + printf("FATAL: Z_Realloc: Out of memory trying to reallocate %zu bytes\n", n); + #endif + assert(false);exit(-1); + } + return newptr; +} + +/** + * Z_Calloc replacement + */ +void * Z_Calloc(size_t count, size_t size, int tag, void **user) { + auto ptr = Z_Malloc(size*count, tag, user); + if (ptr) { + // Zero out the memory + auto realsize = ((size*count + 3) & ~3); // Align to 4 bytes + auto ptr32 = (uint32_t *)ptr; + for (unsigned n=0; n < (realsize >> 2); n++) { + ptr32[n] = 0; + } + } + #if TH_CANARY_ENABLED == 1 + if (TH_checkhealth_verbose()==false) { + printf("FATAL: Heap corrupted after Z_Calloc of %zu bytes with tag %u\n",size*count,tag); + assert(false);exit(-1); + } + #endif + return ptr; +} + +/** + * Z_FreeTags replacement + */ +void Z_FreeTags(int lowtag, int hightag) { + unsigned tag = 0x80000000; + th_memblock_t *block = FIRSTBLOCK; + unsigned lt = lowtag | 0x80000000; + unsigned ht = hightag | 0x80000000; + while (block) { + auto userptr = (uint8_t *)(block+1); + auto ptr = userptr + sizeof(void**); + if (lt <= block->tag && block->tag <= ht) { + Z_Free(ptr); + } + block = block->next; + } +} + +void Z_Init() { + TH_init(); +} + +void Z_CheckHeap() { + // NOP for now +} + +/** + * Z_Strdup replacement lifted directly from original z_zone.cc + */ +char* Z_Strdup(const char* s) +{ + const unsigned int len = strlen(s); + + if(!len) + return NULL; + + char* ptr = (char *)Z_Malloc(len+1, PU_STATIC, NULL); + + if(ptr) + strcpy(ptr, s); + + return ptr; +} + + diff --git a/source/doom_iwad.c b/gamedata/original/doom_iwad.cc similarity index 73% rename from source/doom_iwad.c rename to gamedata/original/doom_iwad.cc index da988456..9ffc8fa3 100644 --- a/source/doom_iwad.c +++ b/gamedata/original/doom_iwad.cc @@ -1,9 +1,9 @@ -#pragma GCC optimize ("-O0") +//#pragma GCC optimize ("-O0") #include "doom_iwad.h" //Uncomment which edition you want to compile -//#include "iwad/doom1.c" -#include "iwad/doomu.c" +#include "iwad/doom1.c" +//#include "iwad/doomu.c" //#include "iwad/doom2.c" //#include "iwad/tnt.c" //#include "iwad/plutonia.c" diff --git a/source/iwad/doom1.c b/gamedata/original/iwad/doom1.c similarity index 100% rename from source/iwad/doom1.c rename to gamedata/original/iwad/doom1.c diff --git a/gamedata/original/w_nc.cc b/gamedata/original/w_nc.cc new file mode 100644 index 00000000..96092f3a --- /dev/null +++ b/gamedata/original/w_nc.cc @@ -0,0 +1,75 @@ +#include "../newcache/newcache.h" +#include "../include/annotations.h" +#include "../include/r_defs.h" + +extern unsigned char gfx_stbar[]; +extern line_t junk; + + + +const void * W_CacheLumpNum(int lumpnum); +int W_LumpLength(int lumpnum); +int W_GetNumForName (const char* name); +int W_CheckNumForName(const char *name); +const char *W_GetNameForNum(int lumpnum); +void W_Init(void); +void ExtractFileBase(const char* path, char* dest); + +// Simple wrappers mapping to W_ functions in the newcache namespace +const uint8_t * NC_CacheLumpNum(int lumpnum) +{ + // Violent hack ! + if (lumpnum == STBAR_LUMP_NUM){ + return (const uint8_t *)gfx_stbar; + } + if (lumpnum == JUNK_LUMP_NUM){ + return (const uint8_t *)&junk; + } + return (const uint8_t *)W_CacheLumpNum(lumpnum); +} + +int NC_LumpLength(int lumpnum) +{ + return W_LumpLength(lumpnum); +} + +int NC_GetNumForName (const char* name) +{ + return W_GetNumForName(name); +} + +int NC_CheckNumForName(const char *name) +{ + return W_CheckNumForName(name); +} + +const char* NC_GetNameForNum(int lump, char buffer[8]) +{ + const char* name = W_GetNameForNum(lump); + strncpy(buffer,name,8); + return buffer; +} + +void NC_Init(void) +{ + W_Init(); +} + +void NC_ExtractFileBase(const char* path, char* dest) +{ + ExtractFileBase(path, dest); +} + +const uint8_t* NC_Pin(int lumpnum) +{ + return NC_CacheLumpNum(lumpnum); // We can assume it is constant in this implementaiton +} +void NC_Unpin(int lumpnum UNUSED) +{ + // No-op for this simple cache +} + +void NC_FlushCache(void) +{ + // No-op for this simple cache +} \ No newline at end of file diff --git a/source/w_wad.c b/gamedata/original/w_wad.cc similarity index 98% rename from source/w_wad.c rename to gamedata/original/w_wad.cc index 90e22d21..4604159b 100644 --- a/source/w_wad.c +++ b/gamedata/original/w_wad.cc @@ -50,9 +50,9 @@ #include "doom_iwad.h" #ifdef __GNUG__ -#pragma implementation "w_wad.h" + #endif -#include "w_wad.h" + #include "lprintf.h" #include "global_data.h" @@ -253,6 +253,10 @@ void W_Init(void) // CPhipps - start with nothing W_AddFile(); + + const wadinfo_t *header = (const wadinfo_t *)doom_iwad; + + printf("*** Number of lumps in file: %d ***\n",header->numlumps); } // diff --git a/source/z_bmalloc.c b/gamedata/original/z_bmalloc.cc similarity index 87% rename from source/z_bmalloc.c rename to gamedata/original/z_bmalloc.cc index 020a8dbc..c7608fde 100644 --- a/source/z_bmalloc.c +++ b/gamedata/original/z_bmalloc.cc @@ -43,12 +43,12 @@ typedef struct bmalpool_s { struct bmalpool_s *nextpool; size_t blocks; - byte used[0]; + uint8_t used[0]; } bmalpool_t; __inline static void* getelem(bmalpool_t *p, size_t size, size_t n) { - return (((byte*)p) + sizeof(bmalpool_t) + sizeof(byte)*(p->blocks) + size*n); + return (((uint8_t*)p) + sizeof(bmalpool_t) + sizeof(uint8_t)*(p->blocks) + size*n); } __inline static PUREFUNC int iselem(const bmalpool_t *pool, size_t size, const void* p) @@ -67,9 +67,9 @@ enum { unused_block = 0, used_block = 1}; void* Z_BMalloc(struct block_memory_alloc_s *pzone) { - register bmalpool_t **pool = (bmalpool_t **)&(pzone->firstpool); + bmalpool_t **pool = (bmalpool_t **)&(pzone->firstpool); while (*pool != NULL) { - byte *p = memchr((*pool)->used, unused_block, (*pool)->blocks); // Scan for unused marker + uint8_t *p = (uint8_t *)memchr((*pool)->used, unused_block, (*pool)->blocks); // Scan for unused marker if (p) { int n = p - (*pool)->used; (*pool)->used[n] = used_block; @@ -83,7 +83,7 @@ void* Z_BMalloc(struct block_memory_alloc_s *pzone) // CPhipps: Allocate new memory, initialised to 0 - *pool = newpool = Z_Calloc(sizeof(*newpool) + (sizeof(byte) + pzone->size)*(pzone->perpool), + *pool = newpool = (bmalpool_t *)Z_Calloc(sizeof(*newpool) + (sizeof(uint8_t) + pzone->size)*(pzone->perpool), 1, pzone->tag, NULL); newpool->nextpool = NULL; // NULL = (void*)0 so this is redundant @@ -96,7 +96,7 @@ void* Z_BMalloc(struct block_memory_alloc_s *pzone) void Z_BFree(struct block_memory_alloc_s *pzone, void* p) { - register bmalpool_t **pool = (bmalpool_t**)&(pzone->firstpool); + bmalpool_t **pool = (bmalpool_t**)&(pzone->firstpool); while (*pool != NULL) { int n = iselem(*pool, pzone->size, p); diff --git a/source/z_zone.c b/gamedata/original/z_zone.cc similarity index 89% rename from source/z_zone.c rename to gamedata/original/z_zone.cc index d4de6a27..33e98e4b 100644 --- a/source/z_zone.c +++ b/gamedata/original/z_zone.cc @@ -26,6 +26,12 @@ #include "doomtype.h" #include "lprintf.h" +#ifdef RPT_MALLOC +#undef Z_Malloc +#undef Z_Free +#undef Z_Realloc +#undef Z_Calloc +#endif // // ZONE MEMORY ALLOCATION @@ -77,7 +83,7 @@ void Z_Init (void) //We can now alloc all of the rest fo the memory. do { - mainzone = malloc(heapSize); + mainzone = (memzone_t *)malloc(heapSize); heapSize -= 4; } while(mainzone == NULL); @@ -89,9 +95,9 @@ void Z_Init (void) // set the entire zone to one free block mainzone->blocklist.next = mainzone->blocklist.prev = - block = (memblock_t *)( (byte *)mainzone + sizeof(memzone_t) ); + block = (memblock_t *)( (uint8_t *)mainzone + sizeof(memzone_t) ); - mainzone->blocklist.user = (void *)mainzone; + mainzone->blocklist.user = (void **)mainzone; mainzone->blocklist.tag = PU_STATIC; mainzone->rover = block; @@ -115,7 +121,7 @@ void Z_Free (void* ptr) if(ptr == NULL) return; - block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); + block = (memblock_t *) ( (uint8_t *)ptr - sizeof(memblock_t)); if (block->user > (void **)0x100) { @@ -133,7 +139,7 @@ void Z_Free (void* ptr) #ifndef GBA running_count -= block->size; - printf("Free: %d\n", running_count); + //printf("Free: %d\n", running_count); #endif other = block->prev; @@ -223,7 +229,7 @@ void* Z_Malloc(int size, int tag, void **user) // the rover can be the base block base = base->prev; - Z_Free ((byte *)rover+sizeof(memblock_t)); + Z_Free ((uint8_t *)rover+sizeof(memblock_t)); base = base->next; rover = base->next; } @@ -240,7 +246,7 @@ void* Z_Malloc(int size, int tag, void **user) if (extra > MINFRAGMENT) { // there will be a free fragment after the allocated block - newblock = (memblock_t *) ((byte *)base + size ); + newblock = (memblock_t *) ((uint8_t *)base + size ); newblock->size = extra; // NULL indicates free block. @@ -258,7 +264,7 @@ void* Z_Malloc(int size, int tag, void **user) { // mark as an in use block base->user = user; - *(void **)user = (void *) ((byte *)base + sizeof(memblock_t)); + *(void **)user = (void *) ((uint8_t *)base + sizeof(memblock_t)); } else { @@ -266,7 +272,7 @@ void* Z_Malloc(int size, int tag, void **user) I_Error ("Z_Malloc: an owner is required for purgable blocks"); // mark as in use, but unowned - base->user = (void *)2; + base->user = (void **)2; } base->tag = tag; @@ -276,10 +282,10 @@ void* Z_Malloc(int size, int tag, void **user) #ifndef GBA running_count += base->size; - printf("Alloc: %d (%d)\n", base->size, running_count); + //printf("Alloc: %d (%d)\n", base->size, running_count); #endif - return (void *) ((byte *)base + sizeof(memblock_t)); + return (void *) ((uint8_t *)base + sizeof(memblock_t)); } void* Z_Calloc(size_t count, size_t size, int tag, void **user) @@ -300,7 +306,7 @@ char* Z_Strdup(const char* s) if(!len) return NULL; - char* ptr = Z_Malloc(len+1, PU_STATIC, NULL); + char* ptr = (char *)Z_Malloc(len+1, PU_STATIC, NULL); if(ptr) strcpy(ptr, s); @@ -346,7 +352,7 @@ void Z_FreeTags(int lowtag, int hightag) continue; if (block->tag >= lowtag && block->tag <= hightag) - Z_Free ( (byte *)block+sizeof(memblock_t)); + Z_Free ( (uint8_t *)block+sizeof(memblock_t)); } } @@ -365,7 +371,7 @@ void Z_CheckHeap (void) break; } - if ( (byte *)block + block->size != (byte *)block->next) + if ( (uint8_t *)block + block->size != (uint8_t *)block->next) I_Error ("Z_CheckHeap: block size does not touch the next block\n"); if ( block->next->prev != block) diff --git a/gamedata/scripts/c_array_to_bin.py b/gamedata/scripts/c_array_to_bin.py new file mode 100755 index 00000000..92b73223 --- /dev/null +++ b/gamedata/scripts/c_array_to_bin.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import re +import sys +from pathlib import Path + +def extract_c_array_bytes(c_text, array_name): + """ + Extract uint8_t values from a C array definition. + Returns a list of integers (0–255). + """ + + # Find the array body: array_name[...] = { ... }; + pattern = rf"{array_name}\s*\[.*?\]\s*=\s*\{{(.*?)\}};" + match = re.search(pattern, c_text, re.S) + + if not match: + raise ValueError(f"Array '{array_name}' not found") + + body = match.group(1) + + # Remove C comments + body = re.sub(r"//.*?$", "", body, flags=re.M) + body = re.sub(r"/\*.*?\*/", "", body, flags=re.S) + + # Find numbers: hex or decimal + tokens = re.findall(r"0x[0-9a-fA-F]+|\d+", body) + + bytes_out = [] + for t in tokens: + value = int(t, 16) if t.startswith("0x") else int(t) + if not 0 <= value <= 255: + raise ValueError(f"Value out of uint8_t range: {value}") + bytes_out.append(value) + + return bytes_out + + +def main(): + if len(sys.argv) != 4: + print("Usage:") + print(" c_array_to_bin.py ") + sys.exit(1) + + input_c = Path(sys.argv[1]) + array_name = sys.argv[2] + output_bin = Path(sys.argv[3]) + + c_text = input_c.read_text(encoding="utf-8", errors="ignore") + data = extract_c_array_bytes(c_text, array_name) + + output_bin.write_bytes(bytes(data)) + print(f"Wrote {len(data)} bytes to {output_bin}") + + +if __name__ == "__main__": + main() diff --git a/gamedata/scripts/wad2cc.py b/gamedata/scripts/wad2cc.py new file mode 100644 index 00000000..604e2131 --- /dev/null +++ b/gamedata/scripts/wad2cc.py @@ -0,0 +1,73 @@ +import sys +import struct +import os + +class FileLump: + def __init__(self, filepos, size, name_high, name_low): + self.filepos = filepos + self.size = size + self.name_high = name_high + self.name_low = name_low + +def main(): + if len(sys.argv) != 2: + print("Usage: python wad2cc.py ") + sys.exit(1) + + wadfile = sys.argv[1] + base = os.path.splitext(os.path.basename(wadfile))[0] + ccfile = f"{base}_lumps.cc" + hfile = f"{base}_lumps.h" + guard = f"_{base.upper()}_LUMPS_H_" + + with open(wadfile, "rb") as f: + header = f.read(12) + if len(header) < 12: + print("Invalid WAD file: header too short") + sys.exit(1) + ident, numlumps, infotableofs = struct.unpack('<4sii', header) + f.seek(infotableofs) + lumps = [] + for _ in range(numlumps): + lumpdata = f.read(16) + if len(lumpdata) < 16: + print("Invalid WAD file: lump directory too short") + sys.exit(1) + filepos, size, name_low, name_high = struct.unpack('\n\n") + h.write(f"#define WADLUMPS {numlumps}\n\n") + h.write(f"extern int32_t filepos[WADLUMPS];\n") + h.write(f"extern int32_t lumpsize[WADLUMPS];\n") + h.write(f"extern uint32_t lumpname_high[WADLUMPS];\n") + h.write(f"extern uint32_t lumpname_low[WADLUMPS];\n\n") + h.write(f"#endif // {guard}\n") + + # Write .cc file + with open(ccfile, "w") as cc: + cc.write(f'#include "{hfile}"\n') + cc.write('#include "annotations.h"\n\n') + cc.write(f"int32_t CONSTMEM filepos[WADLUMPS] = {{\n") + for lump in lumps: + cc.write(f" {lump.filepos},\n") + cc.write("};\n\n") + cc.write(f"int32_t CONSTMEM lumpsize[WADLUMPS] = {{\n") + for lump in lumps: + cc.write(f" {lump.size},\n") + cc.write("};\n\n") + cc.write(f"uint32_t CONSTMEM lumpname_high[WADLUMPS] = {{\n") + for lump in lumps: + cc.write(f" 0x{lump.name_high:08x},\n") + cc.write("};\n\n") + cc.write(f"uint32_t CONSTMEM lumpname_low[WADLUMPS] = {{\n") + for lump in lumps: + cc.write(f" 0x{lump.name_low:08x},\n") + cc.write("};\n") + +if __name__ == "__main__": + main() diff --git a/gbadoom1.wad b/gbadoom1.wad new file mode 120000 index 00000000..2c509281 --- /dev/null +++ b/gbadoom1.wad @@ -0,0 +1 @@ +./gamedata/minimem/gbadoom1.wad \ No newline at end of file diff --git a/guardmalloc/Makefile b/guardmalloc/Makefile new file mode 100644 index 00000000..beadd886 --- /dev/null +++ b/guardmalloc/Makefile @@ -0,0 +1,96 @@ +CXX := clang++ +CXXFLAGS := -std=c++17 -Wall -Wextra -g +LDFLAGS := + +# Build directory +BUILD_DIR := build +TEST_DIR := test + +# Source files +GUARDMALLOC_SRC := guardmalloc.cc +CORRECTUSE_SRC := $(TEST_DIR)/gmalloc_correctuse.cc +USEAFTERFREE_SRC := $(TEST_DIR)/gmalloc_useafterfree.cc +BUFFEROVERFLOW_SRC := $(TEST_DIR)/gmalloc_bufferoverflow.cc +BUFFERUNDERFLOW_SRC := $(TEST_DIR)/gmalloc_bufferunderflow.cc +TEST_SRC := $(TEST_DIR)/gmalloc_test.cc + +# Object files +GUARDMALLOC_OBJ := $(BUILD_DIR)/guardmalloc.o +CORRECTUSE_OBJ := $(BUILD_DIR)/gmalloc_correctuse.o +USEAFTERFREE_OBJ := $(BUILD_DIR)/gmalloc_useafterfree.o +BUFFEROVERFLOW_OBJ := $(BUILD_DIR)/gmalloc_bufferoverflow.o +BUFFERUNDERFLOW_OBJ := $(BUILD_DIR)/gmalloc_bufferunderflow.o +TEST_OBJ := $(BUILD_DIR)/gmalloc_test.o + +# Executables +CORRECTUSE_BIN := $(BUILD_DIR)/gmalloc_correctuse +USEAFTERFREE_BIN := $(BUILD_DIR)/gmalloc_useafterfree +BUFFEROVERFLOW_BIN := $(BUILD_DIR)/gmalloc_bufferoverflow +BUFFERUNDERFLOW_BIN := $(BUILD_DIR)/gmalloc_bufferunderflow +TEST_BIN := $(BUILD_DIR)/gmalloc_test + +# Phony targets +.PHONY: all test clean + +# Default target +all: $(BUILD_DIR) $(CORRECTUSE_BIN) $(USEAFTERFREE_BIN) $(BUFFEROVERFLOW_BIN) $(BUFFERUNDERFLOW_BIN) $(TEST_BIN) + +# Create build directory +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +# Build guardmalloc object file +$(GUARDMALLOC_OBJ): $(GUARDMALLOC_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Build gmalloc_correctuse executable +$(CORRECTUSE_BIN): $(CORRECTUSE_OBJ) $(GUARDMALLOC_OBJ) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(CORRECTUSE_OBJ) $(GUARDMALLOC_OBJ) -o $@ $(LDFLAGS) + +# Build gmalloc_useafterfree executable +$(USEAFTERFREE_BIN): $(USEAFTERFREE_OBJ) $(GUARDMALLOC_OBJ) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(USEAFTERFREE_OBJ) $(GUARDMALLOC_OBJ) -o $@ $(LDFLAGS) + +# Build gmalloc_bufferoverflow executable +$(BUFFEROVERFLOW_BIN): $(BUFFEROVERFLOW_OBJ) $(GUARDMALLOC_OBJ) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(BUFFEROVERFLOW_OBJ) $(GUARDMALLOC_OBJ) -o $@ $(LDFLAGS) + +# Build gmalloc_bufferunderflow executable +$(BUFFERUNDERFLOW_BIN): $(BUFFERUNDERFLOW_OBJ) $(GUARDMALLOC_OBJ) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $(BUFFERUNDERFLOW_OBJ) $(GUARDMALLOC_OBJ) -o $@ $(LDFLAGS) + +# Build gmalloc_test executable +$(TEST_BIN): $(TEST_OBJ) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) $< -o $@ $(LDFLAGS) + +# Compile source files to object files +$(CORRECTUSE_OBJ): $(CORRECTUSE_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(USEAFTERFREE_OBJ): $(USEAFTERFREE_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(BUFFEROVERFLOW_OBJ): $(BUFFEROVERFLOW_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(BUFFERUNDERFLOW_OBJ): $(BUFFERUNDERFLOW_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(TEST_OBJ): $(TEST_SRC) | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Run tests (depends on building all targets first) +test: all + ./$(TEST_BIN) + +# Clean build artifacts +clean: + rm -rf $(BUILD_DIR) + +# Help target +help: + @echo "Available targets:" + @echo " all - Build all test programs (default)" + @echo " test - Run the test harness (builds all first)" + @echo " clean - Remove all build artifacts" + @echo " help - Display this help message" diff --git a/guardmalloc/README.md b/guardmalloc/README.md new file mode 100644 index 00000000..344b4a67 --- /dev/null +++ b/guardmalloc/README.md @@ -0,0 +1,147 @@ +# gmalloc - Guard Page Memory Allocator + +A custom memory allocator for debugging buffer overflows, underflows, and use-after-free errors using POSIX memory protection features (mmap/mprotect). + +## Features + +- **Guard Pages**: Detects buffer overflows and underflows by placing protected memory pages before and after allocations +- **Use-After-Free Detection**: Protects freed memory to catch accidental reads/writes to deallocated regions +- **Leak Reporting**: Tracks allocated memory and reports leaks on program termination +- **High-Level Interface**: Simple C-style allocation with file/line tracking + +## Architecture + +### Memory Layout + +Each allocation has the following layout: + +``` +[Lower Guard Page (4KB)] [Header | User Data (page-aligned)] [Upper Guard Page (4KB)] +``` + +- **Lower Guard Page**: Protected with `PROT_NONE`, catches buffer underflows +- **Header**: 24-byte metadata (size, file, line) +- **User Data**: Requested size, followed by padding to page boundary +- **Upper Guard Page**: Protected with `PROT_NONE`, catches buffer overflows + +### Page Alignment + +The critical insight is that `mprotect()` requires page-aligned addresses. The implementation ensures: + +```cpp +size_t data_region_size = (sizeof(AllocHeader) + size + pagesize - 1) & ~(pagesize - 1); +``` + +This rounds up the combined size of header + user data to the next page boundary, ensuring the upper guard page starts at a page-aligned address. + +## Building and Testing + +### Build + +```bash +make # Build all test programs +make test # Build and run test suite +make clean # Clean build artifacts +``` + +### Test Suite + +The `gmalloc_test` harness runs 4 tests, each demonstrating a memory safety feature: + +1. **gmalloc_correctuse**: Tests proper allocation/deallocation cycle + - Expected: Exit code 0 + - Result: ✓ PASS + +2. **gmalloc_useafterfree**: Intentional use-after-free detection + - Allocates memory, frees it, then attempts to read freed memory + - Expected: Crash with SIGSEGV or SIGBUS + - Result: ✓ PASS (Signal 10 - SIGBUS) + +3. **gmalloc_bufferoverflow**: Buffer overflow detection + - Allocates 100 bytes, writes beyond the upper guard page + - Expected: Crash with SIGSEGV or SIGBUS + - Result: ✓ PASS (Signal 10 - SIGBUS) + +4. **gmalloc_bufferunderflow**: Buffer underflow detection + - Allocates 5 integers, writes before the lower guard page + - Expected: Crash with SIGSEGV or SIGBUS + - Result: ✓ PASS (Signal 10 - SIGBUS) + +### Running Tests + +```bash +cd /Users/brian/src/GBADoom/guardmalloc +make test +``` + +Expected output: +``` +=== gmalloc Test Harness === + +Test 1: gmalloc_correctuse (should succeed) + ✓ PASS: gmalloc_correctuse exited successfully + +Test 2: gmalloc_useafterfree (should crash with SIGSEGV) + ✓ PASS: gmalloc_useafterfree crashed with signal 10 as expected + +Test 3: gmalloc_bufferoverflow (upper guard page detection) + ✓ PASS: gmalloc_bufferoverflow crashed with signal 10 as expected + +Test 4: gmalloc_bufferunderflow (should crash with SIGSEGV/SIGBUS) + ✓ PASS: gmalloc_bufferunderflow crashed with signal 10 as expected + +=== Test Results === +Passed: 4/4 tests + +✓ All tests passed! +``` + +## Usage + +Replace standard malloc/free with gmalloc/gfree: + +```cpp +#include "guardmalloc.h" + +int *arr = (int*)GMALLOC(100 * sizeof(int)); +// ... use array ... +GFREE(arr); + +// Check for leaks before exit +gcheckleaks(); +``` + +The `GMALLOC` and `GFREE` macros automatically track file and line number for better debugging output. + +## Implementation Details + +### Files + +- `guardmalloc.h`: Header with public API +- `guardmalloc.cc`: Implementation of gmalloc, gfree, and leak tracking +- `gmalloc_test.cc`: Test harness using fork/exec/waitpid +- `gmalloc_correctuse.cc`: Correct usage test +- `gmalloc_useafterfree.cc`: Use-after-free detection test +- `gmalloc_bufferoverflow.cc`: Buffer overflow detection test +- `gmalloc_bufferunderflow.cc`: Buffer underflow detection test +- `Makefile`: Build system + +### Key Functions + +- `gmalloc(size, file, line)`: Allocate memory with guard pages +- `gfree(ptr, file, line)`: Free memory and protect against use-after-free +- `gcheckleaks()`: Report any remaining allocated memory +- `gflushfreed()`: Actually deallocate freed memory + +## Platform Notes + +- Requires POSIX mmap/mprotect support +- Page size is detected at runtime via `sysconf(_SC_PAGESIZE)` +- Tested on macOS and Linux +- Uses signal SIGBUS (signal 10) for page protection violations (platform-dependent) + +## Limitations + +- High memory overhead due to guard pages (minimum 2x for small allocations) +- Not thread-safe; use only for single-threaded debugging +- Should not be used in production; intended for development/testing diff --git a/guardmalloc/guardmalloc.cc b/guardmalloc/guardmalloc.cc new file mode 100644 index 00000000..de17d0a9 --- /dev/null +++ b/guardmalloc/guardmalloc.cc @@ -0,0 +1,109 @@ +#include "guardmalloc.h" +// implementation of guardmalloc functions +#include +#include +#include +#include +#include + +struct AllocHeader { + size_t size; + const char* file; + int line; +}; + +std::set allocations; +std::set freed_allocations; + +void *gmalloc(size_t size, const char *file, int line) { + size_t pagesize = sysconf(_SC_PAGESIZE); + // Layout: [lower guard page] [header + user data rounded to page] [upper guard page] + // This ensures the upper guard page is at a page-aligned address for mprotect + size_t data_region_size = (sizeof(AllocHeader) + size + pagesize - 1) & ~(pagesize - 1); + size_t total_size = pagesize + data_region_size + pagesize; + + // Allocate memory with mmap + void *ptr = mmap(NULL, total_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ptr == MAP_FAILED) { + perror("mmap failed"); + return NULL; + } + + // Set up guard pages (addresses MUST be page-aligned for mprotect) + mprotect(ptr, pagesize, PROT_NONE); // Lower guard page (starts at 0, page-aligned) + mprotect((char*)ptr + pagesize + data_region_size, pagesize, PROT_NONE); // Upper guard page (page-aligned by construction) + + // Store allocation header + AllocHeader *header = (AllocHeader*)((char*)ptr + pagesize); + header->size = size; + header->file = file; + header->line = line; + + // Track the allocation + allocations.insert(header); + + return (char*)header + sizeof(AllocHeader); +} + +void gfree(void *ptr, const char *file, int line) { + if (!ptr) return; + + AllocHeader *header = (AllocHeader*)((char*)ptr - sizeof(AllocHeader)); + size_t pagesize = sysconf(_SC_PAGESIZE); + // Data region size (header + user data) rounded up to page boundary + size_t data_region_size = (header->size + sizeof(AllocHeader) + pagesize - 1) & ~(pagesize - 1); + + // Update header from where it was freed + header->file = file; + header->line = line; + + // Fill the rest of the memory with a pattern to make it easier to debug use-after-free + memset((char*)header + sizeof(AllocHeader), 0xDE, header->size); + + // Protect the memory to catch use-after-free (protect data region) + mprotect((char*)header, data_region_size, PROT_NONE); + + // "Free" the memory by tracking it (we don't actually unmap it here) + freed_allocations.insert(header); + allocations.erase(header); +} + +void gcheckleaks() { + for (const auto& alloc : allocations) { + printf("Memory leak detected: %zu bytes allocated at %s:%d\n", + alloc->size, alloc->file, alloc->line); + } +} + +static size_t get_aligned_size(AllocHeader* alloc) { + size_t pagesize = sysconf(_SC_PAGESIZE); + // Data region size (header + user data) rounded up to page boundary + size_t data_region_size = (alloc->size + sizeof(AllocHeader) + pagesize - 1) & ~(pagesize - 1); + return pagesize + data_region_size + pagesize; // lower guard + data + upper guard +} + +void gflushfreed() { + for (const auto& alloc : freed_allocations) { + size_t pagesize = sysconf(_SC_PAGESIZE); + size_t aligned_size = get_aligned_size(alloc); + + // Unmap the memory + if (munmap((char*)alloc - pagesize, aligned_size) != 0) { + perror("munmap failed"); + } + } + freed_allocations.clear(); +} + +int ggetnumfreed() { + return freed_allocations.size(); +} + +size_t ggetpendingfreesize() { + size_t total = 0; + for (const auto& alloc : freed_allocations) { + total += get_aligned_size(alloc); + } + return total; +} \ No newline at end of file diff --git a/guardmalloc/guardmalloc.h b/guardmalloc/guardmalloc.h new file mode 100644 index 00000000..fbf4cd4b --- /dev/null +++ b/guardmalloc/guardmalloc.h @@ -0,0 +1,32 @@ +#ifndef __guardmalloc_h__ +#define __guardmalloc_h__ +// This library dfines guardmalloc, a debugging malloc library +// that helps detect memory overwrites and leaks. +// It does this by allocating extra "guard" pages before +// and after each allocation, and by keeping track of +// all allocated blocks. +// Allocation is done using anonymous mmap() to get page-aligned +// memory regions, and mprotect() to set guard pages +// as inaccessible. Any access to these guard pages +// will cause a segmentation fault, which can be caught +// using a debugger to find the source of the memory error. +// Free will not free the pages, but will read and write +// protect them to catch any use-after-free errors. +// This library is intended for use in debugging and testing, +// and should not be used in production code due to its +// performance overhead and increased memory usage. It is +// built using standard POSIX system calls, so it should be +// portable to any POSIX-compliant operating system. +#include +void *gmalloc(size_t size, const char *file, int line); +void gfree(void *ptr, const char *file, int line); + +#define GMALLOC(size) gmalloc(size, __FILE__, __LINE__) +#define GFREE(ptr) gfree(ptr, __FILE__, __LINE__) + +void gcheckleaks(); +void gflushfreed(); +int ggetnumfreed(); +size_t getpendingfreesize(); + +#endif // __guardmalloc_h__ \ No newline at end of file diff --git a/guardmalloc/test/gmalloc_bufferoverflow.cc b/guardmalloc/test/gmalloc_bufferoverflow.cc new file mode 100644 index 00000000..4784ea45 --- /dev/null +++ b/guardmalloc/test/gmalloc_bufferoverflow.cc @@ -0,0 +1,45 @@ +#include "../guardmalloc.h" +#include +#include +#include +#include + +// This program intentionally crashes due to a buffer overflow +// (writing past the end of allocated memory into the upper guard page) +int main() { + printf("Testing upper guard page detection (buffer overflow)...\n"); + fflush(stdout); + + // Get page size to know how far we need to overflow + size_t pagesize = sysconf(_SC_PAGESIZE); + + // Allocate 100 bytes + // This will be rounded up to the next page boundary for the data region + // Data region = header (24 bytes) + user data (100 bytes) = 124 bytes + // Rounded up to nearest page: ceil(124 / pagesize) * pagesize + char *ptr = (char*)GMALLOC(100); + if (!ptr) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + // Write to the allocated memory + ptr[0] = 'A'; + printf("Allocated and wrote to memory\n"); + + // Intentionally write past the allocation into the guard page + printf("Attempting to write past allocated memory (buffer overflow)...\n"); + fflush(stdout); + + // Write far past the boundary + // The data region is one page in size (header + 100 bytes rounded up) + // We need to write past pagesize bytes of the user data pointer to hit the guard + // Since header is 24 bytes before user data, we need to write to indices >= (pagesize - 24) + for (int i = pagesize; i < (int)(pagesize + 100); i++) { + ptr[i] = 'X'; + } + + printf("Should not reach here!\n"); + fflush(stdout); + return 0; +} diff --git a/guardmalloc/test/gmalloc_bufferunderflow.cc b/guardmalloc/test/gmalloc_bufferunderflow.cc new file mode 100644 index 00000000..9692f730 --- /dev/null +++ b/guardmalloc/test/gmalloc_bufferunderflow.cc @@ -0,0 +1,31 @@ +#include "../guardmalloc.h" +#include +#include + +// This program intentionally crashes due to a buffer underflow +// (writing before the start of allocated memory into the lower guard page) +int main() { + printf("Testing lower guard page detection (buffer underflow)...\n"); + fflush(stdout); + + // Allocate a small buffer + int *ptr = (int*)GMALLOC(sizeof(int) * 5); + if (!ptr) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + // Write to the allocated memory + for (int i = 0; i < 5; i++) { + ptr[i] = i * 10; + } + printf("Allocated and initialized array of 5 integers\n"); + + // Intentionally write before the start of the allocation into the guard page + // This should cause a crash + printf("Attempting to write before allocated memory (buffer underflow)...\n"); + fflush(stdout); + ptr[-10] = 999; // Writing before the allocated region + + return 0; +} diff --git a/guardmalloc/test/gmalloc_correctuse.cc b/guardmalloc/test/gmalloc_correctuse.cc new file mode 100644 index 00000000..649f134c --- /dev/null +++ b/guardmalloc/test/gmalloc_correctuse.cc @@ -0,0 +1,75 @@ +#include "../guardmalloc.h" +#include +#include +#include + +// This program uses gmalloc correctly +int main() { + printf("Testing correct gmalloc usage...\n"); + fflush(stdout); + + size_t pagesize = sysconf(_SC_PAGESIZE); + size_t alloc_size = pagesize + 500; + + // Allocate memory for pagesize + 500 bytes + char *ptr = (char*)GMALLOC(alloc_size); + if (!ptr) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + printf("Allocated %zu bytes\n", alloc_size); + + // Write to the beginning of the allocation + printf("Writing to beginning of allocation...\n"); + for (size_t i = 0; i < 100; i++) { + ptr[i] = 'A' + (i % 26); + } + + // Verify writes at the beginning + printf("Verifying beginning: "); + for (size_t i = 0; i < 10; i++) { + printf("%c", ptr[i]); + } + printf("...\n"); + + // Write to the end of the allocation + printf("Writing to end of allocation...\n"); + for (size_t i = alloc_size - 100; i < alloc_size; i++) { + ptr[i] = 'Z' - ((i - (alloc_size - 100)) % 26); + } + + // Verify writes at the end + printf("Verifying end: "); + for (size_t i = alloc_size - 10; i < alloc_size; i++) { + printf("%c", ptr[i]); + } + printf("...\n"); + + // Allocate additional memory to verify multiple allocations + int *arr = (int*)GMALLOC(sizeof(int) * 10); + if (!arr) { + fprintf(stderr, "Failed to allocate array\n"); + return 1; + } + + // Initialize and use the array + for (int i = 0; i < 10; i++) { + arr[i] = i * 10; + } + printf("Allocated and initialized array of 10 integers\n"); + + // Free both allocations + GFREE(arr); + printf("Freed integer array memory\n"); + + GFREE(ptr); + printf("Freed large allocation memory\n"); + + // Check for memory leaks + gcheckleaks(); + printf("All memory properly freed!\n"); + fflush(stdout); + + return 0; +} diff --git a/guardmalloc/test/gmalloc_test.cc b/guardmalloc/test/gmalloc_test.cc new file mode 100644 index 00000000..8afad583 --- /dev/null +++ b/guardmalloc/test/gmalloc_test.cc @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include + +// Test harness that runs both gmalloc test programs and reports results +int main() { + printf("=== gmalloc Test Harness ===\n\n"); + + int total_tests = 4; + int tests_passed = 0; + + // Test 1: Correct usage should succeed (exit code 0, no crash) + printf("Test 1: gmalloc_correctuse (should succeed)\n"); + printf(" Running gmalloc_correctuse...\n"); + + pid_t pid1 = fork(); + if (pid1 == 0) { + // Child process: run the correct usage test + execl("./build/gmalloc_correctuse", "gmalloc_correctuse", NULL); + perror("Failed to exec gmalloc_correctuse"); + exit(1); + } else if (pid1 > 0) { + // Parent process: wait for child + int status; + waitpid(pid1, &status, 0); + + if (WIFEXITED(status)) { + int exit_code = WEXITSTATUS(status); + if (exit_code == 0) { + printf(" ✓ PASS: gmalloc_correctuse exited successfully\n\n"); + tests_passed++; + } else { + printf(" ✗ FAIL: gmalloc_correctuse exited with code %d\n\n", exit_code); + } + } else if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + printf(" ✗ FAIL: gmalloc_correctuse was killed by signal %d\n\n", signal); + } + } else { + perror("fork failed"); + return 1; + } + + // Test 2: Use-after-free should crash (killed by SIGSEGV) + printf("Test 2: gmalloc_useafterfree (should crash with SIGSEGV)\n"); + printf(" Running gmalloc_useafterfree...\n"); + + pid_t pid2 = fork(); + if (pid2 == 0) { + // Child process: run the use-after-free test + execl("./build/gmalloc_useafterfree", "gmalloc_useafterfree", NULL); + perror("Failed to exec gmalloc_useafterfree"); + exit(1); + } else if (pid2 > 0) { + // Parent process: wait for child + int status; + waitpid(pid2, &status, 0); + + if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + // Accept both SIGSEGV (11) and SIGBUS (10) since different systems handle + // page protection violations differently + if (signal == SIGSEGV || signal == SIGBUS) { + printf(" ✓ PASS: gmalloc_useafterfree crashed with signal %d as expected\n\n", signal); + tests_passed++; + } else { + printf(" ✗ FAIL: gmalloc_useafterfree was killed by signal %d (expected SIGSEGV or SIGBUS)\n\n", signal); + } + } else if (WIFEXITED(status)) { + int exit_code = WEXITSTATUS(status); + printf(" ✗ FAIL: gmalloc_useafterfree exited with code %d (expected crash)\n\n", exit_code); + } + } else { + perror("fork failed"); + return 1; + } + + // Test 3: Buffer overflow - currently this doesn't trigger the guard page + // The implementation may have issues with upper guard page detection + printf("Test 3: gmalloc_bufferoverflow (upper guard page detection)\n"); + printf(" Running gmalloc_bufferoverflow...\n"); + + pid_t pid3 = fork(); + if (pid3 == 0) { + // Child process: run the buffer overflow test + execl("./build/gmalloc_bufferoverflow", "gmalloc_bufferoverflow", NULL); + perror("Failed to exec gmalloc_bufferoverflow"); + exit(1); + } else if (pid3 > 0) { + // Parent process: wait for child + int status; + waitpid(pid3, &status, 0); + + if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + // Accept both SIGSEGV (11) and SIGBUS (10) since different systems handle + // page protection violations differently + if (signal == SIGSEGV || signal == SIGBUS) { + printf(" ✓ PASS: gmalloc_bufferoverflow crashed with signal %d as expected\n\n", signal); + tests_passed++; + } else { + printf(" ✗ FAIL: gmalloc_bufferoverflow was killed by signal %d (expected SIGSEGV or SIGBUS)\n\n", signal); + } + } else if (WIFEXITED(status)) { + int exit_code = WEXITSTATUS(status); + printf(" ✗ FAIL: gmalloc_bufferoverflow exited with code %d (expected crash)\n\n", exit_code); + } + } else { + perror("fork failed"); + return 1; + } + + // Test 4: Buffer underflow should crash with SIGSEGV/SIGBUS + printf("Test 4: gmalloc_bufferunderflow (should crash with SIGSEGV/SIGBUS)\n"); + printf(" Running gmalloc_bufferunderflow...\n"); + + pid_t pid4 = fork(); + if (pid4 == 0) { + // Child process: run the buffer underflow test + execl("./build/gmalloc_bufferunderflow", "gmalloc_bufferunderflow", NULL); + perror("Failed to exec gmalloc_bufferunderflow"); + exit(1); + } else if (pid4 > 0) { + // Parent process: wait for child + int status; + waitpid(pid4, &status, 0); + + if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + // Accept both SIGSEGV (11) and SIGBUS (10) since different systems handle + // page protection violations differently + if (signal == SIGSEGV || signal == SIGBUS) { + printf(" ✓ PASS: gmalloc_bufferunderflow crashed with signal %d as expected\n\n", signal); + tests_passed++; + } else { + printf(" ✗ FAIL: gmalloc_bufferunderflow was killed by signal %d (expected SIGSEGV or SIGBUS)\n\n", signal); + } + } else if (WIFEXITED(status)) { + int exit_code = WEXITSTATUS(status); + printf(" ✗ FAIL: gmalloc_bufferunderflow exited with code %d (expected crash)\n\n", exit_code); + } + } else { + perror("fork failed"); + return 1; + } + + // Summary + printf("=== Test Results ===\n"); + printf("Passed: %d/%d tests\n", tests_passed, total_tests); + + if (tests_passed == total_tests) { + printf("\n✓ All tests passed!\n"); + return 0; + } else { + printf("\n✗ Some tests failed!\n"); + return 1; + } +} diff --git a/guardmalloc/test/gmalloc_useafterfree.cc b/guardmalloc/test/gmalloc_useafterfree.cc new file mode 100644 index 00000000..add8e918 --- /dev/null +++ b/guardmalloc/test/gmalloc_useafterfree.cc @@ -0,0 +1,30 @@ +#include "../guardmalloc.h" +#include +#include + +// This program intentionally crashes due to use-after-free +int main() { + printf("Testing use-after-free detection...\n"); + fflush(stdout); + + // Allocate some memory + int *ptr = (int*)GMALLOC(sizeof(int) * 10); + if (!ptr) { + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + // Write to the allocated memory + ptr[0] = 42; + printf("Allocated and wrote to memory: ptr[0] = %d\n", ptr[0]); + + // Free the memory + GFREE(ptr); + printf("Freed the memory\n"); + + // Intentionally try to read from freed memory - this should crash + printf("Attempting to read from freed memory: ptr[0] = %d\n", ptr[0]); + fflush(stdout); + + return 0; +} diff --git a/include/annotations.h b/include/annotations.h new file mode 100644 index 00000000..116945e7 --- /dev/null +++ b/include/annotations.h @@ -0,0 +1,47 @@ +#ifndef __annotations_h +#define __annotations_h +#include +#include + +#define UNUSED __attribute__((unused)) + +#ifndef GBA +#define MAYBE_UNUSED UNUSED +#else +#define MAYBE_UNUSED +#endif + +#ifdef __chess__ +#define CONSTMEMAREA chess_storage(PMEM) +#define CONSTMEM chess_storage(PMEM%2) +#else +#define CONSTMEMAREA +#define CONSTMEM +#endif + +// Slightly ugly hack allowing address translation for constmem access +template +struct ConstMemArray { +public: + ConstMemArray(const T CONSTMEMAREA *ptr ) : data(ptr) { + static_assert(sizeof(T)==4); + } + + // Read-only accessor + const T operator[](size_t index) const { + + uintptr_t ptr = (uintptr_t)&data[index]; + #ifdef XLATADDR + ptr >>= 1; + #endif + return *((uint32_t CONSTMEMAREA *)ptr); + } + +private: + const T CONSTMEMAREA *data; // must be public for aggregate initialization + +}; + + +#endif /* annotations.h */ + diff --git a/include/config.h b/include/config.h index c74ce31e..8c9ad37c 100644 --- a/include/config.h +++ b/include/config.h @@ -74,7 +74,7 @@ //#define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 +#define HAVE_STDLIB_H 0 /* Define to 1 if you have the header file. */ //#define HAVE_STRINGS_H 1 @@ -171,7 +171,7 @@ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ -/* Define to 1 if your processor stores words with the most significant byte +/* Define to 1 if your processor stores words with the most significant uint8_t first (like Motorola and SPARC, unlike Intel and VAX). */ /* #undef WORDS_BIGENDIAN */ diff --git a/include/d_englsh.h b/include/d_englsh.h index bfd3f31d..58228cdd 100644 --- a/include/d_englsh.h +++ b/include/d_englsh.h @@ -44,25 +44,25 @@ #define PRESSKEY "press a key." #define PRESSYN "press A or B." #define QUITMSG "are you sure you want to\nquit this great game?" -#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY -#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY -#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY -#define SAVEDEAD "you can't save if\nyou aren't playing!\n\n"PRESSKEY -#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN -#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN +#define LOADNET "you can't do load while in a net game!\n\n" PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n" PRESSKEY +#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n" PRESSKEY +#define SAVEDEAD "you can't save if\nyou aren't playing!\n\n" PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n" PRESSYN +#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n" PRESSYN #define NEWGAME \ "you can't start a new game\n"\ - "while in a network game.\n\n"PRESSKEY + "while in a network game.\n\n" PRESSKEY #define NIGHTMARE \ "are you sure? this skill level\n"\ - "isn't even remotely fair.\n\n"PRESSYN + "isn't even remotely fair.\n\n" PRESSYN #define SWSTRING \ "this is the shareware version\n"\ "of doom. You need to order\n"\ - "the entire trilogy.\n\n"PRESSKEY + "the entire trilogy.\n\n" PRESSKEY #define MSGOFF "Messages OFF" #define MSGON "Messages ON" @@ -73,9 +73,9 @@ #define HIGHDETAIL "High Detail." #define LOWDETAIL "Low Detail." -#define NETEND "you can't end a netgame!\n\n"PRESSKEY -#define ENDGAME "are you sure you want to\nend the game?\n\n"PRESSYN -#define RESTARTLEVEL "restart the level?\n\n"PRESSYN +#define NETEND "you can't end a netgame!\n\n" PRESSKEY +#define ENDGAME "are you sure you want to\nend the game?\n\n" PRESSYN +#define RESTARTLEVEL "restart the level?\n\n" PRESSYN #define DOSY "(press y to quit)" diff --git a/include/d_main.h b/include/d_main.h index a39093c4..b54af5aa 100644 --- a/include/d_main.h +++ b/include/d_main.h @@ -35,7 +35,7 @@ #define __D_MAIN__ #include "d_event.h" -#include "w_wad.h" + #ifdef __GNUG__ #pragma interface @@ -49,6 +49,9 @@ extern const boolean nomusicparm; extern const boolean nodrawers; // Called by IO functions when input is detected. +#ifdef __cplusplus +extern "C" +#endif void D_PostEvent(event_t* ev); // Demo stuff diff --git a/include/d_think.h b/include/d_think.h index 750bd5fa..8519090f 100644 --- a/include/d_think.h +++ b/include/d_think.h @@ -40,6 +40,22 @@ #pragma interface #endif +/* Forward declarations of types used in some prototypes */ +typedef struct mobj_s mobj_t; +typedef struct player_s player_t; +typedef struct pspdef_s pspdef_t; +typedef struct scroll_s scroll_t; +typedef struct thinker_s thinker_t; +typedef struct ceiling_s ceiling_t; +typedef struct vldoor_s vldoor_t; +typedef struct plat_s plat_t; +typedef struct floormove_s floormove_t; +typedef struct elevator_s elevator_t; +typedef struct fireflicker_s fireflicker_t; +typedef struct glow_s glow_t; +typedef struct lightflash_s lightflash_t; +typedef struct strobe_s strobe_t; + /* * Experimental stuff. * To compile this as "ANSI C with classes" @@ -47,23 +63,45 @@ * action functions cleanly. */ // killough 11/98: convert back to C instead of C++ -typedef void (*actionf_t)(); -//typedef void (*actionf_v)(); -//typedef void (*actionf_p1)( void* ); -//typedef void (*actionf_p2)( void*, void* ); +//typedef void (*actionf_t)(); +typedef void (*actionf_v)(); +typedef void (*actionf_p1)( player_t* ); +typedef void (*actionf_p2)( player_t*, pspdef_t* ); +typedef void (*actionf_m1)( mobj_t* ); +typedef void (*actionf_s1)( scroll_t* ); +typedef void (*actionf_t1)( thinker_t*); +typedef void (*actionf_c1)( ceiling_t* ); +typedef void (*actionf_d1)( vldoor_t* ); +typedef void (*actionf_l1)( plat_t* ); +typedef void (*actionf_f1)( floormove_t* ); +typedef void (*actionf_e1)( elevator_t* ); +typedef void (*actionf_r1)( fireflicker_t* ); +typedef void (*actionf_g1)( glow_t* ); +typedef void (*actionf_i1)( lightflash_t* ); +typedef void (*actionf_o1)( strobe_t* ); /* Note: In d_deh.c you will find references to these * wherever code pointers and function handlers exist */ -/* typedef union { - actionf_p1 acp1; - actionf_v acv; - actionf_p2 acp2; + actionf_v acv; /// No parameters + actionf_p1 acp1; /// player_t * + actionf_p2 acp2; /// player_t *, pspdef_t * + actionf_m1 acm1; /// mobj_t * + actionf_s1 acs1; /// scroll_t * + actionf_t1 act1; /// thinker_t* + actionf_c1 acc1; /// ceiling_t * + actionf_d1 acd1; /// vldoor_t * + actionf_l1 acl1; /// plat_t * + actionf_f1 acf1; /// floormove_t * + actionf_e1 ace1; /// elevator_t * + actionf_r1 acr1; /// fireflicker_t * + actionf_g1 acg1; /// glow_t * + actionf_i1 aci1; /// lightflash_t * + actionf_o1 aco1; /// strobe_t * } actionf_t; -*/ /* Historically, "think_t" is yet another * function pointer to a routine to handle diff --git a/include/d_ticcmd.h b/include/d_ticcmd.h index 4469dfb1..866565c8 100644 --- a/include/d_ticcmd.h +++ b/include/d_ticcmd.h @@ -52,8 +52,8 @@ typedef struct signed char sidemove; /* *2048 for move */ signed short angleturn; /* <<16 for angle delta */ short consistancy; /* checks for net game */ - byte chatchar; - byte buttons; + uint8_t chatchar; + uint8_t buttons; } ticcmd_t; #endif diff --git a/include/doomdata.h b/include/doomdata.h index 28e2a18f..75ede83d 100644 --- a/include/doomdata.h +++ b/include/doomdata.h @@ -195,7 +195,7 @@ typedef struct { //This is used at runtime so not packed. -//compiler uses byte access on packed structs. +//compiler uses uint8_t access on packed structs. typedef struct { short x; // Partition line from (x,y) to x+dx,y+dy) diff --git a/include/doomdef.h b/include/doomdef.h index 416b268c..8b58ef15 100644 --- a/include/doomdef.h +++ b/include/doomdef.h @@ -49,11 +49,13 @@ #include "z_zone.h" #include -#include +//#include #include #include #include +#include "annotations.h" + // this should go here, not in makefile/configure.ac -- josh #ifndef O_BINARY #define O_BINARY 0 @@ -140,10 +142,11 @@ typedef enum { // at the intermission screen, the game final animation, or a demo. typedef enum { - GS_LEVEL, - GS_INTERMISSION, - GS_FINALE, - GS_DEMOSCREEN + GS_NOTSET=-1, + GS_LEVEL=1, + GS_INTERMISSION=2, + GS_FINALE=3, + GS_DEMOSCREEN=4 } gamestate_t; // diff --git a/include/doomtype.h b/include/doomtype.h index fe7fd58b..2e6dea51 100644 --- a/include/doomtype.h +++ b/include/doomtype.h @@ -47,7 +47,7 @@ typedef bool boolean; #else typedef enum {false, true} boolean; #endif -typedef unsigned char byte; +//typedef unsigned char uint8_t; #endif //e6y diff --git a/include/g_game.h b/include/g_game.h index 9d1e0b89..1ad3fa4a 100644 --- a/include/g_game.h +++ b/include/g_game.h @@ -65,7 +65,7 @@ void G_DoCompleted(void); void G_ReadDemoTiccmd(ticcmd_t *cmd); void G_DoWorldDone(void); void G_Compatibility(void); -const byte *G_ReadOptions(const byte *demo_p); /* killough 3/1/98 - cph: const byte* */ +const uint8_t *G_ReadOptions(const uint8_t *demo_p); /* killough 3/1/98 - cph: const uint8_t* */ void G_PlayerReborn(int player); void G_DoVictory(void); void G_BuildTiccmd (ticcmd_t* cmd); // CPhipps - move decl to header diff --git a/include/gba_functions.h b/include/gba_functions.h index c413e112..621d7268 100644 --- a/include/gba_functions.h +++ b/include/gba_functions.h @@ -10,6 +10,8 @@ #include #endif +#include "annotations.h" + inline static CONSTFUNC int IDiv32 (int a, int b) { @@ -55,7 +57,7 @@ inline static void BlockSet(void* dest, volatile unsigned int val, const unsigne #endif } -inline static void ByteCopy(byte* dest, const byte* src, unsigned int count) +inline static void ByteCopy(uint8_t* dest, const uint8_t* src, unsigned int count) { do { @@ -63,7 +65,7 @@ inline static void ByteCopy(byte* dest, const byte* src, unsigned int count) } while(--count); } -inline static void ByteSet(byte* dest, byte val, unsigned int count) +inline static void ByteSet(uint8_t* dest, uint8_t val, unsigned int count) { do { @@ -71,7 +73,7 @@ inline static void ByteSet(byte* dest, byte val, unsigned int count) } while(--count); } -inline static void* ByteFind(byte* mem, byte val, unsigned int count) +inline static void* ByteFind(uint8_t* mem, uint8_t val, unsigned int count) { do { @@ -84,17 +86,18 @@ inline static void* ByteFind(byte* mem, byte val, unsigned int count) return NULL; } -inline static void SaveSRAM(const byte* eeprom, unsigned int size, unsigned int offset) + +inline static void SaveSRAM(const uint8_t* eeprom MAYBE_UNUSED, unsigned int size MAYBE_UNUSED, unsigned int offset MAYBE_UNUSED) { #ifdef GBA - ByteCopy((byte*)(0xE000000 + offset), eeprom, size); + ByteCopy((uint8_t*)(0xE000000 + offset), eeprom, size); #endif } -inline static void LoadSRAM(byte* eeprom, unsigned int size, unsigned int offset) +inline static void LoadSRAM(uint8_t* eeprom MAYBE_UNUSED, unsigned int size MAYBE_UNUSED, unsigned int offse MAYBE_UNUSED) { #ifdef GBA - ByteCopy(eeprom, (byte*)(0xE000000 + offset), size); + ByteCopy(eeprom, (uint8_t*)(0xE000000 + offset), size); #endif } diff --git a/include/global_data.h b/include/global_data.h index ef28b1ee..0d40beab 100644 --- a/include/global_data.h +++ b/include/global_data.h @@ -31,10 +31,15 @@ #include "v_video.h" -#include "w_wad.h" + #include "wi_stuff.h" +#include "../newcache/newcache.h" + +#include "annotations.h" + + typedef struct globals_t { @@ -141,7 +146,7 @@ const char* finaleflat; // made static const int castnum; int casttics; -const state_t* caststate; +const state_t * caststate; int castframes; int castonmelee; @@ -156,10 +161,10 @@ boolean castdeath; //g_game.c //****************************************************************************** -const byte *demobuffer; /* cph - only used for playback */ +CachedBuffer demobuffer; /* cph - only used for playback */ int demolength; // check for overrun (missing DEMOMARKER) -const byte *demo_p; +CachedBuffer demo_p; gameaction_t gameaction; gamestate_t gamestate; @@ -191,7 +196,7 @@ skill_t d_skill; int d_episode; int d_map; -byte savegameslot; // Slot to load if gameaction == ga_loadgame +uint8_t savegameslot; // Slot to load if gameaction == ga_loadgame boolean secretexit; @@ -211,7 +216,7 @@ boolean haswolflevels;// jff 4/18/98 wolf levels present //****************************************************************************** // font sets -const patch_t* hu_font[HU_FONTSIZE]; +hu_fontlist_t hu_font; // widgets hu_textline_t w_title; @@ -235,8 +240,8 @@ int basetime; //i_video.c //****************************************************************************** -const unsigned char* current_pallete; -const unsigned char* pallete_lump; +CachedBuffer current_pallete; +CachedBuffer pallete_lump; int newpal; //****************************************************************************** @@ -341,16 +346,16 @@ fixed_t tmdropoffz; // dropoff on other side of line you're crossing // keep track of the line that lowers the ceiling, // so missiles don't explode against sky hack walls -const line_t *ceilingline; -const line_t *blockline; /* killough 8/11/98: blocking linedef */ -const line_t *floorline; /* killough 8/1/98: Highest touched floor */ +Cached ceilingline; +Cached blockline; /* killough 8/11/98: blocking linedef */ +Cached floorline; /* killough 8/1/98: Highest touched floor */ int tmunstuck; /* killough 8/1/98: whether to allow unsticking */ // keep track of special lines as they are hit, // but don't process them until the move is proven valid // 1/11/98 killough: removed limit on special lines crossed -const line_t *spechit[4]; // new code -- killough +Cached spechit[4]; // new code -- killough int numspechit; @@ -359,7 +364,7 @@ msecnode_t* sector_list; // phares 3/16/98 /* killough 8/2/98: make variables static */ fixed_t bestslidefrac; -const line_t* bestslideline; +Cached bestslideline; mobj_t* slidemo; fixed_t tmxmove; fixed_t tmymove; @@ -449,9 +454,9 @@ fixed_t bulletslope; // int numvertexes; -const vertex_t *vertexes; +CachedBuffer vertexes; -const seg_t *segs; +CachedBuffer segs; int numsectors; sector_t *sectors; @@ -463,7 +468,7 @@ subsector_t *subsectors; int numlines; -const line_t *lines; +CachedBuffer lines; linedata_t* linedata; @@ -482,10 +487,10 @@ side_t *sides; int bmapwidth, bmapheight; // size in mapblocks // killough 3/1/98: remove blockmap limit internally: -const short *blockmap; // was short -- killough +CachedBuffer blockmap; // was short -- killough // offsets in blockmap are from here -const short *blockmaplump; // was short -- killough +CachedBuffer blockmaplump; // was short -- killough fixed_t bmaporgx, bmaporgy; // origin of block map @@ -501,7 +506,7 @@ mobj_t **blocklinks; // for thing chains // int rejectlump;// cph - store reject lump num if cached -const byte *rejectmatrix; // cph - const* +CachedBuffer rejectmatrix; // cph - const* // Maintain single and multi player starting spots. mapthing_t playerstarts[MAXPLAYERS]; @@ -564,7 +569,7 @@ int firstspritelump, lastspritelump, numspritelumps; int numtextures; //Store last lookup and return that if they match. -const char* tex_lookup_last_name; +char tex_lookup_last_name[8]; int tex_lookup_last_num; @@ -677,26 +682,25 @@ boolean mus_paused; unsigned int st_needrefresh; // 0-9, tall numbers -const patch_t* tallnum[10]; +Cached tallnum[10]; // 0-9, short, yellow (,different!) numbers -const patch_t* shortnum[10]; +Cached shortnum[10]; // tall % sign -const patch_t* tallpercent; - -const patch_t* keys[NUMCARDS]; +Cached tallpercent; +Cached keys[NUMCARDS]; // face status patches -const patch_t* faces[ST_NUMFACES]; +Cached faces[ST_NUMFACES]; //e6y: status bar background -const patch_t* stbarbg; +Cached stbarbg; unsigned int stbar_len; // weapon ownership patches -const patch_t* arms[6][2]; +Cached arms[6][2]; // ready-weapon widget st_number_t w_ready; @@ -779,7 +783,7 @@ int cnt_par; int cnt_pause; // 0-9 graphic -const patch_t* num[10]; +Cached num[10]; int sp_state; diff --git a/include/global_init.h b/include/global_init.h index c4d348cc..ddef698b 100644 --- a/include/global_init.h +++ b/include/global_init.h @@ -21,7 +21,7 @@ _g->ftom_zoommul = FRACUNIT; // how far the window zooms each tic (fb coords) //****************************************************************************** _g->wipegamestate = GS_DEMOSCREEN; -_g->oldgamestate = -1; +_g->oldgamestate = (gamestate_t)-1; //****************************************************************************** diff --git a/include/hu_lib.h b/include/hu_lib.h index 7f8d2996..a0125a4a 100644 --- a/include/hu_lib.h +++ b/include/hu_lib.h @@ -36,6 +36,10 @@ // We are referring to patches. #include "r_defs.h" #include "v_video.h" //jff 2/16/52 include color range defs +#include "../newcache/newcache.h" +#include "hu_stuff.h" + +typedef Cached hu_fontlist_t[HU_FONTSIZE]; /* background and foreground screen numbers @@ -65,7 +69,7 @@ typedef struct int x; int y; - const patch_t** f; // font + hu_fontlist_t f; // font int sc; // start character //const char *cr; //jff 2/16/52 output color range // Proff - Made this an int again. Needed for OpenGL @@ -149,7 +153,7 @@ void HUlib_initTextLine (hu_textline_t *t, int x, int y, - const patch_t *f, + hu_fontlist_t f, int sc); // returns success @@ -172,7 +176,7 @@ void HUlib_initSText int x, int y, int h, - const patch_t *font, + hu_fontlist_t font, int startchar, //jff 2/16/98 add color range parameter boolean* on ); diff --git a/include/i_system.h b/include/i_system.h index 425eecb3..a76f9bf1 100644 --- a/include/i_system.h +++ b/include/i_system.h @@ -37,6 +37,7 @@ #ifdef __GNUG__ #pragma interface #endif +#include boolean I_StartDisplay(void); void I_EndDisplay(void); diff --git a/include/i_system_e32.h b/include/i_system_e32.h index e483d11b..d72906c3 100644 --- a/include/i_system_e32.h +++ b/include/i_system_e32.h @@ -6,6 +6,7 @@ #ifndef HEADER_ISYSTEME32 #define HEADER_ISYSTEME32 +#include "../newcache/newcache.h" #ifdef __cplusplus extern "C" { @@ -20,25 +21,25 @@ int I_GetVideoWidth_e32(); int I_GetVideoHeight_e32(); -void I_FinishUpdate_e32(const byte* srcBuffer, const byte* pallete, const unsigned int width, const unsigned int height); +void I_FinishUpdate_e32(const uint8_t* srcBuffer, const uint8_t* pallete, const unsigned int width, const unsigned int height); -void I_SetPallete_e32(const byte* pallete); +void I_SetPallete_e32(CachedBuffer pallete); void I_ProcessKeyEvents(); int I_GetTime_e32(void); -void I_Error (const char *error, ...); - void I_Quit_e32(); unsigned short* I_GetBackBuffer(); -unsigned short* I_GetFrontBuffer(); + +void I_Error (const char *error, ...); #ifdef __cplusplus } #endif + #endif diff --git a/include/i_system_win.h b/include/i_system_win.h index 4624e639..3893b6fd 100644 --- a/include/i_system_win.h +++ b/include/i_system_win.h @@ -6,6 +6,8 @@ #include #include +#include "annotations.h" + //GBA Keys #define KEYD_A 1 #define KEYD_B 2 @@ -18,11 +20,14 @@ #define KEYD_START 9 #define KEYD_SELECT 10 +//using std::uint8_t; + extern "C" { -extern const byte gammatable[2][32]; +extern const uint8_t gammatable[2][32]; +/* typedef enum { ev_keydown, @@ -39,7 +44,7 @@ typedef struct int data2; // mouse/joystick x move int data3; // mouse/joystick y move } event_t; - +*/ void D_PostEvent(event_t* ev); } @@ -49,7 +54,7 @@ extern unsigned char* pl; class DoomWindow : public QWidget { protected: - void paintEvent(QPaintEvent *event) override + void paintEvent(QPaintEvent *event UNUSED) override { QPainter p(this); @@ -68,7 +73,7 @@ class DoomWindow : public QWidget p.drawImage(this->rect(), i, i.rect()); } - void closeEvent(QCloseEvent *event) override + void closeEvent(QCloseEvent *event UNUSED) override { exit(0); } diff --git a/include/info.h b/include/info.h index 1bcec0bf..c22028cc 100644 --- a/include/info.h +++ b/include/info.h @@ -39,6 +39,8 @@ /* Needed for action function pointer handling. */ #include "d_think.h" +#include "annotations.h" + /******************************************************************** * Sprite name enumeration - must match info.c * ********************************************************************/ @@ -196,7 +198,7 @@ typedef enum * States (frames) enumeration -- must match info.c * ********************************************************************/ -typedef enum +typedef enum { S_NULL, S_LIGHTDONE, @@ -1247,7 +1249,6 @@ typedef enum S_MUSHROOM, /* killough 10/98: mushroom explosion effect */ NUMSTATES /* Counter of how many there are */ - } statenum_t; /******************************************************************** @@ -1265,7 +1266,7 @@ typedef struct } state_t; /* these are in info.c */ -extern const state_t states[NUMSTATES]; +extern const state_t states[NUMSTATES]; extern const char* const sprnames[]; /* 1/17/98 killough - CPhipps - const */ /******************************************************************** diff --git a/include/lprintf.h b/include/lprintf.h index 8eacb30d..3872f6a2 100644 --- a/include/lprintf.h +++ b/include/lprintf.h @@ -50,6 +50,9 @@ extern int lprintf(OutputLevels pri, const char *fmt, ...); /* killough 3/20/98: add const * killough 4/25/98: add gcc attributes * cphipps 01/11- moved from i_system.h */ + #ifdef __cplusplus +extern "C" +#endif void I_Error (const char *error, ...); #endif diff --git a/include/m_fixed.h b/include/m_fixed.h index 66841d7e..ecca2a85 100644 --- a/include/m_fixed.h +++ b/include/m_fixed.h @@ -38,6 +38,7 @@ #include "doomtype.h" #include "m_recip.h" +#include /* * Fixed point, 32bit as 16.16. @@ -70,7 +71,12 @@ inline static int CONSTFUNC D_abs(fixed_t x) /* CPhipps - made __inline__ to inline, as specified in the gcc docs * Also made const */ -fixed_t CONSTFUNC FixedMul(fixed_t a, fixed_t b); +static inline fixed_t CONSTFUNC FixedMul(fixed_t a, fixed_t b) +{ + return (fixed_t)((int64_t) a*b >> FRACBITS); // TODO: funnel shifter +} + + /* * Fixed Point Division @@ -78,12 +84,73 @@ fixed_t CONSTFUNC FixedMul(fixed_t a, fixed_t b); /* CPhipps - made __inline__ to inline, as specified in the gcc docs * Also made const */ + +#define SW_DIV //For testing + +#if defined(__chess__) || defined(SW_DIV) + +// Return the lower 32 bits of the division result - don't care about overflow +static inline int32_t idiv64(int64_t numerator, int32_t denominator) { + if (denominator == 0) { + // Undefined; choose your own behavior + return 0; + } + + // Compute sign of the result: 1 if signs differ, 0 otherwise + int32_t s_mask = ((numerator >> 63) ^ (denominator >> 31)); + + // Branchless absolute value for 64-bit numerator + int64_t n_mask = numerator >> 63; // all 1s if negative, 0 if non-negative + uint64_t u_num = (uint64_t)((numerator ^ n_mask) - n_mask); + + // For 32 bit we have built in abs + #ifdef __chess__ + uint32_t u_den = abs(denominator); + #else + uint32_t u_den = D_abs(denominator); + #endif + + // Long division: shift-subtract + uint64_t r = 0; + + uint32_t unum_h = u_num >> 32; + uint32_t unum_l = u_num; + uint32_t q32 = 0; + + // First part we don't need to store a result for + for (int i = 31; i >= 0; --i) { + r = (r << 1) | ((unum_h >> i) & 1u); + if (r >= u_den) { + r -= u_den; + } + } + + // We only need the lower 32 bits of the quotient + for (int i = 31; i >= 0; --i) { + r = (r << 1) | ((unum_l >> i) & 1u); + if (r >= u_den) { + r -= u_den; + q32 |= (uint32_t)1 << i; + } + } + + // Apply sign branchlessly: if sign == 1, return -q32; else return q32 + // Using two's complement trick: -x == (~x + 1) + int32_t result = (int32_t)((q32 ^ s_mask) - s_mask); + + return result; +} +#endif inline static fixed_t CONSTFUNC FixedDiv(fixed_t a, fixed_t b) { #ifndef GBA +#if !defined(__chess__) && !defined(SW_DIV) return ((unsigned)D_abs(a)>>14) >= (unsigned)D_abs(b) ? ((a^b)>>31) ^ INT_MAX : (fixed_t)(((int_64_t) a << FRACBITS) / b); +#else + return ((unsigned)D_abs(a)>>14) >= (unsigned)D_abs(b) ? ((a^b)>>31) ^ INT_MAX : idiv64((int_64_t) a << FRACBITS,b); +#endif // __chess__ #else unsigned int udiv64_arm (unsigned int a, unsigned int b, unsigned int c); @@ -103,7 +170,7 @@ inline static fixed_t CONSTFUNC FixedDiv(fixed_t a, fixed_t b) q = -q; return q; -#endif +#endif // GBA } /* CPhipps - diff --git a/include/m_recip.h b/include/m_recip.h index edc666c6..2d9f2203 100644 --- a/include/m_recip.h +++ b/include/m_recip.h @@ -1,6 +1,8 @@ #ifndef RECIP_H #define RECIP_H -const extern unsigned int reciprocalTable[]; +#include "annotations.h" + +extern ConstMemArray reciprocalTable; #endif // RECIP_H diff --git a/include/m_swap.h b/include/m_swap.h index 7ee3f803..e8cafbc8 100644 --- a/include/m_swap.h +++ b/include/m_swap.h @@ -51,7 +51,7 @@ /* Endianess handling. */ -/* cph - First the macros to do the actual byte swapping */ +/* cph - First the macros to do the actual uint8_t swapping */ /* leban * rather than continue the confusing tradition of redefining the diff --git a/include/p_enemy.h b/include/p_enemy.h index a0707b35..a0ac4c53 100644 --- a/include/p_enemy.h +++ b/include/p_enemy.h @@ -38,6 +38,7 @@ #include "p_mobj.h" + void P_NoiseAlert (mobj_t *target, mobj_t *emmiter); void P_SpawnBrainTargets(void); /* killough 3/26/98: spawn icon landings */ @@ -46,6 +47,10 @@ typedef struct brain_t int easy, targeton; } brain_t; +// Forward declarations of types used in some prototypes +typedef struct player_s player_t; +typedef struct pspdef_s pspdef_t; + // ******************************************************************** // Function addresses or Code Pointers // ******************************************************************** @@ -54,65 +59,71 @@ typedef struct brain_t // allows more extensive changes (see d_deh.c) // Doesn't work with g++, needs actionf_p1 -void A_Explode(); -void A_Pain(); -void A_PlayerScream(); -void A_Fall(); -void A_XScream(); -void A_Look(); -void A_Chase(); -void A_FaceTarget(); -void A_PosAttack(); -void A_Scream(); -void A_SPosAttack(); -void A_VileChase(); -void A_VileStart(); -void A_VileTarget(); -void A_VileAttack(); -void A_StartFire(); -void A_Fire(); -void A_FireCrackle(); -void A_Tracer(); -void A_SkelWhoosh(); -void A_SkelFist(); -void A_SkelMissile(); -void A_FatRaise(); -void A_FatAttack1(); -void A_FatAttack2(); -void A_FatAttack3(); -void A_BossDeath(); -void A_CPosAttack(); -void A_CPosRefire(); -void A_TroopAttack(); -void A_SargAttack(); -void A_HeadAttack(); -void A_BruisAttack(); -void A_SkullAttack(); -void A_Metal(); -void A_SpidRefire(); -void A_BabyMetal(); -void A_BspiAttack(); -void A_Hoof(); -void A_CyberAttack(); -void A_PainAttack(); -void A_PainDie(); -void A_KeenDie(); -void A_BrainPain(); -void A_BrainScream(); -void A_BrainDie(); -void A_BrainAwake(); -void A_BrainSpit(); -void A_SpawnSound(); -void A_SpawnFly(); -void A_BrainExplode(); -void A_Die(); -void A_Detonate(); /* killough 8/9/98: detonate a bomb or other device */ -void A_Mushroom(); /* killough 10/98: mushroom effect */ -void A_Spawn(); // killough 11/98 -void A_Turn(); // killough 11/98 -void A_Face(); // killough 11/98 -void A_Scratch(); // killough 11/98 -void A_PlaySound(); // killough 11/98 -void A_RandomJump(); // killough 11/98 +// Forward-declare types used in some prototypes +void A_Explode(mobj_t *thingy); +void A_Pain(mobj_t *actor); +void A_PlayerScream(mobj_t *mo); +void A_Fall(mobj_t *actor); +void A_XScream(mobj_t *actor); +void A_Look(mobj_t *actor); +void A_Chase(mobj_t *actor); +void A_FaceTarget(mobj_t *actor); +void A_PosAttack(mobj_t *actor); +void A_Scream(mobj_t *actor); +void A_SPosAttack(mobj_t *actor); +void A_VileChase(mobj_t *actor); +void A_VileStart(mobj_t *actor); +void A_VileTarget(mobj_t *actor); +void A_VileAttack(mobj_t *actor); +void A_StartFire(mobj_t *actor); +void A_Fire(mobj_t *actor); +void A_FireCrackle(mobj_t *actor); +void A_Tracer(mobj_t *actor); +void A_SkelWhoosh(mobj_t *actor); +void A_SkelFist(mobj_t *actor); +void A_SkelMissile(mobj_t *actor); +void A_FatRaise(mobj_t *actor); +void A_FatAttack1(mobj_t *actor); +void A_FatAttack2(mobj_t *actor); +void A_FatAttack3(mobj_t *actor); +void A_BossDeath(mobj_t *mo); +void A_CPosAttack(mobj_t *actor); +void A_CPosRefire(mobj_t *actor); +void A_TroopAttack(mobj_t *actor); +void A_SargAttack(mobj_t *actor); +void A_HeadAttack(mobj_t *actor); +void A_BruisAttack(mobj_t *actor); +void A_SkullAttack(mobj_t *actor); +void A_Metal(mobj_t *mo); +void A_SpidRefire(mobj_t *actor); +void A_BabyMetal(mobj_t *mo); +void A_BspiAttack(mobj_t *actor); +void A_Hoof(mobj_t *mo); +void A_CyberAttack(mobj_t *actor); +void A_PainAttack(mobj_t *actor); +void A_PainDie(mobj_t *actor); +void A_KeenDie(mobj_t *mo); +void A_BrainPain(mobj_t *mo); +void A_BrainScream(mobj_t *mo); +void A_BrainDie(mobj_t *mo); +void A_BrainAwake(mobj_t *mo); +void A_BrainSpit(mobj_t *mo); +void A_SpawnSound(mobj_t *mo); +void A_SpawnFly(mobj_t *mo); +void A_BrainExplode(mobj_t *mo); +void A_Die(mobj_t *actor); +void A_Detonate(mobj_t *mo); /* killough 8/9/98: detonate a bomb or other device */ +void A_Mushroom(mobj_t *actor); /* killough 10/98: mushroom effect */ +void A_Spawn(mobj_t *mo); // killough 11/98 +void A_Turn(mobj_t *mo); // killough 11/98 +void A_Face(mobj_t *mo); // killough 11/98 +void A_Scratch(mobj_t *mo); // killough 11/98 +void A_PlaySound(mobj_t *mo); // killough 11/98 +void A_RandomJump(mobj_t *mo); // killough 11/98 + +/* Player sprite-related psprite actions */ +void A_OpenShotgun2(player_t *player, pspdef_t *psp); +void A_LoadShotgun2(player_t *player, pspdef_t *psp); +void A_CloseShotgun2(player_t *player, pspdef_t *psp); #endif // __P_ENEMY__ diff --git a/include/p_maputl.h b/include/p_maputl.h index 8ee5f093..6d880088 100644 --- a/include/p_maputl.h +++ b/include/p_maputl.h @@ -63,7 +63,7 @@ typedef struct { union { mobj_t* thing; - const line_t* line; + Cached line; } d; } intercept_t; @@ -78,15 +78,15 @@ typedef struct { typedef boolean (*traverser_t)(intercept_t *in); fixed_t CONSTFUNC P_AproxDistance (fixed_t dx, fixed_t dy); -int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line); -int P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld); +int P_PointOnLineSide (fixed_t x, fixed_t y, Cached line); +int P_BoxOnLineSide (const fixed_t *tmbox, Cached ld); /* cph - old compatibility version below */ fixed_t P_InterceptVector2(const divline_t *v2, const divline_t *v1); -void P_LineOpening (const line_t *linedef); +void P_LineOpening (Cached linedef); void P_UnsetThingPosition(mobj_t *thing); void P_SetThingPosition(mobj_t *thing); -boolean P_BlockLinesIterator (int x, int y, boolean func(const line_t *)); +boolean P_BlockLinesIterator (int x, int y, boolean func(Cached)); boolean P_BlockThingsIterator(int x, int y, boolean func(mobj_t *)); boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, boolean trav(intercept_t *)); diff --git a/include/p_mobj.h b/include/p_mobj.h index f8d6a1e3..23ba5116 100644 --- a/include/p_mobj.h +++ b/include/p_mobj.h @@ -118,6 +118,8 @@ // Misc. mobj flags // +#include "../newcache/newcache.h" + // Call P_SpecialThing when touched. #define MF_SPECIAL (unsigned int)(0x0000000000000001) // Blocks. @@ -285,7 +287,7 @@ typedef struct mobj_s unsigned short type; int tics; // state tic counter - const state_t* state; + const state_t * state; unsigned int flags; // Thing being chased/attacked (or NULL), @@ -362,7 +364,7 @@ void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage); mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type); void P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type); boolean P_IsDoomnumAllowed(int doomnum); -void P_SpawnMapThing (const mapthing_t* mthing); +void P_SpawnMapThing (Cached mthing); void P_SpawnPlayer(int n, const mapthing_t *mthing); void P_CheckMissileSpawn(mobj_t*); // killough 8/2/98 void P_ExplodeMissile(mobj_t*); // killough diff --git a/include/p_pspr.h b/include/p_pspr.h index b9744502..7ec201c3 100644 --- a/include/p_pspr.h +++ b/include/p_pspr.h @@ -48,6 +48,7 @@ */ #include "info.h" +#include "p_enemy.h" #ifdef __GNUG__ #pragma interface @@ -74,7 +75,7 @@ typedef enum NUMPSPRITES } psprnum_t; -typedef struct +typedef struct pspdef_s { const state_t *state; /* a NULL state means not active */ int tics; @@ -96,28 +97,31 @@ int P_WeaponCycleUp(struct player_s *player); int P_WeaponCycleDown(struct player_s *player); -void A_Light0(); -void A_WeaponReady(); -void A_Lower(); -void A_Raise(); -void A_Punch(); -void A_ReFire(); -void A_FirePistol(); -void A_Light1(); -void A_FireShotgun(); -void A_Light2(); -void A_FireShotgun2(); -void A_CheckReload(); -void A_OpenShotgun2(); -void A_LoadShotgun2(); -void A_CloseShotgun2(); -void A_FireCGun(); -void A_GunFlash(); -void A_FireMissile(); -void A_Saw(); -void A_FirePlasma(); -void A_BFGsound(); -void A_FireBFG(); -void A_BFGSpray(); + +void A_Light0(player_t *player, pspdef_t *psp); +void A_WeaponReady(player_t *player, pspdef_t *psp); +void A_Lower(player_t *player, pspdef_t *psp); +void A_Raise(player_t *player, pspdef_t *psp); +void A_Punch(player_t *player, pspdef_t *psp); +void A_ReFire(player_t *player, pspdef_t *psp); +void A_FirePistol(player_t *player, pspdef_t *psp); +void A_Light1(player_t *player, pspdef_t *psp); +void A_FireShotgun(player_t *player, pspdef_t *psp); +void A_Light2(player_t *player, pspdef_t *psp); +void A_FireShotgun2(player_t *player, pspdef_t *psp); +void A_CheckReload(player_t *player, pspdef_t *psp); +void A_OpenShotgun2(player_t *player, pspdef_t *psp); +void A_LoadShotgun2(player_t *player, pspdef_t *psp); +void A_CloseShotgun2(player_t *player, pspdef_t *psp); +void A_FireCGun(player_t *player, pspdef_t *psp); +void A_GunFlash(player_t *player, pspdef_t *psp); +void A_FireMissile(player_t *player, pspdef_t *psp); +void A_Saw(player_t *player, pspdef_t *psp); +void A_FirePlasma(player_t *player, pspdef_t *psp); +void A_BFGsound(player_t *player, pspdef_t *psp); +void A_FireBFG(player_t *player, pspdef_t *psp); +void A_BFGSpray(mobj_t *mo); + + #endif diff --git a/include/p_spec.h b/include/p_spec.h index 8e1a32d3..80acd2ed 100644 --- a/include/p_spec.h +++ b/include/p_spec.h @@ -35,6 +35,7 @@ #include "r_defs.h" #include "d_player.h" +#include "../newcache/newcache.h" // Define values for map objects #define MO_TELEPORTMAN 14 @@ -534,7 +535,7 @@ typedef struct typedef struct { - const line_t* line; + Cached line; bwhere_e where; int btexture; int btimer; @@ -544,7 +545,7 @@ typedef struct // p_lights -typedef struct +typedef struct fireflicker_s { thinker_t thinker; sector_t* sector; @@ -554,7 +555,7 @@ typedef struct } fireflicker_t; -typedef struct +typedef struct lightflash_s { thinker_t thinker; sector_t* sector; @@ -566,7 +567,7 @@ typedef struct } lightflash_t; -typedef struct +typedef struct strobe_s { thinker_t thinker; sector_t* sector; @@ -578,7 +579,7 @@ typedef struct } strobe_t; -typedef struct +typedef struct glow_s { thinker_t thinker; sector_t* sector; @@ -590,7 +591,7 @@ typedef struct // p_plats -typedef struct +typedef struct plat_s { thinker_t thinker; sector_t* sector; @@ -617,7 +618,7 @@ typedef struct platlist { // p_ceilng -typedef struct +typedef struct vldoor_s { thinker_t thinker; vldoor_e type; @@ -635,7 +636,7 @@ typedef struct int topcountdown; //jff 1/31/98 keep track of line door is triggered by - const line_t *line; + Cached line; /* killough 10/98: sector tag for gradual lighting effects */ int lighttag; @@ -643,7 +644,7 @@ typedef struct // p_doors -typedef struct +typedef struct ceiling_s { thinker_t thinker; ceiling_e type; @@ -675,7 +676,7 @@ typedef struct ceilinglist { // p_floor -typedef struct +typedef struct floormove_s { thinker_t thinker; floor_e type; @@ -690,7 +691,7 @@ typedef struct } floormove_t; -typedef struct +typedef struct elevator_s { thinker_t thinker; elevator_e type; @@ -705,7 +706,7 @@ typedef struct // killough 3/7/98: Add generalized scroll effects -typedef struct { +typedef struct scroll_s { thinker_t thinker; // Thinker structure for scrolling int affectee; // Number of affected sidedef, sector, tag, or whatever } scroll_t; @@ -831,11 +832,11 @@ sector_t* P_FindModelCeilingSector int secnum ); //jff 02/04/98 int P_FindSectorFromLineTag -( const line_t *line, +( Cached line, int start ); // killough 4/17/98 int P_FindLineFromLineTag -( const line_t *line, +( Cached line, int start ); // killough 4/17/98 int P_FindMinSurroundingLight @@ -843,14 +844,14 @@ int P_FindMinSurroundingLight int max ); sector_t* getNextSector -( const line_t* line, +( const Cached &line, sector_t* sec ); int P_CheckTag -(const line_t *line); // jff 2/27/98 +(Cached line); // jff 2/27/98 boolean P_CanUnlockGenDoor -( const line_t* line, +( Cached line, player_t* player); boolean P_SectorActive @@ -864,7 +865,7 @@ boolean P_WasSecret ( const sector_t *sec ); void P_ChangeSwitchTexture -( const line_t* line, +( Cached line, int useAgain ); //////////////////////////////////////////////////////////////// @@ -933,19 +934,19 @@ void T_Scroll // p_telept int EV_Teleport -( const line_t* line, +( Cached line, int side, mobj_t* thing ); // killough 2/14/98: Add silent teleporter int EV_SilentTeleport -( const line_t* line, +( Cached line, int side, mobj_t* thing ); // killough 1/31/98: Add silent line teleporter int EV_SilentLineTeleport -( const line_t* line, +( Cached line, int side, mobj_t* thing, boolean reverse); @@ -954,96 +955,96 @@ int EV_SilentLineTeleport int EV_DoElevator -( const line_t* line, +( Cached line, elevator_e type ); int EV_BuildStairs -( const line_t* line, +( Cached line, stair_e type ); int EV_DoFloor -( const line_t* line, +( Cached line, floor_e floortype ); // p_ceilng int EV_DoCeiling -( const line_t* line, +( Cached line, ceiling_e type ); int EV_CeilingCrushStop -( const line_t* line ); +( Cached line ); // p_doors int EV_VerticalDoor -( const line_t* line, +( Cached line, mobj_t* thing ); int EV_DoDoor -( const line_t* line, +( Cached line, vldoor_e type ); int EV_DoLockedDoor -( const line_t* line, +( Cached line, vldoor_e type, mobj_t* thing ); // p_lights int EV_StartLightStrobing -( const line_t* line ); +( Cached line ); int EV_TurnTagLightsOff -( const line_t* line ); +( Cached line ); int EV_LightTurnOn -( const line_t* line, +( Cached line, int bright ); -int EV_LightTurnOnPartway(const line_t* line, fixed_t level); // killough 10/10/98 +int EV_LightTurnOnPartway(Cached line, fixed_t level); // killough 10/10/98 // p_floor int EV_DoChange -( const line_t* line, +( Cached line, change_e changetype ); int EV_DoDonut -( const line_t* line ); +( Cached line ); // p_plats int EV_DoPlat -( const line_t* line, +( Cached line, plattype_e type, int amount ); int EV_StopPlat -( const line_t* line ); +( Cached line ); // p_genlin int EV_DoGenFloor -( const line_t* line ); +( Cached line ); int EV_DoGenCeiling -( const line_t* line ); +( Cached line ); int EV_DoGenLift -( const line_t* line ); +( Cached line ); int EV_DoGenStairs -( const line_t* line ); +( Cached line ); int EV_DoGenCrusher -( const line_t* line ); +( Cached line ); int EV_DoGenDoor -( const line_t* line ); +( Cached line ); int EV_DoGenLockedDoor -( const line_t* line ); +( Cached line ); //////////////////////////////////////////////////////////////// // @@ -1069,14 +1070,14 @@ void P_UpdateSpecials // when needed boolean P_UseSpecialLine ( mobj_t* thing, - const line_t* line, + Cached line, int side ); void P_ShootSpecialLine ( mobj_t* thing, - const line_t* line ); + Cached line ); -void P_CrossSpecialLine(const line_t *line, int side, mobj_t *thing); +void P_CrossSpecialLine(Cached line, int side, mobj_t *thing); void P_PlayerInSpecialSector ( player_t* player ); @@ -1132,6 +1133,6 @@ void P_AddActiveCeiling ( ceiling_t* c ); int P_ActivateInStasisCeiling -( const line_t* line ); +( Cached line ); #endif diff --git a/include/protocol.h b/include/protocol.h index c2af10d3..bee68814 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -49,9 +49,9 @@ enum packet_type_e { }; typedef struct { - byte checksum; // Simple checksum of the entire packet - byte type; /* Type of packet */ - byte reserved[2]; /* Was random in prboom <=2.2.4, now 0 */ + uint8_t checksum; // Simple checksum of the entire packet + uint8_t type; /* Type of packet */ + uint8_t reserved[2]; /* Was random in prboom <=2.2.4, now 0 */ unsigned tic; // Timestamp } PACKEDATTR packet_header_t; @@ -64,13 +64,13 @@ static inline void packet_set(packet_header_t* p, enum packet_type_e t, unsigned #endif struct setup_packet_s { - byte players, yourplayer, skill, episode, level, deathmatch, complevel, ticdup, extratic; - byte game_options[GAME_OPTIONS_SIZE]; - byte numwads; - byte wadnames[1]; // Actually longer + uint8_t players, yourplayer, skill, episode, level, deathmatch, complevel, ticdup, extratic; + uint8_t game_options[GAME_OPTIONS_SIZE]; + uint8_t numwads; + uint8_t wadnames[1]; // Actually longer }; -/* cph - convert network byte stream to usable ticcmd_t and visa-versa +/* cph - convert network uint8_t stream to usable ticcmd_t and visa-versa * - the functions are functionally identical apart from parameters * - the void* param can be unaligned. By using void* as the parameter * it means gcc won't assume alignment so won't make false assumptions @@ -85,7 +85,7 @@ inline static void RawToTic(ticcmd_t* dst, const void* src) inline static void TicToRaw(void* dst, const ticcmd_t* src) { - /* We have to make a copy of the source struct, then do byte swaps, + /* We have to make a copy of the source struct, then do uint8_t swaps, * and fnially copy to the destination (can't do the swaps in the * destination, because it might not be aligned). */ diff --git a/include/r_data.h b/include/r_data.h index 30f18b86..5fde0a03 100644 --- a/include/r_data.h +++ b/include/r_data.h @@ -49,7 +49,7 @@ typedef struct { short originx, originy; // Block origin, which has already accounted - const patch_t* patch; // for the internal origin of the patch. + Cached patch; // for the internal origin of the patch. } texpatch_t; // @@ -60,7 +60,7 @@ typedef struct typedef struct { - const char* name; // Keep name for switch changing, etc. + const char name[9]; // Keep name for switch changing, etc. //int next, index; // killough 1/31/98: used in hashing algorithm // CPhipps - moved arrays with per-texture entries to elements here unsigned short widthmask; diff --git a/include/r_defs.h b/include/r_defs.h index ca3a0227..bb554e1f 100644 --- a/include/r_defs.h +++ b/include/r_defs.h @@ -48,6 +48,8 @@ // SECTORS do store MObjs anyway. #include "p_mobj.h" +#include "../newcache/newcache.h" + #ifdef __GNUG__ #pragma interface #endif @@ -111,7 +113,7 @@ typedef struct // thinglist is a subset of touching_thinglist struct msecnode_s *touching_thinglist; // phares 3/14/98 - const struct line_s **lines; + Cached *lines; short linecount; @@ -189,7 +191,6 @@ typedef struct line_s short const_special; short tag; short slopetype; // To aid move clipping. - } line_t; #define LN_FRONTSECTOR(l) (_g->sides[(l)->sidenum[0]].sector) @@ -295,7 +296,7 @@ typedef struct subsector_s // from darkening PLAYPAL to all black. // Could use even more than 32 levels. -typedef byte lighttable_t; +typedef uint8_t lighttable_t; // // Masked 2s linedefs @@ -303,7 +304,7 @@ typedef byte lighttable_t; typedef struct drawseg_s { - const seg_t *curline; + Cached curline; short x1, x2; fixed_t scale1, scale2, scalestep; int silhouette; // 0=none, 1=bottom, 2=top, 3=both @@ -336,11 +337,11 @@ typedef struct // posts are runs of non masked source pixels typedef struct { - byte topdelta; // -1 is the last post in a column - byte length; // length data bytes follows + uint8_t topdelta; // -1 is the last post in a column + uint8_t length; // length data bytes follows } post_t; -// column_t is a list of 0 or more post_t, (byte)-1 terminated +// column_t is a list of 0 or more post_t, (uint8_t)-1 terminated typedef post_t column_t; // @@ -359,12 +360,12 @@ typedef struct vissprite_s fixed_t texturemid; fixed_t iscale; - const patch_t* patch; + Cached patch; unsigned int mobjflags; // for color translation and shadow draw, maxbright frames as well - const lighttable_t *colormap; + CachedBuffer colormap; } vissprite_t; @@ -390,8 +391,8 @@ typedef struct short lump[8]; // Flip bit (1 = flip) to use for view angles 0-7. - //byte flip[8]; - byte flipmask; + //uint8_t flip[8]; + uint8_t flipmask; // If false use 0 for any position. // Note: as eight entries are available, @@ -427,17 +428,17 @@ typedef struct visplane fixed_t height; boolean modified; - byte pad1; - byte pad2; - byte pad3; + uint8_t pad1; + uint8_t pad2; + uint8_t pad3; // Here lies the rub for all // dynamic resize/change of resolution. - byte top[SCREENWIDTH]; - byte pad4; - byte pad5; + uint8_t top[SCREENWIDTH]; + uint8_t pad4; + uint8_t pad5; // See above. - byte bottom[SCREENWIDTH]; - byte pad6; + uint8_t bottom[SCREENWIDTH]; + uint8_t pad6; } visplane_t; diff --git a/include/r_draw.h b/include/r_draw.h index cc47260d..6758ddb5 100644 --- a/include/r_draw.h +++ b/include/r_draw.h @@ -49,10 +49,11 @@ typedef struct { fixed_t iscale; fixed_t texturemid; - const byte *source; // first pixel in a column + CachedBuffer sourcecache; // if the column is cached + const uint8_t *source; // first pixel in a column - const lighttable_t *colormap; - const byte *translation; + CachedBuffer colormap; + const uint8_t *translation; boolean odd_pixel; @@ -63,8 +64,8 @@ void R_SetDefaultDrawColumnVars(draw_column_vars_t *dcvars); typedef struct { unsigned int position; unsigned int step; - const byte *source; // start of a 64*64 tile image - const lighttable_t *colormap; + CachedBuffer source; // start of a 64*64 tile image + CachedBuffer colormap; } draw_span_vars_t; typedef struct diff --git a/include/r_main.h b/include/r_main.h index 425451da..049be04e 100644 --- a/include/r_main.h +++ b/include/r_main.h @@ -73,7 +73,7 @@ extern const fixed_t iprojection; //Global vars. extern int numnodes; -extern const mapnode_t *nodes; +extern CachedBuffer nodes; extern fixed_t viewx, viewy, viewz; @@ -81,9 +81,9 @@ extern angle_t viewangle; extern short *floorclip, *ceilingclip; -extern const lighttable_t *fullcolormap; -extern const lighttable_t *colormaps; -extern const lighttable_t* fixedcolormap; +extern CachedBuffer fullcolormap; +extern CachedBuffer colormaps; +extern CachedBuffer fixedcolormap; extern int extralight; // bumped light from gun blasts diff --git a/include/r_patch.h b/include/r_patch.h index 2d520bb3..be135719 100644 --- a/include/r_patch.h +++ b/include/r_patch.h @@ -35,7 +35,7 @@ // Size query funcs int R_NumPatchWidth(int lump) ; int R_NumPatchHeight(int lump); -#define R_NamePatchWidth(name) R_NumPatchWidth(W_GetNumForName(name)) -#define R_NamePatchHeight(name) R_NumPatchHeight(W_GetNumForName(name)) +#define R_NamePatchWidth(name) R_NumPatchWidth(NC_GetNumForName(name)) +#define R_NamePatchHeight(name) R_NumPatchHeight(NC_GetNumForName(name)) #endif diff --git a/include/st_gfx.h b/include/st_gfx.h index 3bff329f..9f6a2f06 100644 --- a/include/st_gfx.h +++ b/include/st_gfx.h @@ -1,7 +1,7 @@ #ifndef ST_GFX_H #define ST_GFX_H -extern const unsigned char gfx_stbar[]; -extern const unsigned int gfx_stbar_len; +extern unsigned char gfx_stbar[]; +extern unsigned int gfx_stbar_len; #endif // ST_GFX_H diff --git a/include/st_lib.h b/include/st_lib.h index 04dbf386..58b4fac4 100644 --- a/include/st_lib.h +++ b/include/st_lib.h @@ -64,14 +64,14 @@ typedef struct short oldnum; // pointer to current value - short* num; + int* num; // pointer to boolean stating // whether to update number boolean* on; // list of patches for 0-9 - const patch_t** p; + Cached *p; } st_number_t; @@ -83,7 +83,7 @@ typedef struct st_number_t n; // percent sign graphic - const patch_t* p; + Cached p; } st_percent_t; // Multiple Icon widget @@ -104,7 +104,7 @@ typedef struct boolean* on; // list of icons - const patch_t** p; + const Cached *p; } st_multicon_t; @@ -145,7 +145,7 @@ void STlib_initNum (st_number_t* n, int x, int y, - const patch_t **pl, + Cached *pl, int* num, boolean* on, int width ); @@ -161,10 +161,10 @@ void STlib_initPercent ( st_percent_t* p, int x, int y, - const patch_t** pl, + Cached *pl, int* num, boolean* on, - const patch_t* percent ); + Cached percent ); void STlib_updatePercent @@ -178,7 +178,7 @@ void STlib_initMultIcon ( st_multicon_t* mi, int x, int y, - const patch_t** il, + const Cached *il, int* inum, boolean* on ); diff --git a/include/tables.h b/include/tables.h index fab31405..5c4134a3 100644 --- a/include/tables.h +++ b/include/tables.h @@ -47,6 +47,8 @@ #ifndef __TABLES__ #define __TABLES__ +#include "annotations.h" + #include "m_fixed.h" #define FINEANGLES 8192 @@ -74,29 +76,30 @@ typedef unsigned angle_t; void R_LoadTrigTables(void); // Effective size is 10240. -extern const fixed_t finesine[10240]; +extern ConstMemArray finesine; // Re-use data, is just PI/2 phase shift. -static const fixed_t *const finecosine = finesine + (FINEANGLES/4); +//static const fixed_t CONSTMEM * const finecosine = finesine + (FINEANGLES/4); +extern ConstMemArray finecosine; // Effective size is 4096. -extern const fixed_t finetangent[4096]; +extern ConstMemArray finetangent; // Effective size is 2049; // The +1 size is to handle the case when x==y without additional checking. -extern const angle_t tantoangle[2049]; +extern ConstMemArray tantoangle; -extern const int viewangletox[4096]; +extern ConstMemArray viewangletox; -extern const angle_t xtoviewangle[121]; +extern const angle_t xtoviewangle[121]; extern const angle_t* xtoviewangle_vram; //VRAM Copy. -extern const fixed_t yslope[160]; +extern const fixed_t yslope[160]; extern const fixed_t* yslope_vram; //VRAM Copy. -extern const fixed_t distscale[120]; +extern const fixed_t distscale[120]; extern const fixed_t* distscale_vram; //VRAM Copy. extern short* screenheightarray; diff --git a/include/v_video.h b/include/v_video.h index 717ce2f5..6846a906 100644 --- a/include/v_video.h +++ b/include/v_video.h @@ -81,7 +81,7 @@ typedef struct #define NUM_SCREENS 1 // V_FillRect -void V_FillRect(int x, int y, int width, int height, byte colour); +void V_FillRect(int x, int y, int width, int height, uint8_t colour); // CPhipps - patch drawing @@ -99,15 +99,15 @@ void V_DrawPatchNoScale(int x, int y, const patch_t* patch); // V_DrawNamePatch - Draws the patch from lump "name" -#define V_DrawNamePatch(x,y,s,n,t,f) V_DrawNumPatch(x,y,s,W_GetNumForName(n),t,f) +#define V_DrawNamePatch(x,y,s,n,t,f) V_DrawNumPatch(x,y,s,NC_GetNumForName(n),t,f) /* cph - * Functions to return width & height of a patch. * Doesn't really belong here, but is often used in conjunction with * this code. */ -#define V_NamePatchWidth(name) R_NumPatchWidth(W_GetNumForName(name)) -#define V_NamePatchHeight(name) R_NumPatchHeight(W_GetNumForName(name)) +#define V_NamePatchWidth(name) R_NumPatchWidth(NC_GetNumForName(name)) +#define V_NamePatchHeight(name) R_NumPatchHeight(NC_GetNumForName(name)) /* cphipps 10/99: function to tile a flat over the screen */ void V_DrawBackground(const char* flatname); diff --git a/include/w_wad.h b/include/w_wad.h deleted file mode 100644 index abb13b75..00000000 --- a/include/w_wad.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Emacs style mode select -*- C++ -*- - *----------------------------------------------------------------------------- - * - * - * PrBoom: a Doom port merged with LxDoom and LSDLDoom - * based on BOOM, a modified and improved DOOM engine - * Copyright (C) 1999 by - * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman - * Copyright (C) 1999-2000 by - * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze - * Copyright 2005, 2006 by - * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * DESCRIPTION: - * WAD I/O functions. - * - *-----------------------------------------------------------------------------*/ - - -#ifndef __W_WAD__ -#define __W_WAD__ - -#include "doomtype.h" - -// -// TYPES -// - -typedef struct -{ - char identification[4]; // Should be "IWAD" or "PWAD". - int numlumps; - int infotableofs; -} wadinfo_t; - -typedef struct -{ - int filepos; - int size; - char name[8]; -} filelump_t; - - -// killough 4/17/98: if W_CheckNumForName() called with only -// one argument, pass ns_global as the default namespace - -void W_Init(void); // CPhipps - uses the above array - -int PUREFUNC W_CheckNumForName(const char* name); // killough 4/17/98 -int PUREFUNC W_GetNumForName (const char* name); -const char* PUREFUNC W_GetNameForNum(int lump); - - -int PUREFUNC W_LumpLength (int lump); - -// CPhipps - modified for 'new' lump locking -const void* PUREFUNC W_CacheLumpNum (int lump); - -// CPhipps - convenience macros -#define W_CacheLumpName(name) W_CacheLumpNum(W_GetNumForName(name)) - -void ExtractFileBase(const char *, char *); // killough - -#endif diff --git a/include/z_zone.h b/include/z_zone.h index b728c1e4..e7953fec 100644 --- a/include/z_zone.h +++ b/include/z_zone.h @@ -31,7 +31,7 @@ #include "config.h" #endif #include -#include +//#include #include #include @@ -58,8 +58,15 @@ char* Z_Strdup(const char* s); void* Z_Realloc(void *ptr, size_t n, int tag, void **user); void Z_CheckHeap (void); - - +#ifdef RPT_MALLOC +void* Z_MallocRpt(int size, int tag, void **ptr, const char* file, int line); +#define Z_Malloc(s,t,p) Z_MallocRpt(s,t,p,__FILE__,__LINE__) +void Z_FreeRpt(void *ptr, const char* file, int line); +#define Z_Free(p) Z_FreeRpt(p,__FILE__,__LINE__) +void* Z_ReallocRpt(void *ptr, size_t n, int tag, void **user, const char* file, int line); +#define Z_Realloc(p,n,t,u) Z_ReallocRpt(p,n,t,u,__FILE__,__LINE__) +void Z_ReportAll(); +#endif // RPT_MALLOC #endif diff --git a/newcache/README.md b/newcache/README.md new file mode 100644 index 00000000..2928cfb6 --- /dev/null +++ b/newcache/README.md @@ -0,0 +1,94 @@ +# NewCache +NewCache is an optimization that allows GBADoom to run on systems with very little RAM and memory mapped ROM/FLASH, like microcontrollers. The WAD file in doom is a little less than 4Mb and in GBADoom it is put in the game ROM. NewCache makes it possible to move this to external FLASH, also on devices that don't support memory mapped external flash, while keeping the need of RAM to a minimum. The original doom allows caching LUMPs loaded from the WAD file in RAM by only requesting them from disk when they are needed, and releasing them when they are not needed. To save RAM this mechanism is partially disabled/broken in GBADoom as it is not necessary to cache LUMPs when they are readily available in memory mapped ROM. + +NewCache reintroduces this mechanism in a more aggressive form where LUMPs can be evicted from RAM and reloaded triggered by OOM and pointer access respectively. This is done in the C++ introducing a smartpointer class to handle all LUMPs. Instead of loading the LUMP into memory and keeping it there until it is not needed anymore, each access to the pointer is checked and may cause a (re)load of the underlying data. This allows aggressive eviction of data from the RAM cache, assuming that it is cheap to reload it from external flash. + +## How it works +The smartpointer class doesn't hold a pointer per se, but the ID of the LUMP that it represents, which is then turned into an actual pointer on each access. If the object is already in memory, the pointer lookup is fairly cheap and does this: + +- Convert lump ID to a cache index +- Convert cache index to a pointer +- Update an LRU list + +but if not it will be loaded from flash which may entail the following: + +- Free up memory if not enough is available by evicting object(s) from the cache +- Defragment heap if not enough contiguous memory is available +- Allocate memory and load data from flash +- Update the free/LRU list +- Return the pointer + +Having the pointer re-materialize on each access allows lumps to move around in physical memory, and thereby to address heap fragmentation. This means that it is possible to move much closer to the theoretical memory lower limit by being much more aggressive on reloading objects - assuming external FLASH access is cheap. + +## Implementation details + +### LumpInfo +LumpInfo is an array with enough entries to hold information about all available lumps in the WAD. For GBADoom with Doom1.wad this means 1198 entries. Each entry looks like this + +``` c++ +typedef struct { + uint32_t wad_offset; + uint32_t size; + uint8_t cacheID; +} lumpinfo_t; +``` + +wad_offset and size are discovered during initialization by parsing the file system in the WAD file. Note that lookup by name will require a procedure that will actually traverse the WAD file directly. cacheID is the field that allows the pointer lookup. If the ID is 0, the object is not in memory and will need to be loaded from cache. + +The cache structure is a 256-entry array of CacheItems. it looks like this +```c++ +struct cacheitem { + void *data; + union { + uint8_t prev; + uint8_t next_unused; + } + uint8_t next; +} cacheindex[256]; +``` + +The array constitutes an indexed doubly linked list, so that efficient LRU tracking can be done. It also keeps track of unused cache indices by a singly linked list. + +Index 0 is special as it never points to any data. Instead it constitutes the top of both lists. cacheindex[0].next is the index of the most recently used entry, and cacheindex[0].next_unused is the index of the first unused entry. Entry 255 is also special in that cacheindex[255].prev always points to the least recently used cached object. This structure allows very efficient tracking of LRU, and it also allows very efficient keeping track of unused items, while at the same time being compact. + +if the cache runs out of entries, cacheindex[0].next_unused will be 0, and object(s) needs to be evicted to free up space. Most likely heap runs out of space before cache, so this should be a rare case. + +## Heap +The heap utilizes two features of the doom code, namely that + +1) Static data is always allocated before per-level data (provided that per-level data is flushed between levels) +2) Per level data is rarely freed + +So we will have one heap that supports both the lump cache and static data needed by the game during runtime. + +Static data is allocated in descending stack fashion from the top. Then a marker is put in and per-level data is allocated as requested, but never freed. This makes the allocation process cheap and removes the need for heap management for these objects + +Cache entries are allocated from the bottom and is subject to the watermark set by the level data. The bigger the total heap, the less the need for eviction of during execution, but in theory the system will work with just space for the biggest LUMP after loading all static and level data (which should mean 200kbyte or less). A memory block has a header that looks like this: + +```c++ +struct memblock_s { + struct memblock_s *prev; + uint32_t inuse : 1; + uint32_t bytesize : 19; + uint32_t lump : 12; +} memblock_t +``` + +lump is needed during defrag operations, as the cache entry will need its pointer updated when the block is moved. size is used to track where the next block starts. inuse is used for tracking a free block between two occupied blocks. Size is then the free area. When a block is freed due to a cache eviction, the system checks if the preceeding block or next block are free as well. If so, they are coalesced into one larger free block. + +cacheindex[0].data always points to the first memory block, and cacheindex[255].data always points to the last memory block, which will - by definition - not be in use. Upon initialization, these will be the same, and size will represent the total size of the heap. It will be adjusted if the block is freed or if level data eats into the free area of the cache. When memory is allocated for level data after lumps has been loaded, this can cause lumps to get evicted and the watermark to drop. But + +### Heap allocation +Allocation of lump data follows this procedure: +1) If enough free space is available in the last block, use that, otherwise find the first free memory block with enough space to hold the requested data. When found mark it as in-use. If 264 bytes or more are available after allocation of data, insert a new memory block right after the allocated one, marked as unused, with the remaining size (not counting the memory block size) +2) If no such block exists, defrag the heap by traversing all blocks and copying down when an unused block is encountered. Repeat at (1) + +Allocation of level data follows this procedure: +1) If enough free space is available in the last block, just reduce the size of that. +2) If not enough space was available, evict least recently used data until enough is evicted to make room. Don't bother to defrag yet +3) Defrag heap as described above, and go to (1) + +### Heap free +When changing level, all level data is evicted by simply rolling back to the watermark set by the static allocation + +Freeing a memory block means setting its inuse flag to 0, and then check if either previous or next block are free. If they are, coaelsce the two blocks into one free one. Check if the new free block should move the last block marker. The cache index should then be moved to unused. This is done by using the lump index to look up the cache index, and then set its next_free to cacheindex[0].next_free and cacheindex[0].nextfree to index. cacheID for the lump is then set to 0. \ No newline at end of file diff --git a/newcache/newcache.h b/newcache/newcache.h new file mode 100644 index 00000000..01366d42 --- /dev/null +++ b/newcache/newcache.h @@ -0,0 +1,236 @@ +#ifndef __NEWCACHE_H__ +#define __NEWCACHE_H__ + + /* Emacs style mode select -*- C++ -*- + *----------------------------------------------------------------------------- + * + * + * PrBoom: a Doom port merged with LxDoom and LSDLDoom + * based on BOOM, a modified and improved DOOM engine + * Copyright (C) 1999 by + * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman + * Copyright (C) 1999-2000 by + * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze + * Copyright 2005, 2006 by + * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko + * Copyright 2025 by + * Brian Dam Pedersen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * DESCRIPTION: + * New caching system interface. Portions from original w_wad.h + * + *-----------------------------------------------------------------------------*/ + +#include + +const uint8_t * NC_CacheLumpNum(int lumpnum); +int NC_GetNumForName (const char* name); +int NC_CheckNumForName(const char *name); +const char* NC_GetNameForNum(int lump, char buffer[8]); +int NC_LumpLength(int lumpnum); +void NC_Init(void); +void NC_ExtractFileBase(const char* path, char* dest); +const uint8_t* NC_Pin(int lumpnum); +void NC_Unpin(int lumpnum); +void NC_FlushCache(void); + +// WAD parser types +typedef struct +{ + char identification[4]; // Should be "IWAD" or "PWAD". + int numlumps; + int infotableofs; +} wadinfo_t; + +typedef struct +{ + int filepos; + int size; + union { + char name[8]; + uint64_t nname; + }; +} filelump_t; + +// Matches WADLUMPS in gbadoom1.wad +#define WADLUMPS 1158 +#define MAXLUMPS 1160 + +template +class Cached; + +#define STBAR_LUMP_NUM WADLUMPS +#define JUNK_LUMP_NUM (WADLUMPS+1) + +template +class Pinned { + public: + // TODO: implement pinning mechanism + Pinned() : ptr(nullptr), lumpnum(-1) {} + Pinned(short lumpnum, int _byteoffset) : ptr((T*)(NC_Pin(lumpnum) + _byteoffset)), lumpnum(lumpnum) {} + ~Pinned() {NC_Unpin(lumpnum);} + + operator const T*() const { + return ptr; + } + + const T* operator->() const { + return ptr; + } + + bool isnull() const { + return lumpnum == -1; + } + + private: + const T* ptr; + short lumpnum; +}; + +template +class CachedBuffer { + public: + CachedBuffer() : lumpnum(-1), _byteoffset(0) {} + CachedBuffer(short lumpnum) : lumpnum(lumpnum), _byteoffset(0) {} + CachedBuffer(short lumpnum, unsigned int byteoffset) : lumpnum(lumpnum), _byteoffset(byteoffset) {} + CachedBuffer(const char* name) : lumpnum(NC_GetNumForName(name)), _byteoffset(0) {} + + const Cached operator[](int index) const { + return Cached(lumpnum, _byteoffset+index*sizeof(T)); + } + + int size() const { + return (NC_LumpLength(lumpnum)-_byteoffset) / sizeof(T); + } + + template + CachedBuffer transmute() const { + return CachedBuffer(lumpnum,_byteoffset); + } + + CachedBuffer addOffset(int offset) const { + return CachedBuffer(lumpnum, _byteoffset+offset*sizeof(T)); + } + + Pinned pin() const { + return Pinned(lumpnum, _byteoffset); + } + + bool isnull() const { + return lumpnum == -1; + } + + bool isvalid() const { + return lumpnum != -1; + } + + unsigned int byteoffset() const { + return _byteoffset; + } + + CachedBuffer operator++(int) { + CachedBuffer old = *this; + _byteoffset += sizeof(T); + return old; + } + + T operator*() const { + return *(T*)(base() + _byteoffset); + } + + CachedBuffer& operator+=(int count) { + _byteoffset += count * sizeof(T); + return *this; + } + + private: + const char * base() const { + return (const char *)NC_CacheLumpNum(lumpnum); + } + + short lumpnum; + unsigned int _byteoffset; +}; + +template +class Sentinel { + public: + // TODO: implement pinning mechanism + Sentinel() : ptr(nullptr), lumpnum(-1) {} + Sentinel(short lumpnum, int _byteoffset) : ptr((T*)(NC_Pin(lumpnum)+_byteoffset)), lumpnum(lumpnum) {} + ~Sentinel() {NC_Unpin(lumpnum);} + + const T* operator->() const { + return ptr; + } + + private: + const T* ptr; + short lumpnum; +}; + +template +class Cached { + public: + Cached() : lumpnum(-1), byteoffset(0) {} + Cached(short lumpnum) : lumpnum(lumpnum), byteoffset(0) {} + Cached(short lumpnum, int offset) : lumpnum(lumpnum), byteoffset(offset) {} + Cached(const char* name) : lumpnum(NC_GetNumForName(name)), byteoffset(0) {} + + const Sentinel operator->() const { + + return Sentinel(lumpnum, byteoffset); + } + + T operator*() const { + return *(T*)(base() + byteoffset); + } + + const Pinned pin() const { + return Pinned(lumpnum, byteoffset); + } + + template + Cached transmuteToObjectAtByteOffset(int extrabyteoffset) const { + return Cached(lumpnum, byteoffset+extrabyteoffset); + } + + CachedBuffer bytebuffer() { + return CachedBuffer(lumpnum,byteoffset); + } + Cached operator++(int) { + Cached old = *this; + byteoffset += sizeof(T); + return old; + } + + bool isvalid() { + return lumpnum != -1; + } + private: + const char * base() const { + // TODO: Address this by pemanently pinning an entry in the cache for this + return (const char *)NC_CacheLumpNum(lumpnum); + } + short lumpnum; + unsigned int byteoffset; +}; + + + +#endif // __NEWCACHE_H__ \ No newline at end of file diff --git a/ports/PORTING.md b/ports/PORTING.md new file mode 100644 index 00000000..333bff3a --- /dev/null +++ b/ports/PORTING.md @@ -0,0 +1,57 @@ +# Porting guide +To port this source to a new platform you need to do the following: + +In i_system_e32.cc: +- Implement rendering of the framebuffer + +In wadfilereader.cc +- Implement a wad file reader + +Somewhere: +- Implement keyboard handling + + +An example for Qt running on posix (macOS or Linux) is found in the Qt/ directory. A headless version that renders the first 10 seconds of the demo can be found in headless/ . It outputs frames to the headless/screenbuffers directory. These can be converted to an animated gif using the sb2gif.py script - called like this: + +python3 sb2gif.py headless + +## Framebuffer rendering +The framebuffer is rendered in I_FinishUpdate_e32(). Palette is a 256-entry RGB table defined like this: + +``` C +struct { + uint8_t r; + uint8_t g; + uint8_t b; +} palette[256]; +``` + +srcBuffer is containing indices into the palette, and it is containing 160 lines of *240* pixels each (even though width is set to 120). That data needs to be rendered somehow. + +## Reading the WAD data +You need to implement ```WR_Init()``` to initialize reading of WAD data, and WR_Read() with the following signature: + +``` C +void WR_Read(uint8_t *dst, int offset, int len) +``` + +dst is a pointer to where data should be put. offset is the offset (in bytes) into the file where reading should start, and len is the number of bytes to read. + +## Keyboard handling +To support keyboard input, you have to include d_event.h to get the definition of event_t. You set event.type to either ev_keyup or ev_keydown, and then event.data1 according to these definitions: + +```C +#define KEYD_A 1 // Use / Sprint +#define KEYD_B 2 // Fire +#define KEYD_L 3 // Strafe left (+A Weapon down) +#define KEYD_R 4 // Strafe right (+A Weapon up) +#define KEYD_UP 5 // Run forward +#define KEYD_DOWN 6 // Back up +#define KEYD_LEFT 7 // Turn left +#define KEYD_RIGHT 8 // Turn right +#define KEYD_START 9 // Menu +#define KEYD_SELECT 10 // Automap +``` + +## Extending main +main() can be found i i_main.cc, and can be extended as desired. \ No newline at end of file diff --git a/ports/headless/Makefile b/ports/headless/Makefile new file mode 100644 index 00000000..a829f8fa --- /dev/null +++ b/ports/headless/Makefile @@ -0,0 +1,107 @@ +# Simple Makefile for GBADoom (Qt6, macOS, Apple Silicon) + +# ---- Project ----------------------------------------------------- + +TARGET := GBADoomCpp + +SRC_DIR := ../../cppsrc +OBJ_DIR := cppbuild + +# Use all C sources in source/, plus the C++ ones we know about. +# (If you add more .cpp files, just drop them in $(SRC_DIR)/) +CPP_SOURCES := $(wildcard $(SRC_DIR)/*.cc) + +SRCS := $(CPP_SOURCES) + +# Port specific source files +SRCS += i_system_e32.cc +SRCS += wadfilereader.cc +SRCS += i_main.cc + + +# ---- Original Doom Sources -------------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/w_nc.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#vpath %.cc $(SRC_DIR) ../../gamedata/original + +# ---- Guardmalloc Sources ---------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#SRCS += ../../gamedata/guard/w_nc.cc +#SRCS += guardmalloc/guardmalloc.cc +#vpath %.cc guardmalloc ../../gamedata/guard ../../gamedata/original $(SRC_DIR) + +# ---- Minimem Sources ---------------------------------------- +SRCS += ../../gamedata/minimem/w_nc.cc +SRCS += ../../gamedata/minimem/tagheap.cc +SRCS += ../../gamedata/minimem/z_mem_emu.cc +SRCS += ../../gamedata/minimem/w_lumps.cc +SRCS += ../../gamedata/minimem/gbadoom1_lumps.cc +vpath %.cc ../../gamedata/minimem . $(SRC_DIR) + + +# ---- Objects ----------------------------------------------------- +OBJS := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(notdir $(SRCS))) + +# ---- Toolchain --------------------------------------------------- + +CXX := clang++ +CC := clang +AR := ar +RM := rm -f +MKDIR_P := mkdir -p + +# QT configuration +QT_MODULE := Qt6Widgets +QT_CFLAGS := $(shell pkg-config --cflags $(QT_MODULE)) +QT_LIBS := $(shell pkg-config --libs $(QT_MODULE)) + +# ---- Flags / Defines --------------------------------------------- + +DEFINES := \ + -DQT_DEPRECATED_WARNINGS \ + -DRANGECHECK \ + -D_CRT_SECURE_NO_WARNINGS \ + -DDUMP_SCREENBUFFER \ + -DTIME_ON_TITLE_SCREEN_SEC=1 + +INCLUDEPATH := \ + -I../../include \ + -I../../gamedata/minimem + + +CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -Wno-unknown-pragmas -g -O0 $(DEFINES) $(INCLUDEPATH) +CFLAGS += $(QT_CFLAGS) +CXXFLAGS += $(QT_CFLAGS) + +LDFLAGS := $(QT_LIBS) + +# ---- Targets ----------------------------------------------------- + +.PHONY: all clean distclean run + +all: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) + $(CXX) -o $@ $(OBJS) $(LDFLAGS) + +$(OBJ_DIR): + $(MKDIR_P) $(OBJ_DIR) + + +# C++ compilation rule - works for .cc files from any directory in vpath +$(OBJ_DIR)/%.o: %.cc + $(MKDIR_P) $(OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + $(RM) $(OBJ_DIR)/*.o + +distclean: clean + $(RM) $(TARGET) + +run: all + ./$(TARGET) diff --git a/ports/headless/gbadoom1.wad b/ports/headless/gbadoom1.wad new file mode 100644 index 00000000..bc250b6c Binary files /dev/null and b/ports/headless/gbadoom1.wad differ diff --git a/ports/headless/i_main.cc b/ports/headless/i_main.cc new file mode 100644 index 00000000..3309fbe7 --- /dev/null +++ b/ports/headless/i_main.cc @@ -0,0 +1,100 @@ +/* Emacs style mode select -*- C++ -*- + *----------------------------------------------------------------------------- + * + * + * PrBoom: a Doom port merged with LxDoom and LSDLDoom + * based on BOOM, a modified and improved DOOM engine + * Copyright (C) 1999 by + * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman + * Copyright (C) 1999-2000 by + * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze + * Copyright 2005, 2006 by + * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * DESCRIPTION: + * Startup and quit functions. Handles signals, inits the + * memory management, then calls D_DoomMain. Also contains + * I_Init which does other system-related startup stuff. + * + *----------------------------------------------------------------------------- + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "doomdef.h" +#include "d_main.h" +#include "m_fixed.h" +#include "i_system.h" +#include "i_video.h" +#include "z_zone.h" +#include "lprintf.h" +#include "m_random.h" +#include "doomstat.h" +#include "g_game.h" +#include "m_misc.h" +#include "i_sound.h" +#include "i_main.h" +#include "lprintf.h" +#include "global_data.h" + +#include +//#include +#include "annotations.h" + +/* Most of the following has been rewritten by Lee Killough + * + * I_GetTime + * killough 4/13/98: Make clock rate adjustable by scale factor + * cphipps - much made static + */ + +void I_Init(void) +{ + if (!(nomusicparm && nosfxparm)) + I_InitSound(); +} + +static void PrintVer(void) +{ + char vbuf[24]; + lprintf(LO_INFO,"%s",I_GetVersionString(vbuf,200)); +} + +int main(int argc UNUSED, const char * const * argv UNUSED) +{ + /* cphipps - call to video specific startup code */ + I_PreInitGraphics(); + + PrintVer(); + + //Call this before Z_Init as maxmod uses malloc. + I_Init(); + + Z_Init(); /* 1/18/98 killough: start up memory stuff first */ + + InitGlobals(); + + D_DoomMain (); + + return 0; +} diff --git a/ports/headless/i_system_e32.cc b/ports/headless/i_system_e32.cc new file mode 100644 index 00000000..52c35310 --- /dev/null +++ b/ports/headless/i_system_e32.cc @@ -0,0 +1,287 @@ +// PsionDoomDoc.cpp +// +// Copyright 17/02/2019 +// + +#include "global_data.h" +#include "doomdef.h" + +#include +#include +#include + +#include "i_system_e32.h" + +#include "lprintf.h" + +#include "annotations.h" + +#ifndef __chess__ +#include +#endif + +extern globals_t* _g; + +//************************************************************************************** + +unsigned int vid_width = 0; +unsigned int vid_height = 0; + +unsigned int screen_width = 0; +unsigned int screen_height = 0; + +unsigned int y_pitch = 0; + +unsigned char* pb = NULL; +unsigned char* pl = NULL; + + +unsigned char* thearray = NULL; +int thesize; + +unsigned short backbuffer[120 *160]; + + +int I_GetTime(void) +{ + int thistimereply; + + #ifndef __chess__ + clock_t now = clock(); + + // For microseconds we can do (37*time_us)>>20 + thistimereply = (int)((double)now / ((double)CLOCKS_PER_SEC / (double)TICRATE)); + #else + #define MCYCLES_PER_SEC 32 + uint64_t cycles_us = chess_cycle_count()/MCYCLES_PER_SEC; // Or other us timer + thistimereply = (cycles_us*37)>>20; // Approx. 35/1000000 + #endif + + if (thistimereply < _g->lasttimereply) + { + _g->basetime -= 0xffff; + } + + _g->lasttimereply = thistimereply; + + + /* Fix for time problem */ + if (!_g->basetime) + { + _g->basetime = thistimereply; + thistimereply = 0; + } + else + { + thistimereply -= _g->basetime; + } + + return thistimereply; +} + + +//************************************************************************************** + +void I_InitScreen_e32() +{ + //Gives 480px on a 5(mx) and 320px on a Revo. + vid_width = 120; + + vid_height = screen_height = 160; +} + +//************************************************************************************** + +void I_BlitScreenBmp_e32() +{ + +} + +//************************************************************************************** + +void I_StartWServEvents_e32() +{ + +} + +//************************************************************************************** + +void I_PollWServEvents_e32() +{ + +} + +//************************************************************************************** + +void I_ClearWindow_e32() +{ + +} + +unsigned short* I_GetBackBuffer() +{ + return &backbuffer[0]; +} + + +//************************************************************************************** + +void I_CreateWindow_e32() +{ + +} + +//************************************************************************************** + +void I_CreateBackBuffer_e32() +{ + I_CreateWindow_e32(); +} + +//************************************************************************************** + +void I_FinishUpdate_e32(const uint8_t* srcBuffer, const uint8_t* pallete, const unsigned int width UNUSED, const unsigned int height UNUSED) +{ + // BDPNOTE: This is where the screenbuffer is drawn + pb = (unsigned char*)srcBuffer; + pl = (unsigned char*)pallete; + + static int filenum = 0; + static uint32_t timebase = 0xffffffff; + char filename[256]; + snprintf(filename, sizeof(filename), "screenbuffers/scr%05d.raw", filenum++); + struct image_header_s + { + uint32_t sequence_no; + uint32_t timestamp_ms; + uint16_t width; + uint16_t height; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } palette[256] __attribute__((packed)); + } header; + #ifndef __chess__ + clock_t clock_now = clock(); + uint32_t time_ms = (uint32_t)((double)clock_now / ((double)CLOCKS_PER_SEC / 1000.0)); + #else + uint32_t clock_now = chess_cycle_count() >> 5; + uint32_t time_ms = clock_now/1000; + #endif + + + #ifdef __chess__ + static unsigned lastcyclecount = 0xffffffff; + unsigned cyclecount = chess_cycle_count(); + if (lastcyclecount != 0xffffffff) { + printf("Generated frame #%d in %u cycles\n",filenum,cyclecount-lastcyclecount); + } + lastcyclecount = cyclecount; + #else + static uint32_t lastclock = 0xffffffff; + if (lastclock != 0xffffffff) { + printf("Generated frame #%d in %u ms\n",filenum,time_ms-lastclock); + } + lastclock = time_ms; + #endif + + FILE *f = fopen(filename, "wb"); + if (f) { + if (timebase == 0xffffffff) + timebase = time_ms; + header.timestamp_ms = time_ms-timebase; + header.sequence_no = filenum; + header.width = 2*width; + header.height = height; + for (int i=0; i<256; i++) { + header.palette[i].r = pl[3*i]; + header.palette[i].g = pl[3*i+1]; + header.palette[i].b = pl[3*i+2]; + } + fwrite(&header, sizeof(header), 1, f); + fwrite(srcBuffer, 2*width*height, 1, f); + fclose(f); + } else { + printf("Failed to open screenbuffer dump file %s\n", filename); + } + + // Stop after ~10 seconds + if (filenum == 350) { + printf("\n\n.. It did run DOOM\n"); + exit(0); + } +} + +//************************************************************************************** + +void I_SetPallete_e32(CachedBuffer pallete UNUSED) +{ + +} + +//************************************************************************************** + +int I_GetVideoWidth_e32() +{ + return vid_width; +} + +//************************************************************************************** + +int I_GetVideoHeight_e32() +{ + return vid_height; +} + +//************************************************************************************** + +void I_ProcessKeyEvents() +{ + I_PollWServEvents_e32(); +} + +//************************************************************************************** + +#define MAX_MESSAGE_SIZE 128 + +extern "C" +void I_Error (const char *error, ...) +{ + char msg[MAX_MESSAGE_SIZE+1]; + + va_list v; + va_start(v, error); + + int n = vsnprintf(msg, MAX_MESSAGE_SIZE, error, v); + + va_end(v); + + if (n < 0) + { + msg[0] = '\0'; + } + else if ((size_t)n >= MAX_MESSAGE_SIZE) + { + msg[MAX_MESSAGE_SIZE - 1] = '\0'; + } + + printf("%s\n", msg); + + + fflush( stderr ); + fflush( stdout ); + + //fgets(msg, sizeof(msg), stdin); + + I_Quit_e32(); +} + +//************************************************************************************** + +void I_Quit_e32() +{ + +} + +//************************************************************************************** diff --git a/ports/headless/wadfilereader.cc b/ports/headless/wadfilereader.cc new file mode 100644 index 00000000..96d612b2 --- /dev/null +++ b/ports/headless/wadfilereader.cc @@ -0,0 +1,32 @@ +#include "../gamedata/minimem/wadreader.h" +#include "../newcache/newcache.h" + +#include +#include +#include + +FILE *wad; + +void WR_Init(){ + wad = fopen("gbadoom1.wad","rb"); + if (!wad) { + printf("Couldn't open WAD file\n"); + assert(false);exit(-1); + } +} + +void WR_Read(uint8_t *dst, int offset, int len) { + // Emulate flash read speed - assume + // Read 1 byte in 4 cycles (16 MHz, 4 bit per cycle) + // Read 2 bytes from buffer and store in memory in 2 cycles + // Overhead of 100 cycles for init and polling + 5 cycles/byte + #ifdef __chess__ + uint32_t readtime = 5*len+100; + uint32_t t0 = chess_cycle_count(); + #endif + fseek(wad,offset,SEEK_SET); + fread(dst,1,len,wad); + #ifdef __chess__ + while (chess_cycle_count() < readtime+t0); + #endif +} diff --git a/ports/qt/Makefile b/ports/qt/Makefile new file mode 100644 index 00000000..ce833cb7 --- /dev/null +++ b/ports/qt/Makefile @@ -0,0 +1,104 @@ +# Simple Makefile for GBADoom (Qt6, macOS, Apple Silicon) + +# ---- Project ----------------------------------------------------- + +TARGET := GBADoomCpp + +SRC_DIR := ../../cppsrc +OBJ_DIR := cppbuild + +# Use all C sources in source/, plus the C++ ones we know about. +# (If you add more .cpp files, just drop them in $(SRC_DIR)/) +CPP_SOURCES := $(wildcard $(SRC_DIR)/*.cc) + +SRCS := $(CPP_SOURCES) + +# Port specific source files +SRCS += i_system_e32.cc +SRCS += wadfilereader.cc +SRCS += i_main.cc + + +# ---- Original Doom Sources -------------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/w_nc.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#vpath %.cc $(SRC_DIR) ../../gamedata/original + +# ---- Guardmalloc Sources ---------------------------------------- +#SRCS += ../../gamedata/original/doom_iwad.cc +#SRCS += ../../gamedata/original/w_wad.cc +#SRCS += ../../gamedata/original/z_bmalloc.cc +#SRCS += ../../gamedata/guard/w_nc.cc +#SRCS += guardmalloc/guardmalloc.cc +#vpath %.cc guardmalloc ../../gamedata/guard ../../gamedata/original $(SRC_DIR) + +# ---- Minimem Sources ---------------------------------------- +SRCS += ../../gamedata/minimem/w_nc.cc +SRCS += ../../gamedata/minimem/tagheap.cc +SRCS += ../../gamedata/minimem/z_mem_emu.cc +vpath %.cc ../../gamedata/minimem . $(SRC_DIR) + + +# ---- Objects ----------------------------------------------------- +OBJS := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(notdir $(SRCS))) + +# ---- Toolchain --------------------------------------------------- + +CXX := clang++ +CC := clang +AR := ar +RM := rm -f +MKDIR_P := mkdir -p + +# QT configuration +QT_MODULE := Qt6Widgets +QT_CFLAGS := $(shell pkg-config --cflags $(QT_MODULE)) +QT_LIBS := $(shell pkg-config --libs $(QT_MODULE)) + +# ---- Flags / Defines --------------------------------------------- + +DEFINES := \ + -DQT_DEPRECATED_WARNINGS \ + -DRANGECHECK \ + -DRPT_MALLOC \ + -D_CRT_SECURE_NO_WARNINGS \ + +INCLUDEPATH := \ + -I../../include \ + -I../../gamedata/minimem + + +CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -Wno-unknown-pragmas -Os $(DEFINES) $(INCLUDEPATH) +CFLAGS += $(QT_CFLAGS) +CXXFLAGS += $(QT_CFLAGS) + +LDFLAGS := $(QT_LIBS) + +# ---- Targets ----------------------------------------------------- + +.PHONY: all clean distclean run + +all: $(TARGET) + +$(TARGET): $(OBJ_DIR) $(OBJS) + $(CXX) -o $@ $(OBJS) $(LDFLAGS) + +$(OBJ_DIR): + $(MKDIR_P) $(OBJ_DIR) + + +# C++ compilation rule - works for .cc files from any directory in vpath +$(OBJ_DIR)/%.o: %.cc + $(MKDIR_P) $(OBJ_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + $(RM) $(OBJ_DIR)/*.o + +distclean: clean + $(RM) $(TARGET) + +run: all + ./$(TARGET) diff --git a/ports/qt/gbadoom1.wad b/ports/qt/gbadoom1.wad new file mode 120000 index 00000000..6d319c73 --- /dev/null +++ b/ports/qt/gbadoom1.wad @@ -0,0 +1 @@ +../../gamedata/minimem/gbadoom1.wad \ No newline at end of file diff --git a/source/i_main.c b/ports/qt/i_main.cc similarity index 96% rename from source/i_main.c rename to ports/qt/i_main.cc index e4897033..720835b6 100644 --- a/source/i_main.c +++ b/ports/qt/i_main.cc @@ -60,6 +60,7 @@ #include #include #include +#include "annotations.h" /* Most of the following has been rewritten by Lee Killough * @@ -80,7 +81,7 @@ static void PrintVer(void) lprintf(LO_INFO,"%s",I_GetVersionString(vbuf,200)); } -int main(int argc, const char * const * argv) +int main(int argc UNUSED, const char * const * argv UNUSED) { /* cphipps - call to video specific startup code */ I_PreInitGraphics(); @@ -95,5 +96,6 @@ int main(int argc, const char * const * argv) InitGlobals(); D_DoomMain (); + return 0; } diff --git a/ports/qt/i_system_e32.cc b/ports/qt/i_system_e32.cc new file mode 100644 index 00000000..21cd61d0 --- /dev/null +++ b/ports/qt/i_system_e32.cc @@ -0,0 +1,288 @@ +// PsionDoomDoc.cpp +// +// Copyright 17/02/2019 +// + +#include "global_data.h" +#include "doomdef.h" +#include "i_system_win.h" + +#include +#include + +#include "i_system_e32.h" + +#include "lprintf.h" + +#include "annotations.h" + +#ifdef DUMP_SCREENBUFFER +#include +#include +#endif + +#include + +extern globals_t* _g; + +//************************************************************************************** + +unsigned int vid_width = 0; +unsigned int vid_height = 0; + +unsigned int screen_width = 0; +unsigned int screen_height = 0; + +unsigned int y_pitch = 0; + +DoomWindow* window = NULL; + +QApplication * app = NULL; + +unsigned char* pb = NULL; +unsigned char* pl = NULL; + + +unsigned char* thearray = NULL; +int thesize; + +unsigned short backbuffer[120 *160]; + + +int I_GetTime(void) +{ + int thistimereply; + + clock_t now = clock(); + + // For microseconds we can do (37*time_us)>>20 + thistimereply = (int)((double)now / ((double)CLOCKS_PER_SEC / (double)TICRATE)); + + if (thistimereply < _g->lasttimereply) + { + _g->basetime -= 0xffff; + } + + _g->lasttimereply = thistimereply; + + + /* Fix for time problem */ + if (!_g->basetime) + { + _g->basetime = thistimereply; + thistimereply = 0; + } + else + { + thistimereply -= _g->basetime; + } + + return thistimereply; +} + + +//************************************************************************************** + +void I_InitScreen_e32() +{ + //Gives 480px on a 5(mx) and 320px on a Revo. + vid_width = 120; + + vid_height = screen_height = 160; +} + +//************************************************************************************** + +void I_BlitScreenBmp_e32() +{ + +} + +//************************************************************************************** + +void I_StartWServEvents_e32() +{ + +} + +//************************************************************************************** + +void I_PollWServEvents_e32() +{ + +} + +//************************************************************************************** + +void I_ClearWindow_e32() +{ + +} + +unsigned short* I_GetBackBuffer() +{ + return &backbuffer[0]; +} + + +//************************************************************************************** + +void I_CreateWindow_e32() +{ + int z = 0; + + app = new QApplication (z, nullptr); + + window = new DoomWindow(); + + #ifndef __APPLE__ + window->setAttribute(Qt::WA_PaintOnScreen); + #endif + + + window->resize(vid_width * 8, vid_height * 4); + + window->show(); +} + +//************************************************************************************** + +void I_CreateBackBuffer_e32() +{ + I_CreateWindow_e32(); + #ifdef DUMP_SCREENBUFFER + // Create directory to put the screen buffer files into - use posix for this. + // Only create this if it doesn't already exist. + struct stat st; + if (!(stat("screenbuffers", &st) == 0 && S_ISDIR(st.st_mode))) + { + mkdir("screenbuffers", S_IRWXU | S_IRGRP | S_IROTH | S_IXOTH); + } + #endif +} + +//************************************************************************************** + +void I_FinishUpdate_e32(const uint8_t* srcBuffer, const uint8_t* pallete, const unsigned int width UNUSED, const unsigned int height UNUSED) +{ + // BDPNOTE: This is where the screenbuffer is drawn + pb = (unsigned char*)srcBuffer; + pl = (unsigned char*)pallete; + + window->repaint(); + + app->processEvents(); + + #ifdef DUMP_SCREENBUFFER + static int filenum = 0; + static uint32_t timebase = 0xffffffff; + char filename[256]; + snprintf(filename, sizeof(filename), "screenbuffers/scr%05d.raw", filenum++); + struct image_header_s + { + uint32_t sequence_no; + uint32_t timestamp_ms; + uint16_t width; + uint16_t height; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } palette[256] __attribute__((packed)); + } header; + FILE *f = fopen(filename, "wb"); + if (f) { + clock_t clock_now = clock(); + uint32_t time_ms = (uint32_t)((double)clock_now / ((double)CLOCKS_PER_SEC / 1000.0)); + if (timebase == 0xffffffff) + timebase = time_ms; + header.timestamp_ms = time_ms-timebase; + header.sequence_no = filenum; + header.width = 2*width; + header.height = height; + for (int i=0; i<256; i++) { + header.palette[i].r = pl[3*i]; + header.palette[i].g = pl[3*i+1]; + header.palette[i].b = pl[3*i+2]; + } + fwrite(&header, sizeof(header), 1, f); + fwrite(srcBuffer, 2*width*height, 1, f); + fclose(f); + } else { + printf("Failed to open screenbuffer dump file %s\n", filename); + } + #endif +} + +//************************************************************************************** + +void I_SetPallete_e32(CachedBuffer pallete UNUSED) +{ + +} + +//************************************************************************************** + +int I_GetVideoWidth_e32() +{ + return vid_width; +} + +//************************************************************************************** + +int I_GetVideoHeight_e32() +{ + return vid_height; +} + +//************************************************************************************** + +void I_ProcessKeyEvents() +{ + I_PollWServEvents_e32(); +} + +//************************************************************************************** + +#define MAX_MESSAGE_SIZE 1024 + +extern "C" +void I_Error (const char *error, ...) +{ + char msg[MAX_MESSAGE_SIZE]; + + va_list v; + va_start(v, error); + + int n = vsnprintf(msg, MAX_MESSAGE_SIZE, error, v); + + va_end(v); + + if (n < 0) + { + msg[0] = '\0'; + } + else if ((size_t)n >= MAX_MESSAGE_SIZE) + { + msg[MAX_MESSAGE_SIZE - 1] = '\0'; + } + + printf("%s\n", msg); + + + fflush( stderr ); + fflush( stdout ); + + //fgets(msg, sizeof(msg), stdin); + + I_Quit_e32(); +} + +//************************************************************************************** + +void I_Quit_e32() +{ + +} + +//************************************************************************************** diff --git a/ports/qt/wadfilereader.cc b/ports/qt/wadfilereader.cc new file mode 100644 index 00000000..6e773d28 --- /dev/null +++ b/ports/qt/wadfilereader.cc @@ -0,0 +1,21 @@ +#include "wadreader.h" +#include "../newcache/newcache.h" + +#include +#include +#include + +FILE *wad; + +void WR_Init(){ + wad = fopen("gbadoom1.wad","rb"); + if (!wad) { + printf("Couldn't open WAD file\n"); + assert(false);exit(-1); + } +} + +void WR_Read(uint8_t *dst, int offset, int len) { + fseek(wad,offset,SEEK_SET); + fread(dst,1,len,wad); +} diff --git a/ports/sb2gif.py b/ports/sb2gif.py new file mode 100644 index 00000000..50ce650d --- /dev/null +++ b/ports/sb2gif.py @@ -0,0 +1,100 @@ +# This script converts the .raw files in screenbuffers/ to an animated GIF. +import os +from PIL import Image +import glob +import sys + +def read_header(file): + """ + Reads the custom header from the .raw file. + struct image_header_s + { + uint32_t sequence_no; + uint32_t timestamp_ms; + uint16_t width; + uint16_t height; + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } palette[256] __attribute__((packed)); + } header; + """ + header_data = file.read(4 + 4 + 2 + 2 + (256 * 3)) + sequence_no = int.from_bytes(header_data[0:4], 'little') + timestamp_ms = int.from_bytes(header_data[4:8], 'little') + width = int.from_bytes(header_data[8:10], 'little') + height = int.from_bytes(header_data[10:12], 'little') + + palette = [] + for i in range(256): + r = header_data[12 + i*3] + g = header_data[12 + i*3 + 1] + b = header_data[12 + i*3 + 2] + palette.append((r, g, b)) + + return sequence_no, timestamp_ms, width, height, palette + +def read_image_data(file, width, height): + """ Reads the pixel data from the .raw file. """ + pixel_data = file.read(width * height) + return pixel_data + +def convert_raw_to_numpy_image(pixel_data, width, height, palette): + """ Converts raw pixel data to a PIL Image using the provided palette. """ + img = Image.new('P', (width, height)) + img.putpalette([value for rgb in palette for value in rgb]) + img.putdata(pixel_data) + return img + +def read_images_from_raw_files(directory): + """ Reads all .raw files in the specified directory and returns a list of PIL Images. """ + images = [] + timestamps = [] + last_seq_no = 0 + raw_files = sorted(glob.glob(os.path.join(directory, '*.raw'))) + + for raw_file in raw_files: + with open(raw_file, 'rb') as file: + sequence_no, timestamp_ms, width, height, palette = read_header(file) + if sequence_no != last_seq_no + 1: + print(f"Warning: Missing frame(s) between sequence {last_seq_no} and {sequence_no}") + last_seq_no = sequence_no + timestamps.append(timestamp_ms) + pixel_data = read_image_data(file, width, height) + img = convert_raw_to_numpy_image(pixel_data, width, height, palette) + images.append(img) + + return (images,timestamps) + +def save_images_as_gif(images, output_file, timestamps, scale=1): + """ Saves a list of PIL Images as an animated GIF. """ + durations = [] + for i in range(1, len(timestamps)): + durations.append(min(timestamps[i] - timestamps[i-1],65535)) + durations.append(durations[-1]) # Last frame duration same as second last + # Scale images if needed + if scale != 1: + images = [img.resize((img.width * scale, img.height * scale), Image.NEAREST) for img in images] + + images[0].save(output_file, save_all=True, append_images=images[1:], duration=durations, loop=0) + +if __name__ == "__main__": + input_directory = os.path.join(sys.argv[1],'screenbuffers') + output_gif = os.path.join(sys.argv[1],'output.gif') + + images,timestamps = read_images_from_raw_files(input_directory) + # Compute average FPS + fps = len(images) / ((timestamps[-1] - timestamps[0]) / 1000.0) + print(f"Read {len(images)} frames with average FPS: {fps:.2f}") + + durations = [] + for i in range(1,len(timestamps)): + durations.append(timestamps[i]-timestamps[i-1]) + durations.sort() + perc90 = int(len(durations)*0.90+0.5) + fps90=1000.0/durations[perc90] + print(f"95% of the time FPS will be at least: {fps90}") + + save_images_as_gif(images, output_gif, timestamps,2) + print(f"Saved animated GIF to {output_gif}") \ No newline at end of file diff --git a/source/fixeddiv.s b/source/fixeddiv.s deleted file mode 100644 index 5f68d316..00000000 --- a/source/fixeddiv.s +++ /dev/null @@ -1,41 +0,0 @@ -.section .iwram -.arm -.align - -.global udiv64_arm - -udiv64_arm: - -/* - Tweaked version of 64/32 division found in - section 7.3.1.3 of - ARM System Developer’s Guide - Designing and Optimizing System Software - - ISBN: 1-55860-874-5 - - r0 = numerator high, return quotient - r1 = numerator low - r2 = denominator - r3 = scratch -*/ - - cmp r0, r2 - bcs .overflow_32 - rsb r2, r2, #0 - adds r3, r1, r1 - adcs r1, r2, r0, LSL#1 - subcc r1, r1, r2 - - .rept 31 - adcs r3, r3, r3 - adcs r1, r2, r1, LSL#1 - subcc r1,r1, r2 - .endr - - adcs r0, r3, r3 - bx lr - - .overflow_32: - mov r0, #-1 - bx lr diff --git a/source/i_system_e32.cpp b/source/i_system_e32.cpp deleted file mode 100644 index 72a4b89d..00000000 --- a/source/i_system_e32.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// PsionDoomDoc.cpp -// -// Copyright 17/02/2019 -// - -#ifndef GBA - - -#include "i_system_win.h" - -#include -#include - -#include "i_system_e32.h" - -#include "lprintf.h" - - -//************************************************************************************** - -unsigned int vid_width = 0; -unsigned int vid_height = 0; - -unsigned int screen_width = 0; -unsigned int screen_height = 0; - -unsigned int y_pitch = 0; - -DoomWindow* window = NULL; - -QApplication * app = NULL; - -unsigned char* pb = NULL; -unsigned char* pl = NULL; - - -unsigned char* thearray = NULL; -int thesize; - -unsigned short backbuffer[120 *160]; -unsigned short frontbuffer[120 *160]; - -//************************************************************************************** - -void I_InitScreen_e32() -{ - //Gives 480px on a 5(mx) and 320px on a Revo. - vid_width = 120; - - vid_height = screen_height = 160; -} - -//************************************************************************************** - -void I_BlitScreenBmp_e32() -{ - -} - -//************************************************************************************** - -void I_StartWServEvents_e32() -{ - -} - -//************************************************************************************** - -void I_PollWServEvents_e32() -{ - -} - -//************************************************************************************** - -void I_ClearWindow_e32() -{ - -} - -unsigned short* I_GetBackBuffer() -{ - return &backbuffer[0]; -} - -unsigned short* I_GetFrontBuffer() -{ - return &frontbuffer[0]; -} - -//************************************************************************************** - -void I_CreateWindow_e32() -{ - int z = 0; - - app = new QApplication (z, nullptr); - - window = new DoomWindow(); - - window->setAttribute(Qt::WA_PaintOnScreen); - - - - window->resize(vid_width * 8, vid_height * 4); - - window->show(); -} - -//************************************************************************************** - -void I_CreateBackBuffer_e32() -{ - I_CreateWindow_e32(); -} - -//************************************************************************************** - -void I_FinishUpdate_e32(const byte* srcBuffer, const byte* pallete, const unsigned int width, const unsigned int height) -{ - pb = (unsigned char*)srcBuffer; - pl = (unsigned char*)pallete; - - window->repaint(); - - app->processEvents(); - - int arrayCount = thesize; - - if(arrayCount == 0) - return; - - //dump the _g->viewangletox var - QFile f("C:\\temp\\gfx_stbar.c"); - f.open(QIODevice::ReadWrite); - - f.write("const byte gfx_stbar["); - f.write(QString::number(arrayCount).toLatin1().constData()); - - f.write("] =\n{\n"); - - for(int i = 0; i < arrayCount; i++) - { - f.write(QString::number(thearray[i]).toLatin1().constData()); - f.write(","); - - if((i%16) == 0) - f.write("\n"); - } - - f.write("\n};\n"); - - f.close(); - -} - -//************************************************************************************** - -void I_SetPallete_e32(const byte* pallete) -{ - -} - -//************************************************************************************** - -int I_GetVideoWidth_e32() -{ - return vid_width; -} - -//************************************************************************************** - -int I_GetVideoHeight_e32() -{ - return vid_height; -} - -//************************************************************************************** - -void I_ProcessKeyEvents() -{ - I_PollWServEvents_e32(); -} - -//************************************************************************************** - -#define MAX_MESSAGE_SIZE 1024 - -void I_Error (const char *error, ...) -{ - char msg[MAX_MESSAGE_SIZE]; - - va_list v; - va_start(v, error); - - vsprintf(msg, error, v); - - va_end(v); - - printf("%s\n", msg); - - - fflush( stderr ); - fflush( stdout ); - - //fgets(msg, sizeof(msg), stdin); - - I_Quit_e32(); -} - -//************************************************************************************** - -void I_Quit_e32() -{ - -} - -//************************************************************************************** - -#endif diff --git a/source/i_system_gba.cpp b/source/i_system_gba.cpp deleted file mode 100644 index 698e2193..00000000 --- a/source/i_system_gba.cpp +++ /dev/null @@ -1,373 +0,0 @@ -#include -#include -#include - -#ifdef GBA - -// ******************************************************************** -// GBA save type -// ******************************************************************** -// This is needed for emulators to know which save type the ROM is using. - -static volatile const char save_type[10] = "SRAM_V110"; - -extern "C" -{ - #include "doomdef.h" - #include "doomtype.h" - #include "d_main.h" - #include "d_event.h" - - #include "global_data.h" - - #include "tables.h" -} - -#include "i_system_e32.h" - -#include "lprintf.h" - -#include -#include -#include - -#include - -#define DCNT_PAGE 0x0010 - -#define VID_PAGE1 VRAM -#define VID_PAGE2 0x600A000 - -#define TM_FREQ_1024 0x0003 -#define TM_ENABLE 0x0080 -#define TM_CASCADE 0x0004 -#define TM_FREQ_1024 0x0003 -#define TM_FREQ_256 0x0002 - -#define REG_WAITCNT *((vu16 *)(0x4000204)) - - -//************************************************************************************** - - -//******************************************************************************* -//VBlank handler. -//******************************************************************************* - -void VBlankCallback() -{ - mmVBlank(); - mmFrame(); -} - - -void I_InitScreen_e32() -{ - irqInit(); - - irqSet( IRQ_VBLANK, VBlankCallback ); - irqEnable(IRQ_VBLANK); - - - //Set gamepak wait states and prefetch. - REG_WAITCNT = 0x46DA; - - consoleDemoInit(); - - REG_TM2CNT_L= 65535-1872; // 1872 ticks = 1/35 secs - REG_TM2CNT_H = TM_FREQ_256 | TM_ENABLE; // we're using the 256 cycle timer - - // cascade into tm3 - REG_TM3CNT_H = TM_CASCADE | TM_ENABLE; -} - -//************************************************************************************** - -void I_BlitScreenBmp_e32() -{ - -} - -//************************************************************************************** - -void I_StartWServEvents_e32() -{ - -} - -//************************************************************************************** - -void I_PollWServEvents_e32() -{ - scanKeys(); - - u16 key_down = keysDown(); - - event_t ev; - - if(key_down) - { - ev.type = ev_keydown; - - if(key_down & KEY_UP) - { - ev.data1 = KEYD_UP; - D_PostEvent(&ev); - } - else if(key_down & KEY_DOWN) - { - ev.data1 = KEYD_DOWN; - D_PostEvent(&ev); - } - - if(key_down & KEY_LEFT) - { - ev.data1 = KEYD_LEFT; - D_PostEvent(&ev); - } - else if(key_down & KEY_RIGHT) - { - ev.data1 = KEYD_RIGHT; - D_PostEvent(&ev); - } - - if(key_down & KEY_SELECT) - { - ev.data1 = KEYD_SELECT; - D_PostEvent(&ev); - } - - if(key_down & KEY_START) - { - ev.data1 = KEYD_START; - D_PostEvent(&ev); - } - - if(key_down & KEY_A) - { - ev.data1 = KEYD_A; - D_PostEvent(&ev); - } - - if(key_down & KEY_B) - { - ev.data1 = KEYD_B; - D_PostEvent(&ev); - } - - if(key_down & KEY_L) - { - ev.data1 = KEYD_L; - D_PostEvent(&ev); - } - - if(key_down & KEY_R) - { - ev.data1 = KEYD_R; - D_PostEvent(&ev); - } - } - - u16 key_up = keysUp(); - - if(key_up) - { - ev.type = ev_keyup; - - if(key_up & KEY_UP) - { - ev.data1 = KEYD_UP; - D_PostEvent(&ev); - } - else if(key_up & KEY_DOWN) - { - ev.data1 = KEYD_DOWN; - D_PostEvent(&ev); - } - - if(key_up & KEY_LEFT) - { - ev.data1 = KEYD_LEFT; - D_PostEvent(&ev); - } - else if(key_up & KEY_RIGHT) - { - ev.data1 = KEYD_RIGHT; - D_PostEvent(&ev); - } - - if(key_up & KEY_SELECT) - { - ev.data1 = KEYD_SELECT; - D_PostEvent(&ev); - } - - if(key_up & KEY_START) - { - ev.data1 = KEYD_START; - D_PostEvent(&ev); - } - - if(key_up & KEY_A) - { - ev.data1 = KEYD_A; - D_PostEvent(&ev); - } - - if(key_up & KEY_B) - { - ev.data1 = KEYD_B; - D_PostEvent(&ev); - } - - if(key_up & KEY_L) - { - ev.data1 = KEYD_L; - D_PostEvent(&ev); - } - - if(key_up & KEY_R) - { - ev.data1 = KEYD_R; - D_PostEvent(&ev); - } - } -} - -//************************************************************************************** - -void I_ClearWindow_e32() -{ - -} - -//************************************************************************************** - -unsigned short* I_GetBackBuffer() -{ - if(REG_DISPCNT & DCNT_PAGE) - return (unsigned short*)VID_PAGE1; - - return (unsigned short*)VID_PAGE2; -} - -//************************************************************************************** - -unsigned short* I_GetFrontBuffer() -{ - if(REG_DISPCNT & DCNT_PAGE) - return (unsigned short*)VID_PAGE2; - - return (unsigned short*)VID_PAGE1; -} - -//************************************************************************************** - -void I_CreateWindow_e32() -{ - - //Bit5 = unlocked vram at h-blank. - SetMode(MODE_4 | BG2_ENABLE | BIT(5)); - - unsigned short* bb = I_GetBackBuffer(); - - memset(bb, 0, 240*160); - - I_FinishUpdate_e32(NULL, NULL, 0, 0); - - bb = I_GetBackBuffer(); - - memset(bb, 0, 240*160); - - I_FinishUpdate_e32(NULL, NULL, 0, 0); - -} - -//************************************************************************************** - -void I_CreateBackBuffer_e32() -{ - I_CreateWindow_e32(); -} - -//************************************************************************************** - -void I_FinishUpdate_e32(const byte* srcBuffer, const byte* pallete, const unsigned int width, const unsigned int height) -{ - REG_DISPCNT ^= DCNT_PAGE; -} - -//************************************************************************************** - -void I_SetPallete_e32(const byte* pallete) -{ - unsigned short* pal_ram = (unsigned short*)0x5000000; - - for(int i = 0; i< 256; i++) - { - unsigned int r = *pallete++; - unsigned int g = *pallete++; - unsigned int b = *pallete++; - - pal_ram[i] = RGB5(r >> 3, g >> 3, b >> 3); - } -} - -//************************************************************************************** - -int I_GetVideoWidth_e32() -{ - return 120; -} - -//************************************************************************************** - -int I_GetVideoHeight_e32() -{ - return 160; -} - - - -//************************************************************************************** - -void I_ProcessKeyEvents() -{ - I_PollWServEvents_e32(); -} - -//************************************************************************************** - -#define MAX_MESSAGE_SIZE 1024 - -void I_Error (const char *error, ...) -{ - consoleDemoInit(); - - char msg[MAX_MESSAGE_SIZE]; - - va_list v; - va_start(v, error); - - vsprintf(msg, error, v); - - va_end(v); - - printf("%s", msg); - - while(true) - { - VBlankIntrWait(); - } -} - -//************************************************************************************** - -void I_Quit_e32() -{ - -} - -//************************************************************************************** - -#endif diff --git a/source/st_gfx.c b/source/st_gfx.c deleted file mode 100644 index c05fdcd2..00000000 --- a/source/st_gfx.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "gfx/stbar.h" - -#include "st_gfx.h" - -const unsigned int gfx_stbar_len = sizeof(gfx_stbar);