This commit is contained in:
Rachael Alexanderson 2018-11-26 20:33:44 -05:00
commit f07e7797bb
44 changed files with 2075 additions and 1510 deletions

View file

@ -1149,6 +1149,7 @@ set (PCH_SOURCES
r_data/models/models_ue1.cpp
r_data/models/models_obj.cpp
scripting/symbols.cpp
scripting/vmthunks.cpp
scripting/types.cpp
scripting/thingdef.cpp
scripting/thingdef_data.cpp
@ -1165,6 +1166,7 @@ set (PCH_SOURCES
scripting/vm/vmexec.cpp
scripting/vm/vmframe.cpp
scripting/vm/jit.cpp
scripting/vm/jit_runtime.cpp
scripting/vm/jit_call.cpp
scripting/vm/jit_flow.cpp
scripting/vm/jit_load.cpp

View file

@ -266,8 +266,6 @@ void PClass::StaticShutdown ()
// This flags DObject::Destroy not to call any scripted OnDestroy methods anymore.
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)
{
p.PendingWeapon = nullptr;

View file

@ -735,7 +735,7 @@ void ProcessEDSector(sector_t *sec, int recordnum)
sec->terrainnum[sector_t::floor] = esec->floorterrain;
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;
for (int i = 0; i < 2; i++)

View file

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

View file

@ -958,33 +958,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)
{
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;
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_Direction = -1;
break;
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_Direction = 1;
break;
@ -420,8 +420,8 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t
type == DCeiling::ceilRaiseToFloor ||
/*type == ceilLowerToHighest ||*/
type == DCeiling::ceilLowerToFloor) ?
sec->FindModelFloorSector (targheight) :
sec->FindModelCeilingSector (targheight);
FindModelFloorSector(sec, targheight) :
FindModelCeilingSector(sec, targheight);
if (modelsec != NULL)
{
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:
floor->m_Direction = -1;
newheight = sec->CenterFloor() - sec->FindShortestTextureAround();
newheight = sec->CenterFloor() - FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
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
// enough, BOOM preserved the code here even though it
// also had this function.)
newheight = sec->CenterFloor() + sec->FindShortestTextureAround();
newheight = sec->CenterFloor() + FindShortestTextureAround(sec);
floor->m_FloorDestDist = sec->floorplane.PointToDist(sec->centerspot, newheight);
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
sector_t *modelsec;
modelsec = sec->FindModelFloorSector(newheight);
modelsec = FindModelFloorSector(sec, newheight);
if (modelsec != NULL)
{
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::floorRaiseToCeiling ||
floortype == DFloor::floorLowerToCeiling) ?
sec->FindModelCeilingSector(-floor->m_FloorDestDist) :
sec->FindModelFloorSector(-floor->m_FloorDestDist);
FindModelCeilingSector(sec, -floor->m_FloorDestDist) :
FindModelFloorSector(sec, -floor->m_FloorDestDist);
if (modelsec != NULL)
{
@ -1126,7 +1126,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
}
break;
case numChangeOnly:
secm = sec->FindModelFloorSector (sec->CenterFloor());
secm = FindModelFloorSector(sec, sec->CenterFloor());
if (secm)
{ // if no model, no change
sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor));

View file

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

File diff suppressed because it is too large Load diff

View file

@ -77,6 +77,15 @@ public:
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);
private:

View file

