Merge branch 'asmjit' into weapon_scriptification

# Conflicts:
#	src/gi.cpp
#	wadsrc/static/zscript/base.txt
This commit is contained in:
Christoph Oelckers 2018-11-26 00:14:44 +01:00
commit 47b1fa774d
51 changed files with 1825 additions and 1255 deletions

View file

@ -1150,6 +1150,7 @@ set (PCH_SOURCES
r_data/models/models_ue1.cpp r_data/models/models_ue1.cpp
r_data/models/models_obj.cpp r_data/models/models_obj.cpp
scripting/symbols.cpp scripting/symbols.cpp
scripting/vmthunks.cpp
scripting/types.cpp scripting/types.cpp
scripting/thingdef.cpp scripting/thingdef.cpp
scripting/thingdef_data.cpp scripting/thingdef_data.cpp

View file

@ -749,7 +749,7 @@ static void (*MBFCodePointerFactories[])(FunctionCallEmitter&, int, int) =
void SetDehParams(FState *state, int codepointer) void SetDehParams(FState *state, int codepointer)
{ {
static uint8_t regts[] = { REGT_POINTER, REGT_POINTER, REGT_POINTER }; static const uint8_t regts[] = { REGT_POINTER, REGT_POINTER, REGT_POINTER };
int value1 = state->GetMisc1(); int value1 = state->GetMisc1();
int value2 = state->GetMisc2(); int value2 = state->GetMisc2();
if (!(value1|value2)) return; if (!(value1|value2)) return;

View file

@ -266,8 +266,6 @@ void PClass::StaticShutdown ()
// This flags DObject::Destroy not to call any scripted OnDestroy methods anymore. // This flags DObject::Destroy not to call any scripted OnDestroy methods anymore.
bVMOperational = false; bVMOperational = false;
// PendingWeapon must be cleared manually because it is not subjected to the GC if it contains WP_NOCHANGE, which is just RUNTIME_CLASS(AWWeapon).
// But that will get cleared here, confusing the GC if the value is left in.
for (auto &p : players) for (auto &p : players)
{ {
p.PendingWeapon = nullptr; p.PendingWeapon = nullptr;

View file

@ -38,6 +38,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <exception> #include <exception>
#include <stdexcept>
#define MAX_ERRORTEXT 1024 #define MAX_ERRORTEXT 1024
@ -70,7 +71,7 @@ public:
else else
return NULL; return NULL;
} }
char const *what() const override char const *what() const noexcept override
{ {
return m_Message; return m_Message;
} }
@ -80,10 +81,10 @@ protected:
char m_Message[MAX_ERRORTEXT]; char m_Message[MAX_ERRORTEXT];
}; };
class CNoRunExit : public std::exception class CNoRunExit : public std::runtime_error
{ {
public: public:
CNoRunExit() : std::exception("NoRunExit") CNoRunExit() : std::runtime_error("NoRunExit")
{ {
} }
}; };

View file

@ -735,7 +735,7 @@ void ProcessEDSector(sector_t *sec, int recordnum)
sec->terrainnum[sector_t::floor] = esec->floorterrain; sec->terrainnum[sector_t::floor] = esec->floorterrain;
sec->terrainnum[sector_t::ceiling] = esec->ceilingterrain; sec->terrainnum[sector_t::ceiling] = esec->ceilingterrain;
if (esec->colorSet) sec->SetColor(RPART(esec->color), GPART(esec->color), BPART(esec->color), 0); if (esec->colorSet) sec->SetColor(esec->color, 0);
const uint32_t pflagmask = PLANEF_DISABLED | PLANEF_NORENDER | PLANEF_NOPASS | PLANEF_BLOCKSOUND | PLANEF_ADDITIVE; const uint32_t pflagmask = PLANEF_DISABLED | PLANEF_NORENDER | PLANEF_NOPASS | PLANEF_BLOCKSOUND | PLANEF_ADDITIVE;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)

View file

@ -3833,7 +3833,7 @@ void FParser::SF_SetColor(void)
{ {
if (!DFraggleThinker::ActiveThinker->setcolormaterial) if (!DFraggleThinker::ActiveThinker->setcolormaterial)
{ {
level.sectors[i].SetColor(color.r, color.g, color.b, 0); level.sectors[i].SetColor(color, 0);
} }
else else
{ {

View file

@ -61,10 +61,10 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_single)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_coop) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_coop)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_dm) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, statusscreen_dm)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mSliderColor) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mSliderColor)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defaultbloodcolor)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, telefogheight) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, telefogheight)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defKickback) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, defKickback)
const char *GameNames[17] = const char *GameNames[17] =
{ {
NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex" NULL, "Doom", "Heretic", NULL, "Hexen", NULL, NULL, NULL, "Strife", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Chex"

View file

@ -147,7 +147,7 @@ FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe)
{ 1, VATTR_VERTEX2, VFmt_Float3, (int)myoffsetof(FModelVertex, x) }, { 1, VATTR_VERTEX2, VFmt_Float3, (int)myoffsetof(FModelVertex, x) },
{ 1, VATTR_NORMAL2, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) } { 1, VATTR_NORMAL2, VFmt_Packed_A2R10G10B10, (int)myoffsetof(FModelVertex, packedNormal) }
}; };
mVertexBuffer->SetFormat(2, 4, sizeof(FModelVertex), format); mVertexBuffer->SetFormat(2, 5, sizeof(FModelVertex), format);
} }
//=========================================================================== //===========================================================================

View file

@ -957,33 +957,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CopyFriendliness)
// //
//========================================================================== //==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_PlaySound)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_SOUND (soundid);
PARAM_INT (channel);
PARAM_FLOAT (volume);
PARAM_BOOL (looping);
PARAM_FLOAT (attenuation);
PARAM_BOOL (local);
if (!looping)
{
if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
}
}
else
{
if (!S_IsActorPlayingSomething (self, channel&7, soundid))
{
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local);
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_StopSound) DEFINE_ACTION_FUNCTION(AActor, A_StopSound)
{ {
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);

View file

@ -368,13 +368,13 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
break; break;
case DCeiling::ceilLowerByTexture: case DCeiling::ceilLowerByTexture:
targheight = sec->ceilingplane.ZatPoint (spot) - sec->FindShortestUpperAround (); targheight = sec->ceilingplane.ZatPoint (spot) - FindShortestUpperAround (sec);
ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight); ceiling->m_BottomHeight = sec->ceilingplane.PointToDist (spot, targheight);
ceiling->m_Direction = -1; ceiling->m_Direction = -1;
break; break;
case DCeiling::ceilRaiseByTexture: case DCeiling::ceilRaiseByTexture:
targheight = sec->ceilingplane.ZatPoint (spot) + sec->FindShortestUpperAround (); targheight = sec->ceilingplane.ZatPoint (spot) + FindShortestUpperAround (sec);
ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight); ceiling->m_TopHeight = sec->ceilingplane.PointToDist (spot, targheight);
ceiling->m_Direction = 1; ceiling->m_Direction = 1;
break; break;
@ -420,8 +420,8 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
type == DCeiling::ceilRaiseToFloor || type == DCeiling::ceilRaiseToFloor ||
/*type == ceilLowerToHighest ||*/ /*type == ceilLowerToHighest ||*/
type == DCeiling::ceilLowerToFloor) ? type == DCeiling::ceilLowerToFloor) ?
sec->FindModelFloorSector (targheight) : FindModelFloorSector(sec, targheight) :
sec->FindModelCeilingSector (targheight); FindModelCeilingSector(sec, targheight);
if (modelsec != NULL) if (modelsec != NULL)
{ {
ceiling->m_Texture = modelsec->GetTexture(sector_t::ceiling); ceiling->m_Texture = modelsec->GetTexture(sector_t::ceiling);

View file

@ -392,7 +392,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
case DFloor::floorLowerByTexture: case DFloor::floorLowerByTexture:
floor->m_Direction = -1; floor->m_Direction = -1;
newheight = sec->CenterFloor() - sec->FindShortestTextureAround(); newheight = sec->CenterFloor() - FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight); floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
break; break;
@ -409,7 +409,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
// since the code is identical to what was here. (Oddly // since the code is identical to what was here. (Oddly
// enough, BOOM preserved the code here even though it // enough, BOOM preserved the code here even though it
// also had this function.) // also had this function.)
newheight = sec->CenterFloor() + sec->FindShortestTextureAround(); newheight = sec->CenterFloor() + FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight); floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
break; break;
@ -440,7 +440,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
//jff 5/23/98 use model subroutine to unify fixes and handling //jff 5/23/98 use model subroutine to unify fixes and handling
sector_t *modelsec; sector_t *modelsec;
modelsec = sec->FindModelFloorSector(newheight); modelsec = FindModelFloorSector(sec, newheight);
if (modelsec != NULL) if (modelsec != NULL)
{ {
floor->m_Texture = modelsec->GetTexture(sector_t::floor); floor->m_Texture = modelsec->GetTexture(sector_t::floor);
@ -485,8 +485,8 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
floortype == DFloor::floorLowerToLowestCeiling || floortype == DFloor::floorLowerToLowestCeiling ||
floortype == DFloor::floorRaiseToCeiling || floortype == DFloor::floorRaiseToCeiling ||
floortype == DFloor::floorLowerToCeiling) ? floortype == DFloor::floorLowerToCeiling) ?
sec->FindModelCeilingSector(-floor->m_FloorDestDist) : FindModelCeilingSector(sec, -floor->m_FloorDestDist) :
sec->FindModelFloorSector(-floor->m_FloorDestDist); FindModelFloorSector(sec, -floor->m_FloorDestDist);
if (modelsec != NULL) if (modelsec != NULL)
{ {
@ -1126,7 +1126,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
} }
break; break;
case numChangeOnly: case numChangeOnly:
secm = sec->FindModelFloorSector (sec->CenterFloor()); secm = FindModelFloorSector(sec, sec->CenterFloor());
if (secm) if (secm)
{ // if no model, no change { // if no model, no change
sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor)); sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor));

