Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 622-teamlives-hud
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • alien-breed-3d
  • appveyor
  • bbox
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bosszero
  • bustablemobjzfix
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • cmake-clang-tidy
  • cmake-enable-cxx
  • cmake-valgrind
  • crawlacommander-sprites
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • few-kart-lua-changes
  • ffloorclip
  • fix-cvar-conflicts
  • fix-opengl-shear-roll
  • flipfuncpointers
  • floorsprite-and-shadow-fake-planes-fix
  • fof-lightlist-fixes
  • font-FUCK
  • font_drawer
  • frictionrefactor
  • fuck-macros-1
  • fullscreen-toggle
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • ghost-networking
  • gif-splitting
  • gitlab-ci
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-packet-tics
  • increasemaxunlockables
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-command-netids
  • lua-local
  • lua-minmax-plus-bruh-moments
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • master
  • menu-edits
  • mobj-dispoffset
  • models-plus-final
  • more-cleanup
  • multithread
  • musicdef-lua
  • net-test
  • netcode-refactor
  • netcode-tests
  • netxcmd-refactor
  • next
  • next-test
  • next-test-2021-7-11
  • nextmapspecialoverride
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
139 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
  • 1392-2-2-15-attempting-to-draw-a-hud-graphic-with-the-same-lump-name-as-a-lua-script-crashes-the
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results
Show changes
......@@ -19,6 +19,7 @@
#include "r_main.h"
#include "r_draw.h"
#include "r_things.h" // R_Frame2Char etc
#include "r_rotsprite.h" // R_GetRollAngle
#include "m_random.h"
#include "s_sound.h"
#include "g_game.h"
......@@ -2434,6 +2435,16 @@ static int lib_rPointInSubsectorOrNil(lua_State *L)
return 1;
}
#ifdef ROTSPRITE
// R_ROTSPRITE
////////////
static int lib_rGetRollAngle(lua_State *L)
{
lua_pushinteger(L, R_GetRollAngle(luaL_checkangle(L, 1)));
return 1;
}
#endif
// R_THINGS
////////////
......@@ -3489,6 +3500,11 @@ static luaL_Reg lib[] = {
{"R_PointInSubsector",lib_rPointInSubsector},
{"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil},
#ifdef ROTSPRITE
// r_rotsprite
{"R_GetRollAngle",lib_rGetRollAngle},
#endif
// r_things (sprite)
{"R_Char2Frame",lib_rChar2Frame},
{"R_Frame2Char",lib_rFrame2Char},
......
......@@ -14,6 +14,7 @@
#include "fastcmp.h"
#include "r_defs.h"
#include "r_local.h"
#include "r_rotsprite.h"
#include "st_stuff.h" // hudinfo[]
#include "g_game.h"
#include "i_video.h" // rendermode
......@@ -35,11 +36,6 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
#ifdef LUA_PATCH_SAFETY
static patchinfo_t *patchinfo, *patchinfohead;
static int numluapatches;
#endif
// must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = {
"stagetitle",
......@@ -292,14 +288,9 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
#else
patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH));
#endif
patch_t *patch = **((patch_t ***)luaL_checkudata(L, 1, META_PATCH));
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
// patches are invalidated when switching renderers
if (!patch) {
if (field == patch_valid) {
lua_pushboolean(L, 0);
......@@ -403,59 +394,18 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L)
{
#ifdef LUA_PATCH_SAFETY
int i;
lumpnum_t lumpnum;
patchinfo_t *luapat;
patch_t *realpatch;
#ifdef ROTSPRITE
INT32 rollangle = R_GetRollAngle(luaL_optinteger(L, 2, 0));
#endif
HUDONLY
luapat = patchinfohead;
lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1));
if (lumpnum == LUMPERROR)
lumpnum = W_GetNumForLongName("MISSING");
for (i = 0; i < numluapatches; i++)
{
// check if already cached
if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum))
{
LUA_PushUserdata(L, luapat, META_PATCH);
return 1;
}
luapat = luapat->next;
if (!luapat)
break;
}
if (numluapatches > 0)
{
patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfo = patchinfo->next;
}
#ifdef ROTSPRITE
if (rollangle)
LUA_PushUserdata(L, W_GetRotatedPatchPointerFromLongName(luaL_checkstring(L, 1), PU_PATCH, rollangle, false, NULL, lua_optboolean(L, 3)), META_PATCH);
else
{
patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL);
patchinfohead = patchinfo;
}
realpatch = W_CachePatchNum(lumpnum, PU_PATCH);
patchinfo->width = realpatch->width;
patchinfo->height = realpatch->height;
patchinfo->leftoffset = realpatch->leftoffset;
patchinfo->topoffset = realpatch->topoffset;
patchinfo->wadnum = WADFILENUM(lumpnum);
patchinfo->lumpnum = LUMPNUM(lumpnum);
LUA_PushUserdata(L, patchinfo, META_PATCH);
numluapatches++;
#else
HUDONLY
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
#endif
LUA_PushUserdata(L, W_GetPatchPointerFromLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
return 1;
}
......@@ -517,10 +467,9 @@ static int libd_getSpritePatch(lua_State *L)
angle_t rollangle = luaL_checkangle(L, 4);
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(i, frame, NULL, sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
if (rot)
{
LUA_PushUserdata(L, W_GetRotatedPatchPointer(sprframe->lumppat[angle], PU_PATCH, rot, true, NULL, sprframe->flip & (1<<angle)), META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
......@@ -528,8 +477,8 @@ static int libd_getSpritePatch(lua_State *L)
}
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
// push both the patch and its "flip" value
LUA_PushUserdata(L, W_GetPatchPointer(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
......@@ -631,9 +580,9 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
if (!(sprframe->rotsprite.cached & (1<<angle)))
R_CacheRotSprite(SPR_PLAY, frame, &skins[i].sprinfo[j], sprframe, angle, sprframe->flip & (1<<angle));
LUA_PushUserdata(L, sprframe->rotsprite.patch[angle][rot], META_PATCH);
spriteinfo_t *sprinfo = &skins[i].sprinfo[j];
spriteframepivot_t *pivot = (sprinfo->available) ? &sprinfo->pivot[frame] : NULL;
LUA_PushUserdata(L, W_GetRotatedPatchPointer(sprframe->lumppat[angle], PU_PATCH, rot, true, pivot, sprframe->flip & (1<<angle)), META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
return 3;
......@@ -641,8 +590,8 @@ static int libd_getSprite2Patch(lua_State *L)
}
#endif
// push both the patch and it's "flip" value
LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
// push both the patch and its "flip" value
LUA_PushUserdata(L, W_GetPatchPointer(sprframe->lumppat[angle], PU_PATCH), META_PATCH);
lua_pushboolean(L, (sprframe->flip & (1<<angle)) != 0);
return 2;
}
......@@ -651,22 +600,14 @@ static int libd_draw(lua_State *L)
{
INT32 x, y, flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 3, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH));
patch = **((patch_t ***)luaL_checkudata(L, 3, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 4, 0);
if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
......@@ -682,9 +623,6 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale;
INT32 flags;
patch_t *patch;
#ifdef LUA_PATCH_SAFETY
patchinfo_t *luapat;
#endif
const UINT8 *colormap = NULL;
HUDONLY
......@@ -693,14 +631,9 @@ static int libd_drawScaled(lua_State *L)
scale = luaL_checkinteger(L, 3);
if (scale < 0)
return luaL_error(L, "negative scale");
#ifdef LUA_PATCH_SAFETY
luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH));
patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH);
#else
patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH));
patch = **((patch_t ***)luaL_checkudata(L, 4, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
#endif
flags = luaL_optinteger(L, 5, 0);
if (!lua_isnoneornil(L, 6))
colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP));
......@@ -727,7 +660,9 @@ static int libd_drawStretched(lua_State *L)
vscale = luaL_checkinteger(L, 4);
if (vscale < 0)
return luaL_error(L, "negative vertical scale");
patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH));
patch = **((patch_t ***)luaL_checkudata(L, 5, META_PATCH));
if (!patch)
return LUA_ErrInvalid(L, "patch_t");
flags = luaL_optinteger(L, 6, 0);
if (!lua_isnoneornil(L, 7))
colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP));
......@@ -1247,10 +1182,6 @@ int LUA_HudLib(lua_State *L)
{
memset(hud_enabled, 0xff, (hud_MAX/8)+1);
#ifdef LUA_PATCH_SAFETY
numluapatches = 0;
#endif
lua_newtable(L); // HUD registry table
lua_newtable(L);
luaL_register(L, NULL, lib_draw);
......
......@@ -18,6 +18,7 @@
#include "p_local.h"
#include "z_zone.h"
#include "r_patch.h"
#include "r_rotsprite.h"
#include "r_things.h"
#include "r_draw.h" // R_GetColorByName
#include "doomstat.h" // luabanks[]
......@@ -377,10 +378,6 @@ static int lib_setSpriteInfo(lua_State *L)
UINT32 i = luaL_checkinteger(L, 1);
if (i == 0 || i >= NUMSPRITES)
return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1);
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[i]);
#endif
info = &spriteinfo[i]; // get the spriteinfo to assign to.
}
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
......@@ -462,11 +459,6 @@ static int spriteinfo_set(lua_State *L)
lua_remove(L, 1); // remove field
lua_settop(L, 1); // leave only one value
#ifdef ROTSPRITE
if (sprites != NULL)
R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]);
#endif
if (fastcmp(field, "pivot"))
{
// pivot[] is a table
......
......@@ -62,7 +62,7 @@ extern lua_State *gL;
#define META_BBOX "BOUNDING_BOX"
#define META_HUDINFO "HUDINFO_T*"
#define META_PATCH "PATCH_T*"
#define META_PATCH "PATCH_T**"
#define META_COLORMAP "COLORMAP"
#define META_CAMERA "CAMERA_T*"
......
......@@ -203,7 +203,7 @@ menu_t SPauseDef;
// Level Select
static levelselect_t levelselect = {0, NULL};
static UINT8 levelselectselect[3];
static patch_t *levselp[2][3];
static patch_t **levselp[2][3];
static INT32 lsoffs[2];
#define lsrow levelselectselect[0]
......@@ -342,7 +342,7 @@ static void M_EraseData(INT32 choice);
static void M_Addons(INT32 choice);
static void M_AddonsOptions(INT32 choice);
static patch_t *addonsp[NUM_EXT+5];
static patch_t **addonsp[NUM_EXT+5];
#define addonmenusize 9 // number of items actually displayed in the addons menu view, formerly (2*numaddonsshown + 1)
#define numaddonsshown 4 // number of items to each side of the currently selected item, unless at top/bottom ends of directory
......@@ -1345,11 +1345,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11},
#endif
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16},
#ifdef HWRENDER
{IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21},
#else
{IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21},
#endif
{IT_STRING | IT_CVAR, NULL, "Renderer", &cv_newrenderer, 21},
{IT_HEADER, NULL, "Color Profile", NULL, 30},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma,36},
......@@ -2147,15 +2143,21 @@ menu_t OP_PlaystyleDef = {
static void M_VideoOptions(INT32 choice)
{
(void)choice;
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
#ifdef HWRENDER
if (vid_opengl_state == -1)
if (vid.glstate != VID_GL_LIBRARY_ERROR)
{
OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
OP_VideoOptionsMenu[op_video_renderer].text = "Software";
OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR);
OP_VideoOptionsMenu[op_video_renderer].patch = NULL;
OP_VideoOptionsMenu[op_video_renderer].text = "Renderer";
}
CV_StealthSetValue(&cv_newrenderer, cv_renderer.value);
#endif
M_SetupNextMenu(&OP_VideoOptionsDef);
}
......@@ -5206,13 +5208,13 @@ static INT32 M_CountRowsToShowOnPlatter(INT32 gt)
//
static void M_CacheLevelPlatter(void)
{
levselp[0][0] = W_CachePatchName("SLCT1LVL", PU_PATCH);
levselp[0][1] = W_CachePatchName("SLCT2LVL", PU_PATCH);
levselp[0][2] = W_CachePatchName("BLANKLVL", PU_PATCH);
levselp[0][0] = (patch_t **)W_GetPatchPointerFromName("SLCT1LVL", PU_PATCH);
levselp[0][1] = (patch_t **)W_GetPatchPointerFromName("SLCT2LVL", PU_PATCH);
levselp[0][2] = (patch_t **)W_GetPatchPointerFromName("BLANKLVL", PU_PATCH);
levselp[1][0] = W_CachePatchName("SLCT1LVW", PU_PATCH);
levselp[1][1] = W_CachePatchName("SLCT2LVW", PU_PATCH);
levselp[1][2] = W_CachePatchName("BLANKLVW", PU_PATCH);
levselp[1][0] = (patch_t **)W_GetPatchPointerFromName("SLCT1LVW", PU_PATCH);
levselp[1][1] = (patch_t **)W_GetPatchPointerFromName("SLCT2LVW", PU_PATCH);
levselp[1][2] = (patch_t **)W_GetPatchPointerFromName("BLANKLVW", PU_PATCH);
}
//
......@@ -5591,13 +5593,10 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
if (map <= 0)
return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 564x100 image of the level as entry MAPxxW
if (!(levelselect.rows[row].mapavailable[col]))
{
V_DrawSmallScaledPatch(x, y, 0, levselp[1][2]);
V_DrawSmallScaledPatch(x, y, 0, *levselp[1][2]);
M_DrawStaticBox(x, y, V_80TRANS, 282, 50);
}
else
......@@ -5605,7 +5604,7 @@ static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, bo
if (W_CheckNumForName(va("%sW", G_BuildMapName(map))) != LUMPERROR)
patch = W_CachePatchName(va("%sW", G_BuildMapName(map)), PU_PATCH);
else
patch = levselp[1][2]; // don't static to indicate that it's just a normal level
patch = *levselp[1][2]; // don't static to indicate that it's just a normal level
V_DrawSmallScaledPatch(x, y, 0, patch);
}
......@@ -5625,13 +5624,10 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
if (map <= 0)
return;
if (needpatchrecache)
M_CacheLevelPlatter();
// A 160x100 image of the level as entry MAPxxP
if (!(levelselect.rows[row].mapavailable[col]))
{
V_DrawSmallScaledPatch(x, y, 0, levselp[0][2]);
V_DrawSmallScaledPatch(x, y, 0, *levselp[0][2]);
M_DrawStaticBox(x, y, V_80TRANS, 80, 50);
}
else
......@@ -5639,7 +5635,7 @@ static void M_DrawLevelPlatterMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolea
if (W_CheckNumForName(va("%sP", G_BuildMapName(map))) != LUMPERROR)
patch = W_CachePatchName(va("%sP", G_BuildMapName(map)), PU_PATCH);
else
patch = levselp[0][2]; // don't static to indicate that it's just a normal level
patch = *levselp[0][2]; // don't static to indicate that it's just a normal level
V_DrawSmallScaledPatch(x, y, 0, patch);
}
......@@ -5913,7 +5909,7 @@ static void M_DrawLevelPlatterMenu(void)
// draw cursor box
if (levellistmode != LLM_CREATESERVER || lsrow)
V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey+lsoffs[0], 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)]));
V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey+lsoffs[0], 0, (*levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)]));
#if 0
if (levelselect.rows[lsrow].maplist[lscol] > 0)
......@@ -6248,23 +6244,23 @@ static void M_AddonsOptions(INT32 choice)
static void M_LoadAddonsPatches(void)
{
addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_PATCH);
addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_PATCH);
addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_PATCH);
addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_PATCH);
addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_PATCH);
addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_PATCH);
addonsp[EXT_FOLDER] = (patch_t **)W_GetPatchPointerFromName("M_FFLDR", PU_PATCH);
addonsp[EXT_UP] = (patch_t **)W_GetPatchPointerFromName("M_FBACK", PU_PATCH);
addonsp[EXT_NORESULTS] = (patch_t **)W_GetPatchPointerFromName("M_FNOPE", PU_PATCH);
addonsp[EXT_TXT] = (patch_t **)W_GetPatchPointerFromName("M_FTXT", PU_PATCH);
addonsp[EXT_CFG] = (patch_t **)W_GetPatchPointerFromName("M_FCFG", PU_PATCH);
addonsp[EXT_WAD] = (patch_t **)W_GetPatchPointerFromName("M_FWAD", PU_PATCH);
#ifdef USE_KART
addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_PATCH);
addonsp[EXT_KART] = (patch_t **)W_GetPatchPointerFromName("M_FKART", PU_PATCH);
#endif
addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_PATCH);
addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_PATCH);
addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_PATCH);
addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_PATCH);
addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_PATCH);
addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_PATCH);
addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_PATCH);
addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_PATCH);
addonsp[EXT_PK3] = (patch_t **)W_GetPatchPointerFromName("M_FPK3", PU_PATCH);
addonsp[EXT_SOC] = (patch_t **)W_GetPatchPointerFromName("M_FSOC", PU_PATCH);
addonsp[EXT_LUA] = (patch_t **)W_GetPatchPointerFromName("M_FLUA", PU_PATCH);
addonsp[NUM_EXT] = (patch_t **)W_GetPatchPointerFromName("M_FUNKN", PU_PATCH);
addonsp[NUM_EXT+1] = (patch_t **)W_GetPatchPointerFromName("M_FSEL", PU_PATCH);
addonsp[NUM_EXT+2] = (patch_t **)W_GetPatchPointerFromName("M_FLOAD", PU_PATCH);
addonsp[NUM_EXT+3] = (patch_t **)W_GetPatchPointerFromName("M_FSRCH", PU_PATCH);
addonsp[NUM_EXT+4] = (patch_t **)W_GetPatchPointerFromName("M_FSAVE", PU_PATCH);
}
static void M_Addons(INT32 choice)
......@@ -6450,10 +6446,6 @@ static void M_DrawAddons(void)
return;
}
// Lactozilla: Load addons menu patches.
if (needpatchrecache)
M_LoadAddonsPatches();
if (Playing())
V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems.");
else
......@@ -6548,16 +6540,16 @@ static void M_DrawAddons(void)
if (type & EXT_LOADED)
{
flags |= V_TRANSLUCENT;
V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]);
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]);
V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, *addonsp[(type & ~EXT_LOADED)]);
V_DrawSmallScaledPatch(x-(16+4), y, 0, *addonsp[NUM_EXT+2]);
}
else
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]);
V_DrawSmallScaledPatch(x-(16+4), y, 0, *addonsp[(type & ~EXT_LOADED)]);
// draw selection box for the item currently selected
if ((size_t)i == dir_on[menudepthleft])
{
V_DrawFixedPatch((x-(16+4))<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, 0, addonsp[NUM_EXT+1], flashcol);
V_DrawFixedPatch((x-(16+4))<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, 0, *addonsp[NUM_EXT+1], flashcol);
flags = V_ALLOWLOWERCASE|highlightflags;
}
......@@ -6591,14 +6583,14 @@ static void M_DrawAddons(void)
// draw search icon
x -= (21 + 5 + 16);
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]);
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), *addonsp[NUM_EXT+3]);
// draw save icon
x = BASEVIDWIDTH - x - 16;
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), *addonsp[NUM_EXT+4]);
if (modifiedgame)
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]);
V_DrawSmallScaledPatch(x, y + 4, 0, *addonsp[NUM_EXT+2]);
}
static void M_AddonExec(INT32 ch)
......@@ -7552,8 +7544,8 @@ static void M_HandleEmblemHints(INT32 choice)
static musicdef_t *curplaying = NULL;
static INT32 st_sel = 0, st_cc = 0;
static tic_t st_time = 0;
static patch_t* st_radio[9];
static patch_t* st_launchpad[4];
static patch_t **st_radio[9];
static patch_t **st_launchpad[4];
static void M_CacheSoundTest(void)
{
......@@ -7564,14 +7556,14 @@ static void M_CacheSoundTest(void)
for (i = 0; i < 9; i++)
{
buf[7] = (char)('0'+i);
st_radio[i] = W_CachePatchName(buf, PU_PATCH);
st_radio[i] = (patch_t **)W_GetPatchPointerFromName(buf, PU_PATCH);
}
STRBUFCPY(buf, "M_LPADn");
for (i = 0; i < 4; i++)
{
buf[6] = (char)('0'+i);
st_launchpad[i] = W_CachePatchName(buf, PU_PATCH);
st_launchpad[i] = (patch_t **)W_GetPatchPointerFromName(buf, PU_PATCH);
}
}
......@@ -7608,9 +7600,6 @@ static void M_DrawSoundTest(void)
fixed_t hscale = FRACUNIT/2, vscale = FRACUNIT/2, bounce = 0;
UINT8 frame[4] = {0, 0, -1, SKINCOLOR_RUBY};
if (needpatchrecache)
M_CacheSoundTest();
// let's handle the ticker first. ideally we'd tick this somewhere else, BUT...
if (curplaying)
{
......@@ -7663,19 +7652,19 @@ static void M_DrawSoundTest(void)
V_DrawStretchyFixedPatch(x, y,
hscale, vscale,
0, st_radio[frame[0]], NULL);
0, *st_radio[frame[0]], NULL);
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, st_launchpad[0], NULL);
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, *st_launchpad[0], NULL);
for (i = 0; i < 9; i++)
{
if (i == frame[2])
{
UINT8 *colmap = R_GetTranslationColormap(TC_RAINBOW, frame[3], GTC_CACHE);
V_DrawFixedPatch(x, y + (frame[1]<<FRACBITS), FRACUNIT/2, 0, st_launchpad[frame[1]+1], colmap);
V_DrawFixedPatch(x, y + (frame[1]<<FRACBITS), FRACUNIT/2, 0, *st_launchpad[frame[1]+1], colmap);
}
else
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, st_launchpad[1], NULL);
V_DrawFixedPatch(x, y, FRACUNIT/2, 0, *st_launchpad[1], NULL);
if ((i % 3) == 2)
{
......@@ -8258,9 +8247,6 @@ static void M_DrawLoadGameData(void)
if (vid.width != BASEVIDWIDTH*vid.dupx)
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
if (needpatchrecache)
M_CacheLoadGameData();
for (i = -2; i <= 2; i++)
{
savetodraw = (saveSlotSelected + i + numsaves)%numsaves;
......@@ -8964,7 +8950,6 @@ void M_ForceSaveSlotSelected(INT32 sslot)
// CHARACTER SELECT
// ================
// lactozilla: sometimes the renderer changes and these patches don't exist anymore
static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{
if (!(description[i].picname[0]))
......@@ -8973,32 +8958,16 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum)
{
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL];
description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH);
description[i].charpic = (patch_t **)W_GetPatchPointer(sprframe->lumppat[0], PU_PATCH);
}
else
description[i].charpic = W_CachePatchName("MISSING", PU_PATCH);
description[i].charpic = (patch_t **)W_GetPatchPointerFromName("MISSING", PU_PATCH);
}
else
description[i].charpic = W_CachePatchName(description[i].picname, PU_PATCH);
description[i].charpic = (patch_t **)W_GetPatchPointerFromName(description[i].picname, PU_PATCH);
if (description[i].nametag[0])
description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH);
}
static void M_CacheCharacterSelect(void)
{
INT32 i, skinnum;
for (i = 0; i < MAXSKINS; i++)
{
if (!description[i].used)
continue;
// Already set in M_SetupChoosePlayer
skinnum = description[i].skinnum[0];
if ((skinnum != -1) && (R_SkinUsable(-1, skinnum)))
M_CacheCharacterSelectEntry(i, skinnum);
}
description[i].namepic = (patch_t **)W_GetPatchPointerFromName(description[i].nametag, PU_PATCH);
}
static UINT8 M_SetupChoosePlayerDirect(INT32 choice)
......@@ -9207,10 +9176,6 @@ static void M_DrawSetupChoosePlayerMenu(void)
INT32 x, y;
INT32 w = (vid.width/vid.dupx);
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
if (abs(char_scroll) > FRACUNIT)
char_scroll -= (char_scroll>>2);
else // close enough.
......@@ -9264,11 +9229,11 @@ static void M_DrawSetupChoosePlayerMenu(void)
{
x = 8;
y = (my+16) - FixedInt(char_scroll);
V_DrawScaledPatch(x, y, 0, description[char_on].charpic);
V_DrawScaledPatch(x, y, 0, *description[char_on].charpic);
if (prev != -1)
V_DrawScaledPatch(x, y - 144, 0, description[prev].charpic);
V_DrawScaledPatch(x, y - 144, 0, *description[prev].charpic);
if (next != -1)
V_DrawScaledPatch(x, y + 144, 0, description[next].charpic);
V_DrawScaledPatch(x, y + 144, 0, *description[next].charpic);
}
// Character description
......@@ -9292,14 +9257,14 @@ static void M_DrawSetupChoosePlayerMenu(void)
curtextcolor = description[char_on].tagtextcolor;
curoutlinecolor = description[char_on].tagoutlinecolor;
if (curtext[0] == '\0')
curpatch = description[char_on].namepic;
curpatch = *description[char_on].namepic;
if (!curtextcolor)
curtextcolor = charskin->prefcolor;
if (!curoutlinecolor)
curoutlinecolor = col = skincolors[charskin->prefcolor].invcolor;
txsh = oxsh;
ox = 8 + SHORT((description[char_on].charpic)->width)/2;
ox = 8 + SHORT((*description[char_on].charpic)->width)/2;
y = my + 144;
// cur
......@@ -9330,7 +9295,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
prevtextcolor = description[prev].tagtextcolor;
prevoutlinecolor = description[prev].tagoutlinecolor;
if (prevtext[0] == '\0')
prevpatch = description[prev].namepic;
prevpatch = *description[prev].namepic;
charskin = &skins[description[prev].skinnum[0]];
if (!prevtextcolor)
prevtextcolor = charskin->prefcolor;
......@@ -9360,7 +9325,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
nexttextcolor = description[next].tagtextcolor;
nextoutlinecolor = description[next].tagoutlinecolor;
if (nexttext[0] == '\0')
nextpatch = description[next].namepic;
nextpatch = *description[next].namepic;
charskin = &skins[description[next].skinnum[0]];
if (!nexttextcolor)
nexttextcolor = charskin->prefcolor;
......@@ -10582,10 +10547,6 @@ void M_DrawMarathon(void)
angle_t fa;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
// lactozilla: the renderer changed so recache patches
if (needpatchrecache)
M_CacheCharacterSelect();
curbgxspeed = 0;
curbgyspeed = 18;
......@@ -10719,10 +10680,10 @@ void M_DrawMarathon(void)
if (dispstatus == IT_STRING || dispstatus == IT_WHITESTRING)
{
soffset = 68;
if (description[char_on].charpic->width >= 256)
V_DrawTinyScaledPatch(224, 120, 0, description[char_on].charpic);
if ((*description[char_on].charpic)->width >= 256)
V_DrawTinyScaledPatch(224, 120, 0, *description[char_on].charpic);
else
V_DrawSmallScaledPatch(224, 120, 0, description[char_on].charpic);
V_DrawSmallScaledPatch(224, 120, 0, *description[char_on].charpic);
}
else
soffset = 0;
......@@ -12836,9 +12797,6 @@ static void M_VideoModeMenu(INT32 choice)
memset(modedescs, 0, sizeof(modedescs));
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
VID_PrepareModeList(); // FIXME: hack
#endif
vidm_nummodes = 0;
vidm_selected = 0;
nummodes = VID_NumModes();
......
......@@ -351,7 +351,7 @@ typedef struct
char notes[441];
char picname[8];
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
patch_t *charpic;
patch_t **charpic;
UINT8 prev;
UINT8 next;
......@@ -360,7 +360,7 @@ typedef struct
SINT8 skinnum[2];
UINT16 oppositecolor;
char nametag[8];
patch_t *namepic;
patch_t **namepic;
UINT16 tagtextcolor;
UINT16 tagoutlinecolor;
} description_t;
......
......@@ -29,6 +29,7 @@
#include "r_data.h"
#include "r_things.h" // for R_AddSpriteDefs
#include "r_patch.h"
#include "r_rotsprite.h"
#include "r_sky.h"
#include "r_draw.h"
......@@ -3703,14 +3704,12 @@ boolean P_LoadLevel(boolean fromnetsave)
P_SpawnPrecipitation();
#ifdef HWRENDER // not win32 only 19990829 by Kin
// Lactozilla: Free extrasubsectors regardless of renderer.
// Maybe we're not in OpenGL anymore.
if (extrasubsectors)
free(extrasubsectors);
extrasubsectors = NULL;
// stuff like HWR_CreatePlanePolygons is called there
// Free extrasubsectors regardless of the renderer.
HWR_FreeExtraSubsectors();
// Create plane polygons.
if (rendermode == render_opengl)
HWR_SetupLevel();
HWR_LoadLevel();
#endif
// oh god I hope this helps
......@@ -3796,7 +3795,7 @@ boolean P_LoadLevel(boolean fromnetsave)
}
#ifdef HWRENDER
void HWR_SetupLevel(void)
void HWR_LoadLevel(void)
{
// Lactozilla (December 8, 2019)
// Level setup used to free EVERY mipmap from memory.
......@@ -4054,6 +4053,13 @@ boolean P_AddWadFile(const char *wadfilename)
//
S_LoadMusicDefs(wadnum);
//
// recache sprite rotation data
//
#ifdef ROTSPRITE
RotSprite_RecreateAll();
#endif
//
// search for maps
//
......
......@@ -99,7 +99,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave);
#ifdef HWRENDER
void HWR_SetupLevel(void);
void HWR_LoadLevel(void);
#endif
boolean P_AddWadFile(const char *wadfilename);
boolean P_RunSOC(const char *socfilename);
......
......@@ -471,7 +471,7 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache
// Allocate space for full size texture, either single patch or 'composite'
// Build the full textures from patches.
// The texture caching system is a little more hungry of memory, but has
// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed.
// been simplified for the sake of highcolor, dynamic ligthing, & speed.
//
// This is not optimised, but it's supposed to be executed only once
// per level, when enough memory is available.
......@@ -838,8 +838,6 @@ Rloadflats (INT32 i, INT32 w)
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(flatlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
......@@ -939,8 +937,6 @@ Rloadtextures (INT32 i, INT32 w)
patch->lump = texstart + j;
patch->flip = 0;
Z_Unlock(patchlump);
texturewidth[i] = texture->width;
textureheight[i] = texture->height << FRACBITS;
i++;
......
......@@ -688,14 +688,21 @@ typedef struct
#pragma pack()
#endif
// rotsprite
#ifdef ROTSPRITE
typedef struct
{
patch_t *patch[16][ROTANGLES];
UINT16 cached;
} rotsprite_t;
#endif/*ROTSPRITE*/
UINT8 *data;
void **columnofs;
size_t *columnsize;
} pmcache_t;
typedef struct
{
UINT32 width, height;
INT16 leftoffset, topoffset;
size_t size;
INT32 *map;
pmcache_t cache;
} pixelmap_t;
typedef enum
{
......@@ -709,24 +716,6 @@ typedef enum
SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up!
// Same as a patch_t, except just the header
// and the wadnum/lumpnum combination that points
// to wherever the patch is in memory.
struct patchinfo_s
{
INT16 width; // bounding box size
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
UINT16 wadnum; // the software patch lump num for when the patch
UINT16 lumpnum; // was flushed, and we need to re-create it
// next patchinfo_t in memory
struct patchinfo_s *next;
};
typedef struct patchinfo_s patchinfo_t;
//
// Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites.
......@@ -754,10 +743,6 @@ typedef struct
// Flip bits (1 = flip) to use for view angles 0-7/15.
UINT16 flip;
#ifdef ROTSPRITE
rotsprite_t rotsprite;
#endif
} spriteframe_t;
//
......
......@@ -18,7 +18,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "r_local.h"
#include "st_stuff.h" // need ST_HEIGHT
#include "st_stuff.h"
#include "i_video.h"
#include "v_video.h"
#include "m_misc.h"
......@@ -65,9 +65,11 @@ lighttable_t *dc_colormap;
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
fixed_t dc_iscale, dc_texturemid;
UINT8 *dc_source;
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
// soo lets make it a byte on all system for the ASM code
UINT8 *dc_source;
// -----------------------
// translucency stuff here
......
......@@ -150,7 +150,7 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo,
consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_ViewSizeChanged, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
......@@ -180,7 +180,7 @@ void SplitScreen_OnChange(void)
}
// recompute screen size
R_ExecuteSetViewSize();
R_SetViewSize();
if (!demoplayback && !botingame)
{
......@@ -210,7 +210,7 @@ static void Fov_OnChange(void)
//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
// CV_Set(&cv_fov, cv_fov.defaultvalue);
R_SetViewSize();
R_ViewSizeChanged();
}
static void ChaseCam_OnChange(void)
......@@ -642,7 +642,7 @@ void R_CheckViewMorph(void)
viewmorph.use = false;
viewmorph.x1 = 0;
if (viewmorph.zoomneeded != FRACUNIT)
R_SetViewSize();
R_ViewSizeChanged();
viewmorph.zoomneeded = FRACUNIT;
return;
......@@ -692,7 +692,7 @@ void R_CheckViewMorph(void)
if (temp != viewmorph.zoomneeded)
{
viewmorph.zoomneeded = temp;
R_SetViewSize();
R_ViewSizeChanged();
}
zoomfactor = FIXED_TO_FLOAT(viewmorph.zoomneeded);
......@@ -864,22 +864,22 @@ void R_ApplyViewMorph(void)
//
// R_SetViewSize
// R_ViewSizeChanged
// Do not really change anything here,
// because it might be in the middle of a refresh.
// The change will take effect next refresh.
//
boolean setsizeneeded;
void R_SetViewSize(void)
void R_ViewSizeChanged(void)
{
setsizeneeded = true;
}
//
// R_ExecuteSetViewSize
// R_SetViewSize
//
void R_ExecuteSetViewSize(void)
void R_SetViewSize(void)
{
fixed_t dy;
INT32 i;
......@@ -981,7 +981,7 @@ void R_Init(void)
//I_OutputMsg("\nR_InitViewBorder");
R_InitViewBorder();
R_SetViewSize(); // setsizeneeded is set true
R_ViewSizeChanged(); // setsizeneeded is set true
//I_OutputMsg("\nR_InitPlanes");
R_InitPlanes();
......@@ -1542,26 +1542,6 @@ void R_RenderPlayerView(player_t *player)
free(masks);
}
// Lactozilla: Renderer switching
#ifdef HWRENDER
void R_InitHardwareMode(void)
{
HWR_AddSessionCommands();
HWR_Switch();
HWR_LoadTextures(numtextures);
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))
HWR_SetupLevel();
}
#endif
void R_ReloadHUDGraphics(void)
{
CONS_Debug(DBG_RENDER, "R_ReloadHUDGraphics()...\n");
ST_LoadGraphics();
HU_LoadGraphics();
ST_ReloadSkinFaceGraphics();
}
// =========================================================================
// ENGINE COMMANDS & VARS
// =========================================================================
......
......@@ -111,21 +111,14 @@ extern consvar_t cv_tailspickup;
// Called by startup code.
void R_Init(void);
#ifdef HWRENDER
void R_InitHardwareMode(void);
#endif
void R_ReloadHUDGraphics(void);
void R_CheckViewMorph(void);
void R_ApplyViewMorph(void);
// just sets setsizeneeded true
extern boolean setsizeneeded;
void R_ViewSizeChanged(void); // sets setsizeneeded true
void R_SetViewSize(void);
// do it (sometimes explicitly called)
void R_ExecuteSetViewSize(void);
void R_SetupFrame(player_t *player);
void R_SkyboxFrame(player_t *player);
......
......@@ -10,7 +10,7 @@
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_patch.c
/// \brief Patch generation.
/// \brief Patch caching and generation.
#include "byteptr.h"
#include "dehacked.h"
......@@ -19,6 +19,7 @@
#include "r_draw.h"
#include "r_patch.h"
#include "r_things.h"
#include "r_rotsprite.h"
#include "z_zone.h"
#include "w_wad.h"
......@@ -50,6 +51,356 @@
static unsigned char imgbuf[1<<26];
// ==========================================================================
// CACHING OF GRAPHIC PATCH RESOURCES
// ==========================================================================
// Graphic 'patches' are loaded, and if necessary, converted into the format
// the most useful for the current render mode. For the software renderer, the
// graphic patches are kept as is. For the hardware renderer, graphic patches
// are 'unpacked', and are kept into the cache in that unpacked format, and
// the heap memory cache then acts as a 'level 2' cache just after the
// graphics card memory.
// If patches need to be cached only once, references to those patches
// can be obtained with W_GetPatchPointer and relatives. By returning a
// double pointer that can be dereferenced, the addresses of the patches
// can be swapped out to point to another patch instead. The main use case
// for this is renderer switching.
static patchreference_t *patchlist_head = NULL;
static patchreference_t *patchlist_tail = NULL;
// Find patch in list
patchreference_t *Patch_FindReference(UINT16 wad, UINT16 lump, INT32 rollangle, boolean flip)
{
patchreference_t *patch = patchlist_head;
CONS_Debug(DBG_RENDER, "Patch_FindReference: searching for %s (%d)\n", W_CheckNameForNumPwad(wad, lump), rollangle);
while (patch)
{
patchreference_t *prev = NULL, *next = NULL;
if (patch->wad == wad && patch->lump == lump && patch->rollangle == rollangle && patch->flip == flip)
{
CONS_Debug(DBG_RENDER, "found\n");
return patch;
}
// Lazy memory deallocation.
// References aren't removed until an iteration
// knows the pointer isn't valid anymore.
next = patch->next;
if (patch->ptr == NULL)
{
CONS_Debug(DBG_RENDER, "freeing %s (%d) in the list\n", W_CheckNameForNumPwad(patch->wad, patch->lump), patch->rollangle);
prev = patch->prev;
if (prev)
prev->next = next;
Z_Free(patch);
}
patch = next;
}
CONS_Debug(DBG_RENDER, "not found\n");
return NULL;
}
// Insert patch in list
patchreference_t *Patch_StoreReference(UINT16 wad, UINT16 lump, INT32 tag, void *ptr, INT32 rollangle, boolean flip)
{
patchreference_t *found = Patch_FindReference(wad, lump, rollangle, flip);
if (found)
return found;
CONS_Debug(DBG_RENDER, "Patch_StoreReference: storing %s (%d)\n", W_CheckNameForNumPwad(wad, lump), rollangle);
if (!patchlist_head)
{
patchlist_head = Z_Calloc(sizeof(patchreference_t), PU_STATIC, NULL);
patchlist_head->wad = wad;
patchlist_head->lump = lump;
patchlist_head->tag = tag;
patchlist_head->ptr = ptr;
patchlist_head->rollangle = rollangle;
patchlist_head->flip = flip;
patchlist_tail = patchlist_head;
return patchlist_head;
}
else
{
patchreference_t *list = Z_Calloc(sizeof(patchreference_t), PU_STATIC, NULL);
list->wad = wad;
list->lump = lump;
list->tag = tag;
list->ptr = ptr;
list->rollangle = rollangle;
list->flip = flip;
list->prev = patchlist_tail; // set the previous item to the tail
patchlist_tail->next = list; // set the tail's next item to the new item
patchlist_tail = list; // set the tail to the new item
return list;
}
}
// Get patch tree type from a render mode.
patchtreetype_t Patch_GetTreeType(rendermode_t mode)
{
return (mode == render_opengl) ? patchtree_mipmap : patchtree_software;
}
// Get patch tree.
patchtree_t *Patch_GetRendererTree(UINT16 wadnum, rendermode_t mode)
{
return &(wadfiles[wadnum]->patchinfo.renderer[Patch_GetTreeType(mode)]);
}
// Get patch base subtree.
aatree_t *Patch_GetRendererBaseSubTree(UINT16 wadnum, rendermode_t mode)
{
return Patch_GetRendererTree(wadnum, mode)->base;
}
#ifdef ROTSPRITE
// Get rotated patch subtree.
aatree_t *Patch_GetRendererRotatedSubTree(UINT16 wadnum, rendermode_t mode, boolean flip)
{
UINT8 f = (flip == true) ? 1 : 0;
return Patch_GetRendererTree(wadnum, mode)->rotated[f];
}
#endif
//
// Initializes patch info for a WAD file.
//
void Patch_InitInfo(wadfile_t *wadfile)
{
patchinfo_t *cache = &wadfile->patchinfo;
rendermode_t rmode;
// Patch info is uninitialized.
memset(cache, 0x00, sizeof(patchinfo_t));
// Main patch cache for the current renderer
Z_Calloc(wadfile->numlumps * sizeof(lumpcache_t), PU_STATIC, &cache->current);
#ifdef ROTSPRITE
// Rotated patch cache for the current renderer
Z_Calloc(wadfile->numlumps * sizeof(lumpcache_t *), PU_STATIC, &cache->rotated);
#endif
// Patch trees for each renderer
for (rmode = render_first; rmode < render_last; rmode++)
{
patchtree_t *rcache = &(cache->renderer[Patch_GetTreeType(rmode)]);
// Multiple renderers can point to the same tree.
// If this tree was already initialized, then
// don't try initializing it again.
if (rcache->base)
continue;
rcache->base = M_AATreeAlloc(AATREE_ZUSER);
#ifdef ROTSPRITE
RotSprite_InitPatchTree(rcache);
#endif
}
}
// Get renderer patch info.
void *GetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode)
{
return M_AATreeGet(Patch_GetRendererBaseSubTree(wadnum, mode), lumpnum);
}
// Set renderer patch info.
void SetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, void *ptr)
{
M_AATreeSet(Patch_GetRendererBaseSubTree(wadnum, mode), lumpnum, ptr);
}
// Update current patch info.
void UpdateCurrentPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode)
{
wadfiles[wadnum]->patchinfo.current[lumpnum] = GetRendererPatchInfo(wadnum, lumpnum, mode);
}
#ifdef ROTSPRITE
void RotSprite_InitPatchTree(patchtree_t *rcache)
{
INT32 i;
for (i = 0; i < 2; i++)
rcache->rotated[i] = M_AATreeAlloc(AATREE_ZUSER);
}
int RotSprite_GetCurrentPatchInfoIdx(INT32 rollangle, boolean flip)
{
UINT8 f = (flip == true) ? 1 : 0;
return rollangle + (ROTANGLES * f);
}
void RotSprite_AllocCurrentPatchInfo(patchinfo_t *patchinfo, UINT16 lumpnum)
{
patchinfo->rotated[lumpnum] = Z_Calloc((ROTANGLES * 2) * sizeof(lumpcache_t), PU_STATIC, NULL);
}
// Get renderer rotated patch info.
void *GetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip)
{
return M_AATreeGet(Patch_GetRendererRotatedSubTree(wadnum, mode, flip), lumpnum);
}
// Set renderer rotated patch info.
void SetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip, void *ptr)
{
M_AATreeSet(Patch_GetRendererRotatedSubTree(wadnum, mode, flip), lumpnum, ptr);
}
// Update current rotated patch info.
void UpdateCurrentRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, INT32 rollangle, boolean flip)
{
patchinfo_t *patchinfo = &wadfiles[wadnum]->patchinfo;
if (!patchinfo->rotated[lumpnum])
RotSprite_AllocCurrentPatchInfo(patchinfo, lumpnum);
patchinfo->rotated[lumpnum][RotSprite_GetCurrentPatchInfoIdx(rollangle, flip)] = ((rotsprite_t *)GetRotatedPatchInfo(wadnum, lumpnum, mode, flip))->patches[rollangle];
}
#endif
void *Patch_CacheSoftware(UINT16 wad, UINT16 lump, INT32 tag, boolean store)
{
void *cache = GetRendererPatchInfo(wad, lump, render_soft);
if (!GetRendererPatchInfo(wad, lump, render_soft))
{
size_t len = W_LumpLengthPwad(wad, lump);
void *ptr, *lumpdata;
#ifndef NO_PNG_LUMPS
void *converted = NULL;
#endif
ptr = Z_Malloc(len, tag, &cache);
lumpdata = Z_Malloc(len, tag, NULL);
// read the lump in full
W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0);
#ifndef NO_PNG_LUMPS
// lump is a png so convert it
if (R_IsLumpPNG((UINT8 *)lumpdata, len))
{
size_t newlen;
converted = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen);
ptr = Z_Realloc(ptr, newlen, tag, &cache);
M_Memcpy(ptr, converted, newlen);
Z_Free(converted);
}
else // just copy it into the patch cache
#endif
M_Memcpy(ptr, lumpdata, len);
// insert into list
if (store)
Patch_StoreReference(wad, lump, tag, ptr, 0, false);
SetRendererPatchInfo(wad, lump, render_soft, ptr);
UpdateCurrentPatchInfo(wad, lump, render_soft);
return ptr;
}
else
Z_ChangeTag(cache, tag);
return cache;
}
#ifdef HWRENDER
void *Patch_CacheGL(UINT16 wad, UINT16 lump, INT32 tag, boolean store)
{
GLPatch_t *grPatch = HWR_GetCachedGLPatchPwad(wad, lump, Patch_GetRendererBaseSubTree(wad, render_opengl));
if (grPatch->mipmap->data)
{
if (tag == PU_CACHE)
tag = PU_HWRCACHE;
Z_ChangeTag(grPatch->mipmap->data, tag);
}
else
{
patch_t *ptr = NULL;
// Only load the patch if we haven't initialised the grPatch yet
if (grPatch->mipmap->width == 0)
ptr = W_CacheLumpNumPwad(grPatch->wadnum, grPatch->lumpnum, PU_STATIC);
// Run HWR_MakePatch in all cases, to recalculate some things
HWR_MakePatch(ptr, grPatch, grPatch->mipmap, false);
Z_Free(ptr);
// insert into list
if (store)
Patch_StoreReference(wad, lump, tag, (void *)grPatch, 0, false);
UpdateCurrentPatchInfo(wad, lump, render_opengl);
}
// return GLPatch_t, which can be casted to (patch_t *) with valid patch header info
return (void *)grPatch;
}
#endif
//
// Update patch references to point to the current renderer's patches.
//
void Patch_UpdateReferences(void)
{
patchreference_t *patch = patchlist_head;
while (patch)
{
CONS_Debug(DBG_RENDER, "Patch_UpdateReferences: %s (%d)\n", W_CheckNameForNumPwad(patch->wad, patch->lump), patch->rollangle);
#ifdef ROTSPRITE
if (patch->rollangle)
{
static rotsprite_vars_t rsvars;
rsvars.rollangle = patch->rollangle;
rsvars.flip = patch->flip;
Patch_CacheRotatedPwad(patch->wad, patch->lump, patch->tag, rsvars, false);
UpdateCurrentRotatedPatchInfo(patch->wad, patch->lump, rendermode, patch->rollangle, patch->flip);
}
else
#endif
{
#ifdef HWRENDER
if (rendermode == render_opengl)
Patch_CacheGL(patch->wad, patch->lump, patch->tag, false);
else
#endif
Patch_CacheSoftware(patch->wad, patch->lump, patch->tag, false);
UpdateCurrentPatchInfo(patch->wad, patch->lump, rendermode);
}
patch = patch->next;
}
}
//
// Free the patch reference list.
//
void Patch_FreeReferences(void)
{
patchreference_t *patch = patchlist_head;
while (patch)
{
patchreference_t *next = patch->next;
Z_Free(patch);
patch = next;
}
}
//
// R_CheckIfPatch
//
......@@ -198,47 +549,6 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat)
}
}
//
// R_PatchToMaskedFlat
//
// Convert a patch to a masked flat.
// Now, what is a "masked" flat anyway?
// It means the flat uses two bytes to store image data.
// The upper byte is used to store the transparent pixel,
// and the lower byte stores a palette index.
//
void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip)
{
fixed_t col, ofs;
column_t *column;
UINT16 *desttop, *dest, *deststop;
UINT8 *source;
desttop = raw;
deststop = desttop + (SHORT(patch->width) * SHORT(patch->height));
for (col = 0; col < SHORT(patch->width); col++, desttop++)
{
INT32 topdelta, prevdelta = -1;
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-col) : col]));
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
dest = desttop + (topdelta * SHORT(patch->width));
source = (UINT8 *)(column) + 3;
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
{
*dest = source[ofs];
dest += SHORT(patch->width);
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
}
//
// R_FlatToPatch
//
......@@ -354,12 +664,11 @@ patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffse
}
//
// R_MaskedFlatToPatch
// R_TransparentFlatToPatch
//
// Convert a masked flat to a patch.
// Explanation of "masked" flats in R_PatchToMaskedFlat.
// Convert a transparent flat to a patch.
//
patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize)
patch_t *R_TransparentFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize)
{
UINT32 x, y;
UINT8 *img;
......@@ -687,7 +996,7 @@ static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topo
}
// Convert a PNG with transparency to a raw image.
static UINT16 *PNG_MaskedRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size)
static UINT16 *PNG_TransparentRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, INT16 *leftoffset, size_t size)
{
UINT16 *flat;
png_uint_32 x, y;
......@@ -696,7 +1005,7 @@ static UINT16 *PNG_MaskedRawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT1
size_t flatsize, i;
if (!row_pointers)
I_Error("PNG_MaskedRawConvert: conversion failed");
I_Error("PNG_TransparentRawConvert: conversion failed");
// Convert the image to 16bpp
flatsize = (width * height);
......@@ -740,12 +1049,12 @@ patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize)
{
UINT16 width, height;
INT16 topoffset = 0, leftoffset = 0;
UINT16 *raw = PNG_MaskedRawConvert(png, &width, &height, &topoffset, &leftoffset, size);
UINT16 *raw = PNG_TransparentRawConvert(png, &width, &height, &topoffset, &leftoffset, size);
if (!raw)
I_Error("R_PNGToPatch: conversion failed");
return R_MaskedFlatToPatch(raw, width, height, leftoffset, topoffset, destsize);
return R_TransparentFlatToPatch(raw, width, height, leftoffset, topoffset, destsize);
}
//
......@@ -979,11 +1288,6 @@ static void R_ParseSpriteInfo(boolean spr2)
info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL);
info->available = true;
#ifdef ROTSPRITE
if ((sprites != NULL) && (!spr2))
R_FreeSingleRotSprite(&sprites[sprnum]);
#endif
// Left Curly Brace
sprinfoToken = M_GetToken(NULL);
if (sprinfoToken == NULL)
......@@ -1035,18 +1339,17 @@ static void R_ParseSpriteInfo(boolean spr2)
{
R_ParseSpriteInfoFrame(info);
Z_Free(sprinfoToken);
if (spr2)
{
if (!foundskins)
I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition");
for (i = 0; i < foundskins; i++)
{
size_t skinnum = skinnumbers[i];
skin_t *skin = &skins[skinnum];
spriteinfo_t *sprinfo = skin->sprinfo;
#ifdef ROTSPRITE
R_FreeSkinRotSprite(skinnum);
#endif
M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t));
}
}
......@@ -1137,7 +1440,7 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps)
}
}
static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip)
UINT8 *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y, boolean flip)
{
fixed_t ofs;
column_t *column;
......@@ -1146,7 +1449,7 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip)
if (x >= 0 && x < SHORT(patch->width))
{
INT32 topdelta, prevdelta = -1;
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x]));
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (SHORT(patch->width)-1-x) : x]));
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
......@@ -1157,324 +1460,200 @@ static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip)
for (ofs = 0; ofs < column->length; ofs++)
{
if ((topdelta + ofs) == y)
return source[ofs];
return &source[ofs];
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
return 0xFF00;
return NULL;
}
#ifdef ROTSPRITE
//
// R_GetRollAngle
//
// Angles precalculated in R_InitSprites.
//
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
INT32 R_GetRollAngle(angle_t rollangle)
boolean PixelMap_ApplyToColumn(pixelmap_t *pmap, INT32 *map, patch_t *patch, UINT8 *post, size_t *colsize, boolean flipped)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
//
// R_CacheRotSprite
//
// Create a rotated sprite.
//
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip)
{
UINT32 i;
INT32 angle;
patch_t *patch;
patch_t *newpatch;
UINT16 *rawdst;
size_t size;
INT32 bflip = (flip != 0x00);
#define SPRITE_XCENTER (leftoffset)
#define SPRITE_YCENTER (height / 2)
#define ROTSPRITE_XCENTER (newwidth / 2)
#define ROTSPRITE_YCENTER (newheight / 2)
if (!(sprframe->rotsprite.cached & (1<<rot)))
INT32 x, y;
size_t pmsize = pmap->size;
size_t i = 0;
int lastStartY = 0;
int spanSize = 0;
UINT8 *px, *startofspan = NULL, *dest = post;
boolean written = false;
while (i < pmap->height)
{
INT32 dx, dy;
INT32 px, py;
INT32 width, height, leftoffset;
fixed_t ca, sa;
lumpnum_t lump = sprframe->lumppat[rot];
#ifndef NO_PNG_LUMPS
size_t lumplength;
#endif
if (lump == LUMPERROR)
return;
y = map[i];
x = map[i + pmsize];
px = Patch_GetPixel(patch, x, y, flipped); // If not NULL, we have a pixel
i++;
patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC);
#ifndef NO_PNG_LUMPS
lumplength = W_LumpLength(lump);
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
patch = R_PNGToPatch((UINT8 *)patch, lumplength, NULL);
else
#endif
// Because there's something wrong with SPR_DFLM, I guess
if (!R_CheckIfPatch(lump))
return;
width = SHORT(patch->width);
height = SHORT(patch->height);
leftoffset = SHORT(patch->leftoffset);
// rotation pivot
px = SPRITE_XCENTER;
py = SPRITE_YCENTER;
// get correct sprite info for sprite
if (sprinfo == NULL)
sprinfo = &spriteinfo[sprnum];
if (sprinfo->available)
{
px = sprinfo->pivot[frame].x;
py = sprinfo->pivot[frame].y;
}
if (bflip)
// End span if we have a transparent pixel
if (px == NULL)
{
px = width - px;
leftoffset = width - leftoffset;
if (startofspan)
WRITEUINT8(dest, 0);
startofspan = NULL;
continue;
}
// Don't cache angle = 0
for (angle = 1; angle < ROTANGLES; angle++)
// Start new column if we need to
if (!startofspan || spanSize == 255)
{
INT32 newwidth, newheight;
ca = rollcosang[angle];
sa = rollsinang[angle];
int writeY = i;
// Find the dimensions of the rotated patch.
{
INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa));
INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa));
INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca));
INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
newwidth = max(width, max(w1, w2));
newheight = max(height, max(h1, h2));
}
// If we reached the span size limit, finish the previous span
if (startofspan)
WRITEUINT8(dest, 0);
// check boundaries
if (i > 254)
{
fixed_t top[2][2];
fixed_t bottom[2][2];
top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS);
bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS);
top[0][0] >>= FRACBITS;
top[0][1] >>= FRACBITS;
top[1][0] >>= FRACBITS;
top[1][1] >>= FRACBITS;
bottom[0][0] >>= FRACBITS;
bottom[0][1] >>= FRACBITS;
bottom[1][0] >>= FRACBITS;
bottom[1][1] >>= FRACBITS;
#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width)
#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height)
#define BOUNDARYADJUST(x) x *= 2
// top left/right
if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1]))
BOUNDARYADJUST(newwidth);
// bottom left/right
else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1]))
BOUNDARYADJUST(newwidth);
// top left/right
if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1]))
BOUNDARYADJUST(newheight);
// bottom left/right
else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1]))
BOUNDARYADJUST(newheight);
#undef BOUNDARYWCHECK
#undef BOUNDARYHCHECK
#undef BOUNDARYADJUST
}
// Draw the rotated sprite to a temporary buffer.
size = (newwidth * newheight);
if (!size)
size = (width * height);
// Make sure we're aligned to 254
if (lastStartY < 254)
{
WRITEUINT8(dest, 254);
WRITEUINT8(dest, 0);
dest += 2;
lastStartY = 254;
}
rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL);
for (i = 0; i < size; i++)
rawdst[i] = 0xFF00;
// Write stopgap empty spans if needed
writeY = y - lastStartY;
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
while (writeY > 254)
{
INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS;
INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS;
INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS);
INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS);
sx >>= FRACBITS;
sy >>= FRACBITS;
if (sx >= 0 && sy >= 0 && sx < width && sy < height)
rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip);
WRITEUINT8(dest, 254);
WRITEUINT8(dest, 0);
dest += 2;
writeY -= 254;
}
}
// make patch
newpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size);
{
newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px);
newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py);
}
startofspan = dest;
WRITEUINT8(dest, writeY);
dest += 2;
spanSize = 0;
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
if (rendermode != render_none) // not for psprite
newpatch->topoffset += FEETADJUST>>FRACBITS;
lastStartY = i;
}
// P_PrecacheLevel
if (devparm) spritememory += size;
// Write the pixel
WRITEUINT8(dest, *px);
spanSize++;
startofspan[1] = spanSize;
written = true;
}
// convert everything to little-endian, for big-endian support
newpatch->width = SHORT(newpatch->width);
newpatch->height = SHORT(newpatch->height);
newpatch->leftoffset = SHORT(newpatch->leftoffset);
newpatch->topoffset = SHORT(newpatch->topoffset);
if (startofspan)
WRITEUINT8(dest, 0);
WRITEUINT8(dest, 0xFF);
#ifdef HWRENDER
if (rendermode == render_opengl)
{
GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
grPatch->rawpatch = newpatch;
sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch;
HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false);
}
else
#endif // HWRENDER
sprframe->rotsprite.patch[rot][angle] = newpatch;
if (colsize)
*colsize = (dest - post);
return written;
}
// free rotated image data
Z_Free(rawdst);
}
#ifdef ROTSPRITE
/** Creates a rotated patch from another patch.
*
* \param wad The patch's wad number.
* \param lump The patch's lump number.
* \param tag Zone memory tag.
* \param rsvars Sprite rotation variables.
* \param store Store the rotated patch into the patch reference list.
* \return The rotated patch.
* \sa Patch_CacheRotatedPwad
*/
patch_t *Patch_CacheRotatedPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
rotsprite_t *rotsprite = RotSprite_GetFromPatchNumPwad(wad, lump, tag, rsvars, store);
patch_t *patch = NULL;
// This rotation is cached now
sprframe->rotsprite.cached |= (1<<rot);
if (rotsprite->patches[rsvars.rollangle])
return rotsprite->patches[rsvars.rollangle];
// free image data
Z_Free(patch);
rsvars.sprite = false;
rotsprite->vars = rsvars;
rotsprite->tag = tag;
RotSprite_Create(rotsprite, rsvars);
patch = RotSprite_CreatePatch(rotsprite, rsvars);
// Caveat: At the point RotSprite_GetFromPatchNum is called, no patch exists yet.
// So, the update has to be done right below here.
if (store)
UpdateCurrentRotatedPatchInfo(wad, lump, rendermode, rsvars.rollangle, rsvars.flip);
#ifdef HWRENDER
if (rendermode != render_opengl) // uuggghhhhh
#endif
{
Z_ChangeTag(patch, tag);
Z_SetUser(patch, (void **)(&rotsprite->patches[rsvars.rollangle]));
}
#undef SPRITE_XCENTER
#undef SPRITE_YCENTER
#undef ROTSPRITE_XCENTER
#undef ROTSPRITE_YCENTER
return patch;
}
//
// R_FreeSingleRotSprite
//
// Free sprite rotation data from memory, for a single spritedef.
//
void R_FreeSingleRotSprite(spritedef_t *spritedef)
/** Creates a rotated patch from a sprite.
*
* \param wad The sprite's wad number.
* \param lump The sprite's lump number.
* \param tag Zone memory tag.
* \param rsvars Sprite rotation variables.
* \param store Store the rotated sprite into the patch reference list.
* \return The rotated sprite.
* \sa Patch_CacheRotatedPwad
*/
patch_t *Patch_CacheRotatedForSpritePwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
UINT8 frame;
INT32 rot, ang;
lumpnum_t lumpnum = WADANDLUMP(wad, lump);
rotsprite_t *rotsprite = RotSprite_GetFromPatchNum(lumpnum, tag, rsvars, store);
patch_t *patch = NULL;
if (rotsprite->patches[rsvars.rollangle])
return rotsprite->patches[rsvars.rollangle];
rsvars.sprite = true;
rotsprite->vars = rsvars;
rotsprite->tag = tag;
RotSprite_Create(rotsprite, rsvars);
patch = RotSprite_CreatePatch(rotsprite, rsvars);
for (frame = 0; frame < spritedef->numframes; frame++)
{
spriteframe_t *sprframe = &spritedef->spriteframes[frame];
for (rot = 0; rot < 16; rot++)
{
if (sprframe->rotsprite.cached & (1<<rot))
{
for (ang = 0; ang < ROTANGLES; ang++)
{
patch_t *rotsprite = sprframe->rotsprite.patch[rot][ang];
if (rotsprite)
{
#ifdef HWRENDER
if (rendermode == render_opengl)
{
GLPatch_t *grPatch = (GLPatch_t *)rotsprite;
if (grPatch->rawpatch)
{
Z_Free(grPatch->rawpatch);
grPatch->rawpatch = NULL;
}
if (grPatch->mipmap)
{
if (grPatch->mipmap->data)
{
Z_Free(grPatch->mipmap->data);
grPatch->mipmap->data = NULL;
}
Z_Free(grPatch->mipmap);
grPatch->mipmap = NULL;
}
}
if (rendermode != render_opengl) // uuggghhhhh
#endif
Z_Free(rotsprite);
}
}
sprframe->rotsprite.cached &= ~(1<<rot);
}
}
{
Z_ChangeTag(patch, tag);
Z_SetUser(patch, (void **)(&rotsprite->patches[rsvars.rollangle]));
}
return patch;
}
//
// R_FreeSkinRotSprite
//
// Free sprite rotation data from memory, for a skin.
// Calls R_FreeSingleRotSprite.
//
void R_FreeSkinRotSprite(size_t skinnum)
patch_t *Patch_CacheRotated(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
size_t i;
skin_t *skin = &skins[skinnum];
spritedef_t *skinsprites = skin->sprites;
for (i = 0; i < NUMPLAYERSPRITES*2; i++)
{
R_FreeSingleRotSprite(skinsprites);
skinsprites++;
}
return Patch_CacheRotatedPwad(WADFILENUM(lumpnum), LUMPNUM(lumpnum), tag, rsvars, store);
}
//
// R_FreeAllRotSprite
//
// Free ALL sprite rotation data from memory.
//
void R_FreeAllRotSprite(void)
patch_t *Patch_CacheRotatedForSprite(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
INT32 i;
size_t s;
for (s = 0; s < numsprites; s++)
R_FreeSingleRotSprite(&sprites[s]);
for (i = 0; i < numskins; ++i)
R_FreeSkinRotSprite(i);
return Patch_CacheRotatedForSpritePwad(WADFILENUM(lumpnum), LUMPNUM(lumpnum), tag, rsvars, store);
}
patch_t *Patch_CacheRotatedName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
lumpnum_t num = W_CheckNumForName(name);
if (num == LUMPERROR)
return Patch_CacheRotated(W_GetNumForName("MISSING"), tag, rsvars, store);
return Patch_CacheRotated(num, tag, rsvars, store);
}
patch_t *Patch_CacheRotatedLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
lumpnum_t num = W_CheckNumForLongName(name);
if (num == LUMPERROR)
return Patch_CacheRotated(W_GetNumForLongName("MISSING"), tag, rsvars, store);
return Patch_CacheRotated(num, tag, rsvars, store);
}
#endif
......@@ -15,9 +15,53 @@
#define __R_PATCH__
#include "r_defs.h"
#include "r_patchtrees.h"
#include "w_wad.h"
#include "m_aatree.h"
#include "i_video.h"
#include "doomdef.h"
// Structs
void Patch_InitInfo(wadfile_t *wadfile);
void *Patch_CacheSoftware(UINT16 wad, UINT16 lump, INT32 tag, boolean store);
void *Patch_CacheGL(UINT16 wad, UINT16 lump, INT32 tag, boolean store);
patchtreetype_t Patch_GetTreeType(rendermode_t mode);
patchtree_t *Patch_GetRendererTree(UINT16 wadnum, rendermode_t mode);
aatree_t *Patch_GetRendererBaseSubTree(UINT16 wadnum, rendermode_t mode);
#ifdef ROTSPRITE
aatree_t *Patch_GetRendererRotatedSubTree(UINT16 wadnum, rendermode_t mode, boolean flip);
#endif
void *GetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode);
void SetRendererPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, void *ptr);
void UpdateCurrentPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode);
#ifdef ROTSPRITE
void *GetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip);
void SetRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, boolean flip, void *ptr);
void UpdateCurrentRotatedPatchInfo(UINT16 wadnum, UINT16 lumpnum, rendermode_t mode, INT32 rollangle, boolean flip);
#endif
struct patchreference_s
{
struct patchreference_s *prev, *next;
UINT16 wad, lump;
INT32 tag;
boolean flip;
INT32 rollangle;
void *ptr;
};
typedef struct patchreference_s patchreference_t;
patchreference_t *Patch_FindReference(UINT16 wad, UINT16 lump, INT32 rollangle, boolean flip);
patchreference_t *Patch_StoreReference(UINT16 wad, UINT16 lump, INT32 tag, void *ptr, INT32 rollangle, boolean flip);
void Patch_UpdateReferences(void);
void Patch_FreeReferences(void);
// This should be in r_rotsprite.h, but that file
// includes this one, so this file can't include that one.
typedef enum
{
ROTAXIS_X, // Roll (the default)
......@@ -33,19 +77,21 @@ typedef struct
typedef struct
{
spriteframepivot_t pivot[64];
spriteframepivot_t pivot[64]; // Max number of frames in a sprite.
boolean available;
} spriteinfo_t;
boolean PixelMap_ApplyToColumn(pixelmap_t *pmap, INT32 *map, patch_t *patch, UINT8 *post, size_t *colsize, boolean flipped);
UINT8 *Patch_GetPixel(patch_t *patch, INT32 x, INT32 y, boolean flip);
// Conversions between patches / flats / textures...
boolean R_CheckIfPatch(lumpnum_t lump);
void R_TextureToFlat(size_t tex, UINT8 *flat);
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
void R_PatchToMaskedFlat(patch_t *patch, UINT16 *raw, boolean flip);
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency);
patch_t *R_MaskedFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize);
patch_t *R_TransparentFlatToPatch(UINT16 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize);
// Portable Network Graphics
// PNGs
boolean R_IsLumpPNG(const UINT8 *d, size_t s);
#define W_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic
......@@ -62,13 +108,24 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum);
// Sprite rotation
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip);
void R_FreeSingleRotSprite(spritedef_t *spritedef);
void R_FreeSkinRotSprite(size_t skinnum);
// Arguments for RotSprite_ functions.
typedef struct
{
INT32 rollangle;
boolean flip;
boolean sprite;
spriteframepivot_t *pivot;
} rotsprite_vars_t;
patch_t *Patch_CacheRotated(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store);
patch_t *Patch_CacheRotatedForSprite(UINT32 lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store);
patch_t *Patch_CacheRotatedPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store);
patch_t *Patch_CacheRotatedForSpritePwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store);
patch_t *Patch_CacheRotatedName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store);
patch_t *Patch_CacheRotatedLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store);
extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
void R_FreeAllRotSprite(void);
#endif
#endif // __R_PATCH__
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_patchtrees.h
/// \brief Patch tree definitions.
#ifndef __R_PATCHTREES__
#define __R_PATCHTREES__
#include "m_aatree.h"
// Renderer tree types
typedef enum patchtreetype_e
{
patchtree_software, // Software.
patchtree_mipmap, // OpenGL, or any hardware renderer.
num_patchtrees,
} patchtreetype_t;
// Renderer patch trees
typedef struct patchtree_s
{
aatree_t *base;
#ifdef ROTSPRITE
aatree_t *rotated[2]; // Sprite rotation stores flipped and non-flipped variants of a patch.
#endif
} patchtree_t;
#endif // __R_PATCHTREES__
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2019-2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2019-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_rotsprite.c
/// \brief Rotated patch generation.
#include "byteptr.h"
#include "dehacked.h"
#include "i_video.h"
#include "r_data.h"
#include "r_draw.h"
#include "r_patch.h"
#include "r_rotsprite.h"
#include "r_things.h"
#include "z_zone.h"
#include "w_wad.h"
#ifdef HWRENDER
#include "hardware/hw_glob.h"
#endif
#ifdef ROTSPRITE
fixed_t rollcosang[ROTANGLES];
fixed_t rollsinang[ROTANGLES];
static unsigned char imgbuf[1<<26];
/** Get a rotation angle from a roll angle.
*
* \param rollangle The roll angle.
* \return The rotation angle.
*/
INT32 R_GetRollAngle(angle_t rollangle)
{
INT32 ra = AngleFixed(rollangle)>>FRACBITS;
#if (ROTANGDIFF > 1)
ra += (ROTANGDIFF/2);
#endif
ra /= ROTANGDIFF;
ra %= ROTANGLES;
return ra;
}
/** Get rotated sprite info for a patch.
*
* \param wad The patch's wad number.
* \param lump The patch's lump number.
* \param tag Zone memory tag.
* \param rsvars Sprite rotation variables.
* \param store Store the rotated patch into the patch reference list.
* \return The rotated sprite info.
* \sa Patch_CacheRotatedPwad
*/
rotsprite_t *RotSprite_GetFromPatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
void *cache = GetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip);
if (!GetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip))
{
rotsprite_t *ptr = Z_Calloc(sizeof(rotsprite_t), tag, &cache);
ptr->lumpnum = WADANDLUMP(wad, lump);
SetRotatedPatchInfo(wad, lump, rendermode, rsvars.flip, cache);
return (void *)ptr;
}
else
Z_ChangeTag(cache, tag);
// insert into list
if (store)
Patch_StoreReference(wad, lump, tag, cache, rsvars.rollangle, rsvars.flip);
return cache;
}
rotsprite_t *RotSprite_GetFromPatchNum(lumpnum_t lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
return RotSprite_GetFromPatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag,rsvars,store);
}
rotsprite_t *RotSprite_GetFromPatchName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
lumpnum_t num = W_CheckNumForName(name);
if (num == LUMPERROR)
return RotSprite_GetFromPatchNum(W_GetNumForName("MISSING"), tag, rsvars, store);
return RotSprite_GetFromPatchNum(num, tag, rsvars, store);
}
rotsprite_t *RotSprite_GetFromPatchLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store)
{
lumpnum_t num = W_CheckNumForLongName(name);
if (num == LUMPERROR)
return RotSprite_GetFromPatchNum(W_GetNumForLongName("MISSING"), tag, rsvars, store);
return RotSprite_GetFromPatchNum(num, tag, rsvars, store);
}
/** Creates a rotated sprite by calculating a pixel map.
* Caches column data and patches between levels.
*
* \param rotsprite The rotated sprite info.
* \param rsvars Sprite rotation variables.
* \sa RotSprite_CreatePatch
*/
void RotSprite_Create(rotsprite_t *rotsprite, rotsprite_vars_t rsvars)
{
patch_t *patch;
pixelmap_t *pixelmap = &rotsprite->pixelmap[rsvars.rollangle];
lumpnum_t lump = rotsprite->lumpnum;
// Sprite lump is invalid.
if (lump == LUMPERROR)
return;
// Cache the patch.
patch = (patch_t *)W_CacheSoftwarePatchNum(lump, PU_CACHE);
// If this pixel map was not generated, do it.
if (!rotsprite->cached[rsvars.rollangle])
{
RotSprite_CreatePixelMap(patch, pixelmap, rsvars);
rotsprite->cached[rsvars.rollangle] = true;
}
}
/** Caches columns of a rotated sprite, applying the pixel map.
*
* \param pixelmap The source pixel map.
* \param cache The destination pixel map cache.
* \param patch The source patch.
* \param rsvars Sprite rotation variables.
* \sa RotSprite_CreatePatch
*/
void RotSprite_CreateColumns(pixelmap_t *pixelmap, pmcache_t *cache, patch_t *patch, rotsprite_vars_t rsvars)
{
void **colofs;
UINT8 *data;
boolean *colexists;
size_t *coltbl;
static UINT8 pixelmapcol[0xFFFF];
size_t totalsize = 0, colsize = 0;
INT16 width = pixelmap->width, x;
Z_Malloc(width * sizeof(void **), PU_LEVEL, &cache->columnofs);
Z_Malloc(width * sizeof(void *), PU_LEVEL, &cache->columnsize);
colexists = Z_Calloc(width * sizeof(boolean), PU_STATIC, NULL);
coltbl = Z_Calloc(width * sizeof(size_t), PU_STATIC, NULL);
colofs = cache->columnofs;
for (x = 0; x < width; x++)
{
size_t colpos = totalsize;
colexists[x] = PixelMap_ApplyToColumn(pixelmap, &(pixelmap->map[x * pixelmap->height]), patch, pixelmapcol, &colsize, rsvars.flip);
cache->columnsize[x] = colsize;
totalsize += colsize;
// copy pixels
if (colexists[x])
{
data = Z_Realloc(cache->data, totalsize, PU_LEVEL, &cache->data);
data += colpos;
coltbl[x] = colpos;
M_Memcpy(data, pixelmapcol, colsize);
}
}
for (x = 0; x < width; x++)
{
if (colexists[x])
colofs[x] = &(cache->data[coltbl[x]]);
else
colofs[x] = NULL;
}
Z_Free(colexists);
Z_Free(coltbl);
}
/** Calculates the dimensions of a rotated rectangle.
*
* \param width Rectangle width.
* \param height Rectangle height.
* \param ca Cosine for the angle.
* \param sa Sine for the angle.
* \param pivot Rotation pivot.
* \param newwidth The width for the rotated rectangle.
* \param newheight The height for the rotated rectangle.
* \sa RotSprite_CreatePixelMap
*/
static void CalculateRotatedRectangleDimensions(INT16 width, INT16 height, fixed_t ca, fixed_t sa, spriteframepivot_t *pivot, INT16 *newwidth, INT16 *newheight)
{
if (pivot)
{
*newwidth = width + (height * 2);
*newheight = height + (width * 2);
}
else
{
fixed_t fw = (width * FRACUNIT);
fixed_t fh = (height * FRACUNIT);
INT32 w1 = abs(FixedMul(fw, ca) - FixedMul(fh, sa));
INT32 w2 = abs(FixedMul(-fw, ca) - FixedMul(fh, sa));
INT32 h1 = abs(FixedMul(fw, sa) + FixedMul(fh, ca));
INT32 h2 = abs(FixedMul(-fw, sa) + FixedMul(fh, ca));
w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2)));
w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2)));
h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2)));
h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2)));
*newwidth = max(width, max(w1, w2));
*newheight = max(height, max(h1, h2));
}
}
/** Creates a pixel map for a rotated patch.
*
* \param patch The source patch.
* \param pixelmap The destination pixel map.
* \param rsvars Sprite rotation variables.
* \sa RotSprite_CreatePixelMap
*/
void RotSprite_CreatePixelMap(patch_t *patch, pixelmap_t *pixelmap, rotsprite_vars_t rsvars)
{
size_t size;
INT32 dx, dy;
INT16 newwidth, newheight;
fixed_t ca = rollcosang[rsvars.rollangle];
fixed_t sa = rollsinang[rsvars.rollangle];
INT16 width = SHORT(patch->width);
INT16 height = SHORT(patch->height);
INT16 leftoffset = SHORT(patch->leftoffset);
spriteframepivot_t pivot;
INT16 rotxcenter, rotycenter;
spriteframepivot_t *spritepivot = rsvars.pivot;
pivot.x = (spritepivot ? spritepivot->x : (rsvars.sprite ? leftoffset : (width / 2)));
pivot.y = (spritepivot ? spritepivot->y : (height / 2));
if (rsvars.flip)
{
pivot.x = width - pivot.x;
leftoffset = width - leftoffset;
}
// Find the dimensions of the rotated patch.
CalculateRotatedRectangleDimensions(width, height, ca, sa, (spritepivot ? &pivot : NULL), &newwidth, &newheight);
rotxcenter = (newwidth / 2);
rotycenter = (newheight / 2);
size = (newwidth * newheight);
// Build pixel map.
if (pixelmap->map)
Z_Free(pixelmap->map);
pixelmap->map = Z_Calloc(size * sizeof(INT32) * 2, PU_STATIC, NULL);
pixelmap->size = size;
pixelmap->width = newwidth;
pixelmap->height = newheight;
// Calculate the position of every pixel.
for (dy = 0; dy < newheight; dy++)
{
for (dx = 0; dx < newwidth; dx++)
{
INT32 dst = (dx*newheight)+dy;
INT32 x = (dx-rotxcenter) << FRACBITS;
INT32 y = (dy-rotycenter) << FRACBITS;
INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (pivot.x << FRACBITS);
INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (pivot.y << FRACBITS);
sx >>= FRACBITS;
sy >>= FRACBITS;
pixelmap->map[dst] = sy;
pixelmap->map[dst + size] = sx;
}
}
// Set offsets.
if (rsvars.sprite)
{
pixelmap->leftoffset = (newwidth / 2) + (leftoffset - pivot.x);
pixelmap->topoffset = (newheight / 2) + (SHORT(patch->topoffset) - pivot.y);
pixelmap->topoffset += FEETADJUST>>FRACBITS;
}
else
{
pixelmap->leftoffset = leftoffset;
pixelmap->topoffset = SHORT(patch->topoffset);
}
}
/** Creates a rotated patch from sprite rotation data.
*
* \param rotsprite The rotated sprite info.
* \param rsvars Sprite rotation variables.
* \return The rotated patch.
* \sa RotSprite_CreatePixelMap
*/
patch_t *RotSprite_CreatePatch(rotsprite_t *rotsprite, rotsprite_vars_t rsvars)
{
UINT8 *img, *imgptr = imgbuf;
pixelmap_t *pixelmap = &rotsprite->pixelmap[rsvars.rollangle];
patch_t *patch = (patch_t *)W_CacheSoftwarePatchNum(rotsprite->lumpnum, PU_CACHE);
pmcache_t *pmcache = &pixelmap->cache;
UINT32 x, width = pixelmap->width;
UINT8 *colpointers;
void **colofs;
size_t size = 0;
WRITEINT16(imgptr, (INT16)width);
WRITEINT16(imgptr, (INT16)pixelmap->height);
WRITEINT16(imgptr, pixelmap->leftoffset);
WRITEINT16(imgptr, pixelmap->topoffset);
colpointers = imgptr;
imgptr += width*4;
if (!pmcache->columnofs)
RotSprite_CreateColumns(pixelmap, pmcache, patch, rsvars);
colofs = pmcache->columnofs;
for (x = 0; x < width; x++)
{
column_t *column = (column_t *)(colofs[x]);
WRITEINT32(colpointers, imgptr - imgbuf);
if (column)
{
size = pmcache->columnsize[x];
WRITEMEM(imgptr, column, size);
}
else
WRITEUINT8(imgptr, 0xFF);
}
size = imgptr-imgbuf;
img = Z_Malloc(size, PU_STATIC, NULL);
M_Memcpy(img, imgbuf, size);
#ifdef HWRENDER
// Ugh
if (rendermode == render_opengl)
{
GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL);
grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL);
grPatch->patch = (patch_t *)img;
rotsprite->patches[rsvars.rollangle] = (patch_t *)grPatch;
HWR_MakePatch((patch_t *)img, grPatch, grPatch->mipmap, false);
}
else
#endif
rotsprite->patches[rsvars.rollangle] = (patch_t *)img;
return rotsprite->patches[rsvars.rollangle];
}
/** Recreates sprite rotation data in memory.
*
* \param rotsprite The rotated sprite info.
* \sa RotSprite_RecreateAll
* \sa Patch_CacheRotated
* \sa Patch_CacheRotatedForSprite
*/
void RotSprite_Recreate(rotsprite_t *rotsprite, rendermode_t rmode)
{
INT32 ang;
for (ang = 0; ang < ROTANGLES; ang++)
{
if (rotsprite->cached[ang])
{
pixelmap_t *pixelmap = &rotsprite->pixelmap[ang];
pmcache_t *cache = &pixelmap->cache;
rotsprite->cached[ang] = false;
if (pixelmap->map)
Z_Free(pixelmap->map);
if (cache->columnofs)
Z_Free(cache->columnofs);
if (cache->columnsize)
Z_Free(cache->columnsize);
if (cache->data)
Z_Free(cache->data);
pixelmap->map = NULL;
cache->columnofs = NULL;
cache->columnsize = NULL;
cache->data = NULL;
#ifdef HWRENDER
if (rmode == render_opengl)
{
GLPatch_t *grPatch = (GLPatch_t *)(rotsprite->patches[ang]);
if (grPatch && grPatch->patch)
{
Z_Free(grPatch->patch);
grPatch->patch = NULL;
}
}
else
#endif
if (rotsprite->patches[ang])
Z_Free(rotsprite->patches[ang]);
rotsprite->patches[ang] = NULL;
if (rotsprite->vars.sprite)
Patch_CacheRotatedForSprite(rotsprite->lumpnum, rotsprite->tag, rotsprite->vars, false);
else
Patch_CacheRotated(rotsprite->lumpnum, rotsprite->tag, rotsprite->vars, false);
}
}
}
/** Recreates all sprite rotation data in memory.
*
* \sa RotSprite_Recreate
*/
void RotSprite_RecreateAll(void)
{
// TODO: Write this in a more efficient way.
INT32 w, l, r, f;
for (r = render_first; r < render_last; r++)
for (w = 0; w < numwadfiles; w++)
for (l = 0; l < wadfiles[w]->numlumps; l++)
{
for (f = 0; f < 2; f++)
{
rotsprite_t *rotsprite = GetRotatedPatchInfo(w, l, r, (f ? true : false));
if (rotsprite)
RotSprite_Recreate(rotsprite, r);
}
}
}
#endif // ROTSPRITE
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2019-2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2019-2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_rotsprite.h
/// \brief Rotated patch generation.
#ifndef __R_ROTSPRITE__
#define __R_ROTSPRITE__
#include "r_defs.h"
#include "r_patch.h"
#include "doomtype.h"
#ifdef ROTSPRITE
INT32 R_GetRollAngle(angle_t rollangle);
typedef struct
{
pixelmap_t pixelmap[ROTANGLES];
patch_t *patches[ROTANGLES];
boolean cached[ROTANGLES];
UINT32 lumpnum;
rotsprite_vars_t vars;
INT32 tag;
} rotsprite_t;
rotsprite_t *RotSprite_GetFromPatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag, rotsprite_vars_t rsvars, boolean store);
rotsprite_t *RotSprite_GetFromPatchNum(lumpnum_t lumpnum, INT32 tag, rotsprite_vars_t rsvars, boolean store);
rotsprite_t *RotSprite_GetFromPatchName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store);
rotsprite_t *RotSprite_GetFromPatchLongName(const char *name, INT32 tag, rotsprite_vars_t rsvars, boolean store);
void RotSprite_Create(rotsprite_t *rotsprite, rotsprite_vars_t rsvars);
void RotSprite_CreateColumns(pixelmap_t *pixelmap, pmcache_t *cache, patch_t *patch, rotsprite_vars_t rsvars);
void RotSprite_CreatePixelMap(patch_t *patch, pixelmap_t *pixelmap, rotsprite_vars_t rsvars);
patch_t *RotSprite_CreatePatch(rotsprite_t *rotsprite, rotsprite_vars_t rsvars);
void RotSprite_Recreate(rotsprite_t *rotsprite, rendermode_t rmode);
void RotSprite_RecreateAll(void);
void RotSprite_InitPatchTree(patchtree_t *rcache);
void RotSprite_AllocCurrentPatchInfo(patchinfo_t *patchinfo, UINT16 lumpnum);
int RotSprite_GetCurrentPatchInfoIdx(INT32 rollangle, boolean flip);
#endif // ROTSPRITE
#endif // __R_ROTSPRITE__
......@@ -54,9 +54,6 @@ INT32 globallevelskynum;
Called at loadlevel after skytexture is set, or when sky texture changes.
\warning wallcolfunc should be set at R_ExecuteSetViewSize()
I don't bother because we don't use low detail anymore
\return void
*/
void R_SetupSkyDraw(void)
......
......@@ -12,6 +12,7 @@
/// \brief Refresh of things, i.e. objects represented by sprites
#include "doomdef.h"
#include "byteptr.h"
#include "console.h"
#include "g_game.h"
#include "r_local.h"
......@@ -25,6 +26,7 @@
#include "i_system.h"
#include "r_things.h"
#include "r_patch.h"
#include "r_rotsprite.h"
#include "r_plane.h"
#include "r_portal.h"
#include "p_tick.h"
......@@ -96,7 +98,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
{
char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging
INT32 r, ang;
INT32 r;
lumpnum_t lumppat = wad;
lumppat <<= 16;
lumppat += lump;
......@@ -104,16 +106,6 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (maxframe ==(size_t)-1 || frame > maxframe)
maxframe = frame;
// rotsprite
#ifdef ROTSPRITE
sprtemp[frame].rotsprite.cached = 0;
for (r = 0; r < 16; r++)
{
for (ang = 0; ang < ROTANGLES; ang++)
sprtemp[frame].rotsprite.patch[r][ang] = NULL;
}
#endif/*ROTSPRITE*/
if (rotation == 0)
{
// the lump should be used for all rotations
......@@ -240,9 +232,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
// if so, it might patch only certain frames, not all
if (spritedef->numframes) // (then spriteframes is not null)
{
#ifdef ROTSPRITE
R_FreeSingleRotSprite(spritedef);
#endif
// copy the already defined sprite frames
M_Memcpy(sprtemp, spritedef->spriteframes,
spritedef->numframes * sizeof (spriteframe_t));
......@@ -397,9 +386,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
if (spritedef->numframes && // has been allocated
spritedef->numframes < maxframe) // more frames are defined ?
{
#ifdef ROTSPRITE
R_FreeSingleRotSprite(spritedef);
#endif
Z_Free(spritedef->spriteframes);
spritedef->spriteframes = NULL;
}
......@@ -607,7 +593,7 @@ void R_DrawMaskedColumn(column_t *column)
INT32 topscreen;
INT32 bottomscreen;
fixed_t basetexturemid;
INT32 topdelta, prevdelta = 0;
INT32 topdelta = 0, prevdelta = 0;
basetexturemid = dc_texturemid;
......@@ -671,8 +657,8 @@ void R_DrawFlippedMaskedColumn(column_t *column)
INT32 topscreen;
INT32 bottomscreen;
fixed_t basetexturemid = dc_texturemid;
INT32 topdelta, prevdelta = -1;
UINT8 *d,*s;
INT32 topdelta = 0, prevdelta = -1;
UINT8 *d, *s;
for (; column->topdelta != 0xff ;)
{
......@@ -744,6 +730,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
fixed_t this_scale = vis->mobj->scale;
INT32 x1, x2;
INT64 overflow_test;
int colfunctype = BASEDRAWFUNC;
if (!patch)
return;
......@@ -760,12 +747,11 @@ static void R_DrawVisSprite(vissprite_t *vis)
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto
}
colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap;
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
// translate certain pixels to white
colfunc = colfuncs[COLDRAWFUNC_TRANS];
colfunctype = COLDRAWFUNC_TRANS;
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
......@@ -775,7 +761,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
}
else if (vis->mobj->color && vis->transmap) // Color mapping
{
colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS];
colfunctype = COLDRAWFUNC_TRANSTRANS;
dc_transmap = vis->transmap;
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
......@@ -799,13 +785,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
}
else if (vis->transmap)
{
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
colfunctype = COLDRAWFUNC_FUZZY;
dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table
}
else if (vis->mobj->color)
{
// translate green skin to another color
colfunc = colfuncs[COLDRAWFUNC_TRANS];
colfunctype = COLDRAWFUNC_TRANS;
// New colormap stuff for skins Tails 06-07-2002
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
......@@ -830,7 +816,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
}
else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
{
colfunc = colfuncs[COLDRAWFUNC_TRANS];
colfunctype = COLDRAWFUNC_TRANS;
dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE);
}
......@@ -890,6 +876,8 @@ static void R_DrawVisSprite(vissprite_t *vis)
localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn;
lengthcol = SHORT(patch->height);
colfunc = colfuncs[colfunctype];
// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
if (vis->scalestep)
{
......@@ -925,9 +913,9 @@ static void R_DrawVisSprite(vissprite_t *vis)
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
{
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS;
texturecolumn = (frac>>FRACBITS);
if (texturecolumn < 0 || texturecolumn >= pwidth)
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
I_Error("R_DrawVisSprite: bad texturecolumn at %d from end", vis->x2 - dc_x);
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
......@@ -1394,11 +1382,11 @@ static void R_ProjectSprite(mobj_t *thing)
INT32 light = 0;
fixed_t this_scale = thing->scale;
// rotsprite
patch_t *spr_patch = NULL;
fixed_t spr_width, spr_height;
fixed_t spr_offset, spr_topoffset;
#ifdef ROTSPRITE
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
#endif
......@@ -1443,7 +1431,7 @@ static void R_ProjectSprite(mobj_t *thing)
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
#ifdef ROTSPRITE
sprinfo = NULL;
sprinfo = &spriteinfo[thing->sprite];
#endif
frame = thing->frame&FF_FRAMEMASK;
}
......@@ -1452,7 +1440,7 @@ static void R_ProjectSprite(mobj_t *thing)
{
sprdef = &sprites[thing->sprite];
#ifdef ROTSPRITE
sprinfo = NULL;
sprinfo = &spriteinfo[thing->sprite];
#endif
if (frame >= sprdef->numframes)
......@@ -1525,23 +1513,30 @@ static void R_ProjectSprite(mobj_t *thing)
spr_topoffset = spritecachedinfo[lump].topoffset;
#ifdef ROTSPRITE
if (thing->rollangle)
rollangle = R_GetRollAngle(thing->rollangle);
if (rollangle)
{
rollangle = R_GetRollAngle(thing->rollangle);
if (!(sprframe->rotsprite.cached & (1<<rot)))
R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, flip);
rotsprite = sprframe->rotsprite.patch[rot][rollangle];
if (rotsprite != NULL)
{
spr_width = SHORT(rotsprite->width) << FRACBITS;
spr_height = SHORT(rotsprite->height) << FRACBITS;
spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS;
spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS;
// flip -> rotate, not rotate -> flip
flip = 0;
}
spriteframepivot_t *pivot = (sprinfo->available) ? &sprinfo->pivot[(thing->frame & FF_FRAMEMASK)] : NULL;
static rotsprite_vars_t rsvars;
patch_t *rotpatch;
rsvars.rollangle = rollangle;
rsvars.sprite = true;
rsvars.pivot = pivot;
rsvars.flip = (!!flip);
rotpatch = Patch_CacheRotatedForSprite(sprframe->lumppat[rot], PU_LEVEL, rsvars, false);
spr_patch = rotpatch;
spr_width = SHORT(rotpatch->width) << FRACBITS;
spr_height = SHORT(rotpatch->height) << FRACBITS;
spr_offset = SHORT(rotpatch->leftoffset) << FRACBITS;
spr_topoffset = SHORT(rotpatch->topoffset) << FRACBITS;
// flip -> rotate, not rotate -> flip
flip = 0;
}
#endif
#endif // ROTSPRITE
flip = !flip != !hflip;
......@@ -1794,6 +1789,7 @@ static void R_ProjectSprite(mobj_t *thing)
iscale = FixedDiv(FRACUNIT, xscale);
// Flipping
if (flip)
{
vis->startfrac = spr_width-1;
......@@ -1813,12 +1809,9 @@ static void R_ProjectSprite(mobj_t *thing)
//Fab: lumppat is the lump number of the patch to use, this is different
// than lumpid for sprites-in-pwad : the graphics are patched
#ifdef ROTSPRITE
if (rotsprite != NULL)
vis->patch = rotsprite;
else
#endif
vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE);
if (spr_patch == NULL)
spr_patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE);
vis->patch = spr_patch;
//
// determine the colormap (lightlevel & special effects)
......