@ -227,7 +227,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
if (x > xstart)
{
if (writeColor)
drawfunc(y, xstart, x, args);
drawfunc(y, xstart, x, args, thread);
if (writeStencil)
{
@ -379,29 +379,54 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
}
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;
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 startX, startY;
float stepW, stepU, stepV, stepWorldX, stepWorldY, stepWorldZ;
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;
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];
int16_t posdynlight_r, posdynlight_g, posdynlight_b;
fixed_t lightarray[MAXWIDTH / 16];
float *worldposX = thread->worldposX;
float *worldposY = thread->worldposY;
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;
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;
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)
{
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;
posWorldY = v1WorldY + stepWorldY * startX + args->gradientY.WorldY * 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();
num_lights = args->uniforms->NumLights();
@ -503,26 +539,12 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
worldnormalZ *= rcplen;
}
int affineOffset = x0 / 16 * 16 - x0;
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++)
for (int x = x0; x < x1; x++)
{
uint32_t lit_r = RPART(dynlightcolor);
uint32_t lit_g = GPART(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++)
{
float lightposX = lights[i].x;
@ -538,9 +560,9 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
// L = light-pos
// dist = sqrt(dot(L, L))
// distance_attenuation = 1 - MIN(dist * (1/radius), 1)
float Lx = lightposX - worldposX;
float Ly = lightposY - worldposY;
float Lz = lightposZ - worldposZ;
float Lx = lightposX - worldposX[x];
float Ly = lightposY - worldposY[x];
float Lz = lightposZ - worldposZ[x];
float dist2 = Lx * Lx + Ly * Ly + Lz * Lz;
#ifdef NO_SSE
//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_g = MIN<uint32_t>(lit_g, 255);
lit_b = MIN<uint32_t>(lit_b, 255);
dynlights_r[x] = lit_r;
dynlights_g[x] = lit_g;
dynlights_b[x] = lit_b;
posLightW += stepLightW;
posWorldX += stepWorldX;
posWorldY += stepWorldY;
posWorldZ += stepWorldZ;
dynlights[x] = MAKEARGB(255, lit_r, lit_g, lit_b);
}
}
int offset = x0 >> 4;
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];
dynlights_g[x] = dynlights_g[x + 1] - dynlights_g[x];
dynlights_b[x] = dynlights_b[x + 1] - dynlights_b[x];
}
if (OptT::Flags & SWOPT_FixedLight)
{
fixedlight = args->uniforms->Light();
fixedlight += fixedlight >> 7; // 255 -> 256
}
if (OptT::Flags & SWOPT_ColoredFog)
@ -609,8 +616,6 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
inv_desaturate = 256 - desaturate;
}
fixed_t fuzzscale;
int _fuzzpos;
if (ModeT::BlendOp == STYLEOP_Fuzz)
{
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 *destLine = dest + args->pitch * y;
int x = x0;
while (x < x1)
int sseend = x0;
#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)
{
using namespace swrenderer;
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;
unsigned int sampleshadeout = APART(texPixels[texelX * texHeight + texelY]);
unsigned int sampleshadeout = APART(texPixels[texel[x]]);
sampleshadeout += sampleshadeout >> 7; // 255 -> 256
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)
{
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;
uint32_t fg = texPixels[texelX * texHeight + texelY];
uint32_t fg = texPixels[texel[x]];
int v = texelV[x];
int start_fade = 2; // How fast it should fade out
int alpha_top = clamp(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;
if (OptT::Flags & SWOPT_FixedLight)
{
lightshade = light;
lightshade = fixedlight;
}
else
{
lightshade = lightpos >> 4;
lightshade = lightarray[x];
}
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;
}
else if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texel[x]]];
}
else if (ModeT::Flags & STYLEF_RedIsAlpha)
{
fg = ((const uint8_t*)texPixels)[texel[x]];
}
else
{
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;
if (ModeT::SWFlags & SWSTYLEF_Translated)
{
fg = translation[((const uint8_t*)texPixels)[texelX * texHeight + texelY]];
}
else if (ModeT::Flags & STYLEF_RedIsAlpha)
{
fg = ((const uint8_t*)texPixels)[texelX * texHeight + texelY];
}
else
{
fg = texPixels[texelX * texHeight + texelY];
}
fg = texPixels[texel[x]];
}
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))
{
fgalpha = (fgalpha * alpha) >> 8;
fgalpha = (fgalpha * actoralpha) >> 8;
}
int lightshade;
uint32_t lightshade;
if (OptT::Flags & SWOPT_FixedLight)
{
lightshade = light;
lightshade = fixedlight;
}
else
{
lightshade = lightpos >> 4;
lightshade = lightarray[x];
}
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)
{
uint32_t lit_r = posdynlight_r >> 4;
uint32_t lit_g = posdynlight_g >> 4;
uint32_t lit_b = posdynlight_b >> 4;
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);
shadedfg_r = MIN(shadedfg_r + ((fg_r * RPART(dynlights[x])) >> 8), (uint32_t)255);
shadedfg_g = MIN(shadedfg_g + ((fg_g * GPART(dynlights[x])) >> 8), (uint32_t)255);
shadedfg_b = MIN(shadedfg_b + ((fg_b * BPART(dynlights[x])) >> 8), (uint32_t)255);
}
}
else
{
if (OptT::Flags & SWOPT_DynLights)
{
uint32_t lit_r = posdynlight_r >> 4;
uint32_t lit_g = posdynlight_g >> 4;
uint32_t lit_b = posdynlight_b >> 4;
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;
shadedfg_r = (RPART(fg) * MIN(lightshade + RPART(dynlights[x]), (uint32_t)256)) >> 8;
shadedfg_g = (GPART(fg) * MIN(lightshade + GPART(dynlights[x]), (uint32_t)256)) >> 8;
shadedfg_b = (BPART(fg) * MIN(lightshade + BPART(dynlights[x]), (uint32_t)256)) >> 8;
}
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);
}
}
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>
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;
@ -953,16 +961,16 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight())
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOpt>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptC>(y, x0, x1, args, thread);
}
else
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptF>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
}
}
else
@ -970,22 +978,22 @@ void DrawSpan32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
if (!args->uniforms->FixedLight())
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptL>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
}
else
{
if (args->uniforms->SimpleShade())
DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLF>(y, x0, x1, args, thread);
else
DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args);
DrawSpanOpt32<ModeT, DrawerOptLCF>(y, x0, x1, args, thread);
}
}
}
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;
@ -1501,23 +1509,23 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
}
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;
if (args->uniforms->NumLights() == 0 && args->uniforms->DynLightColor() == 0)
{
if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptC>(y, x0, x1, args, thread);
else
DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptCF>(y, x0, x1, args, thread);
}
else
{
if (!args->uniforms->FixedLight())
DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args);
DrawSpanOpt8<ModeT, DrawerOptLC>(y, x0, x1, args, thread);
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);
}
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *) =
void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *, PolyTriangleThreadData *) =
{
&DrawSpan8<TriScreenDrawerModes::StyleOpaque>,
&DrawSpan8<TriScreenDrawerModes::StyleSkycap>,
@ -2081,7 +2089,7 @@ void(*ScreenTriangle::SpanDrawers8[])(int, int, int, const TriDrawTriangleArgs *
&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::StyleSkycap>,

View file

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

View file

@ -630,10 +630,6 @@ public:
double FindHighestCeilingSurrounding(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 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;
sector_t *NextSpecialSector (int type, sector_t *prev) const; // [RH]
double FindLowestCeilingPoint(vertex_t **v) const;
@ -642,12 +638,13 @@ public:
int Index() const;
void AdjustFloorClip () const;
void SetColor(int r, int g, int b, int desat);
void SetFade(int r, int g, int b);
void SetColor(PalEntry pe, int desat);
void SetFade(PalEntry pe);
void SetFogDensity(int dens);
void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
int GetFloorLight () const;
int GetCeilingLight () const;
int GetFloorLight() const;
int GetCeilingLight() const;
sector_t *GetHeightSec() const
{
@ -1585,6 +1582,11 @@ inline sector_t *P_PointInSector(double X, double Y)
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
{
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

View file

@ -1443,6 +1443,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

View file

@ -371,6 +371,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
unsigned int S_GetMSLength(FSoundID sound);
void S_ParseMusInfo();
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.
// 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);
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;
return dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->FindSymbol(funcname, true));
}
//==========================================================================
@ -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_POINTER(rng, FRandom);
PARAM_INT(min);
PARAM_INT(max);
if (max < min)
{
std::swap(max, min);
}
ACTION_RETURN_INT((*rng)(max - min + 1) + min);
ACTION_RETURN_INT(NativeRandom(rng, min, max));
}
ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
{
// Call DecoRandom to generate a random number.
VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
assert(sym);
callfunc = sym->Variants[0].Implementation;
assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
emitters.AddParameter(build, min);
emitters.AddParameter(build, max);
@ -5596,12 +5587,10 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
// Call BuiltinRandom to generate a random number.
VMFunction *callfunc;
static const uint8_t reginfo[] = { REGT_POINTER, REGT_INT, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom, BuiltinRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
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);
double frandom = random / double(0x40000000);
@ -5708,20 +5692,29 @@ int BuiltinFRandom(VM_ARGS)
{
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)
{
// Call the BuiltinFRandom function to generate a floating point random number..
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_FLOAT, REGT_FLOAT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinFRandom, BuiltinFRandom, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinFRandom);
assert(sym);
callfunc = sym->Variants[0].Implementation;
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
assert(min && max);
callfunc = ((PSymbolVMFunction *)sym)->Function;
FunctionCallEmitter emitters(callfunc);
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_POINTER(rng, FRandom);
@ -5794,12 +5792,10 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
{
// Call the BuiltinRandom function to generate the random number.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandom2, BuiltinRandom2, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandom2);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
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_POINTER(rng, FRandom)
@ -5866,12 +5867,10 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
{
// Call DecoRandom to generate a random number.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_INT };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinRandomSeed, BuiltinRandomSeed, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinRandomSeed);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameterPointerConst(rng);
@ -8525,7 +8524,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
//
//==========================================================================
int BuiltinCallLineSpecial(VM_ARGS)
DEFINE_ACTION_FUNCTION(DObject, BuiltinCallLineSpecial)
{
PARAM_PROLOGUE;
PARAM_INT(special);
@ -8545,11 +8544,10 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
// 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 };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial, BuiltinCallLineSpecial, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinCallLineSpecial);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
VMFunction *callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
auto callfunc = sym->Variants[0].Implementation;
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;
FName clsname = ENamedName(_clsname);
if (clsname != NAME_None)
{
cls = PClass::FindClass(clsname);
if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype)))
{
// 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)
@ -10777,12 +10781,10 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
// Call the BuiltinNameToClass function to convert from 'name' to class.
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_INT, REGT_POINTER };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinNameToClass, BuiltinNameToClass, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinNameToClass);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
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_CLASS(from, 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)
@ -10884,12 +10891,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
ExpEmit clsname = basex->Emit(build);
VMFunction *callfunc;
static uint8_t reginfo[] = { REGT_POINTER, REGT_POINTER };
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast, reginfo);
auto sym = FindBuiltinFunction(NAME_BuiltinClassCast);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
assert(sym);
callfunc = sym->Variants[0].Implementation;
FunctionCallEmitter emitters(callfunc);
emitters.AddParameter(clsname, false);

View file

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

View file

@ -37,16 +37,6 @@ protected:
// 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 ------------------------------------------------------
class PSymbolType : public PSymbol

View file

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

View file

@ -8,281 +8,6 @@ extern PStruct *TypeVector3;
static void OutputJitLog(const asmjit::StringLogger &logger);
static TArray<uint8_t*> JitBlocks;
static size_t JitBlockPos = 0;
static size_t JitBlockSize = 0;
static asmjit::CodeInfo GetHostCodeInfo()
{
static bool firstCall = true;
static asmjit::CodeInfo codeInfo;
if (firstCall)
{
asmjit::JitRuntime rt;
codeInfo = rt.getCodeInfo();
firstCall = false;
}
return codeInfo;
}
static void *AllocJitMemory(size_t size)
{
using namespace asmjit;
if (JitBlockPos + size <= JitBlockSize)
{
uint8_t *p = JitBlocks[JitBlocks.Size() - 1];
p += JitBlockPos;
JitBlockPos += size;
return p;
}
else
{
size_t allocatedSize = 0;
void *p = OSUtils::allocVirtualMemory(1024 * 1024, &allocatedSize, OSUtils::kVMWritable | OSUtils::kVMExecutable);
if (!p)
return nullptr;
JitBlocks.Push((uint8_t*)p);
JitBlockSize = allocatedSize;
JitBlockPos = size;
return p;
}
}
#define UWOP_PUSH_NONVOL 0
#define UWOP_ALLOC_LARGE 1
#define UWOP_ALLOC_SMALL 2
#define UWOP_SET_FPREG 3
#define UWOP_SAVE_NONVOL 4
#define UWOP_SAVE_NONVOL_FAR 5
#define UWOP_SAVE_XMM128 8
#define UWOP_SAVE_XMM128_FAR 9
#define UWOP_PUSH_MACHFRAME 10
static TArray<uint16_t> CreateUnwindInfo(asmjit::CCFunc *func)
{
using namespace asmjit;
FuncFrameLayout layout;
Error error = layout.init(func->getDetail(), func->getFrameInfo());
if (error != kErrorOk)
I_FatalError("FuncFrameLayout.init failed");
// We need a dummy emitter for instruction size calculations
CodeHolder code;
code.init(GetHostCodeInfo());
X86Assembler assembler(&code);
X86Emitter *emitter = assembler.asEmitter();
// Build UNWIND_CODE codes:
TArray<uint16_t> codes;
uint32_t opoffset, opcode, opinfo;
// Note: this must match exactly what X86Internal::emitProlog does
X86Gp zsp = emitter->zsp(); // ESP|RSP register.
X86Gp zbp = emitter->zsp(); // EBP|RBP register.
zbp.setId(X86Gp::kIdBp);
X86Gp gpReg = emitter->zsp(); // General purpose register (temporary).
X86Gp saReg = emitter->zsp(); // Stack-arguments base register.
uint32_t gpSaved = layout.getSavedRegs(X86Reg::kKindGp);
if (layout.hasPreservedFP())
{
// Emit: 'push zbp'
// 'mov zbp, zsp'.
gpSaved &= ~Utils::mask(X86Gp::kIdBp);
emitter->push(zbp);
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = X86Gp::kIdBp;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
emitter->mov(zbp, zsp);
}
if (gpSaved)
{
for (uint32_t i = gpSaved, regId = 0; i; i >>= 1, regId++)
{
if (!(i & 0x1)) continue;
// Emit: 'push gp' sequence.
gpReg.setId(regId);
emitter->push(gpReg);
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = regId;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
uint32_t stackArgsRegId = layout.getStackArgsRegId();
if (stackArgsRegId != Globals::kInvalidRegId && stackArgsRegId != X86Gp::kIdSp)
{
saReg.setId(stackArgsRegId);
if (!(layout.hasPreservedFP() && stackArgsRegId == X86Gp::kIdBp))
{
// Emit: 'mov saReg, zsp'.
emitter->mov(saReg, zsp);
}
}
if (layout.hasDynamicAlignment())
{
// Emit: 'and zsp, StackAlignment'.
emitter->and_(zsp, -static_cast<int32_t>(layout.getStackAlignment()));
}
if (layout.hasStackAdjustment())
{
// Emit: 'sub zsp, StackAdjustment'.
emitter->sub(zsp, layout.getStackAdjustment());
uint32_t stackadjust = layout.getStackAdjustment();
if (stackadjust <= 128)
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_SMALL;
opinfo = stackadjust / 8 - 1;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else if (stackadjust <= 512 * 1024 - 8)
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 0;
codes.Push(stackadjust / 8);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 1;
codes.Push((uint16_t)(stackadjust >> 16));
codes.Push((uint16_t)stackadjust);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
if (layout.hasDynamicAlignment() && layout.hasDsaSlotUsed())
{
// Emit: 'mov [zsp + dsaSlot], saReg'.
X86Mem saMem = x86::ptr(zsp, layout._dsaSlot);
emitter->mov(saMem, saReg);
}
uint32_t xmmSaved = layout.getSavedRegs(X86Reg::kKindVec);
if (xmmSaved)
{
X86Mem vecBase = x86::ptr(zsp, layout.getVecStackOffset());
X86Reg vecReg = x86::xmm(0);
bool avx = layout.isAvxEnabled();
bool aligned = layout.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? X86Inst::kIdVmovaps : X86Inst::kIdMovaps) : (avx ? X86Inst::kIdVmovups : X86Inst::kIdMovups);
uint32_t vecSize = 16;
for (uint32_t i = xmmSaved, regId = 0; i; i >>= 1, regId++)
{
if (!(i & 0x1)) continue;
// Emit 'movaps|movups [zsp + X], xmm0..15'.
vecReg.setId(regId);
emitter->emit(vecInst, vecBase, vecReg);
vecBase.addOffsetLo32(static_cast<int32_t>(vecSize));
if (vecBase.getOffsetLo32() / vecSize < (1 << 16))
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128;
opinfo = regId;
codes.Push(vecBase.getOffsetLo32() / vecSize);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128_FAR;
opinfo = regId;
codes.Push((uint16_t)(vecBase.getOffsetLo32() >> 16));
codes.Push((uint16_t)vecBase.getOffsetLo32());
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
}
// Build the UNWIND_INFO structure:
uint16_t version = 1, flags = 0, frameRegister = 0, frameOffset = 0;
uint16_t sizeOfProlog = (uint16_t)assembler.getOffset();
uint16_t countOfCodes = (uint16_t)codes.Size();
TArray<uint16_t> info;
info.Push(version | (flags << 3) | (sizeOfProlog << 8));
info.Push(countOfCodes | (frameRegister << 8) | (frameOffset << 12));
for (unsigned int i = codes.Size(); i > 0; i--)
info.Push(codes[i - 1]);
if (codes.Size() % 2 == 1)
info.Push(0);
return info;
}
static void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func)
{
using namespace asmjit;
size_t codeSize = code->getCodeSize();
if (codeSize == 0)
return nullptr;
#ifdef _WIN64
TArray<uint16_t> unwindInfo = CreateUnwindInfo(func);
size_t unwindInfoSize = unwindInfo.Size() * sizeof(uint16_t);
size_t functionTableSize = sizeof(RUNTIME_FUNCTION);
#else
size_t unwindInfoSize = 0;
size_t functionTableSize = 0;
#endif
codeSize = (codeSize + 15) / 16 * 16;
uint8_t *p = (uint8_t *)AllocJitMemory(codeSize + unwindInfoSize + functionTableSize);
if (!p)
return nullptr;
size_t relocSize = code->relocate(p);
if (relocSize == 0)
return nullptr;
size_t unwindStart = relocSize;
unwindStart = (unwindStart + 15) / 16 * 16;
JitBlockPos -= codeSize - unwindStart;
#ifdef _WIN64
uint8_t *baseaddr = JitBlocks.Last();
uint8_t *startaddr = p;
uint8_t *endaddr = p + relocSize;
uint8_t *unwindptr = p + unwindStart;
memcpy(unwindptr, &unwindInfo[0], unwindInfoSize);
RUNTIME_FUNCTION *table = (RUNTIME_FUNCTION*)(unwindptr + unwindInfoSize);
table[0].BeginAddress = (DWORD)(ptrdiff_t)(startaddr - baseaddr);
table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr);
table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr);
BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr);
if (result == 0)
I_FatalError("RtlAddFunctionTable failed");
#endif
return p;
}
JitFuncPtr JitCompile(VMScriptFunction *sfunc)
{
#if 0

View file

@ -317,13 +317,16 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
{
using namespace asmjit;
auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature(target));
if ((pc - 1)->op == OP_VTBL)
{
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;
X86Xmm tmp2;
@ -398,6 +401,8 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target)
}
}
cc.setCursor(cursorAfter);
if (numparams != B)
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++)
{
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);
key += "v";