View file

@ -2434,7 +2434,7 @@ FUNC(LS_Sector_SetColor)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetColor(arg1, arg2, arg3, arg4); level.sectors[secnum].SetColor(PalEntry(255, arg1, arg2, arg3), arg4);
} }
return true; return true;
@ -2447,7 +2447,7 @@ FUNC(LS_Sector_SetFade)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetFade(arg1, arg2, arg3); level.sectors[secnum].SetFade(PalEntry(255, arg1, arg2, arg3));
} }
return true; return true;
} }

View file

@ -4508,7 +4508,7 @@ DEFINE_ACTION_FUNCTION(AActor, AimLineAttack)
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);
PARAM_ANGLE(angle); PARAM_ANGLE(angle);
PARAM_FLOAT(distance); PARAM_FLOAT(distance);
PARAM_POINTER(pLineTarget, FTranslatedLineTarget); PARAM_OUTPOINTER(pLineTarget, FTranslatedLineTarget);
PARAM_ANGLE(vrange); PARAM_ANGLE(vrange);
PARAM_INT(flags); PARAM_INT(flags);
PARAM_OBJECT(target, AActor); PARAM_OBJECT(target, AActor);
@ -4920,7 +4920,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
PARAM_NAME(damageType); PARAM_NAME(damageType);
PARAM_CLASS(puffType, AActor); PARAM_CLASS(puffType, AActor);
PARAM_INT(flags); PARAM_INT(flags);
PARAM_POINTER(victim, FTranslatedLineTarget); PARAM_OUTPOINTER(victim, FTranslatedLineTarget);
PARAM_FLOAT(offsetz); PARAM_FLOAT(offsetz);
PARAM_FLOAT(offsetforward); PARAM_FLOAT(offsetforward);
PARAM_FLOAT(offsetside); PARAM_FLOAT(offsetside);
@ -5086,7 +5086,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineTrace)
PARAM_FLOAT(offsetz); PARAM_FLOAT(offsetz);
PARAM_FLOAT(offsetforward); PARAM_FLOAT(offsetforward);
PARAM_FLOAT(offsetside); PARAM_FLOAT(offsetside);
PARAM_POINTER(data, FLineTraceData); PARAM_OUTPOINTER(data, FLineTraceData);
ACTION_RETURN_BOOL(P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data)); ACTION_RETURN_BOOL(P_LineTrace(self,angle,distance,pitch,flags,offsetz,offsetforward,offsetside,data));
} }

View file

@ -7375,7 +7375,7 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile)
PARAM_FLOAT(x); PARAM_FLOAT(x);
PARAM_FLOAT(y); PARAM_FLOAT(y);
PARAM_FLOAT(z); PARAM_FLOAT(z);
PARAM_POINTER(lt, FTranslatedLineTarget); PARAM_OUTPOINTER(lt, FTranslatedLineTarget);
PARAM_BOOL(nofreeaim); PARAM_BOOL(nofreeaim);
PARAM_BOOL(noautoaim); PARAM_BOOL(noautoaim);
PARAM_INT(aimflags); PARAM_INT(aimflags);

File diff suppressed because it is too large Load diff

View file

@ -556,17 +556,17 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw
else else
{ {
info = PClass::FindClass (sc.String); info = PClass::FindClass (sc.String);
if (!info->IsDescendantOf (RUNTIME_CLASS(AActor))) if (info == NULL)
{
Printf ("Unknown actor %s in %s %s\n",
sc.String, type, name.GetChars());
}
else if (!info->IsDescendantOf (RUNTIME_CLASS(AActor)))
{ {
Printf ("%s is not an Actor (in %s %s)\n", Printf ("%s is not an Actor (in %s %s)\n",
sc.String, type, name.GetChars()); sc.String, type, name.GetChars());
info = NULL; info = NULL;
} }
else if (info == NULL)
{
Printf ("Unknown actor %s in %s %s\n",
sc.String, type, name.GetChars());
}
} }
SET_FIELD (const PClass *, info); SET_FIELD (const PClass *, info);
break; break;

View file

@ -77,6 +77,15 @@ public:
return clip_first_line + core_skip - first_line; return clip_first_line + core_skip - first_line;
} }
// Varyings
float worldposX[MAXWIDTH];
float worldposY[MAXWIDTH];
float worldposZ[MAXWIDTH];
uint32_t texel[MAXWIDTH];
int32_t texelV[MAXWIDTH];
fixed_t lightarray[MAXWIDTH];
uint32_t dynlights[MAXWIDTH];
static PolyTriangleThreadData *Get(DrawerThread *thread); static PolyTriangleThreadData *Get(DrawerThread *thread);
private: private:

View file

