- Updated lempar.c to v1.31.

- Added .txt files to the list of types (wad, zip, and pk3) that can be
  loaded without listing them after -file.
- Fonts that are created by the ACS setfont command to wrap a texture now
  support animated textures.
- FON2 fonts can now use their full palette for CR_UNTRANSLATED when drawn
  with the hardware 2D path instead of being restricted to the game palette.
- Fixed: Toggling vid_vsync would reset the displayed fullscreen gamma to 1
  on a Radeon 9000.
- Added back the off-by-one palette handling, but in a much more limited
  scope than before. The skipped entry is assumed to always be at 248, and
  it is assumed that all Shader Model 1.4 cards suffer from this. That's
  because all SM1.4 cards are based on variants of the ATI R200 core, and the
  RV250 in a Radeon 9000 craps up like this. I see no reason to assume that
  other flavors of the R200 are any different. (Interesting note: With the
  Radeon 9000, D3DTADDRESS_CLAMP is an invalid address mode when using the
  debug Direct3D 9 runtime, but it works perfectly fine with the retail
  Direct3D 9 runtime.) (Insight: The R200 probably uses bytes for all its
  math inside pixel shaders. That would explain perfectly why I can't use
  constants greater than 1 with PS1.4 and why it can't do an exact mapping to
  every entry in the color palette.
- Fixed: The software shaded drawer did not work for 2D, because its selected
  "color"map was replaced with the identitymap before being used.
- Fixed: I cannot use Printf to output messages before the framebuffer was
  completely setup, meaning that Shader Model 1.4 cards could not change
  resolution.
- I have decided to let remap palettes specify variable alpha values for
  their colors. D3DFB no longer forces them to 255.
- Updated re2c to version 0.12.3.
- Fixed: A_Wander used threshold as a timer, when it should have used
  reactiontime.
- Fixed: A_CustomRailgun would not fire at all for actors without a target
  when the aim parameter was disabled.
- Made the warp command work in multiplayer, again courtesy of Karate Chris.
- Fixed: Trying to spawn a bot while not in a game made for a crashing time.
  (Patch courtesy of Karate Chris.)
- Removed some floating point math from hu_scores.cpp that somebody's GCC
  gave warnings for (not mine, though).
- Fixed: The SBarInfo drawbar command crashed if the sprite image was
  unavailable.
- Fixed: FString::operator=(const char *) did not release its old buffer when
  being assigned to the null string.
- The scanner no longer has an upper limit on the length of strings it
  accepts, though short strings will be faster than long ones.
- Moved all the text scanning functions into a class. Mainly, this means that
  multiple script scanner states can be stored without being forced to do so
  recursively. I think I might be taking advantage of that in the near
  future. Possibly. Maybe.
- Removed some potential buffer overflows from the decal parser.
- Applied Blzut3's SBARINFO update #9:
  * Fixed: When using even length values in drawnumber it would cap to a 98
    value instead of a 99 as intended.
  * The SBarInfo parser can now accept negatives for coordinates. This
    doesn't allow much right now, but later I plan to add better fullscreen
    hud support in which the negatives will be more useful. This also cleans
    up the source a bit since all calls for (x, y) coordinates are with the
    function getCoordinates().
- Added support for stencilling actors.
- Added support for non-black colors specified with DTA_ColorOverlay to the
  software renderer.
- Fixed: The inverse, gold, red, and green fixed colormaps each allocated
  space for 32 different colormaps, even though each only used the first one.
- Added two new blending flags to make reverse subtract blending more useful:
  STYLEF_InvertSource and STYLEF_InvertOverlay. These invert the color that
  gets blended with the background, since that seems like a good idea for
  reverse subtraction. They also work with the other two blending operations.
- Added subtract and reverse subtract blending operations to the renderer.
  Since the ERenderStyle enumeration was getting rather unwieldy, I converted
  it into a new FRenderStyle structure that lets each parameter of the
  blending equation be set separately. This simplified the set up for the
  blend quite a bit, and it means a number of new combinations are available
  by setting the parameters properly.


SVN r710 (trunk)
This commit is contained in:
Randy Heit 2008-01-25 23:57:44 +00:00
parent 67afc9d4fc
commit e5572a1c4e
111 changed files with 10466 additions and 7801 deletions

View file

@ -1,7 +1,96 @@
January 25, 2008
- Lemon is now producing parsers that don't accept anything, so I'm going
back to v1.43 and trying each intermediate version to see where things
went wrong.
January 24, 2008
- Updated Lemon to its latest versions as of today.
(lemon.c: v1.53, lempar.c: v1.31)
- Added .txt files to the list of types (wad, zip, and pk3) that can be
loaded without listing them after -file.
- Fonts that are created by the ACS setfont command to wrap a texture now
support animated textures.
- FON2 fonts can now use their full palette for CR_UNTRANSLATED when drawn
with the hardware 2D path instead of being restricted to the game palette.
January 23, 2008
- Fixed: Toggling vid_vsync would reset the displayed fullscreen gamma to 1
on a Radeon 9000.
- Added back the off-by-one palette handling, but in a much more limited
scope than before. The skipped entry is assumed to always be at 248, and
it is assumed that all Shader Model 1.4 cards suffer from this. That's
because all SM1.4 cards are based on variants of the ATI R200 core, and the
RV250 in a Radeon 9000 craps up like this. I see no reason to assume that
other flavors of the R200 are any different. (Interesting note: With the
Radeon 9000, D3DTADDRESS_CLAMP is an invalid address mode when using the
debug Direct3D 9 runtime, but it works perfectly fine with the retail
Direct3D 9 runtime.) (Insight: The R200 probably uses bytes for all its
math inside pixel shaders. That would explain perfectly why I can't use
constants greater than 1 with PS1.4 and why it can't do an exact mapping to
every entry in the color palette.
- Fixed: The software shaded drawer did not work for 2D, because its selected
"color"map was replaced with the identitymap before being used.
- Fixed: I cannot use Printf to output messages before the framebuffer was
completely setup, meaning that Shader Model 1.4 cards could not change
resolution.
- I have decided to let remap palettes specify variable alpha values for
their colors. D3DFB no longer forces them to 255.
January 22, 2008
- Updated re2c to version 0.12.3.
- Fixed: A_Wander used threshold as a timer, when it should have used
reactiontime.
- Fixed: A_CustomRailgun would not fire at all for actors without a target
when the aim parameter was disabled.
- Made the warp command work in multiplayer, again courtesy of Karate Chris.
- Fixed: Trying to spawn a bot while not in a game made for a crashing time.
(Patch courtesy of Karate Chris.)
January 21, 2008
- Removed some floating point math from hu_scores.cpp that somebody's GCC
gave warnings for (not mine, though).
- Fixed: The SBarInfo drawbar command crashed if the sprite image was
unavailable.
- Fixed: FString::operator=(const char *) did not release its old buffer when
being assigned to the null string.
- The scanner no longer has an upper limit on the length of strings it
accepts, though short strings will be faster than long ones.
- Moved all the text scanning functions into a class. Mainly, this means that
multiple script scanner states can be stored without being forced to do so
recursively. I think I might be taking advantage of that in the near
future. Possibly. Maybe.
- Removed some potential buffer overflows from the decal parser.
January 18, 2008
- Applied Blzut3's SBARINFO update #9:
* Fixed: When using even length values in drawnumber it would cap to a 98
value instead of a 99 as intended.
* The SBarInfo parser can now accept negatives for coordinates. This
doesn't allow much right now, but later I plan to add better fullscreen
hud support in which the negatives will be more useful. This also cleans
up the source a bit since all calls for (x, y) coordinates are with the
function getCoordinates().
- Added support for stencilling actors.
- Added support for non-black colors specified with DTA_ColorOverlay to the
software renderer.
- Fixed: The inverse, gold, red, and green fixed colormaps each allocated
space for 32 different colormaps, even though each only used the first one.
- Added two new blending flags to make reverse subtract blending more useful:
STYLEF_InvertSource and STYLEF_InvertOverlay. These invert the color that
gets blended with the background, since that seems like a good idea for
reverse subtraction. They also work with the other two blending operations.
January 17, 2008
- Added subtract and reverse subtract blending operations to the renderer.
Since the ERenderStyle enumeration was getting rather unwieldy, I converted
it into a new FRenderStyle structure that lets each parameter of the
blending equation be set separately. This simplified the set up for the
blend quite a bit, and it means a number of new combinations are available
by setting the parameters properly.
January 16, 2008 (Changes by Graf Zahl) January 16, 2008 (Changes by Graf Zahl)
- Fixed: The StatusBar pointer was not NULLed after being deleted. - Fixed: The StatusBar pointer was not NULLed after being deleted.
January 15, 2008 January 15, 2008
- Plugged more leaks in SBARINFO. - Plugged more leaks in SBARINFO.
- Spawned actors that have MF2_DORMANT set in their default instance now have - Spawned actors that have MF2_DORMANT set in their default instance now have

View file

@ -40,6 +40,7 @@
#include "info.h" #include "info.h"
#include "doomdef.h" #include "doomdef.h"
#include "r_blend.h"
// //
// NOTES: AActor // NOTES: AActor
@ -330,24 +331,6 @@ enum
MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW
}; };
enum ERenderStyle
{
STYLE_None, // Do not draw
STYLE_Normal, // Normal; just copy the image to the screen
STYLE_Fuzzy, // Draw silhouette using "fuzz" effect
STYLE_SoulTrans, // Draw translucent with amount in r_transsouls
STYLE_OptFuzzy, // Draw as fuzzy or translucent, based on user preference
STYLE_Stencil, // Fill image interior with alphacolor
// The following styles can affect visibility in P_CheckSight()
STYLE_Translucent=64, // Draw translucent
STYLE_Add, // Draw additive
STYLE_Shaded, // Treat patch data as alpha values for alphacolor
STYLE_TranslucentStencil,
STYLE_Count
};
#define TRANSLUC25 (FRACUNIT/4) #define TRANSLUC25 (FRACUNIT/4)
#define TRANSLUC33 (FRACUNIT/3) #define TRANSLUC33 (FRACUNIT/3)
#define TRANSLUC50 (FRACUNIT/2) #define TRANSLUC50 (FRACUNIT/2)
@ -623,13 +606,13 @@ public:
WORD sprite; // used to find patch_t and flip value WORD sprite; // used to find patch_t and flip value
BYTE frame; // sprite frame to draw BYTE frame; // sprite frame to draw
fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size
BYTE RenderStyle; // Style to draw this actor with FRenderStyle RenderStyle; // Style to draw this actor with
DWORD renderflags; // Different rendering flags DWORD renderflags; // Different rendering flags
int picnum; // Draw this instead of sprite if != 0xffff int picnum; // Draw this instead of sprite if != 0xffff
SWORD TIDtoHate; // TID of things to hate (0 if none) SWORD TIDtoHate; // TID of things to hate (0 if none)
DWORD effects; // [RH] see p_effect.h DWORD effects; // [RH] see p_effect.h
fixed_t alpha; fixed_t alpha;
DWORD alphacolor; // Color to draw when STYLE_Shaded DWORD fillcolor; // Color to draw when STYLE_Shaded
// interaction info // interaction info
fixed_t pitch, roll; fixed_t pitch, roll;

View file

@ -1653,7 +1653,7 @@ void AM_drawThings ()
} }
static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust, static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust,
INTBOOL flip, fixed_t xscale, fixed_t yscale, int translation, fixed_t alpha, DWORD alphacolor, int renderstyle) INTBOOL flip, fixed_t xscale, fixed_t yscale, int translation, fixed_t alpha, DWORD fillcolor, FRenderStyle renderstyle)
{ {
if (tex == NULL || tex->UseType == FTexture::TEX_Null) if (tex == NULL || tex->UseType == FTexture::TEX_Null)
{ {
@ -1673,8 +1673,8 @@ static void DrawMarker (FTexture *tex, fixed_t x, fixed_t y, int yadjust,
DTA_FlipX, flip, DTA_FlipX, flip,
DTA_Translation, TranslationToTable(translation), DTA_Translation, TranslationToTable(translation),
DTA_Alpha, alpha, DTA_Alpha, alpha,
DTA_FillColor, alphacolor, DTA_FillColor, fillcolor,
DTA_RenderStyle, renderstyle, DTA_RenderStyle, DWORD(renderstyle),
TAG_DONE); TAG_DONE);
} }
@ -1684,7 +1684,8 @@ void AM_drawMarks ()
{ {
if (markpoints[i].x != -1) if (markpoints[i].x != -1)
{ {
DrawMarker (TexMan(marknums[i]), markpoints[i].x, markpoints[i].y, -3, 0, FRACUNIT, FRACUNIT, 0, FRACUNIT, 0, STYLE_Normal); DrawMarker (TexMan(marknums[i]), markpoints[i].x, markpoints[i].y, -3, 0,
FRACUNIT, FRACUNIT, 0, FRACUNIT, 0, LegacyRenderStyles[STYLE_Normal]);
} }
} }
} }
@ -1743,7 +1744,7 @@ void AM_drawAuthorMarkers ()
{ {
DrawMarker (tex, marked->x >> FRACTOMAPBITS, marked->y >> FRACTOMAPBITS, 0, DrawMarker (tex, marked->x >> FRACTOMAPBITS, marked->y >> FRACTOMAPBITS, 0,
flip, mark->scaleX, mark->scaleY, mark->Translation, flip, mark->scaleX, mark->scaleY, mark->Translation,
mark->alpha, mark->alphacolor, mark->RenderStyle); mark->alpha, mark->fillcolor, mark->RenderStyle);
} }
marked = mark->args[0] != 0 ? it.Next() : NULL; marked = mark->args[0] != 0 ? it.Next() : NULL;
} }

View file

@ -25,6 +25,12 @@ END_POINTERS
CCMD (addbot) CCMD (addbot)
{ {
if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION)
{
Printf ("Bots cannot be added when not in a game!\n");
return;
}
if (consoleplayer != Net_Arbitrator) if (consoleplayer != Net_Arbitrator)
{ {
Printf ("Only player %d can add bots\n", Net_Arbitrator + 1); Printf ("Only player %d can add bots\n", Net_Arbitrator + 1);
@ -36,14 +42,7 @@ CCMD (addbot)
Printf ("addbot [botname] : add a bot to the game\n"); Printf ("addbot [botname] : add a bot to the game\n");
return; return;
} }
/*
if (argc == 3) //Used force colornum
{
color = atoi (argv[2]);
if (color<0) color=0;
if (color>10) color=10;
}
*/
if (argv.argc() > 1) if (argv.argc() > 1)
bglobal.SpawnBot (argv[1]); bglobal.SpawnBot (argv[1]);
else else

View file

@ -504,6 +504,7 @@ void DCajunMaster::ForgetBots ()
bool DCajunMaster::LoadBots () bool DCajunMaster::LoadBots ()
{ {
FScanner sc;
FString tmp; FString tmp;
bool gotteam = false; bool gotteam = false;
@ -526,19 +527,19 @@ bool DCajunMaster::LoadBots ()
return false; return false;
} }
else else
SC_OpenFile (SHARE_DIR BOTFILENAME); sc.OpenFile (SHARE_DIR BOTFILENAME);
} }
#endif #endif
else else
{ {
SC_OpenFile (tmp); sc.OpenFile (tmp);
} }
while (SC_GetString ()) while (sc.GetString ())
{ {
if (!SC_Compare ("{")) if (!sc.Compare ("{"))
{ {
SC_ScriptError ("Unexpected token '%s'\n", sc_String); sc.ScriptError ("Unexpected token '%s'\n", sc.String);
} }
botinfo_t *newinfo = new botinfo_t; botinfo_t *newinfo = new botinfo_t;
@ -550,37 +551,37 @@ bool DCajunMaster::LoadBots ()
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
break; break;
switch (SC_MatchString (BotConfigStrings)) switch (sc.MatchString (BotConfigStrings))
{ {
case BOTCFG_NAME: case BOTCFG_NAME:
SC_MustGetString (); sc.MustGetString ();
appendinfo (newinfo->info, "name"); appendinfo (newinfo->info, "name");
appendinfo (newinfo->info, sc_String); appendinfo (newinfo->info, sc.String);
newinfo->name = copystring (sc_String); newinfo->name = copystring (sc.String);
break; break;
case BOTCFG_AIMING: case BOTCFG_AIMING:
SC_MustGetNumber (); sc.MustGetNumber ();
newinfo->skill.aiming = sc_Number; newinfo->skill.aiming = sc.Number;
break; break;
case BOTCFG_PERFECTION: case BOTCFG_PERFECTION:
SC_MustGetNumber (); sc.MustGetNumber ();
newinfo->skill.perfection = sc_Number; newinfo->skill.perfection = sc.Number;
break; break;
case BOTCFG_REACTION: case BOTCFG_REACTION:
SC_MustGetNumber (); sc.MustGetNumber ();
newinfo->skill.reaction = sc_Number; newinfo->skill.reaction = sc.Number;
break; break;
case BOTCFG_ISP: case BOTCFG_ISP:
SC_MustGetNumber (); sc.MustGetNumber ();
newinfo->skill.isp = sc_Number; newinfo->skill.isp = sc.Number;
break; break;
case BOTCFG_TEAM: case BOTCFG_TEAM:
@ -588,10 +589,10 @@ bool DCajunMaster::LoadBots ()
char teamstr[16]; char teamstr[16];
BYTE teamnum; BYTE teamnum;
SC_MustGetString (); sc.MustGetString ();
if (IsNum (sc_String)) if (IsNum (sc.String))
{ {
teamnum = atoi (sc_String); teamnum = atoi (sc.String);
if (!TEAMINFO_IsValidTeam (teamnum)) if (!TEAMINFO_IsValidTeam (teamnum))
{ {
teamnum = TEAM_None; teamnum = TEAM_None;
@ -602,7 +603,7 @@ bool DCajunMaster::LoadBots ()
teamnum = TEAM_None; teamnum = TEAM_None;
for (int i = 0; i < int(teams.Size()); ++i) for (int i = 0; i < int(teams.Size()); ++i)
{ {
if (stricmp (teams[i].name, sc_String) == 0) if (stricmp (teams[i].name, sc.String) == 0)
{ {
teamnum = i; teamnum = i;
break; break;
@ -617,13 +618,13 @@ bool DCajunMaster::LoadBots ()
} }
default: default:
if (stricmp (sc_String, "playerclass") == 0) if (stricmp (sc.String, "playerclass") == 0)
{ {
gotclass = true; gotclass = true;
} }
appendinfo (newinfo->info, sc_String); appendinfo (newinfo->info, sc.String);
SC_MustGetString (); sc.MustGetString ();
appendinfo (newinfo->info, sc_String); appendinfo (newinfo->info, sc.String);
break; break;
} }
} }
@ -642,10 +643,7 @@ bool DCajunMaster::LoadBots ()
bglobal.botinfo = newinfo; bglobal.botinfo = newinfo;
bglobal.loaded_bots++; bglobal.loaded_bots++;
} }
SC_Close ();
Printf ("%d bots read from %s\n", bglobal.loaded_bots, BOTFILENAME); Printf ("%d bots read from %s\n", bglobal.loaded_bots, BOTFILENAME);
return true; return true;
} }

View file

@ -636,16 +636,15 @@ CCMD (r_visibility)
CCMD (warp) CCMD (warp)
{ {
if (CheckCheatmode ())
{
return;
}
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)
{ {
Printf ("You can only warp inside a level.\n"); Printf ("You can only warp inside a level.\n");
return; return;
} }
if (netgame)
{
Printf ("You cannot warp in a net game!\n");
return;
}
if (argv.argc() != 3) if (argv.argc() != 3)
{ {
Printf ("Usage: warp <x> <y>\n"); Printf ("Usage: warp <x> <y>\n");

View file

@ -382,10 +382,11 @@ void CreatePath(const char * fn)
} }
// [RH] Replaces the escape sequences in a string with actual escaped characters. // [RH] Replaces the escape sequences in a string with actual escaped characters.
// This operation is done in-place. // This operation is done in-place. The result is the new length of the string.
void strbin (char *str) int strbin (char *str)
{ {
char *start;
char *p = str, c; char *p = str, c;
int i; int i;
@ -468,4 +469,5 @@ void strbin (char *str)
} }
} }
*str = 0; *str = 0;
return str - start;
} }

View file

@ -52,7 +52,7 @@ void FormatGUID (char *text, const GUID &guid);
const char *myasctime (); const char *myasctime ();
void strbin (char *str); int strbin (char *str);
void CreatePath(const char * fn); void CreatePath(const char * fn);

View file

@ -811,7 +811,7 @@ static int PatchThing (int thingy)
int style = FindStyle (Line2); int style = FindStyle (Line2);
if (style >= 0) if (style >= 0)
{ {
info->RenderStyle = style; info->RenderStyle = ERenderStyle(style);
hadStyle = true; hadStyle = true;
} }
} }

View file

@ -2130,7 +2130,8 @@ void D_DoomMain (void)
DArgs *files = Args.GatherFiles ("-file", ".wad", true); DArgs *files = Args.GatherFiles ("-file", ".wad", true);
DArgs *files1 = Args.GatherFiles (NULL, ".zip", false); DArgs *files1 = Args.GatherFiles (NULL, ".zip", false);
DArgs *files2 = Args.GatherFiles (NULL, ".pk3", false); DArgs *files2 = Args.GatherFiles (NULL, ".pk3", false);
if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0) DArgs *files3 = Args.GatherFiles (NULL, ".txt", false);
if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0 || files3->NumArgs() > 0)
{ {
// Check for -file in shareware // Check for -file in shareware
if (gameinfo.flags & GI_SHAREWARE) if (gameinfo.flags & GI_SHAREWARE)
@ -2151,10 +2152,15 @@ void D_DoomMain (void)
{ {
D_AddWildFile (files2->GetArg (i)); D_AddWildFile (files2->GetArg (i));
} }
for (int i = 0; i < files3->NumArgs(); i++)
{
D_AddWildFile (files3->GetArg (i));
}
} }
delete files; delete files;
delete files1; delete files1;
delete files2; delete files2;
delete files3;
Printf ("W_Init: Init WADfiles.\n"); Printf ("W_Init: Init WADfiles.\n");
Wads.InitMultipleFiles (&wadfiles); Wads.InitMultipleFiles (&wadfiles);

View file

@ -48,7 +48,7 @@
FDecalLib DecalLibrary; FDecalLib DecalLibrary;
static fixed_t ReadScale (); static fixed_t ReadScale (FScanner &sc);
static TArray<BYTE> DecalTranslations; static TArray<BYTE> DecalTranslations;
// A decal group holds multiple decals and returns one randomly // A decal group holds multiple decals and returns one randomly
@ -358,9 +358,8 @@ void FDecalLib::ReadAllDecals ()
while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1) while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "DECALDEF"); FScanner sc(lump, "DECALDEF");
ReadDecals (); ReadDecals (sc);
SC_Close ();
} }
// Supporting code to allow specifying decals directly in the DECORATE lump // Supporting code to allow specifying decals directly in the DECORATE lump
for (i = 0; i < PClass::m_RuntimeActors.Size(); i++) for (i = 0; i < PClass::m_RuntimeActors.Size(); i++)
@ -375,79 +374,79 @@ void FDecalLib::ReadAllDecals ()
} }
} }
void FDecalLib::ReadDecals () void FDecalLib::ReadDecals(FScanner &sc)
{ {
while (SC_GetString ()) while (sc.GetString())
{ {
if (SC_Compare ("decal")) if (sc.Compare("decal"))
{ {
ParseDecal (); ParseDecal(sc);
} }
else if (SC_Compare ("decalgroup")) else if (sc.Compare("decalgroup"))
{ {
ParseDecalGroup (); ParseDecalGroup(sc);
} }
else if (SC_Compare ("generator")) else if (sc.Compare("generator"))
{ {
ParseGenerator (); ParseGenerator(sc);
} }
else if (SC_Compare ("fader")) else if (sc.Compare("fader"))
{ {
ParseFader (); ParseFader(sc);
} }
else if (SC_Compare ("stretcher")) else if (sc.Compare("stretcher"))
{ {
ParseStretcher (); ParseStretcher(sc);
} }
else if (SC_Compare ("slider")) else if (sc.Compare("slider"))
{ {
ParseSlider (); ParseSlider(sc);
} }
else if (SC_Compare ("combiner")) else if (sc.Compare("combiner"))
{ {
ParseCombiner (); ParseCombiner(sc);
} }
else if (SC_Compare ("colorchanger")) else if (sc.Compare("colorchanger"))
{ {
ParseColorchanger (); ParseColorchanger(sc);
} }
else else
{ {
SC_ScriptError (NULL); sc.MustGetStringName(NULL);
} }
} }
} }
BYTE FDecalLib::GetDecalID () BYTE FDecalLib::GetDecalID (FScanner &sc)
{ {
SC_MustGetString (); sc.MustGetString ();
if (!IsNum (sc_String)) if (!IsNum (sc.String))
{ {
SC_UnGet (); sc.UnGet ();
return 0; return 0;
} }
else else
{ {
unsigned long num = strtoul (sc_String, NULL, 10); unsigned long num = strtoul (sc.String, NULL, 10);
if (num < 1 || num > 255) if (num < 1 || num > 255)
{ {
SC_ScriptError ("Decal ID must be between 1 and 255"); sc.MustGetStringName ("Decal ID must be between 1 and 255");
} }
return (BYTE)num; return (BYTE)num;
} }
} }
void FDecalLib::ParseDecal () void FDecalLib::ParseDecal (FScanner &sc)
{ {
char decalName[64]; FString decalName;
BYTE decalNum; BYTE decalNum;
FDecalTemplate newdecal; FDecalTemplate newdecal;
int code, picnum; int code, picnum;
SC_MustGetString (); sc.MustGetString ();
strcpy (decalName, sc_String); decalName = sc.String;
decalNum = GetDecalID (); decalNum = GetDecalID (sc);
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
memset (&newdecal, 0, sizeof(newdecal)); memset (&newdecal, 0, sizeof(newdecal));
newdecal.PicNum = 0xffff; newdecal.PicNum = 0xffff;
@ -458,26 +457,26 @@ void FDecalLib::ParseDecal ()
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
AddDecal (decalName, decalNum, newdecal); AddDecal (decalName, decalNum, newdecal);
break; break;
} }
switch ((code = SC_MustMatchString (DecalKeywords))) switch ((code = sc.MustMatchString (DecalKeywords)))
{ {
case DECAL_XSCALE: case DECAL_XSCALE:
newdecal.ScaleX = ReadScale (); newdecal.ScaleX = ReadScale (sc);
break; break;
case DECAL_YSCALE: case DECAL_YSCALE:
newdecal.ScaleY = ReadScale (); newdecal.ScaleY = ReadScale (sc);
break; break;
case DECAL_PIC: case DECAL_PIC:
SC_MustGetString (); sc.MustGetString ();
picnum = TexMan.CheckForTexture (sc_String, FTexture::TEX_Any); picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Any);
if (picnum < 0 && (picnum = Wads.CheckNumForName (sc_String, ns_graphics)) >= 0) if (picnum < 0 && (picnum = Wads.CheckNumForName (sc.String, ns_graphics)) >= 0)
{ {
picnum = TexMan.CreateTexture (picnum, FTexture::TEX_Decal); picnum = TexMan.CreateTexture (picnum, FTexture::TEX_Decal);
} }
@ -489,14 +488,14 @@ void FDecalLib::ParseDecal ()
break; break;
case DECAL_ADD: case DECAL_ADD:
SC_MustGetFloat (); sc.MustGetFloat ();
newdecal.Alpha = (WORD)(32768.f * sc_Float); newdecal.Alpha = (WORD)(32768.f * sc.Float);
newdecal.RenderStyle = STYLE_Add; newdecal.RenderStyle = STYLE_Add;
break; break;
case DECAL_TRANSLUCENT: case DECAL_TRANSLUCENT:
SC_MustGetFloat (); sc.MustGetFloat ();
newdecal.Alpha = (WORD)(32768.f * sc_Float); newdecal.Alpha = (WORD)(32768.f * sc.Float);
newdecal.RenderStyle = STYLE_Translucent; newdecal.RenderStyle = STYLE_Translucent;
break; break;
@ -525,9 +524,9 @@ void FDecalLib::ParseDecal ()
break; break;
case DECAL_SHADE: case DECAL_SHADE:
SC_MustGetString (); sc.MustGetString ();
newdecal.RenderStyle = STYLE_Shaded; newdecal.RenderStyle = STYLE_Shaded;
newdecal.ShadeColor = V_GetColor (NULL, sc_String); newdecal.ShadeColor = V_GetColor (NULL, sc.String);
newdecal.ShadeColor |= newdecal.ShadeColor |=
ColorMatcher.Pick (RPART(newdecal.ShadeColor), ColorMatcher.Pick (RPART(newdecal.ShadeColor),
GPART(newdecal.ShadeColor), BPART(newdecal.ShadeColor)) << 24; GPART(newdecal.ShadeColor), BPART(newdecal.ShadeColor)) << 24;
@ -536,42 +535,42 @@ void FDecalLib::ParseDecal ()
case DECAL_COLORS: case DECAL_COLORS:
DWORD startcolor, endcolor; DWORD startcolor, endcolor;
SC_MustGetString (); startcolor = V_GetColor (NULL, sc_String); sc.MustGetString (); startcolor = V_GetColor (NULL, sc.String);
SC_MustGetString (); endcolor = V_GetColor (NULL, sc_String); sc.MustGetString (); endcolor = V_GetColor (NULL, sc.String);
newdecal.Translation = GenerateTranslation (startcolor, endcolor)->Index; newdecal.Translation = GenerateTranslation (startcolor, endcolor)->Index;
break; break;
case DECAL_ANIMATOR: case DECAL_ANIMATOR:
SC_MustGetString (); sc.MustGetString ();
newdecal.Animator = FindAnimator (sc_String); newdecal.Animator = FindAnimator (sc.String);
break; break;
case DECAL_LOWERDECAL: case DECAL_LOWERDECAL:
SC_MustGetString (); sc.MustGetString ();
newdecal.LowerDecal = GetDecalByName (sc_String); newdecal.LowerDecal = GetDecalByName (sc.String);
break; break;
} }
} }
} }
void FDecalLib::ParseDecalGroup () void FDecalLib::ParseDecalGroup (FScanner &sc)
{ {
char groupName[64]; FString groupName;
BYTE decalNum; BYTE decalNum;
FDecalBase *targetDecal; FDecalBase *targetDecal;
FDecalGroup *group; FDecalGroup *group;
SC_MustGetString (); sc.MustGetString ();
strcpy (groupName, sc_String); groupName = sc.String;
decalNum = GetDecalID (); decalNum = GetDecalID (sc);
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
group = new FDecalGroup; group = new FDecalGroup;
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
group->Name = groupName; group->Name = groupName;
group->SpawnID = decalNum; group->SpawnID = decalNum;
@ -579,44 +578,44 @@ void FDecalLib::ParseDecalGroup ()
break; break;
} }
targetDecal = ScanTreeForName (sc_String, Root); targetDecal = ScanTreeForName (sc.String, Root);
if (targetDecal == NULL) if (targetDecal == NULL)
{ {
SC_ScriptError ("%s has not been defined", sc_String); sc.ScriptError ("%s has not been defined", sc.String);
} }
SC_MustGetNumber (); sc.MustGetNumber ();
group->AddDecal (targetDecal, sc_Number); group->AddDecal (targetDecal, sc.Number);
} }
} }
void FDecalLib::ParseGenerator () void FDecalLib::ParseGenerator (FScanner &sc)
{ {
const PClass *type; const PClass *type;
FDecalBase *decal; FDecalBase *decal;
AActor *actor; AActor *actor;
// Get name of generator (actor) // Get name of generator (actor)
SC_MustGetString (); sc.MustGetString ();
type = PClass::FindClass (sc_String); type = PClass::FindClass (sc.String);
if (type == NULL || type->ActorInfo == NULL) if (type == NULL || type->ActorInfo == NULL)
{ {
SC_ScriptError ("%s is not an actor.", sc_String); sc.ScriptError ("%s is not an actor.", sc.String);
} }
actor = (AActor *)type->Defaults; actor = (AActor *)type->Defaults;
// Get name of generated decal // Get name of generated decal
SC_MustGetString (); sc.MustGetString ();
if (stricmp (sc_String, "None") == 0) if (stricmp (sc.String, "None") == 0)
{ {
decal = NULL; decal = NULL;
} }
else else
{ {
decal = ScanTreeForName (sc_String, Root); decal = ScanTreeForName (sc.String, Root);
if (decal == NULL) if (decal == NULL)
{ {
SC_ScriptError ("%s has not been defined.", sc_String); sc.ScriptError ("%s has not been defined.", sc.String);
} }
} }
@ -624,19 +623,19 @@ void FDecalLib::ParseGenerator ()
decal->Users.Push (type); decal->Users.Push (type);
} }
void FDecalLib::ParseFader () void FDecalLib::ParseFader (FScanner &sc)
{ {
char faderName[64]; FString faderName;
int startTime = 0, decayTime = 0; int startTime = 0, decayTime = 0;
SC_MustGetString (); sc.MustGetString ();
strcpy (faderName, sc_String); faderName = sc.String;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
FDecalFaderAnim *fader = new FDecalFaderAnim (faderName); FDecalFaderAnim *fader = new FDecalFaderAnim (faderName);
fader->DecayStart = startTime; fader->DecayStart = startTime;
@ -644,37 +643,37 @@ void FDecalLib::ParseFader ()
Animators.Push (fader); Animators.Push (fader);
break; break;
} }
else if (SC_Compare ("DecayStart")) else if (sc.Compare ("DecayStart"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
startTime = (int)(sc_Float * TICRATE); startTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("DecayTime")) else if (sc.Compare ("DecayTime"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
decayTime = (int)(sc_Float * TICRATE); decayTime = (int)(sc.Float * TICRATE);
} }
else else
{ {
SC_ScriptError ("Unknown fader parameter '%s'", sc_String); sc.ScriptError ("Unknown fader parameter '%s'", sc.String);
} }
} }
} }
void FDecalLib::ParseStretcher () void FDecalLib::ParseStretcher (FScanner &sc)
{ {
char stretcherName[64]; FString stretcherName;
fixed_t goalX = -1, goalY = -1; fixed_t goalX = -1, goalY = -1;
int startTime = 0, takeTime = 0; int startTime = 0, takeTime = 0;
SC_MustGetString (); sc.MustGetString ();
strcpy (stretcherName, sc_String); stretcherName = sc.String;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
if (goalX >= 0 || goalY >= 0) if (goalX >= 0 || goalY >= 0)
{ {
@ -687,45 +686,45 @@ void FDecalLib::ParseStretcher ()
} }
break; break;
} }
else if (SC_Compare ("StretchStart")) else if (sc.Compare ("StretchStart"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
startTime = (int)(sc_Float * TICRATE); startTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("StretchTime")) else if (sc.Compare ("StretchTime"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
takeTime = (int)(sc_Float * TICRATE); takeTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("GoalX")) else if (sc.Compare ("GoalX"))
{ {
goalX = ReadScale (); goalX = ReadScale (sc);
} }
else if (SC_Compare ("GoalY")) else if (sc.Compare ("GoalY"))
{ {
goalY = ReadScale (); goalY = ReadScale (sc);
} }
else else
{ {
SC_ScriptError ("Unknown stretcher parameter '%s'", sc_String); sc.ScriptError ("Unknown stretcher parameter '%s'", sc.String);
} }
} }
} }
void FDecalLib::ParseSlider () void FDecalLib::ParseSlider (FScanner &sc)
{ {
char sliderName[64]; FString sliderName;
fixed_t distX = 0, distY = 0; fixed_t distX = 0, distY = 0;
int startTime = 0, takeTime = 0; int startTime = 0, takeTime = 0;
SC_MustGetString (); sc.MustGetString ();
strcpy (sliderName, sc_String); sliderName = sc.String;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
if ((/*distX |*/ distY) != 0) if ((/*distX |*/ distY) != 0)
{ {
@ -738,48 +737,48 @@ void FDecalLib::ParseSlider ()
} }
break; break;
} }
else if (SC_Compare ("SlideStart")) else if (sc.Compare ("SlideStart"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
startTime = (int)(sc_Float * TICRATE); startTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("SlideTime")) else if (sc.Compare ("SlideTime"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
takeTime = (int)(sc_Float * TICRATE); takeTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("DistX")) else if (sc.Compare ("DistX"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
distX = (fixed_t)(sc_Float * FRACUNIT); distX = (fixed_t)(sc.Float * FRACUNIT);
Printf ("DistX in slider decal %s is unsupported\n", sliderName); Printf ("DistX in slider decal %s is unsupported\n", sliderName.GetChars());
} }
else if (SC_Compare ("DistY")) else if (sc.Compare ("DistY"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
distY = (fixed_t)(sc_Float * FRACUNIT); distY = (fixed_t)(sc.Float * FRACUNIT);
} }
else else
{ {
SC_ScriptError ("Unknown slider parameter '%s'", sc_String); sc.ScriptError ("Unknown slider parameter '%s'", sc.String);
} }
} }
} }
void FDecalLib::ParseColorchanger () void FDecalLib::ParseColorchanger (FScanner &sc)
{ {
char faderName[64]; FString faderName;
int startTime = 0, decayTime = 0; int startTime = 0, decayTime = 0;
PalEntry goal = 0; PalEntry goal = 0;
SC_MustGetString (); sc.MustGetString ();
strcpy (faderName, sc_String); faderName = sc.String;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
for (;;) for (;;)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
FDecalColorerAnim *fader = new FDecalColorerAnim (faderName); FDecalColorerAnim *fader = new FDecalColorerAnim (faderName);
fader->DecayStart = startTime; fader->DecayStart = startTime;
@ -788,46 +787,46 @@ void FDecalLib::ParseColorchanger ()
Animators.Push (fader); Animators.Push (fader);
break; break;
} }
else if (SC_Compare ("FadeStart")) else if (sc.Compare ("FadeStart"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
startTime = (int)(sc_Float * TICRATE); startTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("FadeTime")) else if (sc.Compare ("FadeTime"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
decayTime = (int)(sc_Float * TICRATE); decayTime = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("Color")) else if (sc.Compare ("Color"))
{ {
SC_MustGetString (); sc.MustGetString ();
goal = V_GetColor (NULL, sc_String); goal = V_GetColor (NULL, sc.String);
} }
else else
{ {
SC_ScriptError ("Unknown color changer parameter '%s'", sc_String); sc.ScriptError ("Unknown color changer parameter '%s'", sc.String);
} }
} }
} }
void FDecalLib::ParseCombiner () void FDecalLib::ParseCombiner (FScanner &sc)
{ {
char combinerName[64]; FString combinerName;
size_t first = FDecalCombinerAnim::AnimatorList.Size (); size_t first = FDecalCombinerAnim::AnimatorList.Size ();
SC_MustGetString (); sc.MustGetString ();
strcpy (combinerName, sc_String); combinerName = sc.String;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
SC_MustGetString (); sc.MustGetString ();
while (!SC_Compare ("}")) while (!sc.Compare ("}"))
{ {
FDecalAnimator *anim = FindAnimator (sc_String); FDecalAnimator *anim = FindAnimator (sc.String);
if (anim == NULL) if (anim == NULL)
{ {
SC_ScriptError ("Undefined animator %s", sc_String); sc.ScriptError ("Undefined animator %s", sc.String);
} }
FDecalCombinerAnim::AnimatorList.Push (anim); FDecalCombinerAnim::AnimatorList.Push (anim);
SC_MustGetString (); sc.MustGetString ();
} }
size_t last = FDecalCombinerAnim::AnimatorList.Size (); size_t last = FDecalCombinerAnim::AnimatorList.Size ();
@ -1022,7 +1021,7 @@ FDecalBase::~FDecalBase ()
void FDecalTemplate::ApplyToDecal (DBaseDecal *decal, side_t *wall) const void FDecalTemplate::ApplyToDecal (DBaseDecal *decal, side_t *wall) const
{ {
if (RenderStyle == STYLE_Shaded) if (RenderStyle.Flags & STYLEF_ColorIsFixed)
{ {
decal->SetShade (ShadeColor); decal->SetShade (ShadeColor);
} }
@ -1165,11 +1164,6 @@ void DDecalFader::Tick ()
int distanceToEnd = TimeToEndDecay - level.maptime; int distanceToEnd = TimeToEndDecay - level.maptime;
int fadeDistance = TimeToEndDecay - TimeToStartDecay; int fadeDistance = TimeToEndDecay - TimeToStartDecay;
TheDecal->Alpha = Scale (StartTrans, distanceToEnd, fadeDistance); TheDecal->Alpha = Scale (StartTrans, distanceToEnd, fadeDistance);
if (TheDecal->RenderStyle < STYLE_Translucent)
{
TheDecal->RenderStyle = STYLE_Translucent;
}
} }
} }
@ -1364,7 +1358,7 @@ void DDecalColorer::Serialize (FArchive &arc)
void DDecalColorer::Tick () void DDecalColorer::Tick ()
{ {
if (TheDecal == NULL || TheDecal->RenderStyle != STYLE_Shaded) if (TheDecal == NULL || !(TheDecal->RenderStyle.Flags & STYLEF_ColorIsFixed))
{ {
Destroy (); Destroy ();
} }
@ -1413,8 +1407,8 @@ DThinker *FDecalColorerAnim::CreateThinker (DBaseDecal *actor, side_t *wall) con
return Colorer; return Colorer;
} }
static fixed_t ReadScale () static fixed_t ReadScale (FScanner &sc)
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
return fixed_t(clamp (sc_Float * FRACUNIT, 256.0, 256.0*FRACUNIT)); return fixed_t(clamp (sc.Float * FRACUNIT, 256.0, 256.0*FRACUNIT));
} }

View file

@ -39,8 +39,9 @@
#include "doomtype.h" #include "doomtype.h"
#include "tarray.h" #include "tarray.h"
#include "name.h" #include "name.h"
#include "actor.h"
class AActor; class FScanner;
class FDecalTemplate; class FDecalTemplate;
struct FDecalAnimator; struct FDecalAnimator;
struct PClass; struct PClass;
@ -77,7 +78,7 @@ public:
fixed_t ScaleX, ScaleY; fixed_t ScaleX, ScaleY;
DWORD ShadeColor; DWORD ShadeColor;
DWORD Translation; DWORD Translation;
BYTE RenderStyle; FRenderStyle RenderStyle;
WORD PicNum; WORD PicNum;
WORD RenderFlags; WORD RenderFlags;
WORD Alpha; // same as (actor->alpha >> 1) WORD Alpha; // same as (actor->alpha >> 1)
@ -94,7 +95,7 @@ public:
~FDecalLib (); ~FDecalLib ();
void Clear (); void Clear ();
void ReadDecals (); // SC_Open() should have just been called void ReadDecals (FScanner &sc);
void ReadAllDecals (); void ReadAllDecals ();
const FDecalTemplate *GetDecalByNum (BYTE num) const; const FDecalTemplate *GetDecalByNum (BYTE num) const;
@ -112,15 +113,15 @@ private:
void AddDecal (FDecalBase *decal); void AddDecal (FDecalBase *decal);
FDecalAnimator *FindAnimator (const char *name); FDecalAnimator *FindAnimator (const char *name);
BYTE GetDecalID (); BYTE GetDecalID (FScanner &sc);
void ParseDecal (); void ParseDecal (FScanner &sc);
void ParseDecalGroup (); void ParseDecalGroup (FScanner &sc);
void ParseGenerator (); void ParseGenerator (FScanner &sc);
void ParseFader (); void ParseFader (FScanner &sc);
void ParseStretcher (); void ParseStretcher (FScanner &sc);
void ParseSlider (); void ParseSlider (FScanner &sc);
void ParseCombiner (); void ParseCombiner (FScanner &sc);
void ParseColorchanger (); void ParseColorchanger (FScanner &sc);
FDecalBase *Root; FDecalBase *Root;
FTranslation *Translations; FTranslation *Translations;

View file

@ -180,7 +180,7 @@ struct PalEntry
PalEntry (DWORD argb) { *(DWORD *)this = argb; } PalEntry (DWORD argb) { *(DWORD *)this = argb; }
operator DWORD () const { return *(DWORD *)this; } operator DWORD () const { return *(DWORD *)this; }
PalEntry &operator= (DWORD other) { *(DWORD *)this = other; return *this; } PalEntry &operator= (DWORD other) { *(DWORD *)this = other; return *this; }
PalEntry InverseColor() const { PalEntry nc; nc.a = a; nc.r = 255 - r; nc.g = 255 - g; nc.b = 255 - b; return nc; }
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
PalEntry (BYTE ir, BYTE ig, BYTE ib) : a(0), r(ir), g(ig), b(ib) {} PalEntry (BYTE ir, BYTE ig, BYTE ib) : a(0), r(ir), g(ig), b(ib) {}
PalEntry (BYTE ia, BYTE ir, BYTE ig, BYTE ib) : a(ia), r(ir), g(ig), b(ib) {} PalEntry (BYTE ia, BYTE ir, BYTE ig, BYTE ib) : a(ia), r(ir), g(ig), b(ib) {}

View file

@ -98,13 +98,13 @@ EXTERN_CVAR (Int, disableautosave)
static int FindEndSequence (int type, const char *picname); static int FindEndSequence (int type, const char *picname);
static void SetEndSequence (char *nextmap, int type); static void SetEndSequence (char *nextmap, int type);
static void InitPlayerClasses (); static void InitPlayerClasses ();
static void ParseEpisodeInfo (); static void ParseEpisodeInfo (FScanner &sc);
static void G_DoParseMapInfo (int lump); static void G_DoParseMapInfo (int lump);
static void SetLevelNum (level_info_t *info, int num); static void SetLevelNum (level_info_t *info, int num);
static void ClearEpisodes (); static void ClearEpisodes ();
static void ClearLevelInfoStrings (level_info_t *linfo); static void ClearLevelInfoStrings (level_info_t *linfo);
static void ClearClusterInfoStrings (cluster_info_t *cinfo); static void ClearClusterInfoStrings (cluster_info_t *cinfo);
static void ParseSkill (); static void ParseSkill (FScanner &sc);
static void G_VerifySkill(); static void G_VerifySkill();
static FRandom pr_classchoice ("RandomPlayerClassChoice"); static FRandom pr_classchoice ("RandomPlayerClassChoice");
@ -483,7 +483,8 @@ MapInfoHandler ClusterHandlers[] =
{ MITYPE_STRING, cioffset(clustername), 0 }, { MITYPE_STRING, cioffset(clustername), 0 },
}; };
static void ParseMapInfoLower (MapInfoHandler *handlers, static void ParseMapInfoLower (FScanner &sc,
MapInfoHandler *handlers,
const char *strings[], const char *strings[],
level_info_t *levelinfo, level_info_t *levelinfo,
cluster_info_t *clusterinfo, cluster_info_t *clusterinfo,
@ -605,28 +606,29 @@ static void G_DoParseMapInfo (int lump)
int clusterindex; int clusterindex;
QWORD levelflags; QWORD levelflags;
FScanner sc(lump, Wads.GetLumpFullName(lump));
SetLevelDefaults (&defaultinfo); SetLevelDefaults (&defaultinfo);
SC_OpenLumpNum (lump, Wads.GetLumpFullName(lump));
HexenHack = false; HexenHack = false;
while (SC_GetString ()) while (sc.GetString ())
{ {
switch (SC_MustMatchString (MapInfoTopLevel)) switch (sc.MustMatchString (MapInfoTopLevel))
{ {
case MITL_DEFAULTMAP: case MITL_DEFAULTMAP:
if (defaultinfo.music != NULL) delete [] defaultinfo.music; if (defaultinfo.music != NULL) delete [] defaultinfo.music;
if (defaultinfo.intermusic != NULL) delete [] defaultinfo.intermusic; if (defaultinfo.intermusic != NULL) delete [] defaultinfo.intermusic;
SetLevelDefaults (&defaultinfo); SetLevelDefaults (&defaultinfo);
ParseMapInfoLower (MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags); ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
break; break;
case MITL_MAP: // map <MAPNAME> <Nice Name> case MITL_MAP: // map <MAPNAME> <Nice Name>
levelflags = defaultinfo.flags; levelflags = defaultinfo.flags;
SC_MustGetString (); sc.MustGetString ();
if (IsNum (sc_String)) if (IsNum (sc.String))
{ // MAPNAME is a number; assume a Hexen wad { // MAPNAME is a number; assume a Hexen wad
int map = atoi (sc_String); int map = atoi (sc.String);
sprintf (sc_String, "MAP%02d", map); sprintf (sc.String, "MAP%02d", map);
HexenHack = true; HexenHack = true;
// Hexen levels are automatically nointermission, // Hexen levels are automatically nointermission,
// no auto sound sequences, falling damage, // no auto sound sequences, falling damage,
@ -639,7 +641,7 @@ static void G_DoParseMapInfo (int lump)
| LEVEL_MISSILESACTIVATEIMPACT | LEVEL_MISSILESACTIVATEIMPACT
| LEVEL_INFINITE_FLIGHT; | LEVEL_INFINITE_FLIGHT;
} }
levelindex = FindWadLevelInfo (sc_String); levelindex = FindWadLevelInfo (sc.String);
if (levelindex == -1) if (levelindex == -1)
{ {
levelindex = wadlevelinfos.Reserve(1); levelindex = wadlevelinfos.Reserve(1);
@ -662,17 +664,17 @@ static void G_DoParseMapInfo (int lump)
{ {
levelinfo->WallHorizLight = levelinfo->WallVertLight = 0; levelinfo->WallHorizLight = levelinfo->WallVertLight = 0;
} }
uppercopy (levelinfo->mapname, sc_String); uppercopy (levelinfo->mapname, sc.String);
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("lookup")) if (sc.Compare ("lookup"))
{ {
SC_MustGetString (); sc.MustGetString ();
ReplaceString (&levelinfo->level_name, sc_String); ReplaceString (&levelinfo->level_name, sc.String);
levelflags |= LEVEL_LOOKUPLEVELNAME; levelflags |= LEVEL_LOOKUPLEVELNAME;
} }
else else
{ {
ReplaceString (&levelinfo->level_name, sc_String); ReplaceString (&levelinfo->level_name, sc.String);
} }
// Set up levelnum now so that you can use Teleport_NewMap specials // Set up levelnum now so that you can use Teleport_NewMap specials
// to teleport to maps with standard names without needing a levelnum. // to teleport to maps with standard names without needing a levelnum.
@ -692,7 +694,7 @@ static void G_DoParseMapInfo (int lump)
int mapnum = levelinfo->mapname[3] - '0'; int mapnum = levelinfo->mapname[3] - '0';
levelinfo->levelnum = epinum*10 + mapnum; levelinfo->levelnum = epinum*10 + mapnum;
} }
ParseMapInfoLower (MapHandlers, MapInfoMapLevel, levelinfo, NULL, levelflags); ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, levelinfo, NULL, levelflags);
// When the second sky is -NOFLAT-, make it a copy of the first sky // When the second sky is -NOFLAT-, make it a copy of the first sky
if (strcmp (levelinfo->skypic2, "-NOFLAT-") == 0) if (strcmp (levelinfo->skypic2, "-NOFLAT-") == 0)
{ {
@ -713,8 +715,8 @@ static void G_DoParseMapInfo (int lump)
break; break;
case MITL_CLUSTERDEF: // clusterdef <clusternum> case MITL_CLUSTERDEF: // clusterdef <clusternum>
SC_MustGetNumber (); sc.MustGetNumber ();
clusterindex = FindWadClusterInfo (sc_Number); clusterindex = FindWadClusterInfo (sc.Number);
if (clusterindex == -1) if (clusterindex == -1)
{ {
clusterindex = wadclusterinfos.Reserve(1); clusterindex = wadclusterinfos.Reserve(1);
@ -741,20 +743,20 @@ static void G_DoParseMapInfo (int lump)
} }
} }
memset (clusterinfo, 0, sizeof(cluster_info_t)); memset (clusterinfo, 0, sizeof(cluster_info_t));
clusterinfo->cluster = sc_Number; clusterinfo->cluster = sc.Number;
ParseMapInfoLower (ClusterHandlers, MapInfoClusterLevel, NULL, clusterinfo, 0); ParseMapInfoLower (sc, ClusterHandlers, MapInfoClusterLevel, NULL, clusterinfo, 0);
break; break;
case MITL_EPISODE: case MITL_EPISODE:
ParseEpisodeInfo (); ParseEpisodeInfo(sc);
break; break;
case MITL_CLEAREPISODES: case MITL_CLEAREPISODES:
ClearEpisodes (); ClearEpisodes();
break; break;
case MITL_SKILL: case MITL_SKILL:
ParseSkill(); ParseSkill(sc);
break; break;
case MITL_CLEARSKILLS: case MITL_CLEARSKILLS:
@ -763,7 +765,6 @@ static void G_DoParseMapInfo (int lump)
} }
} }
SC_Close ();
if (defaultinfo.music != NULL) if (defaultinfo.music != NULL)
{ {
delete [] defaultinfo.music; delete [] defaultinfo.music;
@ -833,7 +834,8 @@ static void ClearEpisodes()
EpiDef.numitems = 0; EpiDef.numitems = 0;
} }
static void ParseMapInfoLower (MapInfoHandler *handlers, static void ParseMapInfoLower (FScanner &sc,
MapInfoHandler *handlers,
const char *strings[], const char *strings[],
level_info_t *levelinfo, level_info_t *levelinfo,
cluster_info_t *clusterinfo, cluster_info_t *clusterinfo,
@ -845,52 +847,52 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
info = levelinfo ? (BYTE *)levelinfo : (BYTE *)clusterinfo; info = levelinfo ? (BYTE *)levelinfo : (BYTE *)clusterinfo;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_MatchString (MapInfoTopLevel) != -1) if (sc.MatchString (MapInfoTopLevel) != -1)
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
entry = SC_MustMatchString (strings); entry = sc.MustMatchString (strings);
handler = handlers + entry; handler = handlers + entry;
switch (handler->type) switch (handler->type)
{ {
case MITYPE_EATNEXT: case MITYPE_EATNEXT:
SC_MustGetString (); sc.MustGetString ();
break; break;
case MITYPE_IGNORE: case MITYPE_IGNORE:
break; break;
case MITYPE_INT: case MITYPE_INT:
SC_MustGetNumber (); sc.MustGetNumber ();
*((int *)(info + handler->data1)) = sc_Number; *((int *)(info + handler->data1)) = sc.Number;
break; break;
case MITYPE_FLOAT: case MITYPE_FLOAT:
SC_MustGetFloat (); sc.MustGetFloat ();
*((float *)(info + handler->data1)) = sc_Float; *((float *)(info + handler->data1)) = sc.Float;
break; break;
case MITYPE_HEX: case MITYPE_HEX:
SC_MustGetString (); sc.MustGetString ();
*((int *)(info + handler->data1)) = strtoul (sc_String, NULL, 16); *((int *)(info + handler->data1)) = strtoul (sc.String, NULL, 16);
break; break;
case MITYPE_COLOR: case MITYPE_COLOR:
SC_MustGetString (); sc.MustGetString ();
*((DWORD *)(info + handler->data1)) = V_GetColor (NULL, sc_String); *((DWORD *)(info + handler->data1)) = V_GetColor (NULL, sc.String);
break; break;
case MITYPE_REDIRECT: case MITYPE_REDIRECT:
SC_MustGetString (); sc.MustGetString ();
levelinfo->RedirectType = sc_String; levelinfo->RedirectType = sc.String;
/* /*
if (levelinfo->RedirectType == NULL || if (levelinfo->RedirectType == NULL ||
!(levelinfo->RedirectType->IsDescendantOf (RUNTIME_CLASS(AInventory)))) !(levelinfo->RedirectType->IsDescendantOf (RUNTIME_CLASS(AInventory))))
{ {
SC_ScriptError ("%s is not an inventory item", sc_String); SC_ScriptError ("%s is not an inventory item", sc.String);
} }
*/ */
// Intentional fall-through // Intentional fall-through
@ -899,24 +901,24 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
EndSequence newSeq; EndSequence newSeq;
bool useseq = false; bool useseq = false;
SC_MustGetString (); sc.MustGetString ();
if (IsNum (sc_String)) if (IsNum (sc.String))
{ {
int map = atoi (sc_String); int map = atoi (sc.String);
if (HexenHack) if (HexenHack)
{ {
sprintf (sc_String, "&wt@%02d", map); sprintf (sc.String, "&wt@%02d", map);
} }
else else
{ {
sprintf (sc_String, "MAP%02d", map); sprintf (sc.String, "MAP%02d", map);
} }
} }
if (strnicmp (sc_String, "EndGame", 7) == 0) if (strnicmp (sc.String, "EndGame", 7) == 0)
{ {
int type; int type;
switch (sc_String[7]) switch (sc.String[7])
{ {
case '1': type = END_Pic1; break; case '1': type = END_Pic1; break;
case '2': type = END_Pic2; break; case '2': type = END_Pic2; break;
@ -929,47 +931,47 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
newSeq.EndType = type; newSeq.EndType = type;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endpic")) else if (sc.Compare ("endpic"))
{ {
SC_MustGetString (); sc.MustGetString ();
newSeq.EndType = END_Pic; newSeq.EndType = END_Pic;
strncpy (newSeq.PicName, sc_String, 8); strncpy (newSeq.PicName, sc.String, 8);
newSeq.PicName[8] = 0; newSeq.PicName[8] = 0;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endbunny")) else if (sc.Compare ("endbunny"))
{ {
newSeq.EndType = END_Bunny; newSeq.EndType = END_Bunny;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endcast")) else if (sc.Compare ("endcast"))
{ {
newSeq.EndType = END_Cast; newSeq.EndType = END_Cast;
useseq = true; useseq = true;
} }
else if (SC_Compare ("enddemon")) else if (sc.Compare ("enddemon"))
{ {
newSeq.EndType = END_Demon; newSeq.EndType = END_Demon;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endchess")) else if (sc.Compare ("endchess"))
{ {
newSeq.EndType = END_Chess; newSeq.EndType = END_Chess;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endunderwater")) else if (sc.Compare ("endunderwater"))
{ {
newSeq.EndType = END_Underwater; newSeq.EndType = END_Underwater;
useseq = true; useseq = true;
} }
else if (SC_Compare ("endbuystrife")) else if (sc.Compare ("endbuystrife"))
{ {
newSeq.EndType = END_BuyStrife; newSeq.EndType = END_BuyStrife;
useseq = true; useseq = true;
} }
else else
{ {
strncpy ((char *)(info + handler->data1), sc_String, 8); strncpy ((char *)(info + handler->data1), sc.String, 8);
} }
if (useseq) if (useseq)
{ {
@ -985,22 +987,22 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
} }
case MITYPE_LUMPNAME: case MITYPE_LUMPNAME:
SC_MustGetString (); sc.MustGetString ();
uppercopy ((char *)(info + handler->data1), sc_String); uppercopy ((char *)(info + handler->data1), sc.String);
flags |= handler->data2; flags |= handler->data2;
break; break;
case MITYPE_SKY: case MITYPE_SKY:
SC_MustGetString (); // get texture name; sc.MustGetString (); // get texture name;
uppercopy ((char *)(info + handler->data1), sc_String); uppercopy ((char *)(info + handler->data1), sc.String);
SC_MustGetFloat (); // get scroll speed sc.MustGetFloat (); // get scroll speed
if (HexenHack) if (HexenHack)
{ {
sc_Float /= 256; sc.Float /= 256;
} }
// Sky scroll speed is specified as pixels per tic, but we // Sky scroll speed is specified as pixels per tic, but we
// want pixels per millisecond. // want pixels per millisecond.
*((float *)(info + handler->data2)) = sc_Float * 35 / 1000; *((float *)(info + handler->data2)) = sc.Float * 35 / 1000;
break; break;
case MITYPE_SETFLAG: case MITYPE_SETFLAG:
@ -1018,18 +1020,18 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
break; break;
case MITYPE_CLUSTER: case MITYPE_CLUSTER:
SC_MustGetNumber (); sc.MustGetNumber ();
*((int *)(info + handler->data1)) = sc_Number; *((int *)(info + handler->data1)) = sc.Number;
// If this cluster hasn't been defined yet, add it. This is especially needed // If this cluster hasn't been defined yet, add it. This is especially needed
// for Hexen, because it doesn't have clusterdefs. If we don't do this, every // for Hexen, because it doesn't have clusterdefs. If we don't do this, every
// level on Hexen will sometimes be considered as being on the same hub, // level on Hexen will sometimes be considered as being on the same hub,
// depending on the check done. // depending on the check done.
if (FindWadClusterInfo (sc_Number) == -1) if (FindWadClusterInfo (sc.Number) == -1)
{ {
unsigned int clusterindex = wadclusterinfos.Reserve(1); unsigned int clusterindex = wadclusterinfos.Reserve(1);
clusterinfo = &wadclusterinfos[clusterindex]; clusterinfo = &wadclusterinfos[clusterindex];
memset (clusterinfo, 0, sizeof(cluster_info_t)); memset (clusterinfo, 0, sizeof(cluster_info_t));
clusterinfo->cluster = sc_Number; clusterinfo->cluster = sc.Number;
if (gameinfo.gametype == GAME_Hexen) if (gameinfo.gametype == GAME_Hexen)
{ {
clusterinfo->flags |= CLUSTER_HUB; clusterinfo->flags |= CLUSTER_HUB;
@ -1038,36 +1040,36 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
break; break;
case MITYPE_STRING: case MITYPE_STRING:
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("lookup")) if (sc.Compare ("lookup"))
{ {
flags |= handler->data2; flags |= handler->data2;
SC_MustGetString (); sc.MustGetString ();
} }
ReplaceString ((char **)(info + handler->data1), sc_String); ReplaceString ((char **)(info + handler->data1), sc.String);
break; break;
case MITYPE_F1: case MITYPE_F1:
SC_MustGetString (); sc.MustGetString ();
{ {
char *colon = strchr (sc_String, ':'); char *colon = strchr (sc.String, ':');
if (colon) if (colon)
{ {
*colon = 0; *colon = 0;
} }
ReplaceString ((char **)(info + handler->data1), sc_String); ReplaceString ((char **)(info + handler->data1), sc.String);
} }
break; break;
case MITYPE_MUSIC: case MITYPE_MUSIC:
SC_MustGetString (); sc.MustGetString ();
{ {
char *colon = strchr (sc_String, ':'); char *colon = strchr (sc.String, ':');
if (colon) if (colon)
{ {
*colon = 0; *colon = 0;
} }
ReplaceString ((char **)(info + handler->data1), sc_String); ReplaceString ((char **)(info + handler->data1), sc.String);
*((int *)(info + handler->data2)) = colon ? atoi (colon + 1) : 0; *((int *)(info + handler->data2)) = colon ? atoi (colon + 1) : 0;
if (levelinfo != NULL) if (levelinfo != NULL)
{ {
@ -1078,8 +1080,8 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
break; break;
case MITYPE_RELLIGHT: case MITYPE_RELLIGHT:
SC_MustGetNumber (); sc.MustGetNumber ();
*((SBYTE *)(info + handler->data1)) = (SBYTE)clamp (sc_Number / 2, -128, 127); *((SBYTE *)(info + handler->data1)) = (SBYTE)clamp (sc.Number / 2, -128, 127);
break; break;
case MITYPE_CLRBYTES: case MITYPE_CLRBYTES:
@ -1095,29 +1097,29 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
FSpecialAction *sa = new FSpecialAction; FSpecialAction *sa = new FSpecialAction;
sa->Next = *so; sa->Next = *so;
*so = sa; *so = sa;
SC_SetCMode(true); sc.SetCMode(true);
SC_MustGetString(); sc.MustGetString();
sa->Type = FName(sc_String); sa->Type = FName(sc.String);
SC_CheckString(","); sc.CheckString(",");
SC_MustGetString(); sc.MustGetString();
strlwr(sc_String); strlwr(sc.String);
sa->Action = FindLineSpecial(sc_String); sa->Action = FindLineSpecial(sc.String);
int j = 0; int j = 0;
while (j < 5 && SC_CheckString(",")) while (j < 5 && sc.CheckString(","))
{ {
SC_MustGetNumber(); sc.MustGetNumber();
sa->Args[j++] = sc_Number; sa->Args[j++] = sc.Number;
} }
SC_SetCMode(false); sc.SetCMode(false);
} }
break; break;
case MITYPE_COMPATFLAG: case MITYPE_COMPATFLAG:
if (!SC_CheckNumber()) sc_Number = 1; if (!sc.CheckNumber()) sc.Number = 1;
if (levelinfo != NULL) if (levelinfo != NULL)
{ {
if (sc_Number) levelinfo->compatflags |= (DWORD)handler->data1; if (sc.Number) levelinfo->compatflags |= (DWORD)handler->data1;
else levelinfo->compatflags &= ~ (DWORD)handler->data1; else levelinfo->compatflags &= ~ (DWORD)handler->data1;
levelinfo->compatmask |= (DWORD)handler->data1; levelinfo->compatmask |= (DWORD)handler->data1;
} }
@ -1143,7 +1145,7 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
// noskillmenu // noskillmenu
// remove // remove
static void ParseEpisodeInfo () static void ParseEpisodeInfo (FScanner &sc)
{ {
int i; int i;
char map[9]; char map[9];
@ -1155,54 +1157,54 @@ static void ParseEpisodeInfo ()
bool noskill = false; bool noskill = false;
// Get map name // Get map name
SC_MustGetString (); sc.MustGetString ();
uppercopy (map, sc_String); uppercopy (map, sc.String);
map[8] = 0; map[8] = 0;
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("teaser")) if (sc.Compare ("teaser"))
{ {
SC_MustGetString (); sc.MustGetString ();
if (gameinfo.flags & GI_SHAREWARE) if (gameinfo.flags & GI_SHAREWARE)
{ {
uppercopy (map, sc_String); uppercopy (map, sc.String);
} }
SC_MustGetString (); sc.MustGetString ();
} }
do do
{ {
if (SC_Compare ("name")) if (sc.Compare ("name"))
{ {
SC_MustGetString (); sc.MustGetString ();
ReplaceString (&pic, sc_String); ReplaceString (&pic, sc.String);
picisgfx = false; picisgfx = false;
} }
else if (SC_Compare ("picname")) else if (sc.Compare ("picname"))
{ {
SC_MustGetString (); sc.MustGetString ();
ReplaceString (&pic, sc_String); ReplaceString (&pic, sc.String);
picisgfx = true; picisgfx = true;
} }
else if (SC_Compare ("remove")) else if (sc.Compare ("remove"))
{ {
remove = true; remove = true;
} }
else if (SC_Compare ("key")) else if (sc.Compare ("key"))
{ {
SC_MustGetString (); sc.MustGetString ();
key = sc_String[0]; key = sc.String[0];
} }
else if (SC_Compare("noskillmenu")) else if (sc.Compare("noskillmenu"))
{ {
noskill = true; noskill = true;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }
while (SC_GetString ()); while (sc.GetString ());
for (i = 0; i < EpiDef.numitems; ++i) for (i = 0; i < EpiDef.numitems; ++i)
{ {
@ -3122,7 +3124,7 @@ static void InitPlayerClasses ()
} }
static void ParseSkill () static void ParseSkill (FScanner &sc)
{ {
FSkillInfo skill; FSkillInfo skill;
@ -3142,106 +3144,106 @@ static void ParseSkill ()
skill.Shortcut = 0; skill.Shortcut = 0;
skill.TextColor = ""; skill.TextColor = "";
SC_MustGetString(); sc.MustGetString();
skill.Name = sc_String; skill.Name = sc.String;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("ammofactor")) if (sc.Compare ("ammofactor"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
skill.AmmoFactor = FLOAT2FIXED(sc_Float); skill.AmmoFactor = FLOAT2FIXED(sc.Float);
} }
else if (SC_Compare ("doubleammofactor")) else if (sc.Compare ("doubleammofactor"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
skill.DoubleAmmoFactor = FLOAT2FIXED(sc_Float); skill.DoubleAmmoFactor = FLOAT2FIXED(sc.Float);
} }
else if (SC_Compare ("damagefactor")) else if (sc.Compare ("damagefactor"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
skill.DamageFactor = FLOAT2FIXED(sc_Float); skill.DamageFactor = FLOAT2FIXED(sc.Float);
} }
else if (SC_Compare ("fastmonsters")) else if (sc.Compare ("fastmonsters"))
{ {
skill.FastMonsters = true; skill.FastMonsters = true;
} }
else if (SC_Compare ("disablecheats")) else if (sc.Compare ("disablecheats"))
{ {
skill.DisableCheats = true; skill.DisableCheats = true;
} }
else if (SC_Compare ("easybossbrain")) else if (sc.Compare ("easybossbrain"))
{ {
skill.EasyBossBrain = true; skill.EasyBossBrain = true;
} }
else if (SC_Compare("autousehealth")) else if (sc.Compare("autousehealth"))
{ {
skill.AutoUseHealth = true; skill.AutoUseHealth = true;
} }
else if (SC_Compare("respawntime")) else if (sc.Compare("respawntime"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
skill.RespawnCounter = int(sc_Float*TICRATE); skill.RespawnCounter = int(sc.Float*TICRATE);
} }
else if (SC_Compare("Aggressiveness")) else if (sc.Compare("Aggressiveness"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
skill.Aggressiveness = FRACUNIT - FLOAT2FIXED(clamp<float>(sc_Float, 0,1)); skill.Aggressiveness = FRACUNIT - FLOAT2FIXED(clamp<float>(sc.Float, 0,1));
} }
else if (SC_Compare("SpawnFilter")) else if (sc.Compare("SpawnFilter"))
{ {
SC_MustGetString (); sc.MustGetString ();
strlwr(sc_String); strlwr(sc.String);
if (strstr(sc_String, "easy")) skill.SpawnFilter|=MTF_EASY; if (strstr(sc.String, "easy")) skill.SpawnFilter|=MTF_EASY;
if (strstr(sc_String, "normal")) skill.SpawnFilter|=MTF_NORMAL; if (strstr(sc.String, "normal")) skill.SpawnFilter|=MTF_NORMAL;
if (strstr(sc_String, "hard")) skill.SpawnFilter|=MTF_HARD; if (strstr(sc.String, "hard")) skill.SpawnFilter|=MTF_HARD;
} }
else if (SC_Compare("ACSReturn")) else if (sc.Compare("ACSReturn"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
skill.ACSReturn = sc_Number; skill.ACSReturn = sc.Number;
} }
else if (SC_Compare("Name")) else if (sc.Compare("Name"))
{ {
SC_MustGetString (); sc.MustGetString ();
skill.MenuName = sc_String; skill.MenuName = sc.String;
skill.MenuNameIsLump = false; skill.MenuNameIsLump = false;
} }
else if (SC_Compare("PlayerClassName")) else if (sc.Compare("PlayerClassName"))
{ {
SC_MustGetString (); sc.MustGetString ();
FName pc = sc_String; FName pc = sc.String;
SC_MustGetString (); sc.MustGetString ();
skill.MenuNamesForPlayerClass[pc]=sc_String; skill.MenuNamesForPlayerClass[pc]=sc.String;
} }
else if (SC_Compare("PicName")) else if (sc.Compare("PicName"))
{ {
SC_MustGetString (); sc.MustGetString ();
skill.MenuName = sc_String; skill.MenuName = sc.String;
skill.MenuNameIsLump = true; skill.MenuNameIsLump = true;
} }
else if (SC_Compare("MustConfirm")) else if (sc.Compare("MustConfirm"))
{ {
skill.MustConfirm = true; skill.MustConfirm = true;
if (SC_CheckToken(TK_StringConst)) if (sc.CheckToken(TK_StringConst))
{ {
skill.MustConfirmText = sc_String; skill.MustConfirmText = sc.String;
} }
} }
else if (SC_Compare("Key")) else if (sc.Compare("Key"))
{ {
SC_MustGetString(); sc.MustGetString();
skill.Shortcut = tolower(sc_String[0]); skill.Shortcut = tolower(sc.String[0]);
} }
else if (SC_Compare("TextColor")) else if (sc.Compare("TextColor"))
{ {
SC_MustGetString(); sc.MustGetString();
skill.TextColor = '['; skill.TextColor = '[';
skill.TextColor << sc_String << ']'; skill.TextColor << sc.String << ']';
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }

View file

@ -61,28 +61,31 @@ IMPLEMENT_CLASS (DImpactDecal)
DBaseDecal::DBaseDecal () DBaseDecal::DBaseDecal ()
: DThinker(STAT_DECAL), : DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(0), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT), WallNext(0), WallPrev(0), LeftDistance(0), Z(0), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT),
AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0), RenderStyle(0) AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0)
{ {
RenderStyle = STYLE_None;
} }
DBaseDecal::DBaseDecal (fixed_t z) DBaseDecal::DBaseDecal (fixed_t z)
: DThinker(STAT_DECAL), : DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT), WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT),
AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0), RenderStyle(0) AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0)
{ {
RenderStyle = STYLE_None;
} }
DBaseDecal::DBaseDecal (int statnum, fixed_t z) DBaseDecal::DBaseDecal (int statnum, fixed_t z)
: DThinker(statnum), : DThinker(statnum),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT), WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(FRACUNIT), ScaleY(FRACUNIT), Alpha(FRACUNIT),
AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0), RenderStyle(0) AlphaColor(0), Translation(0), PicNum(0xFFFF), RenderFlags(0)
{ {
RenderStyle = STYLE_None;
} }
DBaseDecal::DBaseDecal (const AActor *basis) DBaseDecal::DBaseDecal (const AActor *basis)
: DThinker(STAT_DECAL), : DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(basis->z), ScaleX(basis->scaleX), ScaleY(basis->scaleY), WallNext(0), WallPrev(0), LeftDistance(0), Z(basis->z), ScaleX(basis->scaleX), ScaleY(basis->scaleY),
Alpha(basis->alpha), AlphaColor(basis->alphacolor), Translation(basis->Translation), PicNum(basis->picnum), Alpha(basis->alpha), AlphaColor(basis->fillcolor), Translation(basis->Translation), PicNum(basis->picnum),
RenderFlags(basis->renderflags), RenderStyle(basis->RenderStyle) RenderFlags(basis->renderflags), RenderStyle(basis->RenderStyle)
{ {
} }

View file

@ -101,7 +101,7 @@ static const char * keywords_lock[]={
// //
//=========================================================================== //===========================================================================
static void AddOneKey(Keygroup * keygroup, const PClass * mi) static void AddOneKey(Keygroup *keygroup, const PClass *mi, FScanner &sc)
{ {
if (mi) if (mi)
{ {
@ -123,12 +123,12 @@ static void AddOneKey(Keygroup * keygroup, const PClass * mi)
} }
else else
{ {
SC_ScriptError("'%s' is not an inventory item", sc_String); sc.ScriptError("'%s' is not an inventory item", sc.String);
} }
} }
else else
{ {
SC_ScriptError("Unknown item '%s'", sc_String); sc.ScriptError("Unknown item '%s'", sc.String);
} }
} }
@ -138,20 +138,20 @@ static void AddOneKey(Keygroup * keygroup, const PClass * mi)
// //
//=========================================================================== //===========================================================================
static Keygroup * ParseKeygroup() static Keygroup * ParseKeygroup(FScanner &sc)
{ {
Keygroup * keygroup; Keygroup * keygroup;
const PClass * mi; const PClass * mi;
SC_MustGetStringName("{"); sc.MustGetStringName("{");
keygroup=new Keygroup; keygroup = new Keygroup;
while (!SC_CheckString("}")) while (!sc.CheckString("}"))
{ {
SC_MustGetString(); sc.MustGetString();
mi=PClass::FindClass(sc_String); mi = PClass::FindClass(sc.String);
AddOneKey(keygroup, mi); AddOneKey(keygroup, mi, sc);
} }
if (keygroup->anykeylist.Size()==0) if (keygroup->anykeylist.Size() == 0)
{ {
delete keygroup; delete keygroup;
return NULL; return NULL;
@ -182,7 +182,7 @@ static void PrintMessage (const char *str)
// //
//=========================================================================== //===========================================================================
static void ParseLock() static void ParseLock(FScanner &sc)
{ {
int i,r,g,b; int i,r,g,b;
int keynum; int keynum;
@ -191,84 +191,90 @@ static void ParseLock()
Keygroup * keygroup; Keygroup * keygroup;
const PClass * mi; const PClass * mi;
SC_MustGetNumber(); sc.MustGetNumber();
keynum=sc_Number; keynum = sc.Number;
SC_MustGetString(); sc.MustGetString();
if (SC_Compare("DOOM")) if (sc.Compare("DOOM"))
{ {
if (gameinfo.gametype != GAME_Doom) keynum=-1; if (gameinfo.gametype != GAME_Doom) keynum=-1;
} }
else if (SC_Compare("HERETIC")) else if (sc.Compare("HERETIC"))
{ {
if (gameinfo.gametype != GAME_Heretic) keynum=-1; if (gameinfo.gametype != GAME_Heretic) keynum=-1;
} }
else if (SC_Compare("HEXEN")) else if (sc.Compare("HEXEN"))
{ {
if (gameinfo.gametype != GAME_Hexen) keynum=-1; if (gameinfo.gametype != GAME_Hexen) keynum=-1;
} }
else if (SC_Compare("STRIFE")) else if (sc.Compare("STRIFE"))
{ {
if (gameinfo.gametype != GAME_Strife) keynum=-1; if (gameinfo.gametype != GAME_Strife) keynum=-1;
} }
else SC_UnGet(); else sc.UnGet();
ignorekey=true; ignorekey = true;
if (keynum>0 && keynum<255) if (keynum > 0 && keynum < 255)
{ {
lock=new Lock; lock = new Lock;
if (locks[keynum]) delete locks[keynum]; if (locks[keynum])
locks[keynum]=lock; {
delete locks[keynum];
}
locks[keynum] = lock;
locks[keynum]->locksound = S_FindSound("misc/keytry"); locks[keynum]->locksound = S_FindSound("misc/keytry");
ignorekey=false; ignorekey=false;
} }
else if (keynum!=-1) else if (keynum != -1)
{ {
SC_ScriptError("Lock index %d out of range", keynum); sc.ScriptError("Lock index %d out of range", keynum);
} }
SC_MustGetStringName("{"); sc.MustGetStringName("{");
while (!SC_CheckString("}")) while (!sc.CheckString("}"))
{ {
SC_MustGetString(); sc.MustGetString();
switch(i=SC_MatchString(keywords_lock)) switch(i = sc.MatchString(keywords_lock))
{ {
case 0: // Any case 0: // Any
keygroup=ParseKeygroup(); keygroup = ParseKeygroup(sc);
if (keygroup) lock->keylist.Push(keygroup); if (keygroup)
{
lock->keylist.Push(keygroup);
}
break; break;
case 1: // message case 1: // message
SC_MustGetString(); sc.MustGetString();
lock->message=copystring(sc_String); lock->message = copystring(sc.String);
break; break;
case 2: // remotemsg case 2: // remotemsg
SC_MustGetString(); sc.MustGetString();
lock->remotemsg=copystring(sc_String); lock->remotemsg = copystring(sc.String);
break; break;
case 3: // mapcolor case 3: // mapcolor
SC_MustGetNumber(); sc.MustGetNumber();
r=sc_Number; r = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
g=sc_Number; g = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
b=sc_Number; b = sc.Number;
lock->rgb=MAKERGB(r,g,b); lock->rgb = MAKERGB(r,g,b);
break; break;
case 4: // locksound case 4: // locksound
SC_MustGetString(); sc.MustGetString();
lock->locksound = S_FindSound(sc_String); lock->locksound = S_FindSound(sc.String);
break; break;
default: default:
mi=PClass::FindClass(sc_String); mi = PClass::FindClass(sc.String);
if (mi) if (mi)
{ {
keygroup=new Keygroup; keygroup = new Keygroup;
AddOneKey(keygroup, mi); AddOneKey(keygroup, mi, sc);
if (keygroup) if (keygroup)
{ {
keygroup->anykeylist.ShrinkToFit(); keygroup->anykeylist.ShrinkToFit();
@ -279,8 +285,14 @@ static void ParseLock()
} }
} }
// copy the messages if the other one does not exist // copy the messages if the other one does not exist
if (!lock->remotemsg && lock->message) lock->remotemsg = copystring(lock->message); if (!lock->remotemsg && lock->message)
if (!lock->message && lock->remotemsg) lock->message = copystring(lock->remotemsg); {
lock->remotemsg = copystring(lock->message);
}
if (!lock->message && lock->remotemsg)
{
lock->message = copystring(lock->remotemsg);
}
lock->keylist.ShrinkToFit(); lock->keylist.ShrinkToFit();
} }
@ -332,24 +344,26 @@ void P_InitKeyMessages()
ClearLocks(); ClearLocks();
while ((lump = Wads.FindLump ("LOCKDEFS", &lastlump)) != -1) while ((lump = Wads.FindLump ("LOCKDEFS", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "LOCKDEFS"); FScanner sc(lump, "LOCKDEFS");
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare("LOCK")) if (sc.Compare("LOCK"))
{ {
ParseLock(); ParseLock(sc);
} }
else if (SC_Compare("CLEARLOCKS")) else if (sc.Compare("CLEARLOCKS"))
{ {
// clear all existing lock defintions and key numbers // clear all existing lock definitions and key numbers
ClearLocks(); ClearLocks();
} }
else else
SC_ScriptError("Unknown command %s in LockDef", sc_String); {
sc.ScriptError("Unknown command %s in LockDef", sc.String);
}
} }
SC_Close(); sc.Close();
} }
keysdone=true; keysdone = true;
} }
//=========================================================================== //===========================================================================

View file

@ -51,7 +51,7 @@ public:
WORD Translation; WORD Translation;
WORD PicNum; WORD PicNum;
DWORD RenderFlags; DWORD RenderFlags;
BYTE RenderStyle; FRenderStyle RenderStyle;
protected: protected:
virtual DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const; virtual DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const;

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
#include "v_collection.h" #include "v_collection.h"
class FBarTexture; class FBarTexture;
class FScanner;
struct SBarInfoCommand; //we need to be able to use this before it is defined. struct SBarInfoCommand; //we need to be able to use this before it is defined.
@ -19,7 +20,7 @@ struct SBarInfoCommand
{ {
SBarInfoCommand(); SBarInfoCommand();
~SBarInfoCommand(); ~SBarInfoCommand();
void setString(const char* source, int strnum, int maxlength=-1, bool exact=false); void setString(FScanner &sc, const char* source, int strnum, int maxlength=-1, bool exact=false);
int type; int type;
int special; int special;
@ -52,10 +53,11 @@ struct SBarInfo
int GetGameType() { return gameType; } int GetGameType() { return gameType; }
void ParseSBarInfo(int lump); void ParseSBarInfo(int lump);
void ParseSBarInfoBlock(SBarInfoBlock &block); void ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block);
void getCoordinates(FScanner &sc, SBarInfoCommand &cmd); //retrieves the next two arguments as x and y.
int newImage(const char* patchname); int newImage(const char* patchname);
void Init(); void Init();
EColorRange GetTranslation(char* translation); EColorRange GetTranslation(FScanner &sc, char* translation);
SBarInfo(); SBarInfo();
SBarInfo(int lumpnum); SBarInfo(int lumpnum);
~SBarInfo(); ~SBarInfo();

View file

@ -928,42 +928,41 @@ void HUD_InitHud()
while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1) while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
{ {
SC_OpenLumpNum(lump, "ALTHUDCF"); FScanner sc(lump, "ALTHUDCF");
while (SC_GetString()) while (sc.GetString())
{ {
if (SC_Compare("Health")) if (sc.Compare("Health"))
{ {
SC_MustGetString(); sc.MustGetString();
int tex = TexMan.AddPatch(sc_String); int tex = TexMan.AddPatch(sc.String);
if (tex<=0) tex = TexMan.AddPatch(sc_String, ns_sprites); if (tex<=0) tex = TexMan.AddPatch(sc.String, ns_sprites);
if (tex>0) healthpic = TexMan[tex]; if (tex>0) healthpic = TexMan[tex];
} }
else else
{ {
const PClass * ti = PClass::FindClass(sc_String); const PClass * ti = PClass::FindClass(sc.String);
if (!ti) if (!ti)
{ {
Printf("Unknown item class '%s' in ALTHUDCF\n", sc_String); Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String);
} }
else if (!ti->IsDescendantOf(RUNTIME_CLASS(AInventory))) else if (!ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{ {
Printf("Invalid item class '%s' in ALTHUDCF\n", sc_String); Printf("Invalid item class '%s' in ALTHUDCF\n", sc.String);
ti=NULL; ti=NULL;
} }
SC_MustGetString(); sc.MustGetString();
int tex=0; int tex=0;
if (!SC_Compare("0") && !SC_Compare("NULL") && !SC_Compare("")) if (!sc.Compare("0") && !sc.Compare("NULL") && !sc.Compare(""))
{ {
tex = TexMan.AddPatch(sc_String); tex = TexMan.AddPatch(sc.String);
if (tex<=0) tex = TexMan.AddPatch(sc_String, ns_sprites); if (tex<=0) tex = TexMan.AddPatch(sc.String, ns_sprites);
} }
else tex=-1; else tex=-1;
if (ti) const_cast<PClass*>(ti)->Meta.SetMetaInt(HUMETA_AltIcon, tex); if (ti) const_cast<PClass*>(ti)->Meta.SetMetaInt(HUMETA_AltIcon, tex);
} }
} }
SC_Close();
} }
} }

View file

@ -423,7 +423,7 @@ void A_AcolyteBits (AActor *self)
} }
else else
{ {
self->RenderStyle = STYLE_None; self->RenderStyle.BlendOp = STYLEOP_None;
} }
} }
} }

View file

@ -290,7 +290,7 @@ void A_Beacon (AActor *self)
self->flags &= ~MF_SPECIAL; self->flags &= ~MF_SPECIAL;
static_cast<AInventory *>(self)->DropTime = 0; static_cast<AInventory *>(self)->DropTime = 0;
// Set up the new rebel. // Set up the new rebel.
rebel->threshold = 100; rebel->threshold = BASETHRESHOLD;
rebel->target = NULL; rebel->target = NULL;
rebel->flags4 |= MF4_INCOMBAT; rebel->flags4 |= MF4_INCOMBAT;
rebel->LastHeard = owner; // Make sure the rebels look for targets rebel->LastHeard = owner; // Make sure the rebels look for targets

View file

@ -180,7 +180,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
} }
if (teamplay && deathmatch) if (teamplay && deathmatch)
gamestate == GS_INTERMISSION ? y = SCREENHEIGHT / 3.5 : y = SCREENHEIGHT / 16; gamestate == GS_INTERMISSION ? y = SCREENHEIGHT * 7 / 2 : y = SCREENHEIGHT / 16;
else else
gamestate == GS_INTERMISSION ? y = SCREENHEIGHT / 4 : y = SCREENHEIGHT / 16; gamestate == GS_INTERMISSION ? y = SCREENHEIGHT / 4 : y = SCREENHEIGHT / 16;
@ -216,7 +216,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
sprintf (score, "%d", teams[i].score); sprintf (score, "%d", teams[i].score);
screen->SetFont (BigFont); screen->SetFont (BigFont);
screen->DrawText (teams[i].GetTextColor (), scorexwidth, gamestate == GS_INTERMISSION ? y / 1.25 : y / 2, score, screen->DrawText (teams[i].GetTextColor (), scorexwidth, gamestate == GS_INTERMISSION ? y * 4 / 5 : y / 2, score,
DTA_CleanNoMove, true, TAG_DONE); DTA_CleanNoMove, true, TAG_DONE);
scorexwidth += SCREENWIDTH / 8; scorexwidth += SCREENWIDTH / 8;
@ -337,7 +337,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int x, int y, int h
if (player->mo->ScoreIcon > 0) if (player->mo->ScoreIcon > 0)
{ {
screen->DrawTexture (TexMan[player->mo->ScoreIcon], SCREENWIDTH / 2.25, y, screen->DrawTexture (TexMan[player->mo->ScoreIcon], SCREENWIDTH * 4 / 9, y,
DTA_CleanNoMove, true, TAG_DONE); DTA_CleanNoMove, true, TAG_DONE);
} }
} }

View file

@ -215,7 +215,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_Flags4Clear: actor->flags4 &= ~dataint; break; case ADEF_Flags4Clear: actor->flags4 &= ~dataint; break;
case ADEF_Flags5Clear: actor->flags5 &= ~dataint; break; case ADEF_Flags5Clear: actor->flags5 &= ~dataint; break;
case ADEF_Alpha: actor->alpha = dataint; break; case ADEF_Alpha: actor->alpha = dataint; break;
case ADEF_RenderStyle: actor->RenderStyle = dataint; break; case ADEF_RenderStyle: actor->RenderStyle = ERenderStyle(dataint); break;
case ADEF_RenderFlags: actor->renderflags = dataint; break; case ADEF_RenderFlags: actor->renderflags = dataint; break;
case ADEF_Translation: actor->Translation = dataint; break; case ADEF_Translation: actor->Translation = dataint; break;
case ADEF_MinMissileChance: actor->MinMissileChance = dataint; break; case ADEF_MinMissileChance: actor->MinMissileChance = dataint; break;

View file

@ -3338,12 +3338,12 @@ void InitCrosshairsList()
while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1) while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1)
{ {
SC_OpenLumpNum(lump, "XHAIRS"); FScanner sc(lump, "XHAIRS");
while (SC_GetNumber()) while (sc.GetNumber())
{ {
value.value = float(sc_Number); value.value = float(sc.Number);
SC_MustGetString(); sc.MustGetString();
value.name = sc_String; value.name = sc.String;
if (value.value != 0) if (value.value != 0)
{ // Check if it already exists. If not, add it. { // Check if it already exists. If not, add it.
unsigned int i; unsigned int i;
@ -3365,7 +3365,6 @@ void InitCrosshairsList()
} }
} }
} }
SC_Close();
} }
VideoItems[CROSSHAIR_INDEX].b.numvalues = float(Crosshairs.Size()); VideoItems[CROSSHAIR_INDEX].b.numvalues = float(Crosshairs.Size());
VideoItems[CROSSHAIR_INDEX].e.valuestrings = &Crosshairs[0]; VideoItems[CROSSHAIR_INDEX].e.valuestrings = &Crosshairs[0];

View file

@ -555,20 +555,19 @@ void FBehavior::StaticLoadDefaultModules ()
while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1) while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "LOADACS"); FScanner sc(lump, "LOADACS");
while (SC_GetString()) while (sc.GetString())
{ {
int acslump = Wads.CheckNumForName (sc_String, ns_acslibrary); int acslump = Wads.CheckNumForName (sc.String, ns_acslibrary);
if (acslump >= 0) if (acslump >= 0)
{ {
StaticLoadModule (acslump); StaticLoadModule (acslump);
} }
else else
{ {
Printf ("Could not find autoloaded ACS library %s\n", sc_String); Printf ("Could not find autoloaded ACS library %s\n", sc.String);
} }
} }
SC_Close ();
} }
} }
@ -2200,7 +2199,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
break; break;
case APROP_RenderStyle: case APROP_RenderStyle:
actor->RenderStyle = value; actor->RenderStyle = ERenderStyle(value);
break; break;
case APROP_Ambush: case APROP_Ambush:
@ -2290,7 +2289,16 @@ int DLevelScript::GetActorProperty (int tid, int property)
case APROP_Speed: return actor->Speed; case APROP_Speed: return actor->Speed;
case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead? case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead?
case APROP_Alpha: return actor->alpha; case APROP_Alpha: return actor->alpha;
case APROP_RenderStyle: return actor->RenderStyle; case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style)
{ // Check for a legacy render style that matches.
if (LegacyRenderStyles[style] == actor->RenderStyle)
{
return style;
}
}
// The current render style isn't expressable as a legacy style,
// so pretends it's normal.
return STYLE_Normal;
case APROP_Gravity: return actor->gravity; case APROP_Gravity: return actor->gravity;
case APROP_Ambush: return !!(actor->flags & MF_AMBUSH); case APROP_Ambush: return !!(actor->flags & MF_AMBUSH);
case APROP_ChaseGoal: return !!(actor->flags5 & MF5_CHASEGOAL); case APROP_ChaseGoal: return !!(actor->flags5 & MF5_CHASEGOAL);

View file

@ -802,7 +802,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay)
return rtn; return rtn;
} }
void P_ParseAnimatedDoor() void P_ParseAnimatedDoor(FScanner &sc)
{ {
const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
FDoorAnimation anim; FDoorAnimation anim;
@ -810,8 +810,8 @@ void P_ParseAnimatedDoor()
bool error = false; bool error = false;
int v; int v;
SC_MustGetString(); sc.MustGetString();
anim.BaseTexture = TexMan.CheckForTexture (sc_String, FTexture::TEX_Wall, texflags); anim.BaseTexture = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
anim.OpenSound = NULL; anim.OpenSound = NULL;
anim.CloseSound = NULL; anim.CloseSound = NULL;
@ -820,38 +820,38 @@ void P_ParseAnimatedDoor()
error = true; error = true;
} }
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("opensound")) if (sc.Compare ("opensound"))
{ {
SC_MustGetString (); sc.MustGetString ();
anim.OpenSound = copystring (sc_String); anim.OpenSound = copystring (sc.String);
} }
else if (SC_Compare ("closesound")) else if (sc.Compare ("closesound"))
{ {
SC_MustGetString (); sc.MustGetString ();
anim.CloseSound = copystring (sc_String); anim.CloseSound = copystring (sc.String);
} }
else if (SC_Compare ("pic")) else if (sc.Compare ("pic"))
{ {
SC_MustGetString (); sc.MustGetString ();
if (IsNum (sc_String)) if (IsNum (sc.String))
{ {
v = atoi(sc_String) + anim.BaseTexture -1; v = atoi(sc.String) + anim.BaseTexture -1;
} }
else else
{ {
v = TexMan.CheckForTexture (sc_String, FTexture::TEX_Wall, texflags); v = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
if (v == -1 && anim.BaseTexture >= 0 && !error) if (v == -1 && anim.BaseTexture >= 0 && !error)
{ {
SC_ScriptError ("Unknown texture %s", sc_String); sc.ScriptError ("Unknown texture %s", sc.String);
} }
frames.Push (v); frames.Push (v);
} }
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }

View file

@ -1664,8 +1664,6 @@ void A_Look (AActor *actor)
//========================================================================== //==========================================================================
void A_Wander (AActor *self) void A_Wander (AActor *self)
{ {
int delta;
// [RH] Strife probably clears this flag somewhere, but I couldn't find where. // [RH] Strife probably clears this flag somewhere, but I couldn't find where.
// This seems as good a place as any. // This seems as good a place as any.
self->flags4 &= ~MF4_INCOMBAT; self->flags4 &= ~MF4_INCOMBAT;
@ -1673,9 +1671,9 @@ void A_Wander (AActor *self)
if (self->flags4 & MF4_STANDSTILL) if (self->flags4 & MF4_STANDSTILL)
return; return;
if (self->threshold != 0) if (self->reactiontime != 0)
{ {
self->threshold--; self->reactiontime--;
return; return;
} }
@ -1683,7 +1681,7 @@ void A_Wander (AActor *self)
if (self->movedir < DI_NODIR) if (self->movedir < DI_NODIR)
{ {
self->angle &= (angle_t)(7<<29); self->angle &= (angle_t)(7<<29);
delta = self->angle - (self->movedir << 29); int delta = self->angle - (self->movedir << 29);
if (delta > 0) if (delta > 0)
{ {
self->angle -= ANG90/2; self->angle -= ANG90/2;

View file

@ -245,7 +245,7 @@ void AActor::Serialize (FArchive &arc)
} }
arc << effects arc << effects
<< alpha << alpha
<< alphacolor << fillcolor
<< pitch << pitch
<< roll << roll
<< Sector << Sector
@ -387,7 +387,7 @@ void AActor::Serialize (FArchive &arc)
touching_sectorlist = NULL; touching_sectorlist = NULL;
LinkToWorld (Sector); LinkToWorld (Sector);
AddToHash (); AddToHash ();
SetShade (alphacolor); SetShade (fillcolor);
if (player) if (player)
{ {
if (playeringame[player - players] && if (playeringame[player - players] &&
@ -1125,7 +1125,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
} }
else else
{ {
mo->RenderStyle = deh.ExplosionStyle; mo->RenderStyle = ERenderStyle(deh.ExplosionStyle);
mo->alpha = deh.ExplosionAlpha; mo->alpha = deh.ExplosionAlpha;
} }
} }
@ -2488,12 +2488,12 @@ bool AActor::IsOkayToAttack (AActor *link)
void AActor::SetShade (DWORD rgb) void AActor::SetShade (DWORD rgb)
{ {
PalEntry *entry = (PalEntry *)&rgb; PalEntry *entry = (PalEntry *)&rgb;
alphacolor = rgb | (ColorMatcher.Pick (entry->r, entry->g, entry->b) << 24); fillcolor = rgb | (ColorMatcher.Pick (entry->r, entry->g, entry->b) << 24);
} }
void AActor::SetShade (int r, int g, int b) void AActor::SetShade (int r, int g, int b)
{ {
alphacolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b);
} }
// //
@ -2607,6 +2607,7 @@ void AActor::Tick ()
else if (flags & MF_STEALTH) else if (flags & MF_STEALTH)
{ {
// [RH] Fade a stealth monster in and out of visibility // [RH] Fade a stealth monster in and out of visibility
RenderStyle.Flags &= ~STYLEF_Alpha1;
if (visdir > 0) if (visdir > 0)
{ {
alpha += 2*FRACUNIT/TICRATE; alpha += 2*FRACUNIT/TICRATE;

View file

@ -493,10 +493,7 @@ sightcounts[0]++;
// //
// [RH] Andy Baker's stealth monsters: // [RH] Andy Baker's stealth monsters:
// Cannot see an invisible object // Cannot see an invisible object
if ((flags & 1) == 0 && if ((flags & 1) == 0 && ((t2->renderflags & RF_INVISIBLE) || !t2->RenderStyle.IsVisible(t2->alpha)))
(t2->RenderStyle == STYLE_None ||
(t2->RenderStyle >= STYLE_Translucent && t2->alpha == 0) ||
(t2->renderflags & RF_INVISIBLE)))
{ // small chance of an attack being made anyway { // small chance of an attack being made anyway
if ((bglobal.m_Thinking ? pr_botchecksight() : pr_checksight()) > 50) if ((bglobal.m_Thinking ? pr_botchecksight() : pr_checksight()) > 50)
{ {

View file

@ -27,6 +27,8 @@
#include "dsectoreffect.h" #include "dsectoreffect.h"
class FScanner;
//jff 2/23/98 identify the special classes that can share sectors //jff 2/23/98 identify the special classes that can share sectors
typedef enum typedef enum
@ -385,7 +387,7 @@ void EV_StartLightFading (int tag, int value, int tics);
bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *quest=NULL); bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *quest=NULL);
void P_InitSwitchList (); void P_InitSwitchList ();
void P_ProcessSwitchDef (); void P_ProcessSwitchDef (FScanner &sc);
// //
// P_PLATS // P_PLATS
@ -589,7 +591,7 @@ struct FDoorAnimation
char *CloseSound; char *CloseSound;
}; };
void P_ParseAnimatedDoor (); void P_ParseAnimatedDoor (FScanner &sc);
class DAnimatedDoor : public DMovingCeiling class DAnimatedDoor : public DMovingCeiling
{ {

View file

@ -107,7 +107,7 @@ struct FSwitchDef
}; };
static int STACK_ARGS SortSwitchDefs (const void *a, const void *b); static int STACK_ARGS SortSwitchDefs (const void *a, const void *b);
static FSwitchDef *ParseSwitchDef (bool ignoreBad); static FSwitchDef *ParseSwitchDef (FScanner &sc, bool ignoreBad);
static WORD AddSwitchDef (FSwitchDef *def); static WORD AddSwitchDef (FSwitchDef *def);
// //
@ -211,84 +211,83 @@ static int STACK_ARGS SortSwitchDefs (const void *a, const void *b)
} }
// Parse a switch block in ANIMDEFS and add the definitions to SwitchList // Parse a switch block in ANIMDEFS and add the definitions to SwitchList
void P_ProcessSwitchDef () void P_ProcessSwitchDef (FScanner &sc)
{ {
const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
char *picname; FString picname;
FSwitchDef *def1, *def2; FSwitchDef *def1, *def2;
SWORD picnum; SWORD picnum;
BYTE max; BYTE max;
bool quest = false; bool quest = false;
def1 = def2 = NULL; def1 = def2 = NULL;
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("doom")) if (sc.Compare ("doom"))
{ {
max = 0; max = 0;
} }
else if (SC_Compare ("heretic")) else if (sc.Compare ("heretic"))
{ {
max = 17; max = 17;
} }
else if (SC_Compare ("hexen")) else if (sc.Compare ("hexen"))
{ {
max = 33; max = 33;
} }
else if (SC_Compare ("strife")) else if (sc.Compare ("strife"))
{ {
max = 49; max = 49;
} }
else if (SC_Compare ("any")) else if (sc.Compare ("any"))
{ {
max = 240; max = 240;
} }
else else
{ {
//SC_ScriptError ("Unknown game");
// There is no game specified; just treat as any // There is no game specified; just treat as any
max = 240; max = 240;
SC_UnGet (); sc.UnGet ();
} }
if (max == 0) if (max == 0)
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
max |= sc_Number & 15; max |= sc.Number & 15;
} }
SC_MustGetString (); sc.MustGetString ();
picnum = TexMan.CheckForTexture (sc_String, FTexture::TEX_Wall, texflags); picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
picname = copystring (sc_String); picname = sc.String;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("quest")) if (sc.Compare ("quest"))
{ {
quest = true; quest = true;
} }
else if (SC_Compare ("on")) else if (sc.Compare ("on"))
{ {
if (def1 != NULL) if (def1 != NULL)
{ {
SC_ScriptError ("Switch already has an on state"); sc.ScriptError ("Switch already has an on state");
} }
def1 = ParseSwitchDef (picnum == -1); def1 = ParseSwitchDef (sc, picnum == -1);
} }
else if (SC_Compare ("off")) else if (sc.Compare ("off"))
{ {
if (def2 != NULL) if (def2 != NULL)
{ {
SC_ScriptError ("Switch already has an off state"); sc.ScriptError ("Switch already has an off state");
} }
def2 = ParseSwitchDef (picnum == -1); def2 = ParseSwitchDef (sc, picnum == -1);
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }
/* /*
if (def1 == NULL) if (def1 == NULL)
{ {
SC_ScriptError ("Switch must have an on state"); sc.ScriptError ("Switch must have an on state");
} }
*/ */
if (def1 == NULL || picnum == -1 || if (def1 == NULL || picnum == -1 ||
@ -304,7 +303,6 @@ void P_ProcessSwitchDef ()
{ {
free (def1); free (def1);
} }
delete [] picname;
return; return;
} }
@ -323,15 +321,14 @@ void P_ProcessSwitchDef ()
def2->PreTexture = def1->u.Textures[def1->NumFrames*2+def1->NumFrames-1]; def2->PreTexture = def1->u.Textures[def1->NumFrames*2+def1->NumFrames-1];
if (def1->PreTexture == def2->PreTexture) if (def1->PreTexture == def2->PreTexture)
{ {
SC_ScriptError ("The on state for switch %s must end with a texture other than %s", picname, picname); sc.ScriptError ("The on state for switch %s must end with a texture other than %s", picname.GetChars(), picname.GetChars());
} }
def2->PairIndex = AddSwitchDef (def1); def2->PairIndex = AddSwitchDef (def1);
def1->PairIndex = AddSwitchDef (def2); def1->PairIndex = AddSwitchDef (def2);
def1->QuestPanel = def2->QuestPanel = quest; def1->QuestPanel = def2->QuestPanel = quest;
delete [] picname;
} }
FSwitchDef *ParseSwitchDef (bool ignoreBad) FSwitchDef *ParseSwitchDef (FScanner &sc, bool ignoreBad)
{ {
const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
FSwitchDef *def; FSwitchDef *def;
@ -346,45 +343,45 @@ FSwitchDef *ParseSwitchDef (bool ignoreBad)
sound = 0; sound = 0;
bad = false; bad = false;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("sound")) if (sc.Compare ("sound"))
{ {
if (sound != 0) if (sound != 0)
{ {
SC_ScriptError ("Switch state already has a sound"); sc.ScriptError ("Switch state already has a sound");
} }
SC_MustGetString (); sc.MustGetString ();
sound = S_FindSound (sc_String); sound = S_FindSound (sc.String);
} }
else if (SC_Compare ("pic")) else if (sc.Compare ("pic"))
{ {
if (numframes == MAX_FRAMES) if (numframes == MAX_FRAMES)
{ {
SC_ScriptError ("Switch has too many frames"); sc.ScriptError ("Switch has too many frames");
} }
SC_MustGetString (); sc.MustGetString ();
picnum = TexMan.CheckForTexture (sc_String, FTexture::TEX_Wall, texflags); picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags);
if (picnum < 0 && !ignoreBad) if (picnum < 0 && !ignoreBad)
{ {
//Printf ("Unknown switch texture %s\n", sc_String); //Printf ("Unknown switch texture %s\n", sc.String);
bad = true; bad = true;
} }
pics[numframes] = picnum; pics[numframes] = picnum;
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("tics")) if (sc.Compare ("tics"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
times[numframes] = sc_Number & 65535; times[numframes] = sc.Number & 65535;
} }
else if (SC_Compare ("rand")) else if (sc.Compare ("rand"))
{ {
int min, max; int min, max;
SC_MustGetNumber (); sc.MustGetNumber ();
min = sc_Number & 65535; min = sc.Number & 65535;
SC_MustGetNumber (); sc.MustGetNumber ();
max = sc_Number & 65535; max = sc.Number & 65535;
if (min > max) if (min > max)
{ {
swap (min, max); swap (min, max);
@ -393,19 +390,19 @@ FSwitchDef *ParseSwitchDef (bool ignoreBad)
} }
else else
{ {
SC_ScriptError ("Must specify a duration for switch frame"); sc.ScriptError ("Must specify a duration for switch frame");
} }
numframes++; numframes++;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }
if (numframes == 0) if (numframes == 0)
{ {
SC_ScriptError ("Switch state needs at least one frame"); sc.ScriptError ("Switch state needs at least one frame");
} }
if (bad) if (bad)
{ {

View file

@ -103,7 +103,7 @@ struct FGenericParse
EGenericType Type; EGenericType Type;
union { union {
size_t Offset; size_t Offset;
void (*Handler) (int type, void *fields); void (*Handler) (FScanner &sc, int type, void *fields);
} u; } u;
}; };
@ -114,16 +114,16 @@ struct FGenericParse
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void MakeDefaultTerrain (); static void MakeDefaultTerrain ();
static void ParseOuter (); static void ParseOuter (FScanner &sc);
static void ParseSplash (); static void ParseSplash (FScanner &sc);
static void ParseTerrain (); static void ParseTerrain (FScanner &sc);
static void ParseFloor (); static void ParseFloor (FScanner &sc);
static int FindSplash (FName name); static int FindSplash (FName name);
static int FindTerrain (FName name); static int FindTerrain (FName name);
static void GenericParse (FGenericParse *parser, const char **keywords, static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keywords,
void *fields, const char *type, FName name); void *fields, const char *type, FName name);
static void ParseDamage (int keyword, void *fields); static void ParseDamage (FScanner &sc, int keyword, void *fields);
static void ParseFriction (int keyword, void *fields); static void ParseFriction (FScanner &sc, int keyword, void *fields);
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -264,9 +264,8 @@ void P_InitTerrainTypes ()
lastlump = 0; lastlump = 0;
while (-1 != (lump = Wads.FindLump ("TERRAIN", &lastlump)) ) while (-1 != (lump = Wads.FindLump ("TERRAIN", &lastlump)) )
{ {
SC_OpenLumpNum (lump, "TERRAIN"); FScanner sc(lump, "TERRAIN");
ParseOuter (); ParseOuter (sc);
SC_Close ();
} }
Splashes.ShrinkToFit (); Splashes.ShrinkToFit ();
Terrains.ShrinkToFit (); Terrains.ShrinkToFit ();
@ -294,51 +293,51 @@ static void MakeDefaultTerrain ()
// //
//========================================================================== //==========================================================================
static void ParseOuter () static void ParseOuter (FScanner &sc)
{ {
int bracedepth = 0; int bracedepth = 0;
bool ifskip = false; bool ifskip = false;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (ifskip) if (ifskip)
{ {
if (bracedepth > 0) if (bracedepth > 0)
{ {
if (SC_Compare ("}")) if (sc.Compare ("}"))
{ {
bracedepth--; bracedepth--;
continue; continue;
} }
} }
else if (SC_Compare ("endif")) else if (sc.Compare ("endif"))
{ {
ifskip = false; ifskip = false;
continue; continue;
} }
if (SC_Compare ("{")) if (sc.Compare ("{"))
{ {
bracedepth++; bracedepth++;
} }
else if (SC_Compare ("}")) else if (sc.Compare ("}"))
{ {
SC_ScriptError ("Too many left braces ('}')"); sc.ScriptError ("Too many left braces ('}')");
} }
} }
else else
{ {
switch (SC_MustMatchString (OuterKeywords)) switch (sc.MustMatchString (OuterKeywords))
{ {
case OUT_SPLASH: case OUT_SPLASH:
ParseSplash (); ParseSplash (sc);
break; break;
case OUT_TERRAIN: case OUT_TERRAIN:
ParseTerrain (); ParseTerrain (sc);
break; break;
case OUT_FLOOR: case OUT_FLOOR:
ParseFloor (); ParseFloor (sc);
break; break;
case OUT_IFDOOM: case OUT_IFDOOM:
@ -403,15 +402,15 @@ static void SetSplashDefaults (FSplashDef *splashdef)
// //
//========================================================================== //==========================================================================
void ParseSplash () void ParseSplash (FScanner &sc)
{ {
int splashnum; int splashnum;
FSplashDef *splashdef; FSplashDef *splashdef;
bool isnew = false; bool isnew = false;
FName name; FName name;
SC_MustGetString (); sc.MustGetString ();
name = sc_String; name = sc.String;
splashnum = (int)FindSplash (name); splashnum = (int)FindSplash (name);
if (splashnum < 0) if (splashnum < 0)
{ {
@ -423,8 +422,8 @@ void ParseSplash ()
} }
splashdef = &Splashes[splashnum]; splashdef = &Splashes[splashnum];
SC_MustGetString (); sc.MustGetString ();
if (!SC_Compare ("modify")) if (!sc.Compare ("modify"))
{ // Set defaults { // Set defaults
if (!isnew) if (!isnew)
{ // New ones already have their defaults set before they're pushed. { // New ones already have their defaults set before they're pushed.
@ -433,15 +432,15 @@ void ParseSplash ()
} }
else else
{ {
SC_MustGetString(); sc.MustGetString();
} }
if (!SC_Compare ("{")) if (!sc.Compare ("{"))
{ {
SC_ScriptError ("Expected {"); sc.ScriptError ("Expected {");
} }
else else
{ {
GenericParse (SplashParser, SplashKeywords, splashdef, "splash", GenericParse (sc, SplashParser, SplashKeywords, splashdef, "splash",
splashdef->Name); splashdef->Name);
} }
} }
@ -452,13 +451,13 @@ void ParseSplash ()
// //
//========================================================================== //==========================================================================
void ParseTerrain () void ParseTerrain (FScanner &sc)
{ {
int terrainnum; int terrainnum;
FName name; FName name;
SC_MustGetString (); sc.MustGetString ();
name = sc_String; name = sc.String;
terrainnum = (int)FindTerrain (name); terrainnum = (int)FindTerrain (name);
if (terrainnum < 0) if (terrainnum < 0)
{ {
@ -470,8 +469,8 @@ void ParseTerrain ()
} }
// Set defaults // Set defaults
SC_MustGetString (); sc.MustGetString ();
if (!SC_Compare ("modify")) if (!sc.Compare ("modify"))
{ {
name = Terrains[terrainnum].Name; name = Terrains[terrainnum].Name;
memset (&Terrains[terrainnum], 0, sizeof(FTerrainDef)); memset (&Terrains[terrainnum], 0, sizeof(FTerrainDef));
@ -480,17 +479,17 @@ void ParseTerrain ()
} }
else else
{ {
SC_MustGetString (); sc.MustGetString ();
} }
if (SC_Compare ("{")) if (sc.Compare ("{"))
{ {
GenericParse (TerrainParser, TerrainKeywords, &Terrains[terrainnum], GenericParse (sc, TerrainParser, TerrainKeywords, &Terrains[terrainnum],
"terrain", Terrains[terrainnum].Name); "terrain", Terrains[terrainnum].Name);
} }
else else
{ {
SC_ScriptError ("Expected {"); sc.ScriptError ("Expected {");
} }
} }
@ -500,14 +499,14 @@ void ParseTerrain ()
// //
//========================================================================== //==========================================================================
static void ParseDamage (int keyword, void *fields) static void ParseDamage (FScanner &sc, int keyword, void *fields)
{ {
FTerrainDef *def = (FTerrainDef *)fields; FTerrainDef *def = (FTerrainDef *)fields;
SC_MustGetString (); sc.MustGetString ();
// Lava is synonymous with Fire here! // Lava is synonymous with Fire here!
if (SC_Compare("Lava")) def->DamageMOD=NAME_Fire; if (sc.Compare("Lava")) def->DamageMOD=NAME_Fire;
else def->DamageMOD=sc_String; else def->DamageMOD=sc.String;
} }
//========================================================================== //==========================================================================
@ -516,17 +515,17 @@ static void ParseDamage (int keyword, void *fields)
// //
//========================================================================== //==========================================================================
static void ParseFriction (int keyword, void *fields) static void ParseFriction (FScanner &sc, int keyword, void *fields)
{ {
FTerrainDef *def = (FTerrainDef *)fields; FTerrainDef *def = (FTerrainDef *)fields;
fixed_t friction, movefactor; fixed_t friction, movefactor;
SC_MustGetFloat (); sc.MustGetFloat ();
// These calculations should match those in P_SetSectorFriction(). // These calculations should match those in P_SetSectorFriction().
// A friction of 1.0 is equivalent to ORIG_FRICTION. // A friction of 1.0 is equivalent to ORIG_FRICTION.
friction = (fixed_t)(0x1EB8*(sc_Float*100))/0x80 + 0xD001; friction = (fixed_t)(0x1EB8*(sc.Float*100))/0x80 + 0xD001;
friction = clamp<fixed_t> (friction, 0, FRACUNIT); friction = clamp<fixed_t> (friction, 0, FRACUNIT);
if (friction > ORIG_FRICTION) // ice if (friction > ORIG_FRICTION) // ice
@ -547,7 +546,7 @@ static void ParseFriction (int keyword, void *fields)
// //
//========================================================================== //==========================================================================
static void GenericParse (FGenericParse *parser, const char **keywords, static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keywords,
void *fields, const char *type, FName name) void *fields, const char *type, FName name)
{ {
bool notdone = true; bool notdone = true;
@ -557,8 +556,8 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
do do
{ {
SC_MustGetString (); sc.MustGetString ();
keyword = SC_MustMatchString (keywords); keyword = sc.MustMatchString (keywords);
switch (parser[keyword].Type) switch (parser[keyword].Type)
{ {
case GEN_End: case GEN_End:
@ -566,69 +565,69 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
break; break;
case GEN_Fixed: case GEN_Fixed:
SC_MustGetFloat (); sc.MustGetFloat ();
SET_FIELD (fixed_t, (fixed_t)(FRACUNIT * sc_Float)); SET_FIELD (fixed_t, (fixed_t)(FRACUNIT * sc.Float));
break; break;
case GEN_Sound: case GEN_Sound:
SC_MustGetString (); sc.MustGetString ();
val = S_FindSound (sc_String); val = S_FindSound (sc.String);
SET_FIELD (int, val); SET_FIELD (int, val);
if (val == 0) if (val == 0)
{ {
Printf ("Unknown sound %s in %s %s\n", Printf ("Unknown sound %s in %s %s\n",
sc_String, type, name.GetChars()); sc.String, type, name.GetChars());
} }
break; break;
case GEN_Byte: case GEN_Byte:
SC_MustGetNumber (); sc.MustGetNumber ();
SET_FIELD (BYTE, sc_Number); SET_FIELD (BYTE, sc.Number);
break; break;
case GEN_Class: case GEN_Class:
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("None")) if (sc.Compare ("None"))
{ {
info = NULL; info = NULL;
} }
else else
{ {
info = PClass::FindClass (sc_String); info = PClass::FindClass (sc.String);
if (!info->IsDescendantOf (RUNTIME_CLASS(AActor))) 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) else if (info == NULL)
{ {
Printf ("Unknown actor %s in %s %s\n", Printf ("Unknown actor %s in %s %s\n",
sc_String, type, name.GetChars()); sc.String, type, name.GetChars());
} }
} }
SET_FIELD (const PClass *, info); SET_FIELD (const PClass *, info);
break; break;
case GEN_Splash: case GEN_Splash:
SC_MustGetString (); sc.MustGetString ();
val = FindSplash (sc_String); val = FindSplash (sc.String);
SET_FIELD (int, val); SET_FIELD (int, val);
if (val == -1) if (val == -1)
{ {
Printf ("Splash %s is not defined yet (in %s %s)\n", Printf ("Splash %s is not defined yet (in %s %s)\n",
sc_String, type, name.GetChars()); sc.String, type, name.GetChars());
} }
break; break;
case GEN_Float: case GEN_Float:
SC_MustGetFloat (); sc.MustGetFloat ();
SET_FIELD (float, sc_Float); SET_FIELD (float, sc.Float);
break; break;
case GEN_Time: case GEN_Time:
SC_MustGetFloat (); sc.MustGetFloat ();
SET_FIELD (int, (int)(sc_Float * TICRATE)); SET_FIELD (int, (int)(sc.Float * TICRATE));
break; break;
case GEN_Bool: case GEN_Bool:
@ -636,12 +635,12 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
break; break;
case GEN_Int: case GEN_Int:
SC_MustGetNumber (); sc.MustGetNumber ();
SET_FIELD (int, sc_Number); SET_FIELD (int, sc.Number);
break; break;
case GEN_Custom: case GEN_Custom:
parser[keyword].u.Handler (keyword, fields); parser[keyword].u.Handler (sc, keyword, fields);
break; break;
} }
} while (notdone); } while (notdone);
@ -653,24 +652,24 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
// //
//========================================================================== //==========================================================================
static void ParseFloor () static void ParseFloor (FScanner &sc)
{ {
int picnum; int picnum;
int terrain; int terrain;
SC_MustGetString (); sc.MustGetString ();
picnum = TexMan.CheckForTexture (sc_String, FTexture::TEX_Flat); picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Flat);
if (picnum == -1) if (picnum == -1)
{ {
Printf ("Unknown flat %s\n", sc_String); Printf ("Unknown flat %s\n", sc.String);
SC_MustGetString (); sc.MustGetString ();
return; return;
} }
SC_MustGetString (); sc.MustGetString ();
terrain = FindTerrain (sc_String); terrain = FindTerrain (sc.String);
if (terrain == -1) if (terrain == -1)
{ {
Printf ("Unknown terrain %s\n", sc_String); Printf ("Unknown terrain %s\n", sc.String);
terrain = 0; terrain = 0;
} }
TerrainTypes[picnum] = terrain; TerrainTypes[picnum] = terrain;

View file

@ -435,100 +435,99 @@ void P_ReadSectorSpecials()
lastlump = 0; lastlump = 0;
while ((lump = Wads.FindLump ("SECTORX", &lastlump)) != -1) while ((lump = Wads.FindLump ("SECTORX", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "SECTORX"); FScanner sc(lump, "SECTORX");
SC_SetCMode(true); sc.SetCMode(true);
while (SC_GetString()) while (sc.GetString())
{ {
if (SC_Compare("IFDOOM")) if (sc.Compare("IFDOOM"))
{ {
SC_MustGetStringName("{"); sc.MustGetStringName("{");
if (gameinfo.gametype != GAME_Doom) if (gameinfo.gametype != GAME_Doom)
{ {
do do
{ {
if (!SC_GetString()) if (!sc.GetString())
{ {
SC_ScriptError("Unexpected end of file"); sc.ScriptError("Unexpected end of file");
} }
} }
while (!SC_Compare("}")); while (!sc.Compare("}"));
} }
} }
else if (SC_Compare("IFHERETIC")) else if (sc.Compare("IFHERETIC"))
{ {
SC_MustGetStringName("{"); sc.MustGetStringName("{");
if (gameinfo.gametype != GAME_Heretic) if (gameinfo.gametype != GAME_Heretic)
{ {
do do
{ {
if (!SC_GetString()) if (!sc.GetString())
{ {
SC_ScriptError("Unexpected end of file"); sc.ScriptError("Unexpected end of file");
} }
} }
while (!SC_Compare("}")); while (!sc.Compare("}"));
} }
} }
else if (SC_Compare("IFSTRIFE")) else if (sc.Compare("IFSTRIFE"))
{ {
SC_MustGetStringName("{"); sc.MustGetStringName("{");
if (gameinfo.gametype != GAME_Strife) if (gameinfo.gametype != GAME_Strife)
{ {
do do
{ {
if (!SC_GetString()) if (!sc.GetString())
{ {
SC_ScriptError("Unexpected end of file"); sc.ScriptError("Unexpected end of file");
} }
} }
while (!SC_Compare("}")); while (!sc.Compare("}"));
} }
} }
else if (SC_Compare("}")) else if (sc.Compare("}"))
{ {
// ignore // ignore
} }
else if (SC_Compare("BOOMMASK")) else if (sc.Compare("BOOMMASK"))
{ {
SC_MustGetNumber(); sc.MustGetNumber();
boommask = sc_Number; boommask = sc.Number;
SC_MustGetStringName(","); sc.MustGetStringName(",");
SC_MustGetNumber(); sc.MustGetNumber();
boomshift = sc_Number; boomshift = sc.Number;
} }
else if (SC_Compare("[")) else if (sc.Compare("["))
{ {
int start; int start;
int end; int end;
SC_MustGetNumber(); sc.MustGetNumber();
start = sc_Number; start = sc.Number;
SC_MustGetStringName(","); sc.MustGetStringName(",");
SC_MustGetNumber(); sc.MustGetNumber();
end = sc_Number; end = sc.Number;
SC_MustGetStringName("]"); sc.MustGetStringName("]");
SC_MustGetStringName(":"); sc.MustGetStringName(":");
SC_MustGetNumber(); sc.MustGetNumber();
for(int j=start;j<=end;j++) for(int j = start; j <= end; j++)
{ {
sectortables[!!boommask][j]=sc_Number + j - start; sectortables[!!boommask][j]=sc.Number + j - start;
} }
} }
else if (IsNum(sc_String)) else if (IsNum(sc.String))
{ {
int start; int start;
start = atoi(sc_String); start = atoi(sc.String);
SC_MustGetStringName(":"); sc.MustGetStringName(":");
SC_MustGetNumber(); sc.MustGetNumber();
sectortables[!!boommask][start]=sc_Number; sectortables[!!boommask][start] = sc.Number;
} }
else else
{ {
SC_ScriptError(NULL); sc.ScriptError(NULL);
} }
} }
SC_Close ();
} }
} }

View file

@ -92,11 +92,11 @@ public:
static void R_InitAnimDefs (); static void R_InitAnimDefs ();
static void R_AddComplexAnim (int picnum, const TArray<FAnimDef::FAnimFrame> &frames); static void R_AddComplexAnim (int picnum, const TArray<FAnimDef::FAnimFrame> &frames);
static void ParseAnim (bool istex); static void ParseAnim (FScanner &sc, bool istex);
static void ParseRangeAnim (int picnum, int usetype, bool missing); static void ParseRangeAnim (FScanner &sc, int picnum, int usetype, bool missing);
static void ParsePicAnim (int picnum, int usetype, bool missing, TArray<FAnimDef::FAnimFrame> &frames); static void ParsePicAnim (FScanner &sc, int picnum, int usetype, bool missing, TArray<FAnimDef::FAnimFrame> &frames);
static int ParseFramenum (int basepicnum, int usetype, bool allowMissing); static int ParseFramenum (FScanner &sc, int basepicnum, int usetype, bool allowMissing);
static void ParseTime (DWORD &min, DWORD &max); static void ParseTime (FScanner &sc, DWORD &min, DWORD &max);
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -255,43 +255,43 @@ static void R_InitAnimDefs ()
while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1) while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "ANIMDEFS"); FScanner sc(lump, "ANIMDEFS");
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("flat")) if (sc.Compare ("flat"))
{ {
ParseAnim (false); ParseAnim (sc, false);
} }
else if (SC_Compare ("texture")) else if (sc.Compare ("texture"))
{ {
ParseAnim (true); ParseAnim (sc, true);
} }
else if (SC_Compare ("switch")) else if (sc.Compare ("switch"))
{ {
P_ProcessSwitchDef (); P_ProcessSwitchDef (sc);
} }
// [GRB] Added warping type 2 // [GRB] Added warping type 2
else if (SC_Compare ("warp") || SC_Compare ("warp2")) else if (sc.Compare ("warp") || sc.Compare ("warp2"))
{ {
bool isflat = false; bool isflat = false;
bool type2 = SC_Compare ("warp2"); // [GRB] bool type2 = sc.Compare ("warp2"); // [GRB]
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("flat")) if (sc.Compare ("flat"))
{ {
isflat = true; isflat = true;
SC_MustGetString (); sc.MustGetString ();
} }
else if (SC_Compare ("texture")) else if (sc.Compare ("texture"))
{ {
isflat = false; isflat = false;
SC_MustGetString (); sc.MustGetString ();
} }
else else
{ {
SC_ScriptError (NULL); sc.ScriptError (NULL);
} }
int picnum = TexMan.CheckForTexture (sc_String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); int picnum = TexMan.CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags);
if (picnum != -1) if (picnum != -1)
{ {
FTexture * warper = TexMan[picnum]; FTexture * warper = TexMan[picnum];
@ -310,31 +310,31 @@ static void R_InitAnimDefs ()
// Warping information is taken from the last warp // Warping information is taken from the last warp
// definition for this texture. // definition for this texture.
warper->bNoDecals = true; warper->bNoDecals = true;
if (SC_GetString ()) if (sc.GetString ())
{ {
if (SC_Compare ("allowdecals")) if (sc.Compare ("allowdecals"))
{ {
warper->bNoDecals = false; warper->bNoDecals = false;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
} }
} }
} }
} }
else if (SC_Compare ("cameratexture")) else if (sc.Compare ("cameratexture"))
{ {
int width, height; int width, height;
int fitwidth, fitheight; int fitwidth, fitheight;
FString picname; FString picname;
SC_MustGetString (); sc.MustGetString ();
picname = sc_String; picname = sc.String;
SC_MustGetNumber (); sc.MustGetNumber ();
width = sc_Number; width = sc.Number;
SC_MustGetNumber (); sc.MustGetNumber ();
height = sc_Number; height = sc.Number;
int picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Flat, texflags); int picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Flat, texflags);
FTexture *viewer = new FCanvasTexture (picname, width, height); FTexture *viewer = new FCanvasTexture (picname, width, height);
if (picnum != -1) if (picnum != -1)
@ -353,32 +353,31 @@ static void R_InitAnimDefs ()
viewer->UseType = FTexture::TEX_Wall; viewer->UseType = FTexture::TEX_Wall;
TexMan.AddTexture (viewer); TexMan.AddTexture (viewer);
} }
if (SC_GetString()) if (sc.GetString())
{ {
if (SC_Compare ("fit")) if (sc.Compare ("fit"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
fitwidth = sc_Number; fitwidth = sc.Number;
SC_MustGetNumber (); sc.MustGetNumber ();
fitheight = sc_Number; fitheight = sc.Number;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
} }
} }
viewer->SetScaledSize(fitwidth, fitheight); viewer->SetScaledSize(fitwidth, fitheight);
} }
else if (SC_Compare ("animatedDoor")) else if (sc.Compare ("animatedDoor"))
{ {
P_ParseAnimatedDoor (); P_ParseAnimatedDoor (sc);
} }
else else
{ {
SC_ScriptError (NULL); sc.ScriptError (NULL);
} }
} }
SC_Close ();
} }
} }
@ -391,7 +390,7 @@ static void R_InitAnimDefs ()
// //
//========================================================================== //==========================================================================
static void ParseAnim (bool istex) static void ParseAnim (FScanner &sc, bool istex)
{ {
const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
TArray<FAnimDef::FAnimFrame> frames (32); TArray<FAnimDef::FAnimFrame> frames (32);
@ -402,13 +401,13 @@ static void ParseAnim (bool istex)
usetype = istex ? FTexture::TEX_Wall : FTexture::TEX_Flat; usetype = istex ? FTexture::TEX_Wall : FTexture::TEX_Flat;
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("optional")) if (sc.Compare ("optional"))
{ {
optional = true; optional = true;
SC_MustGetString (); sc.MustGetString ();
} }
picnum = TexMan.CheckForTexture (sc_String, usetype, texflags); picnum = TexMan.CheckForTexture (sc.String, usetype, texflags);
if (picnum < 0) if (picnum < 0)
{ {
@ -418,7 +417,7 @@ static void ParseAnim (bool istex)
} }
else else
{ {
Printf (PRINT_BOLD, "ANIMDEFS: Can't find %s\n", sc_String); Printf (PRINT_BOLD, "ANIMDEFS: Can't find %s\n", sc.String);
} }
} }
@ -428,9 +427,9 @@ static void ParseAnim (bool istex)
TexMan[picnum]->bNoDecals = true; TexMan[picnum]->bNoDecals = true;
} }
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("allowdecals")) if (sc.Compare ("allowdecals"))
{ {
if (picnum >= 0) if (picnum >= 0)
{ {
@ -438,31 +437,31 @@ static void ParseAnim (bool istex)
} }
continue; continue;
} }
else if (SC_Compare ("range")) else if (sc.Compare ("range"))
{ {
if (defined == 2) if (defined == 2)
{ {
SC_ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation.");
} }
if (defined == 1) if (defined == 1)
{ {
SC_ScriptError ("You can only use one \"range\" per animation."); sc.ScriptError ("You can only use one \"range\" per animation.");
} }
defined = 1; defined = 1;
ParseRangeAnim (picnum, usetype, missing); ParseRangeAnim (sc, picnum, usetype, missing);
} }
else if (SC_Compare ("pic")) else if (sc.Compare ("pic"))
{ {
if (defined == 1) if (defined == 1)
{ {
SC_ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation.");
} }
defined = 2; defined = 2;
ParsePicAnim (picnum, usetype, missing, frames); ParsePicAnim (sc, picnum, usetype, missing, frames);
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
break; break;
} }
} }
@ -473,7 +472,7 @@ static void ParseAnim (bool istex)
{ {
if (frames.Size() < 2) if (frames.Size() < 2)
{ {
SC_ScriptError ("Animation needs at least 2 frames"); sc.ScriptError ("Animation needs at least 2 frames");
} }
R_AddComplexAnim (picnum, frames); R_AddComplexAnim (picnum, frames);
} }
@ -488,14 +487,14 @@ static void ParseAnim (bool istex)
// //
//========================================================================== //==========================================================================
static void ParseRangeAnim (int picnum, int usetype, bool missing) static void ParseRangeAnim (FScanner &sc, int picnum, int usetype, bool missing)
{ {
int type, framenum; int type, framenum;
DWORD min, max; DWORD min, max;
type = FAnimDef::ANIM_Forward; type = FAnimDef::ANIM_Forward;
framenum = ParseFramenum (picnum, usetype, missing); framenum = ParseFramenum (sc, picnum, usetype, missing);
ParseTime (min, max); ParseTime (sc, min, max);
if (framenum == picnum || picnum < 0) if (framenum == picnum || picnum < 0)
{ {
@ -507,15 +506,15 @@ static void ParseRangeAnim (int picnum, int usetype, bool missing)
TexMan[framenum]->bNoDecals = TexMan[picnum]->bNoDecals; TexMan[framenum]->bNoDecals = TexMan[picnum]->bNoDecals;
swap (framenum, picnum); swap (framenum, picnum);
} }
if (SC_GetString()) if (sc.GetString())
{ {
if (SC_Compare ("Oscillate")) if (sc.Compare ("Oscillate"))
{ {
type = type == FAnimDef::ANIM_Forward ? FAnimDef::ANIM_OscillateUp : FAnimDef::ANIM_OscillateDown; type = type == FAnimDef::ANIM_Forward ? FAnimDef::ANIM_OscillateUp : FAnimDef::ANIM_OscillateDown;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
} }
} }
R_AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min); R_AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min);
@ -529,13 +528,13 @@ static void ParseRangeAnim (int picnum, int usetype, bool missing)
// //
//========================================================================== //==========================================================================
static void ParsePicAnim (int picnum, int usetype, bool missing, TArray<FAnimDef::FAnimFrame> &frames) static void ParsePicAnim (FScanner &sc, int picnum, int usetype, bool missing, TArray<FAnimDef::FAnimFrame> &frames)
{ {
int framenum; int framenum;
DWORD min, max; DWORD min, max;
framenum = ParseFramenum (picnum, usetype, missing); framenum = ParseFramenum (sc, picnum, usetype, missing);
ParseTime (min, max); ParseTime (sc, min, max);
if (picnum >= 0) if (picnum >= 0)
{ {
@ -557,22 +556,22 @@ static void ParsePicAnim (int picnum, int usetype, bool missing, TArray<FAnimDef
// //
//========================================================================== //==========================================================================
static int ParseFramenum (int basepicnum, int usetype, bool allowMissing) static int ParseFramenum (FScanner &sc, int basepicnum, int usetype, bool allowMissing)
{ {
const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny;
int framenum; int framenum;
SC_MustGetString (); sc.MustGetString ();
if (IsNum (sc_String)) if (IsNum (sc.String))
{ {
framenum = basepicnum + atoi(sc_String) - 1; framenum = basepicnum + atoi(sc.String) - 1;
} }
else else
{ {
framenum = TexMan.CheckForTexture (sc_String, usetype, texflags); framenum = TexMan.CheckForTexture (sc.String, usetype, texflags);
if (framenum < 0 && !allowMissing) if (framenum < 0 && !allowMissing)
{ {
SC_ScriptError ("Unknown texture %s", sc_String); sc.ScriptError ("Unknown texture %s", sc.String);
} }
} }
return framenum; return framenum;
@ -586,24 +585,24 @@ static int ParseFramenum (int basepicnum, int usetype, bool allowMissing)
// //
//========================================================================== //==========================================================================
static void ParseTime (DWORD &min, DWORD &max) static void ParseTime (FScanner &sc, DWORD &min, DWORD &max)
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("tics")) if (sc.Compare ("tics"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
min = max = DWORD(sc_Float * 1000 / 35); min = max = DWORD(sc.Float * 1000 / 35);
} }
else if (SC_Compare ("rand")) else if (sc.Compare ("rand"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
min = DWORD(sc_Float * 1000 / 35); min = DWORD(sc.Float * 1000 / 35);
SC_MustGetFloat (); sc.MustGetFloat ();
max = DWORD(sc_Float * 1000 / 35); max = DWORD(sc.Float * 1000 / 35);
} }
else else
{ {
SC_ScriptError ("Must specify a duration for animation frame"); sc.ScriptError ("Must specify a duration for animation frame");
} }
} }

144
src/r_blend.h Normal file
View file

@ -0,0 +1,144 @@
/*
** r_blend.h
** Constants and types for specifying texture blending.
**
**---------------------------------------------------------------------------
** Copyright 2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// Legacy render styles
enum ERenderStyle
{
STYLE_None, // Do not draw
STYLE_Normal, // Normal; just copy the image to the screen
STYLE_Fuzzy, // Draw silhouette using "fuzz" effect
STYLE_SoulTrans, // Draw translucent with amount in r_transsouls
STYLE_OptFuzzy, // Draw as fuzzy or translucent, based on user preference
STYLE_Stencil, // Fill image interior with alphacolor
STYLE_Translucent, // Draw translucent
STYLE_Add, // Draw additive
STYLE_Shaded, // Treat patch data as alpha values for alphacolor
STYLE_TranslucentStencil,
STYLE_Count
};
// Flexible render styles (most possible combinations are supported in software)
enum ERenderOp
{
STYLEOP_None, // Do not draw
STYLEOP_Add, // Add source to destination
STYLEOP_Sub, // Subtract source from destination
STYLEOP_RevSub, // Subtract destination from source
STYLEOP_Fuzz, // Draw fuzzy on top of destination - ignores alpha and color
STYLEOP_FuzzOrAdd, // Draw fuzzy or add, based on user preference
STYLEOP_FuzzOrSub, // Draw fuzzy or subtract, based on user preference
STYLEOP_FuzzOrRevSub, // Draw fuzzy or reverse subtract, based on user preference
};
enum ERenderAlpha
{
STYLEALPHA_Zero, // Blend factor is 0.0
STYLEALPHA_One, // Blend factor is 1.0
STYLEALPHA_Src, // Blend factor is alpha
STYLEALPHA_InvSrc, // Blend factor is 1.0 - alpha
};
enum ERenderFlags
{
// Use value of transsouls as alpha.
STYLEF_TransSoulsAlpha = 1,
// Force alpha to 1. Not the same as STYLEALPHA_One, since that also
// ignores alpha from the texture.
STYLEF_Alpha1 = 2,
// Use red component from grayscale/RGB texture as alpha. If the texture
// is paletted, the palette is ignored and it is treated as grayscale.
// This should generally be combined with STYLEF_ColorIsFixed, since that's
// all the software renderer supports, but hardware acceleration can do
// them separately should you want to do that for some reason.
STYLEF_RedIsAlpha = 4,
// Ignore texture for RGB output. Color comes from fillcolor for actors
// or DTA_FillColor for DrawTexture().
STYLEF_ColorIsFixed = 8,
// Invert source color, either the texture color or the fixed color.
STYLEF_InvertSource = 16,
// Invert overlay color. This is the fade for actors and DTA_ColorOverlay
// for DrawTexture().
STYLEF_InvertOverlay = 32,
// Actors only: Ignore sector fade and fade to black. To fade to white,
// combine this with STYLEF_InvertOverlay.
STYLEF_FadeToBlack = 64,
};
union FRenderStyle
{
struct
{
BYTE BlendOp; // Of ERenderOp type
BYTE SrcAlpha; // Of ERenderAlpha type
BYTE DestAlpha; // Of ERenderAlpha type
BYTE Flags;
};
DWORD AsDWORD;
inline FRenderStyle &operator= (ERenderStyle legacy);
operator DWORD() const { return AsDWORD; }
bool operator==(const FRenderStyle &o) const { return AsDWORD == o.AsDWORD; }
bool IsVisible(fixed_t alpha) const throw();
private:
// Code that compares an actor's render style with a legacy render
// style value should be updated. Making these conversion operators
// private will catch those cases.
operator ERenderStyle() const { return STYLE_Normal; }
operator int() const { return STYLE_Normal; }
};
extern const FRenderStyle LegacyRenderStyles[STYLE_Count];
inline FRenderStyle &FRenderStyle::operator= (ERenderStyle legacy)
{
if (legacy < STYLE_None || legacy >= STYLE_Count)
{
legacy = STYLE_None;
}
*this = LegacyRenderStyles[legacy];
return *this;
}
inline FArchive &operator<< (FArchive &arc, FRenderStyle &style)
{
arc << style.BlendOp << style.SrcAlpha << style.DestAlpha << style.Flags;
return arc;
}

View file

@ -979,7 +979,7 @@ static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static
void R_GetExtraLight (int *light, const secplane_t &plane, FExtraLight *el) void R_GetExtraLight (int *light, const secplane_t &plane, FExtraLight *el)
{ {
BYTE *floodcolormap; FDynamicColormap *floodcolormap;
int floodlight; int floodlight;
bool flooding; bool flooding;
vertex_t **triangle; vertex_t **triangle;
@ -1020,7 +1020,7 @@ void R_GetExtraLight (int *light, const secplane_t &plane, FExtraLight *el)
} }
else else
{ {
basecolormap = el->Lights[i].Master->ColorMap->Maps; basecolormap = el->Lights[i].Master->ColorMap;
*light = el->Lights[i].Master->lightlevel; *light = el->Lights[i].Master->lightlevel;
if (el->Lights[i].bFlooder) if (el->Lights[i].bFlooder)
{ {
@ -1060,13 +1060,13 @@ void R_Subsector (subsector_t *sub)
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false); // killough 4/11/98 &ceilinglightlevel, false); // killough 4/11/98
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
R_GetExtraLight (&ceilinglightlevel, frontsector->ceilingplane, frontsector->ExtraLights); R_GetExtraLight (&ceilinglightlevel, frontsector->ceilingplane, frontsector->ExtraLights);
// [RH] set foggy flag // [RH] set foggy flag
foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE); foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE);
r_actualextralight = foggy ? 0 : extralight << 4; r_actualextralight = foggy ? 0 : extralight << 4;
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
ceilingplane = frontsector->ceilingplane.ZatPoint (viewx, viewy) > viewz || ceilingplane = frontsector->ceilingplane.ZatPoint (viewx, viewy) > viewz ||
frontsector->ceilingpic == skyflatnum || frontsector->ceilingpic == skyflatnum ||
(frontsector->CeilingSkyBox != NULL && frontsector->CeilingSkyBox->bAlways) || (frontsector->CeilingSkyBox != NULL && frontsector->CeilingSkyBox->bAlways) ||
@ -1086,7 +1086,7 @@ void R_Subsector (subsector_t *sub)
frontsector->CeilingSkyBox frontsector->CeilingSkyBox
) : NULL; ) : NULL;
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
R_GetExtraLight (&floorlightlevel, frontsector->floorplane, frontsector->ExtraLights); R_GetExtraLight (&floorlightlevel, frontsector->floorplane, frontsector->ExtraLights);
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/7/98: Add (x,y) offsets to flats, add deep water check

View file

@ -425,38 +425,38 @@ void FTextureManager::LoadHiresTex()
while ((remapLump = Wads.FindLump("HIRESTEX", &lastLump)) != -1) while ((remapLump = Wads.FindLump("HIRESTEX", &lastLump)) != -1)
{ {
SC_OpenLumpNum(remapLump, "HIRESTEX"); FScanner sc(remapLump, "HIRESTEX");
while (SC_GetString()) while (sc.GetString())
{ {
if (SC_Compare("remap")) // remap an existing texture if (sc.Compare("remap")) // remap an existing texture
{ {
SC_MustGetString(); sc.MustGetString();
// allow selection by type // allow selection by type
if (SC_Compare("wall")) type=FTexture::TEX_Wall, mode=FTextureManager::TEXMAN_Overridable; if (sc.Compare("wall")) type=FTexture::TEX_Wall, mode=FTextureManager::TEXMAN_Overridable;
else if (SC_Compare("flat")) type=FTexture::TEX_Flat, mode=FTextureManager::TEXMAN_Overridable; else if (sc.Compare("flat")) type=FTexture::TEX_Flat, mode=FTextureManager::TEXMAN_Overridable;
else if (SC_Compare("sprite")) type=FTexture::TEX_Sprite, mode=0; else if (sc.Compare("sprite")) type=FTexture::TEX_Sprite, mode=0;
else type = FTexture::TEX_Any, mode = 0; else type = FTexture::TEX_Any, mode = 0;
sc_String[8]=0; sc.String[8]=0;
tlist.Clear(); tlist.Clear();
int amount = ListTextures(sc_String, tlist); int amount = ListTextures(sc.String, tlist);
if (amount == 0) if (amount == 0)
{ {
int oldtex = AddPatch(sc_String); int oldtex = AddPatch(sc.String);
if (oldtex >= 0) tlist.Push(oldtex); if (oldtex >= 0) tlist.Push(oldtex);
} }
FName texname = sc_String; FName texname = sc.String;
SC_MustGetString(); sc.MustGetString();
int lumpnum = Wads.CheckNumForFullName(sc_String); int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc_String, ns_graphics); if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
if (tlist.Size() == 0) if (tlist.Size() == 0)
{ {
Printf("Attempting to remap non-existent texture %s to %s\n", Printf("Attempting to remap non-existent texture %s to %s\n",
texname.GetChars(), sc_String); texname.GetChars(), sc.String);
} }
else else
{ {
@ -487,22 +487,22 @@ void FTextureManager::LoadHiresTex()
} }
} }
} }
else if (SC_Compare("define")) // define a new "fake" texture else if (sc.Compare("define")) // define a new "fake" texture
{ {
SC_GetString(); sc.GetString();
memcpy(src, sc_String, 8); memcpy(src, sc.String, 8);
int lumpnum = Wads.CheckNumForFullName(sc_String); int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc_String, ns_graphics); if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
SC_GetString(); sc.GetString();
is32bit = !!SC_Compare("force32bit"); is32bit = !!sc.Compare("force32bit");
if (!is32bit) SC_UnGet(); if (!is32bit) sc.UnGet();
SC_GetNumber(); sc.GetNumber();
width = sc_Number; width = sc.Number;
SC_GetNumber(); sc.GetNumber();
height = sc_Number; height = sc.Number;
if (lumpnum>=0) if (lumpnum>=0)
{ {
@ -523,7 +523,6 @@ void FTextureManager::LoadHiresTex()
//else Printf("Unable to define hires texture '%s'\n", tex->Name); //else Printf("Unable to define hires texture '%s'\n", tex->Name);
} }
} }
SC_Close();
} }
} }

View file

@ -860,7 +860,7 @@ struct vissprite_t
fixed_t xiscale; // negative if flipped fixed_t xiscale; // negative if flipped
fixed_t idepth; // 1/z fixed_t idepth; // 1/z
fixed_t texturemid; fixed_t texturemid;
DWORD AlphaColor; DWORD FillColor;
lighttable_t *colormap; lighttable_t *colormap;
sector_t *heightsec; // killough 3/27/98: height sector for underwater/fake ceiling sector_t *heightsec; // killough 3/27/98: height sector for underwater/fake ceiling
sector_t *sector; // [RH] sector this sprite is in sector_t *sector; // [RH] sector this sprite is in
@ -869,7 +869,7 @@ struct vissprite_t
FTexture *pic; FTexture *pic;
short renderflags; short renderflags;
DWORD Translation; // [RH] for color translation DWORD Translation; // [RH] for color translation
BYTE RenderStyle; FRenderStyle RenderStyle;
BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on
BYTE bSplitSprite; // [RH] Sprite was split by a drawseg BYTE bSplitSprite; // [RH] Sprite was split by a drawseg
}; };

View file

@ -111,6 +111,7 @@ fixed_t dc_iscale;
fixed_t dc_texturemid; fixed_t dc_texturemid;
fixed_t dc_texturefrac; fixed_t dc_texturefrac;
int dc_color; // [RH] Color for column filler int dc_color; // [RH] Color for column filler
DWORD dc_srccolor;
DWORD *dc_srcblend; // [RH] Source and destination DWORD *dc_srcblend; // [RH] Source and destination
DWORD *dc_destblend; // blending lookups DWORD *dc_destblend; // blending lookups
@ -134,6 +135,23 @@ cycle_t DetailDoubleCycles;
int dc_fillcolor; int dc_fillcolor;
BYTE *dc_translation; BYTE *dc_translation;
BYTE shadetables[NUMCOLORMAPS*16*256]; BYTE shadetables[NUMCOLORMAPS*16*256];
FDynamicColormap ShadeFakeColormap[16];
BYTE identitymap[256];
// Convert legacy render styles to flexible render styles.
const FRenderStyle LegacyRenderStyles[STYLE_Count] =
{
/* STYLE_None */ {{ STYLEOP_None, }},
/* STYLE_Normal */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }},
/* STYLE_Fuzzy */ {{ STYLEOP_Fuzz, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 }},
/* STYLE_SoulTrans */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_TransSoulsAlpha }},
/* STYLE_OptFuzzy */ {{ STYLEOP_FuzzOrAdd, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }},
/* STYLE_Stencil */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 | STYLEF_ColorIsFixed }},
/* STYLE_Translucent */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }},
/* STYLE_Add */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 }},
/* STYLE_Shaded */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed }},
/* STYLE_TranslucentStencil */{{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed }},
};
/************************************/ /************************************/
/* */ /* */
@ -233,7 +251,7 @@ void R_FillAddColumn (void)
DWORD fg; DWORD fg;
bg2rgb = dc_destblend; bg2rgb = dc_destblend;
fg = dc_srcblend[dc_color]; fg = dc_srccolor;
int pitch = dc_pitch; int pitch = dc_pitch;
do do
@ -246,6 +264,103 @@ void R_FillAddColumn (void)
} }
void R_FillAddClampColumn (void)
{
int count;
BYTE *dest;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
DWORD *bg2rgb;
DWORD fg;
bg2rgb = dc_destblend;
fg = dc_srccolor;
int pitch = dc_pitch;
do
{
DWORD a = fg + bg2rgb[*dest];
DWORD b = a;
a |= 0x01f07c1f;
b &= 0x40100400;
a &= 0x3fffffff;
b = b - (b >> 5);
a |= b;
*dest = RGB32k[0][0][a & (a>>15)];
dest += pitch;
} while (--count);
}
void R_FillSubClampColumn (void)
{
int count;
BYTE *dest;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
DWORD *bg2rgb;
DWORD fg;
bg2rgb = dc_destblend;
fg = dc_srccolor | 0x40100400;
int pitch = dc_pitch;
do
{
DWORD a = fg - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
dest += pitch;
} while (--count);
}
void R_FillRevSubClampColumn (void)
{
int count;
BYTE *dest;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
DWORD *bg2rgb;
DWORD fg;
bg2rgb = dc_destblend;
fg = dc_srccolor;
int pitch = dc_pitch;
do
{
DWORD a = (bg2rgb[*dest] | 0x40100400) - fg;
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
dest += pitch;
} while (--count);
}
// //
// Spectre/Invisibility. // Spectre/Invisibility.
// //
@ -593,8 +708,7 @@ void R_DrawAddClampColumnP_C ()
do do
{ {
DWORD a = fg2rgb[colormap[source[frac>>FRACBITS]]] DWORD a = fg2rgb[colormap[source[frac>>FRACBITS]]] + bg2rgb[*dest];
+ bg2rgb[*dest];
DWORD b = a; DWORD b = a;
a |= 0x01f07c1f; a |= 0x01f07c1f;
@ -609,7 +723,7 @@ void R_DrawAddClampColumnP_C ()
} }
} }
// Add source to destination, clamping it to white // Add translated source to destination, clamping it to white
void R_DrawAddClampTranslatedColumnP_C () void R_DrawAddClampTranslatedColumnP_C ()
{ {
int count; int count;
@ -636,8 +750,7 @@ void R_DrawAddClampTranslatedColumnP_C ()
do do
{ {
DWORD a = fg2rgb[colormap[translation[source[frac>>FRACBITS]]]] DWORD a = fg2rgb[colormap[translation[source[frac>>FRACBITS]]]] + bg2rgb[*dest];
+ bg2rgb[*dest];
DWORD b = a; DWORD b = a;
a |= 0x01f07c1f; a |= 0x01f07c1f;
@ -652,6 +765,168 @@ void R_DrawAddClampTranslatedColumnP_C ()
} }
} }
// Subtract destination from source, clamping it to black
void R_DrawSubClampColumnP_C ()
{
int count;
BYTE *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
fracstep = dc_iscale;
frac = dc_texturefrac;
{
BYTE *colormap = dc_colormap;
const BYTE *source = dc_source;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
DWORD a = (fg2rgb[colormap[source[frac>>FRACBITS]]] | 0x40100400) - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
dest += pitch;
frac += fracstep;
} while (--count);
}
}
// Subtract destination from source, clamping it to black
void R_DrawSubClampTranslatedColumnP_C ()
{
int count;
BYTE *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
fracstep = dc_iscale;
frac = dc_texturefrac;
{
BYTE *translation = dc_translation;
BYTE *colormap = dc_colormap;
const BYTE *source = dc_source;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
DWORD a = (fg2rgb[colormap[translation[source[frac>>FRACBITS]]]] | 0x40100400) - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
dest += pitch;
frac += fracstep;
} while (--count);
}
}
// Subtract source from destination, clamping it to black
void R_DrawRevSubClampColumnP_C ()
{
int count;
BYTE *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
fracstep = dc_iscale;
frac = dc_texturefrac;
{
BYTE *colormap = dc_colormap;
const BYTE *source = dc_source;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
DWORD a = (bg2rgb[*dest] | 0x40100400) - fg2rgb[colormap[source[frac>>FRACBITS]]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
dest += pitch;
frac += fracstep;
} while (--count);
}
}
// Subtract source from destination, clamping it to black
void R_DrawRevSubClampTranslatedColumnP_C ()
{
int count;
BYTE *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_count;
if (count <= 0)
return;
dest = dc_dest;
fracstep = dc_iscale;
frac = dc_texturefrac;
{
BYTE *translation = dc_translation;
BYTE *colormap = dc_colormap;
const BYTE *source = dc_source;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
DWORD a = (bg2rgb[*dest] | 0x40100400) - fg2rgb[colormap[translation[source[frac>>FRACBITS]]]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
dest += pitch;
frac += fracstep;
} while (--count);
}
}
// //
@ -1198,13 +1473,14 @@ void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip)
int b2 = dclip[x]; int b2 = dclip[x];
int rcolormap = GETPALOOKUP (light, wallshade); int rcolormap = GETPALOOKUP (light, wallshade);
int lcolormap; int lcolormap;
BYTE *basecolormapdata = basecolormap->Maps;
if (b2 > t2) if (b2 > t2)
{ {
clearbufshort (spanend+t2, b2-t2, x); clearbufshort (spanend+t2, b2-t2, x);
} }
dc_colormap = basecolormap + (rcolormap << COLORMAPSHIFT); dc_colormap = basecolormapdata + (rcolormap << COLORMAPSHIFT);
for (--x; x >= x1; --x) for (--x; x >= x1; --x)
{ {
@ -1229,11 +1505,11 @@ void R_DrawFogBoundary (int x1, int x2, short *uclip, short *dclip)
clearbufshort (spanend+t2, b2-t2, x); clearbufshort (spanend+t2, b2-t2, x);
} }
rcolormap = lcolormap; rcolormap = lcolormap;
dc_colormap = basecolormap + (lcolormap << COLORMAPSHIFT); dc_colormap = basecolormapdata + (lcolormap << COLORMAPSHIFT);
} }
else else
{ {
if (dc_colormap != basecolormap) if (dc_colormap != basecolormapdata)
{ {
stop = MIN (t1, b2); stop = MIN (t1, b2);
while (t2 < stop) while (t2 < stop)
@ -1406,6 +1682,137 @@ void tmvline4_addclamp ()
} while (--count); } while (--count);
} }
fixed_t tmvline1_subclamp ()
{
DWORD fracstep = dc_iscale;
DWORD frac = dc_texturefrac;
BYTE *colormap = dc_colormap;
int count = dc_count;
const BYTE *source = dc_source;
BYTE *dest = dc_dest;
int bits = tmvlinebits;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
BYTE pix = source[frac>>bits];
if (pix != 0)
{
DWORD a = (fg2rgb[colormap[pix]] | 0x40100400) - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
}
frac += fracstep;
dest += pitch;
} while (--count);
return frac;
}
void tmvline4_subclamp ()
{
BYTE *dest = dc_dest;
int count = dc_count;
int bits = tmvlinebits;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
for (int i = 0; i < 4; ++i)
{
BYTE pix = bufplce[i][vplce[i] >> bits];
if (pix != 0)
{
DWORD a = (fg2rgb[palookupoffse[i][pix]] | 0x40100400) - bg2rgb[dest[i]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[i] = RGB32k[0][0][a & (a>>15)];
}
vplce[i] += vince[i];
}
dest += dc_pitch;
} while (--count);
}
fixed_t tmvline1_revsubclamp ()
{
DWORD fracstep = dc_iscale;
DWORD frac = dc_texturefrac;
BYTE *colormap = dc_colormap;
int count = dc_count;
const BYTE *source = dc_source;
BYTE *dest = dc_dest;
int bits = tmvlinebits;
int pitch = dc_pitch;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
BYTE pix = source[frac>>bits];
if (pix != 0)
{
DWORD a = (bg2rgb[*dest] | 0x40100400) - fg2rgb[colormap[pix]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][a & (a>>15)];
}
frac += fracstep;
dest += pitch;
} while (--count);
return frac;
}
void tmvline4_revsubclamp ()
{
BYTE *dest = dc_dest;
int count = dc_count;
int bits = tmvlinebits;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
do
{
for (int i = 0; i < 4; ++i)
{
BYTE pix = bufplce[i][vplce[i] >> bits];
if (pix != 0)
{
DWORD a = (bg2rgb[dest[i]] | 0x40100400) - fg2rgb[palookupoffse[i][pix]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[i] = RGB32k[0][0][a & (a>>15)];
}
vplce[i] += vince[i];
}
dest += dc_pitch;
} while (--count);
}
void R_DrawBorder (int x1, int y1, int x2, int y2) void R_DrawBorder (int x1, int y1, int x2, int y2)
@ -1655,21 +2062,15 @@ EXTERN_CVAR (Bool, r_drawfuzz)
EXTERN_CVAR (Float, transsouls) EXTERN_CVAR (Float, transsouls)
CVAR (Bool, r_drawtrans, true, 0) CVAR (Bool, r_drawtrans, true, 0)
static BYTE *basecolormapsave; static FDynamicColormap *basecolormapsave;
// Convenience macros, to make the following look more like OpenGL/Direct3D static bool R_SetBlendFunc (int op, fixed_t fglevel, fixed_t bglevel, int flags)
#define BL_ONE FRACUNIT
#define BL_ZERO 0
#define BL_SRC_ALPHA alpha
#define BL_INV_SRC_ALPHA (BL_ONE-alpha)
static bool stencilling;
static bool R_SetBlendFunc (fixed_t fglevel, fixed_t bglevel)
{ {
if (!r_drawtrans || (fglevel == BL_ONE && bglevel == BL_ZERO)) // r_drawtrans is a seriously bad thing to turn off. I wonder if I should
// just remove it completely.
if (!r_drawtrans || (op == STYLEOP_Add && fglevel == FRACUNIT && bglevel == 0 && !(flags & STYLEF_InvertSource)))
{ {
if (stencilling) if (flags & STYLEF_ColorIsFixed)
{ {
colfunc = R_FillColumnP; colfunc = R_FillColumnP;
hcolfunc_post1 = rt_copy1col; hcolfunc_post1 = rt_copy1col;
@ -1689,68 +2090,164 @@ static bool R_SetBlendFunc (fixed_t fglevel, fixed_t bglevel)
} }
return true; return true;
} }
if (fglevel == BL_ZERO && bglevel == BL_ONE) if (flags & STYLEF_InvertSource)
{ {
return false; dc_srcblend = Col2RGB8_Inverse[fglevel>>10];
dc_destblend = Col2RGB8_LessPrecision[bglevel>>10];
} }
if (fglevel + bglevel <= BL_ONE) else if (op == STYLEOP_Add && fglevel + bglevel <= FRACUNIT)
{ // Colors won't overflow when added {
dc_srcblend = Col2RGB8[fglevel>>10]; dc_srcblend = Col2RGB8[fglevel>>10];
dc_destblend = Col2RGB8[bglevel>>10]; dc_destblend = Col2RGB8[bglevel>>10];
if (stencilling) }
else
{
dc_srcblend = Col2RGB8_LessPrecision[fglevel>>10];
dc_destblend = Col2RGB8_LessPrecision[bglevel>>10];
}
switch (op)
{
case STYLEOP_Add:
if (fglevel == 0 && bglevel == FRACUNIT)
{ {
colfunc = R_FillAddColumn; return false;
hcolfunc_post1 = rt_add1col; }
hcolfunc_post4 = rt_add4cols; if (fglevel + bglevel <= FRACUNIT)
{ // Colors won't overflow when added
if (flags & STYLEF_ColorIsFixed)
{
colfunc = R_FillAddColumn;
hcolfunc_post1 = rt_add1col;
hcolfunc_post4 = rt_add4cols;
}
else if (dc_translation == NULL)
{
colfunc = R_DrawAddColumnP_C;
hcolfunc_post1 = rt_add1col;
hcolfunc_post4 = rt_add4cols;
}
else
{
colfunc = R_DrawTlatedAddColumnP_C;
hcolfunc_post1 = rt_tlateadd1col;
hcolfunc_post4 = rt_tlateadd4cols;
}
}
else
{ // Colors might overflow when added
if (flags & STYLEF_ColorIsFixed)
{
colfunc = R_FillAddClampColumn;
hcolfunc_post1 = rt_addclamp1col;
hcolfunc_post4 = rt_addclamp4cols;
}
else if (dc_translation == NULL)
{
colfunc = R_DrawAddClampColumnP_C;
hcolfunc_post1 = rt_addclamp1col;
hcolfunc_post4 = rt_addclamp4cols;
}
else
{
colfunc = R_DrawAddClampTranslatedColumnP_C;
hcolfunc_post1 = rt_tlateaddclamp1col;
hcolfunc_post4 = rt_tlateaddclamp4cols;
}
}
return true;
case STYLEOP_Sub:
if (flags & STYLEF_ColorIsFixed)
{
colfunc = R_FillSubClampColumn;
hcolfunc_post1 = rt_subclamp1col;
hcolfunc_post4 = rt_subclamp4cols;
} }
else if (dc_translation == NULL) else if (dc_translation == NULL)
{ {
colfunc = R_DrawAddColumnP_C; colfunc = R_DrawSubClampColumnP_C;
hcolfunc_post1 = rt_add1col; hcolfunc_post1 = rt_subclamp1col;
hcolfunc_post4 = rt_add4cols; hcolfunc_post4 = rt_subclamp4cols;
} }
else else
{ {
colfunc = R_DrawTlatedAddColumnP_C; colfunc = R_DrawSubClampTranslatedColumnP_C;
hcolfunc_post1 = rt_tlateadd1col; hcolfunc_post1 = rt_tlatesubclamp1col;
hcolfunc_post4 = rt_tlateadd4cols; hcolfunc_post4 = rt_tlatesubclamp4cols;
} }
} return true;
else
{ // Colors might overflow when added case STYLEOP_RevSub:
dc_srcblend = Col2RGB8_LessPrecision[fglevel>>10]; if (fglevel == 0 && bglevel == FRACUNIT)
dc_destblend = Col2RGB8_LessPrecision[bglevel>>10];
if (dc_translation == NULL)
{ {
colfunc = R_DrawAddClampColumnP_C; return false;
hcolfunc_post1 = rt_addclamp1col; }
hcolfunc_post4 = rt_addclamp4cols; if (flags & STYLEF_ColorIsFixed)
{
colfunc = R_FillRevSubClampColumn;
hcolfunc_post1 = rt_subclamp1col;
hcolfunc_post4 = rt_subclamp4cols;
}
else if (dc_translation == NULL)
{
colfunc = R_DrawRevSubClampColumnP_C;
hcolfunc_post1 = rt_revsubclamp1col;
hcolfunc_post4 = rt_revsubclamp4cols;
} }
else else
{ {
colfunc = R_DrawAddClampTranslatedColumnP_C; colfunc = R_DrawRevSubClampTranslatedColumnP_C;
hcolfunc_post1 = rt_tlateaddclamp1col; hcolfunc_post1 = rt_tlaterevsubclamp1col;
hcolfunc_post4 = rt_tlateaddclamp4cols; hcolfunc_post4 = rt_tlaterevsubclamp4cols;
} }
return true;
default:
return false;
} }
return true;
} }
ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD color) static fixed_t GetAlpha(int type, fixed_t alpha)
{
switch (type)
{
case STYLEALPHA_Zero: return 0;
case STYLEALPHA_One: return FRACUNIT;
case STYLEALPHA_Src: return alpha;
case STYLEALPHA_InvSrc: return FRACUNIT - alpha;
default: return 0;
}
}
ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color)
{ {
fixed_t fglevel, bglevel; fixed_t fglevel, bglevel;
if (style == STYLE_OptFuzzy) if (style.BlendOp == STYLEOP_FuzzOrAdd)
{ {
style = (r_drawfuzz || !r_drawtrans) ? STYLE_Fuzzy : STYLE_Translucent; style.BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_Add;
} }
else if (style == STYLE_SoulTrans) else if (style.BlendOp == STYLEOP_FuzzOrSub)
{ {
style = STYLE_Translucent; style.BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_Sub;
alpha = (fixed_t)(FRACUNIT * transsouls); }
else if (style.BlendOp == STYLEOP_FuzzOrRevSub)
{
style.BlendOp = (r_drawfuzz || !r_drawtrans) ? STYLEOP_Fuzz : STYLEOP_RevSub;
} }
alpha = clamp<fixed_t> (alpha, 0, FRACUNIT); if (style.Flags & STYLEF_TransSoulsAlpha)
{
alpha = fixed_t(transsouls * FRACUNIT);
}
else if (style.Flags & STYLEF_Alpha1)
{
alpha = FRACUNIT;
}
else
{
alpha = clamp<fixed_t> (alpha, 0, FRACUNIT);
}
dc_translation = NULL; dc_translation = NULL;
if (translation != 0) if (translation != 0)
@ -1762,63 +2259,56 @@ ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD col
} }
} }
basecolormapsave = basecolormap; basecolormapsave = basecolormap;
stencilling = false;
hcolfunc_pre = R_DrawColumnHoriz; hcolfunc_pre = R_DrawColumnHoriz;
switch (style) // Check for special modes
if (style.BlendOp == STYLEOP_Fuzz)
{ {
// Special modes
case STYLE_Fuzzy:
colfunc = fuzzcolfunc; colfunc = fuzzcolfunc;
return DoDraw0; return DoDraw0;
}
case STYLE_Shaded: else if (style == LegacyRenderStyles[STYLE_Shaded])
{
// Shaded drawer only gets 16 levels because it saves memory. // Shaded drawer only gets 16 levels because it saves memory.
if ((alpha >>= 12) == 0) if ((alpha >>= 12) == 0)
return DontDraw; return DontDraw;
colfunc = R_DrawShadedColumn; colfunc = R_DrawShadedColumn;
hcolfunc_post1 = rt_shaded1col; hcolfunc_post1 = rt_shaded1col;
hcolfunc_post4 = rt_shaded4cols; hcolfunc_post4 = rt_shaded4cols;
dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap[APART(color)]; dc_color = fixedcolormap ? fixedcolormap[APART(color)] : basecolormap->Maps[APART(color)];
dc_colormap = basecolormap = &shadetables[((16-alpha)*NUMCOLORMAPS)*256]; dc_colormap = (basecolormap = &ShadeFakeColormap[16-alpha])->Maps;
if (fixedlightlev) if (fixedlightlev && !fixedcolormap)
{ {
dc_colormap += fixedlightlev; dc_colormap += fixedlightlev;
} }
return r_columnmethod ? DoDraw1 : DoDraw0; return r_columnmethod ? DoDraw1 : DoDraw0;
// Standard modes
case STYLE_Stencil:
dc_color = APART(color);
stencilling = true;
case STYLE_Normal:
fglevel = BL_ONE;
bglevel = BL_ZERO;
break;
case STYLE_TranslucentStencil:
dc_color = APART(color);
stencilling = true;
case STYLE_Translucent:
fglevel = BL_SRC_ALPHA;
bglevel = BL_INV_SRC_ALPHA;
break;
case STYLE_Add:
fglevel = BL_SRC_ALPHA;
bglevel = BL_ONE;
break;
default:
return DontDraw;
} }
if (stencilling) fglevel = GetAlpha(style.SrcAlpha, alpha);
bglevel = GetAlpha(style.DestAlpha, alpha);
if (style.Flags & STYLEF_ColorIsFixed)
{ {
int x = fglevel >> 10;
int r = RPART(color);
int g = GPART(color);
int b = BPART(color);
// dc_color is used by the rt_* routines. It is indexed into dc_srcblend.
dc_color = RGB32k[r>>3][g>>3][b>>3];
if (style.Flags & STYLEF_InvertSource)
{
r = 255 - r;
g = 255 - g;
b = 255 - b;
}
// dc_srccolor is used by the R_Fill* routines. It is premultiplied
// with the alpha.
dc_srccolor = ((((r*x)>>4)<<20) | ((g*x)>>4) | ((((b)*x)>>4)<<10)) & 0x3feffbff;
hcolfunc_pre = R_FillColumnHorizP; hcolfunc_pre = R_FillColumnHorizP;
dc_colormap = identitymap;
} }
return R_SetBlendFunc (fglevel, bglevel) ? return R_SetBlendFunc (style.BlendOp, fglevel, bglevel, style.Flags) ?
(r_columnmethod ? DoDraw1 : DoDraw0) : DontDraw; (r_columnmethod ? DoDraw1 : DoDraw0) : DontDraw;
} }
@ -1841,5 +2331,48 @@ bool R_GetTransMaskDrawers (fixed_t (**tmvline1)(), void (**tmvline4)())
*tmvline4 = tmvline4_addclamp; *tmvline4 = tmvline4_addclamp;
return true; return true;
} }
if (colfunc == R_DrawSubClampColumnP_C)
{
*tmvline1 = tmvline1_subclamp;
*tmvline4 = tmvline4_subclamp;
return true;
}
if (colfunc == R_DrawRevSubClampColumnP_C)
{
*tmvline1 = tmvline1_revsubclamp;
*tmvline4 = tmvline4_revsubclamp;
return true;
}
return false; return false;
} }
//==========================================================================
//
// FRenderStyle :: IsVisible
//
// Coupled with the given alpha, will this render style produce something
// visible on-screen?
//
//==========================================================================
bool FRenderStyle::IsVisible(fixed_t alpha) const
{
if (BlendOp == STYLEOP_None)
{
return false;
}
if (BlendOp == STYLEOP_Add || BlendOp == STYLEOP_RevSub)
{
if (Flags & STYLEF_Alpha1)
{
alpha = FRACUNIT;
}
else
{
alpha = clamp(alpha, 0, FRACUNIT);
}
return GetAlpha(SrcAlpha, alpha) != 0 || GetAlpha(DestAlpha, alpha) != FRACUNIT;
}
// Treat anything else as visible.
return true;
}

View file

@ -25,7 +25,6 @@
#include "r_data.h" #include "r_data.h"
extern "C" int ylookup[MAXHEIGHT]; extern "C" int ylookup[MAXHEIGHT];
extern "C" int dc_pitch; // [RH] Distance between rows extern "C" int dc_pitch; // [RH] Distance between rows
@ -38,6 +37,7 @@ extern "C" fixed_t dc_iscale;
extern "C" fixed_t dc_texturemid; extern "C" fixed_t dc_texturemid;
extern "C" fixed_t dc_texturefrac; extern "C" fixed_t dc_texturefrac;
extern "C" int dc_color; // [RH] For flat colors (no texturing) extern "C" int dc_color; // [RH] For flat colors (no texturing)
extern "C" DWORD dc_srccolor;
extern "C" DWORD *dc_srcblend; extern "C" DWORD *dc_srcblend;
extern "C" DWORD *dc_destblend; extern "C" DWORD *dc_destblend;
@ -122,6 +122,14 @@ void rt_addclamp1col (int hx, int sx, int yl, int yh);
void rt_addclamp4cols (int sx, int yl, int yh); void rt_addclamp4cols (int sx, int yl, int yh);
void rt_tlateaddclamp1col (int hx, int sx, int yl, int yh); void rt_tlateaddclamp1col (int hx, int sx, int yl, int yh);
void rt_tlateaddclamp4cols (int sx, int yl, int yh); void rt_tlateaddclamp4cols (int sx, int yl, int yh);
void rt_subclamp1col (int hx, int sx, int yl, int yh);
void rt_subclamp4cols (int sx, int yl, int yh);
void rt_tlatesubclamp1col (int hx, int sx, int yl, int yh);
void rt_tlatesubclamp4cols (int sx, int yl, int yh);
void rt_revsubclamp1col (int hx, int sx, int yl, int yh);
void rt_revsubclamp4cols (int sx, int yl, int yh);
void rt_tlaterevsubclamp1col (int hx, int sx, int yl, int yh);
void rt_tlaterevsubclamp4cols (int sx, int yl, int yh);
extern "C" void rt_copy1col_asm (int hx, int sx, int yl, int yh); extern "C" void rt_copy1col_asm (int hx, int sx, int yl, int yh);
extern "C" void rt_copy4cols_asm (int sx, int yl, int yh); extern "C" void rt_copy4cols_asm (int sx, int yl, int yh);
@ -202,6 +210,8 @@ extern "C" const BYTE* ds_source;
extern "C" int ds_color; // [RH] For flat color (no texturing) extern "C" int ds_color; // [RH] For flat color (no texturing)
extern BYTE shadetables[NUMCOLORMAPS*16*256]; extern BYTE shadetables[NUMCOLORMAPS*16*256];
extern FDynamicColormap ShadeFakeColormap[16];
extern BYTE identitymap[256];
extern BYTE *dc_translation; extern BYTE *dc_translation;
// [RH] Double view pixels by detail mode // [RH] Double view pixels by detail mode
@ -224,7 +234,7 @@ enum ESPSResult
DoDraw0, // draw this as if r_columnmethod is 0 DoDraw0, // draw this as if r_columnmethod is 0
DoDraw1, // draw this as if r_columnmethod is 1 DoDraw1, // draw this as if r_columnmethod is 1
}; };
ESPSResult R_SetPatchStyle (int style, fixed_t alpha, int translation, DWORD color); ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, DWORD color);
// Call this after finished drawing the current thing, in case its // Call this after finished drawing the current thing, in case its
// style was STYLE_Shade // style was STYLE_Shade

View file

@ -773,6 +773,394 @@ void rt_tlateaddclamp4cols (int sx, int yl, int yh)
} while (--count); } while (--count);
} }
// Subtracts one span at hx to the screen at sx with clamping.
void rt_subclamp1col (int hx, int sx, int yl, int yh)
{
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4 + hx];
pitch = dc_pitch;
colormap = dc_colormap;
do {
DWORD a = (fg2rgb[colormap[*source]] | 0x40100400) - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Subtracts all four spans to the screen starting at sx with clamping.
void rt_subclamp4cols (int sx, int yl, int yh)
{
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4];
pitch = dc_pitch;
colormap = dc_colormap;
do {
DWORD a = (fg2rgb[colormap[source[0]]] | 0x40100400) - bg2rgb[dest[0]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[source[1]]] | 0x40100400) - bg2rgb[dest[1]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[source[2]]] | 0x40100400) - bg2rgb[dest[2]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[source[3]]] | 0x40100400) - bg2rgb[dest[3]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Translates and subtracts one span at hx to the screen at sx with clamping.
void rt_tlatesubclamp1col (int hx, int sx, int yl, int yh)
{
BYTE *translation;
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4 + hx];
pitch = dc_pitch;
colormap = dc_colormap;
translation = dc_translation;
do {
DWORD a = (fg2rgb[colormap[translation[*source]]] | 0x40100400) - bg2rgb[*dest];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Translates and subtracts all four spans to the screen starting at sx with clamping.
void rt_tlatesubclamp4cols (int sx, int yl, int yh)
{
BYTE *translation;
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4];
pitch = dc_pitch;
colormap = dc_colormap;
translation = dc_translation;
do {
DWORD a = (fg2rgb[colormap[translation[source[0]]]] | 0x40100400) - bg2rgb[dest[0]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[translation[source[1]]]] | 0x40100400) - bg2rgb[dest[1]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[translation[source[2]]]] | 0x40100400) - bg2rgb[dest[2]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k[0][0][(a>>15) & a];
a = (fg2rgb[colormap[translation[source[3]]]] | 0x40100400) - bg2rgb[dest[3]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Subtracts one span at hx from the screen at sx with clamping.
void rt_revsubclamp1col (int hx, int sx, int yl, int yh)
{
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4 + hx];
pitch = dc_pitch;
colormap = dc_colormap;
do {
DWORD a = (bg2rgb[*dest] | 0x40100400) - fg2rgb[colormap[*source]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Subtracts all four spans from the screen starting at sx with clamping.
void rt_revsubclamp4cols (int sx, int yl, int yh)
{
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4];
pitch = dc_pitch;
colormap = dc_colormap;
do {
DWORD a = (bg2rgb[dest[0]] | 0x40100400) - fg2rgb[colormap[source[0]]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[1]] | 0x40100400) - fg2rgb[colormap[source[1]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[2]] | 0x40100400) - fg2rgb[colormap[source[2]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[3]] | 0x40100400) - fg2rgb[colormap[source[3]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Translates and subtracts one span at hx from the screen at sx with clamping.
void rt_tlaterevsubclamp1col (int hx, int sx, int yl, int yh)
{
BYTE *translation;
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4 + hx];
pitch = dc_pitch;
colormap = dc_colormap;
translation = dc_translation;
do {
DWORD a = (bg2rgb[dest[0]] | 0x40100400) - fg2rgb[colormap[translation[source[0]]]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
*dest = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Translates and subtracts all four spans from the screen starting at sx with clamping.
void rt_tlaterevsubclamp4cols (int sx, int yl, int yh)
{
BYTE *translation;
BYTE *colormap;
BYTE *source;
BYTE *dest;
int count;
int pitch;
count = yh-yl;
if (count < 0)
return;
count++;
DWORD *fg2rgb = dc_srcblend;
DWORD *bg2rgb = dc_destblend;
dest = ylookup[yl] + sx + dc_destorg;
source = &dc_temp[yl*4];
pitch = dc_pitch;
colormap = dc_colormap;
translation = dc_translation;
do {
DWORD a = (bg2rgb[dest[0]] | 0x40100400) - fg2rgb[colormap[translation[source[0]]]];
DWORD b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[0] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[1]] | 0x40100400) - fg2rgb[colormap[translation[source[1]]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[1] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[2]] | 0x40100400) - fg2rgb[colormap[translation[source[2]]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[2] = RGB32k[0][0][(a>>15) & a];
a = (bg2rgb[dest[3]] | 0x40100400) - fg2rgb[colormap[translation[source[3]]]];
b = a;
b &= 0x40100400;
b = b - (b >> 5);
a &= b;
a |= 0x01f07c1f;
dest[3] = RGB32k[0][0][(a>>15) & a];
source += 4;
dest += pitch;
} while (--count);
}
// Copies all spans in all four columns to the screen starting at sx. // Copies all spans in all four columns to the screen starting at sx.
// sx should be longword-aligned. // sx should be longword-aligned.
void rt_draw4cols (int sx) void rt_draw4cols (int sx)

View file

@ -134,7 +134,7 @@ fixed_t FocalLengthY;
float FocalLengthXfloat; float FocalLengthXfloat;
int viewangleoffset; int viewangleoffset;
int validcount = 1; // increment every time a check is made int validcount = 1; // increment every time a check is made
lighttable_t *basecolormap; // [RH] colormap currently drawing with FDynamicColormap*basecolormap; // [RH] colormap currently drawing with
int fixedlightlev; int fixedlightlev;
lighttable_t *fixedcolormap; lighttable_t *fixedcolormap;
float WallTMapScale; float WallTMapScale;
@ -1077,7 +1077,7 @@ void R_SetupFrame (AActor *actor)
if (player != NULL && gamestate != GS_TITLELEVEL && if (player != NULL && gamestate != GS_TITLELEVEL &&
((player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) && ((player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) &&
(camera->RenderStyle != STYLE_None) && (camera->RenderStyle.BlendOp != STYLEOP_None) &&
!(camera->renderflags & RF_INVISIBLE) && !(camera->renderflags & RF_INVISIBLE) &&
camera->sprite != 0) // Sprite 0 is always TNT1 camera->sprite != 0) // Sprite 0 is always TNT1
{ {

View file

@ -70,7 +70,7 @@ extern fixed_t centeryfrac;
extern fixed_t yaspectmul; extern fixed_t yaspectmul;
extern float iyaspectmulfloat; extern float iyaspectmulfloat;
extern BYTE* basecolormap; // [RH] Colormap for sector currently being drawn extern FDynamicColormap*basecolormap; // [RH] Colormap for sector currently being drawn
extern int validcount; extern int validcount;

View file

@ -207,7 +207,7 @@ void R_MapPlane (int y, int x1)
if (plane_shade) if (plane_shade)
{ {
// Determine lighting based on the span's distance from the viewer. // Determine lighting based on the span's distance from the viewer.
ds_colormap = basecolormap + (GETPALOOKUP ( ds_colormap = basecolormap->Maps + (GETPALOOKUP (
FixedMul (GlobVis, abs (centeryfrac - (y << FRACBITS))), planeshade) << COLORMAPSHIFT); FixedMul (GlobVis, abs (centeryfrac - (y << FRACBITS))), planeshade) << COLORMAPSHIFT);
} }
@ -237,6 +237,7 @@ void STACK_ARGS R_CalcTiltedLighting (fixed_t lval, fixed_t lend, int width)
{ {
fixed_t lstep; fixed_t lstep;
BYTE *lightfiller; BYTE *lightfiller;
BYTE *basecolormapdata = basecolormap->Maps;
int i = 0; int i = 0;
lval = planeshade - lval; lval = planeshade - lval;
@ -244,19 +245,19 @@ void STACK_ARGS R_CalcTiltedLighting (fixed_t lval, fixed_t lend, int width)
if (width == 0 || lval == lend) if (width == 0 || lval == lend)
{ // Constant lighting { // Constant lighting
lightfiller = basecolormap + (GETPALOOKUP (-lval, 0) << COLORMAPSHIFT); lightfiller = basecolormapdata + (GETPALOOKUP (-lval, 0) << COLORMAPSHIFT);
} }
else if ((lstep = (lend - lval) / width) < 0) else if ((lstep = (lend - lval) / width) < 0)
{ // Going from dark to light { // Going from dark to light
if (lval < FRACUNIT) if (lval < FRACUNIT)
{ // All bright { // All bright
lightfiller = basecolormap; lightfiller = basecolormapdata;
} }
else else
{ {
if (lval >= NUMCOLORMAPS*FRACUNIT) if (lval >= NUMCOLORMAPS*FRACUNIT)
{ // Starts beyond the dark end { // Starts beyond the dark end
BYTE *clight = basecolormap + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
while (lval >= NUMCOLORMAPS*FRACUNIT && i <= width) while (lval >= NUMCOLORMAPS*FRACUNIT && i <= width)
{ {
tiltlighting[i++] = clight; tiltlighting[i++] = clight;
@ -267,33 +268,33 @@ void STACK_ARGS R_CalcTiltedLighting (fixed_t lval, fixed_t lend, int width)
} }
while (i <= width && lval >= 0) while (i <= width && lval >= 0)
{ {
tiltlighting[i++] = basecolormap + ((lval >> FRACBITS) << COLORMAPSHIFT); tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT);
lval += lstep; lval += lstep;
} }
lightfiller = basecolormap; lightfiller = basecolormapdata;
} }
} }
else else
{ // Going from light to dark { // Going from light to dark
if (lval >= (NUMCOLORMAPS-1)*FRACUNIT) if (lval >= (NUMCOLORMAPS-1)*FRACUNIT)
{ // All dark { // All dark
lightfiller = basecolormap + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
} }
else else
{ {
while (lval < 0 && i <= width) while (lval < 0 && i <= width)
{ {
tiltlighting[i++] = basecolormap; tiltlighting[i++] = basecolormapdata;
lval += lstep; lval += lstep;
} }
if (i > width) if (i > width)
return; return;
while (i <= width && lval < (NUMCOLORMAPS-1)*FRACUNIT) while (i <= width && lval < (NUMCOLORMAPS-1)*FRACUNIT)
{ {
tiltlighting[i++] = basecolormap + ((lval >> FRACBITS) << COLORMAPSHIFT); tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT);
lval += lstep; lval += lstep;
} }
lightfiller = basecolormap + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
} }
} }
@ -1313,7 +1314,7 @@ sky1:
{ {
dc_colormap = fixedcolormap; dc_colormap = fixedcolormap;
} }
else if (!fixedcolormap) else
{ {
fakefixed = true; fakefixed = true;
fixedcolormap = dc_colormap = NormalLight.Maps; fixedcolormap = dc_colormap = NormalLight.Maps;
@ -1387,7 +1388,7 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool masked)
GlobVis = FixedDiv (r_FloorVisibility, planeheight); GlobVis = FixedDiv (r_FloorVisibility, planeheight);
if (fixedlightlev) if (fixedlightlev)
ds_colormap = basecolormap + fixedlightlev, plane_shade = false; ds_colormap = basecolormap->Maps + fixedlightlev, plane_shade = false;
else if (fixedcolormap) else if (fixedcolormap)
ds_colormap = fixedcolormap, plane_shade = false; ds_colormap = fixedcolormap, plane_shade = false;
else else
@ -1532,11 +1533,11 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool masked)
planelightfloat = -planelightfloat; planelightfloat = -planelightfloat;
if (fixedlightlev) if (fixedlightlev)
ds_colormap = basecolormap + fixedlightlev, plane_shade = false; ds_colormap = basecolormap->Maps + fixedlightlev, plane_shade = false;
else if (fixedcolormap) else if (fixedcolormap)
ds_colormap = fixedcolormap, plane_shade = false; ds_colormap = fixedcolormap, plane_shade = false;
else else
ds_colormap = basecolormap, plane_shade = true; ds_colormap = basecolormap->Maps, plane_shade = true;
if (!plane_shade) if (!plane_shade)
{ {

View file

@ -40,7 +40,7 @@ struct visplane_s
int lightlevel; int lightlevel;
fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats
int minx, maxx; int minx, maxx;
BYTE *colormap; // [RH] Support multiple colormaps FDynamicColormap *colormap; // [RH] Support multiple colormaps
fixed_t xscale, yscale; // [RH] Support flat scaling fixed_t xscale, yscale; // [RH] Support flat scaling
angle_t angle; // [RH] Support flat rotation angle_t angle; // [RH] Support flat rotation
ASkyViewpoint *skybox; // [RH] Support sky boxes ASkyViewpoint *skybox; // [RH] Support sky boxes

View file

@ -1401,13 +1401,13 @@ void RP_Subsector (subsector_t *sub)
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel,
&ceilinglightlevel, false); // killough 4/11/98 &ceilinglightlevel, false); // killough 4/11/98
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
R_GetExtraLight (&ceilinglightlevel, frontsector->ceilingplane, frontsector->ExtraLights); R_GetExtraLight (&ceilinglightlevel, frontsector->ceilingplane, frontsector->ExtraLights);
// [RH] set foggy flag // [RH] set foggy flag
foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE); foggy = level.fadeto || frontsector->ColorMap->Fade || (level.flags & LEVEL_HASFADETABLE);
r_actualextralight = foggy ? 0 : extralight << 4; r_actualextralight = foggy ? 0 : extralight << 4;
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
/* ceilingplane = frontsector->ceilingplane.ZatPoint (viewx, viewy) > viewz || /* ceilingplane = frontsector->ceilingplane.ZatPoint (viewx, viewy) > viewz ||
frontsector->ceilingpic == skyflatnum || frontsector->ceilingpic == skyflatnum ||
(frontsector->CeilingSkyBox != NULL && frontsector->CeilingSkyBox->bAlways) || (frontsector->CeilingSkyBox != NULL && frontsector->CeilingSkyBox->bAlways) ||
@ -1427,7 +1427,7 @@ void RP_Subsector (subsector_t *sub)
frontsector->CeilingSkyBox frontsector->CeilingSkyBox
) : NULL;*/ ) : NULL;*/
basecolormap = frontsector->ColorMap->Maps; basecolormap = frontsector->ColorMap;
R_GetExtraLight (&floorlightlevel, frontsector->floorplane, frontsector->ExtraLights); R_GetExtraLight (&floorlightlevel, frontsector->floorplane, frontsector->ExtraLights);
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check // killough 3/7/98: Add (x,y) offsets to flats, add deep water check

View file

@ -166,7 +166,7 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText
// calculate lighting // calculate lighting
if (!fixedcolormap) if (!fixedcolormap)
{ {
dc_colormap = basecolormap + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
} }
dc_iscale = MulScale18 (MaskedSWall[dc_x], MaskedScaleY); dc_iscale = MulScale18 (MaskedSWall[dc_x], MaskedScaleY);
@ -205,7 +205,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// [RH] modified because we don't use user-definable translucency maps // [RH] modified because we don't use user-definable translucency maps
ESPSResult drawmode; ESPSResult drawmode;
drawmode = R_SetPatchStyle (curline->sidedef->Flags & WALLF_ADDTRANS ? STYLE_Add : STYLE_Translucent, drawmode = R_SetPatchStyle (LegacyRenderStyles[curline->sidedef->Flags & WALLF_ADDTRANS ? STYLE_Add : STYLE_Translucent],
curline->linedef->alpha < 255 ? curline->linedef->alpha<<8 : FRACUNIT, curline->linedef->alpha < 255 ? curline->linedef->alpha<<8 : FRACUNIT,
0, 0); 0, 0);
@ -224,7 +224,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
// killough 4/13/98: get correct lightlevel for 2s normal textures // killough 4/13/98: get correct lightlevel for 2s normal textures
const sector_t *sec = R_FakeFlat (frontsector, &tempsec, NULL, NULL, false); const sector_t *sec = R_FakeFlat (frontsector, &tempsec, NULL, NULL, false);
basecolormap = sec->ColorMap->Maps; // [RH] Set basecolormap basecolormap = sec->ColorMap; // [RH] Set basecolormap
wallshade = ds->shade; wallshade = ds->shade;
rw_lightstep = ds->lightstep; rw_lightstep = ds->lightstep;
@ -276,7 +276,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
} }
if (fixedlightlev) if (fixedlightlev)
dc_colormap = basecolormap + fixedlightlev; dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap) else if (fixedcolormap)
dc_colormap = fixedcolormap; dc_colormap = fixedcolormap;
@ -403,6 +403,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
char bad; char bad;
fixed_t light = rw_light - rw_lightstep; fixed_t light = rw_light - rw_lightstep;
SDWORD yrepeat, texturemid, xoffset; SDWORD yrepeat, texturemid, xoffset;
BYTE *basecolormapdata;
// This function also gets used to draw skies. Unlike BUILD, skies are // This function also gets used to draw skies. Unlike BUILD, skies are
// drawn by visplane instead of by bunch, so these checks are invalid. // drawn by visplane instead of by bunch, so these checks are invalid.
@ -423,6 +424,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
yrepeat = rw_pic->yScale >> (2 + shiftval); yrepeat = rw_pic->yScale >> (2 + shiftval);
texturemid = dc_texturemid << (16 - shiftval); texturemid = dc_texturemid << (16 - shiftval);
xoffset = rw_offset; xoffset = rw_offset;
basecolormapdata = basecolormap->Maps;
x = x1; x = x1;
//while ((umost[x] > dmost[x]) && (x <= x2)) x++; //while ((umost[x] > dmost[x]) && (x <= x2)) x++;
@ -446,7 +448,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -484,7 +486,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
for (z = 0; z < 4; ++z) for (z = 0; z < 4; ++z)
{ {
light += rw_lightstep; light += rw_lightstep;
palookupoffse[z] = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
} }
@ -539,7 +541,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -559,11 +561,11 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t
void wallscan_striped (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t *lwal) void wallscan_striped (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixed_t *lwal)
{ {
bool flooding = false; bool flooding = false;
BYTE *startcolormap = basecolormap; FDynamicColormap *startcolormap = basecolormap;
int startshade = wallshade; int startshade = wallshade;
bool fogginess = foggy; bool fogginess = foggy;
BYTE *floodcolormap = startcolormap; FDynamicColormap *floodcolormap = startcolormap;
int floodshade = startshade; int floodshade = startshade;
bool floodfoggy = foggy; bool floodfoggy = foggy;
@ -612,8 +614,8 @@ void wallscan_striped (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
} }
else else
{ {
basecolormap = el->Lights[i].Master->ColorMap->Maps; basecolormap = el->Lights[i].Master->ColorMap;
fogginess = level.fadeto || el->Lights[i].Master->ColorMap->Fade; fogginess = level.fadeto || basecolormap->Fade;
wallshade = LIGHT2SHADE(curline->sidedef->GetLightLevel(fogginess, wallshade = LIGHT2SHADE(curline->sidedef->GetLightLevel(fogginess,
el->Lights[i].Master->lightlevel) + r_actualextralight); el->Lights[i].Master->lightlevel) + r_actualextralight);
if (el->Lights[i].bFlooder) if (el->Lights[i].bFlooder)
@ -649,6 +651,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
char bad; char bad;
fixed_t light = rw_light - rw_lightstep; fixed_t light = rw_light - rw_lightstep;
SDWORD yrepeat, texturemid, xoffset; SDWORD yrepeat, texturemid, xoffset;
BYTE *basecolormapdata;
if (rw_pic->UseType == FTexture::TEX_Null) if (rw_pic->UseType == FTexture::TEX_Null)
{ {
@ -670,6 +673,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
yrepeat = rw_pic->yScale >> (2 + shiftval); yrepeat = rw_pic->yScale >> (2 + shiftval);
texturemid = dc_texturemid << (16 - shiftval); texturemid = dc_texturemid << (16 - shiftval);
xoffset = rw_offset; xoffset = rw_offset;
basecolormapdata = basecolormap->Maps;
x = startx = x1; x = startx = x1;
p = x + dc_destorg; p = x + dc_destorg;
@ -691,7 +695,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -727,7 +731,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
for (z = 0; z < 4; ++z) for (z = 0; z < 4; ++z)
{ {
light += rw_lightstep; light += rw_lightstep;
palookupoffse[z] = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
} }
@ -780,7 +784,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal, fixe
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -818,6 +822,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
char bad; char bad;
fixed_t light = rw_light - rw_lightstep; fixed_t light = rw_light - rw_lightstep;
SDWORD yrepeat, texturemid, xoffset; SDWORD yrepeat, texturemid, xoffset;
BYTE *basecolormapdata;
if (rw_pic->UseType == FTexture::TEX_Null) if (rw_pic->UseType == FTexture::TEX_Null)
{ {
@ -840,6 +845,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
yrepeat = rw_pic->yScale >> (2 + shiftval); yrepeat = rw_pic->yScale >> (2 + shiftval);
texturemid = dc_texturemid << (16 - shiftval); texturemid = dc_texturemid << (16 - shiftval);
xoffset = rw_offset; xoffset = rw_offset;
basecolormapdata = basecolormap->Maps;
x = startx = x1; x = startx = x1;
p = x + dc_destorg; p = x + dc_destorg;
@ -861,7 +867,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -897,7 +903,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
for (z = 0; z < 4; ++z) for (z = 0; z < 4; ++z)
{ {
light += rw_lightstep; light += rw_lightstep;
palookupoffse[z] = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
} }
@ -953,7 +959,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, fixed_t *swal,
if (!fixedcolormap) if (!fixedcolormap)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
} }
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS); dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
@ -989,7 +995,7 @@ void R_RenderSegLoop ()
fixed_t xoffset = rw_offset; fixed_t xoffset = rw_offset;
if (fixedlightlev) if (fixedlightlev)
dc_colormap = basecolormap + fixedlightlev; dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap) else if (fixedcolormap)
dc_colormap = fixedcolormap; dc_colormap = fixedcolormap;
@ -2347,11 +2353,11 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep; rw_light = rw_lightleft + (x1 - WallSX1) * rw_lightstep;
if (fixedlightlev) if (fixedlightlev)
dc_colormap = basecolormap + fixedlightlev; dc_colormap = basecolormap->Maps + fixedlightlev;
else if (fixedcolormap) else if (fixedcolormap)
dc_colormap = fixedcolormap; dc_colormap = fixedcolormap;
else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT)) else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
dc_colormap = basecolormap; dc_colormap = basecolormap->Maps;
else else
calclighting = true; calclighting = true;
@ -2398,7 +2404,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
} }
WallSpriteColumn (R_DrawMaskedColumn); WallSpriteColumn (R_DrawMaskedColumn);
@ -2409,7 +2415,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
} }
rt_initcols(); rt_initcols();
for (int zz = 4; zz; --zz) for (int zz = 4; zz; --zz)
@ -2424,7 +2430,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
{ {
if (calclighting) if (calclighting)
{ // calculate lighting { // calculate lighting
dc_colormap = basecolormap + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); dc_colormap = basecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
} }
WallSpriteColumn (R_DrawMaskedColumn); WallSpriteColumn (R_DrawMaskedColumn);

View file

@ -453,7 +453,7 @@ void R_InitSkins (void)
sndlumps[j] = -1; sndlumps[j] = -1;
skins[i].namespc = Wads.GetLumpNamespace (base); skins[i].namespc = Wads.GetLumpNamespace (base);
SC_OpenLumpNum (base, "S_SKIN"); FScanner sc(base, "S_SKIN");
intname = 0; intname = 0;
crouchname = 0; crouchname = 0;
@ -462,18 +462,18 @@ void R_InitSkins (void)
transtype = NULL; transtype = NULL;
// Data is stored as "key = data". // Data is stored as "key = data".
while (SC_GetString ()) while (sc.GetString ())
{ {
strncpy (key, sc_String, sizeof(key)-1); strncpy (key, sc.String, sizeof(key)-1);
if (!SC_GetString() || sc_String[0] != '=') if (!sc.GetString() || sc.String[0] != '=')
{ {
Printf (PRINT_BOLD, "Bad format for skin %d: %s\n", i, key); Printf (PRINT_BOLD, "Bad format for skin %d: %s\n", i, key);
break; break;
} }
SC_GetString (); sc.GetString ();
if (0 == stricmp (key, "name")) if (0 == stricmp (key, "name"))
{ {
strncpy (skins[i].name, sc_String, 16); strncpy (skins[i].name, sc.String, 16);
for (j = 0; (size_t)j < i; j++) for (j = 0; (size_t)j < i; j++)
{ {
if (stricmp (skins[i].name, skins[j].name) == 0) if (stricmp (skins[i].name, skins[j].name) == 0)
@ -488,27 +488,27 @@ void R_InitSkins (void)
else if (0 == stricmp (key, "sprite")) else if (0 == stricmp (key, "sprite"))
{ {
for (j = 3; j >= 0; j--) for (j = 3; j >= 0; j--)
sc_String[j] = toupper (sc_String[j]); sc.String[j] = toupper (sc.String[j]);
intname = *((DWORD *)sc_String); intname = *((DWORD *)sc.String);
} }
else if (0 == stricmp (key, "crouchsprite")) else if (0 == stricmp (key, "crouchsprite"))
{ {
for (j = 3; j >= 0; j--) for (j = 3; j >= 0; j--)
sc_String[j] = toupper (sc_String[j]); sc.String[j] = toupper (sc.String[j]);
crouchname = *((DWORD *)sc_String); crouchname = *((DWORD *)sc.String);
} }
else if (0 == stricmp (key, "face")) else if (0 == stricmp (key, "face"))
{ {
for (j = 2; j >= 0; j--) for (j = 2; j >= 0; j--)
skins[i].face[j] = toupper (sc_String[j]); skins[i].face[j] = toupper (sc.String[j]);
} }
else if (0 == stricmp (key, "gender")) else if (0 == stricmp (key, "gender"))
{ {
skins[i].gender = D_GenderToInt (sc_String); skins[i].gender = D_GenderToInt (sc.String);
} }
else if (0 == stricmp (key, "scale")) else if (0 == stricmp (key, "scale"))
{ {
skins[i].Scale = clamp<fixed_t> (FLOAT2FIXED(atof (sc_String)), 1, 256*FRACUNIT); skins[i].Scale = clamp<fixed_t> (FLOAT2FIXED(atof (sc.String)), 1, 256*FRACUNIT);
} }
else if (0 == stricmp (key, "game")) else if (0 == stricmp (key, "game"))
{ {
@ -521,7 +521,7 @@ void R_InitSkins (void)
transtype = basetype; transtype = basetype;
if (stricmp (sc_String, "heretic") == 0) if (stricmp (sc.String, "heretic") == 0)
{ {
if (gameinfo.gametype == GAME_Doom) if (gameinfo.gametype == GAME_Doom)
{ {
@ -533,7 +533,7 @@ void R_InitSkins (void)
remove = true; remove = true;
} }
} }
else if (stricmp (sc_String, "strife") == 0) else if (stricmp (sc.String, "strife") == 0)
{ {
if (gameinfo.gametype != GAME_Strife) if (gameinfo.gametype != GAME_Strife)
{ {
@ -558,7 +558,7 @@ void R_InitSkins (void)
} }
else if (0 == stricmp (key, "class")) else if (0 == stricmp (key, "class"))
{ // [GRB] Define the skin for a specific player class { // [GRB] Define the skin for a specific player class
int pclass = D_PlayerClassToInt (sc_String); int pclass = D_PlayerClassToInt (sc.String);
if (pclass < 0) if (pclass < 0)
{ {
@ -570,11 +570,11 @@ void R_InitSkins (void)
} }
else if (key[0] == '*') else if (key[0] == '*')
{ // Player sound replacment (ZDoom extension) { // Player sound replacment (ZDoom extension)
int lump = Wads.CheckNumForName (sc_String, skins[i].namespc); int lump = Wads.CheckNumForName (sc.String, skins[i].namespc);
if (lump == -1) if (lump == -1)
{ {
lump = Wads.CheckNumForFullName (sc_String); lump = Wads.CheckNumForFullName (sc.String);
if (lump == -1) lump = Wads.CheckNumForName (sc_String, ns_sounds); if (lump == -1) lump = Wads.CheckNumForName (sc.String, ns_sounds);
} }
if (lump != -1) if (lump != -1)
{ {
@ -604,16 +604,16 @@ void R_InitSkins (void)
{ {
if (stricmp (key, skinsoundnames[j][0]) == 0) if (stricmp (key, skinsoundnames[j][0]) == 0)
{ {
sndlumps[j] = Wads.CheckNumForName (sc_String, skins[i].namespc); sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc);
if (sndlumps[j] == -1) if (sndlumps[j] == -1)
{ // Replacement not found, try finding it in the global namespace { // Replacement not found, try finding it in the global namespace
sndlumps[j] = Wads.CheckNumForFullName (sc_String); sndlumps[j] = Wads.CheckNumForFullName (sc.String);
if (sndlumps[j] == -1) sndlumps[j] = Wads.CheckNumForName (sc_String, ns_sounds); if (sndlumps[j] == -1) sndlumps[j] = Wads.CheckNumForName (sc.String, ns_sounds);
} }
} }
} }
//if (j == 8) //if (j == 8)
// Printf ("Funny info for skin %i: %s = %s\n", i, key, sc_String); // Printf ("Funny info for skin %i: %s = %s\n", i, key, sc.String);
} }
} }
@ -751,8 +751,6 @@ void R_InitSkins (void)
} }
} }
SC_Close ();
// Make sure face prefix is a full 3 chars // Make sure face prefix is a full 3 chars
if (skins[i].face[1] == 0 || skins[i].face[2] == 0) if (skins[i].face[1] == 0 || skins[i].face[2] == 0)
{ {
@ -1095,7 +1093,7 @@ void R_DrawVisSprite (vissprite_t *vis)
dc_colormap = vis->colormap; dc_colormap = vis->colormap;
mode = R_SetPatchStyle (vis->RenderStyle, vis->alpha, vis->Translation, vis->AlphaColor); mode = R_SetPatchStyle (vis->RenderStyle, vis->alpha, vis->Translation, vis->FillColor);
if (mode != DontDraw) if (mode != DontDraw)
{ {
@ -1192,10 +1190,10 @@ void R_ProjectSprite (AActor *thing, int fakeside)
sector_t* heightsec; // killough 3/27/98 sector_t* heightsec; // killough 3/27/98
// Don't waste time projecting sprites that are definitely not visible.
if (thing == NULL || if (thing == NULL ||
(thing->renderflags & RF_INVISIBLE) || (thing->renderflags & RF_INVISIBLE) ||
thing->RenderStyle == STYLE_None || !thing->RenderStyle.IsVisible(thing->alpha))
(thing->RenderStyle >= STYLE_Translucent && thing->alpha <= 0))
{ {
return; return;
} }
@ -1385,7 +1383,7 @@ void R_ProjectSprite (AActor *thing, int fakeside)
fixed_t yscale = DivScale16(thing->scaleY, tex->yScale); fixed_t yscale = DivScale16(thing->scaleY, tex->yScale);
vis->renderflags = thing->renderflags; vis->renderflags = thing->renderflags;
vis->RenderStyle = thing->RenderStyle; vis->RenderStyle = thing->RenderStyle;
vis->AlphaColor = thing->alphacolor; vis->FillColor = thing->fillcolor;
vis->xscale = xscale; vis->xscale = xscale;
vis->yscale = Scale (InvZtoScale, yscale, tz)>>4; vis->yscale = Scale (InvZtoScale, yscale, tz)>>4;
vis->idepth = (DWORD)DivScale32 (1, tz) >> 1; // tz is 20.12, so idepth ought to be 12.20, but vis->idepth = (DWORD)DivScale32 (1, tz) >> 1; // tz is 20.12, so idepth ought to be 12.20, but
@ -1417,11 +1415,42 @@ void R_ProjectSprite (AActor *thing, int fakeside)
if (vis->x1 > x1) if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1); vis->startfrac += vis->xiscale*(vis->x1-x1);
// The software renderer cannot invert the source without inverting the overlay
// too. That means if the source is inverted, we need to do the reverse of what
// the invert overlay flag says to do.
INTBOOL invertcolormap = (vis->RenderStyle.Flags & STYLEF_InvertOverlay);
if (vis->RenderStyle.Flags & STYLEF_InvertSource)
{
invertcolormap = !invertcolormap;
}
FDynamicColormap *mybasecolormap = basecolormap;
if (vis->RenderStyle.Flags & STYLEF_FadeToBlack)
{
if (invertcolormap)
{
// Fade to white
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate);
invertcolormap = false;
}
else
{
// Fade to black
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate);
}
}
// get light level // get light level
if (fixedlightlev) if (fixedlightlev)
{ {
vis->colormap = basecolormap + fixedlightlev; if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + fixedlightlev;
} }
else if (fixedcolormap) else if (fixedcolormap)
{ {
@ -1431,12 +1460,20 @@ void R_ProjectSprite (AActor *thing, int fakeside)
else if (!foggy && (thing->renderflags & RF_FULLBRIGHT)) else if (!foggy && (thing->renderflags & RF_FULLBRIGHT))
{ {
// full bright // full bright
vis->colormap = basecolormap; // [RH] Use basecolormap if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps;
} }
else else
{ {
// diminished light // diminished light
vis->colormap = basecolormap + (GETPALOOKUP ( if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (
(fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT); (fixed_t)DivScale12 (r_SpriteVisibility, tz), spriteshade) << COLORMAPSHIFT);
} }
} }
@ -1587,9 +1624,41 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
{ {
vis->alpha = owner->alpha; vis->alpha = owner->alpha;
vis->RenderStyle = owner->RenderStyle; vis->RenderStyle = owner->RenderStyle;
// The software renderer cannot invert the source without inverting the overlay
// too. That means if the source is inverted, we need to do the reverse of what
// the invert overlay flag says to do.
INTBOOL invertcolormap = (vis->RenderStyle.Flags & STYLEF_InvertOverlay);
if (vis->RenderStyle.Flags & STYLEF_InvertSource)
{
invertcolormap = !invertcolormap;
}
FDynamicColormap *mybasecolormap = basecolormap;
if (vis->RenderStyle.Flags & STYLEF_FadeToBlack)
{
if (invertcolormap)
{
// Fade to white
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate);
invertcolormap = false;
}
else
{
// Fade to black
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate);
}
}
if (fixedlightlev) if (fixedlightlev)
{ {
vis->colormap = basecolormap + fixedlightlev; if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + fixedlightlev;
} }
else if (fixedcolormap) else if (fixedcolormap)
{ {
@ -1599,12 +1668,20 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, fixed_t sx, fixed_
else if (!foggy && psp->state->GetFullbright()) else if (!foggy && psp->state->GetFullbright())
{ {
// full bright // full bright
vis->colormap = basecolormap; // [RH] use basecolormap if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps; // [RH] use basecolormap
} }
else else
{ {
// local light // local light
vis->colormap = basecolormap + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT); if (invertcolormap)
{
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
}
vis->colormap = mybasecolormap->Maps + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT);
} }
if (camera->Inventory != NULL) if (camera->Inventory != NULL)
{ {
@ -1648,7 +1725,7 @@ void R_DrawPlayerSprites (void)
r_actualextralight = foggy ? 0 : extralight << 4; r_actualextralight = foggy ? 0 : extralight << 4;
// [RH] set basecolormap // [RH] set basecolormap
basecolormap = sec->ColorMap->Maps; basecolormap = sec->ColorMap;
// get light level // get light level
lightnum = ((floorlight + ceilinglight) >> 1) + r_actualextralight; lightnum = ((floorlight + ceilinglight) >> 1) + r_actualextralight;

View file

@ -471,6 +471,11 @@ void R_InitTranslationTables ()
// Full alpha // Full alpha
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
ShadeFakeColormap[i].Color = -1;
ShadeFakeColormap[i].Desaturate = -1;
ShadeFakeColormap[i].Next = NULL;
ShadeFakeColormap[i].Maps = table;
for (j = 0; j < NUMCOLORMAPS; ++j) for (j = 0; j < NUMCOLORMAPS; ++j)
{ {
int a = (NUMCOLORMAPS - j) * 256 / NUMCOLORMAPS * (16-i); int a = (NUMCOLORMAPS - j) * 256 / NUMCOLORMAPS * (16-i);
@ -482,6 +487,16 @@ void R_InitTranslationTables ()
table += 256; table += 256;
} }
} }
for (i = 0; i < NUMCOLORMAPS*16*256; ++i)
{
assert(shadetables[i] <= 64);
}
// Set up a guaranteed identity map
for (i = 0; i < 256; ++i)
{
identitymap[i] = i;
}
} }
void R_DeinitTranslationTables() void R_DeinitTranslationTables()

View file

@ -200,11 +200,11 @@ static int S_AddPlayerClass (const char *name);
static int S_AddPlayerGender (int classnum, int gender); static int S_AddPlayerGender (int classnum, int gender);
static int S_FindPlayerClass (const char *name); static int S_FindPlayerClass (const char *name);
static int S_LookupPlayerSound (int classidx, int gender, int refid); static int S_LookupPlayerSound (int classidx, int gender, int refid);
static void S_ParsePlayerSoundCommon (FString &pclass, int &gender, int &refid); static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, int &refid);
static void S_AddSNDINFO (int lumpnum); static void S_AddSNDINFO (int lumpnum);
static void S_AddBloodSFX (int lumpnum); static void S_AddBloodSFX (int lumpnum);
static void S_AddStrifeVoice (int lumpnum); static void S_AddStrifeVoice (int lumpnum);
static int S_AddSound (const char *logicalname, int lumpnum); static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc=NULL);
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
@ -470,14 +470,14 @@ int S_FindSoundTentative (const char *name)
// lump. Otherwise, adds the new mapping by using S_AddSoundLump(). // lump. Otherwise, adds the new mapping by using S_AddSoundLump().
//========================================================================== //==========================================================================
int S_AddSound (const char *logicalname, const char *lumpname) int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc)
{ {
int lump = Wads.CheckNumForFullName (lumpname); int lump = Wads.CheckNumForFullName (lumpname);
if (lump == -1) lump = Wads.CheckNumForName (lumpname, ns_sounds); if (lump == -1) lump = Wads.CheckNumForName (lumpname, ns_sounds);
return S_AddSound (logicalname, lump); return S_AddSound (logicalname, lump);
} }
static int S_AddSound (const char *logicalname, int lumpnum) static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc)
{ {
int sfxid; int sfxid;
@ -489,7 +489,14 @@ static int S_AddSound (const char *logicalname, int lumpnum)
if (sfx->bPlayerReserve) if (sfx->bPlayerReserve)
{ {
SC_ScriptError ("Sounds that are reserved for players cannot be reassigned"); if (sc != NULL)
{
sc->ScriptError ("Sounds that are reserved for players cannot be reassigned");
}
else
{
I_Error ("Sounds that are reserved for players cannot be reassigned");
}
} }
// Redefining a player compatibility sound will redefine the target instead. // Redefining a player compatibility sound will redefine the target instead.
if (sfx->bPlayerCompat) if (sfx->bPlayerCompat)
@ -867,23 +874,23 @@ static void S_AddSNDINFO (int lump)
bool skipToEndIf; bool skipToEndIf;
TArray<WORD> list; TArray<WORD> list;
SC_OpenLumpNum (lump, "SNDINFO"); FScanner sc(lump, "SNDINFO");
skipToEndIf = false; skipToEndIf = false;
while (SC_GetString ()) while (sc.GetString ())
{ {
if (skipToEndIf) if (skipToEndIf)
{ {
if (SC_Compare ("$endif")) if (sc.Compare ("$endif"))
{ {
skipToEndIf = false; skipToEndIf = false;
} }
continue; continue;
} }
if (sc_String[0] == '$') if (sc.String[0] == '$')
{ // Got a command { // Got a command
switch (SC_MatchString (SICommandStrings)) switch (sc.MatchString (SICommandStrings))
{ {
case SI_Ambient: { case SI_Ambient: {
// $ambient <num> <logical name> [point [atten] | surround | [world]] // $ambient <num> <logical name> [point [atten] | surround | [world]]
@ -891,20 +898,20 @@ static void S_AddSNDINFO (int lump)
// <volume> // <volume>
AmbientSound *ambient, dummy; AmbientSound *ambient, dummy;
SC_MustGetNumber (); sc.MustGetNumber ();
if (sc_Number < 0 || sc_Number > 255) if (sc.Number < 0 || sc.Number > 255)
{ {
Printf ("Bad ambient index (%d)\n", sc_Number); Printf ("Bad ambient index (%d)\n", sc.Number);
ambient = &dummy; ambient = &dummy;
} }
else if (Ambients[sc_Number] == NULL) else if (Ambients[sc.Number] == NULL)
{ {
ambient = new AmbientSound; ambient = new AmbientSound;
Ambients[sc_Number] = ambient; Ambients[sc.Number] = ambient;
} }
else else
{ {
ambient = Ambients[sc_Number]; ambient = Ambients[sc.Number];
} }
ambient->type = 0; ambient->type = 0;
ambient->periodmin = 0; ambient->periodmin = 0;
@ -913,22 +920,22 @@ static void S_AddSNDINFO (int lump)
ambient->attenuation = 0; ambient->attenuation = 0;
ambient->sound = ""; ambient->sound = "";
SC_MustGetString (); sc.MustGetString ();
ambient->sound = sc_String; ambient->sound = sc.String;
ambient->attenuation = 0; ambient->attenuation = 0;
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("point")) if (sc.Compare ("point"))
{ {
float attenuation; float attenuation;
ambient->type = POSITIONAL; ambient->type = POSITIONAL;
SC_MustGetString (); sc.MustGetString ();
if (IsFloat (sc_String)) if (IsFloat (sc.String))
{ {
attenuation = atof (sc_String); attenuation = atof (sc.String);
SC_MustGetString (); sc.MustGetString ();
if (attenuation > 0) if (attenuation > 0)
{ {
ambient->attenuation = attenuation; ambient->attenuation = attenuation;
@ -943,45 +950,45 @@ static void S_AddSNDINFO (int lump)
ambient->attenuation = 1; ambient->attenuation = 1;
} }
} }
else if (SC_Compare ("surround")) else if (sc.Compare ("surround"))
{ {
ambient->type = SURROUND; ambient->type = SURROUND;
SC_MustGetString (); sc.MustGetString ();
ambient->attenuation = -1; ambient->attenuation = -1;
} }
else else
{ // World is an optional keyword { // World is an optional keyword
if (SC_Compare ("world")) if (sc.Compare ("world"))
{ {
SC_MustGetString (); sc.MustGetString ();
} }
} }
if (SC_Compare ("continuous")) if (sc.Compare ("continuous"))
{ {
ambient->type |= CONTINUOUS; ambient->type |= CONTINUOUS;
} }
else if (SC_Compare ("random")) else if (sc.Compare ("random"))
{ {
ambient->type |= RANDOM; ambient->type |= RANDOM;
SC_MustGetFloat (); sc.MustGetFloat ();
ambient->periodmin = (int)(sc_Float * TICRATE); ambient->periodmin = (int)(sc.Float * TICRATE);
SC_MustGetFloat (); sc.MustGetFloat ();
ambient->periodmax = (int)(sc_Float * TICRATE); ambient->periodmax = (int)(sc.Float * TICRATE);
} }
else if (SC_Compare ("periodic")) else if (sc.Compare ("periodic"))
{ {
ambient->type |= PERIODIC; ambient->type |= PERIODIC;
SC_MustGetFloat (); sc.MustGetFloat ();
ambient->periodmin = (int)(sc_Float * TICRATE); ambient->periodmin = (int)(sc.Float * TICRATE);
} }
else else
{ {
Printf ("Unknown ambient type (%s)\n", sc_String); Printf ("Unknown ambient type (%s)\n", sc.String);
} }
SC_MustGetFloat (); sc.MustGetFloat ();
ambient->volume = sc_Float; ambient->volume = sc.Float;
if (ambient->volume > 1) if (ambient->volume > 1)
ambient->volume = 1; ambient->volume = 1;
else if (ambient->volume < 0) else if (ambient->volume < 0)
@ -994,13 +1001,13 @@ static void S_AddSNDINFO (int lump)
level_info_t *info; level_info_t *info;
char temp[16]; char temp[16];
SC_MustGetNumber (); sc.MustGetNumber ();
sprintf (temp, "MAP%02d", sc_Number); sprintf (temp, "MAP%02d", sc.Number);
info = FindLevelInfo (temp); info = FindLevelInfo (temp);
SC_MustGetString (); sc.MustGetString ();
if (info->mapname[0] && (!(info->flags&LEVEL_MUSICDEFINED))) if (info->mapname[0] && (!(info->flags & LEVEL_MUSICDEFINED)))
{ {
ReplaceString (&info->music, sc_String); ReplaceString (&info->music, sc.String);
} }
} }
break; break;
@ -1010,7 +1017,7 @@ static void S_AddSNDINFO (int lump)
break; break;
case SI_ArchivePath: case SI_ArchivePath:
SC_MustGetString (); // Unused for now sc.MustGetString (); // Unused for now
break; break;
case SI_PlayerSound: { case SI_PlayerSound: {
@ -1018,8 +1025,8 @@ static void S_AddSNDINFO (int lump)
FString pclass; FString pclass;
int gender, refid; int gender, refid;
S_ParsePlayerSoundCommon (pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
S_AddPlayerSound (pclass, gender, refid, sc_String); S_AddPlayerSound (pclass, gender, refid, sc.String);
} }
break; break;
@ -1028,11 +1035,11 @@ static void S_AddSNDINFO (int lump)
FString pclass; FString pclass;
int gender, refid, targid; int gender, refid, targid;
S_ParsePlayerSoundCommon (pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
targid = S_FindSoundNoHash (sc_String); targid = S_FindSoundNoHash (sc.String);
if (!S_sfx[targid].bPlayerReserve) if (!S_sfx[targid].bPlayerReserve)
{ {
SC_ScriptError ("%s is not a player sound", sc_String); sc.ScriptError ("%s is not a player sound", sc.String);
} }
S_DupPlayerSound (pclass, gender, refid, targid); S_DupPlayerSound (pclass, gender, refid, targid);
} }
@ -1044,8 +1051,8 @@ static void S_AddSNDINFO (int lump)
int gender, refid; int gender, refid;
int sfxfrom, aliasto; int sfxfrom, aliasto;
S_ParsePlayerSoundCommon (pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
sfxfrom = S_AddSound (sc_String, -1); sfxfrom = S_AddSound (sc.String, -1, &sc);
aliasto = S_LookupPlayerSound (pclass, gender, refid); aliasto = S_LookupPlayerSound (pclass, gender, refid);
S_sfx[sfxfrom].link = aliasto; S_sfx[sfxfrom].link = aliasto;
S_sfx[sfxfrom].bPlayerCompat = true; S_sfx[sfxfrom].bPlayerCompat = true;
@ -1058,8 +1065,8 @@ static void S_AddSNDINFO (int lump)
int gender, refid; int gender, refid;
int soundnum; int soundnum;
S_ParsePlayerSoundCommon (pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
soundnum = S_FindSoundTentative (sc_String); soundnum = S_FindSoundTentative (sc.String);
S_AddPlayerSoundExisting (pclass, gender, refid, soundnum); S_AddPlayerSoundExisting (pclass, gender, refid, soundnum);
} }
break; break;
@ -1068,14 +1075,14 @@ static void S_AddSNDINFO (int lump)
// $alias <name of alias> <name of real sound> // $alias <name of alias> <name of real sound>
int sfxfrom; int sfxfrom;
SC_MustGetString (); sc.MustGetString ();
sfxfrom = S_AddSound (sc_String, -1); sfxfrom = S_AddSound (sc.String, -1, &sc);
SC_MustGetString (); sc.MustGetString ();
if (S_sfx[sfxfrom].bPlayerCompat) if (S_sfx[sfxfrom].bPlayerCompat)
{ {
sfxfrom = S_sfx[sfxfrom].link; sfxfrom = S_sfx[sfxfrom].link;
} }
S_sfx[sfxfrom].link = S_FindSoundTentative (sc_String); S_sfx[sfxfrom].link = S_FindSoundTentative (sc.String);
} }
break; break;
@ -1083,12 +1090,12 @@ static void S_AddSNDINFO (int lump)
// $limit <logical name> <max channels> // $limit <logical name> <max channels>
int sfx; int sfx;
SC_MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc_String); sfx = S_FindSoundTentative (sc.String);
SC_MustGetNumber (); sc.MustGetNumber ();
//S_sfx[sfx].MaxChannels = clamp<BYTE> (sc_Number, 0, 255); //S_sfx[sfx].MaxChannels = clamp<BYTE> (sc.Number, 0, 255);
//Can't use clamp because of GCC bugs //Can't use clamp because of GCC bugs
S_sfx[sfx].MaxChannels = MIN (MAX (sc_Number, 0), 255); S_sfx[sfx].MaxChannels = MIN (MAX (sc.Number, 0), 255);
} }
break; break;
@ -1096,8 +1103,8 @@ static void S_AddSNDINFO (int lump)
// $singular <logical name> // $singular <logical name>
int sfx; int sfx;
SC_MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc_String); sfx = S_FindSoundTentative (sc.String);
S_sfx[sfx].bSingular = true; S_sfx[sfx].bSingular = true;
} }
break; break;
@ -1106,17 +1113,17 @@ static void S_AddSNDINFO (int lump)
// $pitchshift <logical name> <pitch shift amount> // $pitchshift <logical name> <pitch shift amount>
int sfx; int sfx;
SC_MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc_String); sfx = S_FindSoundTentative (sc.String);
SC_MustGetNumber (); sc.MustGetNumber ();
S_sfx[sfx].PitchMask = (1 << clamp (sc_Number, 0, 7)) - 1; S_sfx[sfx].PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
} }
break; break;
case SI_PitchShiftRange: case SI_PitchShiftRange:
// $pitchshiftrange <pitch shift amount> // $pitchshiftrange <pitch shift amount>
SC_MustGetNumber (); sc.MustGetNumber ();
CurrentPitchMask = (1 << clamp (sc_Number, 0, 7)) - 1; CurrentPitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
break; break;
case SI_Random: { case SI_Random: {
@ -1124,15 +1131,15 @@ static void S_AddSNDINFO (int lump)
FRandomSoundList random; FRandomSoundList random;
list.Clear (); list.Clear ();
SC_MustGetString (); sc.MustGetString ();
random.SfxHead = S_AddSound (sc_String, -1); random.SfxHead = S_AddSound (sc.String, -1, &sc);
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
while (SC_GetString () && !SC_Compare ("}")) while (sc.GetString () && !sc.Compare ("}"))
{ {
WORD sfxto = S_FindSoundTentative (sc_String); WORD sfxto = S_FindSoundTentative (sc.String);
if (sfxto == random.SfxHead) if (sfxto == random.SfxHead)
{ {
Printf("Definition of random sound '%s' refers to itself recursively.", sc_String); Printf("Definition of random sound '%s' refers to itself recursively.", sc.String);
continue; continue;
} }
list.Push (sfxto); list.Push (sfxto);
@ -1153,11 +1160,11 @@ static void S_AddSNDINFO (int lump)
break; break;
case SI_MusicVolume: { case SI_MusicVolume: {
SC_MustGetString(); sc.MustGetString();
FString musname (sc_String); FString musname (sc.String);
SC_MustGetFloat(); sc.MustGetFloat();
FMusicVolume *mv = (FMusicVolume *)M_Malloc (sizeof(*mv) + musname.Len()); FMusicVolume *mv = (FMusicVolume *)M_Malloc (sizeof(*mv) + musname.Len());
mv->Volume = sc_Float; mv->Volume = sc.Float;
strcpy (mv->MusicName, musname); strcpy (mv->MusicName, musname);
mv->Next = MusicVolumes; mv->Next = MusicVolumes;
MusicVolumes = mv; MusicVolumes = mv;
@ -1165,14 +1172,14 @@ static void S_AddSNDINFO (int lump)
break; break;
case SI_MidiDevice: { case SI_MidiDevice: {
SC_MustGetString(); sc.MustGetString();
FName nm = sc_String; FName nm = sc.String;
SC_MustGetString(); sc.MustGetString();
if (SC_Compare("timidity")) MidiDevices[nm] = 1; if (sc.Compare("timidity")) MidiDevices[nm] = 1;
else if (SC_Compare("standard")) MidiDevices[nm] = 0; else if (sc.Compare("standard")) MidiDevices[nm] = 0;
else if (SC_Compare("opl")) MidiDevices[nm] = 2; else if (sc.Compare("opl")) MidiDevices[nm] = 2;
else if (SC_Compare("default")) MidiDevices[nm] = -1; else if (sc.Compare("default")) MidiDevices[nm] = -1;
else SC_ScriptError("Unknown MIDI device %s\n", sc_String); else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
} }
break; break;
@ -1207,12 +1214,11 @@ static void S_AddSNDINFO (int lump)
} }
else else
{ // Got a logical sound mapping { // Got a logical sound mapping
FString name (sc_String); FString name (sc.String);
SC_MustGetString (); sc.MustGetString ();
S_AddSound (name, sc_String); S_AddSound (name, sc.String, &sc);
} }
} }
SC_Close ();
} }
//========================================================================== //==========================================================================
@ -1273,21 +1279,21 @@ static void S_AddStrifeVoice (int lumpnum)
// (player class, gender, and ref id) // (player class, gender, and ref id)
//========================================================================== //==========================================================================
static void S_ParsePlayerSoundCommon (FString &pclass, int &gender, int &refid) static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender, int &refid)
{ {
SC_MustGetString (); sc.MustGetString ();
pclass = sc_String; pclass = sc.String;
SC_MustGetString (); sc.MustGetString ();
gender = D_GenderToInt (sc_String); gender = D_GenderToInt (sc.String);
SC_MustGetString (); sc.MustGetString ();
refid = S_FindSoundNoHash (sc_String); refid = S_FindSoundNoHash (sc.String);
if (refid != 0 && !S_sfx[refid].bPlayerReserve && !S_sfx[refid].bTentative) if (refid != 0 && !S_sfx[refid].bPlayerReserve && !S_sfx[refid].bTentative)
{ {
SC_ScriptError ("%s has already been used for a non-player sound.", sc_String); sc.ScriptError ("%s has already been used for a non-player sound.", sc.String);
} }
if (refid == 0) if (refid == 0)
{ {
refid = S_AddSound (sc_String, -1); refid = S_AddSound (sc.String, -1, &sc);
S_sfx[refid].bTentative = true; S_sfx[refid].bTentative = true;
} }
if (S_sfx[refid].bTentative) if (S_sfx[refid].bTentative)
@ -1296,7 +1302,7 @@ static void S_ParsePlayerSoundCommon (FString &pclass, int &gender, int &refid)
S_sfx[refid].bTentative = false; S_sfx[refid].bTentative = false;
S_sfx[refid].bPlayerReserve = true; S_sfx[refid].bPlayerReserve = true;
} }
SC_MustGetString (); sc.MustGetString ();
} }
//========================================================================== //==========================================================================

View file

@ -465,8 +465,9 @@ FArchive &operator<< (FArchive &arc, ReverbContainer *&env)
return arc; return arc;
} }
static void ReadEAX () static void ReadEAX (int lump, const char *lumpname)
{ {
FScanner sc;
const ReverbContainer *def; const ReverbContainer *def;
ReverbContainer *newenv; ReverbContainer *newenv;
REVERB_PROPERTIES props; REVERB_PROPERTIES props;
@ -475,45 +476,46 @@ static void ReadEAX ()
bool inited[NUM_EAX_FIELDS]; bool inited[NUM_EAX_FIELDS];
BYTE bools[32]; BYTE bools[32];
while (SC_GetString ()) sc.OpenLumpNum(lump, lumpname);
while (sc.GetString ())
{ {
name = copystring (sc_String); name = copystring (sc.String);
SC_MustGetNumber (); sc.MustGetNumber ();
id1 = sc_Number; id1 = sc.Number;
SC_MustGetNumber (); sc.MustGetNumber ();
id2 = sc_Number; id2 = sc.Number;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
memset (inited, 0, sizeof(inited)); memset (inited, 0, sizeof(inited));
props.Flags = 0; props.Flags = 0;
while (SC_MustGetString (), NUM_EAX_FIELDS > (i = SC_MustMatchString (EAXFieldNames))) while (sc.MustGetString (), NUM_EAX_FIELDS > (i = sc.MustMatchString (EAXFieldNames)))
{ {
if (EAXFields[i].Float) if (EAXFields[i].Float)
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
props.*EAXFields[i].Float = clamp (sc_Float, props.*EAXFields[i].Float = clamp (sc.Float,
double(EAXFields[i].Min)/1000, double(EAXFields[i].Min)/1000,
double(EAXFields[i].Max)/1000); double(EAXFields[i].Max)/1000);
} }
else if (EAXFields[i].Int) else if (EAXFields[i].Int)
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
props.*EAXFields[i].Int = (j = clamp (sc_Number, props.*EAXFields[i].Int = (j = clamp (sc.Number,
EAXFields[i].Min, EAXFields[i].Max)); EAXFields[i].Min, EAXFields[i].Max));
if (i == 0 && j != sc_Number) if (i == 0 && j != sc.Number)
{ {
SC_ScriptError ("The Environment field is out of range."); sc.ScriptError ("The Environment field is out of range.");
} }
} }
else else
{ {
SC_MustGetString (); sc.MustGetString ();
bools[EAXFields[i].Flag] = SC_MustMatchString (BoolNames); bools[EAXFields[i].Flag] = sc.MustMatchString (BoolNames);
} }
inited[i] = true; inited[i] = true;
} }
if (!inited[0]) if (!inited[0])
{ {
SC_ScriptError ("Sound %s is missing an Environment field.", name); sc.ScriptError ("Sound %s is missing an Environment field.", name);
} }
// Add the new environment to the list, filling in uninitialized fields // Add the new environment to the list, filling in uninitialized fields
@ -573,9 +575,7 @@ void S_ParseSndEax ()
while ((lump = Wads.FindLump ("SNDEAX", &lastlump)) != -1) while ((lump = Wads.FindLump ("SNDEAX", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "SNDEAX"); ReadEAX (lump, "SNDEAX");
ReadEAX ();
SC_Close ();
} }
} }

View file

@ -161,7 +161,7 @@ struct FSoundSequencePtrArray : public TArray<FSoundSequence *>
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void AssignTranslations (int seq, seqtype_t type); static void AssignTranslations (FScanner &sc, int seq, seqtype_t type);
static void AssignHexenTranslations (void); static void AssignHexenTranslations (void);
static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, const TArray<DWORD> &ScriptTemp); static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, const TArray<DWORD> &ScriptTemp);
static int FindSequence (const char *searchname); static int FindSequence (const char *searchname);
@ -388,19 +388,19 @@ void DSeqSectorNode::Serialize (FArchive &arc)
// //
//========================================================================== //==========================================================================
static void AssignTranslations (int seq, seqtype_t type) static void AssignTranslations (FScanner &sc, int seq, seqtype_t type)
{ {
sc_Crossed = false; sc.Crossed = false;
while (SC_GetString () && !sc_Crossed) while (sc.GetString () && !sc.Crossed)
{ {
if (IsNum (sc_String)) if (IsNum (sc.String))
{ {
SeqTrans[(atoi(sc_String) & 63) + type * 64] = seq; SeqTrans[(atoi(sc.String) & 63) + type * 64] = seq;
} }
} }
SC_UnGet (); sc.UnGet ();
} }
//========================================================================== //==========================================================================
@ -481,17 +481,17 @@ void S_ParseSndSeq (int levellump)
lump = levellump; lump = levellump;
levellump = -2; levellump = -2;
} }
SC_OpenLumpNum (lump, "SNDSEQ"); FScanner sc(lump, "SNDSEQ");
while (SC_GetString ()) while (sc.GetString ())
{ {
if (*sc_String == ':' || *sc_String == '[') if (*sc.String == ':' || *sc.String == '[')
{ {
if (curseq != -1) if (curseq != -1)
{ {
SC_ScriptError ("S_ParseSndSeq: Nested Script Error"); sc.ScriptError ("S_ParseSndSeq: Nested Script Error");
} }
seqname = sc_String + 1; seqname = sc.String + 1;
seqtype = sc_String[0]; seqtype = sc.String[0];
for (curseq = 0; curseq < (int)Sequences.Size(); curseq++) for (curseq = 0; curseq < (int)Sequences.Size(); curseq++)
{ {
if (Sequences[curseq]->SeqName == seqname) if (Sequences[curseq]->SeqName == seqname)
@ -510,7 +510,7 @@ void S_ParseSndSeq (int levellump)
slot = NAME_None; slot = NAME_None;
if (seqtype == '[') if (seqtype == '[')
{ {
SC_SetCMode (true); sc.SetCMode (true);
ScriptTemp.Push (0); // to be filled when definition is complete ScriptTemp.Push (0); // to be filled when definition is complete
} }
continue; continue;
@ -521,101 +521,101 @@ void S_ParseSndSeq (int levellump)
} }
if (seqtype == '[') if (seqtype == '[')
{ {
if (sc_String[0] == ']') if (sc.String[0] == ']')
{ // End of this definition { // End of this definition
ScriptTemp[0] = MakeCommand(SS_CMD_SELECT, (ScriptTemp.Size()-1)/2); ScriptTemp[0] = MakeCommand(SS_CMD_SELECT, (ScriptTemp.Size()-1)/2);
AddSequence (curseq, seqname, slot, stopsound, ScriptTemp); AddSequence (curseq, seqname, slot, stopsound, ScriptTemp);
curseq = -1; curseq = -1;
SC_SetCMode (false); sc.SetCMode (false);
} }
else else
{ // Add a selection { // Add a selection
SC_UnGet(); sc.UnGet();
if (SC_CheckNumber()) if (sc.CheckNumber())
{ {
ScriptTemp.Push (sc_Number); ScriptTemp.Push (sc.Number);
SC_MustGetString(); sc.MustGetString();
ScriptTemp.Push (FName(sc_String)); ScriptTemp.Push (FName(sc.String));
} }
else else
{ {
AssignTranslations (curseq, seqtype_t(SC_MustMatchString (SSStrings + SS_STRING_PLATFORM))); AssignTranslations (sc, curseq, seqtype_t(sc.MustMatchString (SSStrings + SS_STRING_PLATFORM)));
} }
} }
continue; continue;
} }
switch (SC_MustMatchString (SSStrings)) switch (sc.MustMatchString (SSStrings))
{ {
case SS_STRING_PLAYUNTILDONE: case SS_STRING_PLAYUNTILDONE:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String)));
ScriptTemp.Push(MakeCommand(SS_CMD_WAITUNTILDONE, 0)); ScriptTemp.Push(MakeCommand(SS_CMD_WAITUNTILDONE, 0));
break; break;
case SS_STRING_PLAY: case SS_STRING_PLAY:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String)));
break; break;
case SS_STRING_PLAYTIME: case SS_STRING_PLAYTIME:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc.String)));
SC_MustGetNumber (); sc.MustGetNumber ();
ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc.Number));
break; break;
case SS_STRING_PLAYREPEAT: case SS_STRING_PLAYREPEAT:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc_String))); ScriptTemp.Push(MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc.String)));
break; break;
case SS_STRING_PLAYLOOP: case SS_STRING_PLAYLOOP:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc_String))); ScriptTemp.Push(MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc.String)));
SC_MustGetNumber (); sc.MustGetNumber ();
ScriptTemp.Push(sc_Number); ScriptTemp.Push(sc.Number);
break; break;
case SS_STRING_DELAY: case SS_STRING_DELAY:
SC_MustGetNumber (); sc.MustGetNumber ();
ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc.Number));
break; break;
case SS_STRING_DELAYONCE: case SS_STRING_DELAYONCE:
SC_MustGetNumber (); sc.MustGetNumber ();
ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc.Number));
ScriptTemp.Push(MakeCommand(SS_CMD_LAST2NOP, 0)); ScriptTemp.Push(MakeCommand(SS_CMD_LAST2NOP, 0));
break; break;
case SS_STRING_DELAYRAND: case SS_STRING_DELAYRAND:
SC_MustGetNumber (); sc.MustGetNumber ();
delaybase = sc_Number; delaybase = sc.Number;
ScriptTemp.Push(MakeCommand(SS_CMD_DELAYRAND, sc_Number)); ScriptTemp.Push(MakeCommand(SS_CMD_DELAYRAND, sc.Number));
SC_MustGetNumber (); sc.MustGetNumber ();
ScriptTemp.Push(MAX(1, sc_Number - delaybase + 1)); ScriptTemp.Push(MAX(1, sc.Number - delaybase + 1));
break; break;
case SS_STRING_VOLUME: // volume is in range 0..100 case SS_STRING_VOLUME: // volume is in range 0..100
SC_MustGetFloat (); sc.MustGetFloat ();
ScriptTemp.Push(MakeCommand(SS_CMD_VOLUME, int(sc_Float * (FRACUNIT/100.f)))); ScriptTemp.Push(MakeCommand(SS_CMD_VOLUME, int(sc.Float * (FRACUNIT/100.f))));
break; break;
case SS_STRING_VOLUMEREL: case SS_STRING_VOLUMEREL:
SC_MustGetFloat (); sc.MustGetFloat ();
ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMEREL, int(sc_Float * (FRACUNIT/100.f)))); ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMEREL, int(sc.Float * (FRACUNIT/100.f))));
break; break;
case SS_STRING_VOLUMERAND: case SS_STRING_VOLUMERAND:
SC_MustGetFloat (); sc.MustGetFloat ();
volumebase = sc_Float; volumebase = sc.Float;
ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMERAND, int(sc_Float * (FRACUNIT/100.f)))); ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMERAND, int(sc.Float * (FRACUNIT/100.f))));
SC_MustGetFloat (); sc.MustGetFloat ();
ScriptTemp.Push(int((sc_Float - volumebase) * (256/100.f))); ScriptTemp.Push(int((sc.Float - volumebase) * (256/100.f)));
break; break;
case SS_STRING_STOPSOUND: case SS_STRING_STOPSOUND:
SC_MustGetString (); sc.MustGetString ();
stopsound = S_FindSound (sc_String); stopsound = S_FindSound (sc.String);
ScriptTemp.Push(MakeCommand(SS_CMD_STOPSOUND, 0)); ScriptTemp.Push(MakeCommand(SS_CMD_STOPSOUND, 0));
break; break;
@ -625,8 +625,8 @@ void S_ParseSndSeq (int levellump)
break; break;
case SS_STRING_ATTENUATION: case SS_STRING_ATTENUATION:
SC_MustGetString (); sc.MustGetString ();
ScriptTemp.Push(MakeCommand(SS_CMD_ATTENUATION, SC_MustMatchString(Attenuations))); ScriptTemp.Push(MakeCommand(SS_CMD_ATTENUATION, sc.MustMatchString(Attenuations)));
break; break;
case SS_STRING_RANDOMSEQUENCE: case SS_STRING_RANDOMSEQUENCE:
@ -643,24 +643,23 @@ void S_ParseSndSeq (int levellump)
break; break;
case SS_STRING_PLATFORM: case SS_STRING_PLATFORM:
AssignTranslations (curseq, SEQ_PLATFORM); AssignTranslations (sc, curseq, SEQ_PLATFORM);
break; break;
case SS_STRING_DOOR: case SS_STRING_DOOR:
AssignTranslations (curseq, SEQ_DOOR); AssignTranslations (sc, curseq, SEQ_DOOR);
break; break;
case SS_STRING_ENVIRONMENT: case SS_STRING_ENVIRONMENT:
AssignTranslations (curseq, SEQ_ENVIRONMENT); AssignTranslations (sc, curseq, SEQ_ENVIRONMENT);
break; break;
case SS_STRING_SLOT: case SS_STRING_SLOT:
SC_MustGetString(); sc.MustGetString();
slot = sc_String; slot = sc.String;
break; break;
} }
} }
SC_Close ();
} }
if (gameinfo.gametype == GAME_Hexen) if (gameinfo.gametype == GAME_Hexen)

View file

@ -25,6 +25,7 @@
#include "tarray.h" #include "tarray.h"
class AActor; class AActor;
class FScanner;
// //
// SoundFX struct. // SoundFX struct.
@ -196,7 +197,7 @@ int S_FindSkinnedSound (AActor *actor, const char *logicalname);
int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname); int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname);
int S_FindSkinnedSound (AActor *actor, int refid); int S_FindSkinnedSound (AActor *actor, int refid);
int S_FindSoundByLump (int lump); int S_FindSoundByLump (int lump);
int S_AddSound (const char *logicalname, const char *lumpname); // Add sound by lumpname int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL); // Add sound by lumpname
int S_AddSoundLump (const char *logicalname, int lump); // Add sound by lump index int S_AddSoundLump (const char *logicalname, int lump); // Add sound by lump index
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname); int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname);
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false); int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false);

File diff suppressed because it is too large Load diff

View file

@ -1,40 +1,98 @@
#ifndef __SC_MAN_H__ #ifndef __SC_MAN_H__
#define __SC_MAN_H__ #define __SC_MAN_H__
void SC_Open (const char *name); class FScanner
void SC_OpenFile (const char *name); {
void SC_OpenMem (const char *name, char *buffer, int size); public:
void SC_OpenLumpNum (int lump, const char *name); struct SavedPos
void SC_Close (void); {
void SC_SetCMode (bool cmode); const char *SavedScriptPtr;
void SC_SetEscape (bool esc); int SavedScriptLine;
void SC_SavePos (void); };
void SC_RestorePos (void);
FString SC_TokenName (int token, const char *string=NULL); // Methods ------------------------------------------------------
bool SC_GetString (void); FScanner();
void SC_MustGetString (void); FScanner(const FScanner &other);
void SC_MustGetStringName (const char *name); FScanner(int lumpnum, const char *name);
bool SC_CheckString (const char *name); ~FScanner();
bool SC_GetToken (void);
void SC_MustGetAnyToken (void); FScanner &operator=(const FScanner &other);
void SC_TokenMustBe (int token);
void SC_MustGetToken (int token); void Open(const char *lumpname);
bool SC_CheckToken (int token); void OpenFile(const char *filename);
bool SC_CheckTokenId (ENamedName id); void OpenMem(const char *name, char *buffer, int size);
bool SC_GetNumber (void); void OpenLumpNum(int lump, const char *name);
void SC_MustGetNumber (void); void Close();
bool SC_CheckNumber (void);
bool SC_CheckFloat (void); void SetCMode(bool cmode);
bool SC_GetFloat (void); void SetEscape(bool esc);
void SC_MustGetFloat (void); const SavedPos SavePos();
void SC_UnGet (void); void RestorePos(const SavedPos &pos);
//boolean SC_Check(void);
bool SC_Compare (const char *text); FString TokenName(int token, const char *string=NULL);
int SC_MatchString (const char **strings);
int SC_MustMatchString (const char **strings); bool GetString();
void STACK_ARGS SC_ScriptError (const char *message, ...); void MustGetString();
void SC_SaveScriptState(); void MustGetStringName(const char *name);
void SC_RestoreScriptState(); bool CheckString(const char *name);
bool GetToken();
void MustGetAnyToken();
void TokenMustBe(int token);
void MustGetToken(int token);
bool CheckToken(int token);
bool CheckTokenId(ENamedName id);
bool GetNumber();
void MustGetNumber();
bool CheckNumber();
bool GetFloat();
void MustGetFloat();
bool CheckFloat();
void UnGet();
bool Compare(const char *text);
int MatchString(const char **strings);
int MustMatchString(const char **strings);
void ScriptError(const char *message, ...);
// Members ------------------------------------------------------
char *String;
int StringLen;
int TokenType;
int Number;
double Float;
FName Name;
int Line;
bool End;
bool Crossed;
protected:
void PrepareScript();
void CheckOpen();
bool ScanString(bool tokens);
// Strings longer than this minus one will be dynamically allocated.
static const int MAX_STRING_SIZE = 128;
bool ScriptOpen;
FString ScriptName;
FString ScriptBuffer;
const char *ScriptPtr;
const char *ScriptEndPtr;
char StringBuffer[MAX_STRING_SIZE];
FString BigStringBuffer;
bool AlreadyGot;
int AlreadyGotLine;
bool LastGotToken;
const char *LastGotPtr;
int LastGotLine;
bool CMode;
bool Escape;
};
enum enum
{ {
@ -152,15 +210,4 @@ enum
TK_LastToken TK_LastToken
}; };
extern int sc_TokenType;
extern char *sc_String;
extern unsigned int sc_StringLen;
extern int sc_Number;
extern double sc_Float;
extern FName sc_Name;
extern int sc_Line;
extern bool sc_End;
extern bool sc_Crossed;
extern bool sc_FileScripts;
#endif //__SC_MAN_H__ #endif //__SC_MAN_H__

View file

@ -23,8 +23,8 @@
//#define YYDEBUG(s,c) { Printf ("%d: %02x\n", s, c); } //#define YYDEBUG(s,c) { Printf ("%d: %02x\n", s, c); }
#define YYDEBUG(s,c) #define YYDEBUG(s,c)
char *cursor = ScriptPtr; const char *cursor = ScriptPtr;
char *limit = ScriptEndPtr; const char *limit = ScriptEndPtr;
std1: std1:
tok = YYCURSOR; tok = YYCURSOR;
@ -33,7 +33,7 @@ std2:
if (tokens) // A well-defined scanner, based on the c.re example. if (tokens) // A well-defined scanner, based on the c.re example.
{ {
#define RET(x) sc_TokenType = x; goto normal_token; #define RET(x) TokenType = x; goto normal_token;
#line 39 "src/sc_man_scanner.h" #line 39 "src/sc_man_scanner.h"
{ {
@ -482,7 +482,7 @@ yy24:
yy25: yy25:
#line 216 "src/sc_man_scanner.re" #line 216 "src/sc_man_scanner.re"
{ {
SC_ScriptError ("Unexpected character: %c (ASCII %d)\n", *tok, *tok); ScriptError ("Unexpected character: %c (ASCII %d)\n", *tok, *tok);
goto std1; goto std1;
} }
#line 489 "src/sc_man_scanner.h" #line 489 "src/sc_man_scanner.h"
@ -4396,7 +4396,7 @@ yy683:
negative_check: negative_check:
// re2c doesn't have enough state to handle '-' as the start of a negative number // re2c doesn't have enough state to handle '-' as the start of a negative number
// and as its own token, so help it out a little. // and as its own token, so help it out a little.
sc_TokenType = '-'; TokenType = '-';
if (YYCURSOR >= YYLIMIT) if (YYCURSOR >= YYLIMIT)
{ {
goto normal_token; goto normal_token;
@ -4440,8 +4440,8 @@ yy689:
return_val = false; return_val = false;
goto end; goto end;
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
goto comment; goto comment;
} }
#line 4448 "src/sc_man_scanner.h" #line 4448 "src/sc_man_scanner.h"
@ -4472,23 +4472,45 @@ newline:
return_val = false; return_val = false;
goto end; goto end;
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
goto std1; goto std1;
normal_token: normal_token:
ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor; ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor;
sc_StringLen = (unsigned int)MIN<size_t> (ScriptPtr - tok, MAX_STRING_SIZE-1); StringLen = int(ScriptPtr - tok);
if (tokens && (sc_TokenType == TK_StringConst || sc_TokenType == TK_NameConst)) if (tokens && (TokenType == TK_StringConst || TokenType == TK_NameConst))
{ {
sc_StringLen -= 2; StringLen -= 2;
memcpy (sc_String, tok+1, sc_StringLen); if (StringLen >= MAX_STRING_SIZE)
{
BigStringBuffer = FString(tok+1, StringLen);
}
else
{
memcpy (StringBuffer, tok+1, StringLen);
}
} }
else else
{ {
memcpy (sc_String, tok, sc_StringLen); if (StringLen >= MAX_STRING_SIZE)
{
BigStringBuffer = FString(tok, StringLen);
}
else
{
memcpy (StringBuffer, tok, StringLen);
}
}
if (StringLen < MAX_STRING_SIZE)
{
String = StringBuffer;
StringBuffer[StringLen] = '\0';
}
else
{
String = BigStringBuffer.LockBuffer();
} }
sc_String[sc_StringLen] = '\0';
return_val = true; return_val = true;
goto end; goto end;
@ -4500,7 +4522,8 @@ string:
goto end; goto end;
} }
ScriptPtr = cursor; ScriptPtr = cursor;
for (sc_StringLen = 0; cursor < YYLIMIT; ++cursor) BigStringBuffer = "";
for (StringLen = 0; cursor < YYLIMIT; ++cursor)
{ {
if (Escape && *cursor == '\\' && *(cursor + 1) == '"') if (Escape && *cursor == '\\' && *(cursor + 1) == '"')
{ {
@ -4518,24 +4541,36 @@ string:
{ {
if (CMode) if (CMode)
{ {
if (!Escape || sc_StringLen == 0 || sc_String[sc_StringLen - 1] != '\\') if (!Escape || StringLen == 0 || String[StringLen - 1] != '\\')
{ {
SC_ScriptError ("Unterminated string constant"); ScriptError ("Unterminated string constant");
} }
else else
{ {
sc_StringLen--; // overwrite the \ character with \n StringLen--; // overwrite the \ character with \n
} }
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
} }
if (sc_StringLen < MAX_STRING_SIZE-1) if (StringLen == MAX_STRING_SIZE)
{ {
sc_String[sc_StringLen++] = *cursor; BigStringBuffer.AppendCStrPart(StringBuffer, StringLen);
StringLen = 0;
} }
StringBuffer[StringLen++] = *cursor;
}
if (BigStringBuffer.IsNotEmpty() || StringLen == MAX_STRING_SIZE)
{
BigStringBuffer.AppendCStrPart(StringBuffer, StringLen);
String = BigStringBuffer.LockBuffer();
StringLen = int(BigStringBuffer.Len());
}
else
{
String = StringBuffer;
StringBuffer[StringLen] = '\0';
} }
ScriptPtr = cursor + 1; ScriptPtr = cursor + 1;
sc_String[sc_StringLen] = '\0';
return_val = true; return_val = true;
end: end:

View file

@ -21,8 +21,8 @@
//#define YYDEBUG(s,c) { Printf ("%d: %02x\n", s, c); } //#define YYDEBUG(s,c) { Printf ("%d: %02x\n", s, c); }
#define YYDEBUG(s,c) #define YYDEBUG(s,c)
char *cursor = ScriptPtr; const char *cursor = ScriptPtr;
char *limit = ScriptEndPtr; const char *limit = ScriptEndPtr;
std1: std1:
tok = YYCURSOR; tok = YYCURSOR;
@ -51,7 +51,7 @@ std2:
*/ */
if (tokens) // A well-defined scanner, based on the c.re example. if (tokens) // A well-defined scanner, based on the c.re example.
{ {
#define RET(x) sc_TokenType = x; goto normal_token; #define RET(x) TokenType = x; goto normal_token;
/*!re2c /*!re2c
"/*" { goto comment; } /* C comment */ "/*" { goto comment; } /* C comment */
"//" (any\"\n")* "\n" { goto newline; } /* C++ comment */ "//" (any\"\n")* "\n" { goto newline; } /* C++ comment */
@ -214,7 +214,7 @@ std2:
"\n" { goto newline; } "\n" { goto newline; }
any any
{ {
SC_ScriptError ("Unexpected character: %c (ASCII %d)\n", *tok, *tok); ScriptError ("Unexpected character: %c (ASCII %d)\n", *tok, *tok);
goto std1; goto std1;
} }
*/ */
@ -265,7 +265,7 @@ std2:
negative_check: negative_check:
// re2c doesn't have enough state to handle '-' as the start of a negative number // re2c doesn't have enough state to handle '-' as the start of a negative number
// and as its own token, so help it out a little. // and as its own token, so help it out a little.
sc_TokenType = '-'; TokenType = '-';
if (YYCURSOR >= YYLIMIT) if (YYCURSOR >= YYLIMIT)
{ {
goto normal_token; goto normal_token;
@ -304,8 +304,8 @@ comment:
return_val = false; return_val = false;
goto end; goto end;
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
goto comment; goto comment;
} }
any { goto comment; } any { goto comment; }
@ -318,23 +318,45 @@ newline:
return_val = false; return_val = false;
goto end; goto end;
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
goto std1; goto std1;
normal_token: normal_token:
ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor; ScriptPtr = (YYCURSOR >= YYLIMIT) ? ScriptEndPtr : cursor;
sc_StringLen = (unsigned int)MIN<size_t> (ScriptPtr - tok, MAX_STRING_SIZE-1); StringLen = int(ScriptPtr - tok);
if (tokens && (sc_TokenType == TK_StringConst || sc_TokenType == TK_NameConst)) if (tokens && (TokenType == TK_StringConst || TokenType == TK_NameConst))
{ {
sc_StringLen -= 2; StringLen -= 2;
memcpy (sc_String, tok+1, sc_StringLen); if (StringLen >= MAX_STRING_SIZE)
{
BigStringBuffer = FString(tok+1, StringLen);
}
else
{
memcpy (StringBuffer, tok+1, StringLen);
}
} }
else else
{ {
memcpy (sc_String, tok, sc_StringLen); if (StringLen >= MAX_STRING_SIZE)
{
BigStringBuffer = FString(tok, StringLen);
}
else
{
memcpy (StringBuffer, tok, StringLen);
}
}
if (StringLen < MAX_STRING_SIZE)
{
String = StringBuffer;
StringBuffer[StringLen] = '\0';
}
else
{
String = BigStringBuffer.LockBuffer();
} }
sc_String[sc_StringLen] = '\0';
return_val = true; return_val = true;
goto end; goto end;
@ -346,7 +368,8 @@ string:
goto end; goto end;
} }
ScriptPtr = cursor; ScriptPtr = cursor;
for (sc_StringLen = 0; cursor < YYLIMIT; ++cursor) BigStringBuffer = "";
for (StringLen = 0; cursor < YYLIMIT; ++cursor)
{ {
if (Escape && *cursor == '\\' && *(cursor + 1) == '"') if (Escape && *cursor == '\\' && *(cursor + 1) == '"')
{ {
@ -364,24 +387,36 @@ string:
{ {
if (CMode) if (CMode)
{ {
if (!Escape || sc_StringLen == 0 || sc_String[sc_StringLen - 1] != '\\') if (!Escape || StringLen == 0 || String[StringLen - 1] != '\\')
{ {
SC_ScriptError ("Unterminated string constant"); ScriptError ("Unterminated string constant");
} }
else else
{ {
sc_StringLen--; // overwrite the \ character with \n StringLen--; // overwrite the \ character with \n
} }
} }
sc_Line++; Line++;
sc_Crossed = true; Crossed = true;
} }
if (sc_StringLen < MAX_STRING_SIZE-1) if (StringLen == MAX_STRING_SIZE)
{ {
sc_String[sc_StringLen++] = *cursor; BigStringBuffer.AppendCStrPart(StringBuffer, StringLen);
StringLen = 0;
} }
StringBuffer[StringLen++] = *cursor;
}
if (BigStringBuffer.IsNotEmpty() || StringLen == MAX_STRING_SIZE)
{
BigStringBuffer.AppendCStrPart(StringBuffer, StringLen);
String = BigStringBuffer.LockBuffer();
StringLen = int(BigStringBuffer.Len());
}
else
{
String = StringBuffer;
StringBuffer[StringLen] = '\0';
} }
ScriptPtr = cursor + 1; ScriptPtr = cursor + 1;
sc_String[sc_StringLen] = '\0';
return_val = true; return_val = true;
end: end:

View file

@ -43,6 +43,7 @@
#include "sc_man.h" #include "sc_man.h"
#include "zstring.h" #include "zstring.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "v_text.h"
// PassNum identifies which language pass this string is from. // PassNum identifies which language pass this string is from.
// PassNum 0 is for DeHacked. // PassNum 0 is for DeHacked.
@ -148,44 +149,44 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p
code |= orMask; code |= orMask;
SC_OpenLumpNum (lumpnum, "LANGUAGE"); FScanner sc(lumpnum, "LANGUAGE");
SC_SetCMode (true); sc.SetCMode (true);
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare ("[")) if (sc.Compare ("["))
{ // Process language identifiers { // Process language identifiers
bool donot = false; bool donot = false;
bool forceskip = false; bool forceskip = false;
skip = true; skip = true;
SC_MustGetString (); sc.MustGetString ();
do do
{ {
size_t len = strlen (sc_String); size_t len = sc.StringLen;
if (len != 2 && len != 3) if (len != 2 && len != 3)
{ {
if (len == 1 && sc_String[0] == '~') if (len == 1 && sc.String[0] == '~')
{ {
donot = true; donot = true;
SC_MustGetString (); sc.MustGetString ();
continue; continue;
} }
if (len == 1 && sc_String[0] == '*') if (len == 1 && sc.String[0] == '*')
{ {
inCode = MAKE_ID('*',0,0,0); inCode = MAKE_ID('*',0,0,0);
} }
else if (len == 7 && stricmp (sc_String, "default") == 0) else if (len == 7 && stricmp (sc.String, "default") == 0)
{ {
inCode = MAKE_ID('*','*',0,0); inCode = MAKE_ID('*','*',0,0);
} }
else else
{ {
SC_ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %lu characters long.", sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %lu characters long.",
sc_String, len); sc.String, len);
} }
} }
else else
{ {
inCode = MAKE_ID(tolower(sc_String[0]), tolower(sc_String[1]), tolower(sc_String[2]), 0); inCode = MAKE_ID(tolower(sc.String[0]), tolower(sc.String[1]), tolower(sc.String[2]), 0);
} }
if ((inCode | orMask) == code) if ((inCode | orMask) == code)
{ {
@ -199,11 +200,11 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p
skip = false; skip = false;
} }
} }
SC_MustGetString (); sc.MustGetString ();
} while (!SC_Compare ("]")); } while (!sc.Compare ("]"));
if (donot) if (donot)
{ {
SC_ScriptError ("You must specify a language after ~"); sc.ScriptError ("You must specify a language after ~");
} }
skip |= forceskip; skip |= forceskip;
} }
@ -211,30 +212,30 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p
{ // Process string definitions. { // Process string definitions.
if (inCode == 0) if (inCode == 0)
{ {
SC_ScriptError ("Found a string without a language specified."); sc.ScriptError ("Found a string without a language specified.");
} }
if (skip) if (skip)
{ // We're not interested in this language, so skip the string. { // We're not interested in this language, so skip the string.
SC_MustGetStringName ("="); sc.MustGetStringName ("=");
SC_MustGetString (); sc.MustGetString ();
do do
{ {
SC_MustGetString (); sc.MustGetString ();
} while (!SC_Compare (";")); } while (!sc.Compare (";"));
continue; continue;
} }
FString strName (sc_String); FString strName (sc.String);
SC_MustGetStringName ("="); sc.MustGetStringName ("=");
SC_MustGetString (); sc.MustGetString ();
FString strText (sc_String, ProcessEscapes (sc_String)); FString strText (sc.String, ProcessEscapes (sc.String));
SC_MustGetString (); sc.MustGetString ();
while (!SC_Compare (";")) while (!sc.Compare (";"))
{ {
ProcessEscapes (sc_String); ProcessEscapes (sc.String);
strText += sc_String; strText += sc.String;
SC_MustGetString (); sc.MustGetString ();
} }
// Does this string exist? If so, should we overwrite it? // Does this string exist? If so, should we overwrite it?
@ -267,7 +268,6 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p
} }
} }
} }
SC_Close ();
} }
// Replace \ escape sequences in a string with the escaped characters. // Replace \ escape sequences in a string with the escaped characters.
@ -283,7 +283,7 @@ size_t FStringTable::ProcessEscapes (char *iptr)
if (c == 'n') if (c == 'n')
c = '\n'; c = '\n';
else if (c == 'c') else if (c == 'c')
c = -127 /*0x81*/; c = TEXTCOLOR_ESCAPE;
else if (c == 'r') else if (c == 'r')
c = '\r'; c = '\r';
else if (c == 't') else if (c == 't')

View file

@ -49,7 +49,7 @@
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void TEAMINFO_Init (); void TEAMINFO_Init ();
void TEAMINFO_ParseTeam (); void TEAMINFO_ParseTeam (FScanner &sc);
bool TEAMINFO_IsValidTeam (int team); bool TEAMINFO_IsValidTeam (int team);
@ -84,17 +84,16 @@ void TEAMINFO_Init ()
while ((lump = Wads.FindLump ("TEAMINFO", &lastlump)) != -1) while ((lump = Wads.FindLump ("TEAMINFO", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "TEAMINFO"); FScanner sc(lump, "TEAMINFO");
while (SC_GetString ()) while (sc.GetString ())
{ {
if (SC_Compare("CLEARTEAMS")) if (sc.Compare("CLEARTEAMS"))
teams.Clear (); teams.Clear ();
else if (SC_Compare("TEAM")) else if (sc.Compare("TEAM"))
TEAMINFO_ParseTeam (); TEAMINFO_ParseTeam (sc);
else else
SC_ScriptError ("Unknown command %s in TEAMINFO", sc_String); sc.ScriptError ("Unknown command %s in TEAMINFO", sc.String);
} }
SC_Close();
} }
if (teams.Size () < 2) if (teams.Size () < 2)
@ -107,36 +106,34 @@ void TEAMINFO_Init ()
// //
//========================================================================== //==========================================================================
void TEAMINFO_ParseTeam () void TEAMINFO_ParseTeam (FScanner &sc)
{ {
TEAMINFO team; TEAMINFO team;
int i; int i;
char *color;
SC_MustGetString (); sc.MustGetString ();
team.name = sc_String; team.name = sc.String;
SC_MustGetStringName("{"); sc.MustGetStringName("{");
while (!SC_CheckString("}")) while (!sc.CheckString("}"))
{ {
SC_MustGetString(); sc.MustGetString();
switch(i = SC_MatchString (keywords_teaminfo)) switch(i = sc.MatchString (keywords_teaminfo))
{ {
case 0: case 0:
SC_MustGetString (); sc.MustGetString ();
color = sc_String; team.playercolor = V_GetColor (NULL, sc.String);
team.playercolor = V_GetColor (NULL, color);
break; break;
case 1: case 1:
SC_MustGetString(); sc.MustGetString();
team.textcolor = '['; team.textcolor = '[';
team.textcolor << sc_String << ']'; team.textcolor << sc.String << ']';
break; break;
case 2: case 2:
SC_MustGetString (); sc.MustGetString ();
team.logo = sc_String; team.logo = sc.String;
break; break;
default: default:

View file

@ -110,8 +110,8 @@ void A_ActiveSound (AActor *);
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void ParseInsideDecoration (FActorInfo *info, AActor *defaults, static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
TArray<FState> &states, FExtraInfo &extra, EDefinitionType def); TArray<FState> &states, FExtraInfo &extra, EDefinitionType def, FScanner &sc);
static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states); static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states, FScanner &sc);
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -229,7 +229,7 @@ static const char *FlagNames3[] =
// //
//========================================================================== //==========================================================================
void ParseOldDecoration(EDefinitionType def) void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{ {
TArray<FState> states; TArray<FState> states;
FExtraInfo extra; FExtraInfo extra;
@ -241,37 +241,37 @@ void ParseOldDecoration(EDefinitionType def)
if (def == DEF_Pickup) parent = RUNTIME_CLASS(AFakeInventory); if (def == DEF_Pickup) parent = RUNTIME_CLASS(AFakeInventory);
else parent = RUNTIME_CLASS(AActor); else parent = RUNTIME_CLASS(AActor);
SC_MustGetString(); sc.MustGetString();
typeName = FName(sc_String); typeName = FName(sc.String);
type = parent->CreateDerivedClass (typeName, parent->Size); type = parent->CreateDerivedClass (typeName, parent->Size);
info = type->ActorInfo; info = type->ActorInfo;
info->GameFilter = 0x80; info->GameFilter = 0x80;
MakeStateDefines(parent->ActorInfo->StateList); MakeStateDefines(parent->ActorInfo->StateList);
SC_MustGetString (); sc.MustGetString ();
while (!SC_Compare ("{")) while (!sc.Compare ("{"))
{ {
if (SC_Compare ("Doom")) if (sc.Compare ("Doom"))
{ {
info->GameFilter |= GAME_Doom; info->GameFilter |= GAME_Doom;
} }
else if (SC_Compare ("Heretic")) else if (sc.Compare ("Heretic"))
{ {
info->GameFilter |= GAME_Heretic; info->GameFilter |= GAME_Heretic;
} }
else if (SC_Compare ("Hexen")) else if (sc.Compare ("Hexen"))
{ {
info->GameFilter |= GAME_Hexen; info->GameFilter |= GAME_Hexen;
} }
else if (SC_Compare ("Raven")) else if (sc.Compare ("Raven"))
{ {
info->GameFilter |= GAME_Raven; info->GameFilter |= GAME_Raven;
} }
else if (SC_Compare ("Strife")) else if (sc.Compare ("Strife"))
{ {
info->GameFilter |= GAME_Strife; info->GameFilter |= GAME_Strife;
} }
else if (SC_Compare ("Any")) else if (sc.Compare ("Any"))
{ {
info->GameFilter = GAME_Any; info->GameFilter = GAME_Any;
} }
@ -279,17 +279,17 @@ void ParseOldDecoration(EDefinitionType def)
{ {
if (def != DEF_Decoration || info->GameFilter != 0x80) if (def != DEF_Decoration || info->GameFilter != 0x80)
{ {
SC_ScriptError ("Unknown game type %s in %s", sc_String, typeName.GetChars()); sc.ScriptError ("Unknown game type %s in %s", sc.String, typeName.GetChars());
} }
else else
{ {
// If this is a regular decoration (without preceding keyword) and no game // If this is a regular decoration (without preceding keyword) and no game
// filters defined this is more likely a general syntax error so output a // filters defined this is more likely a general syntax error so output a
// more meaningful message. // more meaningful message.
SC_ScriptError ("Syntax error: Unknown identifier '%s'", typeName.GetChars()); sc.ScriptError ("Syntax error: Unknown identifier '%s'", typeName.GetChars());
} }
} }
SC_MustGetString (); sc.MustGetString ();
} }
if (info->GameFilter == 0x80) if (info->GameFilter == 0x80)
{ {
@ -302,24 +302,24 @@ void ParseOldDecoration(EDefinitionType def)
states.Clear (); states.Clear ();
memset (&extra, 0, sizeof(extra)); memset (&extra, 0, sizeof(extra));
ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def); ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def, sc);
info->NumOwnedStates = states.Size(); info->NumOwnedStates = states.Size();
if (info->NumOwnedStates == 0) if (info->NumOwnedStates == 0)
{ {
SC_ScriptError ("%s does not define any animation frames", typeName.GetChars() ); sc.ScriptError ("%s does not define any animation frames", typeName.GetChars() );
} }
else if (extra.SpawnEnd == 0) else if (extra.SpawnEnd == 0)
{ {
SC_ScriptError ("%s does not have a Frames definition", typeName.GetChars() ); sc.ScriptError ("%s does not have a Frames definition", typeName.GetChars() );
} }
else if (def == DEF_BreakableDecoration && extra.DeathEnd == 0) else if (def == DEF_BreakableDecoration && extra.DeathEnd == 0)
{ {
SC_ScriptError ("%s does not have a DeathFrames definition", typeName.GetChars() ); sc.ScriptError ("%s does not have a DeathFrames definition", typeName.GetChars() );
} }
else if (extra.IceDeathEnd != 0 && extra.bGenericIceDeath) else if (extra.IceDeathEnd != 0 && extra.bGenericIceDeath)
{ {
SC_ScriptError ("You cannot use IceDeathFrames and GenericIceDeath together"); sc.ScriptError ("You cannot use IceDeathFrames and GenericIceDeath together");
} }
if (extra.IceDeathEnd != 0) if (extra.IceDeathEnd != 0)
@ -483,275 +483,271 @@ void ParseOldDecoration(EDefinitionType def)
//========================================================================== //==========================================================================
static void ParseInsideDecoration (FActorInfo *info, AActor *defaults, static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
TArray<FState> &states, FExtraInfo &extra, EDefinitionType def) TArray<FState> &states, FExtraInfo &extra, EDefinitionType def, FScanner &sc)
{ {
AFakeInventory *const inv = static_cast<AFakeInventory *>(defaults); AFakeInventory *const inv = static_cast<AFakeInventory *>(defaults);
char sprite[5] = "TNT1"; char sprite[5] = "TNT1";
SC_MustGetString (); sc.MustGetString ();
while (!SC_Compare ("}")) while (!sc.Compare ("}"))
{ {
if (SC_Compare ("DoomEdNum")) if (sc.Compare ("DoomEdNum"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
if (sc_Number < -1 || sc_Number > 32767) if (sc.Number < -1 || sc.Number > 32767)
{ {
SC_ScriptError ("DoomEdNum must be in the range [-1,32767]"); sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
} }
info->DoomEdNum = (SWORD)sc_Number; info->DoomEdNum = (SWORD)sc.Number;
} }
else if (SC_Compare ("SpawnNum")) else if (sc.Compare ("SpawnNum"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
if (sc_Number < 0 || sc_Number > 255) if (sc.Number < 0 || sc.Number > 255)
{ {
SC_ScriptError ("SpawnNum must be in the range [0,255]"); sc.ScriptError ("SpawnNum must be in the range [0,255]");
} }
info->SpawnID = (BYTE)sc_Number; info->SpawnID = (BYTE)sc.Number;
} }
else if (SC_Compare ("Sprite") || ( else if (sc.Compare ("Sprite") || (
(def == DEF_BreakableDecoration || def == DEF_Projectile) && (def == DEF_BreakableDecoration || def == DEF_Projectile) &&
SC_Compare ("DeathSprite") && sc.Compare ("DeathSprite") &&
(extra.DeathSprite[0] = 1)) // This is intentionally = and not == (extra.DeathSprite[0] = 1)) // This is intentionally = and not ==
) )
{ {
SC_MustGetString (); sc.MustGetString ();
if (strlen (sc_String) != 4) if (sc.StringLen != 4)
{ {
SC_ScriptError ("Sprite name must be exactly four characters long"); sc.ScriptError ("Sprite name must be exactly four characters long");
} }
if (extra.DeathSprite[0] == 1) if (extra.DeathSprite[0] == 1)
{ {
memcpy (extra.DeathSprite, sc_String, 4); memcpy (extra.DeathSprite, sc.String, 4);
} }
else else
{ {
memcpy (sprite, sc_String, 4); memcpy (sprite, sc.String, 4);
} }
} }
else if (SC_Compare ("Frames")) else if (sc.Compare ("Frames"))
{ {
SC_MustGetString (); sc.MustGetString ();
extra.SpawnStart = states.Size(); extra.SpawnStart = states.Size();
ParseSpriteFrames (info, states); ParseSpriteFrames (info, states, sc);
extra.SpawnEnd = states.Size(); extra.SpawnEnd = states.Size();
} }
else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) && else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) &&
SC_Compare ("DeathFrames")) sc.Compare ("DeathFrames"))
{ {
SC_MustGetString (); sc.MustGetString ();
extra.DeathStart = states.Size(); extra.DeathStart = states.Size();
ParseSpriteFrames (info, states); ParseSpriteFrames (info, states, sc);
extra.DeathEnd = states.Size(); extra.DeathEnd = states.Size();
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("IceDeathFrames")) else if (def == DEF_BreakableDecoration && sc.Compare ("IceDeathFrames"))
{ {
SC_MustGetString (); sc.MustGetString ();
extra.IceDeathStart = states.Size(); extra.IceDeathStart = states.Size();
ParseSpriteFrames (info, states); ParseSpriteFrames (info, states, sc);
extra.IceDeathEnd = states.Size(); extra.IceDeathEnd = states.Size();
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("BurnDeathFrames")) else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathFrames"))
{ {
SC_MustGetString (); sc.MustGetString ();
extra.FireDeathStart = states.Size(); extra.FireDeathStart = states.Size();
ParseSpriteFrames (info, states); ParseSpriteFrames (info, states, sc);
extra.FireDeathEnd = states.Size(); extra.FireDeathEnd = states.Size();
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("GenericIceDeath")) else if (def == DEF_BreakableDecoration && sc.Compare ("GenericIceDeath"))
{ {
extra.bGenericIceDeath = true; extra.bGenericIceDeath = true;
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("BurnsAway")) else if (def == DEF_BreakableDecoration && sc.Compare ("BurnsAway"))
{ {
extra.bBurnAway = true; extra.bBurnAway = true;
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("DiesAway")) else if (def == DEF_BreakableDecoration && sc.Compare ("DiesAway"))
{ {
extra.bDiesAway = true; extra.bDiesAway = true;
} }
else if (SC_Compare ("Alpha")) else if (sc.Compare ("Alpha"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->alpha = int(clamp (sc_Float, 0.0, 1.0) * OPAQUE); defaults->alpha = int(clamp (sc.Float, 0.0, 1.0) * OPAQUE);
} }
else if (SC_Compare ("Scale")) else if (sc.Compare ("Scale"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->scaleX = defaults->scaleY = FLOAT2FIXED(sc_Float); defaults->scaleX = defaults->scaleY = FLOAT2FIXED(sc.Float);
} }
else if (SC_Compare ("RenderStyle")) else if (sc.Compare ("RenderStyle"))
{ {
SC_MustGetString (); sc.MustGetString ();
defaults->RenderStyle = SC_MustMatchString (RenderStyles); defaults->RenderStyle = LegacyRenderStyles[sc.MustMatchString (RenderStyles)];
if (defaults->RenderStyle > STYLE_OptFuzzy)
{
defaults->RenderStyle += STYLE_Translucent - STYLE_OptFuzzy - 1;
}
} }
else if (SC_Compare ("Radius")) else if (sc.Compare ("Radius"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->radius = int(sc_Float * FRACUNIT); defaults->radius = int(sc.Float * FRACUNIT);
} }
else if (SC_Compare ("Height")) else if (sc.Compare ("Height"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->height = int(sc_Float * FRACUNIT); defaults->height = int(sc.Float * FRACUNIT);
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("DeathHeight")) else if (def == DEF_BreakableDecoration && sc.Compare ("DeathHeight"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
extra.DeathHeight = int(sc_Float * FRACUNIT); extra.DeathHeight = int(sc.Float * FRACUNIT);
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("BurnHeight")) else if (def == DEF_BreakableDecoration && sc.Compare ("BurnHeight"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
extra.BurnHeight = int(sc_Float * FRACUNIT); extra.BurnHeight = int(sc.Float * FRACUNIT);
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("Health")) else if (def == DEF_BreakableDecoration && sc.Compare ("Health"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
defaults->health = sc_Number; defaults->health = sc.Number;
} }
else if (def == DEF_Projectile && SC_Compare ("ExplosionRadius")) else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
info->Class->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc_Number); info->Class->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc.Number);
extra.bExplosive = true; extra.bExplosive = true;
} }
else if (def == DEF_Projectile && SC_Compare ("ExplosionDamage")) else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
info->Class->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc_Number); info->Class->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc.Number);
extra.bExplosive = true; extra.bExplosive = true;
} }
else if (def == DEF_Projectile && SC_Compare ("DoNotHurtShooter")) else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter"))
{ {
info->Class->Meta.SetMetaInt(ACMETA_DontHurtShooter, true); info->Class->Meta.SetMetaInt(ACMETA_DontHurtShooter, true);
} }
else if (def == DEF_Projectile && SC_Compare ("Damage")) else if (def == DEF_Projectile && sc.Compare ("Damage"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
defaults->Damage = sc_Number; defaults->Damage = sc.Number;
} }
else if (def == DEF_Projectile && SC_Compare ("DamageType")) else if (def == DEF_Projectile && sc.Compare ("DamageType"))
{ {
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("Normal")) if (sc.Compare ("Normal"))
{ {
defaults->DamageType = NAME_None; defaults->DamageType = NAME_None;
} }
else else
{ {
defaults->DamageType = sc_String; defaults->DamageType = sc.String;
} }
} }
else if (def == DEF_Projectile && SC_Compare ("Speed")) else if (def == DEF_Projectile && sc.Compare ("Speed"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->Speed = fixed_t(sc_Float * 65536.f); defaults->Speed = fixed_t(sc.Float * 65536.f);
} }
else if (SC_Compare ("Mass")) else if (sc.Compare ("Mass"))
{ {
SC_MustGetFloat (); sc.MustGetFloat ();
defaults->Mass = SDWORD(sc_Float); defaults->Mass = SDWORD(sc.Float);
} }
else if (SC_Compare ("Translation1")) else if (sc.Compare ("Translation1"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
if (sc_Number < 0 || sc_Number > 2) if (sc.Number < 0 || sc.Number > 2)
{ {
SC_ScriptError ("Translation1 must be in the range [0,2]"); sc.ScriptError ("Translation1 must be in the range [0,2]");
} }
defaults->Translation = TRANSLATION(TRANSLATION_Standard, sc_Number); defaults->Translation = TRANSLATION(TRANSLATION_Standard, sc.Number);
} }
else if (SC_Compare ("Translation2")) else if (sc.Compare ("Translation2"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
if (sc_Number < 0 || sc_Number >= MAX_ACS_TRANSLATIONS) if (sc.Number < 0 || sc.Number >= MAX_ACS_TRANSLATIONS)
{ {
#define ERROR(foo) "Translation2 must be in the range [0," #foo "]" #define ERROR(foo) "Translation2 must be in the range [0," #foo "]"
SC_ScriptError (ERROR(MAX_ACS_TRANSLATIONS)); sc.ScriptError (ERROR(MAX_ACS_TRANSLATIONS));
#undef ERROR #undef ERROR
} }
defaults->Translation = TRANSLATION(TRANSLATION_LevelScripted, sc_Number); defaults->Translation = TRANSLATION(TRANSLATION_LevelScripted, sc.Number);
} }
else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) && else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) &&
SC_Compare ("DeathSound")) sc.Compare ("DeathSound"))
{ {
SC_MustGetString (); sc.MustGetString ();
defaults->DeathSound = S_FindSound (sc_String); defaults->DeathSound = S_FindSound (sc.String);
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("BurnDeathSound")) else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathSound"))
{ {
SC_MustGetString (); sc.MustGetString ();
defaults->ActiveSound = S_FindSound (sc_String); defaults->ActiveSound = S_FindSound (sc.String);
} }
else if (def == DEF_Projectile && SC_Compare ("SpawnSound")) else if (def == DEF_Projectile && sc.Compare ("SpawnSound"))
{ {
SC_MustGetString (); sc.MustGetString ();
defaults->SeeSound = S_FindSound (sc_String); defaults->SeeSound = S_FindSound (sc.String);
} }
else if (def == DEF_Projectile && SC_Compare ("DoomBounce")) else if (def == DEF_Projectile && sc.Compare ("DoomBounce"))
{ {
defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_DOOMBOUNCE; defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_DOOMBOUNCE;
} }
else if (def == DEF_Projectile && SC_Compare ("HereticBounce")) else if (def == DEF_Projectile && sc.Compare ("HereticBounce"))
{ {
defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_HERETICBOUNCE; defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_HERETICBOUNCE;
} }
else if (def == DEF_Projectile && SC_Compare ("HexenBounce")) else if (def == DEF_Projectile && sc.Compare ("HexenBounce"))
{ {
defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_HEXENBOUNCE; defaults->flags2 = (defaults->flags2 & ~MF2_BOUNCETYPE) | MF2_HEXENBOUNCE;
} }
else if (def == DEF_Pickup && SC_Compare ("PickupSound")) else if (def == DEF_Pickup && sc.Compare ("PickupSound"))
{ {
SC_MustGetString (); sc.MustGetString ();
inv->PickupSound = S_FindSound (sc_String); inv->PickupSound = S_FindSound (sc.String);
} }
else if (def == DEF_Pickup && SC_Compare ("PickupMessage")) else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{ {
SC_MustGetString (); sc.MustGetString ();
info->Class->Meta.SetMetaString(AIMETA_PickupMessage, sc_String); info->Class->Meta.SetMetaString(AIMETA_PickupMessage, sc.String);
} }
else if (def == DEF_Pickup && SC_Compare ("Respawns")) else if (def == DEF_Pickup && sc.Compare ("Respawns"))
{ {
inv->Respawnable = true; inv->Respawnable = true;
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("SolidOnDeath")) else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath"))
{ {
extra.bSolidOnDeath = true; extra.bSolidOnDeath = true;
} }
else if (def == DEF_BreakableDecoration && SC_Compare ("SolidOnBurn")) else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnBurn"))
{ {
extra.bSolidOnBurn = true; extra.bSolidOnBurn = true;
} }
else if (sc_String[0] != '*') else if (sc.String[0] != '*')
{ {
int bit = SC_MatchString (FlagNames1); int bit = sc.MatchString (FlagNames1);
if (bit != -1) if (bit != -1)
{ {
defaults->flags |= 1 << bit; defaults->flags |= 1 << bit;
} }
else if ((bit = SC_MatchString (FlagNames2)) != -1) else if ((bit = sc.MatchString (FlagNames2)) != -1)
{ {
defaults->flags2 |= 1 << bit; defaults->flags2 |= 1 << bit;
} }
else if ((bit = SC_MatchString (FlagNames3)) != -1) else if ((bit = sc.MatchString (FlagNames3)) != -1)
{ {
defaults->flags3 |= 1 << bit; defaults->flags3 |= 1 << bit;
} }
else else
{ {
SC_ScriptError (NULL); sc.ScriptError (NULL);
} }
} }
else else
{ {
SC_ScriptError (NULL); sc.ScriptError (NULL);
} }
SC_MustGetString (); sc.MustGetString ();
} }
unsigned int i; unsigned int i;
@ -798,10 +794,10 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
// "10:A, 15:B, 8:C, 6:B" // "10:A, 15:B, 8:C, 6:B"
//========================================================================== //==========================================================================
static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states) static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states, FScanner &sc)
{ {
FState state; FState state;
char *token = strtok (sc_String, ",\t\n\r"); char *token = strtok (sc.String, ",\t\n\r");
memset (&state, 0, sizeof(state)); memset (&state, 0, sizeof(state));
@ -823,7 +819,7 @@ static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states)
rate = strtol (token, &stop, 10); rate = strtol (token, &stop, 10);
if (stop == token || rate < 1 || rate > 65534) if (stop == token || rate < 1 || rate > 65534)
{ {
SC_ScriptError ("Rates must be in the range [0,65534]"); sc.ScriptError ("Rates must be in the range [0,65534]");
} }
token = colon + 1; token = colon + 1;
rate += 1; rate += 1;
@ -841,13 +837,13 @@ static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states)
{ {
if (firstState) if (firstState)
{ {
SC_ScriptError ("* must come after a frame"); sc.ScriptError ("* must come after a frame");
} }
state.Frame |= SF_FULLBRIGHT; state.Frame |= SF_FULLBRIGHT;
} }
else if (*token < 'A' || *token > ']') else if (*token < 'A' || *token > ']')
{ {
SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); sc.ScriptError ("Frames must be A-Z, [, \\, or ]");
} }
else else
{ {

View file

@ -82,16 +82,16 @@ const PClass *QuestItemClasses[31];
// //
//========================================================================== //==========================================================================
void ParseConstant (PSymbolTable * symt, PClass *cls) void ParseConstant (FScanner &sc, PSymbolTable * symt, PClass *cls)
{ {
// Read the type and make sure it's int. // Read the type and make sure it's int.
// (Maybe there will be other types later.) // (Maybe there will be other types later.)
SC_MustGetToken(TK_Int); sc.MustGetToken(TK_Int);
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
FName symname = sc_String; FName symname = sc.String;
SC_MustGetToken('='); sc.MustGetToken('=');
int expr = ParseExpression (false, cls); int expr = ParseExpression (sc, false, cls);
SC_MustGetToken(';'); sc.MustGetToken(';');
int val = EvalExpressionI (expr, NULL, cls); int val = EvalExpressionI (expr, NULL, cls);
PSymbolConst *sym = new PSymbolConst; PSymbolConst *sym = new PSymbolConst;
@ -101,7 +101,7 @@ void ParseConstant (PSymbolTable * symt, PClass *cls)
if (symt->AddSymbol (sym) == NULL) if (symt->AddSymbol (sym) == NULL)
{ {
delete sym; delete sym;
SC_ScriptError ("'%s' is already defined in class '%s'.", sc.ScriptError ("'%s' is already defined in class '%s'.",
symname.GetChars(), cls->TypeName.GetChars()); symname.GetChars(), cls->TypeName.GetChars());
} }
} }
@ -114,19 +114,19 @@ void ParseConstant (PSymbolTable * symt, PClass *cls)
// //
//========================================================================== //==========================================================================
void ParseEnum (PSymbolTable * symt, PClass *cls) void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
{ {
int currvalue = 0; int currvalue = 0;
SC_MustGetToken('{'); sc.MustGetToken('{');
while (!SC_CheckToken('}')) while (!sc.CheckToken('}'))
{ {
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
FName symname = sc_String; FName symname = sc.String;
if (SC_CheckToken('=')) if (sc.CheckToken('='))
{ {
int expr = ParseExpression(false, cls); int expr = ParseExpression(sc, false, cls);
currvalue = EvalExpressionI (expr, NULL, cls); currvalue = EvalExpressionI(expr, NULL, cls);
} }
PSymbolConst *sym = new PSymbolConst; PSymbolConst *sym = new PSymbolConst;
sym->SymbolName = symname; sym->SymbolName = symname;
@ -135,15 +135,15 @@ void ParseEnum (PSymbolTable * symt, PClass *cls)
if (symt->AddSymbol (sym) == NULL) if (symt->AddSymbol (sym) == NULL)
{ {
delete sym; delete sym;
SC_ScriptError ("'%s' is already defined in class '%s'.", sc.ScriptError ("'%s' is already defined in class '%s'.",
symname.GetChars(), cls->TypeName.GetChars()); symname.GetChars(), cls->TypeName.GetChars());
} }
// This allows a comma after the last value but doesn't enforce it. // This allows a comma after the last value but doesn't enforce it.
if (SC_CheckToken('}')) break; if (sc.CheckToken('}')) break;
SC_MustGetToken(','); sc.MustGetToken(',');
currvalue++; currvalue++;
} }
SC_MustGetToken(';'); sc.MustGetToken(';');
} }
//========================================================================== //==========================================================================
@ -156,7 +156,7 @@ void ParseEnum (PSymbolTable * symt, PClass *cls)
// //
//========================================================================== //==========================================================================
static void ParseActionDef (PClass *cls) static void ParseActionDef (FScanner &sc, PClass *cls)
{ {
#define OPTIONAL 1 #define OPTIONAL 1
#define EVAL 2 #define EVAL 2
@ -166,18 +166,18 @@ static void ParseActionDef (PClass *cls)
FName funcname; FName funcname;
FString args; FString args;
SC_MustGetToken(TK_Native); sc.MustGetToken(TK_Native);
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
funcname = sc_String; funcname = sc.String;
afd = FindFunction(sc_String); afd = FindFunction(sc.String);
if (afd == NULL) if (afd == NULL)
{ {
SC_ScriptError ("The function '%s' has not been exported from the executable.", sc_String); sc.ScriptError ("The function '%s' has not been exported from the executable.", sc.String);
} }
SC_MustGetToken('('); sc.MustGetToken('(');
if (!SC_CheckToken(')')) if (!sc.CheckToken(')'))
{ {
while (sc_TokenType != ')') while (sc.TokenType != ')')
{ {
int flags = 0; int flags = 0;
char type = '@'; char type = '@';
@ -185,19 +185,19 @@ static void ParseActionDef (PClass *cls)
// Retrieve flags before type name // Retrieve flags before type name
for (;;) for (;;)
{ {
if (SC_CheckToken(TK_Optional)) if (sc.CheckToken(TK_Optional))
{ {
flags |= OPTIONAL; flags |= OPTIONAL;
} }
else if (SC_CheckToken(TK_Eval)) else if (sc.CheckToken(TK_Eval))
{ {
flags |= EVAL; flags |= EVAL;
} }
else if (SC_CheckToken(TK_EvalNot)) else if (sc.CheckToken(TK_EvalNot))
{ {
flags |= EVALNOT; flags |= EVALNOT;
} }
else if (SC_CheckToken(TK_Coerce) || SC_CheckToken(TK_Native)) else if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native))
{ {
} }
else else
@ -206,8 +206,8 @@ static void ParseActionDef (PClass *cls)
} }
} }
// Read the variable type // Read the variable type
SC_MustGetAnyToken(); sc.MustGetAnyToken();
switch (sc_TokenType) switch (sc.TokenType)
{ {
case TK_Bool: type = 'i'; break; case TK_Bool: type = 'i'; break;
case TK_Int: type = 'i'; break; case TK_Int: type = 'i'; break;
@ -218,28 +218,28 @@ static void ParseActionDef (PClass *cls)
case TK_State: type = 'l'; break; case TK_State: type = 'l'; break;
case TK_Color: type = 'c'; break; case TK_Color: type = 'c'; break;
case TK_Class: case TK_Class:
SC_MustGetToken('<'); sc.MustGetToken('<');
SC_MustGetToken(TK_Identifier); // Skip class name, since the parser doesn't care sc.MustGetToken(TK_Identifier); // Skip class name, since the parser doesn't care
SC_MustGetToken('>'); sc.MustGetToken('>');
type = 'm'; type = 'm';
break; break;
case TK_Ellipsis: case TK_Ellipsis:
type = '+'; type = '+';
SC_MustGetToken(')'); sc.MustGetToken(')');
SC_UnGet(); sc.UnGet();
break; break;
default: default:
SC_ScriptError ("Unknown variable type %s", SC_TokenName(sc_TokenType, sc_String).GetChars()); sc.ScriptError ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars());
break; break;
} }
// Read the optional variable name // Read the optional variable name
if (!SC_CheckToken(',') && !SC_CheckToken(')')) if (!sc.CheckToken(',') && !sc.CheckToken(')'))
{ {
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
} }
else else
{ {
SC_UnGet(); sc.UnGet();
} }
// If eval or evalnot were a flag, hey the decorate parser doesn't actually care about the type. // If eval or evalnot were a flag, hey the decorate parser doesn't actually care about the type.
if (flags & EVALNOT) if (flags & EVALNOT)
@ -258,14 +258,14 @@ static void ParseActionDef (PClass *cls)
#undef EVAL #undef EVAL
#undef EVALNOT #undef EVALNOT
args += type; args += type;
SC_MustGetAnyToken(); sc.MustGetAnyToken();
if (sc_TokenType != ',' && sc_TokenType != ')') if (sc.TokenType != ',' && sc.TokenType != ')')
{ {
SC_ScriptError ("Expected ',' or ')' but got %s instead", SC_TokenName(sc_TokenType, sc_String).GetChars()); sc.ScriptError ("Expected ',' or ')' but got %s instead", sc.TokenName(sc.TokenType, sc.String).GetChars());
} }
} }
} }
SC_MustGetToken(';'); sc.MustGetToken(';');
PSymbolActionFunction *sym = new PSymbolActionFunction; PSymbolActionFunction *sym = new PSymbolActionFunction;
sym->SymbolName = funcname; sym->SymbolName = funcname;
sym->SymbolType = SYM_ActionFunction; sym->SymbolType = SYM_ActionFunction;
@ -274,7 +274,7 @@ static void ParseActionDef (PClass *cls)
if (cls->Symbols.AddSymbol (sym) == NULL) if (cls->Symbols.AddSymbol (sym) == NULL)
{ {
delete sym; delete sym;
SC_ScriptError ("'%s' is already defined in class '%s'.", sc.ScriptError ("'%s' is already defined in class '%s'.",
funcname.GetChars(), cls->TypeName.GetChars()); funcname.GetChars(), cls->TypeName.GetChars());
} }
} }
@ -284,27 +284,27 @@ static void ParseActionDef (PClass *cls)
// Starts a new actor definition // Starts a new actor definition
// //
//========================================================================== //==========================================================================
static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag) static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *bag)
{ {
FName typeName; FName typeName;
// Get actor name // Get actor name
SC_MustGetString(); sc.MustGetString();
char * colon = strchr(sc_String, ':'); char *colon = strchr(sc.String, ':');
if (colon != NULL) if (colon != NULL)
{ {
*colon++ = 0; *colon++ = 0;
} }
if (PClass::FindClass (sc_String) != NULL) if (PClass::FindClass (sc.String) != NULL)
{ {
SC_ScriptError ("Actor %s is already defined.", sc_String); sc.ScriptError ("Actor %s is already defined.", sc.String);
} }
typeName = sc_String; typeName = sc.String;
PClass * parent = RUNTIME_CLASS(AActor); PClass *parent = RUNTIME_CLASS(AActor);
if (parentc) if (parentc)
{ {
*parentc = NULL; *parentc = NULL;
@ -313,10 +313,10 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
// without having resort to C-mode (which disallows periods in actor names.) // without having resort to C-mode (which disallows periods in actor names.)
if (colon == NULL) if (colon == NULL)
{ {
SC_MustGetString (); sc.MustGetString ();
if (sc_String[0]==':') if (sc.String[0]==':')
{ {
colon = sc_String + 1; colon = sc.String + 1;
} }
} }
@ -324,8 +324,8 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
{ {
if (colon[0] == 0) if (colon[0] == 0)
{ {
SC_MustGetString (); sc.MustGetString ();
colon = sc_String; colon = sc.String;
} }
} }
@ -335,22 +335,22 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
if (parent == NULL) if (parent == NULL)
{ {
SC_ScriptError ("Parent type '%s' not found", colon); sc.ScriptError ("Parent type '%s' not found", colon);
} }
else if (parent->ActorInfo == NULL) else if (parent->ActorInfo == NULL)
{ {
SC_ScriptError ("Parent type '%s' is not an actor", colon); sc.ScriptError ("Parent type '%s' is not an actor", colon);
} }
else else
{ {
*parentc = parent->ActorInfo; *parentc = parent->ActorInfo;
} }
} }
else SC_UnGet(); else sc.UnGet();
} }
PClass * ti = parent->CreateDerivedClass (typeName, parent->Size); PClass *ti = parent->CreateDerivedClass (typeName, parent->Size);
FActorInfo * info = ti->ActorInfo; FActorInfo *info = ti->ActorInfo;
MakeStateDefines(parent->ActorInfo->StateList); MakeStateDefines(parent->ActorInfo->StateList);
@ -372,38 +372,38 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
} }
// Check for "replaces" // Check for "replaces"
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare ("replaces")) if (sc.Compare ("replaces"))
{ {
const PClass *replacee; const PClass *replacee;
// Get actor name // Get actor name
SC_MustGetString (); sc.MustGetString ();
replacee = PClass::FindClass (sc_String); replacee = PClass::FindClass (sc.String);
if (replacee == NULL) if (replacee == NULL)
{ {
SC_ScriptError ("Replaced type '%s' not found", sc_String); sc.ScriptError ("Replaced type '%s' not found", sc.String);
} }
else if (replacee->ActorInfo == NULL) else if (replacee->ActorInfo == NULL)
{ {
SC_ScriptError ("Replaced type '%s' is not an actor", sc_String); sc.ScriptError ("Replaced type '%s' is not an actor", sc.String);
} }
replacee->ActorInfo->Replacement = ti->ActorInfo; replacee->ActorInfo->Replacement = ti->ActorInfo;
ti->ActorInfo->Replacee = replacee->ActorInfo; ti->ActorInfo->Replacee = replacee->ActorInfo;
} }
else else
{ {
SC_UnGet(); sc.UnGet();
} }
// Now, after the actor names have been parsed, it is time to switch to C-mode // Now, after the actor names have been parsed, it is time to switch to C-mode
// for the rest of the actor definition. // for the rest of the actor definition.
SC_SetCMode (true); sc.SetCMode (true);
if (SC_CheckNumber()) if (sc.CheckNumber())
{ {
if (sc_Number>=-1 && sc_Number<32768) info->DoomEdNum = sc_Number; if (sc.Number>=-1 && sc.Number<32768) info->DoomEdNum = sc.Number;
else SC_ScriptError ("DoomEdNum must be in the range [-1,32767]"); else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
} }
if (parent == RUNTIME_CLASS(AWeapon)) if (parent == RUNTIME_CLASS(AWeapon))
{ {
@ -419,7 +419,7 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
// Reads an actor definition // Reads an actor definition
// //
//========================================================================== //==========================================================================
void ParseActor() void ParseActor(FScanner &sc)
{ {
FActorInfo * info=NULL; FActorInfo * info=NULL;
Baggage bag; Baggage bag;
@ -428,43 +428,43 @@ void ParseActor()
{ {
FActorInfo * parent; FActorInfo * parent;
info=CreateNewActor(&parent, &bag); info = CreateNewActor(sc, &parent, &bag);
SC_MustGetToken('{'); sc.MustGetToken('{');
while (SC_MustGetAnyToken(), sc_TokenType != '}') while (sc.MustGetAnyToken(), sc.TokenType != '}')
{ {
switch (sc_TokenType) switch (sc.TokenType)
{ {
case TK_Action: case TK_Action:
ParseActionDef (info->Class); ParseActionDef (sc, info->Class);
break; break;
case TK_Const: case TK_Const:
ParseConstant (&info->Class->Symbols, info->Class); ParseConstant (sc, &info->Class->Symbols, info->Class);
break; break;
case TK_Enum: case TK_Enum:
ParseEnum (&info->Class->Symbols, info->Class); ParseEnum (sc, &info->Class->Symbols, info->Class);
break; break;
case TK_Identifier: case TK_Identifier:
// other identifier related checks here // other identifier related checks here
case TK_Projectile: // special case: both keyword and property name case TK_Projectile: // special case: both keyword and property name
ParseActorProperty(bag); ParseActorProperty(sc, bag);
break; break;
case '+': case '+':
case '-': case '-':
ParseActorFlag(bag, sc_TokenType); ParseActorFlag(sc, bag, sc.TokenType);
break; break;
default: default:
SC_ScriptError("Unexpected '%s' in definition of '%s'", sc_String, bag.Info->Class->TypeName.GetChars()); sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
break; break;
} }
} }
FinishActor(info, bag); FinishActor(sc, info, bag);
} }
catch(CRecoverableError & e) catch(CRecoverableError & e)
@ -476,13 +476,13 @@ void ParseActor()
catch (...) catch (...)
{ {
if (info) if (info)
SC_ScriptError("Unexpected error during parsing of actor %s", info->Class->TypeName.GetChars()); sc.ScriptError("Unexpected error during parsing of actor %s", info->Class->TypeName.GetChars());
else else
SC_ScriptError("Unexpected error during parsing of actor definitions"); sc.ScriptError("Unexpected error during parsing of actor definitions");
} }
#endif #endif
SC_SetCMode (false); sc.SetCMode (false);
} }
//========================================================================== //==========================================================================
@ -635,52 +635,52 @@ void FinishThingdef()
// //
//========================================================================== //==========================================================================
void ParseClass() void ParseClass(FScanner &sc)
{ {
Baggage bag; Baggage bag;
PClass *cls; PClass *cls;
FName classname; FName classname;
FName supername; FName supername;
SC_MustGetToken(TK_Identifier); // class name sc.MustGetToken(TK_Identifier); // class name
classname = sc_String; classname = sc.String;
SC_MustGetToken(TK_Extends); // because I'm not supporting Object sc.MustGetToken(TK_Extends); // because I'm not supporting Object
SC_MustGetToken(TK_Identifier); // superclass name sc.MustGetToken(TK_Identifier); // superclass name
supername = sc_String; supername = sc.String;
SC_MustGetToken(TK_Native); // use actor definitions for your own stuff sc.MustGetToken(TK_Native); // use actor definitions for your own stuff
SC_MustGetToken('{'); sc.MustGetToken('{');
cls = const_cast<PClass*>(PClass::FindClass (classname)); cls = const_cast<PClass*>(PClass::FindClass (classname));
if (cls == NULL) if (cls == NULL)
{ {
SC_ScriptError ("'%s' is not a native class", classname.GetChars()); sc.ScriptError ("'%s' is not a native class", classname.GetChars());
} }
if (cls->ParentClass == NULL || cls->ParentClass->TypeName != supername) if (cls->ParentClass == NULL || cls->ParentClass->TypeName != supername)
{ {
SC_ScriptError ("'%s' does not extend '%s'", classname.GetChars(), supername.GetChars()); sc.ScriptError ("'%s' does not extend '%s'", classname.GetChars(), supername.GetChars());
} }
bag.Info = cls->ActorInfo; bag.Info = cls->ActorInfo;
SC_MustGetAnyToken(); sc.MustGetAnyToken();
while (sc_TokenType != '}') while (sc.TokenType != '}')
{ {
if (sc_TokenType == TK_Action) if (sc.TokenType == TK_Action)
{ {
ParseActionDef(cls); ParseActionDef(sc, cls);
} }
else if (sc_TokenType == TK_Const) else if (sc.TokenType == TK_Const)
{ {
ParseConstant(&cls->Symbols, cls); ParseConstant(sc, &cls->Symbols, cls);
} }
else if (sc_TokenType == TK_Enum) else if (sc.TokenType == TK_Enum)
{ {
ParseEnum(&cls->Symbols, cls); ParseEnum(sc, &cls->Symbols, cls);
} }
else else
{ {
FString tokname = SC_TokenName(sc_TokenType, sc_String); FString tokname = sc.TokenName(sc.TokenType, sc.String);
SC_ScriptError ("Expected 'action', 'const' or 'enum' but got %s", tokname.GetChars()); sc.ScriptError ("Expected 'action', 'const' or 'enum' but got %s", tokname.GetChars());
} }
SC_MustGetAnyToken(); sc.MustGetAnyToken();
} }
} }

View file

@ -1,6 +1,8 @@
#ifndef __THINGDEF_H #ifndef __THINGDEF_H
#define __THINGDEF_H #define __THINGDEF_H
class FScanner;
//========================================================================== //==========================================================================
// //
// This class is for storing a name inside a const PClass* field without // This class is for storing a name inside a const PClass* field without
@ -97,9 +99,9 @@ FState * FindState(AActor * actor, const PClass * type, const char * name);
void InstallStates(FActorInfo *info, AActor *defaults); void InstallStates(FActorInfo *info, AActor *defaults);
void MakeStateDefines(const FStateLabels *list); void MakeStateDefines(const FStateLabels *list);
FState *P_GetState(AActor *self, FState *CallingState, int offset); FState *P_GetState(AActor *self, FState *CallingState, int offset);
int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag); int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
int ParseStates(FActorInfo * actor, AActor * defaults, Baggage &bag); int ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
FState *CheckState(PClass *type); FState *CheckState(FScanner &sc, PClass *type);
//========================================================================== //==========================================================================
@ -108,15 +110,15 @@ FState *CheckState(PClass *type);
// //
//========================================================================== //==========================================================================
void ParseActorProperty(Baggage &bag); void ParseActorProperty(FScanner &sc, Baggage &bag);
void ParseActorFlag (Baggage &bag, int mod); void ParseActorFlag (FScanner &sc, Baggage &bag, int mod);
void FinishActor(FActorInfo *info, Baggage &bag); void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag);
void ParseConstant (PSymbolTable * symt, PClass *cls); void ParseConstant (FScanner &sc, PSymbolTable *symt, PClass *cls);
void ParseEnum (PSymbolTable * symt, PClass *cls); void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls);
int ParseExpression (bool _not, PClass *cls); int ParseExpression (FScanner &sc, bool _not, PClass *cls);
int EvalExpressionI (int id, AActor *self, const PClass *cls=NULL); int EvalExpressionI (int id, AActor *self, const PClass *cls=NULL);
float EvalExpressionF (int id, AActor *self, const PClass *cls=NULL); float EvalExpressionF (int id, AActor *self, const PClass *cls=NULL);

View file

@ -1190,21 +1190,22 @@ void A_RailAttack (AActor * self)
void A_CustomRailgun (AActor *actor) void A_CustomRailgun (AActor *actor)
{ {
if (!actor->target) int index = CheckIndex(7);
if (index < 0) return;
int Damage = EvalExpressionI (StateParameters[index], actor);
int Spawnofs_XY = EvalExpressionI (StateParameters[index+1], actor);
int Color1 = StateParameters[index+2];
int Color2 = StateParameters[index+3];
bool Silent = !!EvalExpressionI (StateParameters[index+4], actor);
bool aim = !!EvalExpressionI (StateParameters[index+5], actor);
float MaxDiff = EvalExpressionF (StateParameters[index+6], actor);
ENamedName PuffTypeName = (ENamedName)StateParameters[index+7];
if (aim && actor->target == NULL)
{
return; return;
}
int index=CheckIndex(7);
if (index<0) return;
int Damage=EvalExpressionI (StateParameters[index], actor);
int Spawnofs_XY=EvalExpressionI (StateParameters[index+1], actor);
int Color1=StateParameters[index+2];
int Color2=StateParameters[index+3];
bool Silent=!!EvalExpressionI (StateParameters[index+4], actor);
bool aim=!!EvalExpressionI (StateParameters[index+5], actor);
float MaxDiff=EvalExpressionF (StateParameters[index+6], actor);
ENamedName PuffTypeName=(ENamedName)StateParameters[index+7];
// [RH] Andy Baker's stealth monsters // [RH] Andy Baker's stealth monsters
if (actor->flags & MF_STEALTH) if (actor->flags & MF_STEALTH)
{ {
@ -1212,7 +1213,7 @@ void A_CustomRailgun (AActor *actor)
} }
actor->flags &= ~MF_AMBUSH; actor->flags &= ~MF_AMBUSH;
if (aim) if (aim)
{ {
actor->angle = R_PointToAngle2 (actor->x, actor->angle = R_PointToAngle2 (actor->x,
@ -1692,15 +1693,9 @@ void A_SetTranslucent(AActor * self)
int mode = EvalExpressionI (StateParameters[index+1], self); int mode = EvalExpressionI (StateParameters[index+1], self);
mode = mode == 0 ? STYLE_Translucent : mode == 2 ? STYLE_Fuzzy : STYLE_Add; mode = mode == 0 ? STYLE_Translucent : mode == 2 ? STYLE_Fuzzy : STYLE_Add;
self->alpha=clamp<fixed_t>(alpha, 0, FRACUNIT); self->RenderStyle.Flags &= ~STYLEF_Alpha1;
self->alpha = clamp<fixed_t>(alpha, 0, FRACUNIT);
if (mode != STYLE_Fuzzy) self->RenderStyle = ERenderStyle(mode);
{
if (self->alpha == 0) mode = STYLE_None;
else if (mode == STYLE_Translucent && self->alpha >= FRACUNIT) mode = STYLE_Normal;
}
self->RenderStyle=mode;
} }
//=========================================================================== //===========================================================================
@ -1722,7 +1717,7 @@ void A_FadeIn(AActor * self)
if (reduce == 0) reduce = FRACUNIT/10; if (reduce == 0) reduce = FRACUNIT/10;
if (self->RenderStyle==STYLE_Normal) self->RenderStyle=STYLE_Translucent; self->RenderStyle.Flags &= ~STYLEF_Alpha1;
self->alpha += reduce; self->alpha += reduce;
//if (self->alpha<=0) self->Destroy(); //if (self->alpha<=0) self->Destroy();
} }
@ -1746,7 +1741,7 @@ void A_FadeOut(AActor * self)
if (reduce == 0) reduce = FRACUNIT/10; if (reduce == 0) reduce = FRACUNIT/10;
if (self->RenderStyle==STYLE_Normal) self->RenderStyle=STYLE_Translucent; self->RenderStyle.Flags &= ~STYLEF_Alpha1;
self->alpha -= reduce; self->alpha -= reduce;
if (self->alpha<=0) self->Destroy(); if (self->alpha<=0) self->Destroy();
} }

View file

@ -378,21 +378,21 @@ TArray<ExpData *> StateExpressions;
// [GRB] Parses an expression and stores it into Expression array // [GRB] Parses an expression and stores it into Expression array
// //
static ExpData *ParseExpressionM (const PClass *cls); static ExpData *ParseExpressionM (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionL (const PClass *cls); static ExpData *ParseExpressionL (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionK (const PClass *cls); static ExpData *ParseExpressionK (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionJ (const PClass *cls); static ExpData *ParseExpressionJ (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionI (const PClass *cls); static ExpData *ParseExpressionI (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionH (const PClass *cls); static ExpData *ParseExpressionH (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionG (const PClass *cls); static ExpData *ParseExpressionG (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionF (const PClass *cls); static ExpData *ParseExpressionF (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionE (const PClass *cls); static ExpData *ParseExpressionE (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionD (const PClass *cls); static ExpData *ParseExpressionD (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionC (const PClass *cls); static ExpData *ParseExpressionC (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionB (const PClass *cls); static ExpData *ParseExpressionB (FScanner &sc, const PClass *cls);
static ExpData *ParseExpressionA (const PClass *cls); static ExpData *ParseExpressionA (FScanner &sc, const PClass *cls);
int ParseExpression (bool _not, PClass *cls) int ParseExpression (FScanner &sc, bool _not, PClass *cls)
{ {
static bool inited=false; static bool inited=false;
@ -403,7 +403,7 @@ int ParseExpression (bool _not, PClass *cls)
inited=true; inited=true;
} }
ExpData *data = ParseExpressionM (cls); ExpData *data = ParseExpressionM (sc, cls);
if (_not) if (_not)
{ {
@ -426,11 +426,11 @@ int ParseExpression (bool _not, PClass *cls)
return StateExpressions.Push (data); return StateExpressions.Push (data);
} }
static ExpData *ParseExpressionM (const PClass *cls) static ExpData *ParseExpressionM (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionL (cls); ExpData *tmp = ParseExpressionL (sc, cls);
if (SC_CheckToken('?')) if (sc.CheckToken('?'))
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Cond; data->Type = EX_Cond;
@ -438,9 +438,9 @@ static ExpData *ParseExpressionM (const PClass *cls)
ExpData *choices = new ExpData; ExpData *choices = new ExpData;
data->Children[1] = choices; data->Children[1] = choices;
choices->Type = EX_Right; choices->Type = EX_Right;
choices->Children[0] = ParseExpressionM (cls); choices->Children[0] = ParseExpressionM (sc, cls);
SC_MustGetToken(':'); sc.MustGetToken(':');
choices->Children[1] = ParseExpressionM (cls); choices->Children[1] = ParseExpressionM (sc, cls);
data->EvalConst (cls); data->EvalConst (cls);
return data; return data;
} }
@ -450,13 +450,13 @@ static ExpData *ParseExpressionM (const PClass *cls)
} }
} }
static ExpData *ParseExpressionL (const PClass *cls) static ExpData *ParseExpressionL (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionK (cls); ExpData *tmp = ParseExpressionK (sc, cls);
while (SC_CheckToken(TK_OrOr)) while (sc.CheckToken(TK_OrOr))
{ {
ExpData *right = ParseExpressionK (cls); ExpData *right = ParseExpressionK (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_LogOr; data->Type = EX_LogOr;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -467,13 +467,13 @@ static ExpData *ParseExpressionL (const PClass *cls)
return tmp; return tmp;
} }
static ExpData *ParseExpressionK (const PClass *cls) static ExpData *ParseExpressionK (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionJ (cls); ExpData *tmp = ParseExpressionJ (sc, cls);
while (SC_CheckToken(TK_AndAnd)) while (sc.CheckToken(TK_AndAnd))
{ {
ExpData *right = ParseExpressionJ (cls); ExpData *right = ParseExpressionJ (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_LogAnd; data->Type = EX_LogAnd;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -484,13 +484,13 @@ static ExpData *ParseExpressionK (const PClass *cls)
return tmp; return tmp;
} }
static ExpData *ParseExpressionJ (const PClass *cls) static ExpData *ParseExpressionJ (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionI (cls); ExpData *tmp = ParseExpressionI (sc, cls);
while (SC_CheckToken('|')) while (sc.CheckToken('|'))
{ {
ExpData *right = ParseExpressionI (cls); ExpData *right = ParseExpressionI (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Or; data->Type = EX_Or;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -501,13 +501,13 @@ static ExpData *ParseExpressionJ (const PClass *cls)
return tmp; return tmp;
} }
static ExpData *ParseExpressionI (const PClass *cls) static ExpData *ParseExpressionI (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionH (cls); ExpData *tmp = ParseExpressionH (sc, cls);
while (SC_CheckToken('^')) while (sc.CheckToken('^'))
{ {
ExpData *right = ParseExpressionH (cls); ExpData *right = ParseExpressionH (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Xor; data->Type = EX_Xor;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -518,13 +518,13 @@ static ExpData *ParseExpressionI (const PClass *cls)
return tmp; return tmp;
} }
static ExpData *ParseExpressionH (const PClass *cls) static ExpData *ParseExpressionH (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionG (cls); ExpData *tmp = ParseExpressionG (sc, cls);
while (SC_CheckToken('&')) while (sc.CheckToken('&'))
{ {
ExpData *right = ParseExpressionG (cls); ExpData *right = ParseExpressionG (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_And; data->Type = EX_And;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -535,14 +535,14 @@ static ExpData *ParseExpressionH (const PClass *cls)
return tmp; return tmp;
} }
static ExpData *ParseExpressionG (const PClass *cls) static ExpData *ParseExpressionG (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionF (cls); ExpData *tmp = ParseExpressionF (sc, cls);
while (SC_GetToken() && (sc_TokenType == TK_Eq || sc_TokenType == TK_Neq)) while (sc.GetToken() && (sc.TokenType == TK_Eq || sc.TokenType == TK_Neq))
{ {
int token = sc_TokenType; int token = sc.TokenType;
ExpData *right = ParseExpressionF (cls); ExpData *right = ParseExpressionF (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = token == TK_Eq? EX_Eq : EX_NE; data->Type = token == TK_Eq? EX_Eq : EX_NE;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -550,18 +550,18 @@ static ExpData *ParseExpressionG (const PClass *cls)
data->EvalConst (cls); data->EvalConst (cls);
tmp = data; tmp = data;
} }
if (!sc_End) SC_UnGet(); if (!sc.End) sc.UnGet();
return tmp; return tmp;
} }
static ExpData *ParseExpressionF (const PClass *cls) static ExpData *ParseExpressionF (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionE (cls); ExpData *tmp = ParseExpressionE (sc, cls);
while (SC_GetToken() && (sc_TokenType == '<' || sc_TokenType == '>' || sc_TokenType == TK_Leq || sc_TokenType == TK_Geq)) while (sc.GetToken() && (sc.TokenType == '<' || sc.TokenType == '>' || sc.TokenType == TK_Leq || sc.TokenType == TK_Geq))
{ {
int token = sc_TokenType; int token = sc.TokenType;
ExpData *right = ParseExpressionE (cls); ExpData *right = ParseExpressionE (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = token == '<' ? EX_LT : token == '>' ? EX_GT : token == TK_Leq? EX_LE : EX_GE; data->Type = token == '<' ? EX_LT : token == '>' ? EX_GT : token == TK_Leq? EX_LE : EX_GE;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -569,18 +569,18 @@ static ExpData *ParseExpressionF (const PClass *cls)
data->EvalConst (cls); data->EvalConst (cls);
tmp = data; tmp = data;
} }
if (!sc_End) SC_UnGet(); if (!sc.End) sc.UnGet();
return tmp; return tmp;
} }
static ExpData *ParseExpressionE (const PClass *cls) static ExpData *ParseExpressionE (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionD (cls); ExpData *tmp = ParseExpressionD (sc, cls);
while (SC_GetToken() && (sc_TokenType == TK_LShift || sc_TokenType == TK_RShift)) while (sc.GetToken() && (sc.TokenType == TK_LShift || sc.TokenType == TK_RShift))
{ {
int token = sc_TokenType; int token = sc.TokenType;
ExpData *right = ParseExpressionD (cls); ExpData *right = ParseExpressionD (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = token == TK_LShift? EX_LShift : EX_RShift; data->Type = token == TK_LShift? EX_LShift : EX_RShift;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -588,18 +588,18 @@ static ExpData *ParseExpressionE (const PClass *cls)
data->EvalConst (cls); data->EvalConst (cls);
tmp = data; tmp = data;
} }
if (!sc_End) SC_UnGet(); if (!sc.End) sc.UnGet();
return tmp; return tmp;
} }
static ExpData *ParseExpressionD (const PClass *cls) static ExpData *ParseExpressionD (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionC (cls); ExpData *tmp = ParseExpressionC (sc, cls);
while (SC_GetToken() && (sc_TokenType == '+' || sc_TokenType == '-')) while (sc.GetToken() && (sc.TokenType == '+' || sc.TokenType == '-'))
{ {
int token = sc_TokenType; int token = sc.TokenType;
ExpData *right = ParseExpressionC (cls); ExpData *right = ParseExpressionC (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = token == '+'? EX_Add : EX_Sub; data->Type = token == '+'? EX_Add : EX_Sub;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -607,18 +607,18 @@ static ExpData *ParseExpressionD (const PClass *cls)
data->EvalConst (cls); data->EvalConst (cls);
tmp = data; tmp = data;
} }
if (!sc_End) SC_UnGet(); if (!sc.End) sc.UnGet();
return tmp; return tmp;
} }
static ExpData *ParseExpressionC (const PClass *cls) static ExpData *ParseExpressionC (FScanner &sc, const PClass *cls)
{ {
ExpData *tmp = ParseExpressionB (cls); ExpData *tmp = ParseExpressionB (sc, cls);
while (SC_GetToken() && (sc_TokenType == '*' || sc_TokenType == '/' || sc_TokenType == '%')) while (sc.GetToken() && (sc.TokenType == '*' || sc.TokenType == '/' || sc.TokenType == '%'))
{ {
int token = sc_TokenType; int token = sc.TokenType;
ExpData *right = ParseExpressionB (cls); ExpData *right = ParseExpressionB (sc, cls);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = token == '*'? EX_Mul : token == '/'? EX_Div : EX_Mod; data->Type = token == '*'? EX_Mul : token == '/'? EX_Div : EX_Mod;
data->Children[0] = tmp; data->Children[0] = tmp;
@ -626,77 +626,77 @@ static ExpData *ParseExpressionC (const PClass *cls)
data->EvalConst (cls); data->EvalConst (cls);
tmp = data; tmp = data;
} }
if (!sc_End) SC_UnGet(); if (!sc.End) sc.UnGet();
return tmp; return tmp;
} }
static ExpData *ParseExpressionB (const PClass *cls) static ExpData *ParseExpressionB (FScanner &sc, const PClass *cls)
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
if (SC_CheckToken('~')) if (sc.CheckToken('~'))
{ {
data->Type = EX_Compl; data->Type = EX_Compl;
} }
else if (SC_CheckToken('!')) else if (sc.CheckToken('!'))
{ {
data->Type = EX_Not; data->Type = EX_Not;
} }
else if (SC_CheckToken('-')) else if (sc.CheckToken('-'))
{ {
data->Type = EX_Minus; data->Type = EX_Minus;
} }
else else
{ {
SC_CheckToken('+'); sc.CheckToken('+');
delete data; delete data;
return ParseExpressionA (cls); return ParseExpressionA (sc, cls);
} }
data->Children[0] = ParseExpressionA (cls); data->Children[0] = ParseExpressionA (sc, cls);
data->EvalConst (cls); data->EvalConst (cls);
return data; return data;
} }
static ExpData *ParseExpressionA (const PClass *cls) static ExpData *ParseExpressionA (FScanner &sc, const PClass *cls)
{ {
if (SC_CheckToken('(')) if (sc.CheckToken('('))
{ {
ExpData *data = ParseExpressionM (cls); ExpData *data = ParseExpressionM (sc, cls);
SC_MustGetToken(')'); sc.MustGetToken(')');
return data; return data;
} }
else if (SC_CheckToken(TK_IntConst)) else if (sc.CheckToken(TK_IntConst))
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Const; data->Type = EX_Const;
data->Value.Type = VAL_Int; data->Value.Type = VAL_Int;
data->Value.Int = sc_Number; data->Value.Int = sc.Number;
return data; return data;
} }
else if (SC_CheckToken(TK_FloatConst)) else if (sc.CheckToken(TK_FloatConst))
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Const; data->Type = EX_Const;
data->Value.Type = VAL_Float; data->Value.Type = VAL_Float;
data->Value.Float = sc_Float; data->Value.Float = sc.Float;
return data; return data;
} }
else if (SC_CheckToken(TK_Class)) else if (sc.CheckToken(TK_Class))
{ {
// Accept class'SomeClassName'.SomeConstant // Accept class'SomeClassName'.SomeConstant
SC_MustGetToken(TK_NameConst); sc.MustGetToken(TK_NameConst);
cls = PClass::FindClass (sc_Name); cls = PClass::FindClass (sc.Name);
if (cls == NULL) if (cls == NULL)
{ {
SC_ScriptError ("Unknown class '%s'", sc_String); sc.ScriptError ("Unknown class '%s'", sc.String);
} }
SC_MustGetToken('.'); sc.MustGetToken('.');
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
PSymbol *sym = cls->Symbols.FindSymbol (sc_String, true); PSymbol *sym = cls->Symbols.FindSymbol (sc.String, true);
if (sym != NULL && sym->SymbolType == SYM_Const) if (sym != NULL && sym->SymbolType == SYM_Const)
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
@ -707,38 +707,38 @@ static ExpData *ParseExpressionA (const PClass *cls)
} }
else else
{ {
SC_ScriptError ("'%s' is not a constant value in class '%s'", sc_String, cls->TypeName.GetChars()); sc.ScriptError ("'%s' is not a constant value in class '%s'", sc.String, cls->TypeName.GetChars());
return NULL; return NULL;
} }
} }
else if (SC_CheckToken(TK_Identifier)) else if (sc.CheckToken(TK_Identifier))
{ {
switch (FName(sc_String)) switch (FName(sc.String))
{ {
case NAME_Random: case NAME_Random:
{ {
FRandom *rng; FRandom *rng;
if (SC_CheckToken('[')) if (sc.CheckToken('['))
{ {
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
rng = FRandom::StaticFindRNG(sc_String); rng = FRandom::StaticFindRNG(sc.String);
SC_MustGetToken(']'); sc.MustGetToken(']');
} }
else else
{ {
rng = &pr_exrandom; rng = &pr_exrandom;
} }
SC_MustGetToken('('); sc.MustGetToken('(');
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Random; data->Type = EX_Random;
data->RNG = rng; data->RNG = rng;
data->Children[0] = ParseExpressionM (cls); data->Children[0] = ParseExpressionM (sc, cls);
SC_MustGetToken(','); sc.MustGetToken(',');
data->Children[1] = ParseExpressionM (cls); data->Children[1] = ParseExpressionM (sc, cls);
SC_MustGetToken(')'); sc.MustGetToken(')');
return data; return data;
} }
break; break;
@ -747,27 +747,27 @@ static ExpData *ParseExpressionA (const PClass *cls)
{ {
FRandom *rng; FRandom *rng;
if (SC_CheckToken('[')) if (sc.CheckToken('['))
{ {
SC_MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
rng = FRandom::StaticFindRNG(sc_String); rng = FRandom::StaticFindRNG(sc.String);
SC_MustGetToken(']'); sc.MustGetToken(']');
} }
else else
{ {
rng = &pr_exrandom; rng = &pr_exrandom;
} }
SC_MustGetToken('('); sc.MustGetToken('(');
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Random2; data->Type = EX_Random2;
data->RNG = rng; data->RNG = rng;
if (!SC_CheckToken(')')) if (!sc.CheckToken(')'))
{ {
data->Children[0] = ParseExpressionM(cls); data->Children[0] = ParseExpressionM(sc, cls);
SC_MustGetToken(')'); sc.MustGetToken(')');
} }
return data; return data;
} }
@ -775,28 +775,28 @@ static ExpData *ParseExpressionA (const PClass *cls)
case NAME_Sin: case NAME_Sin:
{ {
SC_MustGetToken('('); sc.MustGetToken('(');
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Sin; data->Type = EX_Sin;
data->Children[0] = ParseExpressionM (cls); data->Children[0] = ParseExpressionM (sc, cls);
SC_MustGetToken(')'); sc.MustGetToken(')');
return data; return data;
} }
break; break;
case NAME_Cos: case NAME_Cos:
{ {
SC_MustGetToken('('); sc.MustGetToken('(');
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Cos; data->Type = EX_Cos;
data->Children[0] = ParseExpressionM (cls); data->Children[0] = ParseExpressionM (sc, cls);
SC_MustGetToken(')'); sc.MustGetToken(')');
return data; return data;
} }
break; break;
@ -806,35 +806,35 @@ static ExpData *ParseExpressionA (const PClass *cls)
int specnum, min_args, max_args; int specnum, min_args, max_args;
// Check if this is an action special // Check if this is an action special
strlwr (sc_String); strlwr (sc.String);
specnum = FindLineSpecialEx (sc_String, &min_args, &max_args); specnum = FindLineSpecialEx (sc.String, &min_args, &max_args);
if (specnum != 0) if (specnum != 0)
{ {
int i; int i;
SC_MustGetToken('('); sc.MustGetToken('(');
ExpData *data = new ExpData, **left; ExpData *data = new ExpData, **left;
data->Type = EX_ActionSpecial; data->Type = EX_ActionSpecial;
data->Value.Int = specnum; data->Value.Int = specnum;
data->Children[0] = ParseExpressionM (cls); data->Children[0] = ParseExpressionM (sc, cls);
left = &data->Children[1]; left = &data->Children[1];
for (i = 1; i < 5 && SC_CheckToken(','); ++i) for (i = 1; i < 5 && sc.CheckToken(','); ++i)
{ {
ExpData *right = new ExpData; ExpData *right = new ExpData;
right->Type = EX_Right; right->Type = EX_Right;
right->Children[0] = ParseExpressionM (cls); right->Children[0] = ParseExpressionM (sc, cls);
*left = right; *left = right;
left = &right->Children[1]; left = &right->Children[1];
} }
*left = NULL; *left = NULL;
SC_MustGetToken(')'); sc.MustGetToken(')');
if (i < min_args) if (i < min_args)
SC_ScriptError ("Not enough arguments to action special"); sc.ScriptError ("Not enough arguments to action special");
if (i > max_args) if (i > max_args)
SC_ScriptError ("Too many arguments to action special"); sc.ScriptError ("Too many arguments to action special");
return data; return data;
} }
@ -842,7 +842,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
// Check if this is a constant // Check if this is a constant
if (cls != NULL) if (cls != NULL)
{ {
PSymbol *sym = cls->Symbols.FindSymbol (sc_String, true); PSymbol *sym = cls->Symbols.FindSymbol (sc.String, true);
if (sym != NULL && sym->SymbolType == SYM_Const) if (sym != NULL && sym->SymbolType == SYM_Const)
{ {
ExpData *data = new ExpData; ExpData *data = new ExpData;
@ -855,7 +855,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
// Check if it's a variable we understand // Check if it's a variable we understand
int varid = -1; int varid = -1;
FName vname = sc_String; FName vname = sc.String;
for (size_t i = 0; i < countof(ExpVars); i++) for (size_t i = 0; i < countof(ExpVars); i++)
{ {
if (vname == ExpVars[i].name) if (vname == ExpVars[i].name)
@ -866,7 +866,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
} }
if (varid == -1) if (varid == -1)
SC_ScriptError ("Unknown value '%s'", sc_String); sc.ScriptError ("Unknown value '%s'", sc.String);
ExpData *data = new ExpData; ExpData *data = new ExpData;
data->Type = EX_Var; data->Type = EX_Var;
@ -875,9 +875,9 @@ static ExpData *ParseExpressionA (const PClass *cls)
if (ExpVars[varid].array) if (ExpVars[varid].array)
{ {
SC_MustGetToken('['); sc.MustGetToken('[');
data->Children[0] = ParseExpressionM (cls); data->Children[0] = ParseExpressionM (sc, cls);
SC_MustGetToken(']'); sc.MustGetToken(']');
} }
return data; return data;
} }
@ -886,8 +886,8 @@ static ExpData *ParseExpressionA (const PClass *cls)
} }
else else
{ {
FString tokname = SC_TokenName(sc_TokenType, sc_String); FString tokname = sc.TokenName(sc.TokenType, sc.String);
SC_ScriptError ("Unexpected token %s", tokname.GetChars()); sc.ScriptError ("Unexpected token %s", tokname.GetChars());
return NULL; return NULL;
} }
} }

View file

@ -47,12 +47,12 @@
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void ParseActor(); void ParseActor(FScanner &sc);
void ParseClass(); void ParseClass(FScanner &sc);
void ParseGlobalConst(); void ParseGlobalConst(FScanner &sc);
void ParseGlobalEnum(); void ParseGlobalEnum(FScanner &sc);
void FinishThingdef(); void FinishThingdef();
void ParseOldDecoration(EDefinitionType def); void ParseOldDecoration(FScanner &sc, EDefinitionType def);
// STATIC FUNCTION PROTOTYPES -------------------------------------------- // STATIC FUNCTION PROTOTYPES --------------------------------------------
@ -64,65 +64,64 @@ void ParseOldDecoration(EDefinitionType def);
// //
//========================================================================== //==========================================================================
static void ParseDecorate () static void ParseDecorate (FScanner &sc)
{ {
int recursion=0;
int lump; int lump;
// Get actor class name. // Get actor class name.
while (true) for(;;)
{ {
SC_SavePos(); FScanner::SavedPos pos = sc.SavePos();
if (!SC_GetToken ()) if (!sc.GetToken ())
{ {
if (recursion==0) return; return;
SC_Close();
SC_RestoreScriptState();
recursion--;
continue;
} }
switch (sc_TokenType) switch (sc.TokenType)
{ {
case TK_Include: case TK_Include:
SC_MustGetString(); sc.MustGetString();
// This is not using SC_Open because it can print a more useful error message when done here // This is not using SC_Open because it can print a more useful error message when done here
lump = Wads.CheckNumForFullName(sc_String); lump = Wads.CheckNumForFullName(sc.String);
// Try a normal WAD name lookup only if it's a proper name without path separator and // Try a normal WAD name lookup only if it's a proper name without path separator and
// not longer than 8 characters. // not longer than 8 characters.
if (lump==-1 && strlen(sc_String) <= 8 && !strchr(sc_String, '/')) if (lump == -1 && sc.StringLen <= 8 && !strchr(sc.String, '/'))
lump = Wads.CheckNumForName(sc_String); {
lump = Wads.CheckNumForName(sc.String);
if (lump==-1) }
SC_ScriptError("Lump '%s' not found", sc_String); if (lump == -1)
{
SC_SaveScriptState(); sc.ScriptError("Lump '%s' not found", sc.String);
SC_OpenLumpNum(lump, sc_String); }
recursion++; else
{
FScanner newscanner(lump, sc.String);
ParseDecorate(newscanner);
}
break; break;
case TK_Class: case TK_Class:
ParseClass (); ParseClass (sc);
break; break;
case TK_Const: case TK_Const:
ParseConstant (&RUNTIME_CLASS(AActor)->Symbols, RUNTIME_CLASS(AActor)); ParseConstant (sc, &RUNTIME_CLASS(AActor)->Symbols, RUNTIME_CLASS(AActor));
break; break;
case TK_Enum: case TK_Enum:
ParseEnum (&RUNTIME_CLASS(AActor)->Symbols, RUNTIME_CLASS(AActor)); ParseEnum (sc, &RUNTIME_CLASS(AActor)->Symbols, RUNTIME_CLASS(AActor));
break; break;
case TK_Pickup: case TK_Pickup:
ParseOldDecoration (DEF_Pickup); ParseOldDecoration (sc, DEF_Pickup);
break; break;
case TK_Breakable: case TK_Breakable:
ParseOldDecoration (DEF_BreakableDecoration); ParseOldDecoration (sc, DEF_BreakableDecoration);
break; break;
case TK_Projectile: case TK_Projectile:
ParseOldDecoration (DEF_Projectile); ParseOldDecoration (sc, DEF_Projectile);
break; break;
case ';': case ';':
@ -130,22 +129,22 @@ static void ParseDecorate ()
// is used to parse parts of the DECORATE lump. If we don't add // is used to parse parts of the DECORATE lump. If we don't add
// a check here the user will only get weird non-informative // a check here the user will only get weird non-informative
// error messages if a semicolon is found. // error messages if a semicolon is found.
SC_ScriptError("Unexpected ';'"); sc.ScriptError("Unexpected ';'");
break; break;
case TK_Identifier: case TK_Identifier:
// 'ACTOR' cannot be a keyword because it is also needed as a class identifier // 'ACTOR' cannot be a keyword because it is also needed as a class identifier
// so let's do a special case for this. // so let's do a special case for this.
if (SC_Compare("ACTOR")) if (sc.Compare("ACTOR"))
{ {
ParseActor (); ParseActor (sc);
break; break;
} }
default: default:
// Yuck! Too bad that there's no better way to check this properly // Yuck! Too bad that there's no better way to check this properly
SC_RestorePos(); sc.RestorePos(pos);
ParseOldDecoration(DEF_Decoration); ParseOldDecoration(sc, DEF_Decoration);
break; break;
} }
} }
@ -166,9 +165,8 @@ void LoadDecorations ()
lastlump = 0; lastlump = 0;
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1) while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, Wads.GetLumpFullName(lump)); FScanner sc(lump, Wads.GetLumpFullName(lump));
ParseDecorate (); ParseDecorate (sc);
SC_Close ();
} }
FinishThingdef(); FinishThingdef();
} }

File diff suppressed because it is too large Load diff

View file

@ -436,12 +436,12 @@ int FindLineSpecialEx (const char *string, int *min_args, int *max_args)
// handles action specials as code pointers // handles action specials as code pointers
// //
//========================================================================== //==========================================================================
bool DoActionSpecials(FState & state, bool multistate, int * statecount, Baggage &bag) bool DoActionSpecials(FScanner &sc, FState & state, bool multistate, int * statecount, Baggage &bag)
{ {
int i; int i;
const ACSspecials *spec; const ACSspecials *spec;
if ((spec = is_special (sc_String, sc_StringLen)) != NULL) if ((spec = is_special (sc.String, sc.StringLen)) != NULL)
{ {
int paramindex=PrepareStateParameters(&state, 6); int paramindex=PrepareStateParameters(&state, 6);
@ -449,25 +449,25 @@ bool DoActionSpecials(FState & state, bool multistate, int * statecount, Baggage
StateParameters[paramindex]=spec->Special; StateParameters[paramindex]=spec->Special;
// Make this consistent with all other parameter parsing // Make this consistent with all other parameter parsing
if (SC_CheckToken('(')) if (sc.CheckToken('('))
{ {
for (i = 0; i < 5;) for (i = 0; i < 5;)
{ {
StateParameters[paramindex+i+1]=ParseExpression (false, bag.Info->Class); StateParameters[paramindex+i+1] = ParseExpression (sc, false, bag.Info->Class);
i++; i++;
if (!SC_CheckToken (',')) break; if (!sc.CheckToken (',')) break;
} }
SC_MustGetToken (')'); sc.MustGetToken (')');
} }
else i=0; else i=0;
if (i < spec->MinArgs) if (i < spec->MinArgs)
{ {
SC_ScriptError ("Too few arguments to %s", spec->name); sc.ScriptError ("Too few arguments to %s", spec->name);
} }
if (i > MAX (spec->MinArgs, spec->MaxArgs)) if (i > MAX (spec->MinArgs, spec->MaxArgs))
{ {
SC_ScriptError ("Too many arguments to %s", spec->name); sc.ScriptError ("Too many arguments to %s", spec->name);
} }
state.Action = A_CallSpecial; state.Action = A_CallSpecial;
return true; return true;
@ -514,21 +514,21 @@ static void RetargetStates (intptr_t count, const char *target)
// processes a state block // processes a state block
// //
//========================================================================== //==========================================================================
static FString ParseStateString() static FString ParseStateString(FScanner &sc)
{ {
FString statestring; FString statestring;
SC_MustGetString(); sc.MustGetString();
statestring = sc_String; statestring = sc.String;
if (SC_CheckString("::")) if (sc.CheckString("::"))
{ {
SC_MustGetString (); sc.MustGetString ();
statestring << "::" << sc_String; statestring << "::" << sc.String;
} }
while (SC_CheckString (".")) while (sc.CheckString ("."))
{ {
SC_MustGetString (); sc.MustGetString ();
statestring << "." << sc_String; statestring << "." << sc.String;
} }
return statestring; return statestring;
} }
@ -539,7 +539,7 @@ static FString ParseStateString()
// parses a state block // parses a state block
// //
//========================================================================== //==========================================================================
int ParseStates(FActorInfo * actor, AActor * defaults, Baggage &bag) int ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &bag)
{ {
FString statestring; FString statestring;
intptr_t count = 0; intptr_t count = 0;
@ -548,21 +548,21 @@ int ParseStates(FActorInfo * actor, AActor * defaults, Baggage &bag)
intptr_t lastlabel = -1; intptr_t lastlabel = -1;
int minrequiredstate = -1; int minrequiredstate = -1;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
SC_SetEscape(false); // disable escape sequences in the state parser sc.SetEscape(false); // disable escape sequences in the state parser
while (!SC_CheckString ("}") && !sc_End) while (!sc.CheckString ("}") && !sc.End)
{ {
memset(&state,0,sizeof(state)); memset(&state,0,sizeof(state));
statestring = ParseStateString(); statestring = ParseStateString(sc);
if (!statestring.CompareNoCase("GOTO")) if (!statestring.CompareNoCase("GOTO"))
{ {
do_goto: do_goto:
statestring = ParseStateString(); statestring = ParseStateString(sc);
if (SC_CheckString ("+")) if (sc.CheckString ("+"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
statestring += '+'; statestring += '+';
statestring += sc_String; statestring += sc.String;
} }
// copy the text - this must be resolved later! // copy the text - this must be resolved later!
if (laststate != NULL) if (laststate != NULL)
@ -575,7 +575,7 @@ do_goto:
} }
else else
{ {
SC_ScriptError("GOTO before first state"); sc.ScriptError("GOTO before first state");
} }
} }
else if (!statestring.CompareNoCase("STOP")) else if (!statestring.CompareNoCase("STOP"))
@ -591,7 +591,7 @@ do_stop:
} }
else else
{ {
SC_ScriptError("STOP before first state"); sc.ScriptError("STOP before first state");
continue; continue;
} }
} }
@ -599,7 +599,7 @@ do_stop:
{ {
if (!laststate) if (!laststate)
{ {
SC_ScriptError("%s before first state", sc_String); sc.ScriptError("%s before first state", sc.String);
continue; continue;
} }
laststate->NextState=(FState*)-2; laststate->NextState=(FState*)-2;
@ -608,7 +608,7 @@ do_stop:
{ {
if (!laststate) if (!laststate)
{ {
SC_ScriptError("LOOP before first state"); sc.ScriptError("LOOP before first state");
continue; continue;
} }
laststate->NextState=(FState*)(lastlabel+1); laststate->NextState=(FState*)(lastlabel+1);
@ -617,15 +617,15 @@ do_stop:
{ {
const char * statestrp; const char * statestrp;
SC_MustGetString(); sc.MustGetString();
if (SC_Compare (":")) if (sc.Compare (":"))
{ {
laststate = NULL; laststate = NULL;
do do
{ {
lastlabel = count; lastlabel = count;
AddState(statestring, (FState *) (count+1)); AddState(statestring, (FState *) (count+1));
statestring = ParseStateString(); statestring = ParseStateString(sc);
if (!statestring.CompareNoCase("GOTO")) if (!statestring.CompareNoCase("GOTO"))
{ {
goto do_goto; goto do_goto;
@ -634,72 +634,75 @@ do_stop:
{ {
goto do_stop; goto do_stop;
} }
SC_MustGetString (); sc.MustGetString ();
} while (SC_Compare (":")); } while (sc.Compare (":"));
// continue; // continue;
} }
SC_UnGet (); sc.UnGet ();
if (statestring.Len() != 4) if (statestring.Len() != 4)
{ {
SC_ScriptError ("Sprite names must be exactly 4 characters\n"); sc.ScriptError ("Sprite names must be exactly 4 characters\n");
} }
memcpy(state.sprite.name, statestring, 4); memcpy(state.sprite.name, statestring, 4);
state.Misc1=state.Misc2=0; state.Misc1 = state.Misc2 = 0;
state.ParameterIndex=0; state.ParameterIndex = 0;
SC_MustGetString(); sc.MustGetString();
statestring = (sc_String+1); statestring = (sc.String+1);
statestrp = statestring; statestrp = statestring;
state.Frame=(*sc_String&223)-'A'; state.Frame = (*sc.String & 223)-'A';
if ((*sc_String&223)<'A' || (*sc_String&223)>']') if ((*sc.String & 223)<'A' || (*sc.String & 223)>']')
{ {
SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); sc.ScriptError ("Frames must be A-Z, [, \\, or ]");
state.Frame=0; state.Frame=0;
} }
SC_MustGetNumber(); sc.MustGetNumber();
sc_Number++; sc.Number++;
state.Tics=sc_Number&255; state.Tics = sc.Number & 255;
state.Misc1=(sc_Number>>8)&255; state.Misc1 = (sc.Number >> 8) & 255;
if (state.Misc1) state.Frame|=SF_BIGTIC; if (state.Misc1)
while (SC_GetString() && !sc_Crossed)
{ {
if (SC_Compare("BRIGHT")) state.Frame |= SF_BIGTIC;
}
while (sc.GetString() && !sc.Crossed)
{
if (sc.Compare("BRIGHT"))
{ {
state.Frame|=SF_FULLBRIGHT; state.Frame |= SF_FULLBRIGHT;
continue; continue;
} }
if (SC_Compare("OFFSET")) if (sc.Compare("OFFSET"))
{ {
if (state.Frame&SF_BIGTIC) if (state.Frame & SF_BIGTIC)
{ {
SC_ScriptError("You cannot use OFFSET with a state duration larger than 254!"); sc.ScriptError("You cannot use OFFSET with a state duration larger than 254!");
} }
// specify a weapon offset // specify a weapon offset
SC_MustGetStringName("("); sc.MustGetStringName("(");
SC_MustGetNumber(); sc.MustGetNumber();
state.Misc1=sc_Number; state.Misc1 = sc.Number;
SC_MustGetStringName (","); sc.MustGetStringName (",");
SC_MustGetNumber(); sc.MustGetNumber();
state.Misc2=sc_Number; state.Misc2 = sc.Number;
SC_MustGetStringName(")"); sc.MustGetStringName(")");
continue; continue;
} }
// Make the action name lowercase to satisfy the gperf hashers // Make the action name lowercase to satisfy the gperf hashers
strlwr (sc_String); strlwr (sc.String);
int minreq=count; int minreq = count;
if (DoActionSpecials(state, !statestring.IsEmpty(), &minreq, bag)) if (DoActionSpecials(sc, state, !statestring.IsEmpty(), &minreq, bag))
{ {
if (minreq>minrequiredstate) minrequiredstate=minreq; if (minreq>minrequiredstate) minrequiredstate=minreq;
goto endofstate; goto endofstate;
} }
PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (FName(sc_String, true), true); PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (FName(sc.String, true), true);
if (sym != NULL && sym->SymbolType == SYM_ActionFunction) if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
{ {
PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym); PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym);
@ -713,11 +716,11 @@ do_stop:
if (!islower(*params)) if (!islower(*params))
{ {
SC_MustGetStringName("("); sc.MustGetStringName("(");
} }
else else
{ {
if (!SC_CheckString("(")) goto endofstate; if (!sc.CheckString("(")) goto endofstate;
} }
int paramindex = PrepareStateParameters(&state, numparams); int paramindex = PrepareStateParameters(&state, numparams);
@ -735,47 +738,47 @@ do_stop:
{ {
case 'I': case 'I':
case 'i': // Integer case 'i': // Integer
SC_MustGetNumber(); sc.MustGetNumber();
v=sc_Number; v = sc.Number;
break; break;
case 'F': case 'F':
case 'f': // Fixed point case 'f': // Fixed point
SC_MustGetFloat(); sc.MustGetFloat();
v=fixed_t(sc_Float*FRACUNIT); v = fixed_t(sc.Float*FRACUNIT);
break; break;
case 'S': case 'S':
case 's': // Sound name case 's': // Sound name
SC_MustGetString(); sc.MustGetString();
v=S_FindSound(sc_String); v = S_FindSound(sc.String);
break; break;
case 'M': case 'M':
case 'm': // Actor name case 'm': // Actor name
case 'T': case 'T':
case 't': // String case 't': // String
SC_SetEscape(true); sc.SetEscape(true);
SC_MustGetString(); sc.MustGetString();
SC_SetEscape(false); sc.SetEscape(false);
v = (int)(sc_String[0] ? FName(sc_String) : NAME_None); v = (int)(sc.String[0] ? FName(sc.String) : NAME_None);
break; break;
case 'L': case 'L':
case 'l': // Jump label case 'l': // Jump label
if (SC_CheckNumber()) if (sc.CheckNumber())
{ {
if (sc_Number > 0 && strlen(statestring)>0) if (sc.Number > 0 && strlen(statestring)>0)
{ {
SC_ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n"); sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
} }
v=sc_Number; v=sc.Number;
if (v<0) if (v<0)
{ {
SC_ScriptError("Negative jump offsets are not allowed"); sc.ScriptError("Negative jump offsets are not allowed");
} }
{ {
@ -789,13 +792,13 @@ do_stop:
v = -(int)JumpParameters.Size(); v = -(int)JumpParameters.Size();
// This forces quotation marks around the state name. // This forces quotation marks around the state name.
SC_MustGetToken(TK_StringConst); sc.MustGetToken(TK_StringConst);
if (sc_String[0] == 0 || SC_Compare("None")) if (sc.String[0] == 0 || sc.Compare("None"))
{ {
v = 0; // an empty string means 'no state'. v = 0; // an empty string means 'no state'.
break; break;
} }
FString statestring = sc_String; // ParseStateString(); FString statestring = sc.String; // ParseStateString(sc);
const PClass *stype=NULL; const PClass *stype=NULL;
int scope = statestring.IndexOf("::"); int scope = statestring.IndexOf("::");
if (scope >= 0) if (scope >= 0)
@ -812,15 +815,15 @@ do_stop:
stype = PClass::FindClass (scopename); stype = PClass::FindClass (scopename);
if (stype == NULL) if (stype == NULL)
{ {
SC_ScriptError ("%s is an unknown class.", scopename.GetChars()); sc.ScriptError ("%s is an unknown class.", scopename.GetChars());
} }
if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor))) if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
{ {
SC_ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars()); sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
} }
if (!stype->IsAncestorOf (actor->Class)) if (!stype->IsAncestorOf (actor->Class))
{ {
SC_ScriptError ("%s is not derived from %s so cannot access its states.", sc.ScriptError ("%s is not derived from %s so cannot access its states.",
actor->Class->TypeName.GetChars(), stype->TypeName.GetChars()); actor->Class->TypeName.GetChars(), stype->TypeName.GetChars());
} }
} }
@ -839,7 +842,7 @@ do_stop:
{ {
if (!stype->ActorInfo->FindState(names.Size(), &names[0])) if (!stype->ActorInfo->FindState(names.Size(), &names[0]))
{ {
SC_ScriptError("Jump to unknown state '%s' in class '%s'", sc.ScriptError("Jump to unknown state '%s' in class '%s'",
statestring.GetChars(), stype->TypeName.GetChars()); statestring.GetChars(), stype->TypeName.GetChars());
} }
} }
@ -855,14 +858,14 @@ do_stop:
case 'C': case 'C':
case 'c': // Color case 'c': // Color
SC_MustGetString (); sc.MustGetString ();
if (SC_Compare("none")) if (sc.Compare("none"))
{ {
v = -1; v = -1;
} }
else else
{ {
int c = V_GetColor (NULL, sc_String); int c = V_GetColor (NULL, sc.String);
// 0 needs to be the default so we have to mark the color. // 0 needs to be the default so we have to mark the color.
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c)); v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
} }
@ -870,12 +873,12 @@ do_stop:
case 'X': case 'X':
case 'x': case 'x':
v = ParseExpression (false, bag.Info->Class); v = ParseExpression (sc, false, bag.Info->Class);
break; break;
case 'Y': case 'Y':
case 'y': case 'y':
v = ParseExpression (true, bag.Info->Class); v = ParseExpression (sc, true, bag.Info->Class);
break; break;
default: default:
@ -893,7 +896,7 @@ do_stop:
{ {
if (*params == '+') if (*params == '+')
{ {
if (SC_CheckString(")")) if (sc.CheckString(")"))
{ {
goto endofstate; goto endofstate;
} }
@ -901,29 +904,29 @@ do_stop:
v = 0; v = 0;
StateParameters.Push(v); StateParameters.Push(v);
} }
else if ((islower(*params) || *params=='!') && SC_CheckString(")")) else if ((islower(*params) || *params=='!') && sc.CheckString(")"))
{ {
goto endofstate; goto endofstate;
} }
SC_MustGetStringName (","); sc.MustGetStringName (",");
} }
} }
SC_MustGetStringName(")"); sc.MustGetStringName(")");
} }
else else
{ {
SC_MustGetString(); sc.MustGetString();
if (SC_Compare("(")) if (sc.Compare("("))
{ {
SC_ScriptError("You cannot pass parameters to '%s'\n",sc_String); sc.ScriptError("You cannot pass parameters to '%s'\n",sc.String);
} }
SC_UnGet(); sc.UnGet();
} }
goto endofstate; goto endofstate;
} }
SC_ScriptError("Invalid state parameter %s\n", sc_String); sc.ScriptError("Invalid state parameter %s\n", sc.String);
} }
SC_UnGet(); sc.UnGet();
endofstate: endofstate:
StateArray.Push(state); StateArray.Push(state);
while (*statestrp) while (*statestrp)
@ -932,7 +935,7 @@ endofstate:
if (frame<0 || frame>28) if (frame<0 || frame>28)
{ {
SC_ScriptError ("Frames must be A-Z, [, \\, or ]"); sc.ScriptError ("Frames must be A-Z, [, \\, or ]");
frame=0; frame=0;
} }
@ -946,9 +949,9 @@ endofstate:
} }
if (count<=minrequiredstate) if (count<=minrequiredstate)
{ {
SC_ScriptError("A_Jump offset out of range in %s", actor->Class->TypeName.GetChars()); sc.ScriptError("A_Jump offset out of range in %s", actor->Class->TypeName.GetChars());
} }
SC_SetEscape(true); // re-enable escape sequences sc.SetEscape(true); // re-enable escape sequences
return count; return count;
} }
@ -958,7 +961,7 @@ endofstate:
// //
//========================================================================== //==========================================================================
static FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name) static FState *ResolveGotoLabel (FScanner &sc, AActor *actor, const PClass *mytype, char *name)
{ {
const PClass *type=mytype; const PClass *type=mytype;
FState *state; FState *state;
@ -986,15 +989,15 @@ static FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name
const PClass *stype = PClass::FindClass (classname); const PClass *stype = PClass::FindClass (classname);
if (stype == NULL) if (stype == NULL)
{ {
SC_ScriptError ("%s is an unknown class.", classname); sc.ScriptError ("%s is an unknown class.", classname);
} }
if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor))) if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
{ {
SC_ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars()); sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
} }
if (!stype->IsAncestorOf (type)) if (!stype->IsAncestorOf (type))
{ {
SC_ScriptError ("%s is not derived from %s so cannot access its states.", sc.ScriptError ("%s is not derived from %s so cannot access its states.",
type->TypeName.GetChars(), stype->TypeName.GetChars()); type->TypeName.GetChars(), stype->TypeName.GetChars());
} }
if (type != stype) if (type != stype)
@ -1024,7 +1027,7 @@ static FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name
} }
else if (v != 0) else if (v != 0)
{ {
SC_ScriptError ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars()); sc.ScriptError ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
} }
delete[] namestart; // free the allocated string buffer delete[] namestart; // free the allocated string buffer
return state; return state;
@ -1059,15 +1062,15 @@ static void FixStatePointers (FActorInfo *actor, TArray<FStateDefine> & list)
// //
//========================================================================== //==========================================================================
static void FixStatePointersAgain (FActorInfo *actor, AActor *defaults, TArray<FStateDefine> & list) static void FixStatePointersAgain (FScanner &sc, FActorInfo *actor, AActor *defaults, TArray<FStateDefine> & list)
{ {
for(unsigned i=0;i<list.Size(); i++) for(unsigned i=0;i<list.Size(); i++)
{ {
if (list[i].State != NULL && FState::StaticFindStateOwner (list[i].State, actor) == NULL) if (list[i].State != NULL && FState::StaticFindStateOwner (list[i].State, actor) == NULL)
{ // It's not a valid state, so it must be a label string. Resolve it. { // It's not a valid state, so it must be a label string. Resolve it.
list[i].State = ResolveGotoLabel (defaults, actor->Class, (char *)list[i].State); list[i].State = ResolveGotoLabel (sc, defaults, actor->Class, (char *)list[i].State);
} }
if (list[i].Children.Size() > 0) FixStatePointersAgain(actor, defaults, list[i].Children); if (list[i].Children.Size() > 0) FixStatePointersAgain(sc, actor, defaults, list[i].Children);
} }
} }
@ -1079,7 +1082,7 @@ static void FixStatePointersAgain (FActorInfo *actor, AActor *defaults, TArray<F
// //
//========================================================================== //==========================================================================
int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag) int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag)
{ {
static int c=0; static int c=0;
int count = StateArray.Size(); int count = StateArray.Size();
@ -1122,7 +1125,7 @@ int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag)
} }
else // goto else // goto
{ {
realstates[i].NextState = ResolveGotoLabel (defaults, bag.Info->Class, (char *)realstates[i].NextState); realstates[i].NextState = ResolveGotoLabel (sc, defaults, bag.Info->Class, (char *)realstates[i].NextState);
} }
} }
} }
@ -1130,7 +1133,7 @@ int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag)
StateArray.Clear (); StateArray.Clear ();
// Fix state pointers that are gotos // Fix state pointers that are gotos
FixStatePointersAgain (actor, defaults, StateLabels); FixStatePointersAgain (sc, actor, defaults, StateLabels);
return count; return count;
} }
@ -1142,35 +1145,35 @@ int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag)
// This is strictly for keeping compatibility with old WADs! // This is strictly for keeping compatibility with old WADs!
// //
//========================================================================== //==========================================================================
FState *CheckState(PClass *type) FState *CheckState(FScanner &sc, PClass *type)
{ {
int v=0; int v=0;
if (SC_GetString() && !sc_Crossed) if (sc.GetString() && !sc.Crossed)
{ {
if (SC_Compare("0")) return NULL; if (sc.Compare("0")) return NULL;
else if (SC_Compare("PARENT")) else if (sc.Compare("PARENT"))
{ {
FState * state = NULL; FState * state = NULL;
SC_MustGetString(); sc.MustGetString();
FActorInfo * info = type->ParentClass->ActorInfo; FActorInfo * info = type->ParentClass->ActorInfo;
if (info != NULL) if (info != NULL)
{ {
state = info->FindState(FName(sc_String)); state = info->FindState(FName(sc.String));
} }
if (SC_GetString ()) if (sc.GetString ())
{ {
if (SC_Compare ("+")) if (sc.Compare ("+"))
{ {
SC_MustGetNumber (); sc.MustGetNumber ();
v = sc_Number; v = sc.Number;
} }
else else
{ {
SC_UnGet (); sc.UnGet ();
} }
} }
@ -1178,13 +1181,13 @@ FState *CheckState(PClass *type)
if (v!=0 && state==NULL) if (v!=0 && state==NULL)
{ {
SC_ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars()); sc.ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars());
return NULL; return NULL;
} }
state+=v; state+=v;
return state; return state;
} }
else SC_ScriptError("Invalid state assignment"); else sc.ScriptError("Invalid state assignment");
} }
return NULL; return NULL;
} }

View file

@ -67,7 +67,6 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
{ {
FTexture::Span unmaskedSpan[2]; FTexture::Span unmaskedSpan[2];
const FTexture::Span **spanptr, *spans; const FTexture::Span **spanptr, *spans;
static BYTE identitymap[256];
static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH]; static short bottomclipper[MAXWIDTH], topclipper[MAXWIDTH];
DrawParms parms; DrawParms parms;
@ -86,32 +85,38 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
spanptr = NULL; spanptr = NULL;
} }
fixedcolormap = identitymap;
ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor);
if (APART(parms.colorOverlay) != 0) if (APART(parms.colorOverlay) != 0)
{ {
// In software, DTA_ColorOverlay only does black overlays. // The software renderer cannot invert the source without inverting the overlay
// Maybe I will change this later, but right now white is the only // too. That means if the source is inverted, we need to do the reverse of what
// color that is actually used for this parameter. // the invert overlay flag says to do.
// Note that this is also overriding DTA_Translation in software. INTBOOL invertoverlay = (parms.style.Flags & STYLEF_InvertOverlay);
if ((parms.colorOverlay & MAKEARGB(0,255,255,255)) == 0)
if (parms.style.Flags & STYLEF_InvertSource)
{ {
parms.translation = &NormalLight.Maps[(APART(parms.colorOverlay)*NUMCOLORMAPS/255)*256]; invertoverlay = !invertoverlay;
} }
if (invertoverlay)
{
parms.colorOverlay = PalEntry(parms.colorOverlay).InverseColor();
}
// Note that this overrides DTA_Translation in software, but not in hardware.
FDynamicColormap *colormap = GetSpecialLights(MAKERGB(255,255,255),
parms.colorOverlay & MAKEARGB(0,255,255,255), 0);
parms.translation = &colormap->Maps[(APART(parms.colorOverlay)*NUMCOLORMAPS/255)*256];
} }
if (parms.style != STYLE_Shaded) if (parms.translation != NULL)
{ {
if (parms.translation != NULL) dc_colormap = (lighttable_t *)parms.translation;
{
dc_colormap = (lighttable_t *)parms.translation;
}
else
{
dc_colormap = identitymap;
}
} }
else
{
dc_colormap = identitymap;
}
fixedcolormap = dc_colormap;
ESPSResult mode = R_SetPatchStyle (parms.style, parms.alpha, 0, parms.fillcolor);
BYTE *destorgsave = dc_destorg; BYTE *destorgsave = dc_destorg;
dc_destorg = screen->GetBuffer(); dc_destorg = screen->GetBuffer();
@ -155,13 +160,6 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
if (bottomclipper[0] != parms.dclip) if (bottomclipper[0] != parms.dclip)
{ {
clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip); clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip);
if (identitymap[1] != 1)
{
for (int i = 0; i < 256; ++i)
{
identitymap[i] = i;
}
}
} }
if (parms.uclip != 0) if (parms.uclip != 0)
{ {
@ -299,7 +297,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->virtWidth = this->GetWidth(); parms->virtWidth = this->GetWidth();
parms->virtHeight = this->GetHeight(); parms->virtHeight = this->GetHeight();
parms->keepratio = false; parms->keepratio = false;
parms->style = STYLE_Count; parms->style.BlendOp = 255; // Dummy "not set" value
parms->masked = true; parms->masked = true;
parms->bilinear = false; parms->bilinear = false;
@ -601,7 +599,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->translation = parms->remap->Remap; parms->translation = parms->remap->Remap;
} }
if (parms->style == STYLE_Count) if (parms->style.BlendOp == 255)
{ {
if (parms->fillcolor != -1) if (parms->fillcolor != -1)
{ {

View file

@ -32,6 +32,45 @@
** **
*/ */
/* Special file formats handled here:
FON1 "console" fonts have the following header:
char Magic[4]; -- The characters "FON1"
uword CharWidth; -- Character cell width
uword CharHeight; -- Character cell height
The FON1 header is followed by RLE character data for all 256
8-bit ASCII characters.
FON2 "standard" fonts have the following header:
char Magic[4]; -- The characters "FON2"
uword FontHeight; -- Every character in a font has the same height
ubyte FirstChar; -- First character defined by this font.
ubyte LastChar; -- Last character definde by this font.
ubyte bConstantWidth;
ubyte ShadingType;
ubyte PaletteSize; -- size of palette in entries (not bytes!)
ubyte Flags;
There is presently only one flag for FON2:
FOF_WHOLEFONTKERNING 1 -- The Kerning field is present in the file
The FON2 header is followed by variable length data:
word Kerning;
-- only present if FOF_WHOLEFONTKERNING is set
ubyte Palette[PaletteSize+1][3];
-- The last entry is the delimiter color. The delimiter is not used
-- by the font but is used my imagetool when converting the font
-- back to an image. Color 0 is the transparent color and is also
-- used only for converting the font back to an image. The other
-- entries are all presorted in increasing order of brightness.
ubyte CharacterData[...];
-- RLE character data, in order
*/
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include <stdlib.h> #include <stdlib.h>
@ -171,7 +210,7 @@ static TArray<PalEntry> TranslationColors;
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
FFont * V_GetFont(const char *name) FFont *V_GetFont(const char *name)
{ {
FFont *font = FFont::FindFont (name); FFont *font = FFont::FindFont (name);
if (font == NULL) if (font == NULL)
@ -210,7 +249,7 @@ FFont * V_GetFont(const char *name)
} }
if (picnum > 0) if (picnum > 0)
{ {
font = new FSingleLumpFont (name, -1); font = new FSinglePicFont (name);
} }
} }
} }
@ -334,7 +373,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
{ {
SpaceWidth = 4; SpaceWidth = 4;
} }
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors); BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
delete[] luminosity; delete[] luminosity;
delete[] charlumps; delete[] charlumps;
@ -538,12 +577,13 @@ int FFont::SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *reverse
// large this array is. Identity is an array that remaps the colors to // large this array is. Identity is an array that remaps the colors to
// their original values; it is only used for CR_UNTRANSLATED. Ranges // their original values; it is only used for CR_UNTRANSLATED. Ranges
// is an array of TranslationParm structs defining the ranges for every // is an array of TranslationParm structs defining the ranges for every
// possible color, in order. // possible color, in order. Palette is the colors to use for the
// untranslated version of the font.
// //
//========================================================================== //==========================================================================
void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, void FFont::BuildTranslations (const double *luminosity, const BYTE *identity,
const void *ranges, int total_colors) const void *ranges, int total_colors, const PalEntry *palette)
{ {
int i, j; int i, j;
const TranslationParm *parmstart = (const TranslationParm *)ranges; const TranslationParm *parmstart = (const TranslationParm *)ranges;
@ -559,9 +599,17 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity,
if (identity != NULL) if (identity != NULL)
{ {
memcpy (remap.Remap, identity, ActiveColors); memcpy (remap.Remap, identity, ActiveColors);
for (j = 0; j < ActiveColors; ++j) if (palette != NULL)
{ {
remap.Palette[j] = GPalette.BaseColors[identity[j]]; memcpy (remap.Palette, palette, ActiveColors*sizeof(PalEntry));
}
else
{
remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0,255,255,255);
for (j = 1; j < ActiveColors; ++j)
{
remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255,0,0,0);
}
} }
} }
else else
@ -712,52 +760,35 @@ FFont::FFont ()
// //
// FSingleLumpFont :: FSingleLumpFont // FSingleLumpFont :: FSingleLumpFont
// //
// Loads a FON1 or FON2 font resource or a single texture. // Loads a FON1 or FON2 font resource.
// //
//========================================================================== //==========================================================================
FSingleLumpFont::FSingleLumpFont (const char *name, int lump) FSingleLumpFont::FSingleLumpFont (const char *name, int lump)
{ {
assert(lump >= 0);
Name = copystring (name); Name = copystring (name);
// If lump is -1, then the font name is really a texture name, so FMemLump data1 = Wads.ReadLump (lump);
// the font should be a redirect to the texture. const BYTE *data = (const BYTE *)data1.GetMem();
// If lump is >= 0, then the font is really a font.
if (lump < 0)
{
int picnum = TexMan.CheckForTexture (name, FTexture::TEX_Any);
if (picnum > 0) if (data[0] != 'F' || data[1] != 'O' || data[2] != 'N' ||
{ (data[3] != '1' && data[3] != '2'))
CreateFontFromPic (picnum); {
} I_FatalError ("%s is not a recognizable font", name);
else
{
I_FatalError ("%s is not a font or texture", name);
}
} }
else else
{ {
FMemLump data1 = Wads.ReadLump (lump); switch (data[3])
const BYTE *data = (const BYTE *)data1.GetMem();
if (data[0] != 'F' || data[1] != 'O' || data[2] != 'N' ||
(data[3] != '1' && data[3] != '2'))
{ {
I_FatalError ("%s is not a recognizable font", name); case '1':
} LoadFON1 (lump, data);
else break;
{
switch (data[3])
{
case '1':
LoadFON1 (lump, data);
break;
case '2': case '2':
LoadFON2 (lump, data); LoadFON2 (lump, data);
break; break;
}
} }
} }
@ -813,7 +844,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const BYTE *data)
PatchRemap = new BYTE[256]; PatchRemap = new BYTE[256];
CheckFON1Chars (lump, data, luminosity); CheckFON1Chars (lump, data, luminosity);
BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors); BuildTranslations (luminosity, NULL, &TranslationParms[1][0], ActiveColors, NULL);
} }
//========================================================================== //==========================================================================
@ -831,6 +862,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
int *widths2; int *widths2;
BYTE identity[256]; BYTE identity[256];
double luminosity[256]; double luminosity[256];
PalEntry local_palette[256];
WORD *widths; WORD *widths;
const BYTE *palette; const BYTE *palette;
const BYTE *data_p; const BYTE *data_p;
@ -844,19 +876,19 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
Chars = new CharData[count]; Chars = new CharData[count];
widths2 = new int[count]; widths2 = new int[count];
if (data[11] & 1) if (data[11] & 1)
{ { // Font specifies a kerning value.
GlobalKerning = LittleShort(*(SWORD *)&data[12]); GlobalKerning = LittleShort(*(SWORD *)&data[12]);
widths = (WORD *)(data + 14); widths = (WORD *)(data + 14);
} }
else else
{ { // Font does not specify a kerning value.
GlobalKerning = 0; GlobalKerning = 0;
widths = (WORD *)(data + 12); widths = (WORD *)(data + 12);
} }
totalwidth = 0; totalwidth = 0;
if (data[8]) if (data[8])
{ { // Font is mono-spaced.
totalwidth = LittleShort(widths[0]); totalwidth = LittleShort(widths[0]);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
@ -866,7 +898,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
palette = (BYTE *)&widths[1]; palette = (BYTE *)&widths[1];
} }
else else
{ { // Font has varying character widths.
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
{ {
widths2[i] = LittleShort(widths[i]); widths2[i] = LittleShort(widths[i]);
@ -888,7 +920,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
SpaceWidth = totalwidth * 2 / (3 * count); SpaceWidth = totalwidth * 2 / (3 * count);
} }
FixupPalette (identity, luminosity, palette, data[9] == 0); FixupPalette (identity, luminosity, palette, data[9] == 0, local_palette);
data_p = palette + (ActiveColors+1)*3; data_p = palette + (ActiveColors+1)*3;
@ -924,7 +956,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data)
} }
} }
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors); BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, local_palette);
delete[] widths2; delete[] widths2;
} }
@ -999,7 +1031,7 @@ void FSingleLumpFont::CheckFON1Chars (int lump, const BYTE *data, double *lumino
// //
//========================================================================== //==========================================================================
void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette, bool rescale) void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette, bool rescale, PalEntry *out_palette)
{ {
int i; int i;
double maxlum = 0.0; double maxlum = 0.0;
@ -1009,20 +1041,24 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
identity[0] = 0; identity[0] = 0;
palette += 3; // Skip the transparent color palette += 3; // Skip the transparent color
for (i = 1; i <= ActiveColors; ++i) for (i = 1; i <= ActiveColors; ++i, palette += 3)
{ {
int r = palette[0]; int r = palette[0];
int g = palette[1]; int g = palette[1];
int b = palette[2]; int b = palette[2];
double lum = r*0.299 + g*0.587 + b*0.114; double lum = r*0.299 + g*0.587 + b*0.114;
palette += 3;
identity[i] = ColorMatcher.Pick (r, g, b); identity[i] = ColorMatcher.Pick (r, g, b);
luminosity[i] = lum; luminosity[i] = lum;
out_palette[i].r = r;
out_palette[i].g = g;
out_palette[i].b = b;
out_palette[i].a = 255;
if (lum > maxlum) if (lum > maxlum)
maxlum = lum; maxlum = lum;
if (lum < minlum) if (lum < minlum)
minlum = lum; minlum = lum;
} }
out_palette[0] = 0;
if (rescale) if (rescale)
{ {
@ -1038,6 +1074,74 @@ void FSingleLumpFont::FixupPalette (BYTE *identity, double *luminosity, const BY
} }
} }
//==========================================================================
//
// FSinglePicFont :: FSinglePicFont
//
// Creates a font to wrap a texture so that you can use hudmessage as if it
// were a hudpic command. It does not support translation, but animation
// is supported, unlike all the real fonts.
//
//==========================================================================
FSinglePicFont::FSinglePicFont(const char *picname)
{
int picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Any);
if (picnum <= 0)
{
I_FatalError ("%s is not a font or texture", picname);
}
FTexture *pic = TexMan[picnum];
Name = copystring(picname);
FontHeight = pic->GetHeight();
SpaceWidth = pic->GetWidth();
GlobalKerning = 0;
FirstChar = LastChar = 'A';
ActiveColors = 0;
PicNum = picnum;
Next = FirstFont;
FirstFont = this;
}
//==========================================================================
//
// FSinglePicFont :: GetChar
//
// Returns the texture if code is 'a' or 'A', otherwise NULL.
//
//==========================================================================
FTexture *FSinglePicFont::GetChar (int code, int *const width) const
{
*width = SpaceWidth;
if (code == 'a' || code == 'A')
{
return TexMan(PicNum);
}
else
{
return NULL;
}
}
//==========================================================================
//
// FSinglePicFont :: GetCharWidth
//
// Don't expect the text functions to work properly if I actually allowed
// the character width to vary depending on the animation frame.
//
//==========================================================================
int FSinglePicFont::GetCharWidth (int code) const
{
return SpaceWidth;
}
//========================================================================== //==========================================================================
// //
// FFontChar1 :: FFontChar1 // FFontChar1 :: FFontChar1
@ -1438,7 +1542,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis
SpaceWidth = 4; SpaceWidth = 4;
} }
BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors); BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors, NULL);
// add the untranslated colors to the Ranges tables // add the untranslated colors to the Ranges tables
if (ActiveColors < TotalColors) if (ActiveColors < TotalColors)
@ -1470,6 +1574,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis
void V_InitCustomFonts() void V_InitCustomFonts()
{ {
FScanner sc;
int lumplist[256]; int lumplist[256];
bool notranslate[256]; bool notranslate[256];
char namebuffer[16], templatebuf[16]; char namebuffer[16], templatebuf[16];
@ -1482,75 +1587,75 @@ void V_InitCustomFonts()
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1) while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
{ {
SC_OpenLumpNum (llump, "FONTDEFS"); sc.OpenLumpNum(llump, "FONTDEFS");
while (SC_GetString()) while (sc.GetString())
{ {
memset (lumplist, -1, sizeof(lumplist)); memset (lumplist, -1, sizeof(lumplist));
memset (notranslate, 0, sizeof(notranslate)); memset (notranslate, 0, sizeof(notranslate));
strncpy (namebuffer, sc_String, 15); strncpy (namebuffer, sc.String, 15);
namebuffer[15] = 0; namebuffer[15] = 0;
format = 0; format = 0;
start = 33; start = 33;
first = 33; first = 33;
count = 223; count = 223;
SC_MustGetStringName ("{"); sc.MustGetStringName ("{");
while (!SC_CheckString ("}")) while (!sc.CheckString ("}"))
{ {
SC_MustGetString(); sc.MustGetString();
if (SC_Compare ("TEMPLATE")) if (sc.Compare ("TEMPLATE"))
{ {
if (format == 2) goto wrong; if (format == 2) goto wrong;
SC_MustGetString(); sc.MustGetString();
strncpy (templatebuf, sc_String, 16); strncpy (templatebuf, sc.String, 16);
templatebuf[15] = 0; templatebuf[15] = 0;
format = 1; format = 1;
} }
else if (SC_Compare ("BASE")) else if (sc.Compare ("BASE"))
{ {
if (format == 2) goto wrong; if (format == 2) goto wrong;
SC_MustGetNumber(); sc.MustGetNumber();
start = sc_Number; start = sc.Number;
format = 1; format = 1;
} }
else if (SC_Compare ("FIRST")) else if (sc.Compare ("FIRST"))
{ {
if (format == 2) goto wrong; if (format == 2) goto wrong;
SC_MustGetNumber(); sc.MustGetNumber();
first = sc_Number; first = sc.Number;
format = 1; format = 1;
} }
else if (SC_Compare ("COUNT")) else if (sc.Compare ("COUNT"))
{ {
if (format == 2) goto wrong; if (format == 2) goto wrong;
SC_MustGetNumber(); sc.MustGetNumber();
count = sc_Number; count = sc.Number;
format = 1; format = 1;
} }
else if (SC_Compare ("NOTRANSLATION")) else if (sc.Compare ("NOTRANSLATION"))
{ {
if (format == 1) goto wrong; if (format == 1) goto wrong;
while (SC_CheckNumber() && !sc_Crossed) while (sc.CheckNumber() && !sc.Crossed)
{ {
if (sc_Number >= 0 && sc_Number < 256) if (sc.Number >= 0 && sc.Number < 256)
notranslate[sc_Number] = true; notranslate[sc.Number] = true;
} }
format=2; format=2;
} }
else else
{ {
if (format == 1) goto wrong; if (format == 1) goto wrong;
int *p = &lumplist[*(unsigned char*)sc_String]; int *p = &lumplist[*(unsigned char*)sc.String];
SC_MustGetString(); sc.MustGetString();
*p = Wads.CheckNumForName (sc_String); *p = Wads.CheckNumForName (sc.String);
format=2; format=2;
} }
} }
if (format==1) if (format == 1)
{ {
new FFont (namebuffer, templatebuf, first, count, start); new FFont (namebuffer, templatebuf, first, count, start);
} }
else if (format==2) else if (format == 2)
{ {
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
@ -1575,12 +1680,12 @@ void V_InitCustomFonts()
} }
else goto wrong; else goto wrong;
} }
SC_Close (); sc.Close();
} }
return; return;
wrong: wrong:
SC_ScriptError ("Invalid combination of properties in font '%s'", namebuffer); sc.ScriptError ("Invalid combination of properties in font '%s'", namebuffer);
} }
//========================================================================== //==========================================================================
@ -1610,8 +1715,8 @@ void V_InitFontColors ()
while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1) while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1)
{ {
SC_OpenLumpNum (lump, "textcolors.txt"); FScanner sc(lump, "textcolors.txt");
while (SC_GetString()) while (sc.GetString())
{ {
names.Clear(); names.Clear();
@ -1619,14 +1724,14 @@ void V_InitFontColors ()
// Everything until the '{' is considered a valid name for the // Everything until the '{' is considered a valid name for the
// color range. // color range.
names.Push (sc_String); names.Push (sc.String);
while (SC_MustGetString(), !SC_Compare ("{")) while (sc.MustGetString(), !sc.Compare ("{"))
{ {
if (names[0] == NAME_Untranslated) if (names[0] == NAME_Untranslated)
{ {
SC_ScriptError ("The \"untranslated\" color may not have any other names"); sc.ScriptError ("The \"untranslated\" color may not have any other names");
} }
names.Push (sc_String); names.Push (sc.String);
} }
parmchoice = 0; parmchoice = 0;
@ -1635,66 +1740,66 @@ void V_InitFontColors ()
info.ParmLen[1] = info.ParmLen[0] = 0; info.ParmLen[1] = info.ParmLen[0] = 0;
tparm.RangeEnd = tparm.RangeStart = -1; tparm.RangeEnd = tparm.RangeStart = -1;
while (SC_MustGetString(), !SC_Compare ("}")) while (sc.MustGetString(), !sc.Compare ("}"))
{ {
if (SC_Compare ("Console:")) if (sc.Compare ("Console:"))
{ {
if (parmchoice == 1) if (parmchoice == 1)
{ {
SC_ScriptError ("Each color may only have one set of console ranges"); sc.ScriptError ("Each color may only have one set of console ranges");
} }
parmchoice = 1; parmchoice = 1;
info.StartParm[1] = parms.Size(); info.StartParm[1] = parms.Size();
info.ParmLen[0] = info.StartParm[1] - info.StartParm[0]; info.ParmLen[0] = info.StartParm[1] - info.StartParm[0];
tparm.RangeEnd = tparm.RangeStart = -1; tparm.RangeEnd = tparm.RangeStart = -1;
} }
else if (SC_Compare ("Flat:")) else if (sc.Compare ("Flat:"))
{ {
SC_MustGetString(); sc.MustGetString();
logcolor = V_GetColor (NULL, sc_String); logcolor = V_GetColor (NULL, sc.String);
} }
else else
{ {
// Get first color // Get first color
c = V_GetColor (NULL, sc_String); c = V_GetColor (NULL, sc.String);
tparm.Start[0] = RPART(c); tparm.Start[0] = RPART(c);
tparm.Start[1] = GPART(c); tparm.Start[1] = GPART(c);
tparm.Start[2] = BPART(c); tparm.Start[2] = BPART(c);
// Get second color // Get second color
SC_MustGetString(); sc.MustGetString();
c = V_GetColor (NULL, sc_String); c = V_GetColor (NULL, sc.String);
tparm.End[0] = RPART(c); tparm.End[0] = RPART(c);
tparm.End[1] = GPART(c); tparm.End[1] = GPART(c);
tparm.End[2] = BPART(c); tparm.End[2] = BPART(c);
// Check for range specifier // Check for range specifier
if (SC_CheckNumber()) if (sc.CheckNumber())
{ {
if (tparm.RangeStart == -1 && sc_Number != 0) if (tparm.RangeStart == -1 && sc.Number != 0)
{ {
SC_ScriptError ("The first color range must start at position 0"); sc.ScriptError ("The first color range must start at position 0");
} }
if (sc_Number < 0 || sc_Number > 256) if (sc.Number < 0 || sc.Number > 256)
{ {
SC_ScriptError ("The color range must be within positions [0,256]"); sc.ScriptError ("The color range must be within positions [0,256]");
} }
if (sc_Number <= tparm.RangeEnd) if (sc.Number <= tparm.RangeEnd)
{ {
SC_ScriptError ("The color range must not start before the previous one ends"); sc.ScriptError ("The color range must not start before the previous one ends");
} }
tparm.RangeStart = sc_Number; tparm.RangeStart = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
if (sc_Number < 0 || sc_Number > 256) if (sc.Number < 0 || sc.Number > 256)
{ {
SC_ScriptError ("The color range must be within positions [0,256]"); sc.ScriptError ("The color range must be within positions [0,256]");
} }
if (sc_Number <= tparm.RangeStart) if (sc.Number <= tparm.RangeStart)
{ {
SC_ScriptError ("The color range end position must be larger than the start position"); sc.ScriptError ("The color range end position must be larger than the start position");
} }
tparm.RangeEnd = sc_Number; tparm.RangeEnd = sc.Number;
} }
else else
{ {
@ -1702,7 +1807,7 @@ void V_InitFontColors ()
tparm.RangeEnd = 256; tparm.RangeEnd = 256;
if (tparm.RangeStart >= tparm.RangeEnd) if (tparm.RangeStart >= tparm.RangeEnd)
{ {
SC_ScriptError ("The color has too many ranges"); sc.ScriptError ("The color has too many ranges");
} }
} }
parms.Push (tparm); parms.Push (tparm);
@ -1713,14 +1818,14 @@ void V_InitFontColors ()
{ {
if (names[0] != NAME_Untranslated) if (names[0] != NAME_Untranslated)
{ {
SC_ScriptError ("There must be at least one normal range for a color"); sc.ScriptError ("There must be at least one normal range for a color");
} }
} }
else else
{ {
if (names[0] == NAME_Untranslated) if (names[0] == NAME_Untranslated)
{ {
SC_ScriptError ("The \"untranslated\" color must be left undefined"); sc.ScriptError ("The \"untranslated\" color must be left undefined");
} }
} }
if (info.ParmLen[1] == 0 && names[0] != NAME_Untranslated) if (info.ParmLen[1] == 0 && names[0] != NAME_Untranslated)
@ -1755,7 +1860,6 @@ void V_InitFontColors ()
} }
} }
} }
SC_Close ();
} }
// Make permananent copies of all the color information we found. // Make permananent copies of all the color information we found.
for (i = 0, index = 0; i < colorinfo.Size(); ++i) for (i = 0, index = 0; i < colorinfo.Size(); ++i)

View file

@ -85,8 +85,8 @@ public:
FFont (const char *fontname, const char *nametemplate, int first, int count, int base); FFont (const char *fontname, const char *nametemplate, int first, int count, int base);
~FFont (); ~FFont ();
FTexture *GetChar (int code, int *const width) const; virtual FTexture *GetChar (int code, int *const width) const;
int GetCharWidth (int code) const; virtual int GetCharWidth (int code) const;
FRemapTable *GetColorTranslation (EColorRange range) const; FRemapTable *GetColorTranslation (EColorRange range) const;
int GetSpaceWidth () const { return SpaceWidth; } int GetSpaceWidth () const { return SpaceWidth; }
int GetHeight () const { return FontHeight; } int GetHeight () const { return FontHeight; }
@ -101,9 +101,11 @@ public:
protected: protected:
FFont (); FFont ();
void BuildTranslations (const double *luminosity, const BYTE *identity, const void *ranges, int total_colors); void BuildTranslations (const double *luminosity, const BYTE *identity,
const void *ranges, int total_colors, const PalEntry *palette);
static int SimpleTranslation (BYTE *colorsused, BYTE *translation, BYTE *identity, double **luminosity); static int SimpleTranslation (BYTE *colorsused, BYTE *translation,
BYTE *identity, double **luminosity);
int FirstChar, LastChar; int FirstChar, LastChar;
int SpaceWidth; int SpaceWidth;
@ -141,12 +143,26 @@ public:
protected: protected:
void CheckFON1Chars (int lump, const BYTE *data, double *luminosity); void CheckFON1Chars (int lump, const BYTE *data, double *luminosity);
void BuildTranslations2 (); void BuildTranslations2 ();
void FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette, bool rescale); void FixupPalette (BYTE *identity, double *luminosity, const BYTE *palette,
bool rescale, PalEntry *out_palette);
void LoadFON1 (int lump, const BYTE *data); void LoadFON1 (int lump, const BYTE *data);
void LoadFON2 (int lump, const BYTE *data); void LoadFON2 (int lump, const BYTE *data);
void CreateFontFromPic (int picnum); void CreateFontFromPic (int picnum);
}; };
class FSinglePicFont : public FFont
{
public:
FSinglePicFont(const char *picname);
// FFont interface
FTexture *GetChar (int code, int *const width) const;
int GetCharWidth (int code) const;
protected:
int PicNum;
};
void RecordTextureColors (FTexture *pic, BYTE *colorsused); void RecordTextureColors (FTexture *pic, BYTE *colorsused);
extern FFont *SmallFont, *SmallFont2, *BigFont, *ConFont; extern FFont *SmallFont, *SmallFont2, *BigFont, *ConFont;

View file

@ -59,11 +59,11 @@ extern "C" {
FDynamicColormap NormalLight; FDynamicColormap NormalLight;
} }
FPalette GPalette; FPalette GPalette;
BYTE InverseColormap[NUMCOLORMAPS*256]; BYTE InverseColormap[256];
BYTE GoldColormap[NUMCOLORMAPS*256]; BYTE GoldColormap[256];
// [BC] New Skulltag colormaps. // [BC] New Skulltag colormaps.
BYTE RedColormap[NUMCOLORMAPS*256]; BYTE RedColormap[256];
BYTE GreenColormap[NUMCOLORMAPS*256]; BYTE GreenColormap[256];
int Near255; int Near255;
static void FreeSpecialLights();; static void FreeSpecialLights();;
@ -386,7 +386,7 @@ void InitPalette ()
// build special maps (e.g. invulnerability) // build special maps (e.g. invulnerability)
int intensity; int intensity;
// Doom invulnerability is an inverted grayscale // Doom invulnerability is an inverted grayscale.
// Strife uses it when firing the Sigil // Strife uses it when firing the Sigil
shade = InverseColormap; shade = InverseColormap;
@ -396,10 +396,10 @@ void InitPalette ()
(GPalette.BaseColors[c].r * 77 + (GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37)) >> 8; GPalette.BaseColors[c].b * 37)) >> 8;
*shade++ = ColorMatcher.Pick (intensity, intensity, intensity); shade[c] = ColorMatcher.Pick (intensity, intensity, intensity);
} }
// Heretic invulnerability is a golden shade // Heretic invulnerability is a golden shade.
shade = GoldColormap; shade = GoldColormap;
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
@ -407,7 +407,7 @@ void InitPalette ()
intensity = GPalette.BaseColors[c].r * 77 + intensity = GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37; GPalette.BaseColors[c].b * 37;
*shade++ = ColorMatcher.Pick ( shade[c] = ColorMatcher.Pick (
MIN (255, (intensity+intensity/2)>>8), intensity>>8, 0); MIN (255, (intensity+intensity/2)>>8), intensity>>8, 0);
} }
@ -418,7 +418,7 @@ void InitPalette ()
intensity = ((GPalette.BaseColors[c].r * 77 + intensity = ((GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37)); GPalette.BaseColors[c].b * 37));
*shade++ = ColorMatcher.Pick ( shade[c] = ColorMatcher.Pick (
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), 0, 0 ); MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), 0, 0 );
} }
@ -429,8 +429,10 @@ void InitPalette ()
intensity = GPalette.BaseColors[c].r * 77 + intensity = GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37; GPalette.BaseColors[c].b * 37;
*shade++ = ColorMatcher.Pick ( shade[c] = ColorMatcher.Pick (
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ), intensity>>8 ); MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
intensity>>8 );
} }
} }
@ -743,7 +745,7 @@ void FDynamicColormap::BuildLights ()
} }
} }
else else
{ // Colored light, so do the slower thing { // Colored light, so do the (slightly) slower thing
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
{ {
*shade++ = ColorMatcher.Pick ( *shade++ = ColorMatcher.Pick (

View file

@ -80,11 +80,11 @@ struct FDynamicColormap
FDynamicColormap *Next; FDynamicColormap *Next;
}; };
extern BYTE InverseColormap[NUMCOLORMAPS*256]; extern BYTE InverseColormap[256];
extern BYTE GoldColormap[NUMCOLORMAPS*256]; extern BYTE GoldColormap[256];
// [BC] New Skulltag colormaps. // [BC] New Skulltag colormaps.
extern BYTE RedColormap[NUMCOLORMAPS*256]; extern BYTE RedColormap[256];
extern BYTE GreenColormap[NUMCOLORMAPS*256]; extern BYTE GreenColormap[256];
extern FPalette GPalette; extern FPalette GPalette;
extern "C" { extern "C" {
extern FDynamicColormap NormalLight; extern FDynamicColormap NormalLight;

View file

@ -132,8 +132,9 @@ int DisplayWidth, DisplayHeight, DisplayBits;
FFont *SmallFont, *SmallFont2, *BigFont, *ConFont; FFont *SmallFont, *SmallFont2, *BigFont, *ConFont;
extern "C" { extern "C" {
DWORD *Col2RGB8_LessPrecision[65];
DWORD Col2RGB8[65][256]; DWORD Col2RGB8[65][256];
DWORD *Col2RGB8_LessPrecision[65];
DWORD Col2RGB8_Inverse[65][256];
BYTE RGB32k[32][32][32]; BYTE RGB32k[32][32][32];
} }
@ -682,6 +683,15 @@ static void BuildTransTable (const PalEntry *palette)
} }
Col2RGB8_LessPrecision[0] = Col2RGB8[0]; Col2RGB8_LessPrecision[0] = Col2RGB8[0];
Col2RGB8_LessPrecision[64] = Col2RGB8[64]; Col2RGB8_LessPrecision[64] = Col2RGB8[64];
// create the inverse swizzled palette
for (x = 0; x < 65; x++)
for (y = 0; y < 256; y++)
{
Col2RGB8_Inverse[x][y] = (((((255-palette[y].r)*x)>>4)<<20) |
(((255-palette[y].g)*x)>>4) |
((((255-palette[y].b)*x)>>4)<<10)) & 0x3feffbff;
}
} }
//========================================================================== //==========================================================================

View file

@ -239,7 +239,7 @@ protected:
INTBOOL keepratio; INTBOOL keepratio;
INTBOOL masked; INTBOOL masked;
INTBOOL bilinear; INTBOOL bilinear;
ERenderStyle style; FRenderStyle style;
}; };
bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const;
@ -411,10 +411,35 @@ extern DFrameBuffer *screen;
EXTERN_CVAR (Float, Gamma) EXTERN_CVAR (Float, Gamma)
// Translucency tables // Translucency tables
extern "C" DWORD Col2RGB8[65][256];
// RGB32k is a normal R5G5B5 -> palette lookup table.
extern "C" BYTE RGB32k[32][32][32]; extern "C" BYTE RGB32k[32][32][32];
// Col2RGB8 is a pre-multiplied palette for color lookup. It is stored in a
// special R10B10G10 format for efficient blending computation.
// --RRRRRrrr--BBBBBbbb--GGGGGggg-- at level 64
// --------rrrr------bbbb------gggg at level 1
extern "C" DWORD Col2RGB8[65][256];
// Col2RGB8_LessPrecision is the same as Col2RGB8, but the LSB for red
// and blue are forced to zero, so if the blend overflows, it won't spill
// over into the next component's value.
// --RRRRRrrr-#BBBBBbbb-#GGGGGggg-- at level 64
// --------rrr#------bbb#------gggg at level 1
extern "C" DWORD *Col2RGB8_LessPrecision[65]; extern "C" DWORD *Col2RGB8_LessPrecision[65];
// Col2RGB8_Inverse is the same as Col2RGB8_LessPrecision, except the source
// palette has been inverted.
extern "C" DWORD Col2RGB8_Inverse[65][256];
// "Magic" numbers used during the blending:
// --000001111100000111110000011111 = 0x01f07c1f
// -0111111111011111111101111111111 = 0x3FEFFBFF
// -1000000000100000000010000000000 = 0x40100400
// ------10000000001000000000100000 = 0x40100400 >> 5
// --11111-----11111-----11111----- = 0x40100400 - (0x40100400 >> 5) aka "white"
// --111111111111111111111111111111 = 0x3FFFFFFF
// Allocates buffer screens, call before R_Init. // Allocates buffer screens, call before R_Init.
void V_Init (); void V_Init ();

View file

@ -134,6 +134,7 @@ public:
~FMemLump (); ~FMemLump ();
void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); } void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); }
size_t GetSize () { return Block.Len(); } size_t GetSize () { return Block.Len(); }
FString GetString () { return Block; }
private: private:
FMemLump (const FString &source); FMemLump (const FString &source);

View file

@ -386,7 +386,7 @@ void WI_LoadBackground(bool isenterpic)
lnodes.Clear(); lnodes.Clear();
anims.Clear(); anims.Clear();
yah.Clear(); yah.Clear();
splat=NULL; splat = NULL;
// a name with a starting '$' indicates an intermission script // a name with a starting '$' indicates an intermission script
if (*lumpname!='$') if (*lumpname!='$')
@ -400,154 +400,154 @@ void WI_LoadBackground(bool isenterpic)
int lumpnum=Wads.GetNumForName(lumpname+1); int lumpnum=Wads.GetNumForName(lumpname+1);
if (lumpnum>=0) if (lumpnum>=0)
{ {
SC_OpenLumpNum(lumpnum,lumpname+1); FScanner sc(lumpnum,lumpname+1);
while (SC_GetString()) while (sc.GetString())
{ {
memset(&an,0,sizeof(an)); memset(&an,0,sizeof(an));
int caseval=SC_MustMatchString(WI_Cmd); int caseval = sc.MustMatchString(WI_Cmd);
switch(caseval) switch(caseval)
{ {
case 0: // Background case 0: // Background
SC_MustGetString(); sc.MustGetString();
texture=TexMan.CheckForTexture(sc_String, FTexture::TEX_MiscPatch,FTextureManager::TEXMAN_TryAny); texture=TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch,FTextureManager::TEXMAN_TryAny);
if (texture == -1) texture = TexMan.AddPatch(sc_String); if (texture == -1) texture = TexMan.AddPatch(sc.String);
break; break;
case 1: // Splat case 1: // Splat
SC_MustGetString(); sc.MustGetString();
splat=TexMan[TexMan.AddPatch(sc_String)]; splat=TexMan[TexMan.AddPatch(sc.String)];
break; break;
case 2: // Pointers case 2: // Pointers
while (SC_GetString() && !sc_Crossed) while (sc.GetString() && !sc.Crossed)
{ {
int v=TexMan.AddPatch(sc_String); int v = TexMan.AddPatch(sc.String);
yah.Push(TexMan[v]); yah.Push(TexMan[v]);
} }
if (sc_Crossed) SC_UnGet(); if (sc.Crossed) sc.UnGet();
break; break;
case 3: // Spots case 3: // Spots
SC_MustGetStringName("{"); sc.MustGetStringName("{");
while (!SC_CheckString("}")) while (!sc.CheckString("}"))
{ {
SC_MustGetString(); sc.MustGetString();
strncpy(pt.level, sc_String,8); strncpy(pt.level, sc.String,8);
pt.level[8]=0; pt.level[8] = 0;
SC_MustGetNumber(); sc.MustGetNumber();
pt.x=sc_Number; pt.x = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
pt.y=sc_Number; pt.y = sc.Number;
lnodes.Push(pt); lnodes.Push(pt);
} }
break; break;
case 4: // IfEntering case 4: // IfEntering
an.type=ANIM_IFENTERING; an.type = ANIM_IFENTERING;
goto readanimation; goto readanimation;
case 5: // IfEntering case 5: // IfEntering
an.type=ANIM_IFNOTENTERING; an.type = ANIM_IFNOTENTERING;
goto readanimation; goto readanimation;
case 6: // IfVisited case 6: // IfVisited
an.type=ANIM_IFVISITED; an.type = ANIM_IFVISITED;
goto readanimation; goto readanimation;
case 7: // IfNotVisited case 7: // IfNotVisited
an.type=ANIM_IFNOTVISITED; an.type = ANIM_IFNOTVISITED;
goto readanimation; goto readanimation;
case 8: // IfLeaving case 8: // IfLeaving
an.type=ANIM_IFLEAVING; an.type = ANIM_IFLEAVING;
goto readanimation; goto readanimation;
case 9: // IfNotLeaving case 9: // IfNotLeaving
an.type=ANIM_IFNOTLEAVING; an.type = ANIM_IFNOTLEAVING;
goto readanimation; goto readanimation;
case 10: // IfTravelling case 10: // IfTravelling
an.type=ANIM_IFTRAVELLING; an.type = ANIM_IFTRAVELLING;
SC_MustGetString(); sc.MustGetString();
strncpy(an.levelname2,sc_String,8); strncpy(an.levelname2, sc.String, 8);
an.levelname2[8]=0; an.levelname2[8] = 0;
goto readanimation; goto readanimation;
case 11: // IfNotTravelling case 11: // IfNotTravelling
an.type=ANIM_IFTRAVELLING; an.type = ANIM_IFTRAVELLING;
SC_MustGetString(); sc.MustGetString();
strncpy(an.levelname2,sc_String,8); strncpy(an.levelname2, sc.String, 8);
an.levelname2[8]=0; an.levelname2[8] = 0;
goto readanimation; goto readanimation;
case 14: // NoAutostartMap case 14: // NoAutostartMap
noautostartmap=true; noautostartmap = true;
break; break;
readanimation: readanimation:
SC_MustGetString(); sc.MustGetString();
strncpy(an.levelname,sc_String,8); strncpy(an.levelname, sc.String, 8);
an.levelname[8]=0; an.levelname[8] = 0;
SC_MustGetString(); sc.MustGetString();
caseval=SC_MustMatchString(WI_Cmd); caseval=sc.MustMatchString(WI_Cmd);
default: default:
switch (caseval) switch (caseval)
{ {
case 12: // Animation case 12: // Animation
an.type |= ANIM_ALWAYS; an.type |= ANIM_ALWAYS;
SC_MustGetNumber(); sc.MustGetNumber();
an.loc.x=sc_Number; an.loc.x = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
an.loc.y=sc_Number; an.loc.y = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
an.period=sc_Number; an.period = sc.Number;
an.nexttic = 1 + (M_Random()%an.period); an.nexttic = 1 + (M_Random() % an.period);
if (SC_GetString()) if (sc.GetString())
{ {
if (SC_Compare("ONCE")) if (sc.Compare("ONCE"))
{ {
an.data=1; an.data = 1;
} }
else else
{ {
SC_UnGet(); sc.UnGet();
} }
} }
if (!SC_CheckString("{")) if (!sc.CheckString("{"))
{ {
SC_MustGetString(); sc.MustGetString();
an.p[an.nanims++]=TexMan[TexMan.AddPatch(sc_String)]; an.p[an.nanims++] = TexMan[TexMan.AddPatch(sc.String)];
} }
else else
{ {
while (!SC_CheckString("}")) while (!sc.CheckString("}"))
{ {
SC_MustGetString(); sc.MustGetString();
if (an.nanims<MAX_ANIMATION_FRAMES) an.p[an.nanims++]=TexMan[TexMan.AddPatch(sc_String)]; if (an.nanims<MAX_ANIMATION_FRAMES)
an.p[an.nanims++] = TexMan[TexMan.AddPatch(sc.String)];
} }
} }
an.ctr=-1; an.ctr = -1;
anims.Push(an); anims.Push(an);
break; break;
case 13: // Pic case 13: // Pic
an.type |= ANIM_PIC; an.type |= ANIM_PIC;
SC_MustGetNumber(); sc.MustGetNumber();
an.loc.x=sc_Number; an.loc.x = sc.Number;
SC_MustGetNumber(); sc.MustGetNumber();
an.loc.y=sc_Number; an.loc.y = sc.Number;
SC_MustGetString(); sc.MustGetString();
an.p[0]=TexMan[TexMan.AddPatch(sc_String)]; an.p[0] = TexMan[TexMan.AddPatch(sc.String)];
anims.Push(an); anims.Push(an);
break; break;
default: default:
SC_ScriptError("Unknown token %s in intermission script", sc_String); sc.ScriptError("Unknown token %s in intermission script", sc.String);
} }
} }
} }
SC_Close();
} }
else else
{ {

View file

@ -148,6 +148,7 @@ public:
D3DPal *Next; D3DPal *Next;
IDirect3DTexture9 *Tex; IDirect3DTexture9 *Tex;
D3DCOLOR BorderColor;
bool Update(); bool Update();
@ -159,12 +160,12 @@ public:
enum enum
{ {
BQF_GamePalette = 1, BQF_GamePalette = 1,
BQF_ShadedPalette = 2, BQF_CustomPalette = 7,
BQF_CustomPalette = 3,
BQF_StencilPalette = 4,
BQF_Paletted = 7, BQF_Paletted = 7,
BQF_Bilinear = 8, BQF_Bilinear = 8,
BQF_WrapUV = 16, BQF_WrapUV = 16,
BQF_InvertSource = 32,
BQF_DisableAlphaTest= 64,
}; };
// Shaders for a buffered quad // Shaders for a buffered quad
@ -172,7 +173,7 @@ enum
{ {
BQS_PalTex, BQS_PalTex,
BQS_Plain, BQS_Plain,
BQS_PlainStencil, BQS_RedToAlpha,
BQS_ColorOnly BQS_ColorOnly
}; };
@ -231,12 +232,12 @@ D3DFB::D3DFB (int width, int height, bool fullscreen)
ScreenshotSurface = NULL; ScreenshotSurface = NULL;
FinalWipeScreen = NULL; FinalWipeScreen = NULL;
PaletteTexture = NULL; PaletteTexture = NULL;
StencilPaletteTexture = NULL;
ShadedPaletteTexture = NULL;
PalTexShader = NULL; PalTexShader = NULL;
InvPalTexShader = NULL;
PalTexBilinearShader = NULL; PalTexBilinearShader = NULL;
PlainShader = NULL; PlainShader = NULL;
PlainStencilShader = NULL; InvPlainShader = NULL;
RedToAlphaShader = NULL;
ColorOnlyShader = NULL; ColorOnlyShader = NULL;
GammaFixerShader = NULL; GammaFixerShader = NULL;
BurnShader = NULL; BurnShader = NULL;
@ -322,8 +323,8 @@ D3DFB::~D3DFB ()
// to D3D's defaults. // to D3D's defaults.
void D3DFB::SetInitialState() void D3DFB::SetInitialState()
{ {
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
AlphaBlendEnabled = FALSE; AlphaBlendEnabled = FALSE;
AlphaBlendOp = D3DBLENDOP_ADD;
AlphaSrcBlend = D3DBLEND(0); AlphaSrcBlend = D3DBLEND(0);
AlphaDestBlend = D3DBLEND(0); AlphaDestBlend = D3DBLEND(0);
@ -332,15 +333,45 @@ void D3DFB::SetInitialState()
Texture[0] = NULL; Texture[0] = NULL;
Texture[1] = NULL; Texture[1] = NULL;
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, SM14 ? D3DTADDRESS_BORDER : D3DTADDRESS_CLAMP);
D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE); D3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE);
SetGamma (Gamma); NeedGammaUpdate = true;
NeedPalUpdate = true;
OldRenderTarget = NULL; OldRenderTarget = NULL;
if (!Windowed && SM14)
{
// Fix for Radeon 9000, possibly other R200s: When the device is
// reset, it resets the gamma ramp, but the driver apparently keeps a
// cached copy of the ramp that it doesn't update, so when
// SetGammaRamp is called later to handle the NeedGammaUpdate flag,
// it doesn't do anything, because the gamma ramp is the same as the
// one passed in the last call, even though the visible gamma ramp
// actually has changed.
//
// So here we force the gamma ramp to something absolutely horrible and
// trust that we will be able to properly set the gamma later when
// NeedGammaUpdate is handled.
D3DGAMMARAMP ramp;
memset(&ramp, 0, sizeof(ramp));
D3DDevice->SetGammaRamp(0, 0, &ramp);
}
// Used by the inverse color shaders
float ones[4] = { 1, 1, 1, 1 };
D3DDevice->SetPixelShaderConstantF(6, ones, 1);
// D3DRS_ALPHATESTENABLE defaults to FALSE
// D3DRS_ALPHAREF defaults to 0
D3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
AlphaTestEnabled = FALSE;
CurBorderColor = 0;
} }
void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync) void D3DFB::FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync)
@ -396,15 +427,21 @@ bool D3DFB::CreateResources ()
{ {
return false; return false;
} }
if (FAILED(D3DDevice->CreatePixelShader (InvPalTexShader20Def, &InvPalTexShader)) &&
(SM14 = true, FAILED(D3DDevice->CreatePixelShader (InvPalTexShader14Def, &InvPalTexShader))))
{
return false;
}
if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) || if (FAILED(D3DDevice->CreatePixelShader (PlainShaderDef, &PlainShader)) ||
FAILED(D3DDevice->CreatePixelShader (PlainStencilDef, &PlainStencilShader)) || FAILED(D3DDevice->CreatePixelShader (InvPlainShaderDef, &InvPlainShader)) ||
FAILED(D3DDevice->CreatePixelShader (RedToAlphaDef, &RedToAlphaShader)) ||
FAILED(D3DDevice->CreatePixelShader (ColorOnlyDef, &ColorOnlyShader))) FAILED(D3DDevice->CreatePixelShader (ColorOnlyDef, &ColorOnlyShader)))
{ {
return false; return false;
} }
if (FAILED(D3DDevice->CreatePixelShader (GammaFixerDef, &GammaFixerShader))) if (FAILED(D3DDevice->CreatePixelShader (GammaFixerDef, &GammaFixerShader)))
{ {
Printf ("Windowed mode gamma will not work.\n"); // Printf ("Using Shader Model 1.4: Windowed mode gamma will not work.\n");
GammaFixerShader = NULL; GammaFixerShader = NULL;
} }
if (FAILED(D3DDevice->CreatePixelShader(PalTexBilinearDef, &PalTexBilinearShader))) if (FAILED(D3DDevice->CreatePixelShader(PalTexBilinearDef, &PalTexBilinearShader)))
@ -413,13 +450,10 @@ bool D3DFB::CreateResources ()
} }
if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader))) if (FAILED(D3DDevice->CreatePixelShader (BurnShaderDef, &BurnShader)))
{ {
Printf ("Burn screenwipe will not work in D3D mode.\n");
BurnShader = NULL; BurnShader = NULL;
} }
if (!CreateFBTexture() || if (!CreateFBTexture() ||
!CreatePaletteTexture() || !CreatePaletteTexture())
!CreateStencilPaletteTexture() ||
!CreateShadedPaletteTexture())
{ {
return false; return false;
} }
@ -439,8 +473,6 @@ void D3DFB::ReleaseResources ()
SAFE_RELEASE( ScreenshotSurface ); SAFE_RELEASE( ScreenshotSurface );
SAFE_RELEASE( ScreenshotTexture ); SAFE_RELEASE( ScreenshotTexture );
SAFE_RELEASE( PaletteTexture ); SAFE_RELEASE( PaletteTexture );
SAFE_RELEASE( StencilPaletteTexture );
SAFE_RELEASE( ShadedPaletteTexture );
if (PalTexBilinearShader != NULL) if (PalTexBilinearShader != NULL)
{ {
if (PalTexBilinearShader != PalTexShader) if (PalTexBilinearShader != PalTexShader)
@ -450,8 +482,10 @@ void D3DFB::ReleaseResources ()
PalTexBilinearShader = NULL; PalTexBilinearShader = NULL;
} }
SAFE_RELEASE( PalTexShader ); SAFE_RELEASE( PalTexShader );
SAFE_RELEASE( InvPalTexShader );
SAFE_RELEASE( PlainShader ); SAFE_RELEASE( PlainShader );
SAFE_RELEASE( PlainStencilShader ); SAFE_RELEASE( InvPlainShader );
SAFE_RELEASE( RedToAlphaShader );
SAFE_RELEASE( ColorOnlyShader ); SAFE_RELEASE( ColorOnlyShader );
SAFE_RELEASE( GammaFixerShader ); SAFE_RELEASE( GammaFixerShader );
SAFE_RELEASE( BurnShader ); SAFE_RELEASE( BurnShader );
@ -497,6 +531,7 @@ bool D3DFB::Reset ()
{ {
return false; return false;
} }
LOG("Device was reset\n");
if (!CreateFBTexture() || !CreateVertexes()) if (!CreateFBTexture() || !CreateVertexes())
{ {
return false; return false;
@ -578,48 +613,6 @@ bool D3DFB::CreatePaletteTexture ()
return true; return true;
} }
bool D3DFB::CreateStencilPaletteTexture()
{
// The stencil palette is a special palette where the first entry is zero alpha,
// and everything else is white with full alpha.
if (FAILED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &StencilPaletteTexture, NULL)))
{
return false;
}
D3DLOCKED_RECT lockrect;
if (SUCCEEDED(StencilPaletteTexture->LockRect(0, &lockrect, NULL, 0)))
{
DWORD *pix = (DWORD *)lockrect.pBits;
*pix = 0;
memset(pix + 1, 0xFF, 255*4);
StencilPaletteTexture->UnlockRect(0);
}
return true;
}
bool D3DFB::CreateShadedPaletteTexture()
{
// The shaded palette is similar to the stencil palette, except each entry's
// alpha is the same as its index.
if (FAILED(D3DDevice->CreateTexture(256, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ShadedPaletteTexture, NULL)))
{
return false;
}
D3DLOCKED_RECT lockrect;
if (SUCCEEDED(ShadedPaletteTexture->LockRect(0, &lockrect, NULL, 0)))
{
BYTE *pix = (BYTE *)lockrect.pBits;
for (int i = 0; i < 256; ++i)
{
pix[3] = i;
pix[2] = pix[1] = pix[0] = 255;
pix += 4;
}
ShadedPaletteTexture->UnlockRect(0);
}
return true;
}
bool D3DFB::CreateVertexes () bool D3DFB::CreateVertexes ()
{ {
VertexPos = -1; VertexPos = -1;
@ -829,12 +822,12 @@ void D3DFB::Update ()
{ {
ramp.blue[i] = ramp.green[i] = ramp.red[i] = WORD(65535.f * powf(i / 255.f, igamma)); ramp.blue[i] = ramp.green[i] = ramp.red[i] = WORD(65535.f * powf(i / 255.f, igamma));
} }
LOG("SetGammaRamp\n");
D3DDevice->SetGammaRamp(0, D3DSGR_CALIBRATE, &ramp); D3DDevice->SetGammaRamp(0, D3DSGR_CALIBRATE, &ramp);
} }
psgamma[2] = psgamma[1] = psgamma[0] = igamma; psgamma[2] = psgamma[1] = psgamma[0] = igamma;
psgamma[3] = 1; psgamma[3] = 1;
D3DDevice->SetPixelShaderConstantF(7, psgamma, 1); D3DDevice->SetPixelShaderConstantF(7, psgamma, 1);
NeedPalUpdate = true;
} }
if (NeedPalUpdate) if (NeedPalUpdate)
@ -862,7 +855,7 @@ void D3DFB::Update ()
} }
unclock (BlitCycles); unclock (BlitCycles);
LOG1 ("cycles = %d\n", BlitCycles); //LOG1 ("cycles = %d\n", BlitCycles);
Buffer = NULL; Buffer = NULL;
UpdatePending = false; UpdatePending = false;
@ -940,11 +933,12 @@ void D3DFB::Draw3DPart(bool copy3d)
} }
SetTexture (0, FBTexture); SetTexture (0, FBTexture);
SetPaletteTexture(PaletteTexture, 256); SetPaletteTexture(PaletteTexture, 256, BorderColor);
SetPixelShader(PalTexShader); SetPixelShader(PalTexShader);
D3DDevice->SetFVF (D3DFVF_FBVERTEX); D3DDevice->SetFVF (D3DFVF_FBVERTEX);
memset(Constant, 0, sizeof(Constant)); memset(Constant, 0, sizeof(Constant));
SetAlphaBlend(FALSE); SetAlphaBlend(D3DBLENDOP(0));
EnableAlphaTest(FALSE);
if (copy3d) if (copy3d)
{ {
FBVERTEX verts[4]; FBVERTEX verts[4];
@ -991,7 +985,8 @@ void D3DFB::DoWindowedGamma()
D3DDevice->SetFVF(D3DFVF_FBVERTEX); D3DDevice->SetFVF(D3DFVF_FBVERTEX);
SetTexture(0, TempRenderTexture); SetTexture(0, TempRenderTexture);
SetPixelShader((Windowed && GammaFixerShader != NULL) ? GammaFixerShader : PlainShader); SetPixelShader((Windowed && GammaFixerShader != NULL) ? GammaFixerShader : PlainShader);
SetAlphaBlend(FALSE); SetAlphaBlend(D3DBLENDOP(0));
EnableAlphaTest(FALSE);
D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
OldRenderTarget->Release(); OldRenderTarget->Release();
OldRenderTarget = NULL; OldRenderTarget = NULL;
@ -1001,12 +996,22 @@ void D3DFB::DoWindowedGamma()
void D3DFB::UploadPalette () void D3DFB::UploadPalette ()
{ {
D3DLOCKED_RECT lockrect; D3DLOCKED_RECT lockrect;
int i;
if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0))) if (SUCCEEDED(PaletteTexture->LockRect (0, &lockrect, NULL, 0)))
{ {
BYTE *pix = (BYTE *)lockrect.pBits; BYTE *pix = (BYTE *)lockrect.pBits;
for (i = 0; i < 256; ++i, pix += 4) int i, skipat;
// It is impossible to get the Radeon 9000 to do the proper palette
// lookup. It *will* skip at least one entry in the palette. So we
// let it and have it look at the texture border color for color 255.
// I assume that every other card based on a related graphics chipset
// is similarly affected, which basically means that all Shader Model
// 1.4 cards suffer from this problem, since they all use some variant
// of the ATI R200.
skipat = SM14 ? 256 - 8 : 256;
for (i = 0; i < skipat; ++i, pix += 4)
{ {
pix[0] = SourcePalette[i].b; pix[0] = SourcePalette[i].b;
pix[1] = SourcePalette[i].g; pix[1] = SourcePalette[i].g;
@ -1014,7 +1019,16 @@ void D3DFB::UploadPalette ()
pix[3] = (i == 0 ? 0 : 255); pix[3] = (i == 0 ? 0 : 255);
// To let masked textures work, the first palette entry's alpha is 0. // To let masked textures work, the first palette entry's alpha is 0.
} }
pix += 4;
for (; i < 255; ++i, pix += 4)
{
pix[0] = SourcePalette[i].b;
pix[1] = SourcePalette[i].g;
pix[2] = SourcePalette[i].r;
pix[3] = 255;
}
PaletteTexture->UnlockRect (0); PaletteTexture->UnlockRect (0);
BorderColor = D3DCOLOR_XRGB(SourcePalette[255].r, SourcePalette[255].g, SourcePalette[255].b);
} }
} }
@ -1296,18 +1310,17 @@ void D3DFB::DrawPackedTextures(int packnum)
BufferedQuad *quad = &QuadExtra[QuadBatchPos]; BufferedQuad *quad = &QuadExtra[QuadBatchPos];
FBVERTEX *vert = &VertexData[VertexPos]; FBVERTEX *vert = &VertexData[VertexPos];
quad->Group1 = 0;
if (pack->Format == D3DFMT_L8/* && !tex->IsGray*/) if (pack->Format == D3DFMT_L8/* && !tex->IsGray*/)
{ {
quad->Flags = BQF_WrapUV | BQF_GamePalette; quad->Flags = BQF_WrapUV | BQF_GamePalette | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex; quad->ShaderNum = BQS_PalTex;
} }
else else
{ {
quad->Flags = BQF_WrapUV; quad->Flags = BQF_WrapUV | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain; quad->ShaderNum = BQS_Plain;
} }
quad->SrcBlend = 0;
quad->DestBlend = 0;
quad->Palette = NULL; quad->Palette = NULL;
quad->Texture = pack; quad->Texture = pack;
@ -1956,6 +1969,9 @@ D3DPal::D3DPal(FRemapTable *remap, D3DFB *fb)
if (fb->SM14) if (fb->SM14)
{ {
count = 256; count = 256;
// If the palette isn't big enough, then we don't need to
// worry about setting the gamma ramp.
BorderColor = (remap->NumEntries >= 256 - 8) ? ~0 : 0;
} }
else else
{ {
@ -1965,6 +1981,7 @@ D3DPal::D3DPal(FRemapTable *remap, D3DFB *fb)
for (pow2count = 1; pow2count < remap->NumEntries; pow2count <<= 1) for (pow2count = 1; pow2count < remap->NumEntries; pow2count <<= 1)
{ } { }
count = pow2count; count = pow2count;
BorderColor = 0;
} }
RoundedPaletteSize = count; RoundedPaletteSize = count;
if (SUCCEEDED(fb->D3DDevice->CreateTexture(count, 1, 1, 0, if (SUCCEEDED(fb->D3DDevice->CreateTexture(count, 1, 1, 0,
@ -2013,6 +2030,7 @@ bool D3DPal::Update()
D3DLOCKED_RECT lrect; D3DLOCKED_RECT lrect;
D3DCOLOR *buff; D3DCOLOR *buff;
const PalEntry *pal; const PalEntry *pal;
int skipat, i;
assert(Tex != NULL); assert(Tex != NULL);
@ -2023,12 +2041,19 @@ bool D3DPal::Update()
buff = (D3DCOLOR *)lrect.pBits; buff = (D3DCOLOR *)lrect.pBits;
pal = Remap->Palette; pal = Remap->Palette;
// Should I allow the source palette to specify alpha values? // See explanation in UploadPalette() for skipat rationale.
buff[0] = D3DCOLOR_ARGB(0, pal[0].r, pal[0].g, pal[0].b); skipat = MIN(Remap->NumEntries, BorderColor != 0 ? 256 - 8 : 256);
for (int i = 1; i < Remap->NumEntries; ++i)
for (i = 0; i < skipat; ++i)
{ {
buff[i] = D3DCOLOR_XRGB(pal[i].r, pal[i].g, pal[i].b); buff[i] = D3DCOLOR_ARGB(pal[i].a, pal[i].r, pal[i].g, pal[i].b);
} }
for (++i; i < Remap->NumEntries; ++i)
{
buff[i] = D3DCOLOR_ARGB(pal[i-1].a, pal[i-1].r, pal[i-1].g, pal[i-1].b);
}
BorderColor = D3DCOLOR_ARGB(pal[i-1].a, pal[i-1].r, pal[i-1].g, pal[i-1].b);
Tex->UnlockRect(0); Tex->UnlockRect(0);
return true; return true;
} }
@ -2190,7 +2215,7 @@ void D3DFB::EndLineBatch()
if (VertexPos > 0) if (VertexPos > 0)
{ {
SetPixelShader(ColorOnlyShader); SetPixelShader(ColorOnlyShader);
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(FBVERTEX)); D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(FBVERTEX));
D3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, VertexPos / 2); D3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, VertexPos / 2);
} }
@ -2269,7 +2294,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32 color)
}; };
EndBatch(); // Draw out any batched operations. EndBatch(); // Draw out any batched operations.
SetPixelShader(ColorOnlyShader); SetPixelShader(ColorOnlyShader);
SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
D3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &pt, sizeof(FBVERTEX)); D3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &pt, sizeof(FBVERTEX));
} }
@ -2473,18 +2498,17 @@ void D3DFB::FlatFill(int left, int top, int right, int bottom, FTexture *src, bo
BufferedQuad *quad = &QuadExtra[QuadBatchPos]; BufferedQuad *quad = &QuadExtra[QuadBatchPos];
FBVERTEX *vert = &VertexData[VertexPos]; FBVERTEX *vert = &VertexData[VertexPos];
quad->Group1 = 0;
if (tex->GetTexFormat() == D3DFMT_L8 && !tex->IsGray) if (tex->GetTexFormat() == D3DFMT_L8 && !tex->IsGray)
{ {
quad->Flags = BQF_WrapUV | BQF_GamePalette; quad->Flags = BQF_WrapUV | BQF_GamePalette | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_PalTex; quad->ShaderNum = BQS_PalTex;
} }
else else
{ {
quad->Flags = BQF_WrapUV; quad->Flags = BQF_WrapUV | BQF_DisableAlphaTest;
quad->ShaderNum = BQS_Plain; quad->ShaderNum = BQS_Plain;
} }
quad->SrcBlend = 0;
quad->DestBlend = 0;
quad->Palette = NULL; quad->Palette = NULL;
quad->Texture = tex->Box->Owner; quad->Texture = tex->Box->Owner;
@ -2556,15 +2580,11 @@ void D3DFB::AddColorOnlyQuad(int left, int top, int width, int height, D3DCOLOR
float x = float(left) - 0.5f; float x = float(left) - 0.5f;
float y = float(top) - 0.5f + (GatheringWipeScreen ? 0 : LBOffset); float y = float(top) - 0.5f + (GatheringWipeScreen ? 0 : LBOffset);
quad->Flags = 0; quad->Group1 = 0;
quad->ShaderNum = BQS_ColorOnly; quad->ShaderNum = BQS_ColorOnly;
if ((color & 0xFF000000) == 0xFF000000) if ((color & 0xFF000000) != 0xFF000000)
{
quad->SrcBlend = 0;
quad->DestBlend = 0;
}
else
{ {
quad->BlendOp = D3DBLENDOP_ADD;
quad->SrcBlend = D3DBLEND_SRCALPHA; quad->SrcBlend = D3DBLEND_SRCALPHA;
quad->DestBlend = D3DBLEND_INVSRCALPHA; quad->DestBlend = D3DBLEND_INVSRCALPHA;
} }
@ -2716,48 +2736,43 @@ void D3DFB::EndQuadBatch()
// Set the palette (if one) // Set the palette (if one)
if ((quad->Flags & BQF_Paletted) == BQF_GamePalette) if ((quad->Flags & BQF_Paletted) == BQF_GamePalette)
{ {
SetPaletteTexture(PaletteTexture, 256); SetPaletteTexture(PaletteTexture, 256, BorderColor);
} }
else if ((quad->Flags & BQF_Paletted) == BQF_CustomPalette) else if ((quad->Flags & BQF_Paletted) == BQF_CustomPalette)
{ {
SetPaletteTexture(quad->Palette->Tex, quad->Palette->RoundedPaletteSize); SetPaletteTexture(quad->Palette->Tex, quad->Palette->RoundedPaletteSize, quad->Palette->BorderColor);
}
else if ((quad->Flags & BQF_Paletted) == BQF_ShadedPalette)
{
SetPaletteTexture(ShadedPaletteTexture, 256);
}
else if ((quad->Flags & BQF_Paletted) == BQF_StencilPalette)
{
SetPaletteTexture(StencilPaletteTexture, 256);
} }
// Set paletted bilinear filtering (IF IT WORKED RIGHT!) // Set paletted bilinear filtering (IF IT WORKED RIGHT!)
if (quad->Flags & (BQF_Paletted | BQF_Bilinear)) if ((quad->Flags & (BQF_Paletted | BQF_Bilinear)) == (BQF_Paletted | BQF_Bilinear))
{ {
SetPalTexBilinearConstants(quad->Texture); SetPalTexBilinearConstants(quad->Texture);
} }
// Set the alpha blending // Set the alpha blending
if (quad->SrcBlend != 0) SetAlphaBlend(D3DBLENDOP(quad->BlendOp), D3DBLEND(quad->SrcBlend), D3DBLEND(quad->DestBlend));
{
SetAlphaBlend(TRUE, D3DBLEND(quad->SrcBlend), D3DBLEND(quad->DestBlend)); // Set the alpha test
} EnableAlphaTest(!(quad->Flags & BQF_DisableAlphaTest));
else
{
SetAlphaBlend(FALSE);
}
// Set the pixel shader // Set the pixel shader
if (quad->ShaderNum == BQS_PalTex) if (quad->ShaderNum == BQS_PalTex)
{ {
SetPixelShader(!(quad->Flags & BQF_Bilinear) ? PalTexShader : PalTexBilinearShader); if (!(quad->Flags & BQF_Bilinear))
{
SetPixelShader((quad->Flags & BQF_InvertSource) ? InvPalTexShader : PalTexShader);
}
else
{
SetPixelShader(PalTexBilinearShader);
}
} }
else if (quad->ShaderNum == BQS_Plain) else if (quad->ShaderNum == BQS_Plain)
{ {
SetPixelShader(PlainShader); SetPixelShader((quad->Flags & BQF_InvertSource) ? InvPlainShader : PlainShader);
} }
else if (quad->ShaderNum == BQS_PlainStencil) else if (quad->ShaderNum == BQS_RedToAlpha)
{ {
SetPixelShader(PlainStencilShader); SetPixelShader(RedToAlphaShader);
} }
else if (quad->ShaderNum == BQS_ColorOnly) else if (quad->ShaderNum == BQS_ColorOnly)
{ {
@ -2825,90 +2840,80 @@ void D3DFB::EndBatch()
bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedQuad &quad) bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedQuad &quad)
{ {
D3DFORMAT fmt = tex->GetTexFormat(); D3DFORMAT fmt = tex->GetTexFormat();
ERenderStyle style = parms.style; FRenderStyle style = parms.style;
D3DBLEND fglevel, bglevel;
float alpha; float alpha;
bool stencilling; bool stencilling;
alpha = clamp<fixed_t> (parms.alpha, 0, FRACUNIT) / 65536.f; if (style.Flags & STYLEF_TransSoulsAlpha)
if (style == STYLE_OptFuzzy)
{ {
style = STYLE_Translucent;
}
else if (style == STYLE_SoulTrans)
{
style = STYLE_Translucent;
alpha = transsouls; alpha = transsouls;
} }
else if (style.Flags & STYLEF_Alpha1)
// FIXME: STYLE_Fuzzy is not written
if (style == STYLE_Fuzzy)
{ {
style = STYLE_Translucent; alpha = 1;
alpha = transsouls; }
else
{
alpha = clamp<fixed_t> (parms.alpha, 0, FRACUNIT) / 65536.f;
}
// FIXME: Fuzz effect is not written
if (style.BlendOp == STYLEOP_FuzzOrAdd || style.BlendOp == STYLEOP_Fuzz)
{
style.BlendOp = STYLEOP_Add;
}
else if (style.BlendOp == STYLEOP_FuzzOrSub)
{
style.BlendOp = STYLEOP_Sub;
}
else if (style.BlendOp == STYLEOP_FuzzOrRevSub)
{
style.BlendOp = STYLEOP_RevSub;
} }
stencilling = false; stencilling = false;
quad.Palette = NULL; quad.Palette = NULL;
switch (style) switch (style.BlendOp)
{ {
// Special modes
case STYLE_Shaded:
if (alpha > 0)
{
color0 = 0;
color1 = parms.fillcolor | (D3DCOLOR(alpha * 255) << 24);
quad.Flags = BQF_ShadedPalette;
quad.SrcBlend = D3DBLEND_SRCALPHA;
quad.DestBlend = D3DBLEND_INVSRCALPHA;
quad.ShaderNum = BQS_PalTex;
return true;
}
return false;
// Standard modes
case STYLE_Stencil:
stencilling = true;
case STYLE_Normal:
fglevel = D3DBLEND_SRCALPHA;
bglevel = D3DBLEND_INVSRCALPHA;
alpha = 1;
break;
case STYLE_TranslucentStencil:
stencilling = true;
case STYLE_Translucent:
fglevel = D3DBLEND_SRCALPHA;
bglevel = D3DBLEND_INVSRCALPHA;
if (alpha == 0)
{
return false;
}
if (alpha == 1 && style == STYLE_Translucent)
{
style = STYLE_Normal;
}
break;
case STYLE_Add:
fglevel = D3DBLEND_SRCALPHA;
bglevel = D3DBLEND_ONE;
break;
default: default:
return false; case STYLEOP_Add: quad.BlendOp = D3DBLENDOP_ADD; break;
case STYLEOP_Sub: quad.BlendOp = D3DBLENDOP_SUBTRACT; break;
case STYLEOP_RevSub: quad.BlendOp = D3DBLENDOP_REVSUBTRACT; break;
case STYLEOP_None: return false;
}
quad.SrcBlend = GetStyleAlpha(style.SrcAlpha);
quad.DestBlend = GetStyleAlpha(style.DestAlpha);
if (style.Flags & STYLEF_InvertOverlay)
{
// Only the overlay color is inverted, not the overlay alpha.
parms.colorOverlay = D3DCOLOR_ARGB(APART(parms.colorOverlay),
255 - RPART(parms.colorOverlay), 255 - GPART(parms.colorOverlay),
255 - BPART(parms.colorOverlay));
} }
// Masking can only be turned off for STYLE_Normal, because it requires SetColorOverlay(parms.colorOverlay, alpha, color0, color1);
// turning off the alpha blend.
if (!parms.masked && style == STYLE_Normal) if (style.Flags & STYLEF_ColorIsFixed)
{ {
quad.SrcBlend = 0; if (style.Flags & STYLEF_InvertSource)
quad.DestBlend = 0; { // Since the source color is a constant, we can invert it now
SetColorOverlay(parms.colorOverlay, 1, color0, color1); // without spending time doing it in the shader.
if (fmt == D3DFMT_L8 && !tex->IsGray) parms.fillcolor = D3DCOLOR_XRGB(255 - RPART(parms.fillcolor),
255 - GPART(parms.fillcolor), 255 - BPART(parms.fillcolor));
}
// Set up the color mod to replace the color from the image data.
color0 = (color0 & D3DCOLOR_RGBA(0,0,0,255)) | (parms.fillcolor & D3DCOLOR_RGBA(255,255,255,0));
color1 &= D3DCOLOR_RGBA(0,0,0,255);
if (style.Flags & STYLEF_RedIsAlpha)
{
// Note that if the source texture is paletted, the palette is ignored.
quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == D3DFMT_L8)
{ {
quad.Flags = BQF_GamePalette; quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex; quad.ShaderNum = BQS_PalTex;
@ -2921,56 +2926,72 @@ bool D3DFB::SetStyle(D3DTex *tex, DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &
} }
else else
{ {
quad.SrcBlend = fglevel; if (style.Flags & STYLEF_RedIsAlpha)
quad.DestBlend = bglevel;
if (!stencilling)
{ {
if (fmt == D3DFMT_L8) quad.Flags = 0;
quad.ShaderNum = BQS_RedToAlpha;
}
else if (fmt == D3DFMT_L8)
{
if (parms.remap != NULL)
{ {
if (parms.remap != NULL) quad.Flags = BQF_CustomPalette;
{ quad.Palette = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
quad.Flags = BQF_CustomPalette; quad.ShaderNum = BQS_PalTex;
quad.Palette = reinterpret_cast<D3DPal *>(parms.remap->GetNative());
quad.ShaderNum = BQS_PalTex;
}
else if (tex->IsGray)
{
quad.Flags = 0;
quad.ShaderNum = BQS_Plain;
}
else
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
} }
else else if (tex->IsGray)
{ {
quad.Flags = 0; quad.Flags = 0;
quad.ShaderNum = BQS_Plain; quad.ShaderNum = BQS_Plain;
} }
SetColorOverlay(parms.colorOverlay, alpha, color0, color1); else
{
quad.Flags = BQF_GamePalette;
quad.ShaderNum = BQS_PalTex;
}
} }
else else
{ {
color0 = 0; quad.Flags = 0;
color1 = parms.fillcolor | (D3DCOLOR(alpha * 255) << 24); quad.ShaderNum = BQS_Plain;
if (fmt == D3DFMT_L8) }
{ if (style.Flags & STYLEF_InvertSource)
quad.Flags = BQF_StencilPalette; {
quad.ShaderNum = BQS_PalTex; quad.Flags |= BQF_InvertSource;
}
else
{
quad.Flags = 0;
quad.ShaderNum = BQS_PlainStencil;
}
} }
} }
// For unmasked images, force the alpha from the image data to be ignored.
if (!parms.masked)
{
color0 = (color0 & D3DCOLOR_RGBA(255, 255, 255, 0)) | D3DCOLOR_COLORVALUE(0, 0, 0, alpha);
color1 &= D3DCOLOR_RGBA(255, 255, 255, 0);
// If our alpha is one and we are doing normal adding, then we can turn the blend off completely.
if (quad.BlendOp == D3DBLENDOP_ADD &&
((alpha == 1 && quad.SrcBlend == D3DBLEND_SRCALPHA) || quad.SrcBlend == D3DBLEND_ONE) &&
((alpha == 1 && quad.DestBlend == D3DBLEND_INVSRCALPHA) || quad.DestBlend == D3DBLEND_ZERO))
{
quad.BlendOp = D3DBLENDOP(0);
}
quad.Flags |= BQF_DisableAlphaTest;
}
return true; return true;
} }
D3DBLEND D3DFB::GetStyleAlpha(int type)
{
switch (type)
{
case STYLEALPHA_Zero: return D3DBLEND_ZERO;
case STYLEALPHA_One: return D3DBLEND_ONE;
case STYLEALPHA_Src: return D3DBLEND_SRCALPHA;
case STYLEALPHA_InvSrc: return D3DBLEND_INVSRCALPHA;
default: return D3DBLEND_ZERO;
}
}
void D3DFB::SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1) void D3DFB::SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1)
{ {
if (APART(color) != 0) if (APART(color) != 0)
@ -2991,9 +3012,18 @@ void D3DFB::SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR
} }
} }
void D3DFB::SetAlphaBlend(BOOL enabled, D3DBLEND srcblend, D3DBLEND destblend) void D3DFB::EnableAlphaTest(BOOL enabled)
{ {
if (!enabled) if (enabled != AlphaTestEnabled)
{
AlphaTestEnabled = enabled;
D3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, enabled);
}
}
void D3DFB::SetAlphaBlend(D3DBLENDOP op, D3DBLEND srcblend, D3DBLEND destblend)
{
if (op == 0)
{ // Disable alpha blend { // Disable alpha blend
if (AlphaBlendEnabled) if (AlphaBlendEnabled)
{ {
@ -3011,6 +3041,11 @@ void D3DFB::SetAlphaBlend(BOOL enabled, D3DBLEND srcblend, D3DBLEND destblend)
AlphaBlendEnabled = TRUE; AlphaBlendEnabled = TRUE;
D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
} }
if (AlphaBlendOp != op)
{
AlphaBlendOp = op;
D3DDevice->SetRenderState(D3DRS_BLENDOP, op);
}
if (AlphaSrcBlend != srcblend) if (AlphaSrcBlend != srcblend)
{ {
AlphaSrcBlend = srcblend; AlphaSrcBlend = srcblend;
@ -3059,12 +3094,17 @@ void D3DFB::SetTexture(int tnum, IDirect3DTexture9 *texture)
CVAR(Float, pal, 0.5f, 0) CVAR(Float, pal, 0.5f, 0)
CVAR(Float, pc, 255.f, 0) CVAR(Float, pc, 255.f, 0)
void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count) void D3DFB::SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR border_color)
{ {
if (count == 256 || SM14) if (SM14)
{ {
// Shader Model 1.4 only uses 256-color palettes. // Shader Model 1.4 only uses 256-color palettes.
SetConstant(2, pc / 256.f, pal / 256.f, 0, 0); SetConstant(2, 1.f, 0.5f / 256.f, 0, 0);
if (border_color != 0 && CurBorderColor != border_color)
{
CurBorderColor = border_color;
D3DDevice->SetSamplerState(1, D3DSAMP_BORDERCOLOR, border_color);
}
} }
else else
{ {

View file

@ -103,6 +103,118 @@ const DWORD PalTexShader20Def[] =
0x800f0800, 0x80e40000, 0x0000ffff 0x800f0800, 0x80e40000, 0x0000ffff
}; };
// An inverted paletted texture shader --------------------------------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
sampler1D Palette : register(s1);
float4 PaletteMod : register(c2);
float4 White : register(c6); // Preloaded with (1,1,1,0)
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float index = tex2D (Image, texCoord).x;
index = index * PaletteMod.x + PaletteMod.y;
float4 rgb = tex1D (Palette, index);
rgb.xyz = White.xyz - rgb.xyz;
return Flash + rgb * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc paltex.ps /Tps_1_4 /LD /VnInvPalTexShader14Def /Fhinvpaltex.h
//
//
// Parameters:
//
// sampler2D Image;
// sampler1D Palette;
// float4 PaletteMod;
// float4 White;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// PaletteMod c2 1
// White c6 1
// Image s0 1
// Palette s1 1
//
ps_1_4
texld r0, t0
mad r0.xy, r0.x, c2.x, c2.y
phase
texld r1, r0
add r1.xyz, -r1, c6
mad r0, r1, v1, v0
// approximately 5 instruction slots used (2 texture, 3 arithmetic)
#endif
const DWORD InvPalTexShader14Def[] =
{
0xffff0104, 0x003ffffe, 0x42415443, 0x0000001c, 0x000000c5, 0xffff0104,
0x00000004, 0x0000001c, 0x00000100, 0x000000be, 0x0000006c, 0x00000003,
0x00000001, 0x00000074, 0x00000000, 0x00000084, 0x00010003, 0x00000001,
0x0000008c, 0x00000000, 0x0000009c, 0x00020002, 0x00020001, 0x000000a8,
0x00000000, 0x000000b8, 0x00060002, 0x00020001, 0x000000a8, 0x00000000,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001, 0x00000001,
0x00000000, 0x74696857, 0x73700065, 0x345f315f, 0x63694d00, 0x6f736f72,
0x28207466, 0x44202952, 0x39584433, 0x61685320, 0x20726564, 0x706d6f43,
0x72656c69, 0x312e3920, 0x37372e35, 0x30302e39, 0xab003030, 0x00000042,
0x800f0000, 0xb0e40000, 0x00000004, 0x80030000, 0x80000000, 0xa0000002,
0xa0550002, 0x0000fffd, 0x00000042, 0x800f0001, 0x80e40000, 0x00000002,
0x80070001, 0x81e40001, 0xa0e40006, 0x00000004, 0x800f0000, 0x80e40001,
0x90e40001, 0x90e40000, 0x0000ffff
};
#if SHADER_ASSEMBLY_CODE
ps_2_0
dcl t0.xy
dcl v0
dcl v1
dcl_2d s0
dcl_2d s1
texld r0, t0, s0
mad r0.xy, r0.x, c2.x, c2.y
texld r0, r0, s1
add r0.xyz, -r0, c6
mov r1, v1
mad r0, r0, r1, v0
mov oC0, r0
// approximately 7 instruction slots used (2 texture, 5 arithmetic)
#endif
const DWORD InvPalTexShader20Def[] =
{
0xffff0200, 0x003ffffe, 0x42415443, 0x0000001c, 0x000000c5, 0xffff0200,
0x00000004, 0x0000001c, 0x20000100, 0x000000be, 0x0000006c, 0x00000003,
0x00020001, 0x00000074, 0x00000000, 0x00000084, 0x00010003, 0x00060001,
0x0000008c, 0x00000000, 0x0000009c, 0x00020002, 0x000a0001, 0x000000a8,
0x00000000, 0x000000b8, 0x00060002, 0x001a0001, 0x000000a8, 0x00000000,
0x67616d49, 0xabab0065, 0x000c0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x00657474, 0x000b0004, 0x00010001, 0x00000001, 0x00000000,
0x656c6150, 0x4d657474, 0xab00646f, 0x00030001, 0x00040001, 0x00000001,
0x00000000, 0x74696857, 0x73700065, 0x305f325f, 0x63694d00, 0x6f736f72,
0x28207466, 0x48202952, 0x204c534c, 0x64616853, 0x43207265, 0x69706d6f,
0x2072656c, 0x39312e39, 0x3934392e, 0x3131322e, 0xabab0031, 0x0200001f,
0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f,
0x80000000, 0x900f0001, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f,
0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,
0x04000004, 0x80030000, 0x80000000, 0xa0000002, 0xa0550002, 0x03000042,
0x800f0000, 0x80e40000, 0xa0e40801, 0x03000002, 0x80070000, 0x81e40000,
0xa0e40006, 0x02000001, 0x800f0001, 0x90e40001, 0x04000004, 0x800f0000,
0x80e40000, 0x80e40001, 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000,
0x0000ffff
};
// A paletted texture shader that does bilinear filtering ------------------- // A paletted texture shader that does bilinear filtering -------------------
#if HLSL_SOURCE_CODE #if HLSL_SOURCE_CODE
@ -293,22 +405,77 @@ const DWORD PlainShaderDef[] =
0x90e40000, 0x0000ffff 0x90e40000, 0x0000ffff
}; };
// A shader that uses vertex color and texture alpha ------------------------ // A shader that inverts the source's colors --------------------------------
#if HLSL_SOURCE_CODE #if HLSL_SOURCE_CODE
sampler2D Image : register(s0); sampler2D Image : register(s0);
float4 White : register(c6); // Preloaded with (1,1,1,0)
float4 main (float2 texCoord : TEXCOORD0, float4 StencilColor : COLOR1) : COLOR float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{ {
float4 color = tex2D (Image, texCoord); float4 rgb = tex2D (Image, texCoord);
color.rgb = StencilColor.rgb; rgb.xyz = White.xyz - rgb.xyz;
return color; return Flash + rgb * InvFlash;
} }
#elif SHADER_ASSEMBLY_CODE #elif SHADER_ASSEMBLY_CODE
// //
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000 // Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
// //
// fxc plainstencil.ps /Tps_1_1 /LD /VnPlainStencilDef /Fhplainstencil.h // fxc plain.ps /Tps_1_1 /LD /VnInvPlainShaderDef /Fhinvplain.h
//
//
// Parameters:
//
// sampler2D Image;
// float4 White;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// White c6 1
// Image s0 1
//
ps_1_1
tex t0
add t0.xyz, -t0, c6
mad r0, t0, v1, v0
// approximately 3 instruction slots used (1 texture, 2 arithmetic)
#endif
const DWORD InvPlainShaderDef[] =
{
0xffff0101, 0x002dfffe, 0x42415443, 0x0000001c, 0x0000007b, 0xffff0101,
0x00000002, 0x0000001c, 0x00000100, 0x00000074, 0x00000044, 0x00000003,
0x00000001, 0x0000004c, 0x00000000, 0x0000005c, 0x00060002, 0x00020001,
0x00000064, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00010001,
0x00000001, 0x00000000, 0x74696857, 0xabab0065, 0x00030001, 0x00040001,
0x00000001, 0x00000000, 0x315f7370, 0x4d00315f, 0x6f726369, 0x74666f73,
0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x6c69706d,
0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x00000042,
0xb00f0000, 0x00000002, 0xb0070000, 0xb1e40000, 0xa0e40006, 0x00000004,
0x800f0000, 0xb0e40000, 0x90e40001, 0x90e40000, 0x0000ffff
};
// A shader that copies the red component to the alpha component ------------
#if HLSL_SOURCE_CODE
sampler2D Image : register(s0);
float4 main (float2 texCoord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR
{
float4 color = tex2D (Image, texCoord);
color.a = color.r;
return Flash + color * InvFlash;
}
#elif SHADER_ASSEMBLY_CODE
//
// Generated by Microsoft (R) D3DX9 Shader Compiler 9.15.779.0000
//
// fxc redtoalpha.ps /Tps_1_4 /LD /VnRedToAlphaDef /Fhredtoalpha.h
// //
// //
// Parameters: // Parameters:
@ -323,24 +490,26 @@ float4 main (float2 texCoord : TEXCOORD0, float4 StencilColor : COLOR1) : COLOR
// Image s0 1 // Image s0 1
// //
ps_1_1 ps_1_4
tex t0 texld r0, t0
mov r0.xyz, v1 mad r1.xyz, r0, v1, v0
+ mov r0.w, t0.w + mad r1.w, r0.x, v1.w, v0.w
mov r0, r1
// approximately 2 instruction slots used (1 texture, 1 arithmetic) // approximately 3 instruction slots used (1 texture, 2 arithmetic)
#endif #endif
const DWORD PlainStencilDef[] = const DWORD RedToAlphaDef[] =
{ {
0xffff0101, 0x0022fffe, 0x42415443, 0x0000001c, 0x0000004f, 0xffff0101, 0xffff0104, 0x0022fffe, 0x42415443, 0x0000001c, 0x0000004f, 0xffff0104,
0x00000001, 0x0000001c, 0x00000100, 0x00000048, 0x00000030, 0x00000003, 0x00000001, 0x0000001c, 0x00000100, 0x00000048, 0x00000030, 0x00000003,
0x00000001, 0x00000038, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004, 0x00000001, 0x00000038, 0x00000000, 0x67616d49, 0xabab0065, 0x000c0004,
0x00010001, 0x00000001, 0x00000000, 0x315f7370, 0x4d00315f, 0x6f726369, 0x00010001, 0x00000001, 0x00000000, 0x315f7370, 0x4d00345f, 0x6f726369,
0x74666f73, 0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072, 0x74666f73, 0x29522820, 0x44334420, 0x53203958, 0x65646168, 0x6f432072,
0x6c69706d, 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00, 0x6c69706d, 0x39207265, 0x2e35312e, 0x2e393737, 0x30303030, 0xababab00,
0x00000042, 0xb00f0000, 0x00000001, 0x80070000, 0x90e40001, 0x40000001, 0x00000042, 0x800f0000, 0xb0e40000, 0x00000004, 0x80070001, 0x80e40000,
0x80080000, 0xb0ff0000, 0x0000ffff 0x90e40001, 0x90e40000, 0x40000004, 0x80080001, 0x80000000, 0x90ff0001,
0x90ff0000, 0x00000001, 0x800f0000, 0x80e40001, 0x0000ffff
}; };
// A shader that just returns the first color component from the vertex ----- // A shader that just returns the first color component from the vertex -----

View file

@ -303,6 +303,7 @@ bool D3DFB::WipeDo(int ticks)
} }
In2D = 3; In2D = 3;
EnableAlphaTest(FALSE);
bool done = ScreenWipe->Run(ticks, this); bool done = ScreenWipe->Run(ticks, this);
DrawLetterbox(); DrawLetterbox();
return done; return done;
@ -392,7 +393,7 @@ bool D3DFB::Wiper_Crossfade::Run(int ticks, D3DFB *fb)
fb->CalcFullscreenCoords(verts, false, D3DCOLOR_COLORVALUE(0,0,0,Clock / 32.f), D3DCOLOR_RGBA(255,255,255,0)); fb->CalcFullscreenCoords(verts, false, D3DCOLOR_COLORVALUE(0,0,0,Clock / 32.f), D3DCOLOR_RGBA(255,255,255,0));
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
fb->SetTexture(0, fb->FinalWipeScreen); fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
fb->SetPixelShader(fb->PlainShader); fb->SetPixelShader(fb->PlainShader);
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
@ -450,7 +451,7 @@ bool D3DFB::Wiper_Melt::Run(int ticks, D3DFB *fb)
fb->CalcFullscreenCoords(verts, false, 0, 0xFFFFFFFF); fb->CalcFullscreenCoords(verts, false, 0, 0xFFFFFFFF);
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
fb->SetTexture(0, fb->FinalWipeScreen); fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetAlphaBlend(FALSE); fb->SetAlphaBlend(D3DBLENDOP(0));
fb->SetPixelShader(fb->PlainShader); fb->SetPixelShader(fb->PlainShader);
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX)); fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(FBVERTEX));
@ -599,11 +600,21 @@ bool D3DFB::Wiper_Burn::Run(int ticks, D3DFB *fb)
fb->D3DDevice->SetFVF(D3DFVF_BURNVERTEX); fb->D3DDevice->SetFVF(D3DFVF_BURNVERTEX);
fb->SetTexture(0, fb->FinalWipeScreen); fb->SetTexture(0, fb->FinalWipeScreen);
fb->SetTexture(1, BurnTexture); fb->SetTexture(1, BurnTexture);
fb->SetAlphaBlend(TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); fb->SetAlphaBlend(D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
fb->SetPixelShader(fb->BurnShader); fb->SetPixelShader(fb->BurnShader);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
if (fb->SM14)
{
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}
fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX)); fb->D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(BURNVERTEX));
fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT); fb->D3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
if (fb->SM14)
{
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
fb->D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
}
fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX); fb->D3DDevice->SetFVF(D3DFVF_FBVERTEX);
// The fire may not always stabilize, so the wipe is forced to end // The fire may not always stabilize, so the wipe is forced to end

View file

@ -277,7 +277,8 @@ private:
struct struct
{ {
BYTE Flags; BYTE Flags;
BYTE ShaderNum; BYTE ShaderNum:4;
BYTE BlendOp:4;
BYTE SrcBlend, DestBlend; BYTE SrcBlend, DestBlend;
}; };
DWORD Group1; DWORD Group1;
@ -292,8 +293,6 @@ private:
bool CreateFBTexture(); bool CreateFBTexture();
bool CreatePaletteTexture(); bool CreatePaletteTexture();
bool CreateGrayPaletteTexture(); bool CreateGrayPaletteTexture();
bool CreateStencilPaletteTexture();
bool CreateShadedPaletteTexture();
bool CreateVertexes(); bool CreateVertexes();
void UploadPalette(); void UploadPalette();
void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync); void FillPresentParameters (D3DPRESENT_PARAMETERS *pp, bool fullscreen, bool vsync);
@ -308,6 +307,7 @@ private:
void DrawLetterbox(); void DrawLetterbox();
void Draw3DPart(bool copy3d); void Draw3DPart(bool copy3d);
bool SetStyle(D3DTex *tex, DCanvas::DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedQuad &quad); bool SetStyle(D3DTex *tex, DCanvas::DrawParms &parms, D3DCOLOR &color0, D3DCOLOR &color1, BufferedQuad &quad);
static D3DBLEND GetStyleAlpha(int type);
static void SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1); static void SetColorOverlay(DWORD color, float alpha, D3DCOLOR &color0, D3DCOLOR &color1);
void DoWindowedGamma(); void DoWindowedGamma();
void AddColorOnlyQuad(int left, int top, int width, int height, D3DCOLOR color); void AddColorOnlyQuad(int left, int top, int width, int height, D3DCOLOR color);
@ -319,21 +319,26 @@ private:
void EndBatch(); void EndBatch();
// State // State
void SetAlphaBlend(BOOL enabled, D3DBLEND srcblend=D3DBLEND(0), D3DBLEND destblend=D3DBLEND(0)); void EnableAlphaTest(BOOL enabled);
void SetAlphaBlend(D3DBLENDOP op, D3DBLEND srcblend=D3DBLEND(0), D3DBLEND destblend=D3DBLEND(0));
void SetConstant(int cnum, float r, float g, float b, float a); void SetConstant(int cnum, float r, float g, float b, float a);
void SetPixelShader(IDirect3DPixelShader9 *shader); void SetPixelShader(IDirect3DPixelShader9 *shader);
void SetTexture(int tnum, IDirect3DTexture9 *texture); void SetTexture(int tnum, IDirect3DTexture9 *texture);
void SetPaletteTexture(IDirect3DTexture9 *texture, int count); void SetPaletteTexture(IDirect3DTexture9 *texture, int count, D3DCOLOR border_color);
void SetPalTexBilinearConstants(PackingTexture *texture); void SetPalTexBilinearConstants(PackingTexture *texture);
BOOL AlphaTestEnabled;
BOOL AlphaBlendEnabled; BOOL AlphaBlendEnabled;
D3DBLENDOP AlphaBlendOp;
D3DBLEND AlphaSrcBlend; D3DBLEND AlphaSrcBlend;
D3DBLEND AlphaDestBlend; D3DBLEND AlphaDestBlend;
float Constant[3][4]; float Constant[3][4];
D3DCOLOR CurBorderColor;
IDirect3DPixelShader9 *CurPixelShader; IDirect3DPixelShader9 *CurPixelShader;
IDirect3DTexture9 *Texture[2]; IDirect3DTexture9 *Texture[2];
PalEntry SourcePalette[256]; PalEntry SourcePalette[256];
D3DCOLOR BorderColor;
D3DCOLOR FlashColor0, FlashColor1; D3DCOLOR FlashColor0, FlashColor1;
PalEntry FlashColor; PalEntry FlashColor;
int FlashAmount; int FlashAmount;
@ -361,8 +366,6 @@ private:
IDirect3DTexture9 *FBTexture; IDirect3DTexture9 *FBTexture;
IDirect3DTexture9 *TempRenderTexture; IDirect3DTexture9 *TempRenderTexture;
IDirect3DTexture9 *PaletteTexture; IDirect3DTexture9 *PaletteTexture;
IDirect3DTexture9 *StencilPaletteTexture;
IDirect3DTexture9 *ShadedPaletteTexture;
IDirect3DTexture9 *ScreenshotTexture; IDirect3DTexture9 *ScreenshotTexture;
IDirect3DSurface9 *ScreenshotSurface; IDirect3DSurface9 *ScreenshotSurface;
@ -376,9 +379,9 @@ private:
int QuadBatchPos; int QuadBatchPos;
enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType; enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType;
IDirect3DPixelShader9 *PalTexShader, *PalTexBilinearShader; IDirect3DPixelShader9 *PalTexShader, *PalTexBilinearShader, *InvPalTexShader;
IDirect3DPixelShader9 *PlainShader; IDirect3DPixelShader9 *PlainShader, *InvPlainShader;
IDirect3DPixelShader9 *PlainStencilShader; IDirect3DPixelShader9 *RedToAlphaShader;
IDirect3DPixelShader9 *ColorOnlyShader; IDirect3DPixelShader9 *ColorOnlyShader;
IDirect3DPixelShader9 *GammaFixerShader; IDirect3DPixelShader9 *GammaFixerShader;
IDirect3DPixelShader9 *BurnShader; IDirect3DPixelShader9 *BurnShader;
@ -412,6 +415,15 @@ private:
#define LOG4(x,y,z,a,b) do { if (dbg) { fprintf (dbg, x, y, z, a, b); fflush (dbg); } } while(0) #define LOG4(x,y,z,a,b) do { if (dbg) { fprintf (dbg, x, y, z, a, b); fflush (dbg); } } while(0)
#define LOG5(x,y,z,a,b,c) do { if (dbg) { fprintf (dbg, x, y, z, a, b, c); fflush (dbg); } } while(0) #define LOG5(x,y,z,a,b,c) do { if (dbg) { fprintf (dbg, x, y, z, a, b, c); fflush (dbg); } } while(0)
FILE *dbg; FILE *dbg;
#elif _DEBUG
#define STARTLOG
#define STOPLOG
#define LOG(x) { OutputDebugString(x); }
#define LOG1(x,y) { char poo[1024]; sprintf(poo, x, y); OutputDebugString(poo); }
#define LOG2(x,y,z) { char poo[1024]; sprintf(poo, x, y, z); OutputDebugString(poo); }
#define LOG3(x,y,z,zz) { char poo[1024]; sprintf(poo, x, y, z, zz); OutputDebugString(poo); }
#define LOG4(x,y,z,a,b) { char poo[1024]; sprintf(poo, x, y, z, a, b); OutputDebugString(poo); }
#define LOG5(x,y,z,a,b,c) { char poo[1024]; sprintf(poo, x, y, z, a, b, c); OutputDebugString(poo); }
#else #else
#define STARTLOG #define STARTLOG
#define STOPLOG #define STOPLOG

View file

@ -219,6 +219,7 @@ FString &FString::operator = (const char *copyStr)
{ {
if (copyStr == NULL || *copyStr == '\0') if (copyStr == NULL || *copyStr == '\0')
{ {
Data()->Release();
NullString.RefCount++; NullString.RefCount++;
Chars = &NullString.Nothing[0]; Chars = &NullString.Nothing[0];
} }

View file

@ -1,4 +1,4 @@
/* Generated by re2c 0.10.5 */ /* Generated by re2c 0.12.3 on Wed Jan 23 17:40:06 2008 */
#line 1 "scanner.re" #line 1 "scanner.re"
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
@ -66,8 +66,9 @@ std:
unsigned int yyaccept = 0; unsigned int yyaccept = 0;
if((YYLIMIT - YYCURSOR) < 13) YYFILL(13); if((YYLIMIT - YYCURSOR) < 13) YYFILL(13);
(13);
yych = *YYCURSOR; yych = *YYCURSOR;
switch(yych){ switch(yych) {
case 0x09: case 0x09:
case 0x0B: case 0x0B:
case 0x0C: case 0x0C:
@ -159,7 +160,7 @@ yy2:
yy3: yy3:
#line 107 "scanner.re" #line 107 "scanner.re"
{ RET(DIVIDE); } { RET(DIVIDE); }
#line 163 "scanner.c" #line 164 "scanner.c"
yy4: yy4:
++YYCURSOR; ++YYCURSOR;
if((yych = *YYCURSOR) == 'n') goto yy192; if((yych = *YYCURSOR) == 'n') goto yy192;
@ -167,7 +168,7 @@ yy4:
yy5: yy5:
#line 91 "scanner.re" #line 91 "scanner.re"
{ RET(SYM); } { RET(SYM); }
#line 171 "scanner.c" #line 172 "scanner.c"
yy6: yy6:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych == 'r') goto yy187; if(yych == 'r') goto yy187;
@ -226,7 +227,7 @@ yy17:
yy18: yy18:
#line 94 "scanner.re" #line 94 "scanner.re"
{ RET(NUM); } { RET(NUM); }
#line 230 "scanner.c" #line 231 "scanner.c"
yy19: yy19:
yych = *++YYCURSOR; yych = *++YYCURSOR;
goto yy63; goto yy63;
@ -240,7 +241,7 @@ yy21:
printf("unexpected character: %c\n", *s->tok); printf("unexpected character: %c\n", *s->tok);
goto std; goto std;
} }
#line 244 "scanner.c" #line 245 "scanner.c"
yy22: yy22:
++YYCURSOR; ++YYCURSOR;
yych = *YYCURSOR; yych = *YYCURSOR;
@ -248,62 +249,62 @@ yy22:
yy23: yy23:
#line 99 "scanner.re" #line 99 "scanner.re"
{ goto std; } { goto std; }
#line 252 "scanner.c" #line 253 "scanner.c"
yy24: yy24:
++YYCURSOR; ++YYCURSOR;
#line 101 "scanner.re" #line 101 "scanner.re"
{ RET(OR); } { RET(OR); }
#line 257 "scanner.c" #line 258 "scanner.c"
yy26: yy26:
++YYCURSOR; ++YYCURSOR;
#line 102 "scanner.re" #line 102 "scanner.re"
{ RET(XOR); } { RET(XOR); }
#line 262 "scanner.c" #line 263 "scanner.c"
yy28: yy28:
++YYCURSOR; ++YYCURSOR;
#line 103 "scanner.re" #line 103 "scanner.re"
{ RET(AND); } { RET(AND); }
#line 267 "scanner.c" #line 268 "scanner.c"
yy30: yy30:
++YYCURSOR; ++YYCURSOR;
#line 104 "scanner.re" #line 104 "scanner.re"
{ RET(MINUS); } { RET(MINUS); }
#line 272 "scanner.c" #line 273 "scanner.c"
yy32: yy32:
++YYCURSOR; ++YYCURSOR;
#line 105 "scanner.re" #line 105 "scanner.re"
{ RET(PLUS); } { RET(PLUS); }
#line 277 "scanner.c" #line 278 "scanner.c"
yy34: yy34:
++YYCURSOR; ++YYCURSOR;
#line 106 "scanner.re" #line 106 "scanner.re"
{ RET(MULTIPLY); } { RET(MULTIPLY); }
#line 282 "scanner.c" #line 283 "scanner.c"
yy36: yy36:
++YYCURSOR; ++YYCURSOR;
#line 108 "scanner.re" #line 108 "scanner.re"
{ RET(LPAREN); } { RET(LPAREN); }
#line 287 "scanner.c" #line 288 "scanner.c"
yy38: yy38:
++YYCURSOR; ++YYCURSOR;
#line 109 "scanner.re" #line 109 "scanner.re"
{ RET(RPAREN); } { RET(RPAREN); }
#line 292 "scanner.c" #line 293 "scanner.c"
yy40: yy40:
++YYCURSOR; ++YYCURSOR;
#line 110 "scanner.re" #line 110 "scanner.re"
{ RET(COMMA); } { RET(COMMA); }
#line 297 "scanner.c" #line 298 "scanner.c"
yy42: yy42:
++YYCURSOR; ++YYCURSOR;
#line 111 "scanner.re" #line 111 "scanner.re"
{ RET(LBRACE); } { RET(LBRACE); }
#line 302 "scanner.c" #line 303 "scanner.c"
yy44: yy44:
++YYCURSOR; ++YYCURSOR;
#line 113 "scanner.re" #line 113 "scanner.re"
{ RET(SEMICOLON); } { RET(SEMICOLON); }
#line 307 "scanner.c" #line 308 "scanner.c"
yy46: yy46:
++YYCURSOR; ++YYCURSOR;
#line 117 "scanner.re" #line 117 "scanner.re"
@ -312,7 +313,7 @@ yy46:
s->pos = cursor; s->line++; s->pos = cursor; s->line++;
goto std; goto std;
} }
#line 316 "scanner.c" #line 317 "scanner.c"
yy48: yy48:
yych = *++YYCURSOR; yych = *++YYCURSOR;
goto yy21; goto yy21;
@ -401,7 +402,7 @@ yy55:
++YYCURSOR; ++YYCURSOR;
#line 97 "scanner.re" #line 97 "scanner.re"
{ RET(STRING); } { RET(STRING); }
#line 405 "scanner.c" #line 406 "scanner.c"
yy57: yy57:
++YYCURSOR; ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1); if(YYLIMIT == YYCURSOR) YYFILL(1);
@ -555,7 +556,7 @@ yy71:
yy82: yy82:
#line 89 "scanner.re" #line 89 "scanner.re"
{ RET(RenderStyles); } { RET(RenderStyles); }
#line 559 "scanner.c" #line 560 "scanner.c"
yy83: yy83:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'r') goto yy70; if(yych != 'r') goto yy70;
@ -589,7 +590,7 @@ yy83:
yy92: yy92:
#line 88 "scanner.re" #line 88 "scanner.re"
{ RET(FirstState); } { RET(FirstState); }
#line 593 "scanner.c" #line 594 "scanner.c"
yy93: yy93:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'a') goto yy70; if(yych != 'a') goto yy70;
@ -623,7 +624,7 @@ yy93:
yy102: yy102:
#line 86 "scanner.re" #line 86 "scanner.re"
{ RET(DeathState); } { RET(DeathState); }
#line 627 "scanner.c" #line 628 "scanner.c"
yy103: yy103:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'i') goto yy70; if(yych != 'i') goto yy70;
@ -655,7 +656,7 @@ yy103:
yy111: yy111:
#line 85 "scanner.re" #line 85 "scanner.re"
{ RET(ThingBits); } { RET(ThingBits); }
#line 659 "scanner.c" #line 660 "scanner.c"
yy112: yy112:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'f') goto yy70; if(yych != 'f') goto yy70;
@ -687,7 +688,7 @@ yy112:
yy120: yy120:
#line 84 "scanner.re" #line 84 "scanner.re"
{ RET(InfoNames); } { RET(InfoNames); }
#line 691 "scanner.c" #line 692 "scanner.c"
yy121: yy121:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych == 'u') goto yy140; if(yych == 'u') goto yy140;
@ -725,7 +726,7 @@ yy123:
yy130: yy130:
#line 82 "scanner.re" #line 82 "scanner.re"
{ RET(StateMap); } { RET(StateMap); }
#line 729 "scanner.c" #line 730 "scanner.c"
yy131: yy131:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'w') goto yy70; if(yych != 'w') goto yy70;
@ -757,7 +758,7 @@ yy131:
yy139: yy139:
#line 87 "scanner.re" #line 87 "scanner.re"
{ RET(SpawnState); } { RET(SpawnState); }
#line 761 "scanner.c" #line 762 "scanner.c"
yy140: yy140:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'n') goto yy70; if(yych != 'n') goto yy70;
@ -785,7 +786,7 @@ yy140:
yy146: yy146:
#line 83 "scanner.re" #line 83 "scanner.re"
{ RET(SoundMap); } { RET(SoundMap); }
#line 789 "scanner.c" #line 790 "scanner.c"
yy147: yy147:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'd') goto yy70; if(yych != 'd') goto yy70;
@ -817,7 +818,7 @@ yy147:
yy155: yy155:
#line 80 "scanner.re" #line 80 "scanner.re"
{ RET(CodePConv); } { RET(CodePConv); }
#line 821 "scanner.c" #line 822 "scanner.c"
yy156: yy156:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'g') goto yy70; if(yych != 'g') goto yy70;
@ -860,7 +861,7 @@ yy159:
yy167: yy167:
#line 81 "scanner.re" #line 81 "scanner.re"
{ RET(OrgSprNames); } { RET(OrgSprNames); }
#line 864 "scanner.c" #line 865 "scanner.c"
yy168: yy168:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'i') goto yy70; if(yych != 'i') goto yy70;
@ -888,7 +889,7 @@ yy168:
yy174: yy174:
#line 78 "scanner.re" #line 78 "scanner.re"
{ RET(OrgHeights); } { RET(OrgHeights); }
#line 892 "scanner.c" #line 893 "scanner.c"
yy175: yy175:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 't') goto yy70; if(yych != 't') goto yy70;
@ -917,7 +918,7 @@ yy175:
yy181: yy181:
#line 77 "scanner.re" #line 77 "scanner.re"
{ RET(Actions); } { RET(Actions); }
#line 921 "scanner.c" #line 922 "scanner.c"
yy182: yy182:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'i') goto yy70; if(yych != 'i') goto yy70;
@ -941,7 +942,7 @@ yy182:
yy186: yy186:
#line 79 "scanner.re" #line 79 "scanner.re"
{ RET(ActionList); } { RET(ActionList); }
#line 945 "scanner.c" #line 946 "scanner.c"
yy187: yy187:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'i') goto yy70; if(yych != 'i') goto yy70;
@ -965,7 +966,7 @@ yy187:
yy191: yy191:
#line 76 "scanner.re" #line 76 "scanner.re"
{ RET(PRINT); } { RET(PRINT); }
#line 969 "scanner.c" #line 970 "scanner.c"
yy192: yy192:
yych = *++YYCURSOR; yych = *++YYCURSOR;
if(yych != 'd') goto yy70; if(yych != 'd') goto yy70;
@ -987,7 +988,7 @@ yy192:
yy195: yy195:
#line 75 "scanner.re" #line 75 "scanner.re"
{ RET(ENDL); } { RET(ENDL); }
#line 991 "scanner.c" #line 992 "scanner.c"
yy196: yy196:
++YYCURSOR; ++YYCURSOR;
if(YYLIMIT == YYCURSOR) YYFILL(1); if(YYLIMIT == YYCURSOR) YYFILL(1);
@ -998,7 +999,7 @@ yy198:
++YYCURSOR; ++YYCURSOR;
#line 67 "scanner.re" #line 67 "scanner.re"
{ goto comment; } { goto comment; }
#line 1002 "scanner.c" #line 1003 "scanner.c"
yy200: yy200:
++YYCURSOR; ++YYCURSOR;
#line 69 "scanner.re" #line 69 "scanner.re"
@ -1007,17 +1008,18 @@ yy200:
s->tok = s->pos = cursor; s->line++; s->tok = s->pos = cursor; s->line++;
goto std; goto std;
} }
#line 1011 "scanner.c" #line 1012 "scanner.c"
} }
#line 128 "scanner.re" #line 128 "scanner.re"
comment: comment:
#line 1018 "scanner.c" #line 1019 "scanner.c"
{ {
YYCTYPE yych; YYCTYPE yych;
if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
(2);
yych = *YYCURSOR; yych = *YYCURSOR;
if(yych == 0x0A) goto yy206; if(yych == 0x0A) goto yy206;
if(yych != '*') goto yy208; if(yych != '*') goto yy208;
@ -1026,7 +1028,7 @@ comment:
yy205: yy205:
#line 139 "scanner.re" #line 139 "scanner.re"
{ goto comment; } { goto comment; }
#line 1030 "scanner.c" #line 1032 "scanner.c"
yy206: yy206:
++YYCURSOR; ++YYCURSOR;
#line 134 "scanner.re" #line 134 "scanner.re"
@ -1035,7 +1037,7 @@ yy206:
s->tok = s->pos = cursor; s->line++; s->tok = s->pos = cursor; s->line++;
goto comment; goto comment;
} }
#line 1039 "scanner.c" #line 1041 "scanner.c"
yy208: yy208:
yych = *++YYCURSOR; yych = *++YYCURSOR;
goto yy205; goto yy205;
@ -1043,7 +1045,7 @@ yy209:
++YYCURSOR; ++YYCURSOR;
#line 132 "scanner.re" #line 132 "scanner.re"
{ goto std; } { goto std; }
#line 1047 "scanner.c" #line 1049 "scanner.c"
} }
#line 140 "scanner.re" #line 140 "scanner.re"

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,11 @@ namespace re2c
void Symbol::ClearTable() void Symbol::ClearTable()
{ {
for (SymbolTable::iterator it = symbol_table.begin(); it != symbol_table.end(); ++it)
{
delete it->second;
}
symbol_table.clear(); symbol_table.clear();
} }
@ -519,7 +524,7 @@ uint Scanner::unescape(SubStr &s) const
static const char * oct = "01234567"; static const char * oct = "01234567";
s.len--; s.len--;
uint c; uint c, ucb = 0;
if ((c = *s.str++) != '\\' || s.len == 0) if ((c = *s.str++) != '\\' || s.len == 0)
{ {
@ -582,10 +587,20 @@ uint Scanner::unescape(SubStr &s) const
if (s.str[1] == '0') if (s.str[1] == '0')
{ {
l++; l++;
if (s.str[2] == '0') if (s.str[2] == '0' || (s.str[2] == '1' && uFlag))
{ {
l++; l++;
if (s.str[3] == '0') if (uFlag) {
const char *u3 = strchr(hex, tolower(s.str[2]));
const char *u4 = strchr(hex, tolower(s.str[3]));
if (u3 && u4)
{
ucb = (uint)((u3 - hex) << 20)
+ (uint)((u4 - hex) << 16);
l++;
}
}
else if (s.str[3] == '0')
{ {
l++; l++;
} }
@ -636,7 +651,8 @@ uint Scanner::unescape(SubStr &s) const
uint v = (uint)((p1 - hex) << 12) uint v = (uint)((p1 - hex) << 12)
+ (uint)((p2 - hex) << 8) + (uint)((p2 - hex) << 8)
+ (uint)((p3 - hex) << 4) + (uint)((p3 - hex) << 4)
+ (uint)((p4 - hex)); + (uint)((p4 - hex))
+ ucb;
if (v >= nRealChars) if (v >= nRealChars)
{ {

View file

@ -29,8 +29,8 @@ std::string indent(uint ind)
static std::string space(uint this_label) static std::string space(uint this_label)
{ {
int nl = next_label > 9999 ? 4 : next_label > 999 ? 3 : next_label > 99 ? 2 : next_label > 9 ? 1 : 0; int nl = next_label > 999999 ? 6 : next_label > 99999 ? 5 : next_label > 9999 ? 4 : next_label > 999 ? 3 : next_label > 99 ? 2 : next_label > 9 ? 1 : 0;
int tl = this_label > 9999 ? 4 : this_label > 999 ? 3 : this_label > 99 ? 2 : this_label > 9 ? 1 : 0; int tl = this_label > 999999 ? 6 : this_label > 99999 ? 5 : this_label > 9999 ? 4 : this_label > 999 ? 3 : this_label > 99 ? 2 : this_label > 9 ? 1 : 0;
return std::string(std::max(1, nl - tl + 1), ' '); return std::string(std::max(1, nl - tl + 1), ' ');
} }
@ -180,10 +180,7 @@ BitMap::BitMap(const Go *g, const State *x)
BitMap::~BitMap() BitMap::~BitMap()
{ {
if (next) delete next;
{
delete next;
}
} }
const BitMap *BitMap::find(const Go *g, const State *x) const BitMap *BitMap::find(const Go *g, const State *x)
@ -214,18 +211,17 @@ const BitMap *BitMap::find(const State *x)
void BitMap::gen(std::ostream &o, uint ind, uint lb, uint ub) void BitMap::gen(std::ostream &o, uint ind, uint lb, uint ub)
{ {
BitMap *b = first; if (first && bLastPass)
if (b && bLastPass)
{ {
o << indent(ind) << "static unsigned char yybm[] = {"; o << indent(ind) << "static const unsigned char " << mapCodeName["yybm"] << "[] = {";
uint c = 1, n = ub - lb; uint c = 1, n = ub - lb;
const BitMap *cb = first;
while((b = const_cast<BitMap*>(b->next)) != NULL) { while((cb = cb->next) != NULL) {
++c; ++c;
} }
b = first; BitMap *b = first;
uint *bm = new uint[n]; uint *bm = new uint[n];
@ -291,27 +287,28 @@ void genGoTo(std::ostream &o, uint ind, const State *from, const State *to, bool
{ {
if (readCh && from->label + 1 != to->label) if (readCh && from->label + 1 != to->label)
{ {
o << indent(ind) << "yych = *YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
readCh = false; readCh = false;
} }
o << indent(ind) << "goto yy" << to->label << ";\n"; o << indent(ind) << "goto " << labelPrefix << to->label << ";\n";
vUsedLabels.insert(to->label); vUsedLabels.insert(to->label);
} }
void genIf(std::ostream &o, uint ind, const char *cmp, uint v, bool &readCh) void genIf(std::ostream &o, uint ind, const char *cmp, uint v, bool &readCh)
{ {
o << indent(ind) << "if(";
if (readCh) if (readCh)
{ {
o << indent(ind) << "if((yych = *YYCURSOR) "; o << "(" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")";
readCh = false; readCh = false;
} }
else else
{ {
o << indent(ind) << "if(yych "; o << mapCodeName["yych"];
} }
o << cmp << " "; o << " " << cmp << " ";
prtChOrHex(o, v); prtChOrHex(o, v);
o << ") "; o << ") ";
} }
@ -323,33 +320,38 @@ static void need(std::ostream &o, uint ind, uint n, bool & readCh, bool bSetMark
if (fFlag) if (fFlag)
{ {
next_fill_index++; next_fill_index++;
o << indent(ind) << "YYSETSTATE(" << fillIndex << ");\n"; o << indent(ind) << mapCodeName["YYSETSTATE"] << "(" << fillIndex << ");\n";
} }
if (bUseYYFill) if (bUseYYFill)
{ {
if (n == 1) if (n == 1)
{ {
o << indent(ind) << "if(YYLIMIT == YYCURSOR) YYFILL(1);\n"; o << indent(ind) << "if(" << mapCodeName["YYLIMIT"] << " == " << mapCodeName["YYCURSOR"] << ") " << mapCodeName["YYFILL"];
} }
else else
{ {
o << indent(ind) << "if((YYLIMIT - YYCURSOR) < " << n << ") YYFILL(" << n << ");\n"; o << indent(ind) << "if((YYLIMIT - YYCURSOR) < " << n << ") YYFILL(" << n << ");\n";
} }
if (bUseYYFillParam)
{
o << "(" << n << ")";
}
o << ";\n";
} }
if (fFlag) if (fFlag)
{ {
o << "yyFillLabel" << fillIndex << ":\n"; o << mapCodeName["yyFillLabel"] << fillIndex << ":\n";
} }
if (bSetMarker) if (bSetMarker)
{ {
o << indent(ind) << "yych = *(YYMARKER = YYCURSOR);\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ");\n";
} }
else else
{ {
o << indent(ind) << "yych = *YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
} }
readCh = false; readCh = false;
} }
@ -358,17 +360,17 @@ void Match::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (state->link) if (state->link)
{ {
o << indent(ind) << "++YYCURSOR;\n"; o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
} }
else if (!readAhead()) else if (!readAhead())
{ {
/* do not read next char if match */ /* do not read next char if match */
o << indent(ind) << "++YYCURSOR;\n"; o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
readCh = true; readCh = true;
} }
else else
{ {
o << indent(ind) << "yych = *++YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
readCh = false; readCh = false;
} }
@ -382,20 +384,20 @@ void Enter::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (state->link) if (state->link)
{ {
o << indent(ind) << "++YYCURSOR;\n"; o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
if (vUsedLabels.count(label)) if (vUsedLabels.count(label))
{ {
o << "yy" << label << ":\n"; o << labelPrefix << label << ":\n";
} }
need(o, ind, state->depth, readCh, false); need(o, ind, state->depth, readCh, false);
} }
else else
{ {
/* we shouldn't need 'rule-following' protection here */ /* we shouldn't need 'rule-following' protection here */
o << indent(ind) << "yych = *++YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
if (vUsedLabels.count(label)) if (vUsedLabels.count(label))
{ {
o << "yy" << label << ":\n"; o << labelPrefix << label << ":\n";
} }
readCh = false; readCh = false;
} }
@ -412,17 +414,17 @@ void Initial::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (state->link) if (state->link)
{ {
o << indent(ind) << "++YYCURSOR;\n"; o << indent(ind) << "++" << mapCodeName["YYCURSOR"] << ";\n";
} }
else else
{ {
o << indent(ind) << "yych = *++YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
} }
} }
if (vUsedLabels.count(label)) if (vUsedLabels.count(label))
{ {
o << "yy" << label << ":\n"; o << labelPrefix << label << ":\n";
} }
else if (!label) else if (!label)
{ {
@ -431,7 +433,7 @@ void Initial::emit(std::ostream &o, uint ind, bool &readCh) const
if (dFlag) if (dFlag)
{ {
o << indent(ind) << "YYDEBUG(" << label << ", *YYCURSOR);\n"; o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
} }
if (state->link) if (state->link)
@ -442,7 +444,7 @@ void Initial::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (setMarker && bUsedYYMarker) if (setMarker && bUsedYYMarker)
{ {
o << indent(ind) << "YYMARKER = YYCURSOR;\n"; o << indent(ind) << mapCodeName["YYMARKER"] << " = " << mapCodeName["YYCURSOR"] << ";\n";
} }
readCh = false; readCh = false;
} }
@ -452,14 +454,14 @@ void Save::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (bUsedYYAccept) if (bUsedYYAccept)
{ {
o << indent(ind) << "yyaccept = " << selector << ";\n"; o << indent(ind) << mapCodeName["yyaccept"] << " = " << selector << ";\n";
} }
if (state->link) if (state->link)
{ {
if (bUsedYYMarker) if (bUsedYYMarker)
{ {
o << indent(ind) << "YYMARKER = ++YYCURSOR;\n"; o << indent(ind) << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ";\n";
} }
need(o, ind, state->depth, readCh, false); need(o, ind, state->depth, readCh, false);
} }
@ -467,11 +469,11 @@ void Save::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (bUsedYYMarker) if (bUsedYYMarker)
{ {
o << indent(ind) << "yych = *(YYMARKER = ++YYCURSOR);\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*(" << mapCodeName["YYMARKER"] << " = ++" << mapCodeName["YYCURSOR"] << ");\n";
} }
else else
{ {
o << indent(ind) << "yych = *++YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*++" << mapCodeName["YYCURSOR"] << ";\n";
} }
readCh = false; readCh = false;
} }
@ -510,7 +512,7 @@ void Accept::emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh)
{ {
uint m = (l + r) >> 1; uint m = (l + r) >> 1;
o << indent(ind) << "if(yyaccept <= " << m << ") {\n"; o << indent(ind) << "if(" << mapCodeName["yyaccept"] << " <= " << m << ") {\n";
emitBinary(o, ++ind, l, m, readCh); emitBinary(o, ++ind, l, m, readCh);
o << indent(--ind) << "} else {\n"; o << indent(--ind) << "} else {\n";
emitBinary(o, ++ind, m + 1, r, readCh); emitBinary(o, ++ind, m + 1, r, readCh);
@ -527,11 +529,11 @@ void Accept::emit(std::ostream &o, uint ind, bool &readCh) const
if (mapRules.size() > 0) if (mapRules.size() > 0)
{ {
bUsedYYMarker = true; bUsedYYMarker = true;
o << indent(ind) << "YYCURSOR = YYMARKER;\n"; o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYMARKER"] << ";\n";
if (readCh) // shouldn't be necessary, but might become at some point if (readCh) // shouldn't be necessary, but might become at some point
{ {
o << indent(ind) << "yych = *YYCURSOR;\n"; o << indent(ind) << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ";\n";
readCh = false; readCh = false;
} }
@ -542,14 +544,14 @@ void Accept::emit(std::ostream &o, uint ind, bool &readCh) const
if (gFlag && mapRules.size() >= cGotoThreshold) if (gFlag && mapRules.size() >= cGotoThreshold)
{ {
o << indent(ind++) << "{\n"; o << indent(ind++) << "{\n";
o << indent(ind++) << "static void *yytarget[" << mapRules.size() << "] = {\n"; o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[" << mapRules.size() << "] = {\n";
for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it) for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
{ {
o << indent(ind) << "&&yy" << it->second->label << ",\n"; o << indent(ind) << "&&" << labelPrefix << it->second->label << ",\n";
vUsedLabels.insert(it->second->label); vUsedLabels.insert(it->second->label);
} }
o << indent(--ind) << "};\n"; o << indent(--ind) << "};\n";
o << indent(ind) << "goto *yytarget[yyaccept];\n"; o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << mapCodeName["yyaccept"] << "];\n";
o << indent(--ind) << "}\n"; o << indent(--ind) << "}\n";
} }
else if (sFlag) else if (sFlag)
@ -558,7 +560,7 @@ void Accept::emit(std::ostream &o, uint ind, bool &readCh) const
} }
else else
{ {
o << indent(ind) << "switch(yyaccept) {\n"; o << indent(ind) << "switch(" << mapCodeName["yyaccept"] << ") {\n";
for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it) for (RuleMap::const_iterator it = mapRules.begin(); it != mapRules.end(); ++it)
{ {
@ -588,7 +590,7 @@ void Rule::emit(std::ostream &o, uint ind, bool &) const
if (back != 0u) if (back != 0u)
{ {
o << indent(ind) << "YYCURSOR = YYCTXMARKER;\n"; o << indent(ind) << mapCodeName["YYCURSOR"] << " = " << mapCodeName["YYCTXMARKER"] << ";\n";
} }
RuleLine rl(*rule); RuleLine rl(*rule);
@ -739,17 +741,17 @@ void Go::genSwitch(std::ostream &o, uint ind, const State *from, const State *ne
if (dFlag) if (dFlag)
{ {
o << indent(ind) << "YYDEBUG(-1, yych);\n"; o << indent(ind) << mapCodeName["YYDEBUG"] << "(-1, " << mapCodeName["yych"] << ");\n";
} }
if (readCh) if (readCh)
{ {
o << indent(ind) << "switch((yych = *YYCURSOR)) {\n"; o << indent(ind) << "switch((" << mapCodeName["yych"] << " = " << yychConversion << "*" << mapCodeName["YYCURSOR"] << ")) {\n";
readCh = false; readCh = false;
} }
else else
{ {
o << indent(ind) << "switch(yych){\n"; o << indent(ind) << "switch(" << mapCodeName["yych"] << ") {\n";
} }
while (t != &sP[0]) while (t != &sP[0])
@ -893,21 +895,30 @@ void Go::genBase(std::ostream &o, uint ind, const State *from, const State *next
void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const
{ {
const char * sYych = readCh ? "(yych = *YYCURSOR)" : "yych"; std::string sYych;
if (readCh)
{
sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
}
else
{
sYych = mapCodeName["yych"];
}
readCh = false; readCh = false;
if (wFlag) if (wFlag)
{ {
o << indent(ind) << "if(" << sYych <<" & 0xFF00) {\n"; o << indent(ind) << "if(" << sYych <<" & ~0xFF) {\n";
genBase(o, ind+1, from, next, readCh, 1); genBase(o, ind+1, from, next, readCh, 1);
o << indent(ind++) << "} else {\n"; o << indent(ind++) << "} else {\n";
sYych = "yych"; sYych = mapCodeName["yych"];
} }
else else
{ {
o << indent(ind++) << "{\n"; o << indent(ind++) << "{\n";
} }
o << indent(ind++) << "static void *yytarget[256] = {\n"; o << indent(ind++) << "static void *" << mapCodeName["yytarget"] << "[256] = {\n";
o << indent(ind); o << indent(ind);
uint ch = 0; uint ch = 0;
@ -916,7 +927,7 @@ void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *ne
vUsedLabels.insert(span[i].to->label); vUsedLabels.insert(span[i].to->label);
for(; ch < span[i].ub; ++ch) for(; ch < span[i].ub; ++ch)
{ {
o << "&&yy" << span[i].to->label; o << "&&" << labelPrefix << span[i].to->label;
if (ch == 255) if (ch == 255)
{ {
o << "\n"; o << "\n";
@ -934,7 +945,7 @@ void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *ne
} }
} }
o << indent(--ind) << "};\n"; o << indent(--ind) << "};\n";
o << indent(ind) << "goto *yytarget[" << sYych << "];\n"; o << indent(ind) << "goto *" << mapCodeName["yytarget"] << "[" << sYych << "];\n";
o << indent(--ind) << "}\n"; o << indent(--ind) << "}\n";
} }
@ -997,19 +1008,26 @@ void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next
if (to && to->isBase) if (to && to->isBase)
{ {
const BitMap *b = BitMap::find(to); const BitMap *b = BitMap::find(to);
const char * sYych; std::string sYych;
if (b && matches(b->go, b->on, this, to)) if (b && matches(b->go, b->on, this, to))
{ {
Go go; Go go;
go.span = new Span[nSpans]; go.span = new Span[nSpans];
go.unmap(this, to); go.unmap(this, to);
sYych = readCh ? "(yych = *YYCURSOR)" : "yych"; if (readCh)
{
sYych = "(" + mapCodeName["yych"] + " = " + yychConversion + "*" + mapCodeName["YYCURSOR"] + ")";
}
else
{
sYych = mapCodeName["yych"];
}
readCh = false; readCh = false;
if (wFlag) if (wFlag)
{ {
o << indent(ind) << "if(" << sYych << " & 0xFF00) {\n"; o << indent(ind) << "if(" << sYych << " & ~0xFF) {\n";
sYych = "yych"; sYych = mapCodeName["yych"];
genBase(o, ind+1, from, next, readCh, 1); genBase(o, ind+1, from, next, readCh, 1);
o << indent(ind) << "} else "; o << indent(ind) << "} else ";
} }
@ -1017,7 +1035,7 @@ void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next
{ {
o << indent(ind); o << indent(ind);
} }
o << "if(yybm[" << b->i << "+" << sYych << "] & "; o << "if(" << mapCodeName["yybm"] << "[" << b->i << "+" << sYych << "] & ";
if (yybmHexTable) if (yybmHexTable)
{ {
prtHex(o, b->m, false); prtHex(o, b->m, false);
@ -1044,15 +1062,15 @@ void State::emit(std::ostream &o, uint ind, bool &readCh) const
{ {
if (vUsedLabels.count(label)) if (vUsedLabels.count(label))
{ {
o << "yy" << label << ":\n"; o << labelPrefix << label << ":\n";
} }
if (dFlag && !action->isInitial()) if (dFlag && !action->isInitial())
{ {
o << indent(ind) << "YYDEBUG(" << label << ", *YYCURSOR);\n"; o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");\n";
} }
if (isPreCtxt) if (isPreCtxt)
{ {
o << indent(ind) << "YYCTXMARKER = YYCURSOR + 1;\n"; o << indent(ind) << mapCodeName["YYCTXMARKER"] << " = " << mapCodeName["YYCURSOR"] << " + 1;\n";
} }
action->emit(o, ind, readCh); action->emit(o, ind, readCh);
} }
@ -1407,6 +1425,7 @@ void DFA::emit(std::ostream &o, uint ind)
if (s->go.span[i].to && !s->go.span[i].to->rule) if (s->go.span[i].to && !s->go.span[i].to->rule)
{ {
delete s->action; delete s->action;
s->action = NULL;
if (saves[s->rule->accept] == ~0u) if (saves[s->rule->accept] == ~0u)
{ {
@ -1500,6 +1519,7 @@ void DFA::emit(std::ostream &o, uint ind)
findBaseState(); findBaseState();
delete head->action; delete head->action;
head->action = NULL;
if (bFlag) if (bFlag)
{ {
@ -1550,10 +1570,10 @@ void DFA::emit(std::ostream &o, uint ind)
if (!fFlag) if (!fFlag)
{ {
o << indent(ind) << "YYCTYPE yych;\n"; o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
if (bUsedYYAccept) if (bUsedYYAccept)
{ {
o << indent(ind) << "unsigned int yyaccept = 0;\n"; o << indent(ind) << "unsigned int "<< mapCodeName["yyaccept"] << " = 0;\n";
} }
} }
else else
@ -1566,7 +1586,7 @@ void DFA::emit(std::ostream &o, uint ind)
if (vUsedLabels.count(1)) if (vUsedLabels.count(1))
{ {
vUsedLabels.insert(0); vUsedLabels.insert(0);
o << indent(ind) << "goto yy0;\n"; o << indent(ind) << "goto " << labelPrefix << "0;\n";
} }
// Generate code // Generate code
@ -1602,26 +1622,26 @@ void genGetState(std::ostream &o, uint& ind, uint start_label)
if (fFlag && !bWroteGetState) if (fFlag && !bWroteGetState)
{ {
vUsedLabels.insert(start_label); vUsedLabels.insert(start_label);
o << indent(ind) << "switch(YYGETSTATE()) {\n"; o << indent(ind) << "switch(" << mapCodeName["YYGETSTATE"] << "()) {\n";
if (bUseStateAbort) if (bUseStateAbort)
{ {
o << indent(ind) << "default: abort();\n"; o << indent(ind) << "default: abort();\n";
o << indent(ind) << "case -1: goto yy" << start_label << ";\n"; o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
} }
else else
{ {
o << indent(ind) << "default: goto yy" << start_label << ";\n"; o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
} }
for (size_t i=0; i<last_fill_index; ++i) for (size_t i=0; i<last_fill_index; ++i)
{ {
o << indent(ind) << "case " << i << ": goto yyFillLabel" << i << ";\n"; o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
} }
o << indent(ind) << "}\n"; o << indent(ind) << "}\n";
if (bUseStateNext) if (bUseStateNext)
{ {
o << "yyNext:\n"; o << mapCodeName["yyNext"] << ":\n";
} }
bWroteGetState = true; bWroteGetState = true;
} }
@ -1672,46 +1692,111 @@ void Scanner::config(const Str& cfg, int num)
{ {
bUseYYFill = num != 0; bUseYYFill = num != 0;
} }
else if (cfg.to_string() == "yyfill:parameter")
{
bUseYYFillParam = num != 0;
}
else if (cfg.to_string() == "cgoto:threshold") else if (cfg.to_string() == "cgoto:threshold")
{ {
cGotoThreshold = num; cGotoThreshold = num;
} }
else if (cfg.to_string() == "yych:conversion")
{
if (num)
{
yychConversion = "(";
yychConversion += mapCodeName["YYCTYPE"];
yychConversion += ")";
}
else
{
yychConversion = "";
}
}
else else
{ {
fatal("unrecognized configuration name or illegal integer value"); fatal("unrecognized configuration name or illegal integer value");
} }
} }
static std::set<std::string> mapVariableKeys;
static std::set<std::string> mapDefineKeys;
static std::set<std::string> mapLabelKeys;
void Scanner::config(const Str& cfg, const Str& val) void Scanner::config(const Str& cfg, const Str& val)
{ {
if (mapDefineKeys.empty())
{
mapVariableKeys.insert("variable:yyaccept");
mapVariableKeys.insert("variable:yybm");
mapVariableKeys.insert("variable:yych");
mapVariableKeys.insert("variable:yytarget");
mapDefineKeys.insert("define:YYCTXMARKER");
mapDefineKeys.insert("define:YYCTYPE");
mapDefineKeys.insert("define:YYCURSOR");
mapDefineKeys.insert("define:YYDEBUG");
mapDefineKeys.insert("define:YYFILL");
mapDefineKeys.insert("define:YYGETSTATE");
mapDefineKeys.insert("define:YYLIMIT");
mapDefineKeys.insert("define:YYMARKER");
mapDefineKeys.insert("define:YYSETSTATE");
mapLabelKeys.insert("label:yyFillLabel");
mapLabelKeys.insert("label:yyNext");
}
std::string strVal;
if (val.len >= 2 && val.str[0] == val.str[val.len-1]
&& (val.str[0] == '"' || val.str[0] == '\''))
{
SubStr tmp(val.str + 1, val.len - 2);
unescape(tmp, strVal);
}
else
{
strVal = val.to_string();
}
if (cfg.to_string() == "indent:string") if (cfg.to_string() == "indent:string")
{ {
if (val.len >= 2 && val.str[0] == val.str[val.len-1] indString = strVal;
&& (val.str[0] == '"' || val.str[0] == '\''))
{
SubStr tmp(val.str + 1, val.len - 2);
unescape(tmp, indString);
}
else
{
indString = val.to_string();
}
return;
} }
else if (cfg.to_string() == "startlabel") else if (cfg.to_string() == "startlabel")
{ {
if (val.len >= 2 && val.str[0] == val.str[val.len-1] startLabelName = val.to_string();
&& (val.str[0] == '"' || val.str[0] == '\''))
{
SubStr tmp(val.str + 1, val.len - 2);
unescape(tmp, startLabelName);
}
else
{
startLabelName = val.to_string();
}
bUseStartLabel = !startLabelName.empty(); bUseStartLabel = !startLabelName.empty();
} }
else if (cfg.to_string() == "labelprefix")
{
labelPrefix = strVal;
}
else if (mapVariableKeys.find(cfg.to_string()) != mapVariableKeys.end())
{
if (bFirstPass && !mapCodeName.insert(
std::make_pair(cfg.to_string().substr(sizeof("variable:") - 1), strVal)
).second)
{
fatal("variable already being used and cannot be changed");
}
}
else if (mapDefineKeys.find(cfg.to_string()) != mapDefineKeys.end())
{
if (bFirstPass && !mapCodeName.insert(
std::make_pair(cfg.to_string().substr(sizeof("define:") - 1), strVal)
).second)
{
fatal("define already being used and cannot be changed");
}
}
else if (mapLabelKeys.find(cfg.to_string()) != mapLabelKeys.end())
{
if (bFirstPass && !mapCodeName.insert(
std::make_pair(cfg.to_string().substr(sizeof("label:") - 1), strVal)
).second)
{
fatal("label already being used and cannot be changed");
}
}
else else
{ {
fatal("unrecognized configuration name or illegal string value"); fatal("unrecognized configuration name or illegal string value");

33
tools/re2c/code_names.h Normal file
View file

@ -0,0 +1,33 @@
/* $Id: token.h 547 2006-05-25 13:40:35Z helly $ */
#ifndef _code_names_h
#define _code_names_h
#include <string>
#include <map>
namespace re2c
{
class CodeNames: public std::map<std::string, std::string>
{
public:
std::string& operator [] (const char * what);
};
inline std::string& CodeNames::operator [] (const char * what)
{
CodeNames::iterator it = find(std::string(what));
if (it != end())
{
return it->second;
}
else
{
return insert(std::make_pair(std::string(what), std::string(what))).first->second;
}
}
} // end namespace re2c
#endif

View file

@ -7,10 +7,6 @@
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1 #define HAVE_INTTYPES_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1 #define HAVE_MEMORY_H 1
@ -63,13 +59,13 @@
#define PACKAGE_NAME "re2c" #define PACKAGE_NAME "re2c"
/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "re2c 0.10.5" #define PACKAGE_STRING "re2c 0.12.3"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "re2c" #define PACKAGE_TARNAME "re2c"
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "0.10.5" #define PACKAGE_VERSION "0.12.3"
/* The size of a `char', as computed by sizeof. */ /* The size of a `char', as computed by sizeof. */
#define SIZEOF_CHAR 1 #define SIZEOF_CHAR 1
@ -87,7 +83,7 @@
#define STDC_HEADERS 1 #define STDC_HEADERS 1
/* Version number of package */ /* Version number of package */
#define VERSION "0.10.5" #define VERSION "0.12.3"
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */ /* #undef const */
@ -98,9 +94,6 @@
/* #undef inline */ /* #undef inline */
#endif #endif
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */
/* Define to `unsigned' if <sys/types.h> does not define. */ /* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */ /* #undef size_t */

View file

@ -15,7 +15,7 @@ void prtChOrHex(std::ostream& o, uint c, bool useTalx)
if ((oc < 256) && isprint(oc)) if ((oc < 256) && isprint(oc))
{ {
o << '\''; o << '\'';
prtCh(o, oc); prtCh(o, c);
o << '\''; o << '\'';
} }
else else
@ -28,7 +28,19 @@ void prtHex(std::ostream& o, uint c, bool useTalx)
{ {
int oc = (int)(re2c::wFlag || !useTalx ? c : re2c::talx[c]); int oc = (int)(re2c::wFlag || !useTalx ? c : re2c::talx[c]);
if (re2c::wFlag) if (re2c::uFlag)
{
o << "0x"
<< hexCh(oc >> 28)
<< hexCh(oc >> 24)
<< hexCh(oc >> 20)
<< hexCh(oc >> 16)
<< hexCh(oc >> 12)
<< hexCh(oc >> 8)
<< hexCh(oc >> 4)
<< hexCh(oc);
}
else if (re2c::wFlag)
{ {
o << "0x" o << "0x"
<< hexCh(oc >> 12) << hexCh(oc >> 12)
@ -92,6 +104,16 @@ void prtCh(std::ostream& o, uint c, bool useTalx)
{ {
o << (char) oc; o << (char) oc;
} }
else if (re2c::uFlag)
{
o << "0x"
<< hexCh(oc >> 20)
<< hexCh(oc >> 16)
<< hexCh(oc >> 12)
<< hexCh(oc >> 8)
<< hexCh(oc >> 4)
<< hexCh(oc);
}
else if (re2c::wFlag) else if (re2c::wFlag)
{ {
o << "0x" o << "0x"
@ -189,6 +211,7 @@ State::State()
State::~State() State::~State()
{ {
delete action;
delete [] kernel; delete [] kernel;
delete [] go.span; delete [] go.span;
} }

View file

@ -291,6 +291,7 @@ public:
inline Action::Action(State *s) : state(s) inline Action::Action(State *s) : state(s)
{ {
delete s->action;
s->action = this; s->action = this;
} }

View file

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include "stream_lc.h" #include "stream_lc.h"
#include "code_names.h"
namespace re2c namespace re2c
{ {
@ -21,9 +22,13 @@ extern bool fFlag;
extern bool gFlag; extern bool gFlag;
extern bool iFlag; extern bool iFlag;
extern bool sFlag; extern bool sFlag;
extern bool uFlag;
extern bool wFlag; extern bool wFlag;
extern bool bNoGenerationDate;
extern bool bSinglePass; extern bool bSinglePass;
extern bool bFirstPass;
extern bool bLastPass; extern bool bLastPass;
extern bool bUsedYYAccept; extern bool bUsedYYAccept;
@ -32,6 +37,8 @@ extern bool bUsedYYMarker;
extern bool bUseStartLabel; extern bool bUseStartLabel;
extern std::string startLabelName; extern std::string startLabelName;
extern std::string labelPrefix;
extern std::string yychConversion;
extern uint maxFill; extern uint maxFill;
extern uint next_label; extern uint next_label;
extern uint cGotoThreshold; extern uint cGotoThreshold;
@ -44,6 +51,7 @@ extern bool bUseStateAbort;
extern bool bUseStateNext; extern bool bUseStateNext;
extern bool bWroteGetState; extern bool bWroteGetState;
extern bool bUseYYFill; extern bool bUseYYFill;
extern bool bUseYYFillParam;
extern uint asc2ebc[256]; extern uint asc2ebc[256];
extern uint ebc2asc[256]; extern uint ebc2asc[256];
@ -53,20 +61,12 @@ extern uint *xlat, *talx;
extern uint next_fill_index; extern uint next_fill_index;
extern uint last_fill_index; extern uint last_fill_index;
extern std::set<uint> vUsedLabels; extern std::set<uint> vUsedLabels;
extern re2c::CodeNames mapCodeName;
extern uint nRealChars; extern uint nRealChars;
inline char octCh(uint c) extern char octCh(uint c);
{ extern char hexCh(uint c);
return '0' + c % 8;
}
inline char hexCh(uint c)
{
static const char * sHex = "0123456789ABCDEF";
return sHex[c & 0x0F];
}
} // end namespace re2c } // end namespace re2c

View file

@ -28,20 +28,27 @@ bool fFlag = false;
bool gFlag = false; bool gFlag = false;
bool iFlag = false; bool iFlag = false;
bool sFlag = false; bool sFlag = false;
bool uFlag = false;
bool wFlag = false; bool wFlag = false;
bool bNoGenerationDate = false;
bool bSinglePass = false; bool bSinglePass = false;
bool bFirstPass = true;
bool bLastPass = false; bool bLastPass = false;
bool bUsedYYAccept = false; bool bUsedYYAccept = false;
bool bUsedYYMaxFill = false; bool bUsedYYMaxFill = false;
bool bUsedYYMarker = true; bool bUsedYYMarker = true;
bool bUseStartLabel= false; bool bUseStartLabel = false;
bool bUseStateNext = false; bool bUseStateNext = false;
bool bUseYYFill = true; bool bUseYYFill = true;
bool bUseYYFillParam = true;
std::string startLabelName; std::string startLabelName;
std::string labelPrefix("yy");
std::string yychConversion("");
uint maxFill = 1; uint maxFill = 1;
uint next_label = 0; uint next_label = 0;
uint cGotoThreshold = 9; uint cGotoThreshold = 9;
@ -57,6 +64,10 @@ uint nRealChars = 256;
uint next_fill_index = 0; uint next_fill_index = 0;
uint last_fill_index = 0; uint last_fill_index = 0;
std::set<uint> vUsedLabels; std::set<uint> vUsedLabels;
re2c::CodeNames mapCodeName;
free_list<RegExp*> RegExp::vFreeList;
free_list<Range*> Range::vFreeList;
using namespace std; using namespace std;
@ -75,10 +86,12 @@ static const mbo_opt_struct OPTIONS[] =
mbo_opt_struct('i', 0, "no-debug-info"), mbo_opt_struct('i', 0, "no-debug-info"),
mbo_opt_struct('o', 1, "output"), mbo_opt_struct('o', 1, "output"),
mbo_opt_struct('s', 0, "nested-ifs"), mbo_opt_struct('s', 0, "nested-ifs"),
mbo_opt_struct('u', 0, "unicode"),
mbo_opt_struct('v', 0, "version"), mbo_opt_struct('v', 0, "version"),
mbo_opt_struct('V', 0, "vernum"), mbo_opt_struct('V', 0, "vernum"),
mbo_opt_struct('w', 0, "wide-chars"), mbo_opt_struct('w', 0, "wide-chars"),
mbo_opt_struct('1', 0, "single-pass"), mbo_opt_struct('1', 0, "single-pass"),
mbo_opt_struct(10, 0, "no-generation-date"),
mbo_opt_struct('-', 0, NULL) /* end of args */ mbo_opt_struct('-', 0, NULL) /* end of args */
}; };
@ -113,7 +126,10 @@ static void usage()
"-s --nested-ifs Generate nested ifs for some switches. Many compilers\n" "-s --nested-ifs Generate nested ifs for some switches. Many compilers\n"
" need this assist to generate better code.\n" " need this assist to generate better code.\n"
"\n" "\n"
"-u --unicode Implies -w but supports the full Unicode character set.\n"
"\n"
"-v --version Show version information.\n" "-v --version Show version information.\n"
"\n"
"-V --vernum Show version as one number.\n" "-V --vernum Show version as one number.\n"
"\n" "\n"
"-w --wide-chars Create a parser that supports wide chars (UCS-2). This\n" "-w --wide-chars Create a parser that supports wide chars (UCS-2). This\n"
@ -122,6 +138,9 @@ static void usage()
"-1 --single-pass Force single pass generation, this cannot be combined\n" "-1 --single-pass Force single pass generation, this cannot be combined\n"
" with -f and disables YYMAXFILL generation prior to last\n" " with -f and disables YYMAXFILL generation prior to last\n"
" re2c block.\n" " re2c block.\n"
"\n"
"--no-generation-date Suppress the date output in the generated output so that it\n"
" only shows the re2c version.\n"
; ;
} }
@ -163,10 +182,6 @@ int main(int argc, char *argv[])
case 'f': case 'f':
fFlag = true; fFlag = true;
if (bSinglePass) {
std::cerr << "re2c: error: cannot combine -1 and -f switch\n";
return 1;
}
break; break;
case 'g': case 'g':
@ -188,10 +203,6 @@ int main(int argc, char *argv[])
break; break;
case '1': case '1':
if (bFlag) {
std::cerr << "re2c: error: cannot combine -1 and -f switch\n";
return 1;
}
bSinglePass = true; bSinglePass = true;
break; break;
@ -222,25 +233,51 @@ int main(int argc, char *argv[])
} }
case 'w': case 'w':
nRealChars = (1<<16); nRealChars = (1<<16); /* 0x10000 */
sFlag = true; sFlag = true;
wFlag = true; wFlag = true;
break; break;
case 'u':
nRealChars = 0x110000; /* 17 times w-Flag */
sFlag = true;
uFlag = true;
break;
case 'h': case 'h':
case '?': case '?':
default: default:
usage(); usage();
return 2; return 2;
case 10:
bNoGenerationDate = true;
break;
} }
} }
if ((bFlag || fFlag) && bSinglePass) {
std::cerr << "re2c: error: Cannot combine -1 and -b or -f switch\n";
return 1;
}
if (wFlag && eFlag) if (wFlag && eFlag)
{ {
usage(); std::cerr << "re2c: error: Cannot combine -e with -w or -u switch\n";
return 2; return 2;
} }
else if (argc == opt_ind + 1) if (wFlag && uFlag)
{
std::cerr << "re2c: error: Cannot combine -u with -w switch\n";
return 2;
}
if (uFlag)
{
wFlag = true;
}
if (argc == opt_ind + 1)
{ {
sourceFileName = argv[opt_ind]; sourceFileName = argv[opt_ind];
} }
@ -303,9 +340,9 @@ int main(int argc, char *argv[])
parse(null_scanner, null_dev); parse(null_scanner, null_dev);
next_label = 0; next_label = 0;
next_fill_index = 0; next_fill_index = 0;
Symbol::ClearTable();
bWroteGetState = false; bWroteGetState = false;
bUsedYYMaxFill = false; bUsedYYMaxFill = false;
bFirstPass = false;
} }
bLastPass = true; bLastPass = true;

View file

@ -81,6 +81,10 @@ int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct *opts, char **o
if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-')) if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))
{ {
/* '--' indicates end of args if not followed by a known long option name */ /* '--' indicates end of args if not followed by a known long option name */
if (argv[*optind][2] == '\0') {
(*optind)++;
return(EOF);
}
while (1) while (1)
{ {
@ -89,7 +93,7 @@ int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct *opts, char **o
if (opts[opts_idx].opt_char == '-') if (opts[opts_idx].opt_char == '-')
{ {
(*optind)++; (*optind)++;
return (EOF); return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRARG, show_err));
} }
else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name)) else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name))
{ {
@ -98,22 +102,26 @@ int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct *opts, char **o
} }
optchr = 0; optchr = 0;
dash = 1; dash = 0;
arg_start = 2 + strlen(opts[opts_idx].opt_name); arg_start = 2 + strlen(opts[opts_idx].opt_name);
} }
if (!dash) else
{ {
dash = 1; if (!dash)
optchr = 1; {
} dash = 1;
optchr = 1;
}
/* Check if the guy tries to do a -: kind of flag */ /* Check if the guy tries to do a -: kind of flag */
if (argv[*optind][optchr] == ':') if (argv[*optind][optchr] == ':')
{ {
dash = 0; dash = 0;
(*optind)++; (*optind)++;
return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRCOLON, show_err)); return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRCOLON, show_err));
}
arg_start = 1 + optchr;
} }
if (opts_idx < 0) if (opts_idx < 0)
@ -135,6 +143,7 @@ int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct *opts, char **o
else else
{ {
optchr++; optchr++;
arg_start++;
} }
return (mbo_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err)); return (mbo_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
@ -173,7 +182,7 @@ int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct *opts, char **o
} }
else else
{ {
if (arg_start == 2) if (arg_start >= 2 && !((argv[*optind][0] == '-') && (argv[*optind][1] == '-')))
{ {
if (!argv[*optind][optchr + 1]) if (!argv[*optind][optchr + 1])
{ {

File diff suppressed because it is too large Load diff

View file

@ -19,11 +19,6 @@ public:
static Symbol *find(const SubStr&); static Symbol *find(const SubStr&);
static void ClearTable(); static void ClearTable();
~Symbol()
{
/** \todo should we delete 're'? */
}
typedef std::map<std::string, Symbol*> SymbolTable; typedef std::map<std::string, Symbol*> SymbolTable;
protected: protected:

View file

@ -28,7 +28,7 @@ void yyerror(const char*);
static re2c::uint accept; static re2c::uint accept;
static RegExp *spec; static RegExp *spec;
static Scanner *in; static Scanner *in = NULL;
/* Bison version 1.875 emits a definition that is not working /* Bison version 1.875 emits a definition that is not working
* with several g++ version. Hence we disable it here. * with several g++ version. Hence we disable it here.
@ -92,14 +92,12 @@ decl : ID '=' expr ';'
{ if($1->re) { if($1->re)
in->fatal("sym already defined"); in->fatal("sym already defined");
$1->re = $3; } $1->re = $3; }
| CONFIG '=' VALUE ';' | ID '=' expr '/'
{ in->config(*$1, *$3); }
| CONFIG '=' NUMBER ';'
{ in->config(*$1, $3); }
;
decl : ID '=' expr '/'
{ in->fatal("trailing contexts are not allowed in named definitions"); } { in->fatal("trailing contexts are not allowed in named definitions"); }
| CONFIG '=' VALUE ';'
{ in->config(*$1, *$3); delete $1; delete $3; }
| CONFIG '=' NUMBER ';'
{ in->config(*$1, $3); delete $1; }
; ;
rule : expr look CODE rule : expr look CODE
@ -182,7 +180,7 @@ void yyerror(const char* s)
} }
int yylex(){ int yylex(){
return in->scan(); return in ? in->scan() : 0;
} }
} // end extern "C" } // end extern "C"
@ -193,9 +191,13 @@ void parse(Scanner& i, std::ostream& o)
{ {
in = &i; in = &i;
o << "/* Generated by re2c " PACKAGE_VERSION " on "; o << "/* Generated by re2c " PACKAGE_VERSION;
time_t now = time(&now); if (!bNoGenerationDate)
o.write(ctime(&now), 24); {
o << " on ";
time_t now = time(&now);
o.write(ctime(&now), 24);
}
o << " */\n"; o << " */\n";
o << sourceFileInfo; o << sourceFileInfo;
@ -208,6 +210,11 @@ void parse(Scanner& i, std::ostream& o)
} }
o << sourceFileInfo; o << sourceFileInfo;
} }
RegExp::vFreeList.clear();
Range::vFreeList.clear();
Symbol::ClearTable();
in = NULL;
} }
} // end namespace re2c } // end namespace re2c

View file

@ -3,6 +3,7 @@
#define _re_h #define _re_h
#include <iostream> #include <iostream>
#include <set>
#include "token.h" #include "token.h"
#include "ins.h" #include "ins.h"
#include "globals.h" #include "globals.h"
@ -10,6 +11,51 @@
namespace re2c namespace re2c
{ {
template<class _Ty>
class free_list: protected std::set<_Ty>
{
public:
typedef typename std::set<_Ty>::iterator iterator;
typedef typename std::set<_Ty>::size_type size_type;
typedef typename std::set<_Ty>::key_type key_type;
free_list(): in_clear(false)
{
}
using std::set<_Ty>::insert;
size_type erase(const key_type& key)
{
if (!in_clear)
{
return std::set<_Ty>::erase(key);
}
return 0;
}
void clear()
{
in_clear = true;
for(iterator it = this->begin(); it != this->end(); ++it)
{
delete *it;
}
std::set<_Ty>::clear();
in_clear = false;
}
~free_list()
{
clear();
}
protected:
bool in_clear;
};
typedef struct extop typedef struct extop
{ {
char op; char op;
@ -46,12 +92,18 @@ public:
Range *next; Range *next;
uint lb, ub; // [lb,ub) uint lb, ub; // [lb,ub)
static free_list<Range*> vFreeList;
public: public:
Range(uint l, uint u) : next(NULL), lb(l), ub(u) Range(uint l, uint u) : next(NULL), lb(l), ub(u)
{ } {
vFreeList.insert(this);
}
Range(Range &r) : next(NULL), lb(r.lb), ub(r.ub) Range(Range &r) : next(NULL), lb(r.lb), ub(r.ub)
{ } {
vFreeList.insert(this);
}
friend std::ostream& operator<<(std::ostream&, const Range&); friend std::ostream& operator<<(std::ostream&, const Range&);
friend std::ostream& operator<<(std::ostream&, const Range*); friend std::ostream& operator<<(std::ostream&, const Range*);
@ -68,12 +120,18 @@ class RegExp
public: public:
uint size; uint size;
static free_list<RegExp*> vFreeList;
public: public:
RegExp() : size(0) RegExp() : size(0)
{ {
} }
virtual ~RegExp() {} virtual ~RegExp()
{
vFreeList.erase(this);
}
virtual const char *typeOf() = 0; virtual const char *typeOf() = 0;
RegExp *isA(const char *t) RegExp *isA(const char *t)
{ {
@ -178,6 +236,12 @@ public:
public: public:
RuleOp(RegExp*, RegExp*, Token*, uint); RuleOp(RegExp*, RegExp*, Token*, uint);
~RuleOp()
{
delete code;
}
const char *typeOf() const char *typeOf()
{ {
return type; return type;
@ -228,6 +292,8 @@ public:
const RuleOp& op; const RuleOp& op;
}; };
RegExp *mkAlt(RegExp*, RegExp*);
class AltOp: public RegExp class AltOp: public RegExp
{ {

View file

@ -487,6 +487,10 @@
RelativePath=".\code.h" RelativePath=".\code.h"
> >
</File> </File>
<File
RelativePath=".\code_names.h"
>
</File>
<File <File
RelativePath=".\config_w32.h" RelativePath=".\config_w32.h"
> >

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,8 @@ private:
public: public:
Scanner(const char*, std::istream&, std::ostream&); Scanner(const char*, std::istream&, std::ostream&);
~Scanner();
int echo(); int echo();
int scan(); int scan();
@ -66,7 +68,7 @@ inline SubStr Scanner::token() const
inline uint Scanner::xlat(uint c) const inline uint Scanner::xlat(uint c) const
{ {
return re2c::wFlag ? c : re2c::xlat[c]; return re2c::wFlag ? c : re2c::xlat[c & 0xFF];
} }
} // end namespace re2c } // end namespace re2c

Some files were not shown because too many files have changed in this diff Show more