View file

@ -0,0 +1,298 @@
#include "jit.h"
#include "jitintern.h"
static TArray<uint8_t*> JitBlocks;
static TArray<uint8_t*> JitFrames;
static size_t JitBlockPos = 0;
static size_t JitBlockSize = 0;
asmjit::CodeInfo GetHostCodeInfo()
{
static bool firstCall = true;
static asmjit::CodeInfo codeInfo;
if (firstCall)
{
asmjit::JitRuntime rt;
codeInfo = rt.getCodeInfo();
firstCall = false;
}
return codeInfo;
}
static void *AllocJitMemory(size_t size)
{
using namespace asmjit;
if (JitBlockPos + size <= JitBlockSize)
{
uint8_t *p = JitBlocks[JitBlocks.Size() - 1];
p += JitBlockPos;
JitBlockPos += size;
return p;
}
else
{
size_t allocatedSize = 0;
void *p = OSUtils::allocVirtualMemory(1024 * 1024, &allocatedSize, OSUtils::kVMWritable | OSUtils::kVMExecutable);
if (!p)
return nullptr;
JitBlocks.Push((uint8_t*)p);
JitBlockSize = allocatedSize;
JitBlockPos = size;
return p;
}
}
#define UWOP_PUSH_NONVOL 0
#define UWOP_ALLOC_LARGE 1
#define UWOP_ALLOC_SMALL 2
#define UWOP_SET_FPREG 3
#define UWOP_SAVE_NONVOL 4
#define UWOP_SAVE_NONVOL_FAR 5
#define UWOP_SAVE_XMM128 8
#define UWOP_SAVE_XMM128_FAR 9
#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)
{
using namespace asmjit;
FuncFrameLayout layout;
Error error = layout.init(func->getDetail(), func->getFrameInfo());
if (error != kErrorOk)
I_FatalError("FuncFrameLayout.init failed");
// We need a dummy emitter for instruction size calculations
CodeHolder code;
code.init(GetHostCodeInfo());
X86Assembler assembler(&code);
X86Emitter *emitter = assembler.asEmitter();
// Build UNWIND_CODE codes:
TArray<uint16_t> codes;
uint32_t opoffset, opcode, opinfo;
// Note: this must match exactly what X86Internal::emitProlog does
X86Gp zsp = emitter->zsp(); // ESP|RSP register.
X86Gp zbp = emitter->zsp(); // EBP|RBP register.
zbp.setId(X86Gp::kIdBp);
X86Gp gpReg = emitter->zsp(); // General purpose register (temporary).
X86Gp saReg = emitter->zsp(); // Stack-arguments base register.
uint32_t gpSaved = layout.getSavedRegs(X86Reg::kKindGp);
if (layout.hasPreservedFP())
{
// Emit: 'push zbp'
// 'mov zbp, zsp'.
gpSaved &= ~Utils::mask(X86Gp::kIdBp);
emitter->push(zbp);
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = X86Gp::kIdBp;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
emitter->mov(zbp, zsp);
}
if (gpSaved)
{
for (uint32_t i = gpSaved, regId = 0; i; i >>= 1, regId++)
{
if (!(i & 0x1)) continue;
// Emit: 'push gp' sequence.
gpReg.setId(regId);
emitter->push(gpReg);
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_PUSH_NONVOL;
opinfo = regId;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
uint32_t stackArgsRegId = layout.getStackArgsRegId();
if (stackArgsRegId != Globals::kInvalidRegId && stackArgsRegId != X86Gp::kIdSp)
{
saReg.setId(stackArgsRegId);
if (!(layout.hasPreservedFP() && stackArgsRegId == X86Gp::kIdBp))
{
// Emit: 'mov saReg, zsp'.
emitter->mov(saReg, zsp);
}
}
if (layout.hasDynamicAlignment())
{
// Emit: 'and zsp, StackAlignment'.
emitter->and_(zsp, -static_cast<int32_t>(layout.getStackAlignment()));
}
if (layout.hasStackAdjustment())
{
// Emit: 'sub zsp, StackAdjustment'.
emitter->sub(zsp, layout.getStackAdjustment());
uint32_t stackadjust = layout.getStackAdjustment();
if (stackadjust <= 128)
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_SMALL;
opinfo = stackadjust / 8 - 1;
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else if (stackadjust <= 512 * 1024 - 8)
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 0;
codes.Push(stackadjust / 8);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_ALLOC_LARGE;
opinfo = 1;
codes.Push((uint16_t)(stackadjust >> 16));
codes.Push((uint16_t)stackadjust);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
if (layout.hasDynamicAlignment() && layout.hasDsaSlotUsed())
{
// Emit: 'mov [zsp + dsaSlot], saReg'.
X86Mem saMem = x86::ptr(zsp, layout._dsaSlot);
emitter->mov(saMem, saReg);
}
uint32_t xmmSaved = layout.getSavedRegs(X86Reg::kKindVec);
if (xmmSaved)
{
X86Mem vecBase = x86::ptr(zsp, layout.getVecStackOffset());
X86Reg vecReg = x86::xmm(0);
bool avx = layout.isAvxEnabled();
bool aligned = layout.hasAlignedVecSR();
uint32_t vecInst = aligned ? (avx ? X86Inst::kIdVmovaps : X86Inst::kIdMovaps) : (avx ? X86Inst::kIdVmovups : X86Inst::kIdMovups);
uint32_t vecSize = 16;
for (uint32_t i = xmmSaved, regId = 0; i; i >>= 1, regId++)
{
if (!(i & 0x1)) continue;
// Emit 'movaps|movups [zsp + X], xmm0..15'.
vecReg.setId(regId);
emitter->emit(vecInst, vecBase, vecReg);
vecBase.addOffsetLo32(static_cast<int32_t>(vecSize));
if (vecBase.getOffsetLo32() / vecSize < (1 << 16))
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128;
opinfo = regId;
codes.Push(vecBase.getOffsetLo32() / vecSize);
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
else
{
opoffset = (uint32_t)assembler.getOffset();
opcode = UWOP_SAVE_XMM128_FAR;
opinfo = regId;
codes.Push((uint16_t)(vecBase.getOffsetLo32() >> 16));
codes.Push((uint16_t)vecBase.getOffsetLo32());
codes.Push(opoffset | (opcode << 8) | (opinfo << 12));
}
}
}
// Build the UNWIND_INFO structure:
uint16_t version = 1, flags = 0, frameRegister = 0, frameOffset = 0;
uint16_t sizeOfProlog = (uint16_t)assembler.getOffset();
uint16_t countOfCodes = (uint16_t)codes.Size();
TArray<uint16_t> info;
info.Push(version | (flags << 3) | (sizeOfProlog << 8));
info.Push(countOfCodes | (frameRegister << 8) | (frameOffset << 12));
for (unsigned int i = codes.Size(); i > 0; i--)
info.Push(codes[i - 1]);
if (codes.Size() % 2 == 1)
info.Push(0);
return info;
}
void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func)
{
using namespace asmjit;
size_t codeSize = code->getCodeSize();
if (codeSize == 0)
return nullptr;
#ifdef _WIN64
TArray<uint16_t> unwindInfo = CreateUnwindInfo(func);
size_t unwindInfoSize = unwindInfo.Size() * sizeof(uint16_t);
size_t functionTableSize = sizeof(RUNTIME_FUNCTION);
#else
size_t unwindInfoSize = 0;
size_t functionTableSize = 0;
#endif
codeSize = (codeSize + 15) / 16 * 16;
uint8_t *p = (uint8_t *)AllocJitMemory(codeSize + unwindInfoSize + functionTableSize);
if (!p)
return nullptr;
size_t relocSize = code->relocate(p);
if (relocSize == 0)
return nullptr;
size_t unwindStart = relocSize;
unwindStart = (unwindStart + 15) / 16 * 16;
JitBlockPos -= codeSize - unwindStart;
#ifdef _WIN64
uint8_t *baseaddr = JitBlocks.Last();
uint8_t *startaddr = p;
uint8_t *endaddr = p + relocSize;
uint8_t *unwindptr = p + unwindStart;
memcpy(unwindptr, &unwindInfo[0], unwindInfoSize);
RUNTIME_FUNCTION *table = (RUNTIME_FUNCTION*)(unwindptr + unwindInfoSize);
table[0].BeginAddress = (DWORD)(ptrdiff_t)(startaddr - baseaddr);
table[0].EndAddress = (DWORD)(ptrdiff_t)(endaddr - baseaddr);
table[0].UnwindInfoAddress = (DWORD)(ptrdiff_t)(unwindptr - baseaddr);
BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr);
JitFrames.Push((uint8_t*)table);
if (result == 0)
I_FatalError("RtlAddFunctionTable failed");
#endif
return p;
}

View file

@ -307,3 +307,6 @@ public:
throw AsmJitException(err, message);
}
};
void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func);
asmjit::CodeInfo GetHostCodeInfo();

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_TRY_DEPTH 8 // Maximum number of nested TRYs in a single function
void JitRelease();
typedef unsigned char VM_UBYTE;
typedef signed char VM_SBYTE;
@ -426,6 +428,8 @@ public:
f->~VMFunction();
}
AllFunctions.Clear();
// also release any JIT data
JitRelease();
}
static void CreateRegUseInfo()
{
@ -555,6 +559,7 @@ struct AFuncDesc
const char *FuncName;
actionf_p Function;
VMNativeFunction **VMPointer;
void *DirectNative;
};
#if defined(_MSC_VER)
@ -575,10 +580,19 @@ struct AFuncDesc
// Macros to handle action functions. These are here so that I don't have to
// 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) \
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 }; \
static const AFuncDesc cls##_##name##_Hook = { #cls, #name, AF_##cls##_##name, &cls##_##name##_VMPtr, nullptr }; \
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)

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 (arc.isWriting())
{
if (value != nullptr)
if (value != nullptr && !(value->ObjectFlags & (OF_EuthanizeMe | OF_Transient)))
{
int ndx;
if (value == WP_NOCHANGE)
{
ndx = -1;
}
else if (value->ObjectFlags & (OF_EuthanizeMe | OF_Transient))
{
return arc;
}
else
{
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_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
TXT_NEEDKEY = "You don't have the key";

View file

@ -373,6 +373,15 @@ class Object native
{
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...
native static String G_SkillName();
native static int G_SkillPropertyInt(int p);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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