@ -227,7 +227,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
if (x > xstart) if (x > xstart)
{ {
if (writeColor) if (writeColor)
drawfunc(y, xstart, x, args); drawfunc(y, xstart, x, args, thread);
if (writeStencil) if (writeStencil)
{ {
@ -379,29 +379,54 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
} }
template<typename ModeT, typename OptT> template<typename ModeT, typename OptT>
void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args) void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{ {
using namespace TriScreenDrawerModes; using namespace TriScreenDrawerModes;
uint32_t fixedlight;
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
fixed_t fuzzscale;
int _fuzzpos;
const uint32_t *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int actoralpha;
float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ; float v1X, v1Y, v1W, v1U, v1V, v1WorldX, v1WorldY, v1WorldZ;
float startX, startY; float startX, startY;
float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ; float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ;
float posW, posU, posV, posWorldX, posWorldY, posWorldZ; float posW, posU, posV, posWorldX, posWorldY, posWorldZ;
PolyLight *lights;
int num_lights;
float worldnormalX, worldnormalY, worldnormalZ;
uint32_t dynlightcolor;
const uint32_t *texPixels, *translation;
int texWidth, texHeight;
uint32_t fillcolor;
int alpha;
uint32_t light; uint32_t light;
fixed_t shade, lightpos, lightstep; fixed_t shade, lightpos, lightstep;
uint32_t shade_fade_r, shade_fade_g, shade_fade_b, shade_light_r, shade_light_g, shade_light_b, desaturate, inv_desaturate;
int16_t dynlights_r[MAXWIDTH / 16], dynlights_g[MAXWIDTH / 16], dynlights_b[MAXWIDTH / 16]; float *worldposX = thread->worldposX;
int16_t posdynlight_r, posdynlight_g, posdynlight_b; float *worldposY = thread->worldposY;
fixed_t lightarray[MAXWIDTH / 16]; float *worldposZ = thread->worldposZ;
uint32_t *texel = thread->texel;
int32_t *texelV = thread->texelV;
fixed_t *lightarray = thread->lightarray;
uint32_t *dynlights = thread->dynlights;
if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary))
{
texPixels = (const uint32_t*)args->uniforms->TexturePixels();
texWidth = args->uniforms->TextureWidth();
texHeight = args->uniforms->TextureHeight();
}
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
translation = (const uint32_t*)args->uniforms->Translation();
}
if ((ModeT::SWFlags & SWSTYLEF_Fill) || (ModeT::SWFlags & SWSTYLEF_Skycap) || (ModeT::Flags & STYLEF_ColorIsFixed))
{
fillcolor = args->uniforms->Color();
}
if (!(ModeT::Flags & STYLEF_Alpha1))
{
actoralpha = args->uniforms->Alpha();
}
v1X = args->v1->x; v1X = args->v1->x;
v1Y = args->v1->y; v1Y = args->v1->y;
@ -417,50 +442,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
posU = v1U + stepU * startX + args->gradientY.U * startY; posU = v1U + stepU * startX + args->gradientY.U * startY;
posV = v1V + stepV * startX + args->gradientY.V * startY; posV = v1V + stepV * startX + args->gradientY.V * startY;
texPixels = (const uint32_t*)args->uniforms->TexturePixels();
translation = (const uint32_t*)args->uniforms->Translation();
texWidth = args->uniforms->TextureWidth();
texHeight = args->uniforms->TextureHeight();
fillcolor = args->uniforms->Color();
alpha = args->uniforms->Alpha();
light = args->uniforms->Light();
if (OptT::Flags & SWOPT_FixedLight)
{
light += light >> 7; // 255 -> 256
}
else
{
float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f);
shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT);
lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT);
lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT);
int affineOffset = x0 / 16 * 16 - x0;
lightpos = lightpos + lightstep * affineOffset;
lightstep = lightstep * 16;
fixed_t maxvis = 24 * FRACUNIT / 32;
fixed_t maxlight = 31 * FRACUNIT / 32;
for (int x = x0 / 16; x <= x1 / 16 + 1; x++)
{
lightarray[x] = (FRACUNIT - clamp<fixed_t>(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8;
lightpos += lightstep;
}
int offset = x0 >> 4;
int t1 = x0 & 15;
int t0 = 16 - t1;
lightpos = (lightarray[offset] * t0 + lightarray[offset + 1] * t1);
for (int x = x0 / 16; x <= x1 / 16; x++)
{
lightarray[x] = lightarray[x + 1] - lightarray[x];
}
}
if (OptT::Flags & SWOPT_DynLights) if (OptT::Flags & SWOPT_DynLights)
{ {
v1WorldX = args->v1->worldX * v1W; v1WorldX = args->v1->worldX * v1W;
@ -472,6 +453,61 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
posWorldX = v1WorldX + stepWorldX * startX + args->gradientY.WorldX * startY; posWorldX = v1WorldX + stepWorldX * startX + args->gradientY.WorldX * startY;
posWorldY = v1WorldY + stepWorldY * startX + args->gradientY.WorldY * startY; posWorldY = v1WorldY + stepWorldY * startX + args->gradientY.WorldY * startY;
posWorldZ = v1WorldZ + stepWorldZ * startX + args->gradientY.WorldZ * startY; posWorldZ = v1WorldZ + stepWorldZ * startX + args->gradientY.WorldZ * startY;
}
if (!(OptT::Flags & SWOPT_FixedLight))
{
float globVis = args->uniforms->GlobVis() * (1.0f / 32.0f);
light = args->uniforms->Light();
shade = (fixed_t)((2.0f - (light + 12.0f) / 128.0f) * (float)FRACUNIT);
lightpos = (fixed_t)(globVis * posW * (float)FRACUNIT);
lightstep = (fixed_t)(globVis * stepW * (float)FRACUNIT);
}
for (int x = x0; x < x1; x++)
{
if (OptT::Flags & SWOPT_DynLights)
{
float rcp_posW = 1.0f / posW;
worldposX[x] = posWorldX * rcp_posW;
worldposY[x] = posWorldY * rcp_posW;
worldposZ[x] = posWorldZ * rcp_posW;
posWorldX += stepWorldX;
posWorldY += stepWorldY;
posWorldZ += stepWorldZ;
}
if (!(OptT::Flags & SWOPT_FixedLight))
{
fixed_t maxvis = 24 * FRACUNIT / 32;
fixed_t maxlight = 31 * FRACUNIT / 32;
lightarray[x] = (FRACUNIT - clamp<fixed_t>(shade - MIN(maxvis, lightpos), 0, maxlight)) >> 8;
lightpos += lightstep;
}
if (!(ModeT::SWFlags & SWSTYLEF_Fill) && !(ModeT::SWFlags & SWSTYLEF_FogBoundary))
{
float rcpW = 0x01000000 / posW;
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
texel[x] = texelX * texHeight + texelY;
texelV[x] = v;
posU += stepU;
posV += stepV;
}
posW += stepW;
}
if (OptT::Flags & SWOPT_DynLights)
{
PolyLight *lights;
int num_lights;
float worldnormalX, worldnormalY, worldnormalZ;
uint32_t dynlightcolor;
lights = args->uniforms->Lights(); lights = args->uniforms->Lights();
num_lights = args->uniforms->NumLights(); num_lights = args->uniforms->NumLights();
@ -503,26 +539,12 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
worldnormalZ *= rcplen; worldnormalZ *= rcplen;
} }
int affineOffset = x0 / 16 * 16 - x0; for (int x = x0; x < x1; x++)
float posLightW = posW + stepW * affineOffset;
posWorldX = posWorldX + stepWorldX * affineOffset;
posWorldY = posWorldY + stepWorldY * affineOffset;
posWorldZ = posWorldZ + stepWorldZ * affineOffset;
float stepLightW = stepW * 16.0f;
stepWorldX *= 16.0f;
stepWorldY *= 16.0f;
stepWorldZ *= 16.0f;
for (int x = x0 / 16; x <= x1 / 16 + 1; x++)
{ {
uint32_t lit_r = RPART(dynlightcolor); uint32_t lit_r = RPART(dynlightcolor);
uint32_t lit_g = GPART(dynlightcolor); uint32_t lit_g = GPART(dynlightcolor);
uint32_t lit_b = BPART(dynlightcolor); uint32_t lit_b = BPART(dynlightcolor);
float rcp_posW = 1.0f / posLightW;
float worldposX = posWorldX * rcp_posW;
float worldposY = posWorldY * rcp_posW;
float worldposZ = posWorldZ * rcp_posW;
for (int i = 0; i < num_lights; i++) for (int i = 0; i < num_lights; i++)
{ {
float lightposX = lights[i].x; float lightposX = lights[i].x;
@ -538,9 +560,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
// L = light-pos // L = light-pos
// dist = sqrt(dot(L, L)) // dist = sqrt(dot(L, L))
// distance_attenuation = 1 - MIN(dist * (1/radius), 1) // distance_attenuation = 1 - MIN(dist * (1/radius), 1)
float Lx = lightposX - worldposX; float Lx = lightposX - worldposX[x];
float Ly = lightposY - worldposY; float Ly = lightposY - worldposY[x];
float Lz = lightposZ - worldposZ; float Lz = lightposZ - worldposZ[x];
float dist2 = Lx * Lx + Ly * Ly + Lz * Lz; float dist2 = Lx * Lx + Ly * Ly + Lz * Lz;
#ifdef NO_SSE #ifdef NO_SSE
//float rcp_dist = 1.0f / sqrt(dist2); //float rcp_dist = 1.0f / sqrt(dist2);
@ -572,29 +594,14 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
lit_r = MIN<uint32_t>(lit_r, 255); lit_r = MIN<uint32_t>(lit_r, 255);
lit_g = MIN<uint32_t>(lit_g, 255); lit_g = MIN<uint32_t>(lit_g, 255);
lit_b = MIN<uint32_t>(lit_b, 255); lit_b = MIN<uint32_t>(lit_b, 255);
dynlights_r[x] = lit_r; dynlights[x] = MAKEARGB(255, lit_r, lit_g, lit_b);
dynlights_g[x] = lit_g; }
dynlights_b[x] = lit_b;
posLightW += stepLightW;
posWorldX += stepWorldX;
posWorldY += stepWorldY;
posWorldZ += stepWorldZ;
} }
int offset = x0 >> 4; if (OptT::Flags & SWOPT_FixedLight)
int t1 = x0 & 15;
int t0 = 16 - t1;
posdynlight_r = (dynlights_r[offset] * t0 + dynlights_r[offset + 1] * t1);
posdynlight_g = (dynlights_g[offset] * t0 + dynlights_g[offset + 1] * t1);
posdynlight_b = (dynlights_b[offset] * t0 + dynlights_b[offset + 1] * t1);
for (int x = x0 / 16; x <= x1 / 16; x++)
{ {
dynlights_r[x] = dynlights_r[x + 1] - dynlights_r[x]; fixedlight = args->uniforms->Light();
dynlights_g[x] = dynlights_g[x + 1] - dynlights_g[x]; fixedlight += fixedlight >> 7; // 255 -> 256
dynlights_b[x] = dynlights_b[x + 1] - dynlights_b[x];
}
} }
if (OptT::Flags & SWOPT_ColoredFog) if (OptT::Flags & SWOPT_ColoredFog)
@ -609,8 +616,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
inv_desaturate = 256 - desaturate; inv_desaturate = 256 - desaturate;
} }
fixed_t fuzzscale;
int _fuzzpos;
if (ModeT::BlendOp == STYLEOP_Fuzz) if (ModeT::BlendOp == STYLEOP_Fuzz)
{ {
fuzzscale = (200 << FRACBITS) / viewheight; fuzzscale = (200 << FRACBITS) / viewheight;
@ -620,19 +625,55 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
uint32_t *dest = (uint32_t*)args->dest; uint32_t *dest = (uint32_t*)args->dest;
uint32_t *destLine = dest + args->pitch * y; uint32_t *destLine = dest + args->pitch * y;
int x = x0; int sseend = x0;
while (x < x1) #ifndef NO_SSE
if (ModeT::BlendOp == STYLEOP_Add &&
ModeT::BlendSrc == STYLEALPHA_One &&
ModeT::BlendDest == STYLEALPHA_Zero &&
(ModeT::Flags & STYLEF_Alpha1) &&
!(OptT::Flags & SWOPT_ColoredFog) &&
!(ModeT::Flags & STYLEF_RedIsAlpha) &&
!(ModeT::SWFlags & SWSTYLEF_Skycap) &&
!(ModeT::SWFlags & SWSTYLEF_FogBoundary) &&
!(ModeT::SWFlags & SWSTYLEF_Fill))
{
sseend += (x1 - x0) / 2 * 2;
__m128i mlightshade;
if (OptT::Flags & SWOPT_FixedLight)
mlightshade = _mm_set1_epi16(fixedlight);
__m128i alphamask = _mm_set1_epi32(0xff000000);
for (int x = x0; x < sseend; x += 2)
{
__m128i mfg = _mm_unpacklo_epi8(_mm_setr_epi32(texPixels[texel[x]], texPixels[texel[x + 1]], 0, 0), _mm_setzero_si128());
if (!(OptT::Flags & SWOPT_FixedLight))
mlightshade = _mm_shuffle_epi32(_mm_shufflelo_epi16(_mm_loadl_epi64((const __m128i*)&lightarray[x]), _MM_SHUFFLE(2, 2, 0, 0)), _MM_SHUFFLE(1, 1, 0, 0));
if (OptT::Flags & SWOPT_DynLights)
{
__m128i mdynlight = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)&dynlights[x]), _mm_setzero_si128());
mfg = _mm_srli_epi16(_mm_mullo_epi16(_mm_min_epi16(_mm_add_epi16(mdynlight, mlightshade), _mm_set1_epi16(256)), mfg), 8);
}
else
{
mfg = _mm_srli_epi16(_mm_mullo_epi16(mlightshade, mfg), 8);
}
_mm_storel_epi64((__m128i*)&destLine[x], _mm_or_si128(_mm_packus_epi16(mfg, _mm_setzero_si128()), alphamask));
}
}
#endif
for (int x = sseend; x < x1; x++)
{ {
if (ModeT::BlendOp == STYLEOP_Fuzz) if (ModeT::BlendOp == STYLEOP_Fuzz)
{ {
using namespace swrenderer; using namespace swrenderer;
float rcpW = 0x01000000 / posW; unsigned int sampleshadeout = APART(texPixels[texel[x]]);
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256 sampleshadeout += sampleshadeout >> 7; // 255 -> 256
int scaled_x = (x * fuzzscale) >> FRACBITS; int scaled_x = (x * fuzzscale) >> FRACBITS;
@ -654,14 +695,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
} }
else if (ModeT::SWFlags & SWSTYLEF_Skycap) else if (ModeT::SWFlags & SWSTYLEF_Skycap)
{ {
float rcpW = 0x01000000 / posW; uint32_t fg = texPixels[texel[x]];
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
uint32_t fg = texPixels[texelX * texHeight + texelY];
int v = texelV[x];
int start_fade = 2; // How fast it should fade out int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(v >> (16 - start_fade), 0, 256); int alpha_top = clamp(v >> (16 - start_fade), 0, 256);
int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256); int alpha_bottom = clamp(((2 << 24) - v) >> (16 - start_fade), 0, 256);
@ -695,11 +731,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
int lightshade; int lightshade;
if (OptT::Flags & SWOPT_FixedLight) if (OptT::Flags & SWOPT_FixedLight)
{ {
lightshade = light; lightshade = fixedlight;
} }
else else
{ {
lightshade = lightpos >> 4; lightshade = lightarray[x];
} }
uint32_t shadedfg_r, shadedfg_g, shadedfg_b; uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
@ -731,26 +767,17 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
{ {
fg = fillcolor; fg = fillcolor;
} }
else else if (ModeT::SWFlags & SWSTYLEF_Translated)
{ {
float rcpW = 0x01000000 / posW; fg = translation[((const uint8_t*)texPixels)[texel[x]]];
int32_t u = (int32_t)(posU * rcpW);
int32_t v = (int32_t)(posV * rcpW);
uint32_t texelX = ((((uint32_t)u << 8) >> 16) * texWidth) >> 16;
uint32_t texelY = ((((uint32_t)v << 8) >> 16) * texHeight) >> 16;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
} }
else if (ModeT::Flags & STYLEF_RedIsAlpha) else if (ModeT::Flags & STYLEF_RedIsAlpha)
{ {
fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY]; fg = ((const uint8_t*)texPixels)[texel[x]];
} }
else else
{ {
fg = texPixels[texelX * texHeight + texelY]; fg = texPixels[texel[x]];
}
} }
if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill)) if ((ModeT::Flags & STYLEF_ColorIsFixed) && !(ModeT::SWFlags & SWSTYLEF_Fill))
@ -765,17 +792,17 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!(ModeT::Flags & STYLEF_Alpha1)) if (!(ModeT::Flags & STYLEF_Alpha1))
{ {
fgalpha = (fgalpha * alpha) >> 8; fgalpha = (fgalpha * actoralpha) >> 8;
} }
int lightshade; uint32_t lightshade;
if (OptT::Flags & SWOPT_FixedLight) if (OptT::Flags & SWOPT_FixedLight)
{ {
lightshade = light; lightshade = fixedlight;
} }
else else
{ {
lightshade = lightpos >> 4; lightshade = lightarray[x];
} }
uint32_t shadedfg_r, shadedfg_g, shadedfg_b; uint32_t shadedfg_r, shadedfg_g, shadedfg_b;
@ -792,24 +819,18 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (OptT::Flags & SWOPT_DynLights) if (OptT::Flags & SWOPT_DynLights)
{ {
uint32_t lit_r = posdynlight_r >> 4; shadedfg_r = MIN(shadedfg_r + ((fg_r * RPART(dynlights[x])) >> 8), (uint32_t)255);
uint32_t lit_g = posdynlight_g >> 4; shadedfg_g = MIN(shadedfg_g + ((fg_g * GPART(dynlights[x])) >> 8), (uint32_t)255);
uint32_t lit_b = posdynlight_b >> 4; shadedfg_b = MIN(shadedfg_b + ((fg_b * BPART(dynlights[x])) >> 8), (uint32_t)255);
shadedfg_r = MIN(shadedfg_r + ((fg_r * lit_r) >> 8), (uint32_t)255);
shadedfg_g = MIN(shadedfg_g + ((fg_g * lit_g) >> 8), (uint32_t)255);
shadedfg_b = MIN(shadedfg_b + ((fg_b * lit_b) >> 8), (uint32_t)255);
} }
} }
else else
{ {
if (OptT::Flags & SWOPT_DynLights) if (OptT::Flags & SWOPT_DynLights)
{ {
uint32_t lit_r = posdynlight_r >> 4; shadedfg_r = (RPART(fg) * MIN(lightshade + RPART(dynlights[x]), (uint32_t)256)) >> 8;
uint32_t lit_g = posdynlight_g >> 4; shadedfg_g = (GPART(fg) * MIN(lightshade + GPART(dynlights[x]), (uint32_t)256)) >> 8;
uint32_t lit_b = posdynlight_b >> 4; shadedfg_b = (BPART(fg) * MIN(lightshade + BPART(dynlights[x]), (uint32_t)256)) >> 8;
shadedfg_r = (RPART(fg) * MIN(lightshade + lit_r, (uint32_t)256)) >> 8;
shadedfg_g = (GPART(fg) * MIN(lightshade + lit_g, (uint32_t)256)) >> 8;
shadedfg_b = (BPART(fg) * MIN(lightshade + lit_b, (uint32_t)256)) >> 8;
} }
else else
{ {
@ -927,24 +948,11 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
destLine[x] = MAKEARGB(255, out_r, out_g, out_b); destLine[x] = MAKEARGB(255, out_r, out_g, out_b);
} }
} }
posW += stepW;
posU += stepU;
posV += stepV;
if (OptT::Flags & SWOPT_DynLights)
{
posdynlight_r += dynlights_r[x >> 4];
posdynlight_g += dynlights_g[x >> 4];
posdynlight_b += dynlights_b[x >> 4];
}
if (!(OptT::Flags & SWOPT_FixedLight))
lightpos += lightarray[x >> 4];
x++;
} }
} }
template<typename ModeT> template<typename ModeT>
void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args) void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{ {
using namespace TriScreenDrawerModes; using namespace TriScreenDrawerModes;
@ -953,16 +961,16 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight()) if (!args->uniforms->FixedLight())
{ {
if (args->uniforms->SimpleShade()) if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args, thread);
else else
DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args, thread);
} }
else else
{ {
if (args->uniforms->SimpleShade()) if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args, thread);
else else
DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
} }
} }
else else
@ -970,22 +978,22 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight()) if (!args->uniforms->FixedLight())
{ {
if (args->uniforms->SimpleShade()) if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args, thread);
else else
DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
} }
else else
{ {
if (args->uniforms->SimpleShade()) if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args, thread);
else else
DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args); DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args, thread);
} }
} }
} }
template<typename ModeT, typename OptT> template<typename ModeT, typename OptT>
void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args) void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{ {
using namespace TriScreenDrawerModes; using namespace TriScreenDrawerModes;
@ -1501,23 +1509,23 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
} }
template<typename ModeT> template<typename ModeT>
void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args) void DrawSpan8(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread)
{ {
using namespace TriScreenDrawerModes; using namespace TriScreenDrawerModes;
if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0) if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0)
{ {
if (!args->uniforms->FixedLight()) if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args); DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args, thread);
else else
DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args); DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
} }
else else
{ {
if (!args->uniforms->FixedLight()) if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args); DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
else else
DrawSpanOpt8<ModeT, DrawerOptLCF>(y, x0, x1, args); DrawSpanOpt8<ModeT, DrawerOptLCF>(y, x0, x1, args, thread);
} }
} }
@ -2049,7 +2057,7 @@ void DrawRect32(const void *destOrg, int destWidth, int destHeight, int destPitc
DrawRectOpt32<ModeT, DrawerOptCF>(destOrg, destWidth, destHeight, destPitch, args, thread); DrawRectOpt32<ModeT, DrawerOptCF>(destOrg, destWidth, destHeight, destPitch, args, thread);
} }
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) = void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{ {
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>, &DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan8<TriScreenDrawerModes::StyleSkycap>, &DrawSpan8<TriScreenDrawerModes::StyleSkycap>,
@ -2081,7 +2089,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *
&DrawSpan8<TriScreenDrawerModes::StyleAddShadedTranslated> &DrawSpan8<TriScreenDrawerModes::StyleAddShadedTranslated>
}; };
void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *) = void(*ScreenTriangle::SpanDrawers32[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{ {
&DrawSpan32<TriScreenDrawerModes::StyleOpaque>, &DrawSpan32<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan32<TriScreenDrawerModes::StyleSkycap>, &DrawSpan32<TriScreenDrawerModes::StyleSkycap>,

View file

@ -142,8 +142,8 @@ class ScreenTriangle
public: public:
static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args); static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args); static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread);
static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);
static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); static void(*RectDrawers32[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *);

View file

@ -265,11 +265,11 @@ int main (int argc, char **argv)
fprintf (stderr, "%s\n", error.what ()); fprintf (stderr, "%s\n", error.what ());
#ifdef __APPLE__ #ifdef __APPLE__
Mac_I_FatalError(error.GetMessage()); Mac_I_FatalError(error.what());
#endif // __APPLE__ #endif // __APPLE__
#ifdef __linux__ #ifdef __linux__
Linux_I_FatalError(error.GetMessage()); Linux_I_FatalError(error.what());
#endif // __linux__ #endif // __linux__
exit (-1); exit (-1);

View file

@ -630,10 +630,6 @@ public:
double FindHighestCeilingSurrounding(vertex_t **v) const; // jff 2/04/98 double FindHighestCeilingSurrounding(vertex_t **v) const; // jff 2/04/98
double FindNextLowestCeiling(vertex_t **v) const; // jff 2/04/98 double FindNextLowestCeiling(vertex_t **v) const; // jff 2/04/98
double FindNextHighestCeiling(vertex_t **v) const; // jff 2/04/98 double FindNextHighestCeiling(vertex_t **v) const; // jff 2/04/98
double FindShortestTextureAround() const; // jff 2/04/98
double FindShortestUpperAround() const; // jff 2/04/98
sector_t *FindModelFloorSector(double floordestheight) const; // jff 2/04/98
sector_t *FindModelCeilingSector(double floordestheight) const; // jff 2/04/98
int FindMinSurroundingLight (int max) const; int FindMinSurroundingLight (int max) const;
sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH] sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH]
double FindLowestCeilingPoint(vertex_t **v) const; double FindLowestCeilingPoint(vertex_t **v) const;
@ -642,10 +638,11 @@ public:
int Index() const; int Index() const;
void AdjustFloorClip () const; void AdjustFloorClip () const;
void SetColor(int r, int g, int b, int desat); void SetColor(PalEntry pe, int desat);
void SetFade(int r, int g, int b); void SetFade(PalEntry pe);
void SetFogDensity(int dens); void SetFogDensity(int dens);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const; void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
int GetFloorLight() const; int GetFloorLight() const;
int GetCeilingLight() const; int GetCeilingLight() const;
@ -1585,6 +1582,11 @@ inline sector_t *P_PointInSector(double X, double Y)
return P_PointInSubsector(X, Y)->sector; return P_PointInSubsector(X, Y)->sector;
} }
inline sector_t *P_PointInSectorXY(double X, double Y) // This is for the benefit of unambiguously looking up this function's address
{
return P_PointInSubsector(X, Y)->sector;
}
inline bool FBoundingBox::inRange(const line_t *ld) const inline bool FBoundingBox::inRange(const line_t *ld) const
{ {
return Left() < ld->bbox[BOXRIGHT] && return Left() < ld->bbox[BOXRIGHT] &&
@ -1603,4 +1605,40 @@ inline void FColormap::CopyFrom3DLight(lightlist_t *light)
} }
} }
double FindShortestTextureAround(sector_t *sector); // jff 2/04/98
double FindShortestUpperAround(sector_t *sector); // jff 2/04/98
sector_t *FindModelFloorSector(sector_t *sec, double floordestheight); // jff 2/04/98
sector_t *FindModelCeilingSector(sector_t *sec, double floordestheight); // jff 2/04/98
// This setup is to allow the VM call directily into the implementation.
// With a member function this may be subject to OS implementation details, e.g. on Windows 32 bit members use a different calling convention than regular functions.
void RemoveForceField(sector_t *sec);
bool PlaneMoving(sector_t *sector, int pos);
void TransferSpecial(sector_t *self, sector_t *model);
void GetSpecial(sector_t *self, secspecial_t *spec);
void SetSpecial(sector_t *self, const secspecial_t *spec);
int GetTerrain(const sector_t *, int pos);
void CheckPortalPlane(sector_t *sector, int plane);
void AdjustFloorClip(const sector_t *sector);
void SetColor(sector_t *sector, int color, int desat);
void SetFade(sector_t *sector, int color);
int GetFloorLight(const sector_t *);
int GetCeilingLight(const sector_t *);
inline void sector_t::RemoveForceField() { return ::RemoveForceField(this); }
inline bool sector_t::PlaneMoving(int pos) { return ::PlaneMoving(this, pos); }
inline void sector_t::TransferSpecial(sector_t *model) { return ::TransferSpecial(this, model); }
inline void sector_t::GetSpecial(secspecial_t *spec) { ::GetSpecial(this, spec); }
inline void sector_t::SetSpecial(const secspecial_t *spec) { ::SetSpecial(this, spec); }
inline int sector_t::GetTerrain(int pos) const { return ::GetTerrain(this, pos); }
inline void sector_t::CheckPortalPlane(int plane) { return ::CheckPortalPlane(this, plane); }
inline void sector_t::AdjustFloorClip() const { ::AdjustFloorClip(this); }
inline void sector_t::SetColor(PalEntry pe, int desat) { ::SetColor(this, pe, desat); }
inline void sector_t::SetFade(PalEntry pe) { ::SetFade(this, pe); }
inline int sector_t::GetFloorLight() const { return ::GetFloorLight(this); }
inline int sector_t::GetCeilingLight() const { return ::GetCeilingLight(this); }
#endif #endif

View file

@ -1438,6 +1438,24 @@ void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool
} }
} }
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local)
{
if (!looping)
{
if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
}
}
else
{
if (!S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local);
}
}
}
//========================================================================== //==========================================================================
// //
// S_LoadSound // S_LoadSound

View file

@ -371,6 +371,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
unsigned int S_GetMSLength(FSoundID sound); unsigned int S_GetMSLength(FSoundID sound);
void S_ParseMusInfo(); void S_ParseMusInfo();
bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time); bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time);
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local);
// [RH] Prints sound debug info to the screen. // [RH] Prints sound debug info to the screen.
// Modelled after Hexen's noise cheat. // Modelled after Hexen's noise cheat.

View file

@ -259,20 +259,9 @@ void ExpEmit::Reuse(VMFunctionBuilder *build)
// //
//========================================================================== //==========================================================================
static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCallType func, const uint8_t *reginfo) static PFunction *FindBuiltinFunction(FName funcname)
{ {
PSymbol *sym = Namespaces.GlobalNamespace->Symbols.FindSymbol(funcname, false); return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true));
if (sym == nullptr)
{
PSymbolVMFunction *symfunc = Create<PSymbolVMFunction>(funcname);
VMNativeFunction *calldec = new VMNativeFunction(func, funcname);
calldec->PrintableName = funcname.GetChars();
calldec->RegTypes = reginfo;
symfunc->Function = calldec;
sym = symfunc;
Namespaces.GlobalNamespace->Symbols.AddSymbol(sym);
}
return sym;
} }
//========================================================================== //==========================================================================
@ -5471,33 +5460,35 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
int BuiltinRandom(VM_ARGS) static int NativeRandom(FRandom *rng, int min, int max)
{
if (max < min)
{
std::swap(max, min);
}
return (*rng)(max - min + 1) + min;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom, NativeRandom)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom); PARAM_POINTER(rng, FRandom);
PARAM_INT(min); PARAM_INT(min);
PARAM_INT(max); PARAM_INT(max);
if (max < min) ACTION_RETURN_INT(NativeRandom(rng, min, max));
{
std::swap(max, min);
}
ACTION_RETURN_INT((*rng)(max - min + 1) + min);
} }
ExpEmit FxRandom::Emit(VMFunctionBuilder *build) ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
{ {
// Call DecoRandom to generate a random number. // Call DecoRandom to generate a random number.
VMFunction *callfunc; VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT }; auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
assert(min && max); assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng); emitters.AddParameterPointerConst(rng);
emitters.AddParameter(build, min); emitters.AddParameter(build, min);
emitters.AddParameter(build, max); emitters.AddParameter(build, max);
@ -5596,12 +5587,10 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
// Call BuiltinRandom to generate a random number. // Call BuiltinRandom to generate a random number.
VMFunction *callfunc; VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT }; auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng); emitters.AddParameterPointerConst(rng);
@ -5694,13 +5683,8 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
// //
//========================================================================== //==========================================================================
int BuiltinFRandom(VM_ARGS) static double NativeFRandom(FRandom *rng, double min, double max)
{ {
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
PARAM_FLOAT(min);
PARAM_FLOAT(max);
int random = (*rng)(0x40000000); int random = (*rng)(0x40000000);
double frandom = random / double(0x40000000); double frandom = random / double(0x40000000);
@ -5708,20 +5692,29 @@ int BuiltinFRandom(VM_ARGS)
{ {
std::swap(max, min); std::swap(max, min);
} }
ACTION_RETURN_FLOAT(frandom * (max - min) + min); return frandom * (max - min) + min;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFRandom, NativeFRandom)
{
PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom);
PARAM_FLOAT(min);
PARAM_FLOAT(max);
ACTION_RETURN_FLOAT(NativeFRandom(rng, min, max));
} }
ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
{ {
// Call the BuiltinFRandom function to generate a floating point random number.. // Call the BuiltinFRandom function to generate a floating point random number..
VMFunction *callfunc; VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_FLOAT, REGT_FLOAT }; auto sym = FindBuiltinFunction(NAME_BuiltinFRandom);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom, reginfo);
assert(sym);
callfunc = sym->Variants[0].Implementation;
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
assert(min && max); assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng); emitters.AddParameterPointerConst(rng);
@ -5776,7 +5769,12 @@ FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
int BuiltinRandom2(VM_ARGS) static int NativeRandom2(FRandom *rng, int maskval)
{
return rng->Random2(maskval);
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandom2, NativeRandom2)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom); PARAM_POINTER(rng, FRandom);
@ -5794,12 +5792,10 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
{ {
// Call the BuiltinRandom function to generate the random number. // Call the BuiltinRandom function to generate the random number.
VMFunction *callfunc; VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT }; auto sym = FindBuiltinFunction(NAME_BuiltinRandom2);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom2, BuiltinRandom2, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
@ -5853,7 +5849,12 @@ FxExpression *FxRandomSeed::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
int BuiltinRandomSeed(VM_ARGS) static void NativeRandomSeed(FRandom *rng, int seed)
{
rng->Init(seed);
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinRandomSeed, NativeRandomSeed)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_POINTER(rng, FRandom) PARAM_POINTER(rng, FRandom)
@ -5866,12 +5867,10 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
{ {
// Call DecoRandom to generate a random number. // Call DecoRandom to generate a random number.
VMFunction *callfunc; VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT }; auto sym = FindBuiltinFunction(NAME_BuiltinRandomSeed);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandomSeed, BuiltinRandomSeed, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng); emitters.AddParameterPointerConst(rng);
@ -8525,7 +8524,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
// //
//========================================================================== //==========================================================================
int BuiltinCallLineSpecial(VM_ARGS) DEFINE_ACTION_FUNCTION(DObject, BuiltinCallLineSpecial)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_INT(special); PARAM_INT(special);
@ -8545,11 +8544,10 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
// Call the BuiltinCallLineSpecial function to perform the desired special. // Call the BuiltinCallLineSpecial function to perform the desired special.
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER, REGT_INT, REGT_INT, REGT_INT, REGT_INT, REGT_INT }; static uint8_t reginfo[] = { REGT_INT, REGT_POINTER, REGT_INT, REGT_INT, REGT_INT, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial, reginfo); auto sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); auto callfunc = sym->Variants[0].Implementation;
VMFunction *callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
@ -10749,23 +10747,29 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
int BuiltinNameToClass(VM_ARGS) static PClass *NativeNameToClass(int _clsname, PClass *desttype)
{ {
PARAM_PROLOGUE;
PARAM_NAME(clsname);
PARAM_CLASS(desttype, DObject);
PClass *cls = nullptr; PClass *cls = nullptr;
FName clsname = ENamedName(_clsname);
if (clsname != NAME_None) if (clsname != NAME_None)
{ {
cls = PClass::FindClass(clsname); cls = PClass::FindClass(clsname);
if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype))) if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype)))
{ {
// does not match required parameters or is invalid. // does not match required parameters or is invalid.
cls = nullptr; return nullptr;
} }
} }
ACTION_RETURN_POINTER(cls); return cls;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinNameToClass, NativeNameToClass)
{
PARAM_PROLOGUE;
PARAM_NAME(clsname);
PARAM_CLASS(desttype, DObject);
ACTION_RETURN_POINTER(NativeNameToClass(clsname, desttype));
} }
ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
@ -10777,12 +10781,10 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
// Call the BuiltinNameToClass function to convert from 'name' to class. // Call the BuiltinNameToClass function to convert from 'name' to class.
VMFunction *callfunc; VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER }; auto sym = FindBuiltinFunction(NAME_BuiltinNameToClass);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameter(build, basex); emitters.AddParameter(build, basex);
@ -10871,12 +10873,17 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
// //
//========================================================================== //==========================================================================
int BuiltinClassCast(VM_ARGS) static PClass *NativeClassCast(PClass *from, PClass *to)
{
return from && to && from->IsDescendantOf(to) ? from : nullptr;
}
DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinClassCast, NativeClassCast)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_CLASS(from, DObject); PARAM_CLASS(from, DObject);
PARAM_CLASS(to, DObject); PARAM_CLASS(to, DObject);
ACTION_RETURN_POINTER(from && to && from->IsDescendantOf(to) ? from : nullptr); ACTION_RETURN_POINTER(NativeClassCast(from, to));
} }
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
@ -10884,12 +10891,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
ExpEmit clsname = basex->Emit(build); ExpEmit clsname = basex->Emit(build);
VMFunction *callfunc; VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_POINTER }; auto sym = FindBuiltinFunction(NAME_BuiltinClassCast);
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast, reginfo);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction))); assert(sym);
assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = sym->Variants[0].Implementation;
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc); FunctionCallEmitter emitters(callfunc);
emitters.AddParameter(clsname, false); emitters.AddParameter(clsname, false);

View file

@ -52,7 +52,6 @@ IMPLEMENT_CLASS(PSymbolConstNumeric, false, false);
IMPLEMENT_CLASS(PSymbolConstString, false, false); IMPLEMENT_CLASS(PSymbolConstString, false, false);
IMPLEMENT_CLASS(PSymbolTreeNode, false, false) IMPLEMENT_CLASS(PSymbolTreeNode, false, false)
IMPLEMENT_CLASS(PSymbolType, false, false) IMPLEMENT_CLASS(PSymbolType, false, false)
IMPLEMENT_CLASS(PSymbolVMFunction, false, false)
IMPLEMENT_CLASS(PFunction, false, false) IMPLEMENT_CLASS(PFunction, false, false)
//========================================================================== //==========================================================================

View file

@ -37,16 +37,6 @@ protected:
// A VM function ------------------------------------------------------------ // A VM function ------------------------------------------------------------
class PSymbolVMFunction : public PSymbol
{
DECLARE_CLASS(PSymbolVMFunction, PSymbol);
public:
VMFunction *Function;
PSymbolVMFunction(FName name) : PSymbol(name) {}
PSymbolVMFunction() : PSymbol(NAME_None) {}
};
// A symbol for a type ------------------------------------------------------ // A symbol for a type ------------------------------------------------------
class PSymbolType : public PSymbol class PSymbolType : public PSymbol

View file

@ -944,6 +944,7 @@ void InitThingdef()
assert(afunc->VMPointer != NULL); assert(afunc->VMPointer != NULL);
*(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName); *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName);
(*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName); (*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName);
(*(afunc->VMPointer))->DirectNativeCall = afunc->DirectNative;
AFTable.Push(*afunc); AFTable.Push(*afunc);
} }
AFTable.ShrinkToFit(); AFTable.ShrinkToFit();

View file

@ -9,6 +9,7 @@ extern PStruct *TypeVector3;
static void OutputJitLog(const asmjit::StringLogger &logger); static void OutputJitLog(const asmjit::StringLogger &logger);
static TArray<uint8_t*> JitBlocks; static TArray<uint8_t*> JitBlocks;
static TArray<uint8_t*> JitFrames;
static size_t JitBlockPos = 0; static size_t JitBlockPos = 0;
static size_t JitBlockSize = 0; static size_t JitBlockSize = 0;
@ -61,6 +62,25 @@ static void *AllocJitMemory(size_t size)
#define UWOP_SAVE_XMM128_FAR 9 #define UWOP_SAVE_XMM128_FAR 9
#define UWOP_PUSH_MACHFRAME 10 #define UWOP_PUSH_MACHFRAME 10
void JitRelease()
{
#ifdef _WIN64
for (auto p : JitFrames)
{
RtlDeleteFunctionTable((PRUNTIME_FUNCTION)p);
}
#endif
for (auto p : JitBlocks)
{
asmjit::OSUtils::releaseVirtualMemory(p, 1024 * 1024);
}
JitFrames.Clear();
JitBlocks.Clear();
JitBlockPos = 0;
JitBlockSize = 0;
}
static TArray<uint16_t> CreateUnwindInfo(asmjit::CCFunc *func) static TArray<uint16_t> CreateUnwindInfo(asmjit::CCFunc *func)
{ {
using namespace asmjit; using namespace asmjit;
@ -276,6 +296,7 @@ static void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func)
table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr); table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr);
table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr); table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr);
BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr); BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr);
JitFrames.Push((uint8_t*)table);
if (result == 0) if (result == 0)
I_FatalError("RtlAddFunctionTable failed"); I_FatalError("RtlAddFunctionTable failed");
#endif #endif

View file

@ -317,13 +317,16 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
{ {
using namespace asmjit; using namespace asmjit;
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
if ((pc - 1)->op == OP_VTBL) if ((pc - 1)->op == OP_VTBL)
{ {
I_FatalError("Native direct member function calls not implemented\n"); I_FatalError("Native direct member function calls not implemented\n");
} }
asmjit::CBNode *cursorBefore = cc.getCursor();
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
asmjit::CBNode *cursorAfter = cc.getCursor();
cc.setCursor(cursorBefore);
X86Gp tmp; X86Gp tmp;
X86Xmm tmp2; X86Xmm tmp2;
@ -398,6 +401,8 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
} }
} }
cc.setCursor(cursorAfter);
if (numparams != B) if (numparams != B)
I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n"); I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n");
@ -461,7 +466,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature(VMFunction *func)
for (unsigned int i = 0; i < func->Proto->ArgumentTypes.Size(); i++) for (unsigned int i = 0; i < func->Proto->ArgumentTypes.Size(); i++)
{ {
const PType *type = func->Proto->ArgumentTypes[i]; const PType *type = func->Proto->ArgumentTypes[i];
if (func->ArgFlags[i] & (VARF_Out | VARF_Ref)) if (func->ArgFlags.Size() && func->ArgFlags[i] & (VARF_Out | VARF_Ref))
{ {
args.Push(TypeIdOf<void*>::kTypeId); args.Push(TypeIdOf<void*>::kTypeId);
key += "v"; key += "v";

View file

@ -53,6 +53,8 @@ extern FMemArena ClassDataAllocator;
#define MAX_RETURNS 8 // Maximum number of results a function called by script code can return #define MAX_RETURNS 8 // Maximum number of results a function called by script code can return
#define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function #define MAX_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
void JitRelease();
typedef unsigned char VM_UBYTE; typedef unsigned char VM_UBYTE;
typedef signed char VM_SBYTE; typedef signed char VM_SBYTE;
@ -432,6 +434,8 @@ public:
f->~VMFunction(); f->~VMFunction();
} }
AllFunctions.Clear(); AllFunctions.Clear();
// also release any JIT data
JitRelease();
} }
static void CreateRegUseInfo() static void CreateRegUseInfo()
{ {
@ -511,6 +515,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass()); #define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, self->GetClass());
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass()); #define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type *x = (type *)param[p].a; #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type *x = (type *)param[p].a;
#define PARAM_OUTPOINTER_AT(p,x,type) assert((p) < numparam); type *x = (type *)param[p].a;
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type x = (type )param[p].a; #define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); type x = (type )param[p].a;
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER && AssertObject(param[p].a)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type))); #define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER && AssertObject(param[p].a)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base))); #define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(reginfo[p] == REGT_POINTER); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
@ -534,6 +539,7 @@ bool AssertObject(void * ob);
#define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x) #define PARAM_STATE(x) ++paramnum; PARAM_STATE_AT(paramnum,x)
#define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x) #define PARAM_STATE_ACTION(x) ++paramnum; PARAM_STATE_ACTION_AT(paramnum,x)
#define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type) #define PARAM_POINTER(x,type) ++paramnum; PARAM_POINTER_AT(paramnum,x,type)
#define PARAM_OUTPOINTER(x,type) ++paramnum; PARAM_OUTPOINTER_AT(paramnum,x,type)
#define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type) #define PARAM_POINTERTYPE(x,type) ++paramnum; PARAM_POINTERTYPE_AT(paramnum,x,type)
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type) #define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base) #define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
@ -559,6 +565,7 @@ struct AFuncDesc
const char *FuncName; const char *FuncName;
actionf_p Function; actionf_p Function;
VMNativeFunction **VMPointer; VMNativeFunction **VMPointer;
void *DirectNative;
}; };
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -579,10 +586,19 @@ struct AFuncDesc
// Macros to handle action functions. These are here so that I don't have to // Macros to handle action functions. These are here so that I don't have to
// change every single use in case the parameters change. // change every single use in case the parameters change.
#define DEFINE_ACTION_FUNCTION_NATIVE(cls, name, native) \
static int AF_##cls##_##name(VM_ARGS); \
VMNativeFunction *cls##_##name##_VMPtr; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, reinterpret_cast<void*>(native) }; \
extern AFuncDesc const *const cls##_##name##_HookPtr; \
MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \
static int AF_##cls##_##name(VM_ARGS)
//#define DEFINE_ACTION_FUNCTION(cls, name) DEFINE_ACTION_FUNCTION_NATIVE(cls, name, nullptr)
#define DEFINE_ACTION_FUNCTION(cls, name) \ #define DEFINE_ACTION_FUNCTION(cls, name) \
static int AF_##cls##_##name(VM_ARGS); \ static int AF_##cls##_##name(VM_ARGS); \
VMNativeFunction *cls##_##name##_VMPtr; \ VMNativeFunction *cls##_##name##_VMPtr; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr }; \ static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, nullptr }; \
extern AFuncDesc const *const cls##_##name##_HookPtr; \ extern AFuncDesc const *const cls##_##name##_HookPtr; \
MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \ MSVC_ASEG AFuncDesc const *const cls##_##name##_HookPtr GCC_ASEG = &cls##_##name##_Hook; \
static int AF_##cls##_##name(VM_ARGS) static int AF_##cls##_##name(VM_ARGS)

View file

@ -80,6 +80,7 @@ void VMFunction::CreateRegUse()
return; return;
} }
assert(Proto->isPrototype()); assert(Proto->isPrototype());
for (auto arg : Proto->ArgumentTypes) for (auto arg : Proto->ArgumentTypes)
{ {
count += arg? arg->GetRegCount() : 1; count += arg? arg->GetRegCount() : 1;
@ -87,14 +88,20 @@ void VMFunction::CreateRegUse()
uint8_t *regp; uint8_t *regp;
RegTypes = regp = (uint8_t*)ClassDataAllocator.Alloc(count); RegTypes = regp = (uint8_t*)ClassDataAllocator.Alloc(count);
count = 0; count = 0;
for (auto arg : Proto->ArgumentTypes) for (unsigned i = 0; i < Proto->ArgumentTypes.Size(); i++)
{ {
auto arg = Proto->ArgumentTypes[i];
auto flg = ArgFlags.Size() > i ? ArgFlags[i] : 0;
if (arg == nullptr) if (arg == nullptr)
{ {
// Marker for start of varargs. // Marker for start of varargs.
*regp++ = REGT_NIL; *regp++ = REGT_NIL;
} }
else for (int i = 0; i < arg->GetRegCount(); i++) else if ((flg & VARF_Out) && !arg->isPointer())
{
*regp++ = REGT_POINTER;
}
else for (int j = 0; j < arg->GetRegCount(); j++)
{ {
*regp++ = arg->GetRegType(); *regp++ = arg->GetRegType();
} }

1267
src/scripting/vmthunks.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1586,17 +1586,13 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje
if (retcode) *retcode = true; if (retcode) *retcode = true;
if (arc.isWriting()) if (arc.isWriting())
{ {
if (value != nullptr) if (value != nullptr && !(value->ObjectFlags & (OF_EuthanizeMe | OF_Transient)))
{ {
int ndx; int ndx;
if (value == WP_NOCHANGE) if (value == WP_NOCHANGE)
{ {
ndx = -1; ndx = -1;
} }
else if (value->ObjectFlags & (OF_EuthanizeMe | OF_Transient))
{
return arc;
}
else else
{ {
int *pndx = arc.w->mObjectMap.CheckKey(value); int *pndx = arc.w->mObjectMap.CheckKey(value);

View file

@ -1423,6 +1423,24 @@ TXT_QUIETUS_PIECE = "SEGMENT OF QUIETUS";
TXT_WRAITHVERGE_PIECE = "SEGMENT OF WRAITHVERGE"; TXT_WRAITHVERGE_PIECE = "SEGMENT OF WRAITHVERGE";
TXT_BLOODSCOURGE_PIECE = "SEGMENT OF BLOODSCOURGE"; TXT_BLOODSCOURGE_PIECE = "SEGMENT OF BLOODSCOURGE";
// Friendly names
FN_FIREDEMON = "Afrit";
FN_DEMON1 = "Serpent";
FN_ETTIN = "Ettin";
FN_CENTAUR = "Centaur";
FN_SLAUGHTAUR = "Slaughtaur";
FN_BISHOP = "Bishop";
FN_ICEGUY = "Wendigo";
FN_SERPENT = "Stalker";
FN_WRAITH = "Reiver";
FN_DRAGON = "Death Wyvern";
FN_KORAX = "Korax";
FN_FBOSS = "Zedek";
FN_MBOSS = "Menelkir";
FN_CBOSS = "Traductus";
FN_HERESIARCH = "Heresiarch";
// Strife locks // Strife locks
TXT_NEEDKEY = "You don't have the key"; TXT_NEEDKEY = "You don't have the key";

View file

@ -366,6 +366,7 @@ struct GameInfoStruct native
native double gibfactor; native double gibfactor;
native bool intermissioncounter; native bool intermissioncounter;
native Name mSliderColor; native Name mSliderColor;
native Color defaultbloodcolor;
native double telefogheight; native double telefogheight;
native int defKickback; native int defKickback;
} }
@ -374,6 +375,15 @@ class Object native
{ {
native bool bDestroyed; native bool bDestroyed;
// These must be defined in some class, so that the compiler can find them. Object is just fine, as long as they are private to external code.
private native static int BuiltinRandom(voidptr rng, int min, int max);
private native static double BuiltinFRandom(voidptr rng, double min, double max);
private native static int BuiltinRandom2(voidptr rng, int mask);
private native static void BuiltinRandomSeed(voidptr rng, int seed);
private native static int BuiltinCallLineSpecial(int special, Actor activator, int arg1, int arg2, int arg3, int arg4, int arg5);
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
// These really should be global functions... // These really should be global functions...
native static String G_SkillName(); native static String G_SkillName();
native static int G_SkillPropertyInt(int p); native static int G_SkillPropertyInt(int p);

View file

@ -24,6 +24,7 @@ class Bishop : Actor
DeathSound "BishopDeath"; DeathSound "BishopDeath";
ActiveSound "BishopActiveSounds"; ActiveSound "BishopActiveSounds";
Obituary"$OB_BISHOP"; Obituary"$OB_BISHOP";
Tag "$FN_BISHOP";
} }
States States

View file

@ -21,6 +21,7 @@ class Centaur : Actor
HowlSound "PuppyBeat"; HowlSound "PuppyBeat";
Obituary "$OB_CENTAUR"; Obituary "$OB_CENTAUR";
DamageFactor "Electric", 3; DamageFactor "Electric", 3;
Tag "$FN_CENTAUR";
} }
States States
{ {
@ -107,6 +108,7 @@ class CentaurLeader : Centaur
Speed 10; Speed 10;
Obituary "$OB_SLAUGHTAUR"; Obituary "$OB_SLAUGHTAUR";
HitObituary "$OB_SLAUGHTAURHIT"; HitObituary "$OB_SLAUGHTAURHIT";
Tag "$FN_SLAUGHTAUR";
} }
States States
{ {

View file

@ -15,7 +15,8 @@ class ClericBoss : Actor
+DONTMORPH +DONTMORPH
PainSound "PlayerClericPain"; PainSound "PlayerClericPain";
DeathSound "PlayerClericCrazyDeath"; DeathSound "PlayerClericCrazyDeath";
Obituary "$OBCBOSS"; Obituary "$OB_CBOSS";
Tag "$FN_CBOSS";
} }
States States

View file

@ -20,6 +20,7 @@ class Demon1 : Actor
DeathSound "DemonDeath"; DeathSound "DemonDeath";
ActiveSound "DemonActive"; ActiveSound "DemonActive";
Obituary "$OB_DEMON1"; Obituary "$OB_DEMON1";
Tag "$FN_DEMON1";
} }
const ChunkFlags = SXF_TRANSFERTRANSLATION | SXF_ABSOLUTEVELOCITY; const ChunkFlags = SXF_TRANSFERTRANSLATION | SXF_ABSOLUTEVELOCITY;

View file

@ -19,6 +19,7 @@ class Dragon : Actor
DeathSound "DragonDeath"; DeathSound "DragonDeath";
ActiveSound "DragonActive"; ActiveSound "DragonActive";
Obituary "$OB_DRAGON"; Obituary "$OB_DRAGON";
Tag "$FN_DRAGON";
} }
States States

View file

@ -22,6 +22,7 @@ class Ettin : Actor
ActiveSound "EttinActive"; ActiveSound "EttinActive";
HowlSound "PuppyBeat"; HowlSound "PuppyBeat";
Obituary "$OB_ETTIN"; Obituary "$OB_ETTIN";
Tag "$FN_ETTIN";
} }
States States
{ {

View file

@ -17,6 +17,7 @@ class FighterBoss : Actor
PainSound "PlayerFighterPain"; PainSound "PlayerFighterPain";
DeathSound "PlayerFighterCrazyDeath"; DeathSound "PlayerFighterCrazyDeath";
Obituary "$OB_FBOSS"; Obituary "$OB_FBOSS";
Tag "$FN_FBOSS";
} }
States States

View file

@ -24,6 +24,7 @@ class FireDemon : Actor
DeathSound "FireDemonDeath"; DeathSound "FireDemonDeath";
ActiveSound "FireDemonActive"; ActiveSound "FireDemonActive";
Obituary "$OB_FIREDEMON"; Obituary "$OB_FIREDEMON";
Tag "$FN_FIREDEMON";
} }
States States

View file

@ -70,6 +70,7 @@ class Heresiarch : Actor
DeathSound "SorcererDeathScream"; DeathSound "SorcererDeathScream";
ActiveSound "SorcererActive"; ActiveSound "SorcererActive";
Obituary "$OB_HERESIARCH"; Obituary "$OB_HERESIARCH";
Tag "$FN_HERESIARCH";
} }
States States

View file

@ -65,6 +65,7 @@ class ZRock4 : Actor
{ {
Radius 20; Radius 20;
Height 16; Height 16;
+SOLID
} }
States States
{ {

View file

@ -20,6 +20,7 @@ class IceGuy : Actor
AttackSound "IceGuyAttack"; AttackSound "IceGuyAttack";
ActiveSound "IceGuyActive"; ActiveSound "IceGuyActive";
Obituary "$OB_ICEGUY"; Obituary "$OB_ICEGUY";
Tag "$FN_ICEGUY";
} }

View file

@ -60,6 +60,7 @@ class Korax : Actor
DeathSound "KoraxDeath"; DeathSound "KoraxDeath";
ActiveSound "KoraxActive"; ActiveSound "KoraxActive";
Obituary "$OB_KORAX"; Obituary "$OB_KORAX";
Tag "$FN_KORAX";
} }
States States

View file

@ -16,6 +16,7 @@ class MageBoss : Actor
PainSound "PlayerMagePain"; PainSound "PlayerMagePain";
DeathSound "PlayerMageCrazyDeath"; DeathSound "PlayerMageCrazyDeath";
Obituary "$OB_MBOSS"; Obituary "$OB_MBOSS";
Tag "$FN_MBOSS";
} }
States States

View file

@ -22,6 +22,7 @@ class Serpent : Actor
PainSound "SerpentPain"; PainSound "SerpentPain";
DeathSound "SerpentDeath"; DeathSound "SerpentDeath";
HitObituary "$OB_SERPENTHIT"; HitObituary "$OB_SERPENTHIT";
Tag "$FN_SERPENT";
} }
States States

View file

@ -21,6 +21,7 @@ class Wraith : Actor
ActiveSound "WraithActive"; ActiveSound "WraithActive";
HitObituary "$OB_WRAITHHIT"; HitObituary "$OB_WRAITHHIT";
Obituary "$OB_WRAITH"; Obituary "$OB_WRAITH";
Tag "$FN_WRAITH";
} }
States States