From 0c850e8ddd5fe5c4ae70593d25404e094b17cae2 Mon Sep 17 00:00:00 2001 From: slatenails Date: Sun, 28 Jul 2013 14:58:30 +0300 Subject: [PATCH 001/247] Results for console tab-completion are now color-coded. CCMDs appear blue, CVars green and aliases red. --- src/c_console.cpp | 15 ++++++++++++++- src/c_dispatch.cpp | 5 +++++ src/c_dispatch.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 170cc97d4..0ecd600e4 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -2121,7 +2121,20 @@ static bool C_TabCompleteList () Printf (TEXTCOLOR_BLUE "Completions for %s:\n", CmdLine+2); for (i = TabPos; nummatches > 0; ++i, --nummatches) { - Printf ("%-*s", int(maxwidth), TabCommands[i].TabName.GetChars()); + // [Dusk] Print console commands blue, CVars green, aliases red. + const char* colorcode = ""; + FConsoleCommand* ccmd; + if (FindCVar (TabCommands[i].TabName, NULL)) + colorcode = "\\c[Green]"; + else if ((ccmd = FConsoleCommand::FindByName (TabCommands[i].TabName)) != NULL) + { + if (ccmd->IsAlias()) + colorcode = "\\c[Red]"; + else + colorcode = "\\c[Light Blue]"; + } + + Printf ("%s%-*s", strbin1 (colorcode).GetChars(), int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; if (x > ConCols - maxwidth) { diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index d25354986..76b6e395d 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -955,6 +955,11 @@ bool FConsoleCommand::AddToHash (FConsoleCommand **table) return true; } +FConsoleCommand* FConsoleCommand::FindByName (const char* name) +{ + return FindNameInHashTable (Commands, name, strlen (name)); +} + FConsoleCommand::FConsoleCommand (const char *name, CCmdRun runFunc) : m_RunFunc (runFunc) { diff --git a/src/c_dispatch.h b/src/c_dispatch.h index 12ea559de..96dc50644 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -93,6 +93,7 @@ public: void PrintCommand () { Printf ("%s\n", m_Name); } virtual void Run (FCommandLine &args, APlayerPawn *instigator, int key); + static FConsoleCommand* FindByName (const char* name); FConsoleCommand *m_Next, **m_Prev; char *m_Name; From 6dee878b2e29fc6107c81b5b76ab5b72fa4bf05b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 28 Jul 2013 17:15:47 +0200 Subject: [PATCH 002/247] - used TEXTCOLOR_ #defines for colorizing CCMD list, remove use of strbin1. --- src/c_console.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index 0ecd600e4..e5d3d97ab 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -2125,16 +2125,16 @@ static bool C_TabCompleteList () const char* colorcode = ""; FConsoleCommand* ccmd; if (FindCVar (TabCommands[i].TabName, NULL)) - colorcode = "\\c[Green]"; + colorcode = TEXTCOLOR_GREEN; else if ((ccmd = FConsoleCommand::FindByName (TabCommands[i].TabName)) != NULL) { if (ccmd->IsAlias()) - colorcode = "\\c[Red]"; + colorcode = TEXTCOLOR_RED; else - colorcode = "\\c[Light Blue]"; + colorcode = TEXTCOLOR_LIGHTBLUE; } - Printf ("%s%-*s", strbin1 (colorcode).GetChars(), int(maxwidth), TabCommands[i].TabName.GetChars()); + Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; if (x > ConCols - maxwidth) { From c4af738bf6b0d7f093ccdb0b060a04b8c4ff0cad Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 29 Jul 2013 18:30:26 -0400 Subject: [PATCH 003/247] - Fixed: crash when closing ZDoom in the save menu and a memory leak. --- src/menu/loadsavemenu.cpp | 3 ++- src/sdl/i_system.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 20779a221..9a87bb806 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -131,7 +131,8 @@ void ClearSaveGames() { for(unsigned i=0;ibNoDelete) + delete DLoadSaveMenu::SaveGames[i]; } DLoadSaveMenu::SaveGames.Clear(); } diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 292da5930..def35606a 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -749,6 +749,8 @@ int I_FindClose (void *handle) findstate_t *state = (findstate_t *)handle; if (handle != (void*)-1 && state->count > 0) { + for(int i = 0;i < state->count;++i) + free (state->namelist[i]); state->count = 0; free (state->namelist); state->namelist = NULL; From 81334809c4340c5332a53af83f6bcb5851e514b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 30 Jul 2013 09:32:33 +0200 Subject: [PATCH 004/247] - changed autoloading of *.deh lumps: it is now controlled by a CVAR with 3 options: never load *.deh lumps, load all of them or only load the last one. *.deh loading is disabled by default. --- src/d_dehacked.cpp | 44 ++++++++++++++++++++++++++------------- wadsrc/static/menudef.txt | 8 +++++++ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 82ba21eba..eb4e2fcd6 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2329,6 +2329,18 @@ static int DoInclude (int dummy) return GetLine(); } +CVAR(Int, dehload, 0, CVAR_ARCHIVE) // Autoloading of .DEH lumps is disabled by default. + +// checks if lump is a .deh or .bex file. Only lumps in the root directory are considered valid. +static bool isDehFile(int lumpnum) +{ + const char* const fullName = Wads.GetLumpFullName(lumpnum); + const char* const extension = strrchr(fullName, '.'); + + return NULL != extension && strchr(fullName, '/') == NULL + && (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex")); +} + int D_LoadDehLumps() { int lastlump = 0, lumpnum, count = 0; @@ -2338,28 +2350,32 @@ int D_LoadDehLumps() count += D_LoadDehLump(lumpnum); } -#if 0 // commented out for 'maint' version. - if (0 == PatchSize) + if (0 == PatchSize && dehload > 0) { // No DEH/BEX patch is loaded yet, try to find lump(s) with specific extensions - for (lumpnum = 0, lastlump = Wads.GetNumLumps(); - lumpnum < lastlump; - ++lumpnum) + if (dehload == 1) // load all .DEH lumps that are found. { - const char* const fullName = Wads.GetLumpFullName(lumpnum); - const char* const extension = strrchr(fullName, '.'); - - const bool isDehOrBex = NULL != extension - && (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex")); - - if (isDehOrBex) + for (lumpnum = 0, lastlump = Wads.GetNumLumps(); lumpnum < lastlump; ++lumpnum) { - count += D_LoadDehLump(lumpnum); + if (isDehFile(lumpnum)) + { + count += D_LoadDehLump(lumpnum); + } + } + } + else // only load the last .DEH lump that is found. + { + for (lumpnum = Wads.GetNumLumps()-1; lumpnum >=0; --lumpnum) + { + if (isDehFile(lumpnum)) + { + count += D_LoadDehLump(lumpnum); + break; + } } } } -#endif return count; } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 21f19c106..12201e379 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -850,6 +850,13 @@ OptionValue Autosave 2, "Never" } +OptionValue dehopt +{ + 0, "Never" + 1, "All" + 2, "Only last one" +} + OptionMenu "MiscOptions" { Title "Miscellaneous Options" @@ -864,6 +871,7 @@ OptionMenu "MiscOptions" Option "Enable cheats from all games", "allcheats", "OnOff" Option "Enable autosaves", "disableautosave", "Autosave" Slider "Number of autosaves", "autosavecount", 1, 20, 1, 0 + Option "Load *.deh/*.bex lumps", "dehload", "dehopt" StaticText " " Option "Cache nodes", "gl_cachenodes", "OnOff" Slider "Time threshold for node caching", "gl_cachetime", 0.0, 2.0, 0.1 From 4ce0574b3f562c25f30d1dd5f8a6af835a1eb0de Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Tue, 30 Jul 2013 11:45:42 +0200 Subject: [PATCH 005/247] - Use a more conformant C++ preprocessor macro identifier for Unix systems. The 'unix' identifier isn't defined when '-std' is passed to the compiler (tested with gcc and clang), so use '__unix__' which is well enough documented. --- src/b_game.cpp | 2 +- src/c_console.cpp | 2 +- src/c_dispatch.cpp | 2 +- src/ct_chat.cpp | 2 +- src/d_main.cpp | 8 ++++---- src/g_game.cpp | 4 ++-- src/gameconfigfile.cpp | 6 +++--- src/m_misc.cpp | 6 +++--- src/menu/loadsavemenu.cpp | 2 +- src/menu/menudef.cpp | 2 +- src/sound/fmodsound.cpp | 2 +- src/sound/music_fluidsynth_mididevice.cpp | 4 ++-- src/timidity/instrum.cpp | 2 +- src/version.h | 2 +- 14 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/b_game.cpp b/src/b_game.cpp index a4c0a1842..ed3a5c848 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -505,7 +505,7 @@ bool FCajunMaster::LoadBots () bool gotteam = false; bglobal.ForgetBots (); -#ifndef unix +#ifndef __unix__ tmp = progdir; tmp += "zcajun/" BOTFILENAME; if (!FileExists (tmp)) diff --git a/src/c_console.cpp b/src/c_console.cpp index e5d3d97ab..0c02d0489 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1742,7 +1742,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) } break; -#ifdef unix +#ifdef __unix__ case EV_GUI_MButtonDown: C_PasteText(I_GetFromClipboard(true), buffer, len); break; diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 76b6e395d..88dbc5d64 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -1506,7 +1506,7 @@ CCMD (pullin) { const char *lastSlash; -#ifdef unix +#ifdef __unix__ lastSlash = strrchr (PullinFile, '/'); #else const char *lastSlash1, *lastSlash2; diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index d99acda42..c0c1f13f0 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -169,7 +169,7 @@ bool CT_Responder (event_t *ev) } return true; } -#ifdef unix +#ifdef __unix__ else if (ev->subtype == EV_GUI_MButtonDown) { CT_PasteChat(I_GetFromClipboard(true)); diff --git a/src/d_main.cpp b/src/d_main.cpp index 6c92babe4..5e67b69dd 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -38,7 +38,7 @@ #endif #include -#if defined(unix) || defined(__APPLE__) +#if defined(__unix__) || defined(__APPLE__) #include #endif @@ -2009,7 +2009,7 @@ static void AddAutoloadFiles(const char *gamesection) D_AddFile (allwads, wad); // [RH] Add any .wad files in the skins directory -#ifdef unix +#ifdef __unix__ file = SHARE_DIR; #else file = progdir; @@ -2017,7 +2017,7 @@ static void AddAutoloadFiles(const char *gamesection) file += "skins"; D_AddDirectory (allwads, file); -#ifdef unix +#ifdef __unix__ file = NicePath("~/" GAME_DIR "/skins"); D_AddDirectory (allwads, file); #endif @@ -2137,7 +2137,7 @@ static void CheckCmdLine() Printf ("%s", GStrings("D_DEVSTR")); } -#if !defined(unix) && !defined(__APPLE__) +#if !defined(__unix__) && !defined(__APPLE__) // We do not need to support -cdrom under Unix, because all the files // that would go to c:\\zdoomdat are already stored in .zdoom inside // the user's home directory. diff --git a/src/g_game.cpp b/src/g_game.cpp index 506b8e24b..79cd4b233 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1919,7 +1919,7 @@ FString G_BuildSaveName (const char *prefix, int slot) leader = Args->CheckValue ("-savedir"); if (leader.IsEmpty()) { -#if !defined(unix) && !defined(__APPLE__) +#if !defined(__unix__) && !defined(__APPLE__) if (Args->CheckParm ("-cdrom")) { leader = CDROM_DIR "/"; @@ -1931,7 +1931,7 @@ FString G_BuildSaveName (const char *prefix, int slot) } if (leader.IsEmpty()) { -#ifdef unix +#ifdef __unix__ leader = "~/" GAME_DIR; #elif defined(__APPLE__) char cpath[PATH_MAX]; diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 5c6fb0ce2..211ef96c6 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -135,7 +135,7 @@ FGameConfigFile::FGameConfigFile () local_app_support << cpath << "/" GAME_DIR; SetValueForKey("Path", local_app_support, true); } -#elif !defined(unix) +#elif !defined(__unix__) SetValueForKey ("Path", "$HOME", true); SetValueForKey ("Path", "$PROGDIR", true); #else @@ -153,7 +153,7 @@ FGameConfigFile::FGameConfigFile () SetValueForKey ("Path", user_app_support, true); SetValueForKey ("Path", "$PROGDIR", true); SetValueForKey ("Path", local_app_support, true); -#elif !defined(unix) +#elif !defined(__unix__) SetValueForKey ("Path", "$PROGDIR", true); #else SetValueForKey ("Path", "~/" GAME_DIR, true); @@ -683,7 +683,7 @@ void FGameConfigFile::CreateStandardAutoExec(const char *section, bool start) { path << cpath << "/" GAME_DIR "/autoexec.cfg"; } -#elif !defined(unix) +#elif !defined(__unix__) path = "$PROGDIR/autoexec.cfg"; #else path = GetUserFile ("autoexec.cfg"); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index a8c6b7380..e218cadc4 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -333,7 +333,7 @@ static long ParseCommandLine (const char *args, int *argc, char **argv) } -#if defined(unix) +#if defined(__unix__) FString GetUserFile (const char *file) { FString path; @@ -698,7 +698,7 @@ void M_ScreenShot (const char *filename) // find a file name to save it to if (filename == NULL || filename[0] == '\0') { -#if !defined(unix) && !defined(__APPLE__) +#if !defined(__unix__) && !defined(__APPLE__) if (Args->CheckParm ("-cdrom")) { autoname = CDROM_DIR "\\"; @@ -715,7 +715,7 @@ void M_ScreenShot (const char *filename) dirlen = autoname.Len(); if (dirlen == 0) { -#ifdef unix +#ifdef __unix__ autoname = "~/" GAME_DIR "/screenshots/"; #elif defined(__APPLE__) char cpath[PATH_MAX]; diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 9a87bb806..f16e1cbc2 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -345,7 +345,7 @@ void DLoadSaveMenu::NotifyNewSave (const char *file, const char *title, bool okF for (unsigned i=0; iFilename.Compare (file) == 0) #else if (node->Filename.CompareNoCase (file) == 0) diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 00af179a5..616bdf2ca 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -158,7 +158,7 @@ static bool CheckSkipOptionBlock(FScanner &sc) } else if (sc.Compare("unix")) { - #ifdef unix + #ifdef __unix__ filter = true; #endif } diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index c21ba4054..f832183c0 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -816,7 +816,7 @@ bool FMODSoundRenderer::Init() } result = Sys->getNumDrivers(&driver); -#ifdef unix +#ifdef __unix__ if (result == FMOD_OK) { // On Linux, FMOD defaults to OSS. If OSS is not present, it doesn't diff --git a/src/sound/music_fluidsynth_mididevice.cpp b/src/sound/music_fluidsynth_mididevice.cpp index 53a93fe09..af8fe6667 100644 --- a/src/sound/music_fluidsynth_mididevice.cpp +++ b/src/sound/music_fluidsynth_mididevice.cpp @@ -295,7 +295,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice() fluid_chorus_speed, fluid_chorus_depth, fluid_chorus_type); if (0 == LoadPatchSets(fluid_patchset)) { -#ifdef unix +#ifdef __unix__ // This is the standard location on Ubuntu. if (0 == LoadPatchSets("/usr/share/sounds/sf2/FluidR3_GS.sf2:/usr/share/sounds/sf2/FluidR3_GM.sf2")) { @@ -322,7 +322,7 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice() } } #endif -#ifdef unix +#ifdef __unix__ } #endif } diff --git a/src/timidity/instrum.cpp b/src/timidity/instrum.cpp index 55683cb4e..5ab55201e 100644 --- a/src/timidity/instrum.cpp +++ b/src/timidity/instrum.cpp @@ -166,7 +166,7 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss tmp += ".pat"; if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) { -#ifdef unix // Windows isn't case-sensitive. +#ifdef __unix__ // Windows isn't case-sensitive. tmp.ToUpper(); if ((fp = open_filereader(tmp, openmode, NULL)) == NULL) #endif diff --git a/src/version.h b/src/version.h index 8bdd8ca81..a5bf7be29 100644 --- a/src/version.h +++ b/src/version.h @@ -91,7 +91,7 @@ const char *GetVersionString(); #define FORUM_URL "http://forum.zdoom.org" #define BUGS_FORUM_URL "http://forum.zdoom.org/index.php?c=3" -#ifdef unix +#ifdef __unix__ #define GAME_DIR ".config/zdoom" #elif defined(__APPLE__) #define GAME_DIR GAMENAME From 8cab8f180b2f80918c315a460f2e43e7aa2933a8 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 31 Jul 2013 12:15:33 +0200 Subject: [PATCH 006/247] - Be clear about the safe 'memset/memcpy' operations on virtual classes. Since I remember that 'memset/memcpy' is safe in this code, it should be okay to cast to the generic pointer all the 'virtual class' arguments before calling the above functions. Shuts up Clang warnings. --- src/d_dehacked.cpp | 2 +- src/decallib.cpp | 2 +- src/thingdef/thingdef_properties.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index eb4e2fcd6..d01e9513f 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -2945,7 +2945,7 @@ void FinishDehPatch () PClass *subclass = RUNTIME_CLASS(ADehackedPickup)->CreateDerivedClass (typeNameBuilder, sizeof(ADehackedPickup)); AActor *defaults2 = GetDefaultByType (subclass); - memcpy (defaults2, defaults1, sizeof(AActor)); + memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor)); // Make a copy of the replaced class's state labels FStateDefinitions statedef; diff --git a/src/decallib.cpp b/src/decallib.cpp index c8fe6c593..91827409b 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -452,7 +452,7 @@ void FDecalLib::ParseDecal (FScanner &sc) decalNum = GetDecalID (sc); sc.MustGetStringName ("{"); - memset (&newdecal, 0, sizeof(newdecal)); + memset ((void *)&newdecal, 0, sizeof(newdecal)); newdecal.PicNum.SetInvalid(); newdecal.ScaleX = newdecal.ScaleY = FRACUNIT; newdecal.RenderFlags = RF_WALLSPRITE; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 61a18b370..7b922df02 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -433,7 +433,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor) return; } - memcpy (defaults, GetDefault(), sizeof(AActor)); + memcpy ((void *)defaults, (void *)GetDefault(), sizeof(AActor)); if (bag.DropItemList != NULL) { FreeDropItemChain (bag.DropItemList); From 0dc70f847c5826b384bc694fd65739d964210fc7 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 31 Jul 2013 12:26:47 +0200 Subject: [PATCH 007/247] - Be more compatible with C++11 narrowing conversions system. --- src/d_dehacked.cpp | 30 +++++++++++++++--------------- src/thingdef/thingdef.h | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index d01e9513f..e6376a589 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1755,21 +1755,21 @@ static int PatchCheats (int dummy) static int PatchMisc (int dummy) { static const struct Key keys[] = { - { "Initial Health", myoffsetof(struct DehInfo,StartHealth) }, - { "Initial Bullets", myoffsetof(struct DehInfo,StartBullets) }, - { "Max Health", myoffsetof(struct DehInfo,MaxHealth) }, - { "Max Armor", myoffsetof(struct DehInfo,MaxArmor) }, - { "Green Armor Class", myoffsetof(struct DehInfo,GreenAC) }, - { "Blue Armor Class", myoffsetof(struct DehInfo,BlueAC) }, - { "Max Soulsphere", myoffsetof(struct DehInfo,MaxSoulsphere) }, - { "Soulsphere Health", myoffsetof(struct DehInfo,SoulsphereHealth) }, - { "Megasphere Health", myoffsetof(struct DehInfo,MegasphereHealth) }, - { "God Mode Health", myoffsetof(struct DehInfo,GodHealth) }, - { "IDFA Armor", myoffsetof(struct DehInfo,FAArmor) }, - { "IDFA Armor Class", myoffsetof(struct DehInfo,FAAC) }, - { "IDKFA Armor", myoffsetof(struct DehInfo,KFAArmor) }, - { "IDKFA Armor Class", myoffsetof(struct DehInfo,KFAAC) }, - { "No Autofreeze", myoffsetof(struct DehInfo,NoAutofreeze) }, + { "Initial Health", static_cast(myoffsetof(struct DehInfo,StartHealth)) }, + { "Initial Bullets", static_cast(myoffsetof(struct DehInfo,StartBullets)) }, + { "Max Health", static_cast(myoffsetof(struct DehInfo,MaxHealth)) }, + { "Max Armor", static_cast(myoffsetof(struct DehInfo,MaxArmor)) }, + { "Green Armor Class", static_cast(myoffsetof(struct DehInfo,GreenAC)) }, + { "Blue Armor Class", static_cast(myoffsetof(struct DehInfo,BlueAC)) }, + { "Max Soulsphere", static_cast(myoffsetof(struct DehInfo,MaxSoulsphere)) }, + { "Soulsphere Health", static_cast(myoffsetof(struct DehInfo,SoulsphereHealth)) }, + { "Megasphere Health", static_cast(myoffsetof(struct DehInfo,MegasphereHealth)) }, + { "God Mode Health", static_cast(myoffsetof(struct DehInfo,GodHealth)) }, + { "IDFA Armor", static_cast(myoffsetof(struct DehInfo,FAArmor)) }, + { "IDFA Armor Class", static_cast(myoffsetof(struct DehInfo,FAAC)) }, + { "IDKFA Armor", static_cast(myoffsetof(struct DehInfo,KFAArmor)) }, + { "IDKFA Armor Class", static_cast(myoffsetof(struct DehInfo,KFAAC)) }, + { "No Autofreeze", static_cast(myoffsetof(struct DehInfo,NoAutofreeze)) }, { NULL, 0 } }; int result; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 08264e0a8..63d04ea29 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -354,11 +354,11 @@ int MatchString (const char *in, const char **strings); MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; #define DEFINE_MEMBER_VARIABLE(name, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, name), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, static_cast(myoffsetof(cls, name)), RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; #define DEFINE_MEMBER_VARIABLE_ALIAS(name, alias, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, alias), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, static_cast(myoffsetof(cls, alias)), RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; From d77673d68102d5102c37e04d49dbe6fc031fd75b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 31 Jul 2013 22:59:35 +0200 Subject: [PATCH 008/247] - reorganization of automap color handling for easier maintenance Mostly preparation to implement a per-mod automap option but also fixes a few minor issues with some colors that are not defined in the original game specific colorsets. --- src/am_map.cpp | 655 +++++++++++++++++++++++++++++-------------------- 1 file changed, 386 insertions(+), 269 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 8a4d1cc36..466fe36ab 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -68,97 +68,13 @@ #include "a_keys.h" #include "r_data/colormaps.h" -//============================================================================= -// -// Automap colors -// -//============================================================================= - -struct AMColor -{ - int Index; - uint32 RGB; - - void FromCVar(FColorCVar & cv) - { - Index = cv.GetIndex(); - RGB = uint32(cv) | MAKEARGB(255, 0, 0, 0); - } - - void FromRGB(int r,int g, int b) - { - RGB = MAKEARGB(255, r, g, b); - Index = ColorMatcher.Pick(r, g, b); - } -}; - -static AMColor Background, YourColor, WallColor, TSWallColor, - FDWallColor, CDWallColor, EFWallColor, ThingColor, - ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, ThingColor_Friend, - SpecialWallColor, SecretWallColor, GridColor, XHairColor, - NotSeenColor, - LockedColor, - AlmostBackground, - IntraTeleportColor, InterTeleportColor, - SecretSectorColor; - -static AMColor DoomColors[11]; -static BYTE DoomPaletteVals[11*3] = -{ - 0x00,0x00,0x00, 0xff,0xff,0xff, 0x10,0x10,0x10, - 0xfc,0x00,0x00, 0x80,0x80,0x80, 0xbc,0x78,0x48, - 0xfc,0xfc,0x00, 0x74,0xfc,0x6c, 0x4c,0x4c,0x4c, - 0x80,0x80,0x80, 0x6c,0x6c,0x6c -}; - -static AMColor StrifeColors[11]; -static BYTE StrifePaletteVals[11*3] = -{ - 0x00,0x00,0x00, 239, 239, 0, 0x10,0x10,0x10, - 199, 195, 195, 119, 115, 115, 55, 59, 91, - 119, 115, 115, 0xfc,0x00,0x00, 0x4c,0x4c,0x4c, - 187, 59, 0, 219, 171, 0 -}; - -static AMColor RavenColors[11]; -static BYTE RavenPaletteVals[11*3] = -{ - 0x6c,0x54,0x40, 255, 255, 255, 0x74,0x5c,0x48, - 75, 50, 16, 88, 93, 86, 208, 176, 133, - 103, 59, 31, 236, 236, 236, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -}; //============================================================================= // -// globals +// CVARs // //============================================================================= -#define MAPBITS 12 -#define MapDiv SafeDivScale12 -#define MapMul MulScale12 -#define MAPUNIT (1< -1; + } +}; + +//============================================================================= +// +// a complete color set +// +//============================================================================= + +struct AMColorset +{ + enum + { + Background, + YourColor, + WallColor, + TSWallColor, + FDWallColor, + CDWallColor, + EFWallColor, + ThingColor, + ThingColor_Item, + ThingColor_CountItem, + ThingColor_Monster, + ThingColor_Friend, + SpecialWallColor, + SecretWallColor, + GridColor, + XHairColor, + NotSeenColor, + LockedColor, + IntraTeleportColor, + InterTeleportColor, + SecretSectorColor, + AlmostBackgroundColor, + AM_NUM_COLORS + }; + + AMColor c[AM_NUM_COLORS]; + bool displayLocks; + bool forcebackground; + + void initFromCVars(FColorCVar **values) + { + for(int i=0;i MapArrow; static TArray CheatMapArrow; static TArray CheatKey; @@ -345,15 +576,11 @@ static mline_t square_guy[] = { -EXTERN_CVAR (Bool, sv_cheats) -CUSTOM_CVAR (Int, am_cheat, 0, 0) -{ - // No automap cheat in net games when cheats are disabled! - if (netgame && !sv_cheats && self != 0) - { - self = 0; - } -} +//============================================================================= +// +// +// +//============================================================================= static int grid = 0; @@ -563,21 +790,6 @@ void AM_StaticInit() } markpointnum = 0; mapback.SetInvalid(); - - static DWORD *lastpal = NULL; - //static int lastback = -1; - DWORD *palette; - - palette = (DWORD *)GPalette.BaseColors; - - int i, j; - - for (i = j = 0; i < 11; i++, j += 3) - { - DoomColors[i].FromRGB(DoomPaletteVals[j], DoomPaletteVals[j+1], DoomPaletteVals[j+2]); - StrifeColors[i].FromRGB(StrifePaletteVals[j], StrifePaletteVals[j+1], StrifePaletteVals[j+2]); - RavenColors[i].FromRGB(RavenPaletteVals[j], RavenPaletteVals[j+1], RavenPaletteVals[j+2]); - } } //============================================================================= @@ -913,133 +1125,28 @@ static void AM_initColors (bool overlayed) { if (overlayed) { - YourColor.FromCVar (am_ovyourcolor); - WallColor.FromCVar (am_ovwallcolor); - SpecialWallColor.FromCVar(am_ovspecialwallcolor); - SecretWallColor = WallColor; - SecretSectorColor.FromCVar (am_ovsecretsectorcolor); - ThingColor_Item.FromCVar (am_ovthingcolor_item); - ThingColor_CountItem.FromCVar (am_ovthingcolor_citem); - ThingColor_Friend.FromCVar (am_ovthingcolor_friend); - ThingColor_Monster.FromCVar (am_ovthingcolor_monster); - ThingColor.FromCVar (am_ovthingcolor); - LockedColor.FromCVar (am_ovotherwallscolor); - EFWallColor.FromCVar (am_ovefwallcolor); - FDWallColor.FromCVar (am_ovfdwallcolor); - CDWallColor.FromCVar (am_ovcdwallcolor); - TSWallColor.FromCVar (am_ovunseencolor); - NotSeenColor = TSWallColor; - InterTeleportColor.FromCVar (am_ovtelecolor); - IntraTeleportColor = InterTeleportColor; + AMColors.initFromCVars(cv_overlay); } else switch(am_colorset) { default: - { /* Use the custom colors in the am_* cvars */ - Background.FromCVar (am_backcolor); - YourColor.FromCVar (am_yourcolor); - SecretWallColor.FromCVar (am_secretwallcolor); - SpecialWallColor.FromCVar (am_specialwallcolor); - WallColor.FromCVar (am_wallcolor); - TSWallColor.FromCVar (am_tswallcolor); - FDWallColor.FromCVar (am_fdwallcolor); - CDWallColor.FromCVar (am_cdwallcolor); - EFWallColor.FromCVar (am_efwallcolor); - ThingColor_Item.FromCVar (am_thingcolor_item); - ThingColor_CountItem.FromCVar (am_thingcolor_citem); - ThingColor_Friend.FromCVar (am_thingcolor_friend); - ThingColor_Monster.FromCVar (am_thingcolor_monster); - ThingColor.FromCVar (am_thingcolor); - GridColor.FromCVar (am_gridcolor); - XHairColor.FromCVar (am_xhaircolor); - NotSeenColor.FromCVar (am_notseencolor); - LockedColor.FromCVar (am_lockedcolor); - InterTeleportColor.FromCVar (am_interlevelcolor); - IntraTeleportColor.FromCVar (am_intralevelcolor); - SecretSectorColor.FromCVar (am_secretsectorcolor); - - DWORD ba = am_backcolor; - - int r = RPART(ba) - 16; - int g = GPART(ba) - 16; - int b = BPART(ba) - 16; - - if (r < 0) - r += 32; - if (g < 0) - g += 32; - if (b < 0) - b += 32; - - AlmostBackground.FromRGB(r, g, b); + AMColors.initFromCVars(cv_standard); break; - } case 1: // Doom // Use colors corresponding to the original Doom's - Background = DoomColors[0]; - YourColor = DoomColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = DoomColors[3]; - TSWallColor = DoomColors[4]; - EFWallColor = FDWallColor = DoomColors[5]; - LockedColor = - CDWallColor = DoomColors[6]; - ThingColor_Item = - ThingColor_Friend = - ThingColor_Monster = - ThingColor = DoomColors[7]; - GridColor = DoomColors[8]; - XHairColor = DoomColors[9]; - NotSeenColor = DoomColors[10]; + AMColors.initFromColors(DoomColors, false); break; case 2: // Strife // Use colors corresponding to the original Strife's - Background = StrifeColors[0]; - YourColor = StrifeColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = StrifeColors[3]; - TSWallColor = StrifeColors[4]; - EFWallColor = FDWallColor = StrifeColors[5]; - LockedColor = - CDWallColor = StrifeColors[6]; - ThingColor_Item = StrifeColors[10]; - ThingColor_Friend = - ThingColor_Monster = StrifeColors[7]; - ThingColor = StrifeColors[9]; - GridColor = StrifeColors[8]; - XHairColor = DoomColors[9]; - NotSeenColor = DoomColors[10]; + AMColors.initFromColors(StrifeColors, false); break; case 3: // Raven // Use colors corresponding to the original Raven's - Background = RavenColors[0]; - YourColor = RavenColors[1]; - AlmostBackground = DoomColors[2]; - SecretSectorColor = - SecretWallColor = - SpecialWallColor = - WallColor = RavenColors[3]; - TSWallColor = RavenColors[4]; - EFWallColor = FDWallColor = RavenColors[5]; - LockedColor = - CDWallColor = RavenColors[6]; - ThingColor = - ThingColor_Item = - ThingColor_Friend = - ThingColor_Monster = RavenColors[7]; - GridColor = RavenColors[4]; - XHairColor = RavenColors[9]; - NotSeenColor = RavenColors[10]; + AMColors.initFromColors(RavenColors, true); break; } @@ -1541,13 +1648,18 @@ void AM_drawMline (mline_t *ml, const AMColor &color) } } +inline void AM_drawMline (mline_t *ml, int colorindex) +{ + AM_drawMline(ml, AMColors[colorindex]); +} + //============================================================================= // // Draws flat (floor/ceiling tile) aligned grid lines. // //============================================================================= -void AM_drawGrid (const AMColor &color) +void AM_drawGrid (int color) { fixed_t x, y; fixed_t start, end; @@ -1786,20 +1898,23 @@ void AM_drawSubsectors() static bool AM_CheckSecret(line_t *line) { - if (line->frontsector != NULL) + if (AMColors.isValid(AMColors.SecretSectorColor)) { - if (line->frontsector->secretsector) + if (line->frontsector != NULL) { - if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (line->frontsector->secretsector) + { + if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + } } - } - if (line->backsector != NULL) - { - if (line->backsector->secretsector) + if (line->backsector != NULL) { - if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (line->backsector->secretsector) + { + if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + } } } return false; @@ -1982,39 +2097,42 @@ void AM_drawWalls (bool allmap) if (AM_CheckSecret(&lines[i])) { // map secret sectors like Boom - AM_drawMline(&l, SecretSectorColor); + AM_drawMline(&l, AMColors.SecretSectorColor); } else if (lines[i].flags & ML_SECRET) { // secret door if (am_cheat != 0 && lines[i].backsector != NULL) - AM_drawMline(&l, SecretWallColor); + AM_drawMline(&l, AMColors.SecretWallColor); else - AM_drawMline(&l, WallColor); - } else if (lines[i].locknumber > 0) { // [Dusk] specials w/ locknumbers + AM_drawMline(&l, AMColors.WallColor); + } + else if (lines[i].locknumber > 0 && AMColors.displayLocks) + { // [Dusk] specials w/ locknumbers lock = lines[i].locknumber; color = P_GetMapColorForLock(lock); AMColor c; if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); - else c = LockedColor; + else c = AMColors[AMColors.LockedColor]; AM_drawMline (&l, c); - } else if ((lines[i].special == Teleport || + } + else if ((lines[i].special == Teleport || lines[i].special == Teleport_NoFog || lines[i].special == Teleport_ZombieChanger || lines[i].special == Teleport_Line) && (lines[i].activation & SPAC_PlayerActivate) && - am_colorset == 0) + AMColors.isValid(AMColors.IntraTeleportColor)) { // intra-level teleporters - AM_drawMline(&l, IntraTeleportColor); + AM_drawMline(&l, AMColors.IntraTeleportColor); } else if ((lines[i].special == Teleport_NewMap || lines[i].special == Teleport_EndGame || lines[i].special == Exit_Normal || lines[i].special == Exit_Secret) && - am_colorset == 0) + AMColors.isValid(AMColors.InterTeleportColor)) { // inter-level/game-ending teleporters - AM_drawMline(&l, InterTeleportColor); + AM_drawMline(&l, AMColors.InterTeleportColor); } else if (lines[i].special == Door_LockedRaise || lines[i].special == ACS_LockedExecute || @@ -2022,7 +2140,7 @@ void AM_drawWalls (bool allmap) (lines[i].special == Door_Animated && lines[i].args[3] != 0) || (lines[i].special == Generic_Door && lines[i].args[4] != 0)) { - if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors + if (AMColors.displayLocks) { int P_GetMapColorForLock(int lock); @@ -2035,16 +2153,16 @@ void AM_drawWalls (bool allmap) AMColor c; if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color)); - else c = LockedColor; + else c = AMColors[AMColors.LockedColor]; AM_drawMline (&l, c); } else { - AM_drawMline (&l, LockedColor); // locked special + AM_drawMline (&l, AMColors.LockedColor); // locked special } } - else if (am_showtriggerlines && am_colorset == 0 && lines[i].special != 0 + else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor) && lines[i].special != 0 && lines[i].special != Door_Open && lines[i].special != Door_Close && lines[i].special != Door_CloseWaitOpen @@ -2053,31 +2171,31 @@ void AM_drawWalls (bool allmap) && lines[i].special != Generic_Door && (lines[i].activation & SPAC_PlayerActivate)) { - AM_drawMline(&l, SpecialWallColor); // wall with special non-door action the player can do + AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do } else if (lines[i].backsector == NULL) { - AM_drawMline(&l, WallColor); // one-sided wall + AM_drawMline(&l, AMColors.WallColor); // one-sided wall } else if (lines[i].backsector->floorplane != lines[i].frontsector->floorplane) { - AM_drawMline(&l, FDWallColor); // floor level change + AM_drawMline(&l, AMColors.FDWallColor); // floor level change } else if (lines[i].backsector->ceilingplane != lines[i].frontsector->ceilingplane) { - AM_drawMline(&l, CDWallColor); // ceiling level change + AM_drawMline(&l, AMColors.CDWallColor); // ceiling level change } #ifdef _3DFLOORS else if (AM_Check3DFloors(&lines[i])) { - AM_drawMline(&l, EFWallColor); // Extra floor border + AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border } #endif else if (am_cheat != 0) { - AM_drawMline(&l, TSWallColor); + AM_drawMline(&l, AMColors.TSWallColor); } } else if (allmap) @@ -2089,7 +2207,7 @@ void AM_drawWalls (bool allmap) continue; } } - AM_drawMline(&l, NotSeenColor); + AM_drawMline(&l, AMColors.NotSeenColor); } } } @@ -2239,7 +2357,7 @@ void AM_drawPlayers () arrow = &MapArrow[0]; numarrowlines = MapArrow.Size(); } - AM_drawLineCharacter(arrow, numarrowlines, 0, angle, YourColor, pt.x, pt.y); + AM_drawLineCharacter(arrow, numarrowlines, 0, angle, AMColors[AMColors.YourColor], pt.x, pt.y); return; } @@ -2266,7 +2384,7 @@ void AM_drawPlayers () if (p->mo->alpha < OPAQUE) { - color = AlmostBackground; + color = AMColors[AMColors.AlmostBackgroundColor]; } else { @@ -2322,7 +2440,6 @@ void AM_drawKeys () angle += ANG90 - players[consoleplayer].camera->angle; } - color = ThingColor; if (key->flags & MF_SPECIAL) { // Find the key's own color. @@ -2332,7 +2449,7 @@ void AM_drawKeys () int c = P_GetMapColorForKey(key); if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); - else color = ThingColor_CountItem; + else color = AMColors[AMColors.ThingColor_CountItem]; AM_drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0, color, p.x, p.y); } } @@ -2402,13 +2519,13 @@ void AM_drawThings () angle += ANG90 - players[consoleplayer].camera->angle; } - color = ThingColor; + color = AMColors[AMColors.ThingColor]; // use separate colors for special thing types if (t->flags3&MF3_ISMONSTER && !(t->flags&MF_CORPSE)) { - if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = ThingColor_Friend; - else color = ThingColor_Monster; + if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = AMColors[AMColors.ThingColor_Friend]; + else color = AMColors[AMColors.ThingColor_Monster]; } else if (t->flags&MF_SPECIAL) { @@ -2428,19 +2545,19 @@ void AM_drawThings () int c = P_GetMapColorForKey(static_cast(t)); if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c)); - else color = ThingColor_CountItem; + else color = AMColors[AMColors.ThingColor_CountItem]; AM_drawLineCharacter(&CheatKey[0], CheatKey.Size(), 0, 0, color, p.x, p.y); color.Index = -1; } else { - color = ThingColor_Item; + color = AMColors[AMColors.ThingColor_Item]; } } else if (t->flags&MF_COUNTITEM) - color = ThingColor_CountItem; + color = AMColors[AMColors.ThingColor_CountItem]; else - color = ThingColor_Item; + color = AMColors[AMColors.ThingColor_Item]; } if (color.Index != -1) @@ -2626,7 +2743,7 @@ void AM_Drawer () f_h = ST_Y; f_p = screen->GetPitch (); - AM_clearFB(Background); + AM_clearFB(AMColors[AMColors.Background]); } else { @@ -2642,7 +2759,7 @@ void AM_Drawer () AM_drawSubsectors(); if (grid) - AM_drawGrid(GridColor); + AM_drawGrid(AMColors.GridColor); AM_drawWalls(allmap); AM_drawPlayers(); @@ -2654,7 +2771,7 @@ void AM_Drawer () AM_drawAuthorMarkers(); if (!viewactive) - AM_drawCrosshair(XHairColor); + AM_drawCrosshair(AMColors[AMColors.XHairColor]); AM_drawMarks(); From 845020c6170aa982fa885cb78615b549d3c0cabb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 31 Jul 2013 23:13:20 +0200 Subject: [PATCH 009/247] - ovthingcolors were not properly set. - added all the missing color CVARs for the overlays which previously duplicated use of one of the other CVARs. --- src/am_map.cpp | 40 +++++++++++++++++++++------------------ wadsrc/static/menudef.txt | 7 +++++-- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 466fe36ab..e2d32f737 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -87,6 +87,7 @@ CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE); CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); CVAR (Bool, am_showtriggerlines, false, CVAR_ARCHIVE); +CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); //============================================================================= // @@ -108,29 +109,32 @@ CVAR (Color, am_gridcolor, 0x8b5a2b, CVAR_ARCHIVE); CVAR (Color, am_xhaircolor, 0x808080, CVAR_ARCHIVE); CVAR (Color, am_notseencolor, 0x6c6c6c, CVAR_ARCHIVE); CVAR (Color, am_lockedcolor, 0x007800, CVAR_ARCHIVE); +CVAR (Color, am_intralevelcolor, 0x0000ff, CVAR_ARCHIVE); +CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE); +CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE); + CVAR (Color, am_ovyourcolor, 0xfce8d8, CVAR_ARCHIVE); CVAR (Color, am_ovwallcolor, 0x00ff00, CVAR_ARCHIVE); +CVAR (Color, am_ovsecretwallcolor, 0x008844, CVAR_ARCHIVE); CVAR (Color, am_ovspecialwallcolor, 0xffffff, CVAR_ARCHIVE); -CVAR (Color, am_ovthingcolor, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovotherwallscolor, 0x008844, CVAR_ARCHIVE); +CVAR (Color, am_ovlockedcolor, 0x008844, CVAR_ARCHIVE); CVAR (Color, am_ovefwallcolor, 0x008844, CVAR_ARCHIVE); CVAR (Color, am_ovfdwallcolor, 0x008844, CVAR_ARCHIVE); CVAR (Color, am_ovcdwallcolor, 0x008844, CVAR_ARCHIVE); CVAR (Color, am_ovunseencolor, 0x00226e, CVAR_ARCHIVE); CVAR (Color, am_ovtelecolor, 0xffff00, CVAR_ARCHIVE); -CVAR (Color, am_intralevelcolor, 0x0000ff, CVAR_ARCHIVE); -CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE); -CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE); +CVAR (Color, am_ovinterlevelcolor, 0xffff00, CVAR_ARCHIVE); CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); -CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); -CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); -CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); -CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_citem, 0xe88800, CVAR_ARCHIVE); -CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); //============================================================================= // @@ -293,23 +297,23 @@ static FColorCVar *cv_overlay[] = { &am_backcolor, // this will not be used in overlay mode &am_ovyourcolor, &am_ovwallcolor, - &am_ovspecialwallcolor, + &am_ovotherwallscolor, &am_ovfdwallcolor, &am_ovcdwallcolor, &am_ovefwallcolor, &am_ovthingcolor, - &am_ovthingcolor, - &am_ovthingcolor, - &am_ovthingcolor, - &am_ovthingcolor, + &am_ovthingcolor_item, + &am_ovthingcolor_citem, + &am_ovthingcolor_monster, + &am_ovthingcolor_friend, &am_ovspecialwallcolor, - &am_ovwallcolor, + &am_ovsecretwallcolor, &am_gridcolor, // this will not be used in overlay mode &am_xhaircolor, // this will not be used in overlay mode - &am_ovspecialwallcolor, - &am_ovspecialwallcolor, - &am_ovtelecolor, + &am_ovunseencolor, + &am_ovlockedcolor, &am_ovtelecolor, + &am_ovinterlevelcolor, &am_ovsecretsectorcolor }; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 6097643ba..6789c1436 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1014,12 +1014,15 @@ OptionMenu MapColorMenu ColorPicker "2-sided walls with different ceilings", "am_ovcdwallcolor" ColorPicker "2-sided walls with 3D floors", "am_ovefwallcolor" ColorPicker "Not-yet-seen walls", "am_ovunseencolor" - ColorPicker "Locked doors", "am_ovotherwallscolor" - ColorPicker "Teleporter", "am_ovtelecolor" + ColorPicker "Locked doors", "am_ovlockedcolor" + ColorPicker "Teleporter to the same map", "am_ovtelecolor" + ColorPicker "Teleporter to a different map", "am_ovinterlevelcolor" ColorPicker "Secret sector", "am_ovsecretsectorcolor" ColorPicker "Special trigger lines", "am_ovspecialwallcolor" StaticText " " StaticText "Overlay Cheat Mode", 1 + ColorPicker "Invisible 2-sided walls", "am_ovotherwallscolor" + ColorPicker "Secret walls", "am_ovsecretwallcolor" ColorPicker "Actors", "am_ovthingcolor" ColorPicker "Monsters", "am_ovthingcolor_monster" ColorPicker "Friends", "am_ovthingcolor_friend" From 5c05f1f3cd315da3f4d5509dd6ffdc760eaa35a4 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 2 Aug 2013 10:17:06 +0300 Subject: [PATCH 010/247] - Ignored dehacked.exe from *.zip files to enable loading of *.deh files. --- src/resourcefiles/file_zip.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 7e59bd35a..101b51982 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -259,6 +259,13 @@ bool FZipFile::Open(bool quiet) lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); + + // Ignore some very specific names + if (0 == stricmp("dehacked.exe", name)) + { + memset(lump_p->Name, 0, sizeof(lump_p->Name)); + } + lump_p++; } // Resize the lump record array to its actual size From aa72857c72e8b5392efa213e9e9c89c8033432b1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Aug 2013 16:56:42 +0200 Subject: [PATCH 011/247] - implemented automap color parser for MAPINFO (code not tested yet!) --- src/am_map.cpp | 119 ++++++++++++++++++++++++++++++++++++++ src/g_level.h | 1 + src/g_mapinfo.cpp | 12 ++++ wadsrc/static/menudef.txt | 1 + 4 files changed, 133 insertions(+) diff --git a/src/am_map.cpp b/src/am_map.cpp index e2d32f737..6a765cd7a 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -83,6 +83,7 @@ CVAR (Bool, am_showitems, false, CVAR_ARCHIVE); CVAR (Bool, am_showtime, true, CVAR_ARCHIVE); CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE); CVAR (Int, am_colorset, 0, CVAR_ARCHIVE); +CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE); CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE); CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); @@ -177,6 +178,32 @@ struct AMColor // //============================================================================= +static const char *ColorNames[] = { + "Background", + "YourColor", + "WallColor", + "TwoSidedWallColor", + "FloorDiffWallColor", + "CeilingDiffWallColor", + "ExtraFloorWallColor", + "ThingColor", + "ThingColor_Item", + "ThingColor_CountItem", + "ThingColor_Monster", + "ThingColor_Friend", + "SpecialWallColor", + "SecretWallColor", + "GridColor", + "XHairColor", + "NotSeenColor", + "LockedColor", + "IntraTeleportColor", + "InterTeleportColor", + "SecretSectorColor", + "AlmostBackgroundColor", + NULL +}; + struct AMColorset { enum @@ -209,6 +236,7 @@ struct AMColorset AMColor c[AM_NUM_COLORS]; bool displayLocks; bool forcebackground; + bool defined; // only for mod specific colorsets: must be true to be usable void initFromCVars(FColorCVar **values) { @@ -252,6 +280,15 @@ struct AMColorset forcebackground = false; } + void setWhite() + { + c[0].FromRGB(0,0,0); + for(int i=1; i Date: Fri, 2 Aug 2013 18:15:39 +0200 Subject: [PATCH 012/247] - fixed typo in MENUDEFS. --- wadsrc/static/menudef.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index c722384bc..5331f5047 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -924,7 +924,7 @@ OptionMenu AutomapOptions { Title "AUTOMAP OPTIONS" Option "Map color set", "am_colorset", "MapColorTypes" - Option "Allow map defined colors" "am_customcolors", "YesNo" + Option "Allow map defined colors", "am_customcolors", "YesNo" Submenu "Set custom colors", "MapColorMenu" Submenu "Customize map controls", "MapControlsMenu" StaticText " " From 9f357881647140a92ee7b142d37d830bb67d5734 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Aug 2013 11:00:24 +0200 Subject: [PATCH 013/247] - added custom automap overlay colors. - extended am_drawmapback so that map backgrounds can only be drawn if used with custom colorsets and Raven's, assuming that these sets were specifically made for the accompanying backgrounds. --- src/am_map.cpp | 44 ++++++++++++++++++++++++++++----------- src/g_level.h | 2 +- src/g_mapinfo.cpp | 4 ++-- wadsrc/static/menudef.txt | 9 +++++++- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 6a765cd7a..b8cb84dd7 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -85,7 +85,7 @@ CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE); CVAR (Int, am_colorset, 0, CVAR_ARCHIVE); CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE); CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); -CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE); +CVAR (Int, am_drawmapback, 1, CVAR_ARCHIVE); CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); CVAR (Bool, am_showtriggerlines, false, CVAR_ARCHIVE); CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); @@ -435,6 +435,7 @@ static unsigned char RavenColors[]= { static AMColorset AMColors; static AMColorset AMMod; +static AMColorset AMModOverlay; //============================================================================= @@ -443,12 +444,14 @@ static AMColorset AMMod; // //============================================================================= -void FMapInfoParser::ParseAMColors() +void FMapInfoParser::ParseAMColors(bool overlay) { bool colorset = false; - AMMod.setWhite(); - AMMod.defined = true; + AMColorset &cset = overlay? AMModOverlay : AMMod; + + cset.setWhite(); + cset.defined = true; sc.MustGetToken('{'); while(sc.GetToken()) { @@ -464,15 +467,15 @@ void FMapInfoParser::ParseAMColors() sc.MustGetToken(TK_StringConst); if (sc.Compare("doom")) { - AMMod.initFromColors(DoomColors, false); + cset.initFromColors(DoomColors, false); } else if (sc.Compare("raven")) { - AMMod.initFromColors(RavenColors, true); + cset.initFromColors(RavenColors, true); } else if (sc.Compare("strife")) { - AMMod.initFromColors(StrifeColors, false); + cset.initFromColors(StrifeColors, false); } else { @@ -482,11 +485,11 @@ void FMapInfoParser::ParseAMColors() else if (nextKey.CompareNoCase("showlocks") == 0) { if(sc.CheckToken(TK_False)) - AMMod.displayLocks = false; + cset.displayLocks = false; else { sc.MustGetToken(TK_True); - AMMod.displayLocks = true; + cset.displayLocks = true; } } else @@ -501,7 +504,7 @@ void FMapInfoParser::ParseAMColors() FString colorName = V_GetColorStringByName(color); if(!colorName.IsEmpty()) color = colorName; int colorval = V_GetColorFromString(NULL, color); - AMMod.c[i].FromRGB(RPART(colorval), GPART(colorval), BPART(colorval)); + cset.c[i].FromRGB(RPART(colorval), GPART(colorval), BPART(colorval)); colorset = true; break; } @@ -1244,7 +1247,14 @@ static void AM_initColors (bool overlayed) { if (overlayed) { - AMColors.initFromCVars(cv_overlay); + if (am_customcolors && AMModOverlay.defined) + { + AMColors = AMModOverlay; + } + else + { + AMColors.initFromCVars(cv_overlay); + } } else if (am_customcolors && AMMod.defined) { @@ -1598,7 +1608,17 @@ void AM_Ticker () void AM_clearFB (const AMColor &color) { - if (!mapback.isValid() || !am_drawmapback) + bool drawback = mapback.isValid() && am_drawmapback != 0; + if (am_drawmapback == 2) + { + // only draw background when using a mod defined custom color set or Raven colors, if am_drawmapback is 2. + if (!am_customcolors || !AMMod.defined) + { + drawback &= (am_colorset == 3); + } + } + + if (!drawback) { screen->Clear (0, 0, f_w, f_h, color.Index, color.RGB); } diff --git a/src/g_level.h b/src/g_level.h index 087f9bb19..c431b9695 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -103,7 +103,7 @@ struct FMapInfoParser void ParseIntermissionAction(FIntermissionDescriptor *Desc); void ParseIntermission(); - void ParseAMColors(); + void ParseAMColors(bool); FName CheckEndSequence(); FName ParseEndGame(); }; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 94c6a2317..04617a068 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1842,12 +1842,12 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i sc.ScriptError("intermission definitions not supported with old MAPINFO syntax"); } } - else if (sc.Compare("automap")) + else if (sc.Compare("automap") || sc.Compare("automap_overlay")) { if (format_type != FMT_Old) { format_type = FMT_New; - ParseAMColors(); + ParseAMColors(sc.Compare("automap_overlay")); } else { diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 136335238..b2a46469a 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -928,6 +928,13 @@ OptionValue STSTypes 3, "Rotated" } +OptionValue MapBackTypes +{ + 0, "Off" + 1, "On" + 2, "Map defined colors only" +} + OptionMenu AutomapOptions { Title "AUTOMAP OPTIONS" @@ -948,7 +955,7 @@ OptionMenu AutomapOptions Option "Show total time elapsed", "am_showtotaltime", "OnOff" Option "Show secrets on map", "am_map_secrets", "SecretTypes" Option "Show map label", "am_showmaplabel", "MaplabelTypes" - Option "Draw map background", "am_drawmapback", "OnOff" + Option "Draw map background", "am_drawmapback", "MapBackTypes" Option "Show keys (cheat)", "am_showkeys", "OnOff" Option "Show trigger lines", "am_showtriggerlines", "OnOff" Option "Show things as sprites", "am_showthingsprites", "STSTypes" From 151d54aaf59a64bcb56e7dbed4f2192c25f714a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Aug 2013 11:32:46 +0200 Subject: [PATCH 014/247] - added 3 more modes for am_cheat: 4-6 are the same as 1-3 with the exception that lines not drawn on the regular automap won't be shown. --- src/am_map.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index b8cb84dd7..bae48120d 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2229,7 +2229,7 @@ void AM_drawWalls (bool allmap) if (am_cheat != 0 || (lines[i].flags & ML_MAPPED)) { - if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0) + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { if (!am_showallenabled || CheckCheatmode(false)) { @@ -2336,14 +2336,14 @@ void AM_drawWalls (bool allmap) AM_drawMline(&l, AMColors.EFWallColor); // Extra floor border } #endif - else if (am_cheat != 0) + else if (am_cheat > 0 && am_cheat < 4) { AM_drawMline(&l, AMColors.TSWallColor); } } else if (allmap) { - if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0) + if ((lines[i].flags & ML_DONTDRAW) && (am_cheat == 0 || am_cheat >= 4)) { if (!am_showallenabled || CheckCheatmode(false)) { @@ -2463,7 +2463,7 @@ AM_drawLineCharacter void AM_drawPlayers () { - if (am_cheat >= 2 && am_showthingsprites > 0) + if (am_cheat >= 2 && am_cheat != 4 && am_showthingsprites > 0) { // Player sprites are drawn with the others return; @@ -2710,7 +2710,7 @@ void AM_drawThings () 16<= 3) + if (am_cheat == 3 || am_cheat == 6) { static const mline_t box[4] = { @@ -2908,7 +2908,7 @@ void AM_Drawer () AM_drawPlayers(); if (G_SkillProperty(SKILLP_EasyKey)) AM_drawKeys(); - if (am_cheat >= 2 || allthings) + if ((am_cheat >= 2 && am_cheat != 4) || allthings) AM_drawThings(); AM_drawAuthorMarkers(); From 55f637c9069cbce46998488d56cd4e518e4a6045 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 9 Aug 2013 23:40:34 +0200 Subject: [PATCH 015/247] - fixed: When creating colormaps for 3D floors the model sector's fade value must be used when defining a fog volume. --- src/p_3dfloors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 56b34ca0f..51ac24229 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -60,7 +60,7 @@ FDynamicColormap *F3DFloor::GetColormap() { // If there's no fog in either model or target sector this is easy and fast. - if ((target->ColorMap->Fade == 0 && model->ColorMap->Fade == 0) || (flags & FF_FADEWALLS)) + if ((target->ColorMap->Fade == 0 && model->ColorMap->Fade == 0) || (flags & (FF_FADEWALLS|FF_FOG))) { return model->ColorMap; } From 25ec3fb8feeff395576808268254ef46f03de333 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 10 Aug 2013 09:32:55 +0200 Subject: [PATCH 016/247] - added MF6_RELATIVETOFLOOR flag. --- src/actor.h | 1 + src/p_map.cpp | 44 ++++++++++++++++++++++++---------- src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/actor.h b/src/actor.h index 768008182..bf1b1cc60 100644 --- a/src/actor.h +++ b/src/actor.h @@ -332,6 +332,7 @@ enum MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. + MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts. // --- mobj.renderflags --- diff --git a/src/p_map.cpp b/src/p_map.cpp index da87481d0..ee7c63263 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -5047,6 +5047,15 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) P_CheckFakeFloorTriggers (thing, oldz); } } + else if ((thing->z != oldfloorz && !(thing->flags & MF_NOLIFTDROP))) + { + fixed_t oldz = thing->z; + if ((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) + { + thing->z = thing->z - oldfloorz + thing->floorz; + P_CheckFakeFloorTriggers (thing, oldz); + } + } } //============================================================================= @@ -5058,6 +5067,7 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos) void PIT_FloorRaise (AActor *thing, FChangePosition *cpos) { fixed_t oldfloorz = thing->floorz; + fixed_t oldz = thing->z; P_AdjustFloorCeil (thing, cpos); @@ -5072,22 +5082,30 @@ void PIT_FloorRaise (AActor *thing, FChangePosition *cpos) return; // do not move bridge things } intersectors.Clear (); - fixed_t oldz = thing->z; thing->z = thing->floorz; - switch (P_PushUp (thing, cpos)) + } + else + { + if((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR)) { - default: - P_CheckFakeFloorTriggers (thing, oldz); - break; - case 1: - P_DoCrunch (thing, cpos); - P_CheckFakeFloorTriggers (thing, oldz); - break; - case 2: - P_DoCrunch (thing, cpos); - thing->z = oldz; - break; + intersectors.Clear (); + thing->z = thing->z - oldfloorz + thing->floorz; } + else return; + } + switch (P_PushUp (thing, cpos)) + { + default: + P_CheckFakeFloorTriggers (thing, oldz); + break; + case 1: + P_DoCrunch (thing, cpos); + P_CheckFakeFloorTriggers (thing, oldz); + break; + case 2: + P_DoCrunch (thing, cpos); + thing->z = oldz; + break; } } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index ef0cf2fe1..c01855eec 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -235,6 +235,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6), DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6), DEFINE_FLAG(MF6, NOTONAUTOMAP, AActor, flags6), + DEFINE_FLAG(MF6, RELATIVETOFLOOR, AActor, flags6), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From f2c250d35df2db2ca7a69aead7fc97588d1d83a5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 20:09:21 +0200 Subject: [PATCH 017/247] - flags7 variable added to AActor. --- src/actor.h | 1 + src/m_cheat.cpp | 1 + src/p_enemy.cpp | 1 + src/p_mobj.cpp | 11 +++++++++-- src/p_things.cpp | 1 + src/thingdef/thingdef_properties.cpp | 3 ++- src/version.h | 2 +- 7 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/actor.h b/src/actor.h index 768008182..d06e968f7 100644 --- a/src/actor.h +++ b/src/actor.h @@ -837,6 +837,7 @@ public: DWORD flags4; // [RH] Even more flags! DWORD flags5; // OMG! We need another one. DWORD flags6; // Shit! Where did all the flags go? + DWORD flags7; // // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it. DWORD VisibleToTeam; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 07c467bac..5d9d48bea 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -311,6 +311,7 @@ void cht_DoCheat (player_t *player, int cheat) player->mo->flags4 = player->mo->GetDefault()->flags4; player->mo->flags5 = player->mo->GetDefault()->flags5; player->mo->flags6 = player->mo->GetDefault()->flags6; + player->mo->flags7 = player->mo->GetDefault()->flags7; player->mo->renderflags &= ~RF_INVISIBLE; player->mo->height = player->mo->GetDefault()->height; player->mo->radius = player->mo->GetDefault()->radius; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 81a58ac15..5df2b4b5e 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2644,6 +2644,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) corpsehit->flags4 = info->flags4; corpsehit->flags5 = info->flags5; corpsehit->flags6 = info->flags6; + corpsehit->flags7 = info->flags7; corpsehit->health = info->health; corpsehit->target = NULL; corpsehit->lastenemy = NULL; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 14607a682..34100c935 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -200,8 +200,12 @@ void AActor::Serialize (FArchive &arc) << flags3 << flags4 << flags5 - << flags6 - << special1 + << flags6; + if (SaveVersion >= 4504) + { + arc << flags7; + } + arc << special1 << special2 << health << movedir @@ -6133,6 +6137,9 @@ void PrintMiscActorInfo(AActor *query) Printf("\n\tflags6: %x", query->flags6); for (flagi = 0; flagi <= 31; flagi++) if (query->flags6 & 1<flags7); + for (flagi = 0; flagi <= 31; flagi++) + if (query->flags7 & 1<BounceFlags, FIXED2FLOAT(query->bouncefactor), FIXED2FLOAT(query->wallbouncefactor)); diff --git a/src/p_things.cpp b/src/p_things.cpp index a0f905a7f..4828e8cbc 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -452,6 +452,7 @@ bool P_Thing_Raise(AActor *thing) thing->flags4 = info->flags4; thing->flags5 = info->flags5; thing->flags6 = info->flags6; + thing->flags7 = info->flags7; thing->health = info->health; thing->target = NULL; thing->lastenemy = NULL; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index dc08db361..262846bf2 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1286,7 +1286,8 @@ DEFINE_PROPERTY(clearflags, 0, Actor) defaults->flags3 = defaults->flags4 = defaults->flags5 = - defaults->flags6 = 0; + defaults->flags6 = + defaults->flags7 = 0; defaults->flags2 &= MF2_ARGSDEFINED; // this flag must not be cleared } diff --git a/src/version.h b/src/version.h index 01fbc7a88..0c62c5ef2 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4503 +#define SAVEVER 4504 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) From 44a1b94ad9bd67496b0cbfe508c603ecb4f13df1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 20:23:54 +0200 Subject: [PATCH 018/247] - added MF6_NOTELESTOMP flag that prevents an actor from telefragging under all possible circumstances. --- src/actor.h | 7 ++++--- src/p_map.cpp | 3 +-- src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/actor.h b/src/actor.h index d06e968f7..98210753a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -236,7 +236,7 @@ enum MF4_RANDOMIZE = 0x00000010, // Missile has random initial tic count MF4_NOSKIN = 0x00000020, // Player cannot use skins MF4_FIXMAPTHINGPOS = 0x00000040, // Fix this actor's position when spawned as a map thing - MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor + MF4_ACTLIKEBRIDGE = 0x00000080, // Pickups can "stand" on this actor / cannot be moved by any sector action. MF4_STRIFEDAMAGE = 0x00000100, // Strife projectiles only do up to 4x damage, not 8x MF4_CANUSEWALLS = 0x00000200, // Can activate 'use' specials @@ -266,7 +266,7 @@ enum // --- mobj.flags5 --- MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. - /* = 0x00000002, */ + /* = 0x00000002, reserved for use by scripting branch */ MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. MF5_NOFORWARDFALL = 0x00000008, // Does not make any actor fall forward by being damaged by this MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret @@ -284,7 +284,7 @@ enum MF5_NEVERFAST = 0x00010000, // never uses 'fast' attacking logic MF5_ALWAYSRESPAWN = 0x00020000, // always respawns, regardless of skill setting MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting - MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hittin this actor + MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hitting this actor MF5_NOINFIGHTING = 0x00100000, // This actor doesn't switch target when it's hurt MF5_NOINTERACTION = 0x00200000, // Thing is completely excluded from any gameplay related checks MF5_NOTIMEFREEZE = 0x00400000, // Actor is not affected by time freezer @@ -332,6 +332,7 @@ enum MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. + MF6_NOTELESTOMP = 0x80000000, // cannot telefrag under any circumstances (even when set by MAPINFO) // --- mobj.renderflags --- diff --git a/src/p_map.cpp b/src/p_map.cpp index da87481d0..a892c4a95 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -334,8 +334,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr spechit.Clear (); - bool StompAlwaysFrags = (thing->flags2 & MF2_TELESTOMP) || - (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag; + bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags6 & MF6_NOTELESTOMP); FBoundingBox box(x, y, thing->radius); FBlockLinesIterator it(box); diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index ef0cf2fe1..938c48e45 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -235,6 +235,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6), DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6), DEFINE_FLAG(MF6, NOTONAUTOMAP, AActor, flags6), + DEFINE_FLAG(MF6, NOTELESTOMP, AActor, flags6), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From e14590d8ced826c6301e31e9908927a4657d5293 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 20:41:33 +0200 Subject: [PATCH 019/247] - moved NOTELESTOMP to flags7. When committing I was accidentally on maint instead of master and in master flags6 was already full. --- src/actor.h | 6 +++++- src/p_interaction.cpp | 3 +++ src/p_map.cpp | 2 +- src/p_mobj.cpp | 2 +- src/thingdef/thingdef_data.cpp | 4 +++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/actor.h b/src/actor.h index 98210753a..5a3298488 100644 --- a/src/actor.h +++ b/src/actor.h @@ -332,7 +332,11 @@ enum MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. - MF6_NOTELESTOMP = 0x80000000, // cannot telefrag under any circumstances (even when set by MAPINFO) + +// --- mobj.flags6 --- + + MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered. + MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO) // --- mobj.renderflags --- diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 0ee955a82..47ed87888 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1508,6 +1508,9 @@ bool AActor::OkayToSwitchTarget (AActor *other) if (other == this) return false; // [RH] Don't hate self (can happen when shooting barrels) + if (other->flags7 & MF7_NEVERTARGET) + return false; // never EVER target me! + if (!(other->flags & MF_SHOOTABLE)) return false; // Don't attack things that can't be hurt diff --git a/src/p_map.cpp b/src/p_map.cpp index a892c4a95..3c7370f02 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -334,7 +334,7 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr spechit.Clear (); - bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags6 & MF6_NOTELESTOMP); + bool StompAlwaysFrags = ((thing->flags2 & MF2_TELESTOMP) || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag) && !(thing->flags7 & MF7_NOTELESTOMP); FBoundingBox box(x, y, thing->radius); FBlockLinesIterator it(box); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 34100c935..a2addad0e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -830,7 +830,7 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget, bool resetHealt flags4 = (flags4 & ~(MF4_NOHATEPLAYERS | MF4_BOSSSPAWNED)) | (other->flags4 & (MF4_NOHATEPLAYERS | MF4_BOSSSPAWNED)); FriendPlayer = other->FriendPlayer; DesignatedTeam = other->DesignatedTeam; - if (changeTarget && other->target != NULL && !(other->target->flags3 & MF3_NOTARGET)) + if (changeTarget && other->target != NULL && !(other->target->flags3 & MF3_NOTARGET) && !(other->target->flags7 & MF7_NEVERTARGET)) { // LastHeard must be set as well so that A_Look can react to the new target if called LastHeard = target = other->target; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 938c48e45..e4c166761 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -235,7 +235,9 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6), DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6), DEFINE_FLAG(MF6, NOTONAUTOMAP, AActor, flags6), - DEFINE_FLAG(MF6, NOTELESTOMP, AActor, flags6), + + DEFINE_FLAG(MF7, NEVERTARGET, AActor, flags7), + DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From aa03609b69406c0742a0c7ff174272df2584d931 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 21:00:23 +0200 Subject: [PATCH 020/247] - added IF_TOSSED inventory flag. --- src/g_shared/a_pickups.h | 2 ++ src/p_enemy.cpp | 1 + src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 6c68990d1..22d1e009f 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -134,6 +134,8 @@ enum IF_RESTRICTABSOLUTELY = 1<<19, // RestrictedTo and ForbiddenTo do not allow pickup in any form by other classes IF_NEVERRESPAWN = 1<<20, // Never, ever respawns IF_NOSCREENFLASH = 1<<21, // No pickup flash on the player's screen + IF_TOSSED = 1<<22, // Was spawned by P_DropItem (i.e. as a monster drop) + }; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5df2b4b5e..437940d03 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3088,6 +3088,7 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int dropamount, int { AInventory * inv = static_cast(mo); ModifyDropAmount(inv, dropamount); + inv->ItemFlags |= IF_TOSSED; if (inv->SpecialDropAction (source)) { // The special action indicates that the item should not spawn diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 1f1c6ec00..57dd363c8 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -308,6 +308,7 @@ static FFlagDef InventoryFlags[] = DEFINE_FLAG(IF, RESTRICTABSOLUTELY, AInventory, ItemFlags), DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags), DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags), + DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags), DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),}; From 61c94648dca658117f4d837bb55e9bd6f01b8b21 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 22:38:52 +0200 Subject: [PATCH 021/247] - added ACS CheckFlag function. --- src/p_acs.cpp | 11 +++++++++++ src/thingdef/thingdef.h | 1 + src/thingdef/thingdef_codeptr.cpp | 26 ++------------------------ src/thingdef/thingdef_properties.cpp | 27 +++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 8a015bae4..bb92b42bd 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4235,6 +4235,7 @@ enum EACSFunctions ACSF_SpawnDecal, ACSF_CheckFont, ACSF_DropItem, + ACSF_CheckFlag, // ZDaemon ACSF_GetTeamScore = 19620, // (int team) @@ -5270,6 +5271,16 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } + case ACSF_CheckFlag: + { + AActor *actor = SingleActorFromTID(args[0], activator); + if (actor != NULL) + { + return !!CheckActorFlag(actor, FBehavior::StaticLookupString(args[1])); + } + break; + } + default: break; } diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 63d04ea29..c388a8544 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -31,6 +31,7 @@ bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index); const char *GetFlagName(unsigned int flagnum, int flagoffset); void ModActorFlag(AActor *actor, FFlagDef *fd, bool set); INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd); +INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror = true); #define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar)) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 456a1d6e3..7964c422b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3777,32 +3777,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) COPY_AAPTR_NOT_NULL(self, owner, checkpointer); - const char *dot = strchr (flagname, '.'); - FFlagDef *fd; - const PClass *cls = owner->GetClass(); - - if (dot != NULL) + if (CheckActorFlag(owner, flagname)) { - FString part1(flagname, dot-flagname); - fd = FindFlag (cls, part1, dot+1); + ACTION_JUMP(jumpto); } - else - { - fd = FindFlag (cls, flagname, NULL); - } - - if (fd != NULL) - { - if (CheckActorFlag(owner, fd)) - { - ACTION_JUMP(jumpto); - } - } - else - { - Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); - } - } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 2c0abee17..d6731aafa 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -180,6 +180,33 @@ INTBOOL CheckActorFlag(const AActor *owner, FFlagDef *fd) #endif } +INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror) +{ + const char *dot = strchr (flagname, '.'); + FFlagDef *fd; + const PClass *cls = owner->GetClass(); + + if (dot != NULL) + { + FString part1(flagname, dot-flagname); + fd = FindFlag (cls, part1, dot+1); + } + else + { + fd = FindFlag (cls, flagname, NULL); + } + + if (fd != NULL) + { + return CheckActorFlag(owner, fd); + } + else + { + if (printerror) Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); + return false; + } +} + //=========================================================================== // // HandleDeprecatedFlags From 3518b4dd28a4c1bbf1f39ea31f63926b221683c6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 12 Aug 2013 22:46:45 +0200 Subject: [PATCH 022/247] - allow menu's back button and the pause sign to be animated. --- src/d_main.cpp | 2 +- src/menu/menu.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 75a616bf4..b70e5d779 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -855,7 +855,7 @@ void D_Display () FTexture *tex; int x; - tex = TexMan[gameinfo.PauseSign]; + tex = TexMan(gameinfo.PauseSign); x = (SCREENWIDTH - tex->GetScaledWidth() * CleanXfac)/2 + tex->GetScaledLeftOffset() * CleanXfac; screen->DrawTexture (tex, x, 4, DTA_CleanNoMove, true, TAG_DONE); diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index dc1b8ccd8..dd25c9e0b 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -207,7 +207,7 @@ bool DMenu::MouseEventBack(int type, int x, int y) { if (m_show_backbutton >= 0) { - FTexture *tex = TexMan[gameinfo.mBackButton]; + FTexture *tex = TexMan(gameinfo.mBackButton); if (tex != NULL) { if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetScaledWidth() * CleanXfac; @@ -263,7 +263,7 @@ void DMenu::Drawer () { if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse) { - FTexture *tex = TexMan[gameinfo.mBackButton]; + FTexture *tex = TexMan(gameinfo.mBackButton); int w = tex->GetScaledWidth() * CleanXfac; int h = tex->GetScaledHeight() * CleanYfac; int x = (!(m_show_backbutton&1))? 0:screen->GetWidth() - w; From 7a87e08107511228c05ef6387109eed3ab6fb469 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Aug 2013 21:01:14 +0200 Subject: [PATCH 023/247] - added MF7_ALWAYSTELEFRAG flag that causes an actor to be telefragged by everything that teleports into the same place. --- src/actor.h | 1 + src/p_map.cpp | 3 ++- src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/actor.h b/src/actor.h index 17c00041b..c60b6a516 100644 --- a/src/actor.h +++ b/src/actor.h @@ -338,6 +338,7 @@ enum MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered. MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO) + MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings. // --- mobj.renderflags --- diff --git a/src/p_map.cpp b/src/p_map.cpp index 442e77876..1b5c31167 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -382,7 +382,8 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr // monsters don't stomp things except on boss level // [RH] Some Heretic/Hexen monsters can telestomp - if (StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) + // ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them. + if ((StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) || (th->flags7 & MF7_ALWAYSTELEFRAG)) { P_DamageMobj (th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS); continue; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 57dd363c8..bf0bf2e13 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -239,6 +239,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, NEVERTARGET, AActor, flags7), DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7), + DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From c8b4fb0d3dd782ca9974c436d2d44b5325e1515d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 Aug 2013 21:09:46 +0200 Subject: [PATCH 024/247] - added a 'closemenu' CCMD so that menu options that close the menu can be added. --- src/menu/menu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index dd25c9e0b..d01f0807f 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -909,6 +909,11 @@ CCMD (openmenu) M_SetMenu(argv[1], -1); } +CCMD (closemenu) +{ + M_ClearMenus(); +} + // // Toggle messages on/off // From 62830f7927c8f1a8aa2d387237f66b5acaf4b17f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 Aug 2013 00:32:05 +0200 Subject: [PATCH 025/247] - added separate automap color for non-counting monsters. - fixed: using a nonexistent CVAR in a ColorPicker menu item caused a crash. --- src/am_map.cpp | 12 +++++++++++- src/menu/optionmenuitems.h | 2 +- wadsrc/static/menudef.txt | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index c9e88c70b..c22714316 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -115,6 +115,7 @@ CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE); CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE); +CVAR (Color, am_thingcolor_ncmonster, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE); CVAR (Color, am_thingcolor_citem, 0xfcfcfc, CVAR_ARCHIVE); @@ -134,6 +135,7 @@ CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE); +CVAR (Color, am_ovthingcolor_ncmonster, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE); CVAR (Color, am_ovthingcolor_citem, 0xe88800, CVAR_ARCHIVE); @@ -190,6 +192,7 @@ static const char *ColorNames[] = { "ThingColor_Item", "ThingColor_CountItem", "ThingColor_Monster", + "ThingColor_NocountMonster", "ThingColor_Friend", "SpecialWallColor", "SecretWallColor", @@ -219,6 +222,7 @@ struct AMColorset ThingColor_Item, ThingColor_CountItem, ThingColor_Monster, + ThingColor_NocountMonster, ThingColor_Friend, SpecialWallColor, SecretWallColor, @@ -318,6 +322,7 @@ static FColorCVar *cv_standard[] = { &am_thingcolor_item, &am_thingcolor_citem, &am_thingcolor_monster, + &am_thingcolor_ncmonster, &am_thingcolor_friend, &am_specialwallcolor, &am_secretwallcolor, @@ -342,6 +347,7 @@ static FColorCVar *cv_overlay[] = { &am_ovthingcolor_item, &am_ovthingcolor_citem, &am_ovthingcolor_monster, + &am_ovthingcolor_ncmonster, &am_ovthingcolor_friend, &am_ovspecialwallcolor, &am_ovsecretwallcolor, @@ -368,6 +374,7 @@ static unsigned char DoomColors[]= { 0x74,0xfc,0x6c, // thingcolor_item 0x74,0xfc,0x6c, // thingcolor_citem 0x74,0xfc,0x6c, // thingcolor_monster + 0x74,0xfc,0x6c, // thingcolor_ncmonster 0x74,0xfc,0x6c, // thingcolor_friend NOT_USED, // specialwallcolor NOT_USED, // secretwallcolor @@ -393,6 +400,7 @@ static unsigned char StrifeColors[]= { 219, 171, 0, // thingcolor_item 219, 171, 0, // thingcolor_citem 0xfc,0x00,0x00, // thingcolor_monster + 0xfc,0x00,0x00, // thingcolor_ncmonster 0xfc,0x00,0x00, // thingcolor_friend NOT_USED, // specialwallcolor NOT_USED, // secretwallcolor @@ -418,6 +426,7 @@ static unsigned char RavenColors[]= { 236, 236, 236, // thingcolor_item 236, 236, 236, // thingcolor_citem 236, 236, 236, // thingcolor_monster + 236, 236, 236, // thingcolor_ncmonster 236, 236, 236, // thingcolor_friend NOT_USED, // specialwallcolor NOT_USED, // secretwallcolor @@ -2669,7 +2678,8 @@ void AM_drawThings () // use separate colors for special thing types if (t->flags3&MF3_ISMONSTER && !(t->flags&MF_CORPSE)) { - if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = AMColors[AMColors.ThingColor_Friend]; + if (t->flags & MF_FRIENDLY) color = AMColors[AMColors.ThingColor_Friend]; + else if (!(t->flags & MF_COUNTKILL)) color = AMColors[AMColors.ThingColor_NocountMonster]; else color = AMColors[AMColors.ThingColor_Monster]; } else if (t->flags&MF_SPECIAL) diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index d57e13d05..ff3eb016a 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -763,7 +763,7 @@ public: : FOptionMenuItem(label, menu) { FBaseCVar *cv = FindCVar(menu, NULL); - if (cv->GetRealType() == CVAR_Color) + if (cv != NULL && cv->GetRealType() == CVAR_Color) { mCVar = (FColorCVar*)cv; } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b2a46469a..6457051bf 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1019,6 +1019,7 @@ OptionMenu MapColorMenu ColorPicker "Secret walls", "am_secretwallcolor" ColorPicker "Actors", "am_thingcolor" ColorPicker "Monsters", "am_thingcolor_monster" + ColorPicker "non-counting Monsters", "am_thingcolor_ncmonster" ColorPicker "Friends", "am_thingcolor_friend" ColorPicker "Items", "am_thingcolor_item" ColorPicker "Count Items", "am_thingcolor_citem" @@ -1041,6 +1042,7 @@ OptionMenu MapColorMenu ColorPicker "Secret walls", "am_ovsecretwallcolor" ColorPicker "Actors", "am_ovthingcolor" ColorPicker "Monsters", "am_ovthingcolor_monster" + ColorPicker "non-counting Monsters", "am_ovthingcolor_ncmonster" ColorPicker "Friends", "am_ovthingcolor_friend" ColorPicker "Items", "am_ovthingcolor_item" ColorPicker "Count Items", "am_ovthingcolor_citem" From 116defbb35d8cc472a21de7656f0b24c23af832e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 Aug 2013 09:11:40 +0200 Subject: [PATCH 026/247] - fixed: LookForEnemiesInBlock needs to check for MF7_NEVERTARGET. --- src/p_enemy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 437940d03..fa39297e6 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1425,6 +1425,9 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) if (!(link->flags3 & MF3_ISMONSTER)) continue; // don't target it if it isn't a monster (could be a barrel) + if (link->flags7 & MF7_NEVERTARGET) + continue; + other = NULL; if (link->flags & MF_FRIENDLY) { From 8e8f6cf5a6fbe6393a0dfd290f728f54d7557274 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 20 Aug 2013 20:33:03 +0200 Subject: [PATCH 027/247] - A_AlertMonsters flags submission by NeuralStunner. --- src/g_strife/a_strifeweapons.cpp | 28 +++++++++++++++++++++++++--- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/constants.txt | 7 +++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 82560e6f7..d37f0ea5a 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -137,18 +137,40 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger) // //============================================================================ +enum +{ + AMF_TARGETEMITTER = 1, + AMF_TARGETNONPLAYER = 2, + AMF_EMITFROMTARGET = 4, +}; + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) { ACTION_PARAM_START(1); ACTION_PARAM_FIXED(maxdist, 0); + ACTION_PARAM_INT(Flags, 1); - if (self->player != NULL) + AActor * target; + AActor * emitter = self; + + if (self->player != NULL || (Flags & AMF_TARGETEMITTER)) { - P_NoiseAlert(self, self, false, maxdist); + target = self; + } + else if (self->target != NULL && (Flags & AMF_TARGETNONPLAYER)) + { + target = self->target; } else if (self->target != NULL && self->target->player != NULL) { - P_NoiseAlert (self->target, self, false, maxdist); + target = self->target; + } + + if (Flags & AMF_EMITFROMTARGET) emitter = target; + + if (target != NULL && emitter != NULL) + { + P_NoiseAlert(target, emitter, false, maxdist); } } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 3ba47a5c1..73119c941 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -180,7 +180,7 @@ ACTOR Actor native //: Thinker action native A_TurretLook(); action native A_KlaxonBlare(); action native A_Countdown(); - action native A_AlertMonsters(float maxdist = 0); + action native A_AlertMonsters(float maxdist = 0, int flags = 0); action native A_ClearSoundTarget(); action native A_FireAssaultGun(); action native A_CheckTerrain(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index cd9b088ab..dee498b6a 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -348,5 +348,12 @@ enum CLOFF_NOAIM = CLOFF_NOAIM_VERT|CLOFF_NOAIM_HORZ }; + +// Flags for A_AlertMonsters +const int AMF_TARGETEMITTER = 1; +const int AMF_TARGETNONPLAYER = 2; +const int AMF_EMITFROMTARGET = 4; + + // This is only here to provide one global variable for testing. native int testglobalvar; From 0a16e9a2562cb560a5459c52d6ee42d8685447f4 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 27 Aug 2013 20:42:35 -0400 Subject: [PATCH 028/247] - Fixed uninitialized variable in A_AlertMonsters. --- src/g_strife/a_strifeweapons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index d37f0ea5a..a41058492 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -150,7 +150,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_AlertMonsters) ACTION_PARAM_FIXED(maxdist, 0); ACTION_PARAM_INT(Flags, 1); - AActor * target; + AActor * target = NULL; AActor * emitter = self; if (self->player != NULL || (Flags & AMF_TARGETEMITTER)) From ba2a07fb26fe47e4c11d9df0bcf330eec4d6b0e0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 2 Sep 2013 09:08:47 +0200 Subject: [PATCH 029/247] - removed all uses of single precision floats from FraggleScript code. --- src/fragglescript/t_func.cpp | 7 +++---- src/fragglescript/t_script.h | 2 +- src/fragglescript/t_variable.cpp | 9 +++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 448c200d8..2513a68a8 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -73,7 +73,6 @@ static FRandom pr_script("FScript"); #define AngleToFixed(x) ((((double) x) / ((double) ANG45/45)) * FRACUNIT) #define FixedToAngle(x) ((((double) x) / FRACUNIT) * ANG45/45) -#define FIXED_TO_FLOAT(f) ((f)/(float)FRACUNIT) // functions. FParser::SF_ means Script Function not, well.. heh, me @@ -1417,11 +1416,11 @@ void FParser::SF_PointToDist(void) if (CheckArgs(4)) { // Doing this in floating point is actually faster with modern computers! - float x = floatvalue(t_argv[2]) - floatvalue(t_argv[0]); - float y = floatvalue(t_argv[3]) - floatvalue(t_argv[1]); + double x = floatvalue(t_argv[2]) - floatvalue(t_argv[0]); + double y = floatvalue(t_argv[3]) - floatvalue(t_argv[1]); t_return.type = svt_fixed; - t_return.value.f = (fixed_t)(sqrtf(x*x+y*y)*65536.f); + t_return.value.f = FLOAT2FIXED(sqrt(x*x+y*y)*65536.f); } } diff --git a/src/fragglescript/t_script.h b/src/fragglescript/t_script.h index e3db7da3d..ffa2dae3c 100644 --- a/src/fragglescript/t_script.h +++ b/src/fragglescript/t_script.h @@ -110,7 +110,7 @@ struct svalue_t int intvalue(const svalue_t & v); fixed_t fixedvalue(const svalue_t & v); -float floatvalue(const svalue_t & v); +double floatvalue(const svalue_t & v); const char *stringvalue(const svalue_t & v); AActor *actorvalue(const svalue_t &svalue); diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index 7326fe4eb..7076a395b 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -89,11 +89,12 @@ fixed_t fixedvalue(const svalue_t &v) // //========================================================================== -float floatvalue(const svalue_t &v) +double floatvalue(const svalue_t &v) { - return (float)( (v.type == svt_string ? atof(v.string) : - v.type == svt_fixed ? (float)(v.value.f / (float)FRACUNIT) : - v.type == svt_mobj ? -1.f : (float)v.value.i )); + return + v.type == svt_string ? atof(v.string) : + v.type == svt_fixed ? FIXED2DBL(v.value.f) : + v.type == svt_mobj ? -1. : (double)v.value.i; } //========================================================================== From b6baeecd9a18c5e0cb46e58059f52672a16e83e4 Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae Date: Tue, 3 Sep 2013 03:49:39 +0400 Subject: [PATCH 030/247] Fixed compilation with LLVM compilers --- src/sdl/i_system.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index def35606a..ba126bf54 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -699,7 +699,7 @@ bool I_WriteIniFailed () static const char *pattern; -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(__llvm__) static int matchfile (struct dirent *ent) #else static int matchfile (const struct dirent *ent) From da02a44126c67e0e7e084c1517dee8fd888f2961 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 14 Sep 2013 21:02:47 -0500 Subject: [PATCH 031/247] Consolidate special path functions into m_specialpaths.cpp - Also remove CDROM_DIR while I'm at it. --- src/CMakeLists.txt | 1 + src/b_game.cpp | 24 +- src/d_main.cpp | 11 - src/g_game.cpp | 26 +-- src/gameconfigfile.cpp | 94 +------- src/m_misc.cpp | 112 +-------- src/m_misc.h | 15 +- src/m_specialpaths.cpp | 500 +++++++++++++++++++++++++++++++++++++++++ src/p_glnodes.cpp | 51 +---- src/version.h | 2 - zdoom.vcproj | 4 + 11 files changed, 541 insertions(+), 299 deletions(-) create mode 100644 src/m_specialpaths.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82f347fd8..4223598f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -701,6 +701,7 @@ add_executable( zdoom WIN32 m_misc.cpp m_png.cpp m_random.cpp + m_specialpaths.cpp memarena.cpp md5.cpp name.cpp diff --git a/src/b_game.cpp b/src/b_game.cpp index ed3a5c848..f3878b8bb 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -505,31 +505,13 @@ bool FCajunMaster::LoadBots () bool gotteam = false; bglobal.ForgetBots (); -#ifndef __unix__ - tmp = progdir; - tmp += "zcajun/" BOTFILENAME; - if (!FileExists (tmp)) + tmp = M_GetCajunPath(BOTFILENAME); + if (tmp.IsEmpty()) { DPrintf ("No " BOTFILENAME ", so no bots\n"); return false; } -#else - tmp = GetUserFile (BOTFILENAME); - if (!FileExists (tmp)) - { - if (!FileExists (SHARE_DIR BOTFILENAME)) - { - DPrintf ("No " BOTFILENAME ", so no bots\n"); - return false; - } - else - sc.OpenFile (SHARE_DIR BOTFILENAME); - } -#endif - else - { - sc.OpenFile (tmp); - } + sc.OpenFile(tmp); while (sc.GetString ()) { diff --git a/src/d_main.cpp b/src/d_main.cpp index b70e5d779..f72dc368b 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2137,17 +2137,6 @@ static void CheckCmdLine() Printf ("%s", GStrings("D_DEVSTR")); } -#if !defined(__unix__) && !defined(__APPLE__) - // We do not need to support -cdrom under Unix, because all the files - // that would go to c:\\zdoomdat are already stored in .zdoom inside - // the user's home directory. - if (Args->CheckParm("-cdrom")) - { - Printf ("%s", GStrings("D_CDROM")); - mkdir (CDROM_DIR, 0); - } -#endif - // turbo option // [RH] (now a cvar) v = Args->CheckValue("-turbo"); if (v != NULL) diff --git a/src/g_game.cpp b/src/g_game.cpp index 79cd4b233..698b52e79 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1919,32 +1919,10 @@ FString G_BuildSaveName (const char *prefix, int slot) leader = Args->CheckValue ("-savedir"); if (leader.IsEmpty()) { -#if !defined(__unix__) && !defined(__APPLE__) - if (Args->CheckParm ("-cdrom")) - { - leader = CDROM_DIR "/"; - } - else -#endif - { - leader = save_dir; - } + leader = save_dir; if (leader.IsEmpty()) { -#ifdef __unix__ - leader = "~/" GAME_DIR; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - leader << cpath << "/" GAME_DIR "/Savegames/"; - } -#else - leader = progdir; -#endif + leader = M_GetSavegamesPath(); } } size_t len = leader.Len(); diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 211ef96c6..f679bec3d 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -42,8 +42,6 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include -#include -#include extern HWND Window; #define USE_WINDOWS_DWORD #endif @@ -588,106 +586,20 @@ void FGameConfigFile::ArchiveGlobalData () FString FGameConfigFile::GetConfigPath (bool tryProg) { const char *pathval; - FString path; pathval = Args->CheckValue ("-config"); if (pathval != NULL) { return FString(pathval); } -#ifdef _WIN32 - path = NULL; - HRESULT hr; - - TCHAR uname[UNLEN+1]; - DWORD unamelen = countof(uname); - - // Because people complained, try for a user-specific .ini in the program directory first. - // If that is not writeable, use the one in the home directory instead. - hr = GetUserName (uname, &unamelen); - if (SUCCEEDED(hr) && uname[0] != 0) - { - // Is it valid for a user name to have slashes? - // Check for them and substitute just in case. - char *probe = uname; - while (*probe != 0) - { - if (*probe == '\\' || *probe == '/') - *probe = '_'; - ++probe; - } - - path = progdir; - path += "zdoom-"; - path += uname; - path += ".ini"; - if (tryProg) - { - if (!FileExists (path.GetChars())) - { - path = ""; - } - } - else - { // check if writeable - FILE *checker = fopen (path.GetChars(), "a"); - if (checker == NULL) - { - path = ""; - } - else - { - fclose (checker); - } - } - } - - if (path.IsEmpty()) - { - if (Args->CheckParm ("-cdrom")) - return CDROM_DIR "\\zdoom.ini"; - - path = progdir; - path += "zdoom.ini"; - } - return path; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path = cpath; - path += "/zdoom.ini"; - return path; - } - // Ungh. - return "zdoom.ini"; -#else - return GetUserFile ("zdoom.ini"); -#endif + return M_GetConfigPath(tryProg); } void FGameConfigFile::CreateStandardAutoExec(const char *section, bool start) { if (!SetSection(section)) { - FString path; -#ifdef __APPLE__ - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/autoexec.cfg"; - } -#elif !defined(__unix__) - path = "$PROGDIR/autoexec.cfg"; -#else - path = GetUserFile ("autoexec.cfg"); -#endif + FString path = M_GetAutoexecPath(); SetSection (section, true); SetValueForKey ("Path", path.GetChars()); } @@ -794,6 +706,6 @@ void FGameConfigFile::SetRavenDefaults (bool isHexen) CCMD (whereisini) { - FString path = GameConfig->GetConfigPath (false); + FString path = M_GetConfigPath(false); Printf ("%s\n", path.GetChars()); } diff --git a/src/m_misc.cpp b/src/m_misc.cpp index e218cadc4..14b9d9b1b 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -31,9 +31,6 @@ #include #include #include -#ifdef __APPLE__ -#include -#endif #include "doomtype.h" #include "version.h" @@ -333,65 +330,6 @@ static long ParseCommandLine (const char *args, int *argc, char **argv) } -#if defined(__unix__) -FString GetUserFile (const char *file) -{ - FString path; - struct stat info; - - path = NicePath("~/" GAME_DIR "/"); - - if (stat (path, &info) == -1) - { - struct stat extrainfo; - - // Sanity check for ~/.config - FString configPath = NicePath("~/.config/"); - if (stat (configPath, &extrainfo) == -1) - { - if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - { - I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno)); - } - } - else if (!S_ISDIR(extrainfo.st_mode)) - { - I_FatalError ("~/.config must be a directory"); - } - - // This can be removed after a release or two - // Transfer the old zdoom directory to the new location - bool moved = false; - FString oldpath = NicePath("~/.zdoom/"); - if (stat (oldpath, &extrainfo) != -1) - { - if (rename(oldpath, path) == -1) - { - I_Error ("Failed to move old zdoom directory (%s) to new location (%s).", - oldpath.GetChars(), path.GetChars()); - } - else - moved = true; - } - - if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - { - I_FatalError ("Failed to create %s directory:\n%s", - path.GetChars(), strerror (errno)); - } - } - else - { - if (!S_ISDIR(info.st_mode)) - { - I_FatalError ("%s must be a directory", path.GetChars()); - } - } - path += file; - return path; -} -#endif - // // M_SaveDefaults // @@ -698,48 +636,22 @@ void M_ScreenShot (const char *filename) // find a file name to save it to if (filename == NULL || filename[0] == '\0') { -#if !defined(__unix__) && !defined(__APPLE__) - if (Args->CheckParm ("-cdrom")) + size_t dirlen; + autoname = Args->CheckValue("-shotdir"); + if (autoname.IsEmpty()) { - autoname = CDROM_DIR "\\"; + autoname = screenshot_dir; } - else -#endif + dirlen = autoname.Len(); + if (dirlen == 0) { - size_t dirlen; - autoname = Args->CheckValue("-shotdir"); - if (autoname.IsEmpty()) + autoname = M_GetScreenshotsPath(); + } + else if (dirlen > 0) + { + if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') { - autoname = screenshot_dir; - } - dirlen = autoname.Len(); - if (dirlen == 0) - { -#ifdef __unix__ - autoname = "~/" GAME_DIR "/screenshots/"; -#elif defined(__APPLE__) - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - autoname << cpath << "/" GAME_DIR "/Screenshots/"; - } - else - { - autoname = "~"; - } -#else - autoname = progdir; -#endif - } - else if (dirlen > 0) - { - if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') - { - autoname += '/'; - } + autoname += '/'; } } autoname = NicePath(autoname); diff --git a/src/m_misc.h b/src/m_misc.h index 27006cf87..327df3de4 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -24,6 +24,7 @@ #define __M_MISC__ #include "basictypes.h" +#include "zstring.h" class FConfigFile; class FGameConfigFile; @@ -44,9 +45,19 @@ bool M_SaveDefaults (const char *filename); void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection, size_t sublen); -// Prepends ~/.zdoom to path -FString GetUserFile (const char *path); FString M_ZLibError(int zerrnum); +// Get special directory paths (defined in m_specialpaths.cpp) + +#ifdef __unix__ +FString GetUserFile (const char *path); // Prepends ~/.zdoom to path +#endif +FString M_GetCachePath(); +FString M_GetAutoexecPath(); +FString M_GetCajunPath(const char *filename); +FString M_GetConfigPath(bool for_reading); +FString M_GetScreenshotsPath(); +FString M_GetSavegamesPath(); + #endif diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp new file mode 100644 index 000000000..6f77551ae --- /dev/null +++ b/src/m_specialpaths.cpp @@ -0,0 +1,500 @@ +#ifdef __APPLE__ +#include +#endif + +#ifdef _WIN32 +#include +#include +#include +#define USE_WINDOWS_DWORD +#endif + +#include "cmdlib.h" +#include "m_misc.h" + +#if defined(_WIN32) + +//=========================================================================== +// +// M_GetCachePath Windows +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath() +{ + FString path; + + char pathstr[MAX_PATH]; + if (0 != SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pathstr)) + { // Failed (e.g. On Win9x): use program directory + path = progdir; + } + else + { + path = pathstr; + } + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + path += "/zdoom/cache"; + return path; +} + +//=========================================================================== +// +// M_GetAutoexecPath Windows +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + return "$PROGDIR/autoexec.cfg"; +} + +//=========================================================================== +// +// M_GetCajunPath Windows +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + path << progdir << "zcajun/" << botfilename; + if (!FileExists(path)) + { + path = ""; + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Windows +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + FString path; + HRESULT hr; + + TCHAR uname[UNLEN+1]; + DWORD unamelen = countof(uname); + + // Because people complained, try for a user-specific .ini in the program directory first. + // If that is not writeable, use the one in the home directory instead. + hr = GetUserName(uname, &unamelen); + if (SUCCEEDED(hr) && uname[0] != 0) + { + // Is it valid for a user name to have slashes? + // Check for them and substitute just in case. + char *probe = uname; + while (*probe != 0) + { + if (*probe == '\\' || *probe == '/') + *probe = '_'; + ++probe; + } + + path = progdir; + path += "zdoom-"; + path += uname; + path += ".ini"; + if (for_reading) + { + if (!FileExists(path.GetChars())) + { + path = ""; + } + } + else + { // check if writeable + FILE *checker = fopen (path.GetChars(), "a"); + if (checker == NULL) + { + path = ""; + } + else + { + fclose (checker); + } + } + } + return path; +} + +//=========================================================================== +// +// M_GetScreenshotsPath Windows +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +FString M_GetScreenshotsPath() +{ + FString path; + path = progdir; + return path; +} + +//=========================================================================== +// +// M_GetSavegamesPath Windows +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + FString path; + path = progdir; + return path; +} + +#elif defined(__APPLE__) + +//=========================================================================== +// +// M_GetCachePath Mac OS X +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath() +{ + FString path; + + char pathstr[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) + { + path = pathstr; + } + else + { + path = progdir; + } + path += "/zdoom/cache"; + return path; +} + +//=========================================================================== +// +// M_GetAutoexecPath Mac OS X +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + FString path; + + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/autoexec.cfg"; + } + return path; +} + +//=========================================================================== +// +// M_GetCajunPath Mac OS X +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + // Just copies the Windows code. Should this be more Mac-specific? + path << progdir << "zcajun/" << botfilename; + if (!FileExists(path)) + { + path = ""; + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Mac OS X +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + FString path; + path << cpath << "/zdoom.ini"; + return path; + } + // Ungh. + return "zdoom.ini"; +} + +//=========================================================================== +// +// M_GetScreenshotsPath Mac OS X +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +FString M_GetScreenshotsPath() +{ + FString path; + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/Screenshots/"; + } + else + { + path = "~/"; + } + return path; +} + +//=========================================================================== +// +// M_GetSavegamesPath Mac OS X +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + FString path; + char cpath[PATH_MAX]; + FSRef folder; + + if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && + noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) + { + path << cpath << "/" GAME_DIR "/Savegames/"; + } + return path; +} + +#else // Linux, et al. + +FString GetUserFile(const char *file) +{ + FString path; + struct stat info; + + path = NicePath("~/" GAME_DIR "/"); + + if (stat(path, &info) == -1) + { + struct stat extrainfo; + + // Sanity check for ~/.config + FString configPath = NicePath("~/.config/"); + if (stat(configPath, &extrainfo) == -1) + { + if (mkdir(configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + I_FatalError("Failed to create ~/.config directory:\n%s", strerror(errno)); + } + } + else if (!S_ISDIR(extrainfo.st_mode)) + { + I_FatalError("~/.config must be a directory"); + } + + // This can be removed after a release or two + // Transfer the old zdoom directory to the new location + bool moved = false; + FString oldpath = NicePath("~/.zdoom/"); + if (stat #if defined(__unix__) +FString GetUserFile (const char *file) +{ + FString path; + struct stat info; + + path = NicePath("~/" GAME_DIR "/"); + + if (stat (path, &info) == -1) + { + struct stat extrainfo; + + // Sanity check for ~/.config + FString configPath = NicePath("~/.config/"); + if (stat (configPath, &extrainfo) == -1) + { + if (mkdir (configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + I_FatalError ("Failed to create ~/.config directory:\n%s", strerror(errno)); + } + } + else if (!S_ISDIR(extrainfo.st_mode)) + { + I_FatalError ("~/.config must be a directory"); + } + + // This can be removed after a release or two + // Transfer the old zdoom directory to the new location + bool moved = false; + FString oldpath = NicePath("~/.zdoom/"); + if (stat (oldpath, &extrainfo) != -1) + { + if (rename(oldpath, path) == -1) + { + I_Error ("Failed to move old zdoom directory (%s) to new location (%s).", + oldpath.GetChars(), path.GetChars()); + } + else + moved = true; + } + + if (!moved && mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + I_FatalError ("Failed to create %s directory:\n%s", + path.GetChars(), strerror (errno)); + } + } + else + { + if (!S_ISDIR(info.st_mode)) + { + I_FatalError ("%s must be a directory", path.GetChars()); + } + } + path += file; + return path; +} + +//=========================================================================== +// +// M_GetCachePath Unix +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath() +{ + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + return NicePath("~/.config/zdoom/cache"); +} + +//=========================================================================== +// +// M_GetAutoexecPath Unix +// +// Returns the expected location of autoexec.cfg. +// +//=========================================================================== + +FString M_GetAutoexecPath() +{ + return GetUserFile("autoexec.cfg"); +} + +//=========================================================================== +// +// M_GetCajunPath Unix +// +// Returns the location of the Cajun Bot definitions. +// +//=========================================================================== + +FString M_GetCajunPath(const char *botfilename) +{ + FString path; + + // Check first in ~/.config/zdoom./botfilename. + path = GetUserFile(BOTFILENAME); + if (!FileExists(tmp)) + { + // Then check in SHARE_DIR/botfilename. (Some allowance for Macs + // should probably be made here.) + path = SHARE_DIR BOTFILENAME; + if (!FileExists(path)) + { + path =""; + } + } + return path; +} + +//=========================================================================== +// +// M_GetConfigPath Unix +// +// Returns the path to the config file. On Windows, this can vary for reading +// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try +// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. +// +//=========================================================================== + +FString M_GetConfigPath(bool for_reading) +{ + return GetUserFile("zdoom.ini"); +} + +//=========================================================================== +// +// M_GetScreenshotsPath Unix +// +// Returns the path to the default screenshots directory. +// +//=========================================================================== + +FString M_GetScreenshotsPath() +{ + return "~/" GAME_DIR "/screenshots/"; +} + +//=========================================================================== +// +// M_GetSavegamesPath Unix +// +// Returns the path to the default save games directory. +// +//=========================================================================== + +FString M_GetSavegamesPath() +{ + return = "~/" GAME_DIR; +} + +#endif diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 2665f69ba..7dde9c80f 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -43,17 +43,6 @@ #define rmdir _rmdir -// TODO, maybe: stop using DWORD so I don't need to worry about conflicting -// with Windows' typedef. Then I could just include the header file instead -// of declaring everything here. -#define MAX_PATH 260 -#define CSIDL_LOCAL_APPDATA 0x001c -extern "C" __declspec(dllimport) long __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, char *pszPath); - -#endif - -#ifdef __APPLE__ -#include #endif #include "templates.h" @@ -75,6 +64,7 @@ extern "C" __declspec(dllimport) long __stdcall SHGetFolderPathA(void *hwnd, int #include "x86.h" #include "version.h" #include "md5.h" +#include "m_misc.h" void P_GetPolySpots (MapData * lump, TArray &spots, TArray &anchors); @@ -1048,45 +1038,10 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) typedef TArray MemFile; -static FString GetCachePath() -{ - FString path; - -#ifdef _WIN32 - char pathstr[MAX_PATH]; - if (0 != SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pathstr)) - { // Failed (e.g. On Win9x): use program directory - path = progdir; - } - else - { - path = pathstr; - } - path += "/zdoom/cache"; -#elif defined(__APPLE__) - char pathstr[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) - { - path = pathstr; - } - else - { - path = progdir; - } - path += "/zdoom/cache"; -#else - // Don't use GAME_DIR and such so that ZDoom and its child ports can share the node cache. - path = NicePath("~/.config/zdoom/cache"); -#endif - return path; -} static FString CreateCacheName(MapData *map, bool create) { - FString path = GetCachePath(); + FString path = M_GetCachePath(); FString lumpname = Wads.GetLumpFullPath(map->lumpnum); int separator = lumpname.IndexOf(':'); path << '/' << lumpname.Left(separator); @@ -1299,7 +1254,7 @@ errorout: CCMD(clearnodecache) { TArray list; - FString path = GetCachePath(); + FString path = M_GetCachePath(); path += "/"; try diff --git a/src/version.h b/src/version.h index d7acf1e6a..5fee0bd83 100644 --- a/src/version.h +++ b/src/version.h @@ -95,8 +95,6 @@ const char *GetVersionString(); #define GAME_DIR ".config/zdoom" #elif defined(__APPLE__) #define GAME_DIR GAMENAME -#else -#define CDROM_DIR "C:\\ZDOOMDAT" #endif diff --git a/zdoom.vcproj b/zdoom.vcproj index 89cf4c7b0..b6ebdeb90 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -710,6 +710,10 @@ RelativePath=".\src\m_random.cpp" > + + From 0645053431884fafdcc7ede11694058b16d2b3af Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 14 Sep 2013 23:07:59 -0500 Subject: [PATCH 032/247] Add support for standard file paths on Windows. - If the current user does not have write permissions for the directory zdoom.exe is located in, use standard folder paths located in their home directory instead. This is a common scenario when people put ZDoom into Program Files. (Ironically, zdoom.ini used to be in AppData, buth then people complained when it wasn't in the same directory as zdoom.exe, so it got turned into zdoom-.ini so at least it could retain some multi-user support. I'm not sure when the AppData support was removed, though, since it should have still been kept around for migrating configs to the new name.) --- src/m_misc.cpp | 3 +- src/m_misc.h | 2 +- src/m_specialpaths.cpp | 242 +++++++++++++++++++++++++++++++++-------- src/p_glnodes.cpp | 4 +- 4 files changed, 202 insertions(+), 49 deletions(-) diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 14b9d9b1b..c550c4593 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -646,8 +646,9 @@ void M_ScreenShot (const char *filename) if (dirlen == 0) { autoname = M_GetScreenshotsPath(); + dirlen = autoname.Len(); } - else if (dirlen > 0) + if (dirlen > 0) { if (autoname[dirlen-1] != '/' && autoname[dirlen-1] != '\\') { diff --git a/src/m_misc.h b/src/m_misc.h index 327df3de4..90844221f 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -53,7 +53,7 @@ FString M_ZLibError(int zerrnum); #ifdef __unix__ FString GetUserFile (const char *path); // Prepends ~/.zdoom to path #endif -FString M_GetCachePath(); +FString M_GetCachePath(bool create); FString M_GetAutoexecPath(); FString M_GetCajunPath(const char *filename); FString M_GetConfigPath(bool for_reading); diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index 6f77551ae..cd116e538 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -14,6 +14,114 @@ #if defined(_WIN32) +#include "version.h" // for GAMENAME +typedef HRESULT (*GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); + +//=========================================================================== +// +// IsProgramDirectoryWritable +// +// If the program directory is writable, then dump everything in there for +// historical reasons. Otherwise, known folders get used instead. +// +//=========================================================================== + +bool UseKnownFolders() +{ + // Cache this value so the semantics don't change during a single run + // of the program. (e.g. Somebody could add write access while the + // program is running.) + static INTBOOL iswritable = -1; + FString testpath; + HANDLE file; + + if (iswritable >= 0) + { + return !iswritable; + } + testpath << progdir << "writest"; + file = CreateFile(testpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (file != INVALID_HANDLE_VALUE) + { + CloseHandle(file); + Printf("Using program directory for storage\n"); + iswritable = true; + return false; + } + Printf("Using known folders for storage\n"); + iswritable = false; + return true; +} + +//=========================================================================== +// +// GetKnownFolder +// +// Returns the known_folder if SHGetKnownFolderPath is available, otherwise +// returns the shell_folder using SHGetFolderPath. +// +//=========================================================================== + +bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path) +{ + static GKFP SHGetKnownFolderPath = NULL; + static bool tested = false; + + if (!tested) + { + tested = true; + HMODULE shell32 = GetModuleHandle("shell32.dll"); + if (shell32 != NULL) + { + SHGetKnownFolderPath = (GKFP)GetProcAddress(shell32, "SHGetKnownFolderPath"); + } + } + + char pathstr[MAX_PATH]; + + // SHGetKnownFolderPath knows about more folders than SHGetFolderPath, but is + // new to Vista, hence the reason we support both. + if (SHGetKnownFolderPath == NULL) + { + if (shell_folder < 0) + { // Not supported by SHGetFolderPath + return false; + } + if (create) + { + shell_folder |= CSIDL_FLAG_CREATE; + } + if (FAILED(SHGetFolderPathA(NULL, shell_folder, NULL, 0, pathstr))) + { + return false; + } + path = pathstr; + return true; + } + else + { + PWSTR wpath; + if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath))) + { + return false; + } + // FIXME: Support Unicode, at least for filenames. This function + // has no MBCS equivalent, so we have to convert it since we don't + // support Unicode. :( + bool converted = false; + if (WideCharToMultiByte(GetACP(), WC_NO_BEST_FIT_CHARS, wpath, -1, + pathstr, countof(pathstr), NULL, NULL) > 0) + { + path = pathstr; + converted = true; + } + CoTaskMemFree(wpath); + return converted; + } +} + //=========================================================================== // // M_GetCachePath Windows @@ -22,19 +130,14 @@ // //=========================================================================== -FString M_GetCachePath() +FString M_GetCachePath(bool create) { FString path; - char pathstr[MAX_PATH]; - if (0 != SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pathstr)) + if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) { // Failed (e.g. On Win9x): use program directory path = progdir; } - else - { - path = pathstr; - } // Don't use GAME_DIR and such so that ZDoom and its child ports can // share the node cache. path += "/zdoom/cache"; @@ -89,48 +192,50 @@ FString M_GetConfigPath(bool for_reading) FString path; HRESULT hr; - TCHAR uname[UNLEN+1]; - DWORD unamelen = countof(uname); - - // Because people complained, try for a user-specific .ini in the program directory first. - // If that is not writeable, use the one in the home directory instead. - hr = GetUserName(uname, &unamelen); - if (SUCCEEDED(hr) && uname[0] != 0) + // Construct a user-specific config name + if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path)) { - // Is it valid for a user name to have slashes? - // Check for them and substitute just in case. - char *probe = uname; - while (*probe != 0) - { - if (*probe == '\\' || *probe == '/') - *probe = '_'; - ++probe; - } + path += "/zdoom"; + CreatePath(path); + path += "/zdoom.ini"; + } + else + { // construct "$PROGDIR/zdoom-$USER.ini" + TCHAR uname[UNLEN+1]; + DWORD unamelen = countof(uname); path = progdir; - path += "zdoom-"; - path += uname; - path += ".ini"; - if (for_reading) + hr = GetUserName(uname, &unamelen); + if (SUCCEEDED(hr) && uname[0] != 0) { - if (!FileExists(path.GetChars())) + // Is it valid for a user name to have slashes? + // Check for them and substitute just in case. + char *probe = uname; + while (*probe != 0) { - path = ""; + if (*probe == '\\' || *probe == '/') + *probe = '_'; + ++probe; } + path << "zdoom-" << uname << ".ini"; } else - { // check if writeable - FILE *checker = fopen (path.GetChars(), "a"); - if (checker == NULL) - { - path = ""; - } - else - { - fclose (checker); - } + { // Couldn't get user name, so just use zdoom.ini + path += "zdoom.ini"; } } + + // If we are reading the config file, check if it exists. If not, fallback + // to $PROGDIR/zdoom.ini + if (for_reading) + { + if (!FileExists(path)) + { + path = progdir; + path << "zdoom.ini"; + } + } + return path; } @@ -142,10 +247,31 @@ FString M_GetConfigPath(bool for_reading) // //=========================================================================== +// I'm not sure when FOLDERID_Screenshots was added, but it was probably +// for Windows 8, since it's not in the v7.0 Windows SDK. +static const GUID MyFOLDERID_Screenshots = { 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f }; + FString M_GetScreenshotsPath() { FString path; - path = progdir; + + if (!UseKnownFolders()) + { + return progdir; + } + else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path)) + { + path << "/" GAMENAME; + } + else if (GetKnownFolder(CSIDL_MYPICTURES, FOLDERID_Pictures, true, path)) + { + path << "/Screenshots/" GAMENAME; + } + else + { + return progdir; + } + CreatePath(path); return path; } @@ -160,7 +286,28 @@ FString M_GetScreenshotsPath() FString M_GetSavegamesPath() { FString path; - path = progdir; + + if (!UseKnownFolders()) + { + return progdir; + } + // Try standard Saved Games folder + else if (GetKnownFolder(-1, FOLDERID_SavedGames, true, path)) + { + path << "/" GAMENAME; + } + // Try defacto My Documents/My Games folder + else if (GetKnownFolder(CSIDL_PERSONAL, FOLDERID_Documents, true, path)) + { + // I assume since this isn't a standard folder, it doesn't have + // a localized name either. + path << "/My Games/" GAMENAME; + CreatePath(path); + } + else + { + path = progdir; + } return path; } @@ -174,14 +321,14 @@ FString M_GetSavegamesPath() // //=========================================================================== -FString M_GetCachePath() +FString M_GetCachePath(bool create) { FString path; char pathstr[PATH_MAX]; FSRef folder; - if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &folder) && + if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) { path = pathstr; @@ -409,11 +556,16 @@ FString GetUserFile (const char *file) // //=========================================================================== -FString M_GetCachePath() +FString M_GetCachePath(bool create) { // Don't use GAME_DIR and such so that ZDoom and its child ports can // share the node cache. - return NicePath("~/.config/zdoom/cache"); + FString path = NicePath("~/.config/zdoom/cache"); + if (create) + { + CreatePath(create); + } + return path; } //=========================================================================== diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 7dde9c80f..b07d50aed 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1041,7 +1041,7 @@ typedef TArray MemFile; static FString CreateCacheName(MapData *map, bool create) { - FString path = M_GetCachePath(); + FString path = M_GetCachePath(create); FString lumpname = Wads.GetLumpFullPath(map->lumpnum); int separator = lumpname.IndexOf(':'); path << '/' << lumpname.Left(separator); @@ -1254,7 +1254,7 @@ errorout: CCMD(clearnodecache) { TArray list; - FString path = M_GetCachePath(); + FString path = M_GetCachePath(false); path += "/"; try From d36afb975ca7017920998998248e2f4f35b0229e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 15 Sep 2013 08:57:22 +0200 Subject: [PATCH 033/247] - fixed the Linux portion of m_specialpaths.cpp which had a section of GetUserFile duplicated. --- src/m_specialpaths.cpp | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index cd116e538..469a2fa6b 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -461,36 +461,7 @@ FString M_GetSavegamesPath() #else // Linux, et al. -FString GetUserFile(const char *file) -{ - FString path; - struct stat info; - path = NicePath("~/" GAME_DIR "/"); - - if (stat(path, &info) == -1) - { - struct stat extrainfo; - - // Sanity check for ~/.config - FString configPath = NicePath("~/.config/"); - if (stat(configPath, &extrainfo) == -1) - { - if (mkdir(configPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - { - I_FatalError("Failed to create ~/.config directory:\n%s", strerror(errno)); - } - } - else if (!S_ISDIR(extrainfo.st_mode)) - { - I_FatalError("~/.config must be a directory"); - } - - // This can be removed after a release or two - // Transfer the old zdoom directory to the new location - bool moved = false; - FString oldpath = NicePath("~/.zdoom/"); - if (stat #if defined(__unix__) FString GetUserFile (const char *file) { FString path; From 88b05fe2a10f20299a44ce7f23de7892489a552b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 17 Sep 2013 17:31:29 -0500 Subject: [PATCH 034/247] Fixed: SHGetKnownFolderPath needs to be declared as WINAPI. --- src/m_specialpaths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index cd116e538..469f7587e 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -15,7 +15,7 @@ #if defined(_WIN32) #include "version.h" // for GAMENAME -typedef HRESULT (*GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); +typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); //=========================================================================== // From e021fba5e1813636245baad445d260240da73a63 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 17 Sep 2013 20:44:13 -0500 Subject: [PATCH 035/247] Improve NoDelay reliability. - Instead of tying NoDelay behavior to OF_JustSpawned, use a new actor flag, MF7_HANDLENODELAY. This only gets cleared once it has actually been checked by Tick(). This is necessary because freeze mode delays the initial run of Tick() past the initial spawn, so OF_JustSpawned will no longer be set when it does the initial tick. - Delay NoDelay processing if an actor is spawned dormant. Actors spawned dormant have Deactivate() called before they tick, so MF7_HANDLENODELAY will remain set as long as an actor is dormant. This allows the NoDelay handling to occur as expected once it is activated. --- src/actor.h | 3 ++- src/dobject.h | 2 +- src/dthinker.cpp | 2 +- src/p_mobj.cpp | 27 ++++++++++++++++----------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/actor.h b/src/actor.h index c60b6a516..3a97ef49a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -334,11 +334,12 @@ enum MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts. -// --- mobj.flags6 --- +// --- mobj.flags7 --- MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered. MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO) MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings. + MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag // --- mobj.renderflags --- diff --git a/src/dobject.h b/src/dobject.h index 2ae5493c6..40b47ee5c 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -473,7 +473,7 @@ public: // use this method. virtual size_t PointerSubstitution (DObject *old, DObject *notOld); static size_t StaticPointerSubstitution (DObject *old, DObject *notOld); - + PClass *GetClass() const { if (Class == NULL) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 15206dabd..327b29731 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -457,7 +457,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest) node->PostBeginPlay(); } else if (dest != NULL) - { // Move thinker from this list to the destination list + { I_Error("There is a thinker in the fresh list that has already ticked.\n"); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 13f9de0af..492dd3389 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3525,19 +3525,23 @@ void AActor::Tick () Destroy(); return; } - if (ObjectFlags & OF_JustSpawned && state->GetNoDelay()) + if ((flags7 & MF7_HANDLENODELAY) && !(flags2 & MF2_DORMANT)) { - // For immediately spawned objects with the NoDelay flag set for their - // Spawn state, explicitly set the current state so that it calls its - // action and chains 0-tic states. - int starttics = tics; - if (!SetState(state)) - return; // freed itself - // If the initial state had a duration of 0 tics, let the next state run - // normally. Otherwise, increment tics by 1 so that we don't double up ticks. - if (starttics > 0 && tics >= 0) + flags7 &= ~MF7_HANDLENODELAY; + if (state->GetNoDelay()) { - tics++; + // For immediately spawned objects with the NoDelay flag set for their + // Spawn state, explicitly set the current state so that it calls its + // action and chains 0-tic states. + int starttics = tics; + if (!SetState(state)) + return; // freed itself + // If the initial state had a duration of 0 tics, let the next state run + // normally. Otherwise, increment tics by 1 so that we don't double up ticks. + else if (starttics > 0 && tics >= 0) + { + tics++; + } } } // cycle through states, calling action functions at transitions @@ -4024,6 +4028,7 @@ void AActor::PostBeginPlay () Renderer->StateChanged(this); } PrevAngle = angle; + flags7 |= MF7_HANDLENODELAY; } void AActor::MarkPrecacheSounds() const From f591c5df5e3a1a18c8d737777d1f7f5f62835c20 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 Sep 2013 09:40:40 +0200 Subject: [PATCH 036/247] - fixed: saving the config to the user's known folders should use the GAME_DIR #define, not 'zdoom' so that child ports can have their own. --- src/m_specialpaths.cpp | 2 +- src/version.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index 469a2fa6b..d9b776d58 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -195,7 +195,7 @@ FString M_GetConfigPath(bool for_reading) // Construct a user-specific config name if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path)) { - path += "/zdoom"; + path << '/' << GAME_DIR; CreatePath(path); path += "/zdoom.ini"; } diff --git a/src/version.h b/src/version.h index 5fee0bd83..b0717fbf8 100644 --- a/src/version.h +++ b/src/version.h @@ -95,6 +95,8 @@ const char *GetVersionString(); #define GAME_DIR ".config/zdoom" #elif defined(__APPLE__) #define GAME_DIR GAMENAME +#else +#define GAME_DIR "zdoom" #endif From e748c49dd0c672829d23ab31358e6671ebf5b215 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 18 Sep 2013 17:29:42 -0500 Subject: [PATCH 037/247] - Fixed: m_specialpaths.cpp did not compile under Linux. --- src/m_specialpaths.cpp | 31 +++++++++++++++++++------------ src/version.h | 6 ++---- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index 1f17f90c2..b4fcba3c3 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -12,9 +12,16 @@ #include "cmdlib.h" #include "m_misc.h" -#if defined(_WIN32) +#if !defined(__APPLE__) && !defined(_WIN32) +#include +#include +#include "i_system.h" +#endif #include "version.h" // for GAMENAME + +#if defined(_WIN32) + typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); //=========================================================================== @@ -195,7 +202,7 @@ FString M_GetConfigPath(bool for_reading) // Construct a user-specific config name if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path)) { - path << '/' << GAME_DIR; + path += "/" GAME_DIR; CreatePath(path); path += "/zdoom.ini"; } @@ -534,7 +541,7 @@ FString M_GetCachePath(bool create) FString path = NicePath("~/.config/zdoom/cache"); if (create) { - CreatePath(create); + CreatePath(path); } return path; } @@ -564,16 +571,16 @@ FString M_GetCajunPath(const char *botfilename) { FString path; - // Check first in ~/.config/zdoom./botfilename. - path = GetUserFile(BOTFILENAME); - if (!FileExists(tmp)) + // Check first in ~/.config/zdoom/botfilename. + path = GetUserFile(botfilename); + if (!FileExists(path)) { - // Then check in SHARE_DIR/botfilename. (Some allowance for Macs - // should probably be made here.) - path = SHARE_DIR BOTFILENAME; + // Then check in SHARE_DIR/botfilename. + path = SHARE_DIR; + path << botfilename; if (!FileExists(path)) { - path =""; + path = ""; } } return path; @@ -604,7 +611,7 @@ FString M_GetConfigPath(bool for_reading) FString M_GetScreenshotsPath() { - return "~/" GAME_DIR "/screenshots/"; + return NicePath("~/" GAME_DIR "/screenshots/"); } //=========================================================================== @@ -617,7 +624,7 @@ FString M_GetScreenshotsPath() FString M_GetSavegamesPath() { - return = "~/" GAME_DIR; + return NicePath("~/" GAME_DIR); } #endif diff --git a/src/version.h b/src/version.h index b0717fbf8..66e2f8938 100644 --- a/src/version.h +++ b/src/version.h @@ -91,12 +91,10 @@ const char *GetVersionString(); #define FORUM_URL "http://forum.zdoom.org" #define BUGS_FORUM_URL "http://forum.zdoom.org/index.php?c=3" -#ifdef __unix__ -#define GAME_DIR ".config/zdoom" -#elif defined(__APPLE__) +#if defined(__APPLE__) || defined(_WIN32) #define GAME_DIR GAMENAME #else -#define GAME_DIR "zdoom" +#define GAME_DIR ".config/zdoom" #endif From a144221174b99341051f26af21b39c4da8e450de Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 20 Sep 2013 10:43:10 +0200 Subject: [PATCH 038/247] - changed the invisible waiting frame of the ExplosiveBarrel to use TNTA10 instead of the real barrel frame. This is so that sprite checks do not erroneously determine that there's still something to see. GZDoom's dynamic light code has problems with this. --- wadsrc/static/actors/doom/doommisc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/actors/doom/doommisc.txt b/wadsrc/static/actors/doom/doommisc.txt index 131bb273d..fadab2b05 100644 --- a/wadsrc/static/actors/doom/doommisc.txt +++ b/wadsrc/static/actors/doom/doommisc.txt @@ -27,8 +27,8 @@ ACTOR ExplosiveBarrel 2035 BEXP C 5 BRIGHT BEXP D 5 BRIGHT A_Explode BEXP E 10 BRIGHT - BEXP E 1050 BRIGHT A_BarrelDestroy - BEXP E 5 A_Respawn + TNT1 A 1050 BRIGHT A_BarrelDestroy + TNT1 A 5 A_Respawn Wait } } From f73275ad8892fc6ce46d78b1318e6966ee5e8d44 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 21 Sep 2013 12:46:19 -0400 Subject: [PATCH 039/247] - Applied Tesseract's patch for drawimage extensions. (Extended icon support and maximum width/height.) --- src/g_shared/sbar.h | 16 ++- src/g_shared/sbarinfo.cpp | 8 +- src/g_shared/sbarinfo_commands.cpp | 165 +++++++++++++++++++++++------ src/g_shared/shared_hud.cpp | 48 ++++++--- 4 files changed, 188 insertions(+), 49 deletions(-) diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index 3d8c62001..b8dde5850 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -444,6 +444,20 @@ void ST_LoadCrosshair(bool alwaysload=false); void ST_Clear(); extern FTexture *CrosshairImage; -FTextureID GetWeaponIcon(AWeapon *weapon); +FTextureID GetInventoryIcon(AInventory *item, DWORD flags, bool *applyscale); + +enum DI_Flags +{ + DI_SKIPICON = 0x1, + DI_SKIPALTICON = 0x2, + DI_SKIPSPAWN = 0x4, + DI_SKIPREADY = 0x8, + DI_ALTICONFIRST = 0x10, + + DI_DRAWINBOX = 0x20, // Set when either width or height is not zero + + DI_FORCESCALE = 0x40, + DI_ALTERNATEONFAIL = 0x80 +}; #endif /* __SBAR_H__ */ diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 09be47363..3e1c364e2 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1187,8 +1187,12 @@ public: if((offsetflags & SBarInfoCommand::CENTER) == SBarInfoCommand::CENTER) { - dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble(); - dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble(); + if (forceWidth < 0) dx -= (texture->GetScaledWidthDouble()/2.0)-texture->GetScaledLeftOffsetDouble(); + else dx -= forceWidth*(0.5-(texture->GetScaledLeftOffsetDouble()/texture->GetScaledWidthDouble())); + //Unoptimalized formula is dx -= forceWidth/2.0-(texture->GetScaledLeftOffsetDouble()*forceWidth/texture->GetScaledWidthDouble()); + + if (forceHeight < 0) dy -= (texture->GetScaledHeightDouble()/2.0)-texture->GetScaledTopOffsetDouble(); + else dy -= forceHeight*(0.5-(texture->GetScaledTopOffsetDouble()/texture->GetScaledHeightDouble())); } dx += xOffset; diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index febf32b80..d5ee06d11 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -41,28 +41,65 @@ // classes. //////////////////////////////////////////////////////////////////////////////// - -class CommandDrawImage : public SBarInfoCommand +class CommandDrawImage : public SBarInfoCommandFlowControl { public: - CommandDrawImage(SBarInfo *script) : SBarInfoCommand(script), - translatable(false), type(NORMAL_IMAGE), image(-1), offset(static_cast (TOP|LEFT)), + CommandDrawImage(SBarInfo *script) : SBarInfoCommandFlowControl(script), + translatable(false), type(NORMAL_IMAGE), image(-1), maxwidth(-1), + maxheight(-1), spawnScaleX(1.0f), spawnScaleY(1.0f), flags(0), + applyscale(false), offset(static_cast (TOP|LEFT)), texture(NULL), alpha(FRACUNIT) { } void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) { + if(flags & DI_ALTERNATEONFAIL) + SBarInfoCommandFlowControl::Draw(block, statusBar); + if(texture == NULL) return; + int w = maxwidth, h = maxheight; + // We must calculate this per frame in order to prevent glitches with cl_capfps true. fixed_t frameAlpha = block->Alpha(); if(alpha != FRACUNIT) frameAlpha = fixed_t(((double) block->Alpha() / (double) FRACUNIT) * ((double) alpha / (double) OPAQUE) * FRACUNIT); - + + if(flags & DI_DRAWINBOX) + { + double scale1, scale2; + scale1 = scale2 = 1.0f; + double texwidth = (int) (texture->GetScaledWidthDouble()*spawnScaleX); + double texheight = (int) (texture->GetScaledHeightDouble()*spawnScaleY); + + if (w != -1 && (wGetScaledWidthDouble()*spawnScaleX); + h=(int) (texture->GetScaledHeightDouble()*spawnScaleY); + } statusBar->DrawGraphic(texture, imgx, imgy, block->XOffset(), block->YOffset(), frameAlpha, block->FullScreenOffsets(), - translatable, false, offset); + translatable, false, offset, false, w, h); } void Parse(FScanner &sc, bool fullScreenOffsets) { @@ -98,7 +135,7 @@ class CommandDrawImage : public SBarInfoCommand type = HEXENARMOR_AMULET; else { - sc.ScriptMessage("Unkown armor type: '%s'", sc.String); + sc.ScriptMessage("Unknown armor type: '%s'", sc.String); type = HEXENARMOR_ARMOR; } sc.MustGetToken(','); @@ -141,48 +178,90 @@ class CommandDrawImage : public SBarInfoCommand offset = CENTER; else if(sc.Compare("centerbottom")) offset = static_cast (HMIDDLE|BOTTOM); - else + else if(!sc.Compare("lefttop")) //That's already set sc.ScriptError("'%s' is not a valid alignment.", sc.String); } - sc.MustGetToken(';'); + if(sc.CheckToken(',')) + { + sc.MustGetToken(TK_IntConst); + if((maxwidth = sc.Number) > 0) + flags |= DI_DRAWINBOX; + else + maxwidth = -1; + sc.MustGetToken(','); + sc.MustGetToken(TK_IntConst); + if ((maxheight = sc.Number) > 0) + flags |= DI_DRAWINBOX; + else + maxheight = -1; + } + if(sc.CheckToken(',')) + { + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("skipicon")) + flags |= DI_SKIPICON; + else if(sc.Compare("skipalticon")) + flags |= DI_SKIPALTICON; + else if(sc.Compare("skipspawn")) + flags |= DI_SKIPSPAWN; + else if(sc.Compare("skipready")) + flags |= DI_SKIPREADY; + else if(sc.Compare("alticonfirst")) + flags |= DI_ALTICONFIRST; + else if(sc.Compare("forcescale")) + { + if(flags & DI_DRAWINBOX) + flags |= DI_FORCESCALE; + } + else if(sc.Compare("alternateonfail")) + flags |= DI_ALTERNATEONFAIL; + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|') && !sc.CheckToken(',')) break; + } + } + if(flags & DI_ALTERNATEONFAIL) + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + else + sc.MustGetToken(';'); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { + SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + texture = NULL; alpha = FRACUNIT; + if (applyscale) + { + spawnScaleX = spawnScaleY = 1.0f; + applyscale = false; + } if(type == PLAYERICON) texture = TexMan[statusBar->CPlayer->mo->ScoreIcon]; else if(type == AMMO1) { - if(statusBar->ammo1 != NULL) - texture = TexMan[statusBar->ammo1->Icon]; + AAmmo *ammo = statusBar->ammo1; + if(ammo != NULL) + GetIcon(ammo); } else if(type == AMMO2) { - if(statusBar->ammo2 != NULL) - texture = TexMan[statusBar->ammo2->Icon]; + AAmmo *ammo = statusBar->ammo2; + if(ammo != NULL) + GetIcon(ammo); } else if(type == ARMOR) { - if(statusBar->armor != NULL && statusBar->armor->Amount != 0) - texture = TexMan(statusBar->armor->Icon); + ABasicArmor *armor = statusBar->armor; + if(armor != NULL && armor->Amount != 0) + GetIcon(armor); } else if(type == WEAPONICON) { AWeapon *weapon = statusBar->CPlayer->ReadyWeapon; if(weapon != NULL) - { - FTextureID icon; - if (weapon->Icon.isValid()) - { - icon = weapon->Icon; - } - else - { - icon = GetWeaponIcon(weapon); - } - texture = TexMan[icon]; - } + GetIcon(weapon); } else if(type == SIGIL) { @@ -213,8 +292,26 @@ class CommandDrawImage : public SBarInfoCommand texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon); else if(image >= 0) texture = statusBar->Images[image]; + + if (flags & DI_ALTERNATEONFAIL) + { + SetTruth(texture == NULL || !(texture->GetID().isValid()), block, statusBar); + } } protected: + void GetIcon(AInventory *item) + { + FTextureID icon = GetInventoryIcon(item, flags, &applyscale); + + if (applyscale) + { + spawnScaleX = FIXED2FLOAT(item->scaleX); + spawnScaleY = FIXED2FLOAT(item->scaleY); + } + + texture = TexMan[icon]; + } + enum ImageType { PLAYERICON, @@ -238,6 +335,12 @@ class CommandDrawImage : public SBarInfoCommand ImageType type; int image; FTextureID sprite; + int maxwidth; + int maxheight; + double spawnScaleX; + double spawnScaleY; + DWORD flags; + bool applyscale; //Set remotely from from GetInventoryIcon when selected sprite comes from Spawn state // I'm using imgx/imgy here so that I can inherit drawimage with drawnumber for some commands. SBarInfoCoordinate imgx; SBarInfoCoordinate imgy; @@ -1479,11 +1582,11 @@ class CommandDrawMugShot : public SBarInfoCommand //////////////////////////////////////////////////////////////////////////////// -class CommandDrawSelectedInventory : public SBarInfoCommandFlowControl, private CommandDrawImage, private CommandDrawNumber +class CommandDrawSelectedInventory : public CommandDrawImage, private CommandDrawNumber { public: - CommandDrawSelectedInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), - CommandDrawImage(script), CommandDrawNumber(script), alternateOnEmpty(false), + CommandDrawSelectedInventory(SBarInfo *script) : CommandDrawImage(script), + CommandDrawNumber(script), alternateOnEmpty(false), artiflash(false), alwaysShowCounter(false) { length = INT_MAX; // Counter size @@ -3011,7 +3114,7 @@ class CommandDrawGem : public SBarInfoCommand else sc.ScriptError("Unknown drawgem flag '%s'.", sc.String); if(!sc.CheckToken('|')) - sc.MustGetToken(','); + sc.MustGetToken(','); } sc.MustGetToken(TK_StringConst); //chain chain = script->newImage(sc.String); diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 3416bb82d..964a28e2b 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -135,12 +135,12 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans if (tex) { - int texwidth=tex->GetWidth(); - int texheight=tex->GetHeight(); + double texwidth=tex->GetScaledWidthDouble(); + double texheight=tex->GetScaledHeightDouble(); - if (wGetClass()); + FTextureID picnum, AltIcon = GetHUDIcon(item->GetClass()); FState * state=NULL, *ReadyState; - FTextureID picnum = !AltIcon.isNull()? AltIcon : weapon->Icon; - - if (picnum.isNull()) + picnum.SetNull(); + if (flags & DI_ALTICONFIRST) { - if (weapon->SpawnState && weapon->SpawnState->sprite!=0) + if (!(flags & DI_SKIPALTICON) && AltIcon.isValid()) + picnum = AltIcon; + else if (!(flags & DI_SKIPICON)) + picnum = item->Icon; + } + else + { + if (!(flags & DI_SKIPICON) && item->Icon.isValid()) + picnum = item->Icon; + else if (!(flags & DI_SKIPALTICON)) + picnum = AltIcon; + } + + if (!picnum.isValid()) //isNull() is bad for checking, because picnum could be also invalid (-1) + { + if (!(flags & DI_SKIPSPAWN) && item->SpawnState && item->SpawnState->sprite!=0) { - state = weapon->SpawnState; + state = item->SpawnState; + + if (applyscale != NULL && !(flags & DI_FORCESCALE)) + { + *applyscale = true; + } } - // no spawn state - now try the ready state - else if ((ReadyState = weapon->FindState(NAME_Ready)) && ReadyState->sprite!=0) + // no spawn state - now try the ready state if it's weapon + else if (!(flags & DI_SKIPREADY) && item->GetClass()->IsDescendantOf(RUNTIME_CLASS(AWeapon)) && (ReadyState = item->FindState(NAME_Ready)) && ReadyState->sprite!=0) { state = ReadyState; } @@ -651,7 +669,7 @@ static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon) if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans=0xd999; } - FTextureID picnum = GetWeaponIcon(weapon); + FTextureID picnum = GetInventoryIcon(weapon, DI_ALTICONFIRST); if (picnum.isValid()) { From e8bcbd14fbbac6e407f1b85553024b9302da6ee3 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 21 Sep 2013 13:20:36 -0400 Subject: [PATCH 040/247] - Added vid_asyncblit for Linux and OS X. It defaults to true and sets SDL_AYNCBLIT on the frame buffer. This allows for ZDoom to obtain ~100% CPU usage with an uncapped frame rate on Linux like it should. (Not sure if it does anything for OS X yet.) It also makes uncapped play smoothly for me (as long as the frame rate is >= 2*refresh rate), but I'm not sure if capped feels more jittery or not. I could use some feedback here. Do note that vid_asyncblit requires a restart after the value is changed. --- src/sdl/i_video.h | 64 ----------------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 src/sdl/i_video.h diff --git a/src/sdl/i_video.h b/src/sdl/i_video.h deleted file mode 100644 index 2865df02f..000000000 --- a/src/sdl/i_video.h +++ /dev/null @@ -1,64 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// DESCRIPTION: -// System specific interface stuff. -// -//----------------------------------------------------------------------------- - - -#ifndef __I_VIDEO_H__ -#define __I_VIDEO_H__ - -#include "basictypes.h" - -class DCanvas; - -// [RH] Set the display mode -void I_SetMode (int &width, int &height, int &bits); - -// Takes full 8 bit values. -void I_SetPalette (DWORD *palette); - -void I_BeginUpdate (void); // [RH] Locks screen[0] -void I_FinishUpdate (void); -void I_FinishUpdateNoBlit (void); - -// Wait for vertical retrace or pause a bit. -void I_WaitVBL(int count); - -void I_ReadScreen (BYTE *scr); - -bool I_CheckResolution (int width, int height, int bits); -void I_ClosestResolution (int *width, int *height, int bits); -bool I_SetResolution (int width, int height, int bits); - -bool I_AllocateScreen (DCanvas *canvas, int width, int height, int bits); -void I_FreeScreen (DCanvas *canvas); - -void I_LockScreen (DCanvas *canvas); -void I_UnlockScreen (DCanvas *canvas); -void I_Blit (DCanvas *from, int srcx, int srcy, int srcwidth, int srcheight, - DCanvas *to, int destx, int desty, int destwidth, int destheight); - -enum EDisplayType -{ - DISPLAY_WindowOnly, - DISPLAY_FullscreenOnly, - DISPLAY_Both -}; - -#endif // __I_VIDEO_H__ From 658b4f7e0ff4bf723105fbafe993cfcd8fbc5964 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 21 Sep 2013 15:30:32 -0400 Subject: [PATCH 041/247] - For some reason git decided not to include the actual changes for the last commit. --- src/sdl/sdlvideo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdlvideo.cpp b/src/sdl/sdlvideo.cpp index 2f11b8bbd..92741d325 100644 --- a/src/sdl/sdlvideo.cpp +++ b/src/sdl/sdlvideo.cpp @@ -87,6 +87,10 @@ EXTERN_CVAR (Bool, cl_capfps) CVAR (Int, vid_displaybits, 8, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +// vid_asyncblit needs a restart to work. SDL doesn't seem to change if the +// frame buffer is changed at run time. +CVAR (Bool, vid_asyncblit, 1, CVAR_NOINITCALL|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + CUSTOM_CVAR (Float, rgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (screen != NULL) @@ -301,9 +305,8 @@ SDLFB::SDLFB (int width, int height, bool fullscreen) UpdatePending = false; NotPaletted = false; FlashAmount = 0; - Screen = SDL_SetVideoMode (width, height, vid_displaybits, - SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF|SDL_ANYFORMAT| + (vid_asyncblit ? SDL_ASYNCBLIT : 0)|SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF|SDL_ANYFORMAT| (fullscreen ? SDL_FULLSCREEN : 0)); if (Screen == NULL) From ffae34c5fd0977938bf46b673397b17c58bc99e7 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 30 Sep 2013 20:02:05 -0400 Subject: [PATCH 042/247] - Changed the new default alignment keyword for drawimage from topleft to none in order to allow a potential topleft without image offsets. --- src/g_shared/sbarinfo_commands.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index d5ee06d11..449079ab5 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -173,13 +173,18 @@ class CommandDrawImage : public SBarInfoCommandFlowControl GetCoordinates(sc, fullScreenOffsets, imgx, imgy); if(sc.CheckToken(',')) { - sc.MustGetToken(TK_Identifier); - if(sc.Compare("center")) - offset = CENTER; - else if(sc.Compare("centerbottom")) - offset = static_cast (HMIDDLE|BOTTOM); - else if(!sc.Compare("lefttop")) //That's already set - sc.ScriptError("'%s' is not a valid alignment.", sc.String); + // Use none instead of topleft in case we decide we want to use + // alignments to remove the offset from images. + if(!sc.CheckToken(TK_None)) + { + sc.MustGetToken(TK_Identifier); + if(sc.Compare("center")) + offset = CENTER; + else if(sc.Compare("centerbottom")) + offset = static_cast (HMIDDLE|BOTTOM); + else + sc.ScriptError("'%s' is not a valid alignment.", sc.String); + } } if(sc.CheckToken(',')) { From f386d6b1e3c2311e664dc6385c018ad39eb67edd Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 6 Oct 2013 14:37:51 -0400 Subject: [PATCH 043/247] - Embed the proper manifest file and group soure files when building Visual Studio projects with CMake. (The groups probably also apply to other project types as well.) --- src/CMakeLists.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4223598f5..4a05c8278 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -999,4 +999,35 @@ endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" S if( MSVC ) set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") + add_custom_command(TARGET zdoom POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#2 + COMMENT "Adding manifest..." + ) endif( MSVC ) + +source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+") +source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/oplsynth/.+") +source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.h oplsynth/dosbox/opl.cpp) +source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$") +source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$") +source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") +source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+") +source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+") +source_group("Games\\Heretic Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_heretic/.+") +source_group("Games\\Hexen Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_hexen/.+") +source_group("Games\\Raven Shared" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_raven/.+") +source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_strife/.+") +source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+") +source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") +source_group("Render Core\\Render Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.h$") +source_group("Render Core\\Render Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_.+\\.cpp$") +source_group("Render Data\\Resource Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.h$") +source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+\\.cpp$") +source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") +source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) +source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") +source_group("SFML" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") +source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") +source_group("Versioning" FILES version.h win32/zdoom.rc) +source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") +source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+") From 4ced90756acc631ee0285bc510c953ab662ccde6 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 8 Oct 2013 15:35:50 -0400 Subject: [PATCH 044/247] - Let CMake know about noncompiled cpp files so they can appear in project files. - Fixed: Somehow when I added a way to disable generator expressions I inverted the meaning of NO_GENERATOR_EXPRESSIONS. --- CMakeLists.txt | 6 +- src/CMakeLists.txt | 182 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 150 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0858ecab5..087535b69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,16 +19,16 @@ function( add_pk3 PK3_NAME PK3_DIR ) set( PK3_TARGET "pk3" ) endif( ${PK3_TARGET} STREQUAL "zdoom_pk3" ) - if( NO_GENERATOR_EXPRESSIONS ) + if( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $ DEPENDS zipdir ${PK3_DIR} ) - else( NO_GENERATOR_EXPRESSIONS ) + else( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} DEPENDS zipdir ${PK3_DIR} ) - endif( NO_GENERATOR_EXPRESSIONS ) + endif( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_target( ${PK3_TARGET} ALL DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4a05c8278..708e562c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -511,29 +511,46 @@ if( FLUIDSYNTH_FOUND ) endif( FLUIDSYNTH_FOUND ) # Start defining source files for ZDoom - +set( PLAT_WIN32_SOURCES + win32/eaxedit.cpp + win32/fb_d3d9.cpp + win32/fb_d3d9_wipe.cpp + win32/fb_ddraw.cpp + win32/hardware.cpp + win32/helperthread.cpp + win32/i_cd.cpp + win32/i_crash.cpp + win32/i_input.cpp + win32/i_keyboard.cpp + win32/i_mouse.cpp + win32/i_dijoy.cpp + win32/i_rawps2.cpp + win32/i_xinput.cpp + win32/i_main.cpp + win32/i_movie.cpp + win32/i_system.cpp + win32/st_start.cpp + win32/win32video.cpp ) +set( PLAT_SDL_SOURCES + sdl/crashcatcher.c + sdl/hardware.cpp + sdl/i_cd.cpp + sdl/i_input.cpp + sdl/i_joystick.cpp + sdl/i_main.cpp + sdl/i_movie.cpp + sdl/i_system.cpp + sdl/sdlvideo.cpp + sdl/st_start.cpp ) +set( PLAT_MAC_SOURCES + sdl/SDLMain.m + sdl/iwadpicker_cocoa.mm + sdl/i_system_cocoa.mm ) if( WIN32 ) set( SYSTEM_SOURCES_DIR win32 ) - set( SYSTEM_SOURCES - win32/eaxedit.cpp - win32/fb_d3d9.cpp - win32/fb_d3d9_wipe.cpp - win32/fb_ddraw.cpp - win32/hardware.cpp - win32/helperthread.cpp - win32/i_cd.cpp - win32/i_crash.cpp - win32/i_input.cpp - win32/i_keyboard.cpp - win32/i_mouse.cpp - win32/i_dijoy.cpp - win32/i_rawps2.cpp - win32/i_xinput.cpp - win32/i_main.cpp - win32/i_movie.cpp - win32/i_system.cpp - win32/st_start.cpp - win32/win32video.cpp ) + set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) + set( OTHER_SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ${PLAT_MAC_SOURCES} ) + if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) # CMake is not set up to compile and link rc files with GCC. :( add_custom_command( OUTPUT zdoom-rc.o @@ -545,19 +562,12 @@ if( WIN32 ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) else( WIN32 ) set( SYSTEM_SOURCES_DIR sdl ) - set( SYSTEM_SOURCES - sdl/crashcatcher.c - sdl/hardware.cpp - sdl/i_cd.cpp - sdl/i_input.cpp - sdl/i_joystick.cpp - sdl/i_main.cpp - sdl/i_movie.cpp - sdl/i_system.cpp - sdl/sdlvideo.cpp - sdl/st_start.cpp ) + set( SYSTEM_SOURCES ${PLAT_SDL_SOURCES} ) if( APPLE ) - set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m sdl/iwadpicker_cocoa.mm sdl/i_system_cocoa.mm ) + set( SYSTEM_SOURCES ${SYSTEM_SOURCES} ${PLAT_MAC_SOURCES} ) + set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ) + else( APPLE ) + set( OTHER_SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} ${PLAT_MAC_SOURCES} ) endif( APPLE ) endif( WIN32 ) @@ -627,8 +637,10 @@ file( GLOB HEADER_FILES intermission/*.h menu/*.h oplsynth/*.h + oplsynth/dosbox/*.h r_data/*.h resourcefiles/*.h + sdl/*.h sfmt/*.h sound/*.h textures/*.h @@ -637,8 +649,103 @@ file( GLOB HEADER_FILES *.h ) +# These files will be flagged as "headers" so that they appear in project files +# without being compiled. +set( NOT_COMPILED_SOURCE_FILES + ${OTHER_SYSTEM_SOURCES} + sc_man_scanner.h + sc_man_scanner.re + g_doom/a_arachnotron.cpp + g_doom/a_archvile.cpp + g_doom/a_bossbrain.cpp + g_doom/a_bruiser.cpp + g_doom/a_cacodemon.cpp + g_doom/a_cyberdemon.cpp + g_doom/a_demon.cpp + g_doom/a_doomimp.cpp + g_doom/a_doomweaps.cpp + g_doom/a_fatso.cpp + g_doom/a_keen.cpp + g_doom/a_lostsoul.cpp + g_doom/a_painelemental.cpp + g_doom/a_possessed.cpp + g_doom/a_revenant.cpp + g_doom/a_scriptedmarine.cpp + g_doom/a_spidermaster.cpp + g_heretic/a_chicken.cpp + g_heretic/a_dsparil.cpp + g_heretic/a_hereticartifacts.cpp + g_heretic/a_hereticimp.cpp + g_heretic/a_hereticweaps.cpp + g_heretic/a_ironlich.cpp + g_heretic/a_knight.cpp + g_heretic/a_wizard.cpp + g_hexen/a_bats.cpp + g_hexen/a_bishop.cpp + g_hexen/a_blastradius.cpp + g_hexen/a_boostarmor.cpp + g_hexen/a_centaur.cpp + g_hexen/a_clericflame.cpp + g_hexen/a_clericholy.cpp + g_hexen/a_clericmace.cpp + g_hexen/a_clericstaff.cpp + g_hexen/a_dragon.cpp + g_hexen/a_fighteraxe.cpp + g_hexen/a_fighterhammer.cpp + g_hexen/a_fighterplayer.cpp + g_hexen/a_fighterquietus.cpp + g_hexen/a_firedemon.cpp + g_hexen/a_flechette.cpp + g_hexen/a_fog.cpp + g_hexen/a_healingradius.cpp + g_hexen/a_heresiarch.cpp + g_hexen/a_hexenspecialdecs.cpp + g_hexen/a_iceguy.cpp + g_hexen/a_korax.cpp + g_hexen/a_magecone.cpp + g_hexen/a_magelightning.cpp + g_hexen/a_magestaff.cpp + g_hexen/a_pig.cpp + g_hexen/a_serpent.cpp + g_hexen/a_spike.cpp + g_hexen/a_summon.cpp + g_hexen/a_teleportother.cpp + g_hexen/a_wraith.cpp + g_strife/a_acolyte.cpp + g_strife/a_alienspectres.cpp + g_strife/a_coin.cpp + g_strife/a_crusader.cpp + g_strife/a_entityboss.cpp + g_strife/a_inquisitor.cpp + g_strife/a_oracle.cpp + g_strife/a_programmer.cpp + g_strife/a_reaver.cpp + g_strife/a_rebels.cpp + g_strife/a_sentinel.cpp + g_strife/a_stalker.cpp + g_strife/a_strifeitems.cpp + g_strife/a_strifeweapons.cpp + g_strife/a_templar.cpp + g_strife/a_thingstoblowup.cpp + g_shared/sbarinfo_commands.cpp + xlat/xlat_parser.y + xlat_parser.c + xlat_parser.h + + # We could have the ASM macro add these files, but it wouldn't add all + # platforms. + asm_ia32/a.asm + asm_ia32/misc.asm + asm_ia32/tmap.asm + asm_ia32/tmap2.asm + asm_ia32/tmap3.asm + asm_x86_64/tmap3.asm + asm_x86_64/tmap3.s +) + add_executable( zdoom WIN32 ${HEADER_FILES} + ${NOT_COMPILED_SOURCE_FILES} autostart.cpp ${ASM_SOURCES} ${SYSTEM_SOURCES} @@ -948,6 +1055,7 @@ add_executable( zdoom WIN32 set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) +set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") # [BL] Solaris requires these to be explicitly linked. @@ -1005,9 +1113,11 @@ if( MSVC ) ) endif( MSVC ) +source_group("Assembly Files\\ia32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_ia32/.+") +source_group("Assembly Files\\x86_64" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_x86_64/.+") source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+") source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/oplsynth/.+") -source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.h oplsynth/dosbox/opl.cpp) +source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h) source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$") source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$") source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+") @@ -1026,8 +1136,10 @@ source_group("Render Data\\Resource Sources" REGULAR_EXPRESSION "^${CMAKE_CURREN source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/textures/.+") source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") +source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+") source_group("SFML" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") source_group("Versioning" FILES version.h win32/zdoom.rc) source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") -source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+") +source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h) +source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h sc_man_scanner.re) From 1f723c10ae6e2c56d0a5569134228006bfe363b6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 9 Oct 2013 21:50:24 -0500 Subject: [PATCH 045/247] Add CF_INTERPVIEW for players. - Added CF_INTERPVIEW flag for players. A_SetPitch/A_SetAngle and the similar ACS APROPs set this when changing an angle. This forces the renderer to interpolate the view angles instead of updating with the latest mouse positions. The effect lasts one tick. --- src/actor.h | 4 ++++ src/d_player.h | 1 + src/p_acs.cpp | 12 ++++++++---- src/p_mobj.cpp | 24 ++++++++++++++++++++++++ src/p_user.cpp | 3 +++ src/r_utility.cpp | 1 + src/thingdef/thingdef_codeptr.cpp | 5 ++--- 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/actor.h b/src/actor.h index 3a97ef49a..f8b583101 100644 --- a/src/actor.h +++ b/src/actor.h @@ -764,6 +764,10 @@ public: return (PalEntry)GetClass()->Meta.GetMetaInt(AMETA_BloodColor); } + // These also set CF_INTERPVIEW for players. + void SetPitch(int p); + void SetAngle(angle_t ang); + const PClass *GetBloodType(int type = 0) const { const PClass *bloodcls; diff --git a/src/d_player.h b/src/d_player.h index f6f7674d7..22f01f490 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -198,6 +198,7 @@ typedef enum CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted + CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_DRAIN = 1 << 16, // Player owns a drain powerup CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;) CF_REFLECTION = 1 << 19, diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 21e0d5c0b..d70cc2c0b 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -8250,7 +8250,9 @@ scriptwait: if (STACK(2) == 0) { if (activator != NULL) - activator->angle = STACK(1) << 16; + { + activator->SetAngle(STACK(1) << 16); + } } else { @@ -8259,7 +8261,7 @@ scriptwait: while ( (actor = iterator.Next ()) ) { - actor->angle = STACK(1) << 16; + actor->SetAngle(STACK(1) << 16); } } sp -= 2; @@ -8269,7 +8271,9 @@ scriptwait: if (STACK(2) == 0) { if (activator != NULL) - activator->pitch = STACK(1) << 16; + { + activator->SetPitch(STACK(1) << 16); + } } else { @@ -8278,7 +8282,7 @@ scriptwait: while ( (actor = iterator.Next ()) ) { - actor->pitch = STACK(1) << 16; + actor->SetPitch(STACK(1) << 16); } } sp -= 2; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 492dd3389..69d4203fe 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2962,6 +2962,30 @@ void AActor::SetShade (int r, int g, int b) fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); } +void AActor::SetPitch(int p) +{ + if (p != pitch) + { + pitch = p; + if (player != NULL) + { + player->cheats |= CF_INTERPVIEW; + } + } +} + +void AActor::SetAngle(angle_t ang) +{ + if (ang != angle) + { + angle = ang; + if (player != NULL) + { + player->cheats |= CF_INTERPVIEW; + } + } +} + // // P_MobjThinker // diff --git a/src/p_user.cpp b/src/p_user.cpp index 901f6cfaa..938c7727f 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2252,6 +2252,9 @@ void P_PlayerThink (player_t *player) { player->inventorytics--; } + // Don't interpolate the view for more than one tic + player->cheats &= ~CF_INTERPVIEW; + // No-clip cheat if ((player->cheats & (CF_NOCLIP | CF_NOCLIP2)) == CF_NOCLIP2) { // No noclip2 without noclip diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 0b51578ed..606cca840 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -581,6 +581,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy); viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz); if (player != NULL && + !(player->cheats & CF_INTERPVIEW) && player - players == consoleplayer && camera == player->mo && !demoplayback && diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 9faeb7442..d48b18a2a 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3935,7 +3935,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { ACTION_PARAM_START(1); ACTION_PARAM_ANGLE(angle, 0); - self->angle = angle; + self->SetAngle(angle); } //=========================================================================== @@ -3973,8 +3973,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) } pitch = clamp(pitch, min, max); } - - self->pitch = pitch; + self->SetPitch(pitch); } //=========================================================================== From b9a1528747b5d98af77070518f2027612efdbd37 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 10 Oct 2013 17:40:15 -0700 Subject: [PATCH 046/247] - DYN_FLUIDSYNTH now defaults to ON. - Added ZDOOM_OUTPUT_OLDSTYLE (could probably use a more descriptive name) which causes CMake to vary the executable name by build type and place the exes and pk3s into the directory specified in ZDOOM_OUTPUT_DIR. - ALL_BUILD will now launch ZDoom. --- CMakeLists.txt | 16 +- CleanDirectoryList.cmake | 48 +++ CreateLaunchers.cmake | 336 +++++++++++++++++++ launcher-templates/genericlauncher.cmd.in | 14 + launcher-templates/launcher.env.cmd.in | 1 + launcher-templates/perconfig.vcproj.user.in | 28 ++ launcher-templates/perconfig.vcxproj.user.in | 7 + launcher-templates/targetlauncher.cmd.in | 8 + launcher-templates/vcproj.user.in | 10 + launcher-templates/vcxproj.user.in | 4 + src/CMakeLists.txt | 40 ++- 11 files changed, 496 insertions(+), 16 deletions(-) create mode 100644 CleanDirectoryList.cmake create mode 100644 CreateLaunchers.cmake create mode 100644 launcher-templates/genericlauncher.cmd.in create mode 100644 launcher-templates/launcher.env.cmd.in create mode 100644 launcher-templates/perconfig.vcproj.user.in create mode 100644 launcher-templates/perconfig.vcxproj.user.in create mode 100644 launcher-templates/targetlauncher.cmd.in create mode 100644 launcher-templates/vcproj.user.in create mode 100644 launcher-templates/vcxproj.user.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 087535b69..ecb4a5be7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required( VERSION 2.4 ) project(ZDoom) +list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ) +include( CreateLaunchers ) + # Generator expression are available some time in CMake 2.8. Due to # cmake_minimum_required, we can assume a minor version of > 7 implies major >= 2 if(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) @@ -19,16 +22,16 @@ function( add_pk3 PK3_NAME PK3_DIR ) set( PK3_TARGET "pk3" ) endif( ${PK3_TARGET} STREQUAL "zdoom_pk3" ) - if( NOT NO_GENERATOR_EXPRESSIONS ) + if( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $ DEPENDS zipdir ${PK3_DIR} ) - else( NOT NO_GENERATOR_EXPRESSIONS ) + else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} DEPENDS zipdir ${PK3_DIR} ) - endif( NOT NO_GENERATOR_EXPRESSIONS ) + endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_target( ${PK3_TARGET} ALL DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ) @@ -42,6 +45,13 @@ ENDIF( NOT CMAKE_BUILD_TYPE ) set( ZDOOM_OUTPUT_DIR ${CMAKE_BINARY_DIR} CACHE PATH "Directory where zdoom.pk3 and the executable will be created." ) set( ZDOOM_EXE_NAME "zdoom" CACHE FILEPATH "Name of the executable to create." ) +if( MSVC ) + # Allow the user to use ZDOOM_OUTPUT_DIR as a single release point. + # Use zdoom, zdoomd, zdoom64, and zdoomd64 for the binary names + option( ZDOOM_OUTPUT_OLDSTYLE "Don't use Release/Debug directories." OFF ) +else( MSVC ) + set( ZDOOM_OUTPUT_OLDSTYLE OFF ) +endif( MSVC ) if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." ) diff --git a/CleanDirectoryList.cmake b/CleanDirectoryList.cmake new file mode 100644 index 000000000..58b8963f9 --- /dev/null +++ b/CleanDirectoryList.cmake @@ -0,0 +1,48 @@ +# - Removes duplicate entries and non-directories from a provided list +# +# clean_directory_list( [...]) +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__clean_directory_list) + return() +endif() +set(__clean_directory_list YES) + +function(clean_directory_list _var) + # combine variable's current value with additional list items + set(_in ${${_var}} ${ARGN}) + + if(_in) + # Initial list cleaning + list(REMOVE_DUPLICATES _in) + + # Grab the absolute path of each actual directory + set(_out) + foreach(_dir ${_in}) + if(IS_DIRECTORY "${_dir}") + get_filename_component(_dir "${_dir}" ABSOLUTE) + file(TO_CMAKE_PATH "${_dir}" _dir) + list(APPEND _out "${_dir}") + endif() + endforeach() + + if(_out) + # Clean up the output list now + list(REMOVE_DUPLICATES _out) + endif() + + # return _out + set(${_var} "${_out}" PARENT_SCOPE) + endif() +endfunction() diff --git a/CreateLaunchers.cmake b/CreateLaunchers.cmake new file mode 100644 index 000000000..8acca1c17 --- /dev/null +++ b/CreateLaunchers.cmake @@ -0,0 +1,336 @@ +# - Create launchers to set working directory, env. vars, etc. +# +# include(CreateLaunchers) - to make these available +# guess_runtime_library_dirs( [ ...]) +# create_default_target_launcher( +# [ARGS ] +# [FORWARD_ARGS] +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# +# create_target_launcher( +# [ARGS ] +# [FORWARD_ARGS] +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# +# create_generic_launcher( +# [RUNTIME_LIBRARY_DIRS ] +# [WORKING_DIRECTORY ] +# [ENVIRONMENT [...]]) +# - sets GENERIC_LAUNCHER_COMMAND and GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION +# +# Requires these CMake modules: +# ListFilter +# ProgramFilesGlob +# CleanDirectoryList +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__create_launchers) + return() +endif() +set(__create_launchers YES) + +include(CleanDirectoryList) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_launchermoddir + ${CMAKE_CURRENT_LIST_FILE} + PATH) +set(_launchermoddir "${_launchermoddir}/launcher-templates") + +macro(_launcher_system_settings) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BITS 64) + else() + set(BITS 32) + endif() + + if(WIN32) + # Find user and system name + set(SYSTEM_NAME $ENV{USERDOMAIN}) + set(USER_NAME $ENV{USERNAME}) + set(VCPROJ_TYPE vcproj) + set(USERFILE_EXTENSION ${SYSTEM_NAME}.${USER_NAME}.user) + set(LAUNCHER_LINESEP " ") + if(MSVC90) + set(USERFILE_VC_VERSION 9.00) + elseif(MSVC80) + set(USERFILE_VC_VERSION 8.00) + elseif(MSVC71) + set(USERFILE_VC_VERSION 7.10) + elseif(MSVC10 OR (MSVC AND MSVC_VERSION GREATER 1600)) # 2010 or newer + set(LAUNCHER_LINESEP "\n") + set(USERFILE_VC_VERSION 10.00) + set(USERFILE_EXTENSION user) + set(VCPROJ_TYPE vcxproj) + endif() + if(BITS EQUAL 64) + set(USERFILE_PLATFORM x64) + else() + set(USERFILE_PLATFORM Win${BITS}) + endif() + set(_pathdelim ";") + set(_suffix "cmd") + else() + set(_pathdelim ":") + set(USERFILE_PLATFORM ${CMAKE_SYSTEM_NAME}${BITS}) + set(_suffix "sh") + find_package(GDB QUIET) + if(GDB_FOUND) + set(LAUNCHERS_GOT_GDB YES) + if(GDB_HAS_RETURN_CHILD_RESULT) + set(LAUNCHERS_GDB_ARG --return-child-result) + endif() + else() + set(LAUNCHERS_GOT_GDB) + endif() + endif() + + if(WIN32 AND NOT USERFILE_REMOTE_MACHINE) + site_name(USERFILE_REMOTE_MACHINE) + mark_as_advanced(USERFILE_REMOTE_MACHINE) + endif() +endmacro() + +macro(_launcher_process_args) + set(_nowhere) + set(_curdest _nowhere) + set(_val_args + ARGS + RUNTIME_LIBRARY_DIRS + WORKING_DIRECTORY + ENVIRONMENT) + set(_bool_args FORWARD_ARGS) + foreach(_arg ${_val_args} ${_bool_args}) + set(${_arg}) + endforeach() + foreach(_element ${ARGN}) + list(FIND _val_args "${_element}" _val_arg_find) + list(FIND _bool_args "${_element}" _bool_arg_find) + if("${_val_arg_find}" GREATER "-1") + set(_curdest "${_element}") + elseif("${_bool_arg_find}" GREATER "-1") + set("${_element}" ON) + set(_curdest _nowhere) + else() + list(APPEND ${_curdest} "${_element}") + endif() + endforeach() + + if(_nowhere) + message(FATAL_ERROR + "Syntax error in use of a function in CreateLaunchers!") + endif() + + # Turn into a list of native paths + set(_runtime_lib_dirs) + foreach(_dlldir ${RUNTIME_LIBRARY_DIRS}) + file(TO_NATIVE_PATH "${_dlldir}" _path) + set(_runtime_lib_dirs "${_runtime_lib_dirs}${_path}${_pathdelim}") + endforeach() + + if(NOT WORKING_DIRECTORY) + set(WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + + if(FORWARD_ARGS) + if(WIN32) + set(FWD_ARGS %*) + else() + set(FWD_ARGS $*) + endif() + else() + set(FWD_ARGS) + endif() + + set(USERFILE_WORKING_DIRECTORY "${WORKING_DIRECTORY}") + set(USERFILE_COMMAND_ARGUMENTS "${ARGS}") + set(LAUNCHERSCRIPT_COMMAND_ARGUMENTS "${ARGS} ${FWD_ARGS}") + + if(WIN32) + set(RUNTIME_LIBRARIES_ENVIRONMENT "PATH=${_runtime_lib_dirs};%PATH%") + file(READ + "${_launchermoddir}/launcher.env.cmd.in" + _cmdenv) + else() + if(APPLE) + set(RUNTIME_LIBRARIES_ENVIRONMENT + "DYLD_LIBRARY_PATH=${_runtime_lib_dirs}:$DYLD_LIBRARY_PATH") + else() + set(RUNTIME_LIBRARIES_ENVIRONMENT + "LD_LIBRARY_PATH=${_runtime_lib_dirs}:$LD_LIBRARY_PATH") + endif() + file(READ + "${_launchermoddir}/launcher.env.sh.in" + _cmdenv) + endif() + set(USERFILE_ENVIRONMENT "${RUNTIME_LIBRARIES_ENVIRONMENT}") + + set(USERFILE_ENV_COMMANDS) + foreach(_arg "${RUNTIME_LIBRARIES_ENVIRONMENT}" ${ENVIRONMENT}) + string(CONFIGURE + "@USERFILE_ENVIRONMENT@@LAUNCHER_LINESEP@@_arg@" + USERFILE_ENVIRONMENT + @ONLY) + string(CONFIGURE + "@USERFILE_ENV_COMMANDS@${_cmdenv}" + USERFILE_ENV_COMMANDS + @ONLY) + endforeach() +endmacro() + +macro(_launcher_produce_vcproj_user) + if(MSVC) + file(READ + "${_launchermoddir}/perconfig.${VCPROJ_TYPE}.user.in" + _perconfig) + set(USERFILE_CONFIGSECTIONS) + foreach(USERFILE_CONFIGNAME ${CMAKE_CONFIGURATION_TYPES}) + get_target_property(USERFILE_${USERFILE_CONFIGNAME}_COMMAND + ${_targetname} + LOCATION_${USERFILE_CONFIGNAME}) + file(TO_NATIVE_PATH + "${USERFILE_${USERFILE_CONFIGNAME}_COMMAND}" + USERFILE_${USERFILE_CONFIGNAME}_COMMAND) + string(CONFIGURE "${_perconfig}" _temp @ONLY ESCAPE_QUOTES) + string(CONFIGURE + "${USERFILE_CONFIGSECTIONS}${_temp}" + USERFILE_CONFIGSECTIONS + ESCAPE_QUOTES) + endforeach() + + + configure_file("${_launchermoddir}/${VCPROJ_TYPE}.user.in" + ${VCPROJNAME}.${VCPROJ_TYPE}.${USERFILE_EXTENSION} + @ONLY) + endif() + +endmacro() + +macro(_launcher_configure_executable _src _tmp _target) +# get_filename_component(_targetname "${_target}" NAME) + get_filename_component(_targetpath "${_target}" PATH) + configure_file("${_src}" + "${_tmp}" + @ONLY) + file(COPY "${_tmp}" + DESTINATION "${_targetpath}" + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endmacro() + +macro(_launcher_create_target_launcher) + if(CMAKE_CONFIGURATION_TYPES) + # Multi-config generator - multiple launchers + foreach(_config ${CMAKE_CONFIGURATION_TYPES}) + get_target_property(USERFILE_${_config}_COMMAND + ${_targetname} + LOCATION_${_config}) + file(TO_NATIVE_PATH + "${USERFILE_${_config}_COMMAND}" + USERFILE_COMMAND) + set(_fn "launch-${_targetname}-${_config}.${_suffix}") + _launcher_configure_executable("${_launchermoddir}/targetlauncher.${_suffix}.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_fn}" + "${CMAKE_CURRENT_BINARY_DIR}/${_fn}") + endforeach() + else() + # Single-config generator - single launcher + get_target_property(USERFILE_COMMAND + ${_targetname} + LOCATION) + file(TO_NATIVE_PATH + "${USERFILE_COMMAND}" + USERFILE_COMMAND) + _launcher_configure_executable("${_launchermoddir}/targetlauncher.${_suffix}.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/launch-${_targetname}.${_suffix}" + "${CMAKE_CURRENT_BINARY_DIR}/launch-${_targetname}.${_suffix}" + @ONLY) + endif() +endmacro() + +function(create_default_target_launcher _targetname) + _launcher_system_settings() + _launcher_process_args(${ARGN}) + + set(VCPROJNAME "${CMAKE_BINARY_DIR}/ALL_BUILD") + _launcher_produce_vcproj_user() + + _launcher_create_target_launcher() +endfunction() + +function(create_target_launcher _targetname) + _launcher_system_settings() + _launcher_process_args(${ARGN}) + + set(VCPROJNAME "${CMAKE_CURRENT_BINARY_DIR}/${_targetname}") + _launcher_produce_vcproj_user() + + _launcher_create_target_launcher() +endfunction() + +function(create_generic_launcher _launchername) + _launcher_system_settings() + _launcher_process_args(${ARGN}) + + if(NOT IS_ABSOLUTE _launchername) + set(_launchername + "${CMAKE_CURRENT_BINARY_DIR}/${_launchername}.${_suffix}") + else() + set(_launchername "${_launchername}.${_suffix}") + endif() + if(WIN32) + set(GENERIC_LAUNCHER_COMMAND "${_launchername}" PARENT_SCOPE) + set(GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION) + else() + set(GENERIC_LAUNCHER_COMMAND sh "${_launchername}" PARENT_SCOPE) + set(GENERIC_LAUNCHER_FAIL_REGULAR_EXPRESSION + "Program terminated with signal") + endif() + + _launcher_configure_executable("${_launchermoddir}/genericlauncher.${_suffix}.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/genericlauncher.${_suffix}.in" + "${_launchername}") +endfunction() + +function(guess_runtime_library_dirs _var) + # Start off with the link directories of the calling listfile's directory + get_directory_property(_libdirs LINK_DIRECTORIES) + + # Add additional libraries passed to the function + foreach(_lib ${ARGN}) + get_filename_component(_libdir "${_lib}" PATH) + list(APPEND _libdirs "${_libdir}") + endforeach() + + # Now, build a list of potential dll directories + set(_dlldirs) + foreach(_libdir ${_libdirs}) + # Add the libdir itself + list(APPEND _dlldirs "${_libdir}") + + # Look also in libdir/../bin since the dll might not be with the lib + get_filename_component(_libdir "${_libdir}/../bin" ABSOLUTE) + list(APPEND _dlldirs "${_libdir}") + endforeach() + + # Only keep the valid, unique directories + clean_directory_list(_dlldirs) + + # Return _dlldirs + set(${_var} "${_dlldirs}" PARENT_SCOPE) +endfunction() diff --git a/launcher-templates/genericlauncher.cmd.in b/launcher-templates/genericlauncher.cmd.in new file mode 100644 index 000000000..9a19bbc7a --- /dev/null +++ b/launcher-templates/genericlauncher.cmd.in @@ -0,0 +1,14 @@ +cd @USERFILE_WORKING_DIRECTORY@ +@USERFILE_ENV_COMMANDS@ + +IF NOT [x%1]==[x--debugger] GOTO SkipDebuggingMess + +ECHO Need to ditch the debugger! +SHIFT /1 +%1 %2 %3 %4 %5 %6 %7 %8 %9 +GOTO EOF + +:SkipDebuggingMess +%* + +:EOF \ No newline at end of file diff --git a/launcher-templates/launcher.env.cmd.in b/launcher-templates/launcher.env.cmd.in new file mode 100644 index 000000000..72a24e67e --- /dev/null +++ b/launcher-templates/launcher.env.cmd.in @@ -0,0 +1 @@ +set @_arg@ diff --git a/launcher-templates/perconfig.vcproj.user.in b/launcher-templates/perconfig.vcproj.user.in new file mode 100644 index 000000000..95cacecff --- /dev/null +++ b/launcher-templates/perconfig.vcproj.user.in @@ -0,0 +1,28 @@ + + + diff --git a/launcher-templates/perconfig.vcxproj.user.in b/launcher-templates/perconfig.vcxproj.user.in new file mode 100644 index 000000000..ef0237999 --- /dev/null +++ b/launcher-templates/perconfig.vcxproj.user.in @@ -0,0 +1,7 @@ + + @USERFILE_ENVIRONMENT@ + WindowsLocalDebugger + ${USERFILE_@USERFILE_CONFIGNAME@_COMMAND} + @USERFILE_COMMAND_ARGUMENTS@ + @USERFILE_WORKING_DIRECTORY@ + diff --git a/launcher-templates/targetlauncher.cmd.in b/launcher-templates/targetlauncher.cmd.in new file mode 100644 index 000000000..c5715d679 --- /dev/null +++ b/launcher-templates/targetlauncher.cmd.in @@ -0,0 +1,8 @@ +cd @USERFILE_WORKING_DIRECTORY@ +@USERFILE_ENV_COMMANDS@ +if [%1]==[--debugger] ( + SHIFT +) + +"@USERFILE_COMMAND@" @LAUNCHERSCRIPT_COMMAND_ARGUMENTS@ +pause diff --git a/launcher-templates/vcproj.user.in b/launcher-templates/vcproj.user.in new file mode 100644 index 000000000..117473d70 --- /dev/null +++ b/launcher-templates/vcproj.user.in @@ -0,0 +1,10 @@ + + + +@USERFILE_CONFIGSECTIONS@ + + diff --git a/launcher-templates/vcxproj.user.in b/launcher-templates/vcxproj.user.in new file mode 100644 index 000000000..f3e423835 --- /dev/null +++ b/launcher-templates/vcxproj.user.in @@ -0,0 +1,4 @@ + + +@USERFILE_CONFIGSECTIONS@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 464d6db97..7c6820423 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,7 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( APPLE ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ) +option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON ) if( CMAKE_SIZEOF_VOID_P MATCHES "8" ) set( X64 64 ) @@ -1087,10 +1087,32 @@ include_directories( . add_dependencies( zdoom revision_check ) -# RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. -# Linux distributions are slow to adopt 2.6. :( -set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) -set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +if( MSVC ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") + add_custom_command(TARGET zdoom POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#2 + COMMENT "Adding manifest..." + ) + + create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) +endif( MSVC ) + +if( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) + set_target_properties( zdoom PROPERTIES + RUNTIME_OUTPUT_NAME ${ZDOOM_EXE_NAME} + RUNTIME_OUTPUT_NAME_DEBUG ${ZDOOM_EXE_NAME}d + RUNTIME_OUTPUT_NAME_MINSIZEREL ${ZDOOM_EXE_NAME}msr + RUNTIME_OUTPUT_NAME_RELWITHDEBINFO ${ZDOOM_EXE_NAME}rd + ) + add_custom_command(TARGET zdoom POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ + COMMENT "Copying to output directory..." ) +else( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) + # RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. + # Linux distributions are slow to adopt 2.6. :( + set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) + set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +endif( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) if( NOT WIN32 ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) @@ -1108,14 +1130,6 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( SSE_MATTERS ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -if( MSVC ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") - add_custom_command(TARGET zdoom POST_BUILD - COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#2 - COMMENT "Adding manifest..." - ) -endif( MSVC ) - source_group("Assembly Files\\ia32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_ia32/.+") source_group("Assembly Files\\x86_64" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_x86_64/.+") source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+") From 3e90b65014e7e8bcef2762a52a4ed803fd33cdc7 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 12 Oct 2013 00:24:04 -0400 Subject: [PATCH 047/247] - Use release compiler flags for debug builds of third party libraries. --- CMakeLists.txt | 10 ++++++++++ bzip2/CMakeLists.txt | 2 ++ dumb/CMakeLists.txt | 2 ++ game-music-emu/CMakeLists.txt | 2 ++ jpeg-6b/CMakeLists.txt | 2 ++ lzma/CMakeLists.txt | 2 ++ zlib/CMakeLists.txt | 2 ++ 7 files changed, 22 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb4a5be7..48fe7145c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,16 @@ function( add_pk3 PK3_NAME PK3_DIR ) DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ) endfunction( add_pk3 ) +# Macro for building libraries without debugging information +macro( make_release_only ) + set( CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_RELEASE} ) + set( CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_RELEASE} ) + set( CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELEASE} ) + set( CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_RELEASE} ) + set( CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_RELEASE} ) + set( CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELEASE} ) +endmacro( make_release_only ) + IF( NOT CMAKE_BUILD_TYPE ) SET( CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." diff --git a/bzip2/CMakeLists.txt b/bzip2/CMakeLists.txt index 6006f491c..5f35eb346 100644 --- a/bzip2/CMakeLists.txt +++ b/bzip2/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) +make_release_only() + if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) diff --git a/dumb/CMakeLists.txt b/dumb/CMakeLists.txt index ee50c4a0a..178de53a9 100644 --- a/dumb/CMakeLists.txt +++ b/dumb/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) +make_release_only() + include( CheckFunctionExists ) # DUMB is much slower in a Debug build than a Release build, so we force a Release diff --git a/game-music-emu/CMakeLists.txt b/game-music-emu/CMakeLists.txt index 5c4a03043..f880023ab 100644 --- a/game-music-emu/CMakeLists.txt +++ b/game-music-emu/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required( VERSION 2.4 ) include( CheckCXXCompilerFlag ) +make_release_only() + # I don't plan on debugging this, so make it a release build. if( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) set( CMAKE_BUILD_TYPE "RelWithDebInfo" ) diff --git a/jpeg-6b/CMakeLists.txt b/jpeg-6b/CMakeLists.txt index 5c8b5972e..21096465e 100644 --- a/jpeg-6b/CMakeLists.txt +++ b/jpeg-6b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) +make_release_only() + if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) diff --git a/lzma/CMakeLists.txt b/lzma/CMakeLists.txt index 7582712fe..019383d42 100644 --- a/lzma/CMakeLists.txt +++ b/lzma/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) +make_release_only() + if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 7ac44940a..43795934d 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.4.4) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) +make_release_only() + project(zlib C) set(VERSION "1.2.7") From 03b75ae7c18d2eda22704c8f835270cd762ccc0f Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 12 Oct 2013 00:56:49 -0400 Subject: [PATCH 048/247] - Fixed a few flags for Visual Studio compilation. --- CMakeLists.txt | 8 +++++--- src/CMakeLists.txt | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48fe7145c..08fc30afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ find_package( ZLIB ) if( MSVC ) # Eliminate unreferenced functions and data # Perform identical COMDAT folding - set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt" ) + set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE" ) # String pooling # Function-level linking @@ -84,10 +84,10 @@ if( MSVC ) set( ALL_C_FLAGS "/GF /Gy /GR-" ) # Avoid CRT DLL dependancies in release builds - set( REL_C_FLAGS "/MT" ) + set( REL_C_FLAGS "/MT /Oy" ) # Debug allocations in debug builds - set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC" ) + set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd /Gm" ) # Disable warnings for unsecure CRT functions from VC8+ if( MSVC_VERSION GREATER 1399 ) @@ -98,9 +98,11 @@ if( MSVC ) string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} ) string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} ) string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ) + string(REPLACE "/MDd " " " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} ) string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} ) string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) + string(REPLACE "/MDd " " " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} ) string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) endif( MSVC ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7c6820423..16f0e51f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -430,6 +430,12 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( NOT NO_STRIP ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +# MSVC Flags + +if( MSVC ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DELAYLOAD:\"fmodex${X64}.dll\"" ) +endif( MSVC ) + # Check for functions that may or may not exist. CHECK_FUNCTION_EXISTS( filelength FILELENGTH_EXISTS ) From 0759a4b4383d8cceb5fc2f132bcc784db180dd1b Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 12 Oct 2013 01:44:57 -0400 Subject: [PATCH 049/247] - Actually, lets not use /Gm since it's incompatible with /MP which will be much faster on multi-core machines. - Added ZDOOM_GENERATE_MAPFILE which enables linker map file generation. --- CMakeLists.txt | 6 +++--- src/CMakeLists.txt | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08fc30afb..4740603b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,12 +39,12 @@ endfunction( add_pk3 ) # Macro for building libraries without debugging information macro( make_release_only ) - set( CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_RELEASE} ) set( CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_RELEASE} ) set( CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELEASE} ) - set( CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_RELEASE} ) + string( REPLACE "/MT " "/MTd " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_RELEASE} ) set( CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_RELEASE} ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELEASE} ) + string( REPLACE "/MT " "/MTd " CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_RELEASE} ) endmacro( make_release_only ) IF( NOT CMAKE_BUILD_TYPE ) @@ -87,7 +87,7 @@ if( MSVC ) set( REL_C_FLAGS "/MT /Oy" ) # Debug allocations in debug builds - set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd /Gm" ) + set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" ) # Disable warnings for unsecure CRT functions from VC8+ if( MSVC_VERSION GREATER 1399 ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16f0e51f0..23b689847 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1093,8 +1093,22 @@ include_directories( . add_dependencies( zdoom revision_check ) +# Due to some quirks, we need to do this in this order +if( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + # RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. + # Linux distributions are slow to adopt 2.6. :( + set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) + set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + if( MSVC ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") + option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) + if( ZDOOM_GENERATE_MAPFILE ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") + else( ZDOOM_GENERATE_MAPFILE ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /MAP:${ZDOOM_EXE_NAME}.map") + endif( ZDOOM_GENERATE_MAPFILE ) + add_custom_command(TARGET zdoom POST_BUILD COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#2 COMMENT "Adding manifest..." @@ -1103,22 +1117,25 @@ if( MSVC ) create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) endif( MSVC ) -if( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) +if( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSIONS ) set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_NAME ${ZDOOM_EXE_NAME} RUNTIME_OUTPUT_NAME_DEBUG ${ZDOOM_EXE_NAME}d RUNTIME_OUTPUT_NAME_MINSIZEREL ${ZDOOM_EXE_NAME}msr RUNTIME_OUTPUT_NAME_RELWITHDEBINFO ${ZDOOM_EXE_NAME}rd ) - add_custom_command(TARGET zdoom POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ - COMMENT "Copying to output directory..." ) -else( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) - # RUNTIME_OUTPUT_DIRECTORY does not exist in CMake 2.4. - # Linux distributions are slow to adopt 2.6. :( - set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) - set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) -endif( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSION ) + + if( ZDOOM_GENERATE_MAPFILE ) + add_custom_command(TARGET zdoom POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ + COMMAND ${CMAKE_COMMAND} -E copy_if_different $/zdoom.map ${ZDOOM_OUTPUT_DIR}/$.map + COMMENT "Copying to output directory..." ) + else( ZDOOM_GENERATE_MAPFILE ) + add_custom_command(TARGET zdoom POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ + COMMENT "Copying to output directory..." ) + endif( ZDOOM_GENERATE_MAPFILE ) +endif( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSIONS ) if( NOT WIN32 ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) From 7dbf4ec38f3e08ec0fe9aeb8f994ae807acf5845 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 12 Oct 2013 01:58:39 -0400 Subject: [PATCH 050/247] - Slight cleanup and I accidentally inverted the map generation flag. --- src/CMakeLists.txt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23b689847..9506e6a59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -430,12 +430,6 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( NOT NO_STRIP ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -# MSVC Flags - -if( MSVC ) - set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DELAYLOAD:\"fmodex${X64}.dll\"" ) -endif( MSVC ) - # Check for functions that may or may not exist. CHECK_FUNCTION_EXISTS( filelength FILELENGTH_EXISTS ) @@ -1104,9 +1098,9 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) if( ZDOOM_GENERATE_MAPFILE ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO") + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:${ZDOOM_EXE_NAME}.map") else( ZDOOM_GENERATE_MAPFILE ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /MAP:${ZDOOM_EXE_NAME}.map") + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") endif( ZDOOM_GENERATE_MAPFILE ) add_custom_command(TARGET zdoom POST_BUILD From f0b946c3cf73266d1d849e424a37330c39707bd1 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Wed, 6 Nov 2013 13:37:34 -0500 Subject: [PATCH 051/247] - Allow use of system GME library. It defaults to forcing the use of the internal library at least for now though. --- CMakeLists.txt | 19 ++++++++++++++++++- src/CMakeLists.txt | 7 +++---- src/sound/music_gme.cpp | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4740603b0..3715cdac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(ZDoom) list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ) include( CreateLaunchers ) +include( FindPackageHandleStandardArgs ) # Generator expression are available some time in CMake 2.8. Due to # cmake_minimum_required, we can assume a minor version of > 7 implies major >= 2 @@ -72,6 +73,13 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}") find_package( BZip2 ) find_package( JPEG ) find_package( ZLIB ) +# GME +find_path( GME_INCLUDE_DIR gme.h ) +find_library( GME_LIBRARIES gme ) +mark_as_advanced( GME_INCLUDE_DIR GME_LIBRARIES ) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME + REQUIRED_VARS GME_LIBRARIES GME_INCLUDE_DIR +) if( MSVC ) # Eliminate unreferenced functions and data @@ -125,6 +133,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) option(FORCE_INTERNAL_ZLIB "Use internal zlib") option(FORCE_INTERNAL_JPEG "Use internal jpeg") option(FORCE_INTERNAL_BZIP2 "Use internal bzip2") +option(FORCE_INTERNAL_GME "Use internal gme" ON) if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB ) message( STATUS "Using system zlib" ) @@ -156,11 +165,19 @@ else( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 ) set( BZIP2_LIBRARY bz2 ) endif( BZIP2_FOUND AND NOT FORCE_INTERNAL_BZIP2 ) +if( GME_FOUND AND NOT FORCE_INTERNAL_GME ) + message( STATUS "Using system gme library ${GME_INCLUDE_DIR}" ) +else( GME_FOUND AND NOT FORCE_INTERNAL_GME ) + message( STATUS "Using internal gme library" ) + add_subdirectory( game-music-emu ) + set( GME_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/game-music-emu" ) + set( GME_LIBRARIES gme ) +endif( GME_FOUND AND NOT FORCE_INTERNAL_GME ) + set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lzma/C" ) add_subdirectory( lzma ) add_subdirectory( tools ) -add_subdirectory( game-music-emu ) add_subdirectory( dumb ) add_subdirectory( gdtoa ) add_subdirectory( wadsrc ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9506e6a59..268c1d705 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -503,8 +503,8 @@ add_custom_target( revision_check ALL # Libraries ZDoom needs message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) -set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" ) -include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" ) +set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${FMOD_LIBRARY}" ) +include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" ) if( FLUIDSYNTH_FOUND ) if( NOT DYN_FLUIDSYNTH) @@ -1065,7 +1065,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") set( ZDOOM_LIBS ${ZDOOM_LIBS} nsl socket) endif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") -target_link_libraries( zdoom ${ZDOOM_LIBS} gme gdtoa dumb lzma ) +target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma ) include_directories( . g_doom g_heretic @@ -1079,7 +1079,6 @@ include_directories( . thingdef timidity xlat - ../game-music-emu/gme ../gdtoa ../dumb/include ${CMAKE_BINARY_DIR}/gdtoa diff --git a/src/sound/music_gme.cpp b/src/sound/music_gme.cpp index 0c3d8c8c3..7f017b7d2 100644 --- a/src/sound/music_gme.cpp +++ b/src/sound/music_gme.cpp @@ -40,7 +40,7 @@ #include "i_musicinterns.h" #include "c_cvars.h" #include "critsec.h" -#include "gme.h" +#include #include "v_text.h" // MACROS ------------------------------------------------------------------ From 34457ce737ed2b67d7c928f27d853cc4a76a3de1 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Wed, 6 Nov 2013 13:42:05 -0500 Subject: [PATCH 052/247] - Applied VoidMage's patch to strip color codes from system console on SDL platforms. --- src/sdl/i_system.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index ba126bf54..03cbd74bf 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -422,7 +422,27 @@ void I_SetIWADInfo () void I_PrintStr (const char *cp) { - fputs (cp, stdout); + // Strip out any color escape sequences before writing to the log file + char * copy = new char[strlen(cp)+1]; + const char * srcp = cp; + char * dstp = copy; + + while (*srcp != 0) + { + if (*srcp!=0x1c && *srcp!=0x1d && *srcp!=0x1e && *srcp!=0x1f) + { + *dstp++=*srcp++; + } + else + { + if (srcp[1]!=0) srcp+=2; + else break; + } + } + *dstp=0; + + fputs (copy, stdout); + delete [] copy; fflush (stdout); } From a967b05290f324787358b751b06d145d463c6629 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 11 Nov 2013 20:42:54 +1300 Subject: [PATCH 053/247] Improvements to restoring stalled netgames - The waiting message is now always cleared, regardless if it needed to be in the first place. It's a rather simple for-loop so I doubt it matters. - Nodes are also cleared from the list if they catch up while other nodes are still behind. - "lastglobalrecvtime" is now bumped after the waiting loop if a tic was successful, rather then bumping it every time a packet was received. It appears that you can receive a packet before the game knows it stalled, thus stalling it anyway. - Instead of comparing the nettics to the local node, all nodes are tested against gametic+counts (the real reason why the game has stopped). - More then one node can be marked as late at any one time. - In a packet-server game, the arbitrator is now assumed slow, rather then testing it. There is no point, seeing as we already know the game has stalled because of it. --- src/d_net.cpp | 52 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 0ea8e58c5..9c4bf14dd 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -704,8 +704,6 @@ void GetPackets (void) } continue; // extra setup packet } - - lastglobalrecvtime = I_GetTime (false); //Update the last time a packet was recieved netnode = doomcom.remotenode; netconsole = playerfornode[netnode] & ~PL_DRONE; @@ -1827,30 +1825,39 @@ void TryRunTics (void) I_Error ("TryRunTics: lowtic < gametic"); // [Ed850] Check to see the last time a packet was recieved. - // If it's longer then 3 seconds, a node has likely stalled. Check which one and re-request its last packet. + // If it's longer then 3 seconds, a node has likely stalled. if(I_GetTime(false) - lastglobalrecvtime >= TICRATE*3) { - int latenode = 0; // Node 0 is the local player, and should always be the highest lastglobalrecvtime = I_GetTime(false); //Bump the count if(NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) { + //Keep the local node in the for loop so we can still log any cases where the local node is /somehow/ late. + //However, we don't send a resend request for sanity reasons. for (i = 0; i < doomcom.numnodes; i++) - if (nodeingame[i] && nettics[i] < nettics[latenode]) - latenode = i; + { + if (nodeingame[i] && nettics[i] < gametic + counts) + { + if (debugfile) + fprintf (debugfile, "%i is slow (%i to %i)\n", + i, nettics[i], gametic+counts); + //Send resend request to the late node. Also mark the node as waiting to display it in the hud. + if(i != 0) + remoteresend[i] = players[playerfornode[i]].waiting = hadlate = true; + } + else + players[playerfornode[i]].waiting = false; + } } - else if (nodeingame[nodeforplayer[Net_Arbitrator]] && - nettics[nodeforplayer[Net_Arbitrator]] < nettics[0]) - { // Likely a packet server game. Only check the packet host. - latenode = Net_Arbitrator; + else + { //Send a resend request to the Arbitrator, as it's obvious we are stuck here. + if (debugfile) + fprintf (debugfile, "Arbitrator is slow (%i to %i)\n", + Net_Arbitrator, nettics[Net_Arbitrator], gametic+counts); + //Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud. + if(i != 0) + remoteresend[Net_Arbitrator] = players[playerfornode[Net_Arbitrator]].waiting = hadlate = true; } - - if (debugfile) - fprintf (debugfile, "lost tics from %i (%i to %i)\n", - latenode, nettics[latenode], gametic); - - if(latenode != 0) // Send resend request to late node (if not yourself... somehow). Also mark the node as waiting to display it in the hud. - remoteresend[latenode] = players[playerfornode[latenode]].waiting = hadlate = true; } // don't stay in here forever -- give the menu a chance to work @@ -1862,12 +1869,11 @@ void TryRunTics (void) } } - if (hadlate) - { - hadlate = false; - for (i = 0; i < MAXPLAYERS; i++) - players[i].waiting = false; - } + //Tic lowtic is high enough to process this gametic. Clear all possible waiting info + hadlate = false; + for (i = 0; i < MAXPLAYERS; i++) + players[i].waiting = false; + lastglobalrecvtime = I_GetTime (false); //Update the last time the game tic'd over // run the count tics if (counts > 0) From c7099744bd11baae1b8dd8c793faeeb95ab435fd Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 11 Nov 2013 23:56:58 -0500 Subject: [PATCH 054/247] - Minor changes to the CMake since it looks like VS2005 doesn't support a few things that were added. --- src/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 268c1d705..7a9b0138d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -143,6 +143,11 @@ if( WIN32 ) ws2_32 setupapi oleaut32 ) + + # For some reason this isn't implied on 2005 + if( MSVC80 ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} DelayImp ) + endif( MSVC80 ) else( WIN32 ) if( APPLE ) set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) @@ -1097,7 +1102,11 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) if( ZDOOM_GENERATE_MAPFILE ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:${ZDOOM_EXE_NAME}.map") + if( NOT MSVC80 ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:${ZDOOM_EXE_NAME}.map") + else( NOT MSVC80 ) # 2005 doesn't support naming the map file. + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") + endif( NOT MSVC80 ) else( ZDOOM_GENERATE_MAPFILE ) set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") endif( ZDOOM_GENERATE_MAPFILE ) From 62ffe7e4e2673225aea12c4687a4770305c3d639 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 19 Nov 2013 19:42:13 -0600 Subject: [PATCH 055/247] Add NOGRAVITY to every Raven actor with FLOATBOB - Fixed: Heretic and Hexen completely skip all normal Z processing on mobjs with FLOATBOB set. To emulate that, we need to add NOGRAVITY to everything with that flag set. --- wadsrc/static/actors/heretic/hereticammo.txt | 1 + wadsrc/static/actors/heretic/hereticarmor.txt | 2 ++ wadsrc/static/actors/heretic/hereticartifacts.txt | 4 ++++ wadsrc/static/actors/hexen/blastradius.txt | 1 + wadsrc/static/actors/hexen/boostarmor.txt | 1 + wadsrc/static/actors/hexen/clericholy.txt | 1 + wadsrc/static/actors/hexen/fighterquietus.txt | 1 + wadsrc/static/actors/hexen/flechette.txt | 1 + wadsrc/static/actors/hexen/fog.txt | 1 + wadsrc/static/actors/hexen/healingradius.txt | 1 + wadsrc/static/actors/hexen/magestaff.txt | 1 + wadsrc/static/actors/hexen/mana.txt | 4 ++++ wadsrc/static/actors/hexen/speedboots.txt | 1 + wadsrc/static/actors/hexen/summon.txt | 1 + wadsrc/static/actors/hexen/teleportother.txt | 1 + wadsrc/static/actors/raven/artiegg.txt | 2 ++ wadsrc/static/actors/raven/artitele.txt | 1 + wadsrc/static/actors/raven/ravenartifacts.txt | 6 ++++++ wadsrc/static/actors/raven/ravenhealth.txt | 1 + 19 files changed, 32 insertions(+) diff --git a/wadsrc/static/actors/heretic/hereticammo.txt b/wadsrc/static/actors/heretic/hereticammo.txt index 96a20352b..8f02cce0a 100644 --- a/wadsrc/static/actors/heretic/hereticammo.txt +++ b/wadsrc/static/actors/heretic/hereticammo.txt @@ -221,6 +221,7 @@ ACTOR BagOfHolding : BackpackItem 8 Inventory.PickupMessage "$TXT_ITEMBAGOFHOLDING" +COUNTITEM +FLOATBOB + +NOGRAVITY States { Spawn: diff --git a/wadsrc/static/actors/heretic/hereticarmor.txt b/wadsrc/static/actors/heretic/hereticarmor.txt index e027f4f47..40ca671da 100644 --- a/wadsrc/static/actors/heretic/hereticarmor.txt +++ b/wadsrc/static/actors/heretic/hereticarmor.txt @@ -6,6 +6,7 @@ Actor SilverShield : BasicArmorPickup 85 Game Heretic SpawnID 68 +FLOATBOB + +NOGRAVITY Inventory.Pickupmessage "$TXT_ITEMSHIELD1" Inventory.Icon "SHLDA0" Armor.Savepercent 50 @@ -25,6 +26,7 @@ Actor EnchantedShield : BasicArmorPickup 31 Game Heretic SpawnID 69 +FLOATBOB + +NOGRAVITY Inventory.Pickupmessage "$TXT_ITEMSHIELD2" Inventory.Icon "SHD2A0" Armor.Savepercent 75 diff --git a/wadsrc/static/actors/heretic/hereticartifacts.txt b/wadsrc/static/actors/heretic/hereticartifacts.txt index 67d3946b9..404e5ba39 100644 --- a/wadsrc/static/actors/heretic/hereticartifacts.txt +++ b/wadsrc/static/actors/heretic/hereticartifacts.txt @@ -7,6 +7,7 @@ ACTOR SuperMap : MapRevealer 35 +COUNTITEM +INVENTORY.ALWAYSPICKUP +FLOATBOB + +NOGRAVITY Inventory.MaxAmount 0 Inventory.PickupMessage "$TXT_ITEMSUPERMAP" States @@ -26,6 +27,7 @@ ACTOR ArtiInvisibility : PowerupGiver 75 SpawnID 135 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH RenderStyle Translucent Alpha 0.4 @@ -51,6 +53,7 @@ ACTOR ArtiTomeOfPower : PowerupGiver 86 native SpawnID 134 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.Icon "ARTIPWBK" Powerup.Type Weaponlevel2 @@ -94,6 +97,7 @@ ACTOR ArtiTimeBomb : Inventory 34 native SpawnID 72 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.INVBAR +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/blastradius.txt b/wadsrc/static/actors/hexen/blastradius.txt index ad98d7ecc..28af3e698 100644 --- a/wadsrc/static/actors/hexen/blastradius.txt +++ b/wadsrc/static/actors/hexen/blastradius.txt @@ -4,6 +4,7 @@ ACTOR ArtiBlastRadius : CustomInventory 10110 Game Hexen SpawnID 74 +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/boostarmor.txt b/wadsrc/static/actors/hexen/boostarmor.txt index 607c8d66a..8aa6b6eeb 100644 --- a/wadsrc/static/actors/hexen/boostarmor.txt +++ b/wadsrc/static/actors/hexen/boostarmor.txt @@ -7,6 +7,7 @@ ACTOR ArtiBoostArmor : Inventory 8041 native SpawnID 22 +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/clericholy.txt b/wadsrc/static/actors/hexen/clericholy.txt index e97be8b17..cebc44610 100644 --- a/wadsrc/static/actors/hexen/clericholy.txt +++ b/wadsrc/static/actors/hexen/clericholy.txt @@ -8,6 +8,7 @@ ACTOR ClericWeaponPiece : WeaponPiece Inventory.ForbiddenTo FighterPlayer, MagePlayer WeaponPiece.Weapon CWeapWraithverge +FLOATBOB + +NOGRAVITY } // Cleric Weapon Piece 1 ---------------------------------------------------- diff --git a/wadsrc/static/actors/hexen/fighterquietus.txt b/wadsrc/static/actors/hexen/fighterquietus.txt index a77e851d8..b5ecd22e4 100644 --- a/wadsrc/static/actors/hexen/fighterquietus.txt +++ b/wadsrc/static/actors/hexen/fighterquietus.txt @@ -8,6 +8,7 @@ ACTOR FighterWeaponPiece : WeaponPiece Inventory.ForbiddenTo ClericPlayer, MagePlayer WeaponPiece.Weapon FWeapQuietus +FLOATBOB + +NOGRAVITY } // Fighter Weapon Piece 1 --------------------------------------------------- diff --git a/wadsrc/static/actors/hexen/flechette.txt b/wadsrc/static/actors/hexen/flechette.txt index 6e12bff53..74c7a0a6a 100644 --- a/wadsrc/static/actors/hexen/flechette.txt +++ b/wadsrc/static/actors/hexen/flechette.txt @@ -99,6 +99,7 @@ ACTOR ArtiPoisonBag : Inventory 8000 native Game Hexen SpawnID 72 +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" +INVBAR +FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/hexen/fog.txt b/wadsrc/static/actors/hexen/fog.txt index 81f5aeea5..91fdfc3ee 100644 --- a/wadsrc/static/actors/hexen/fog.txt +++ b/wadsrc/static/actors/hexen/fog.txt @@ -6,6 +6,7 @@ ACTOR FogSpawner 10000 Game Hexen +NOSECTOR +NOBLOCKMAP +FLOATBOB + +NOGRAVITY +INVISIBLE action native A_FogSpawn(); diff --git a/wadsrc/static/actors/hexen/healingradius.txt b/wadsrc/static/actors/hexen/healingradius.txt index e0556915b..97efc0449 100644 --- a/wadsrc/static/actors/hexen/healingradius.txt +++ b/wadsrc/static/actors/hexen/healingradius.txt @@ -6,6 +6,7 @@ ACTOR ArtiHealingRadius : Inventory 10120 native Game Hexen +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.DefMaxAmount +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH diff --git a/wadsrc/static/actors/hexen/magestaff.txt b/wadsrc/static/actors/hexen/magestaff.txt index aa75ed446..a8584aae7 100644 --- a/wadsrc/static/actors/hexen/magestaff.txt +++ b/wadsrc/static/actors/hexen/magestaff.txt @@ -8,6 +8,7 @@ ACTOR MageWeaponPiece : WeaponPiece Inventory.ForbiddenTo FighterPlayer, ClericPlayer WeaponPiece.Weapon MWeapBloodscourge +FLOATBOB + +NOGRAVITY } // Mage Weapon Piece 1 ------------------------------------------------------ diff --git a/wadsrc/static/actors/hexen/mana.txt b/wadsrc/static/actors/hexen/mana.txt index ee7ddd37c..97bc419c8 100644 --- a/wadsrc/static/actors/hexen/mana.txt +++ b/wadsrc/static/actors/hexen/mana.txt @@ -11,6 +11,7 @@ ACTOR Mana1 : Ammo 122 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.Icon "MAN1I0" Inventory.PickupMessage "$TXT_MANA_1" States @@ -34,6 +35,7 @@ ACTOR Mana2 : Ammo 124 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.Icon "MAN2G0" Inventory.PickupMessage "$TXT_MANA_2" States @@ -53,6 +55,7 @@ ACTOR Mana3 : CustomInventory 8004 Radius 8 Height 8 +FLOATBOB + +NOGRAVITY Inventory.PickupMessage "$TXT_MANA_BOTH" States { @@ -73,6 +76,7 @@ ACTOR ArtiBoostMana : CustomInventory 8003 Game Hexen SpawnID 26 +FLOATBOB + +NOGRAVITY +COUNTITEM +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH diff --git a/wadsrc/static/actors/hexen/speedboots.txt b/wadsrc/static/actors/hexen/speedboots.txt index 5fd6703b8..c22699b62 100644 --- a/wadsrc/static/actors/hexen/speedboots.txt +++ b/wadsrc/static/actors/hexen/speedboots.txt @@ -5,6 +5,7 @@ ACTOR ArtiSpeedBoots : PowerupGiver 8002 Game Hexen SpawnID 13 +FLOATBOB + +NOGRAVITY +COUNTITEM +INVENTORY.PICKUPFLASH Inventory.Icon ARTISPED diff --git a/wadsrc/static/actors/hexen/summon.txt b/wadsrc/static/actors/hexen/summon.txt index a4b3b8584..28c3c3267 100644 --- a/wadsrc/static/actors/hexen/summon.txt +++ b/wadsrc/static/actors/hexen/summon.txt @@ -7,6 +7,7 @@ ACTOR ArtiDarkServant : Inventory 86 native SpawnID 16 +COUNTITEM +FLOATBOB + +NOGRAVITY Inventory.RespawnTics 4230 Inventory.DefMaxAmount Inventory.PickupFlash "PickupFlash" diff --git a/wadsrc/static/actors/hexen/teleportother.txt b/wadsrc/static/actors/hexen/teleportother.txt index 77a05f6af..49b20a0bd 100644 --- a/wadsrc/static/actors/hexen/teleportother.txt +++ b/wadsrc/static/actors/hexen/teleportother.txt @@ -7,6 +7,7 @@ ACTOR ArtiTeleportOther : Inventory 10040 native SpawnID 17 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/artiegg.txt b/wadsrc/static/actors/raven/artiegg.txt index d94f00151..2a9c6867e 100644 --- a/wadsrc/static/actors/raven/artiegg.txt +++ b/wadsrc/static/actors/raven/artiegg.txt @@ -31,6 +31,7 @@ ACTOR ArtiEgg : CustomInventory 30 SpawnID 14 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND @@ -85,6 +86,7 @@ ACTOR ArtiPork : CustomInventory 30 SpawnID 14 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/artitele.txt b/wadsrc/static/actors/raven/artitele.txt index 79811fd53..b0eedf1cd 100644 --- a/wadsrc/static/actors/raven/artitele.txt +++ b/wadsrc/static/actors/raven/artitele.txt @@ -7,6 +7,7 @@ ACTOR ArtiTeleport : Inventory 36 native SpawnID 18 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.INVBAR +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND diff --git a/wadsrc/static/actors/raven/ravenartifacts.txt b/wadsrc/static/actors/raven/ravenartifacts.txt index c02c19c3b..4f31ad5fb 100644 --- a/wadsrc/static/actors/raven/ravenartifacts.txt +++ b/wadsrc/static/actors/raven/ravenartifacts.txt @@ -8,6 +8,7 @@ ACTOR ArtiHealth : HealthPickup 82 Health 25 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND Inventory.Icon ARTIPTN2 @@ -32,6 +33,7 @@ ACTOR ArtiSuperHealth : HealthPickup 32 Health 100 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.FANCYPICKUPSOUND Inventory.Icon ARTISPHL @@ -55,6 +57,7 @@ ACTOR ArtiFly : PowerupGiver 83 SpawnID 15 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH +INVENTORY.INTERHUBSTRIP Inventory.RespawnTics 4230 @@ -78,6 +81,7 @@ ACTOR ArtiInvulnerability : PowerupGiver 84 SpawnID 133 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.RespawnTics 4230 Inventory.Icon ARTIINVU @@ -101,6 +105,7 @@ ACTOR ArtiInvulnerability2 : PowerupGiver 84 SpawnID 133 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.RespawnTics 4230 Inventory.Icon ARTIDEFN @@ -123,6 +128,7 @@ ACTOR ArtiTorch : PowerupGiver 33 SpawnID 73 +COUNTITEM +FLOATBOB + +NOGRAVITY +INVENTORY.PICKUPFLASH Inventory.Icon ARTITRCH Inventory.PickupMessage "$TXT_ARTITORCH" diff --git a/wadsrc/static/actors/raven/ravenhealth.txt b/wadsrc/static/actors/raven/ravenhealth.txt index af951be1b..45cbe59b9 100644 --- a/wadsrc/static/actors/raven/ravenhealth.txt +++ b/wadsrc/static/actors/raven/ravenhealth.txt @@ -3,6 +3,7 @@ ACTOR CrystalVial : Health 81 Game Raven SpawnID 23 +FLOATBOB + +NOGRAVITY Inventory.Amount 10 Inventory.PickupMessage "$TXT_ITEMHEALTH" States From d4304c3bde102fffa49708f331afe454dc67a5c9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 19 Nov 2013 19:49:17 -0600 Subject: [PATCH 056/247] Change tspeed += 2 to *= 2 - Fixed: The initial keyboard turn rate used the running initial rate whether +speed was down or not. --- src/g_game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 506b8e24b..081ffdb53 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -565,7 +565,7 @@ void G_BuildTiccmd (ticcmd_t *cmd) int tspeed = speed; if (turnheld < SLOWTURNTICS) - tspeed *= 2; // slow turn + tspeed += 2; // slow turn if (Button_Right.bDown) { From f4e9edccb9f6eb0cb4a368070a780229e59e1f7d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 19 Nov 2013 19:55:57 -0600 Subject: [PATCH 057/247] Don't display the cost in dialogues twice - Fixed: Commit 75dd5503, which was to enable the use of LANGUAGE substitutions for conversation items with a cost attached, neglected to remove the original code that attached the cost to the end of the item, so the cost got added twice. --- src/p_conversation.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index e51389ce8..6493bca36 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -522,19 +522,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses) // If the first item check has a positive amount required, then // add that to the reply string. Otherwise, use the reply as-is. - if (rsp->Count[0] > 0) - { - char moneystr[128]; - - mysnprintf (moneystr, countof(moneystr), "%s for %u", rsp->Reply, rsp->Count[0]); - reply->Reply = copystring (moneystr); - reply->NeedsGold = true; - } - else - { - reply->Reply = copystring (rsp->Reply); - reply->NeedsGold = false; - } + reply->Reply = copystring (rsp->Reply); + reply->NeedsGold = (rsp->Count[0] > 0); // QuickYes messages are shown when you meet the item checks. // QuickNo messages are shown when you don't. From 1710e92c3a1a4d5458a67a6506c90d20e5a21937 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 21 Nov 2013 01:54:56 -0500 Subject: [PATCH 058/247] - Fix issues with building XCode projects with CMake. --- gdtoa/CMakeLists.txt | 6 ++++-- tools/lemon/CMakeLists.txt | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 4ad0be6de..91079d94c 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -17,13 +17,15 @@ add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS ) if( NOT MSVC ) add_executable( arithchk arithchk.c ) + get_target_property( ARITHCHK_EXE arithchk LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/arith.h - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/arithchk >${CMAKE_CURRENT_BINARY_DIR}/arith.h + COMMAND ${ARITHCHK_EXE} >${CMAKE_CURRENT_BINARY_DIR}/arith.h DEPENDS arithchk ) add_executable( qnan qnan.c arith.h ) + get_target_property( QNAN_EXE qnan LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/qnan >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h + COMMAND ${QNAN_EXE} >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h DEPENDS qnan ) set( GEN_FP_FILES arith.h gd_qnan.h ) diff --git a/tools/lemon/CMakeLists.txt b/tools/lemon/CMakeLists.txt index 91b144575..f3b07a72f 100644 --- a/tools/lemon/CMakeLists.txt +++ b/tools/lemon/CMakeLists.txt @@ -5,13 +5,13 @@ set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) add_executable( lemon lemon.c ) # Lemon wants lempar.c in its directory -if( MSVC ) +if( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( TARGET lemon POST_BUILD COMMAND echo $ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c $ ) -else( MSVC ) +else( NOT NO_GENERATOR_EXPRESSIONS ) add_custom_command( TARGET lemon POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c ${CMAKE_CURRENT_BINARY_DIR} ) -endif( MSVC ) \ No newline at end of file +endif( NOT NO_GENERATOR_EXPRESSIONS ) \ No newline at end of file From 8bf5872fc0087d22a0b307c573a58e6010d2b055 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Nov 2013 10:27:08 +0100 Subject: [PATCH 059/247] - always add DelayImp.lib for MSVC. --- src/CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7a9b0138d..ee98563b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,12 +142,8 @@ if( WIN32 ) comdlg32 ws2_32 setupapi - oleaut32 ) - - # For some reason this isn't implied on 2005 - if( MSVC80 ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} DelayImp ) - endif( MSVC80 ) + oleaut32 + DelayImp ) else( WIN32 ) if( APPLE ) set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) From c7632174d832c30d7d55caa283b53bd897f4da41 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 26 Nov 2013 12:49:23 -0500 Subject: [PATCH 060/247] - Fixed error in manifest embedding that stopped the binary from working on Windows XP. - Tweaked PK3 copying commands so that it shouldn't be possible to end up with files named Debug/Release. --- CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3715cdac8..625fceb1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,11 +26,11 @@ function( add_pk3 PK3_NAME PK3_DIR ) if( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $/${PK3_NAME} DEPENDS zipdir ${PK3_DIR} ) else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} - COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} + COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR}/${PK3_NAME} DEPENDS zipdir ${PK3_DIR} ) endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee98563b6..aa4013503 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1108,7 +1108,7 @@ if( MSVC ) endif( ZDOOM_GENERATE_MAPFILE ) add_custom_command(TARGET zdoom POST_BUILD - COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#2 + COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#1 COMMENT "Adding manifest..." ) From 0c1d92834acb6b09236f4f41976bd94c8235935f Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 26 Nov 2013 17:58:55 -0500 Subject: [PATCH 061/247] - Fixed: Some setups require the dynamic linking library to be linked explicitly, so specify it when using DYN_FLUIDSYNTH --- src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa4013503..6c31ca69c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -507,12 +507,14 @@ message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${FMOD_LIBRARY}" ) include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" ) -if( FLUIDSYNTH_FOUND ) - if( NOT DYN_FLUIDSYNTH) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) - include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) - endif( NOT DYN_FLUIDSYNTH ) -endif( FLUIDSYNTH_FOUND ) +if( NOT DYN_FLUIDSYNTH) + if( FLUIDSYNTH_FOUND ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) + include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) + endif( FLUIDSYNTH_FOUND ) +else( NOT DYN_FLUIDSYNTH ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} ) +endif( NOT DYN_FLUIDSYNTH ) # Start defining source files for ZDoom set( PLAT_WIN32_SOURCES From 7cb70f60b351f9c4da627455adeea789169f201d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 28 Nov 2013 11:03:19 +0100 Subject: [PATCH 062/247] - removed duplicate #define warning in fmodsound.cpp. - commented out output of Cr0NpxState for floating point state because this variable was renamed in most recent Windows headers. - added CMAKE option to generate assembly output for release builds. - added my CMake-based project directory to .gitignore. --- .gitignore | 1 + CMakeLists.txt | 11 ++++++++--- src/sound/fmodsound.cpp | 2 ++ src/win32/i_crash.cpp | 9 +++++++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 09e3fb4c4..e27cd5a59 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ /tools/lemon/build /tools/re2c/build /wadsrc/*.pk3 +/build_vc2013 diff --git a/CMakeLists.txt b/CMakeLists.txt index 625fceb1d..a442b9ea5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,9 +91,14 @@ if( MSVC ) # Disable run-time type information set( ALL_C_FLAGS "/GF /Gy /GR-" ) - # Avoid CRT DLL dependancies in release builds - set( REL_C_FLAGS "/MT /Oy" ) - + # Avoid CRT DLL dependancies in release builds, optionally generate assembly output for checking crash locations. + option( ZDOOM_GENERATE_ASM "Generate assembly output." OFF ) + if( ZDOOM_GENERATE_ASM ) + set( REL_C_FLAGS "/MT /Oy /FAcs" ) + else( ZDOOM_GENERATE_ASM ) + set( REL_C_FLAGS "/MT /Oy" ) + endif( ZDOOM_GENERATE_ASM ) + # Debug allocations in debug builds set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" ) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index f832183c0..4bdc43081 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -629,7 +629,9 @@ bool FMODSoundRenderer::IsValid() // //========================================================================== +#ifndef FACILITY_VISUALCPP #define FACILITY_VISUALCPP ((LONG)0x6d) +#endif #define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err) static int CheckException(DWORD code) diff --git a/src/win32/i_crash.cpp b/src/win32/i_crash.cpp index d629bacc9..68d78295d 100644 --- a/src/win32/i_crash.cpp +++ b/src/win32/i_crash.cpp @@ -842,10 +842,15 @@ HANDLE WriteTextReport () Writef (file, "\r\nFPU State:\r\n ControlWord=%04x StatusWord=%04x TagWord=%04x\r\n" " ErrorOffset=%08x\r\n ErrorSelector=%08x\r\n DataOffset=%08x\r\n DataSelector=%08x\r\n" - " Cr0NpxState=%08x\r\n\r\n", + // Cr0NpxState was renamed in recent Windows headers so better skip it here. Its meaning is unknown anyway. + //" Cr0NpxState=%08x\r\n" + "\r\n" + , (WORD)ctxt->FloatSave.ControlWord, (WORD)ctxt->FloatSave.StatusWord, (WORD)ctxt->FloatSave.TagWord, ctxt->FloatSave.ErrorOffset, ctxt->FloatSave.ErrorSelector, ctxt->FloatSave.DataOffset, - ctxt->FloatSave.DataSelector, ctxt->FloatSave.Cr0NpxState); + ctxt->FloatSave.DataSelector + //, ctxt->FloatSave.Cr0NpxState + ); for (i = 0; i < 8; ++i) { From c6c6487a3014e954d4db8cf4533619e98bda95cb Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 28 Nov 2013 14:41:40 -0500 Subject: [PATCH 063/247] - Fixed: Got a little hyper corrective in c763217. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a442b9ea5..c6f9fd6ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ function( add_pk3 PK3_NAME PK3_DIR ) DEPENDS zipdir ${PK3_DIR} ) else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} - COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR}/${PK3_NAME} + COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} DEPENDS zipdir ${PK3_DIR} ) endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) From c21beb0b6c88e0cbf599c01c601da3ee31d4a25e Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 29 Nov 2013 01:54:46 -0500 Subject: [PATCH 064/247] - Fixed: Some versions of Visual Studio put the map file in a different location. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c31ca69c..ff29f27e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1101,7 +1101,7 @@ if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) if( ZDOOM_GENERATE_MAPFILE ) if( NOT MSVC80 ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:${ZDOOM_EXE_NAME}.map") + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:\"$(TargetDir)${ZDOOM_EXE_NAME}.map\"") else( NOT MSVC80 ) # 2005 doesn't support naming the map file. set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") endif( NOT MSVC80 ) From a8090dc22c31a765961a01a64108576fd0637fc9 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 29 Nov 2013 02:09:27 -0500 Subject: [PATCH 065/247] - Remove a hardcoded "zdoom" so that the name passed into the copy operation should always match that passed to /MAP. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff29f27e7..60cdb01f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1128,7 +1128,7 @@ if( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSIONS ) if( ZDOOM_GENERATE_MAPFILE ) add_custom_command(TARGET zdoom POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $/zdoom.map ${ZDOOM_OUTPUT_DIR}/$.map + COMMAND ${CMAKE_COMMAND} -E copy_if_different $/${ZDOOM_EXE_NAME}.map ${ZDOOM_OUTPUT_DIR}/$.map COMMENT "Copying to output directory..." ) else( ZDOOM_GENERATE_MAPFILE ) add_custom_command(TARGET zdoom POST_BUILD From b9c032461e7279fc11e7dfe7e92b9212d400e1f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 29 Nov 2013 12:35:45 +0100 Subject: [PATCH 066/247] - add a CMake option to enable/disable SSE2 with Visual C++. This is necessary because since VC 2012 SSE2 is the default instruction set. --- CMakeLists.txt | 18 ++++++++++++++++-- src/CMakeLists.txt | 31 +++++++++++++++++-------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6f9fd6ad..6f07d3ada 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,13 +91,27 @@ if( MSVC ) # Disable run-time type information set( ALL_C_FLAGS "/GF /Gy /GR-" ) + if( CMAKE_SIZEOF_VOID_P MATCHES "4") + # SSE2 option (mostly to switch it off in VC2012 and later where it's the default + option (ZDOOM_USE_SSE2 "Use SSE2 instruction set") + if (ZDOOM_USE_SSE2) + set( ALL_C_FLAGS "${ALL_C_FLAGS} /arch:SSE2") + else (ZDOOM_USE_SSE2) + if (MSVC_VERSION GREATER 1699) + # On Visual C++ 2012 and later SSE2 is the default, so we need to switch it off explicitly + set( ALL_C_FLAGS "${ALL_C_FLAGS} /arch:IA32") + endif (MSVC_VERSION GREATER 1699) + endif (ZDOOM_USE_SSE2) + endif( CMAKE_SIZEOF_VOID_P MATCHES "4") + # Avoid CRT DLL dependancies in release builds, optionally generate assembly output for checking crash locations. option( ZDOOM_GENERATE_ASM "Generate assembly output." OFF ) if( ZDOOM_GENERATE_ASM ) - set( REL_C_FLAGS "/MT /Oy /FAcs" ) + set( REL_C_FLAGS "/MT /Oy /Oi /FAcs" ) else( ZDOOM_GENERATE_ASM ) - set( REL_C_FLAGS "/MT /Oy" ) + set( REL_C_FLAGS "/MT /Oy /Oi" ) endif( ZDOOM_GENERATE_ASM ) + # Debug allocations in debug builds set( DEB_C_FLAGS "/D _CRTDBG_MAP_ALLOC /MTd" ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 60cdb01f8..972e187db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -367,20 +367,23 @@ endif( NOT NO_ASM ) set( SSE_MATTERS NO ) -# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. -if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) - CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) - CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) - if( CAN_DO_MFPMATH ) - set( SSE1_ENABLE "-msse -mfpmath=sse" ) - set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) - set( SSE_MATTERS YES ) - elseif( CAN_DO_ARCHSSE2 ) - set( SSE1_ENABLE -arch:SSE ) - set( SSE2_ENABLE -arch:SSE2 ) - set( SSE_MATTERS YES ) - endif( CAN_DO_MFPMATH ) -endif( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) +# with global use of SSE 2 we do not need special handling for selected files +if (NOT ZDOOM_USE_SSE2) + # SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. + if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) + CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) + CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) + if( CAN_DO_MFPMATH ) + set( SSE1_ENABLE "-msse -mfpmath=sse" ) + set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) + set( SSE_MATTERS YES ) + elseif( CAN_DO_ARCHSSE2 ) + set( SSE1_ENABLE -arch:SSE ) + set( SSE2_ENABLE -arch:SSE2 ) + set( SSE_MATTERS YES ) + endif( CAN_DO_MFPMATH ) + endif( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc ) +endif (NOT ZDOOM_USE_SSE2) if( SSE_MATTERS ) if( WIN32 ) From cbed4624faeb4b192f908b1a2a66b7f3744fb32a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 29 Nov 2013 13:24:38 +0100 Subject: [PATCH 067/247] - added a user-settable factor for earthquake intensity. Value can be between 0 (no shaking) and 1 (normal shaking.) --- src/r_utility.cpp | 13 +++++++++---- wadsrc/static/menudef.txt | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 606cca840..356bfe741 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -89,6 +89,11 @@ CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE) CVAR (Int, r_clearbuffer, 0, 0) CVAR (Bool, r_drawvoxels, true, 0) CVAR (Bool, r_drawplayersprites, true, 0) // [RH] Draw player sprites? +CUSTOM_CVAR(Float, r_quakeintensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0.f) self = 0.f; + else if (self > 1.f) self = 1.f; +} DCanvas *RenderTarget; // [RH] canvas to render to @@ -837,10 +842,10 @@ void R_SetupFrame (AActor *actor) int intensity = DEarthquake::StaticGetQuakeIntensity (camera); if (intensity != 0) { - viewx += ((pr_torchflicker() % (intensity<<2)) - -(intensity<<1))< Date: Fri, 29 Nov 2013 14:41:03 -0500 Subject: [PATCH 068/247] - Get as many files as possible as dependencies for pk3 building. (Kind of feels like CMake changes the behavior of depending on directories every now and then, but maybe it's just me.) --- CMakeLists.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f07d3ada..a257cceab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,20 @@ else(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) set( NO_GENERATOR_EXPRESSIONS ON ) endif(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) +# Function to get a recursive list of files, but also get the directory names +# as well unlike GLOB_RECURSE +function( glob_recurse_with_directories OUTVAR DIR ) + file( GLOB CHILDREN ${DIR}/* ) + foreach( CHILD ${CHILDREN} ) + if( IS_DIRECTORY ${CHILD} ) + set( TEMP_LIST "" ) + glob_recurse_with_directories( TEMP_LIST ${CHILD} ) + set( ${OUTVAR} ${${OUTVAR}} ${TEMP_LIST} ) + endif( IS_DIRECTORY ${CHILD} ) + endforeach( CHILD ${CHILDREN} ) + set( ${OUTVAR} ${${OUTVAR}} ${CHILDREN} PARENT_SCOPE ) +endfunction( glob_recurse_with_directories ) + # Simplify pk3 building, add_pk3(filename srcdirectory) function( add_pk3 PK3_NAME PK3_DIR ) get_target_property(ZIPDIR_EXE zipdir LOCATION) @@ -23,15 +37,18 @@ function( add_pk3 PK3_NAME PK3_DIR ) set( PK3_TARGET "pk3" ) endif( ${PK3_TARGET} STREQUAL "zdoom_pk3" ) + # Get as many files as we can to depend on. + glob_recurse_with_directories( PK3_DEPENDS ${PK3_DIR} ) + if( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $/${PK3_NAME} - DEPENDS zipdir ${PK3_DIR} ) + DEPENDS zipdir ${PK3_DIR} ${PK3_DEPENDS} ) else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} - DEPENDS zipdir ${PK3_DIR} ) + DEPENDS zipdir ${PK3_DIR} ${PK3_DEPENDS} ) endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_target( ${PK3_TARGET} ALL From c04a800e2b855d05283759ef1b21c50c61157c85 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 29 Nov 2013 17:10:29 -0500 Subject: [PATCH 069/247] - When doing OLDSTYLE builds we can use the RUNTIME_OUTPUT_DIRECTORY_ properties to force the output location properly. --- src/CMakeLists.txt | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 972e187db..4e1152294 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1098,16 +1098,23 @@ if( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) # Linux distributions are slow to adopt 2.6. :( set_target_properties( zdoom PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) set_target_properties( zdoom PROPERTIES OUTPUT_NAME ${ZDOOM_EXE_NAME} ) +else( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) + set_target_properties( zdoom PROPERTIES + RUNTIME_OUTPUT_NAME ${ZDOOM_EXE_NAME} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_DEBUG ${ZDOOM_EXE_NAME}d + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_MINSIZEREL ${ZDOOM_EXE_NAME}msr + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${ZDOOM_OUTPUT_DIR} + RUNTIME_OUTPUT_NAME_RELWITHDEBINFO ${ZDOOM_EXE_NAME}rd + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${ZDOOM_OUTPUT_DIR} + ) endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS ) if( MSVC ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) if( ZDOOM_GENERATE_MAPFILE ) - if( NOT MSVC80 ) - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP:\"$(TargetDir)${ZDOOM_EXE_NAME}.map\"") - else( NOT MSVC80 ) # 2005 doesn't support naming the map file. - set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") - endif( NOT MSVC80 ) + set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") else( ZDOOM_GENERATE_MAPFILE ) set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") endif( ZDOOM_GENERATE_MAPFILE ) @@ -1120,26 +1127,6 @@ if( MSVC ) create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) endif( MSVC ) -if( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSIONS ) - set_target_properties( zdoom PROPERTIES - RUNTIME_OUTPUT_NAME ${ZDOOM_EXE_NAME} - RUNTIME_OUTPUT_NAME_DEBUG ${ZDOOM_EXE_NAME}d - RUNTIME_OUTPUT_NAME_MINSIZEREL ${ZDOOM_EXE_NAME}msr - RUNTIME_OUTPUT_NAME_RELWITHDEBINFO ${ZDOOM_EXE_NAME}rd - ) - - if( ZDOOM_GENERATE_MAPFILE ) - add_custom_command(TARGET zdoom POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ - COMMAND ${CMAKE_COMMAND} -E copy_if_different $/${ZDOOM_EXE_NAME}.map ${ZDOOM_OUTPUT_DIR}/$.map - COMMENT "Copying to output directory..." ) - else( ZDOOM_GENERATE_MAPFILE ) - add_custom_command(TARGET zdoom POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${ZDOOM_OUTPUT_DIR}/$ - COMMENT "Copying to output directory..." ) - endif( ZDOOM_GENERATE_MAPFILE ) -endif( ZDOOM_OUTPUT_OLDSTYLE AND NOT NO_GENERATOR_EXPRESSIONS ) - if( NOT WIN32 ) FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/link-make "if [ ! -e ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME} ]; then ln -sf ${CMAKE_CURRENT_BINARY_DIR}/${ZDOOM_EXE_NAME} ${ZDOOM_OUTPUT_DIR}/${ZDOOM_EXE_NAME}; fi" ) add_custom_command( TARGET zdoom POST_BUILD From 974619d5be66c39f44e4bcf90d48ce31e2123838 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 29 Nov 2013 17:13:34 -0500 Subject: [PATCH 070/247] - According to Graf, we should just let zipdir determine if the pk3 needs updating. --- CMakeLists.txt | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a257cceab..fca2e59b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,20 +13,6 @@ else(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) set( NO_GENERATOR_EXPRESSIONS ON ) endif(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) -# Function to get a recursive list of files, but also get the directory names -# as well unlike GLOB_RECURSE -function( glob_recurse_with_directories OUTVAR DIR ) - file( GLOB CHILDREN ${DIR}/* ) - foreach( CHILD ${CHILDREN} ) - if( IS_DIRECTORY ${CHILD} ) - set( TEMP_LIST "" ) - glob_recurse_with_directories( TEMP_LIST ${CHILD} ) - set( ${OUTVAR} ${${OUTVAR}} ${TEMP_LIST} ) - endif( IS_DIRECTORY ${CHILD} ) - endforeach( CHILD ${CHILDREN} ) - set( ${OUTVAR} ${${OUTVAR}} ${CHILDREN} PARENT_SCOPE ) -endfunction( glob_recurse_with_directories ) - # Simplify pk3 building, add_pk3(filename srcdirectory) function( add_pk3 PK3_NAME PK3_DIR ) get_target_property(ZIPDIR_EXE zipdir LOCATION) @@ -37,21 +23,21 @@ function( add_pk3 PK3_NAME PK3_DIR ) set( PK3_TARGET "pk3" ) endif( ${PK3_TARGET} STREQUAL "zdoom_pk3" ) - # Get as many files as we can to depend on. - glob_recurse_with_directories( PK3_DEPENDS ${PK3_DIR} ) - if( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $/${PK3_NAME} - DEPENDS zipdir ${PK3_DIR} ${PK3_DEPENDS} ) + DEPENDS zipdir ) else( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} COMMAND ${ZIPDIR_EXE} -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} - DEPENDS zipdir ${PK3_DIR} ${PK3_DEPENDS} ) + DEPENDS zipdir ) endif( NOT NO_GENERATOR_EXPRESSIONS AND NOT ZDOOM_OUTPUT_OLDSTYLE ) + # Touch the zipdir executable here so that the pk3s are forced to rebuild + # each time since their dependecy has "changed." add_custom_target( ${PK3_TARGET} ALL + COMMAND ${CMAKE_COMMAND} -E touch ${ZIPDIR_EXE} DEPENDS ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ) endfunction( add_pk3 ) From e7225bced6a83314cc67812c3097890aeff2ea6e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 01:15:10 +0100 Subject: [PATCH 071/247] - check negative XScale on sprites to allow mirroring. --- src/r_things.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/r_things.cpp b/src/r_things.cpp index 9bdba99f9..7243ac6f9 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -608,6 +608,11 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } } } + if (spritescaleX < 0) + { + spritescaleX = -spritescaleX; + flip = !flip; + } if (voxel == NULL && (tex == NULL || tex->UseType == FTexture::TEX_Null)) { return; From 698495efc5525fa826d77e066ca100e0231f7664 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 01:21:43 +0100 Subject: [PATCH 072/247] - fixed: missing return in playerinfo CCMD added. --- src/d_netinfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 12fb187ae..c2fb88aaf 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -1018,6 +1018,7 @@ CCMD (playerinfo) if (!playeringame[i]) { Printf(TEXTCOLOR_ORANGE "Player %d is not in the game\n", i); + return; } // Print special info From 7e062f394b11c300b77cc04fe94aa2cab7b0d434 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 01:26:30 +0100 Subject: [PATCH 073/247] - fixed: animated door textures defined by index were not added to the sequence. - fixed: animated doors should set 'no decals' for the texture. - added 'allowdecals' option to override the above. --- src/textures/animations.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 5a6f0729a..09518cd5e 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -776,8 +776,13 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) { sc.ScriptError ("Unknown texture %s", sc.String); } - frames.Push (v); } + frames.Push(v); + if (!sc.CheckString("allowdecals")) + { + Texture(v)->bNoDecals = true; + } + } else { From 662bc7a3ac48ec0aa4e0ac8417db6ad20277616e Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 1 Dec 2013 22:06:48 +1300 Subject: [PATCH 074/247] cl_bloodtype could break playsim sync Corrected entries were blood would spawn inconsistently because of cl_bloodtype. Blood now always spawns but is marked invisible according to cl_bloodtype. --- src/g_hexen/a_fighteraxe.cpp | 2 -- src/p_map.cpp | 14 ++++++++------ src/p_mobj.cpp | 16 +++++++++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index 50b378e50..f80af876b 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -26,8 +26,6 @@ void A_FAxeAttack (AActor *actor); extern void AdjustPlayerAngle (AActor *pmo, AActor *linetarget); -EXTERN_CVAR (Int, cl_bloodtype) - // The Fighter's Axe -------------------------------------------------------- class AFWeapAxe : public AFighterWeapon diff --git a/src/p_map.cpp b/src/p_map.cpp index a3379910d..0e66ee58d 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4879,7 +4879,8 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) const PClass *bloodcls = thing->GetBloodType(); P_TraceBleed (newdam > 0 ? newdam : cpos->crushchange, thing); - if (cl_bloodtype <= 1 && bloodcls != NULL) + + if (bloodcls != NULL) { AActor *mo; @@ -4892,14 +4893,15 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(cl_bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } + + angle_t an; + an = (M_Random () - 128) << 24; if (cl_bloodtype >= 1) { - angle_t an; - - an = (M_Random () - 128) << 24; - P_DrawSplash2 (32, thing->x, thing->y, - thing->z + thing->height/2, an, 2, bloodcolor); + P_DrawSplash2(32, thing->x, thing->y, thing->z + thing->height / 2, an, 2, bloodcolor); } } if (thing->CrushPainSound != 0 && !S_GetSoundPlayingInfo(thing, thing->CrushPainSound)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 69d4203fe..0337ef0dd 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4874,7 +4874,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { z += pr_spawnblood.Random2 () << 10; th = Spawn (bloodcls, x, y, z, NO_REPLACE); // GetBloodType already performed the replacement @@ -4945,7 +4945,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc } statedone: - + if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; if (bloodtype >= 1) P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor); } @@ -4966,7 +4966,7 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *mo; @@ -4981,6 +4981,8 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { @@ -5004,7 +5006,7 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *mo; @@ -5019,6 +5021,8 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) { mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) mo->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { @@ -5047,7 +5051,7 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) bloodtype = 0; - if (bloodcls!=NULL && bloodtype <= 1) + if (bloodcls != NULL) { AActor *th; th = Spawn (bloodcls, x, y, z, NO_REPLACE); // GetBloodType already performed the replacement @@ -5064,6 +5068,8 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) { th->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); } + + if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; } if (bloodtype >= 1) { From c5b2c9557299eba078359af57531c1d31a957f1e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 15:11:41 +0100 Subject: [PATCH 075/247] - fixed placement and handling of 'allowdecals' for animated doors. --- src/textures/animations.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 09518cd5e..13413ae70 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -778,11 +778,10 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) } } frames.Push(v); - if (!sc.CheckString("allowdecals")) - { - Texture(v)->bNoDecals = true; - } - + } + else if (!sc.Compare("allowdecals")) + { + if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = true; } else { From 7045f195f31eb4db41f38d4535dab45ed1fb427b Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 2 Dec 2013 06:23:22 +1300 Subject: [PATCH 076/247] Removed excess value from stall debug output The debug output for a stalled Arbitrator had an excess Net_Arbitrator value, bumping the gametic+counts value off the output. --- src/d_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 9c4bf14dd..37e3f589e 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1853,7 +1853,7 @@ void TryRunTics (void) { //Send a resend request to the Arbitrator, as it's obvious we are stuck here. if (debugfile) fprintf (debugfile, "Arbitrator is slow (%i to %i)\n", - Net_Arbitrator, nettics[Net_Arbitrator], gametic+counts); + nettics[Net_Arbitrator], gametic+counts); //Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud. if(i != 0) remoteresend[Net_Arbitrator] = players[playerfornode[Net_Arbitrator]].waiting = hadlate = true; From 25f60779fdf907dbe628ad00a572777d73ff3ce9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 20:20:26 +0100 Subject: [PATCH 077/247] - fixed: The 'allowdecals' check in animated doors was wrong. --- src/textures/animations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 13413ae70..e35550d51 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -779,7 +779,7 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) } frames.Push(v); } - else if (!sc.Compare("allowdecals")) + else if (sc.Compare("allowdecals")) { if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = true; } From 86d7a326be234c645b10221248ecdbdc2ed1f0e7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Dec 2013 21:11:33 +0100 Subject: [PATCH 078/247] - allowdecals logic was nonfunctional. --- src/textures/animations.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index e35550d51..433baa874 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -749,8 +749,11 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) { error = true; } - - while (sc.GetString ()) + else + { + Texture(anim.BaseTexture)->bNoDecals = true; + } + while (sc.GetString()) { if (sc.Compare ("opensound")) { @@ -781,7 +784,7 @@ void FTextureManager::ParseAnimatedDoor(FScanner &sc) } else if (sc.Compare("allowdecals")) { - if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = true; + if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = false; } else { From c959b3f250386a239521e63f74b1c4e897fbfa36 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 Dec 2013 15:28:09 +0100 Subject: [PATCH 079/247] - added 'subtract' render style to DECORATE parser. This is actually 'reverse subtract' --- src/r_data/renderstyle.cpp | 6 ++++-- src/r_data/renderstyle.h | 1 + src/thingdef/thingdef_properties.cpp | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 4b1d9fed4..4259b3440 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -57,7 +57,8 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] = /* 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 }}, - /* STYLE_Shadow */{{ STYLEOP_Shadow, 0, 0, 0 }}, + /* STYLE_Shadow */ {{ STYLEOP_Shadow, 0, 0, 0 }}, + /* STYLE_Subtract*/ {{ STYLEOP_RevSub, STYLEALPHA_One, STYLEALPHA_One, 0 }}, }; #else FRenderStyle LegacyRenderStyles[STYLE_Count]; @@ -74,7 +75,8 @@ static const BYTE Styles[STYLE_Count * 4] = STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0, STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed, - STYLEOP_Shadow, 0, 0, 0 + STYLEOP_Shadow, 0, 0, 0, + STYLEOP_RevSub, STYLEALPHA_One, STYLEALPHA_One, 0, }; static struct LegacyInit diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index 8133557d5..bd589e8c7 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -49,6 +49,7 @@ enum ERenderStyle STYLE_Shaded, // Treat patch data as alpha values for alphacolor STYLE_TranslucentStencil, STYLE_Shadow, + STYLE_Subtract, // Actually this is 'reverse subtract' but this is what normal people would expect by 'subtract'. STYLE_Count }; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index d6731aafa..61ab5b968 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -796,11 +796,11 @@ DEFINE_PROPERTY(renderstyle, S, Actor) { PROP_STRING_PARM(str, 0); static const char * renderstyles[]={ - "NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD","SHADED", NULL}; + "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL", "TRANSLUCENT", "ADD", "SHADED", "SUBTRACT", NULL }; static const int renderstyle_values[]={ STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, - STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded}; + STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, STYLE_Subtract}; // make this work for old style decorations, too. if (!strnicmp(str, "style_", 6)) str+=6; From 31c9a0b0e892cecbd93780cbc08c65ceb7962550 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 Dec 2013 15:36:20 +0100 Subject: [PATCH 080/247] - Subtract should respect alpha. --- src/r_data/renderstyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 4259b3440..660cd8f09 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -58,7 +58,7 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] = /* STYLE_Shaded */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed }}, /* STYLE_TranslucentStencil */{{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed }}, /* STYLE_Shadow */ {{ STYLEOP_Shadow, 0, 0, 0 }}, - /* STYLE_Subtract*/ {{ STYLEOP_RevSub, STYLEALPHA_One, STYLEALPHA_One, 0 }}, + /* STYLE_Subtract*/ {{ STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 }}, }; #else FRenderStyle LegacyRenderStyles[STYLE_Count]; @@ -76,7 +76,7 @@ static const BYTE Styles[STYLE_Count * 4] = STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed, STYLEOP_Shadow, 0, 0, 0, - STYLEOP_RevSub, STYLEALPHA_One, STYLEALPHA_One, 0, + STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0, }; static struct LegacyInit From 74dee4cd6397a7eacb06fb84f18f72bd69c3752a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 9 Dec 2013 11:24:58 +0100 Subject: [PATCH 081/247] - removed ddraw.lib from CMake files because that library is not used anymore. --- src/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e1152294..2bf5a5a8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,9 +104,6 @@ if( WIN32 ) include_directories( ${XINPUT_INCLUDE_DIR} ) endif( NOT XINPUT_INCLUDE_DIR ) - find_library( DX_ddraw_LIBRARY ddraw - PATHS ENV DXSDK_DIR - PATH_SUFFIXES Lib Lib/${XBITS} ) find_library( DX_dxguid_LIBRARY dxguid PATHS ENV DXSDK_DIR PATH_SUFFIXES Lib Lib/${XBITS} ) @@ -115,9 +112,6 @@ if( WIN32 ) PATH_SUFFIXES Lib Lib/${XBITS} ) set( DX_LIBS_FOUND YES ) - if( NOT DX_ddraw_LIBRARY ) - set( DX_LIBS_FOUND NO ) - endif( NOT DX_ddraw_LIBRARY ) if( NOT DX_dxguid_LIBRARY ) set( DX_LIBS_FOUND NO ) endif( NOT DX_dxguid_LIBRARY ) @@ -132,7 +126,6 @@ if( WIN32 ) set( ZDOOM_LIBS wsock32 winmm - "${DX_ddraw_LIBRARY}" "${DX_dxguid_LIBRARY}" "${DX_dinput8_LIBRARY}" ole32 From 10c312f55ce3a99f9cb027d6398d235982e6fc8d Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 13 Dec 2013 02:51:15 -0500 Subject: [PATCH 082/247] - Silence GCC PCD_PRINTBINARY warning since we've been able to since GCC 4.6. --- src/p_acs.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 32a70cd15..582385c48 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6796,7 +6796,18 @@ scriptwait: break; case PCD_PRINTBINARY: +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))) +#define HAS_DIAGNOSTIC_PRAGMA +#endif +#ifdef HAS_DIAGNOSTIC_PRAGMA +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat=" +#pragma GCC diagnostic ignored "-Wformat-extra-args" +#endif work.AppendFormat ("%B", STACK(1)); +#ifdef HAS_DIAGNOSTIC_PRAGMA +#pragma GCC diagnostic pop +#endif --sp; break; From 12d45bbc33ed833b1d30f7180e5d3dcca1a0f21e Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 13 Dec 2013 03:00:35 -0500 Subject: [PATCH 083/247] - Use setenv for LC_NUMERIC since setlocale gets reset by the libraries on some systems. --- src/sdl/i_main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 65b992f6a..1736305d8 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -257,7 +257,12 @@ int main (int argc, char **argv) #if defined(__MACH__) && !defined(NOASM) unprotect_rtext(); #endif - + + // Set LC_NUMERIC environment variable in case some library decides to + // clear the setlocale call at least this will be correct. + // Note that the LANG environment variable is overridden by LC_* + setenv ("LC_NUMERIC", "C", 1); + #ifndef NO_GTK GtkAvailable = gtk_init_check (&argc, &argv); #endif From a993b0288a0364eafe79c229af162dfc061cc717 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 16 Dec 2013 23:02:27 +1300 Subject: [PATCH 084/247] Stop prediction from playing and stopping sounds Player prediction would play *jump and stop falling sounds, creating odd cases of sound repetition before the gametic caught up. --- src/p_user.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index 938c7727f..14fa9c12c 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2473,9 +2473,10 @@ void P_PlayerThink (player_t *player) if ( player->cheats & CF_HIGHJUMP ) jumpvelz *= 2; player->mo->velz += jumpvelz; - S_Sound (player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM); player->mo->flags2 &= ~MF2_ONMOBJ; player->jumpTics = -1; + if (!(player->cheats & CF_PREDICTING)) + S_Sound(player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM); } } @@ -2502,7 +2503,7 @@ void P_PlayerThink (player_t *player) { player->mo->flags2 |= MF2_FLY; player->mo->flags |= MF_NOGRAVITY; - if (player->mo->velz <= -39*FRACUNIT) + if ((player->mo->velz <= -39 * FRACUNIT) && !(player->cheats & CF_PREDICTING)) { // Stop falling scream S_StopSound (player->mo, CHAN_VOICE); } From ae49044f96e39965b37f4f8ab4562fec130c9d84 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 19 Dec 2013 17:59:58 +0100 Subject: [PATCH 085/247] - let 'showloadtimes' measure UDMF parsing. --- src/p_setup.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3693e9f7e..315da4ffc 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3754,7 +3754,9 @@ void P_SetupLevel (char *lumpname, int position) } else { + times[0].Clock(); P_ParseTextMap(map, missingtex); + times[0].Unclock(); } times[6].Clock(); From 6e0f885135b4e562c0355b08aa52ef1a034dcf9f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 25 Dec 2013 22:30:47 +0100 Subject: [PATCH 086/247] - fixed: The 3D floor setup code treated alphas larger than 255 as translucent. This was causing problems with ZDCMP2 in GZDoom --- src/p_3dfloors.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 51ac24229..95ced549a 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -293,8 +293,9 @@ static int P_Set3DFloor(line_t * line, int param, int param2, int alpha) FTextureID tex = line->sidedef[0]->GetTexture(side_t::top); if (!tex.Exists() && alpha<255) { - alpha=clamp(-tex.GetIndex(), 0, 255); + alpha = -tex.GetIndex(); } + alpha = clamp(alpha, 0, 255); if (alpha==0) flags&=~(FF_RENDERALL|FF_BOTHPLANES|FF_ALLSIDES); else if (alpha!=255) flags|=FF_TRANSLUCENT; From 455145d611e0707fbf4f6fbcaf9cf7b82cf1b94e Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Thu, 2 Jan 2014 00:04:32 +1300 Subject: [PATCH 087/247] Stall testing for interpolation Uncapped framerate never triggered the stall detection code, as it never tried to process a frame to start with. --- src/d_net.cpp | 77 ++++++++++++++++++++++++++++----------------------- src/d_net.h | 3 ++ 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 37e3f589e..c912d29a2 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1747,6 +1747,8 @@ void TryRunTics (void) if (counts == 0 && !doWait) { + // Check possible stall conditions + Net_CheckLastRecieved(counts); return; } @@ -1824,41 +1826,8 @@ void TryRunTics (void) if (lowtic < gametic) I_Error ("TryRunTics: lowtic < gametic"); - // [Ed850] Check to see the last time a packet was recieved. - // If it's longer then 3 seconds, a node has likely stalled. - if(I_GetTime(false) - lastglobalrecvtime >= TICRATE*3) - { - lastglobalrecvtime = I_GetTime(false); //Bump the count - - if(NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) - { - //Keep the local node in the for loop so we can still log any cases where the local node is /somehow/ late. - //However, we don't send a resend request for sanity reasons. - for (i = 0; i < doomcom.numnodes; i++) - { - if (nodeingame[i] && nettics[i] < gametic + counts) - { - if (debugfile) - fprintf (debugfile, "%i is slow (%i to %i)\n", - i, nettics[i], gametic+counts); - //Send resend request to the late node. Also mark the node as waiting to display it in the hud. - if(i != 0) - remoteresend[i] = players[playerfornode[i]].waiting = hadlate = true; - } - else - players[playerfornode[i]].waiting = false; - } - } - else - { //Send a resend request to the Arbitrator, as it's obvious we are stuck here. - if (debugfile) - fprintf (debugfile, "Arbitrator is slow (%i to %i)\n", - nettics[Net_Arbitrator], gametic+counts); - //Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud. - if(i != 0) - remoteresend[Net_Arbitrator] = players[playerfornode[Net_Arbitrator]].waiting = hadlate = true; - } - } + // Check possible stall conditions + Net_CheckLastRecieved (counts); // don't stay in here forever -- give the menu a chance to work if (I_GetTime (false) - entertic >= TICRATE/3) @@ -1901,6 +1870,44 @@ void TryRunTics (void) } } +void Net_CheckLastRecieved (int counts) +{ + // [Ed850] Check to see the last time a packet was recieved. + // If it's longer then 3 seconds, a node has likely stalled. + if (I_GetTime(false) - lastglobalrecvtime >= TICRATE * 3) + { + lastglobalrecvtime = I_GetTime(false); //Bump the count + + if (NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator) + { + //Keep the local node in the for loop so we can still log any cases where the local node is /somehow/ late. + //However, we don't send a resend request for sanity reasons. + for (int i = 0; i < doomcom.numnodes; i++) + { + if (nodeingame[i] && nettics[i] <= gametic + counts) + { + if (debugfile && !players[playerfornode[i]].waiting) + fprintf(debugfile, "%i is slow (%i to %i)\n", + i, nettics[i], gametic + counts); + //Send resend request to the late node. Also mark the node as waiting to display it in the hud. + if (i != 0) + remoteresend[i] = players[playerfornode[i]].waiting = hadlate = true; + } + else + players[playerfornode[i]].waiting = false; + } + } + else + { //Send a resend request to the Arbitrator, as it's obvious we are stuck here. + if (debugfile && !players[playerfornode[Net_Arbitrator]].waiting) + fprintf(debugfile, "Arbitrator is slow (%i to %i)\n", + nettics[Net_Arbitrator], gametic + counts); + //Send resend request to the Arbitrator. Also mark the Arbitrator as waiting to display it in the hud. + remoteresend[Net_Arbitrator] = players[playerfornode[Net_Arbitrator]].waiting = hadlate = true; + } + } +} + void Net_NewMakeTic (void) { specials.NewMakeTic (); diff --git a/src/d_net.h b/src/d_net.h index 507723d53..4cd3e66f5 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -115,6 +115,9 @@ void D_QuitNetGame (void); //? how many ticks to run? void TryRunTics (void); +//Use for checking to see if the netgame has stalled +void Net_CheckLastRecieved(int); + // [RH] Functions for making and using special "ticcmds" void Net_NewMakeTic (); void Net_WriteByte (BYTE); From 49edd7c60c53376a09c385adf841960f71b81662 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 2 Jan 2014 01:59:04 -0500 Subject: [PATCH 088/247] - Add support for cross compiling so that OS X PowerPC builds can still be made on systems without rosetta (10.7+). (Compiling x86 binaries on ppc should also be possible.) --- CMakeLists.txt | 15 +++++++++++++++ gdtoa/CMakeLists.txt | 9 +++++++-- tools/CMakeLists.txt | 2 ++ tools/fixrtext/CMakeLists.txt | 6 +++++- tools/lemon/CMakeLists.txt | 7 +++++-- tools/re2c/CMakeLists.txt | 7 +++++++ tools/updaterevision/CMakeLists.txt | 5 ++++- tools/zipdir/CMakeLists.txt | 18 +++++++++++------- 8 files changed, 56 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fca2e59b3..28379a377 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,17 @@ else(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) set( NO_GENERATOR_EXPRESSIONS ON ) endif(${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) +# Support cross compiling +option( FORCE_CROSSCOMPILE "Turn on cross compiling." NO ) +if( FORCE_CROSSCOMPILE ) + set( CMAKE_CROSSCOMPILING TRUE ) +endif( FORCE_CROSSCOMPILE ) + +if(CMAKE_CROSSCOMPILING) + set(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Export file from native build.") + include(${IMPORT_EXECUTABLES}) +endif(CMAKE_CROSSCOMPILING) + # Simplify pk3 building, add_pk3(filename srcdirectory) function( add_pk3 PK3_NAME PK3_DIR ) get_target_property(ZIPDIR_EXE zipdir LOCATION) @@ -208,3 +219,7 @@ add_subdirectory( src ) if( NOT WIN32 AND NOT APPLE ) add_subdirectory( output_sdl ) endif( NOT WIN32 AND NOT APPLE ) + +if( NOT CMAKE_CROSSCOMPILING ) + export(TARGETS ${CROSS_EXPORTS} FILE "${CMAKE_BINARY_DIR}/ImportExecutables.cmake" ) +endif( NOT CMAKE_CROSSCOMPILING ) diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 91079d94c..9403f1793 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -16,13 +16,18 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS ) if( NOT MSVC ) - add_executable( arithchk arithchk.c ) + if( NOT CMAKE_CROSSCOMPILING ) + add_executable( arithchk arithchk.c ) + endif( NOT CMAKE_CROSSCOMPILING ) get_target_property( ARITHCHK_EXE arithchk LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/arith.h COMMAND ${ARITHCHK_EXE} >${CMAKE_CURRENT_BINARY_DIR}/arith.h DEPENDS arithchk ) - add_executable( qnan qnan.c arith.h ) + if( NOT CMAKE_CROSSCOMPILING ) + add_executable( qnan qnan.c arith.h ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} arithchk qnan PARENT_SCOPE ) + endif( NOT CMAKE_CROSSCOMPILING ) get_target_property( QNAN_EXE qnan LOCATION ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h COMMAND ${QNAN_EXE} >${CMAKE_CURRENT_BINARY_DIR}/gd_qnan.h diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 1d1de65e5..08a1c4f4b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -7,3 +7,5 @@ if( WIN32 ) endif( WIN32 ) add_subdirectory( updaterevision ) add_subdirectory( zipdir ) + +set( CROSS_EXPORTS ${CROSS_EXPORTS} PARENT_SCOPE ) diff --git a/tools/fixrtext/CMakeLists.txt b/tools/fixrtext/CMakeLists.txt index 9af8eb7f4..2b0ab2cda 100644 --- a/tools/fixrtext/CMakeLists.txt +++ b/tools/fixrtext/CMakeLists.txt @@ -1,2 +1,6 @@ cmake_minimum_required( VERSION 2.4 ) -add_executable( fixrtext fixrtext.c ) + +if( NOT CMAKE_CROSSCOMPILING ) + add_executable( fixrtext fixrtext.c ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} fixrtext PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) diff --git a/tools/lemon/CMakeLists.txt b/tools/lemon/CMakeLists.txt index f3b07a72f..0a9b558ee 100644 --- a/tools/lemon/CMakeLists.txt +++ b/tools/lemon/CMakeLists.txt @@ -1,8 +1,11 @@ cmake_minimum_required( VERSION 2.4 ) -set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) +if( NOT CMAKE_CROSSCOMPILING ) + set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG" ) -add_executable( lemon lemon.c ) + add_executable( lemon lemon.c ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} lemon PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) # Lemon wants lempar.c in its directory if( NOT NO_GENERATOR_EXPRESSIONS ) diff --git a/tools/re2c/CMakeLists.txt b/tools/re2c/CMakeLists.txt index e6068a28d..1284f3506 100644 --- a/tools/re2c/CMakeLists.txt +++ b/tools/re2c/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) + +if( NOT CMAKE_CROSSCOMPILING ) + include( CheckFunctionExists ) include( CheckTypeSize ) @@ -30,3 +33,7 @@ add_executable( re2c scanner.cc substr.cc translate.cc ) + +set( CROSS_EXPORTS ${CROSS_EXPORTS} re2c PARENT_SCOPE ) + +endif( NOT CMAKE_CROSSCOMPILING ) diff --git a/tools/updaterevision/CMakeLists.txt b/tools/updaterevision/CMakeLists.txt index d985b9e3f..b857ffbe7 100644 --- a/tools/updaterevision/CMakeLists.txt +++ b/tools/updaterevision/CMakeLists.txt @@ -17,7 +17,10 @@ if( WIN32 ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) endif( WIN32 ) -add_executable( updaterevision updaterevision.c ${TRUSTINFO} ) +if( NOT CMAKE_CROSSCOMPILING ) + add_executable( updaterevision updaterevision.c ${TRUSTINFO} ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} updaterevision PARENT_SCOPE ) +endif( NOT CMAKE_CROSSCOMPILING ) if( MT_MERGE ) get_target_property( UPDATEREVISION_EXE updaterevision LOCATION ) diff --git a/tools/zipdir/CMakeLists.txt b/tools/zipdir/CMakeLists.txt index 40c4042b9..3ee22ddc3 100644 --- a/tools/zipdir/CMakeLists.txt +++ b/tools/zipdir/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required( VERSION 2.4 ) -message(STATUS "${ZLIB_INCLUDE_DIR}" ) -message(STATUS "${BZIP2_INCLUDE_DIR}" ) -message(STATUS "${LZMA_INCLUDE_DIR}" ) -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) -add_executable( zipdir - zipdir.c ) -target_link_libraries( zipdir ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} lzma ) + +if(NOT CMAKE_CROSSCOMPILING) + message(STATUS "${ZLIB_INCLUDE_DIR}" ) + message(STATUS "${BZIP2_INCLUDE_DIR}" ) + message(STATUS "${LZMA_INCLUDE_DIR}" ) + include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" ) + add_executable( zipdir + zipdir.c ) + target_link_libraries( zipdir ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} lzma ) + set( CROSS_EXPORTS ${CROSS_EXPORTS} zipdir PARENT_SCOPE ) +endif(NOT CMAKE_CROSSCOMPILING) From 1e50a0af9ea70967bb4e2d5f343eb23e31e979df Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 2 Jan 2014 03:06:06 -0500 Subject: [PATCH 089/247] =?UTF-8?q?-=20Hard=20code=20gdtoa=20constants=20f?= =?UTF-8?q?or=20OS=20X=20since=20the=20programs=20can=E2=80=99t=20always?= =?UTF-8?q?=20be=20run=20on=20the=20target.=20=20(The=20values=20are=20the?= =?UTF-8?q?=20same=20for=20GCC=20and=20Clang.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdtoa/CMakeLists.txt | 4 ++-- gdtoa/gdtoa.h | 22 +++++++++++++++++++++- gdtoa/gdtoaimp.h | 30 +++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 9403f1793..7a1304d0f 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -15,7 +15,7 @@ endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" S include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS ) -if( NOT MSVC ) +if( NOT MSVC AND NOT APPLE ) if( NOT CMAKE_CROSSCOMPILING ) add_executable( arithchk arithchk.c ) endif( NOT CMAKE_CROSSCOMPILING ) @@ -35,7 +35,7 @@ if( NOT MSVC ) set( GEN_FP_FILES arith.h gd_qnan.h ) set( GEN_FP_DEPS ${CMAKE_CURRENT_BINARY_DIR}/arith.h ${CMAKE_CURRENTY_BINARY_DIR}/gd_qnan.h ) -endif( NOT MSVC ) +endif( NOT MSVC AND NOT APPLE ) add_library( gdtoa ${GEN_FP_FILES} diff --git a/gdtoa/gdtoa.h b/gdtoa/gdtoa.h index 95132294e..2707ff7df 100644 --- a/gdtoa/gdtoa.h +++ b/gdtoa/gdtoa.h @@ -32,7 +32,7 @@ THIS SOFTWARE. #ifndef GDTOA_H_INCLUDED #define GDTOA_H_INCLUDED -#ifdef _MSC_VER +#if defined(_MSC_VER) /* [RH] Generating arith.h strikes me as too cumbersome under Visual * Studio, so here's the equivalent, given the limited number of * architectures that MSC can target. (Itanium? Who cares about that?) @@ -43,6 +43,26 @@ THIS SOFTWARE. #ifdef _M_X64 #define X64_bit_pointers #endif +#elif defined(__APPLE__) +/* [BL] While generating the files may be easy, on OS X we have cross + * compiling to deal with, which means we can't run the generation + * program on the target. + */ +#if defined(__x86_64__) +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Long int +#define Intcast (int)(long) +#define Double_Align +#define X64_bit_pointers +#elif defined(__i386__) +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#else +#define IEEE_MC68k +#define Arith_Kind_ASL 2 +#define Double_Align +#endif #else #include "arith.h" #endif diff --git a/gdtoa/gdtoaimp.h b/gdtoa/gdtoaimp.h index 023d97062..f93e03ef5 100644 --- a/gdtoa/gdtoaimp.h +++ b/gdtoa/gdtoaimp.h @@ -167,7 +167,7 @@ THIS SOFTWARE. #define GDTOAIMP_H_INCLUDED #include "gdtoa.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) /* [RH] Generating gd_qnan.h strikes me as too cumbersome under Visual * Studio, so here's the equivalent, given the limited number of * architectures that MSC can target. (Itanium? Who cares about that?) @@ -188,6 +188,34 @@ THIS SOFTWARE. * it turns out that it has a true long double type. I thought that * all ia32 compilers had phased out extended precision. */ +#elif defined(__APPLE__) +#if defined(__x86_64__) || defined(__i386__) +#define f_QNAN 0xffc00000 +#define d_QNAN0 0x0 +#define d_QNAN1 0xfff80000 +#define ld_QNAN0 0x0 +#define ld_QNAN1 0xc0000000 +#define ld_QNAN2 0xffff +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0x0 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0xc000 +#define ldus_QNAN4 0xffff +#else +#define f_QNAN 0xffc00000 +#define d_QNAN0 0xfff80000 +#define d_QNAN1 0x0 +#define ld_QNAN0 0xfff80000 +#define ld_QNAN1 0x0 +#define ld_QNAN2 0x0 +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0xfff8 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0x0 +#define ldus_QNAN4 0x0 +#endif #else #include "gd_qnan.h" #endif From 50cec119a08d048fc61a38f639a0acbdc1f8f0f3 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 2 Jan 2014 19:12:03 -0500 Subject: [PATCH 090/247] - Work around GCC 4.8 bug 54570 --- src/parsecontext.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/parsecontext.cpp b/src/parsecontext.cpp index 6fa36b2a8..21b7a0ea6 100644 --- a/src/parsecontext.cpp +++ b/src/parsecontext.cpp @@ -157,6 +157,10 @@ loop: { return TokenTrans[NUM]; } +#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 + // Work around GCC 4.8 bug 54570 causing release build crashes. + asm("" : "+g" (yylval)); +#endif strcpy (yylval->sym, token); return TokenTrans[SYM]; } From 511bdc7208ea0589b059a49b2b43c5f761a53e7b Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Thu, 2 Jan 2014 19:12:03 -0500 Subject: [PATCH 091/247] - Work around GCC 4.8 bug 54570 --- src/parsecontext.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/parsecontext.cpp b/src/parsecontext.cpp index 6fa36b2a8..21b7a0ea6 100644 --- a/src/parsecontext.cpp +++ b/src/parsecontext.cpp @@ -157,6 +157,10 @@ loop: { return TokenTrans[NUM]; } +#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 + // Work around GCC 4.8 bug 54570 causing release build crashes. + asm("" : "+g" (yylval)); +#endif strcpy (yylval->sym, token); return TokenTrans[SYM]; } From 4770b9b27b0aebf29117ca1345db0cf0d0ea04fc Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 3 Jan 2014 01:21:21 -0500 Subject: [PATCH 092/247] - Fixed: Rampage timer should only reset when the weapon is ready to be fired. --- src/g_shared/sbar_mugshot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp index 0849fd354..aa0f9302a 100644 --- a/src/g_shared/sbar_mugshot.cpp +++ b/src/g_shared/sbar_mugshot.cpp @@ -270,7 +270,8 @@ void FMugShot::Tick(player_t *player) RampageTimer++; } } - else + // Only reset the rampage timer if the weapon becomes ready to fire. + else if((player->WeaponState & (WF_WEAPONREADY|WF_WEAPONREADYALT))) { RampageTimer = 0; } From b0f40c07338cea851f03720e7355b4ed71d55705 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 4 Jan 2014 00:37:15 -0500 Subject: [PATCH 093/247] - So we did end up restoring the variable that the last commit was compensating for. --- src/g_shared/sbar_mugshot.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp index aa0f9302a..96dd07265 100644 --- a/src/g_shared/sbar_mugshot.cpp +++ b/src/g_shared/sbar_mugshot.cpp @@ -263,15 +263,14 @@ void FMugShot::Tick(player_t *player) CurrentState = NULL; } } - if ((player->cmd.ucmd.buttons & (BT_ATTACK|BT_ALTATTACK)) && !(player->cheats & (CF_FROZEN | CF_TOTALLYFROZEN)) && player->ReadyWeapon) + if (player->attackdown && !(player->cheats & (CF_FROZEN | CF_TOTALLYFROZEN)) && player->ReadyWeapon) { if (RampageTimer != ST_RAMPAGEDELAY) { RampageTimer++; } } - // Only reset the rampage timer if the weapon becomes ready to fire. - else if((player->WeaponState & (WF_WEAPONREADY|WF_WEAPONREADYALT))) + else { RampageTimer = 0; } From cd3f5db16a8866d7ed2e97a05ab74e1f631feaf2 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 4 Jan 2014 16:58:21 -0500 Subject: [PATCH 094/247] - Updated gdtoa in order to fix clang warnings. --- gdtoa/README | 84 ++++++- gdtoa/arithchk.c | 2 +- gdtoa/dmisc.c | 2 +- gdtoa/dtoa.c | 210 +++++++++-------- gdtoa/g_Qfmt.c | 17 +- gdtoa/g__fmt.c | 126 +++++++++- gdtoa/g_ddfmt.c | 47 ++-- gdtoa/g_dfmt.c | 26 +- gdtoa/g_ffmt.c | 17 +- gdtoa/g_xLfmt.c | 17 +- gdtoa/g_xfmt.c | 23 +- gdtoa/gdtoa.c | 196 +++++++-------- gdtoa/gdtoa.h | 42 ++-- gdtoa/gdtoa_fltrnds.h | 18 ++ gdtoa/gdtoaimp.h | 81 +++++-- gdtoa/gethex.c | 155 +++++++++--- gdtoa/gmisc.c | 2 +- gdtoa/hd_init.c | 24 +- gdtoa/hexnan.c | 27 ++- gdtoa/misc.c | 136 ++++------- gdtoa/qnan.c | 45 ++-- gdtoa/smisc.c | 26 +- gdtoa/strtoIQ.c | 2 +- gdtoa/strtoId.c | 2 +- gdtoa/strtoIdd.c | 4 +- gdtoa/strtoIf.c | 2 +- gdtoa/strtoIg.c | 20 +- gdtoa/strtoIx.c | 2 +- gdtoa/strtoIxL.c | 2 +- gdtoa/strtod.c | 536 ++++++++++++++++++++++++------------------ gdtoa/strtodI.c | 90 ++++--- gdtoa/strtodg.c | 203 ++++++++++------ gdtoa/strtodnrp.c | 2 +- gdtoa/strtof.c | 11 +- gdtoa/strtopQ.c | 20 +- gdtoa/strtopd.c | 9 +- gdtoa/strtopdd.c | 47 ++-- gdtoa/strtopf.c | 11 +- gdtoa/strtopx.c | 24 +- gdtoa/strtopxL.c | 20 +- gdtoa/strtorQ.c | 15 +- gdtoa/strtord.c | 11 +- gdtoa/strtordd.c | 58 ++--- gdtoa/strtorf.c | 11 +- gdtoa/strtorx.c | 20 +- gdtoa/strtorxL.c | 18 +- gdtoa/ulp.c | 21 +- 47 files changed, 1528 insertions(+), 956 deletions(-) create mode 100644 gdtoa/gdtoa_fltrnds.h diff --git a/gdtoa/README b/gdtoa/README index cf1947aa2..1bf7d91e4 100644 --- a/gdtoa/README +++ b/gdtoa/README @@ -56,7 +56,9 @@ two letters: whose sum is the desired value For decimal -> binary conversions, there are three families of -helper routines: one for round-nearest: +helper routines: one for round-nearest (or the current rounding +mode on IEEE-arithmetic systems that provide the C99 fegetround() +function, if compiled with -DHonor_FLT_ROUNDS): strtof strtod @@ -150,12 +152,14 @@ suffer double rounding due to use of extended-precision registers. For some conversions this variant of strtod is less efficient than the one in strtod.c when the latter is run with 53-bit rounding precision. -The values that the strto* routines return for NaNs are determined by -gd_qnan.h, which the makefile generates by running the program whose -source is qnan.c. Note that the rules for distinguishing signaling -from quiet NaNs are system-dependent. For cross-compilation, you need -to determine arith.h and gd_qnan.h suitably, e.g., using the -arithmetic of the target machine. +When float or double are involved, the values that the strto* routines +return for NaNs are determined by gd_qnan.h, which the makefile +generates by running the program whose source is qnan.c. For other +types, default NaN values are specified in g__fmt.c and may need +adjusting. Note that the rules for distinguishing signaling from +quiet NaNs are system-dependent. For cross-compilation, you need to +determine arith.h and gd_qnan.h suitably, e.g., using the arithmetic +of the target machine. C99's hexadecimal floating-point constants are recognized by the strto* routines (but this feature has not yet been heavily tested). @@ -170,10 +174,11 @@ hexadecimal digits, it is taken for the fraction bits of the resulting NaN; if there are two or more strings of hexadecimal digits, each string is assigned to the next available sequence of 32-bit words of fractions bits (starting with the most significant), right-aligned in -each sequence. +each sequence. Strings of hexadecimal digits may be preceded by "0x" +or "0X". -For binary -> decimal conversions, I've provided just one family -of helper routines: +For binary -> decimal conversions, I've provided a family of helper +routines: g_ffmt g_dfmt @@ -181,6 +186,12 @@ of helper routines: g_xfmt g_xLfmt g_Qfmt + g_ffmt_p + g_dfmt_p + g_ddfmt_p + g_xfmt_p + g_xLfmt_p + g_Qfmt_p which do a "%g" style conversion either to a specified number of decimal places (if their ndig argument is positive), or to the shortest @@ -191,6 +202,36 @@ in the buffer, if the buffer was long enough, or 0. Other forms of conversion are easily done with the help of gdtoa(), such as %e or %f style and conversions with direction of rounding specified (so that, if desired, the decimal value is either >= or <= the binary value). +On IEEE-arithmetic systems that provide the C99 fegetround() function, +if compiled with -DHonor_FLT_ROUNDS, these routines honor the current +rounding mode. For pedants, the ...fmt_p() routines are similar to the +...fmt() routines, but have an additional final int argument, nik, +that for conversions of Infinity or NaN, determines whether upper, +lower, or mixed case is used, whether (...) is added to NaN values, +and whether the sign of a NaN is reported or suppressed: + + nik = ic + 6*(nb + 3*ns), + +where ic with 0 <= ic < 6 controls the rendering of Infinity and NaN: + + 0 ==> Infinity or NaN + 1 ==> infinity or nan + 2 ==> INFINITY or NAN + 3 ==> Inf or NaN + 4 ==> inf or nan + 5 ==> INF or NAN + +nb with 0 <= nb < 3 determines whether NaN values are rendered +as NaN(...): + + 0 ==> no + 1 ==> yes + 2 ==> no for default NaN values; yes otherwise + +ns = 0 or 1 determines whether the sign of NaN values reported: + + 0 ==> distinguish NaN and -NaN + 1 ==> report both as NaN For an example of more general conversions based on dtoa(), see netlib's "printf.c from ampl/solvers". @@ -332,5 +373,28 @@ Compiling g__fmt.c, strtod.c, and strtodg.c with -DUSE_LOCALE causes the decimal-point character to be taken from the current locale; otherwise it is '.'. +Source files dtoa.c and strtod.c in this directory are derived from +netlib's "dtoa.c from fp" and are meant to function equivalently. +When compiled with Honor_FLT_ROUNDS #defined (on systems that provide +FLT_ROUNDS and fegetround() as specified in the C99 standard), they +honor the current rounding mode. Because FLT_ROUNDS is buggy on some +(Linux) systems -- not reflecting calls on fesetround(), as the C99 +standard says it should -- when Honor_FLT_ROUNDS is #defined, the +current rounding mode is obtained from fegetround() rather than from +FLT_ROUNDS, unless Trust_FLT_ROUNDS is also #defined. + +Compile with -DUSE_LOCALE to use the current locale; otherwise +decimal points are assumed to be '.'. With -DUSE_LOCALE, unless +you also compile with -DNO_LOCALE_CACHE, the details about the +current "decimal point" character string are cached and assumed not +to change during the program's execution. + +On machines with a 64-bit long double and perhaps a 113-bit "quad" +type, you can invoke "make Printf" to add Printf (and variants, such +as Fprintf) to gdtoa.a. These are analogs, declared in stdio1.h, of +printf and fprintf, etc. in which %La, %Le, %Lf, and %Lg are for long +double and (if appropriate) %Lqa, %Lqe, %Lqf, and %Lqg are for quad +precision printing. + Please send comments to David M. Gay (dmg at acm dot org, with " at " changed at "@" and " dot " changed to "."). diff --git a/gdtoa/arithchk.c b/gdtoa/arithchk.c index 3211aeda4..ef6cda3db 100644 --- a/gdtoa/arithchk.c +++ b/gdtoa/arithchk.c @@ -106,7 +106,7 @@ ccheck() long Cray1; /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */ - Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762; + Cray1 = printf("%s", emptyfmt) < 0 ? 0 : 4617762; if (printf(emptyfmt, Cray1) >= 0) Cray1 = 1000000*Cray1 + 693716; if (printf(emptyfmt, Cray1) >= 0) diff --git a/gdtoa/dmisc.c b/gdtoa/dmisc.c index 72d271ca9..3e712511b 100644 --- a/gdtoa/dmisc.c +++ b/gdtoa/dmisc.c @@ -46,7 +46,7 @@ rv_alloc(int i) j = sizeof(ULong); for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)(i); j <<= 1) k++; r = (int*)Balloc(k); diff --git a/gdtoa/dtoa.c b/gdtoa/dtoa.c index 4fc6633b7..c96e6a545 100644 --- a/gdtoa/dtoa.c +++ b/gdtoa/dtoa.c @@ -30,7 +30,6 @@ THIS SOFTWARE. * with " at " changed at "@" and " dot " changed to "."). */ #include "gdtoaimp.h" -#include /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * @@ -67,7 +66,6 @@ THIS SOFTWARE. */ #ifdef Honor_FLT_ROUNDS -#define Rounding rounding #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else @@ -77,17 +75,17 @@ THIS SOFTWARE. char * dtoa #ifdef KR_headers - (d, mode, ndigits, decpt, sign, rve) - double d; int mode, ndigits, *decpt, *sign; char **rve; + (d0, mode, ndigits, decpt, sign, rve) + double d0; int mode, ndigits, *decpt, *sign; char **rve; #else - (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) + (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve) #endif { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to INT_MAX. + then *decpt is set to 9999. mode: 0 ==> shortest string that yields d when read in @@ -129,12 +127,22 @@ dtoa U d, d2, eps; double ds; char *s, *s0; -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif #ifdef SET_INEXACT int inexact, oldinexact; #endif +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ #ifndef MULTIPLE_THREADS if (dtoa_result) { @@ -142,36 +150,35 @@ dtoa dtoa_result = 0; } #endif - - dval(d) = _d; - if (word0(d) & Sign_bit) { + d.d = d0; + if (word0(&d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ + word0(&d) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; #if defined(IEEE_Arith) + defined(VAX) #ifdef IEEE_Arith - if ((word0(d) & Exp_mask) == Exp_mask) + if ((word0(&d) & Exp_mask) == Exp_mask) #else - if (word0(d) == 0x8000) + if (word0(&d) == 0x8000) #endif { /* Infinity or NaN */ - *decpt = INT_MAX; + *decpt = 9999; #ifdef IEEE_Arith - if (!word1(d) && !(word0(d) & 0xfffff)) + if (!word1(&d) && !(word0(&d) & 0xfffff)) return nrv_alloc("Infinity", rve, 8); #endif return nrv_alloc("NaN", rve, 3); } #endif #ifdef IBM - dval(d) += 0; /* normalize */ + dval(&d) += 0; /* normalize */ #endif - if (!dval(d)) { + if (!dval(&d)) { *decpt = 1; return nrv_alloc("0", rve, 1); } @@ -181,35 +188,35 @@ dtoa inexact = 1; #endif #ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { + if (Rounding >= 2) { if (*sign) - rounding = rounding == 2 ? 0 : 2; + Rounding = Rounding == 2 ? 0 : 2; else - if (rounding != 2) - rounding = 0; + if (Rounding != 2) + Rounding = 0; } #endif - b = d2b(dval(d), &be, &bbits); + b = d2b(dval(&d), &be, &bbits); #ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); + i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); #else - if (( i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { + if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { #endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; + dval(&d2) = dval(&d); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; #ifdef IBM - if (( j = 11 - hi0bits(word0(d2) & Frac_mask) )!=0) - dval(d2) /= 1 << j; + if (( j = 11 - hi0bits(word0(&d2) & Frac_mask) )!=0) + dval(&d2) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2) * - * This suggests computing an approximation k to log10(d) by + * This suggests computing an approximation k to log10(&d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); @@ -238,21 +245,21 @@ dtoa /* d is denormalized */ i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 - : word1(d) << 32 - i; - dval(d2) = x; - word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32) + : word1(&d) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } #endif - ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&d) < tens[k]) k--; k_check = 0; } @@ -291,10 +298,11 @@ dtoa try_quick = 0; } leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ switch(mode) { case 0: case 1: - ilim = ilim1 = -1; i = 18; ndigits = 0; break; @@ -319,7 +327,7 @@ dtoa s = s0 = rv_alloc(i); #ifdef Honor_FLT_ROUNDS - if (mode > 1 && rounding != 1) + if (mode > 1 && Rounding != 1) leftright = 0; #endif @@ -328,7 +336,7 @@ dtoa /* Try to get by with floating-point arithmetic. */ i = 0; - dval(d2) = dval(d); + dval(&d2) = dval(&d); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ @@ -338,7 +346,7 @@ dtoa if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; + dval(&d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) @@ -346,32 +354,32 @@ dtoa ieps++; ds *= bigtens[i]; } - dval(d) /= ds; + dval(&d) /= ds; } else if (( j1 = -k )!=0) { - dval(d) *= tens[j1 & 0xf]; + dval(&d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&d) *= bigtens[i]; } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&d) *= 10.; ieps++; } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&d) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -380,34 +388,34 @@ dtoa /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = 0.5/tens[ilim-1] - dval(eps); + dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); for(i = 0;;) { - L = (Long)dval(d); - dval(d) -= L; + L = (Long)dval(&d); + dval(&d) -= L; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) + if (dval(&d) < dval(&eps)) goto ret1; - if (1. - dval(d) < dval(eps)) + if (1. - dval(&d) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d)); - if (!(dval(d) -= L)) + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d)); + if (!(dval(&d) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) + if (dval(&d) > 0.5 + dval(&eps)) goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { + else if (dval(&d) < 0.5 - dval(&eps)) { while(*--s == '0'); s++; goto ret1; @@ -420,7 +428,7 @@ dtoa #endif fast_failed: s = s0; - dval(d) = dval(d2); + dval(&d) = dval(&d2); k = k0; ilim = ilim0; } @@ -432,22 +440,22 @@ dtoa ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) + if (ilim < 0 || dval(&d) <= 5*ds) goto no_digits; goto one_digit; } - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d) / ds); + dval(&d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&d) < 0) { L--; - dval(d) += ds; + dval(&d) += ds; } #endif *s++ = '0' + (int)L; - if (!dval(d)) { + if (!dval(&d)) { #ifdef SET_INEXACT inexact = 0; #endif @@ -456,13 +464,18 @@ dtoa if (i == ilim) { #ifdef Honor_FLT_ROUNDS if (mode > 1) - switch(rounding) { + switch(Rounding) { case 0: goto ret1; case 2: goto bump_up; } #endif - dval(d) += dval(d); - if (dval(d) > ds || dval(d) == ds && L & 1) { + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { bump_up: while(*--s == '9') if (s == s0) { @@ -524,12 +537,12 @@ dtoa spec_case = 0; if ((mode < 2 || leftright) #ifdef Honor_FLT_ROUNDS - && rounding == 1 + && Rounding == 1 #endif ) { - if (!word1(d) && !(word0(d) & Bndry_mask) + if (!word1(&d) && !(word0(&d) & Bndry_mask) #ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) + && word0(&d) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ @@ -615,9 +628,9 @@ dtoa j1 = delta->sign ? 1 : cmp(b, delta); Bfree(delta); #ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(d) & 1) + if (j1 == 0 && mode != 1 && !(word1(&d) & 1) #ifdef Honor_FLT_ROUNDS - && rounding >= 1 + && Rounding >= 1 #endif ) { if (dig == '9') @@ -632,11 +645,11 @@ dtoa goto ret; } #endif - if (j < 0 || j == 0 && mode != 1 + if (j < 0 || (j == 0 && mode != 1 #ifndef ROUND_BIASED - && !(word1(d) & 1) + && !(word1(&d) & 1) #endif - ) { + )) { if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; @@ -645,7 +658,7 @@ dtoa } #ifdef Honor_FLT_ROUNDS if (mode > 1) - switch(rounding) { + switch(Rounding) { case 0: goto accept_dig; case 2: goto keep_dig; } @@ -653,7 +666,11 @@ dtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); - if ((j1 > 0 || j1 == 0 && dig & 1) +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else + if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif && dig++ == '9') goto round_9_up; } @@ -663,7 +680,7 @@ dtoa } if (j1 > 0) { #ifdef Honor_FLT_ROUNDS - if (!rounding) + if (!Rounding) goto accept_dig; #endif if (dig == '9') { /* possible if i == 1 */ @@ -706,14 +723,19 @@ dtoa /* Round off last digit */ #ifdef Honor_FLT_ROUNDS - switch(rounding) { + switch(Rounding) { case 0: goto trimzeros; case 2: goto roundoff; } #endif b = lshift(b, 1); j = cmp(b, S); - if (j > 0 || j == 0 && dig & 1) { +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { roundoff: while(*--s == '9') if (s == s0) { @@ -724,7 +746,9 @@ dtoa ++*s++; } else { +#ifdef Honor_FLT_ROUNDS trimzeros: +#endif while(*--s == '0'); s++; } @@ -739,9 +763,9 @@ dtoa #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; + word0(&d) = Exp_1 + (70 << Exp_shift); + word1(&d) = 0; + dval(&d) += 1.; } } else if (!oldinexact) diff --git a/gdtoa/g_Qfmt.c b/gdtoa/g_Qfmt.c index 9d227d170..0f0697005 100644 --- a/gdtoa/g_Qfmt.c +++ b/gdtoa/g_Qfmt.c @@ -51,19 +51,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_Qfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 }; + static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[4], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)V; @@ -109,6 +114,6 @@ g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g__fmt.c b/gdtoa/g__fmt.c index 021ecfb57..652c82b68 100644 --- a/gdtoa/g__fmt.c +++ b/gdtoa/g__fmt.c @@ -35,26 +35,77 @@ THIS SOFTWARE. #include "locale.h" #endif +#ifndef ldus_QNAN0 +#define ldus_QNAN0 0x7fff +#endif +#ifndef ldus_QNAN1 +#define ldus_QNAN1 0xc000 +#endif +#ifndef ldus_QNAN2 +#define ldus_QNAN2 0 +#endif +#ifndef ldus_QNAN3 +#define ldus_QNAN3 0 +#endif +#ifndef ldus_QNAN4 +#define ldus_QNAN4 0 +#endif + + const char *InfName[6] = { "Infinity", "infinity", "INFINITY", "Inf", "inf", "INF" }; + const char *NanName[3] = { "NaN", "nan", "NAN" }; + ULong NanDflt_Q_D2A[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }; + ULong NanDflt_d_D2A[2] = { d_QNAN1, d_QNAN0 }; + ULong NanDflt_f_D2A[1] = { f_QNAN }; + ULong NanDflt_xL_D2A[3] = { 1, 0x80000000, 0x7fff0000 }; + UShort NanDflt_ldus_D2A[5] = { ldus_QNAN4, ldus_QNAN3, ldus_QNAN2, ldus_QNAN1, ldus_QNAN0 }; + char * #ifdef KR_headers -g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign; +g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen; #else -g__fmt(char *b, char *s, char *se, int decpt, ULong sign) +g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen) #endif { int i, j, k; - char *s0 = s; + char *be, *s0; + size_t len; #ifdef USE_LOCALE - char decimalpoint = *localeconv()->decimal_point; +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + size_t dlen = strlen(decimalpoint); #else -#define decimalpoint '.' + char *decimalpoint; + static char *decimalpoint_cache; + static size_t dlen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + dlen = strlen(s0); + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; #endif +#else +#define dlen 0 +#endif + s0 = s; + len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */ + if (blen < len) + goto ret0; + be = b + blen - 1; if (sign) *b++ = '-'; if (decpt <= -4 || decpt > se - s + 5) { *b++ = *s++; if (*s) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif while((*b = *s++) !=0) b++; } @@ -69,6 +120,8 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} for(;;) { i = decpt / k; + if (b >= be) + goto ret0; *b++ = i + '0'; if (--j <= 0) break; @@ -78,22 +131,73 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign) *b = 0; } else if (decpt <= 0) { - *b++ = decimalpoint; +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + if (be < b - decpt + (se - s)) + goto ret0; for(; decpt < 0; decpt++) *b++ = '0'; - while((*b = *s++) !=0) + while((*b = *s++) != 0) b++; } else { - while((*b = *s++) !=0) { + while((*b = *s++) != 0) { b++; - if (--decpt == 0 && *s) - *b++ = decimalpoint; + if (--decpt == 0 && *s) { +#ifdef USE_LOCALE + while(*b = *decimalpoint++) + ++b; +#else + *b++ = '.'; +#endif + } + } + if (b + decpt > be) { + ret0: + b = 0; + goto ret; } for(; decpt > 0; decpt--) *b++ = '0'; *b = 0; } + ret: freedtoa(s0); return b; } + + char * +add_nanbits_D2A(char *b, size_t blen, ULong *bits, int nb) +{ + ULong t; + char *rv; + int i, j; + size_t L; + static char Hexdig[16] = "0123456789abcdef"; + + while(!bits[--nb]) + if (!nb) + return b; + L = 8*nb + 3; + t = bits[nb]; + do ++L; while((t >>= 4)); + if (L > blen) + return b; + b += L; + *--b = 0; + rv = b; + *--b = /*(*/ ')'; + for(i = 0; i < nb; ++i) { + t = bits[i]; + for(j = 0; j < 8; ++j, t >>= 4) + *--b = Hexdig[t & 0xf]; + } + t = bits[nb]; + do *--b = Hexdig[t & 0xf]; while(t >>= 4); + *--b = '('; /*)*/ + return rv; + } diff --git a/gdtoa/g_ddfmt.c b/gdtoa/g_ddfmt.c index d96e78dbe..5ce4a076b 100644 --- a/gdtoa/g_ddfmt.c +++ b/gdtoa/g_ddfmt.c @@ -33,9 +33,9 @@ THIS SOFTWARE. char * #ifdef KR_headers -g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize; +g_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize; #else -g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) +g_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize) #endif { FPI fpi; @@ -43,12 +43,28 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) ULong *L, bits0[4], *bits, *zx; int bx, by, decpt, ex, ey, i, j, mode; Bigint *x, *y, *z; - double ddx[2]; + U *dd, ddx[2]; +#ifdef Honor_FLT_ROUNDS /*{{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#else /*}{*/ +#define Rounding FPI_Round_near +#endif /*}}*/ - if (bufsize < 10 || bufsize < (unsigned)(ndig + 8)) + if (bufsize < 10 || bufsize < (size_t)(ndig + 8)) return 0; - L = (ULong*)dd; + dd = (U*)dd0; + L = dd->L; if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) { /* Infinity or NaN */ if (L[_0] & 0xfffff || L[_1]) { @@ -73,7 +89,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) goto nanret; goto infret; } - if (dd[0] + dd[1] == 0.) { + if (dval(&dd[0]) + dval(&dd[1]) == 0.) { b = buf; #ifndef IGNORE_ZERO_SIGN if (L[_0] & L[2+_0] & 0x80000000L) @@ -84,16 +100,16 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) return b; } if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) { - ddx[1] = dd[0]; - ddx[0] = dd[1]; + dval(&ddx[1]) = dval(&dd[0]); + dval(&ddx[0]) = dval(&dd[1]); dd = ddx; - L = (ULong*)dd; + L = dd->L; } - z = d2b(dd[0], &ex, &bx); - if (dd[1] == 0.) + z = d2b(dval(&dd[0]), &ex, &bx); + if (dval(&dd[1]) == 0.) goto no_y; x = z; - y = d2b(dd[1], &ey, &by); + y = d2b(dval(&dd[1]), &ey, &by); if ( (i = ex - ey) !=0) { if (i > 0) { x = lshift(x, i); @@ -136,7 +152,7 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) } mode = 2; if (ndig <= 0) { - if (bufsize < (unsigned)((int)(fpi.nbits * .301029995664) + 10)) { + if (bufsize < (size_t)((int)(fpi.nbits * .301029995664) + 10)) { Bfree(z); return 0; } @@ -144,11 +160,12 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize) } fpi.emin = 1-1023-53+1; fpi.emax = 2046-1023-106+1; - fpi.rounding = FPI_Round_near; + fpi.rounding = Rounding; fpi.sudden_underflow = 0; + fpi.int_max = Int_max; i = STRTOG_Normal; s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - b = g__fmt(buf, s, se, decpt, z->sign); + b = g__fmt(buf, s, se, decpt, z->sign, bufsize); Bfree(z); return b; } diff --git a/gdtoa/g_dfmt.c b/gdtoa/g_dfmt.c index 74b4ccc28..d8e1438c4 100644 --- a/gdtoa/g_dfmt.c +++ b/gdtoa/g_dfmt.c @@ -33,25 +33,32 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize; +g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; size_t bufsize; #else -g_dfmt(char *buf, double *d, int ndig, unsigned bufsize) +g_dfmt(char *buf, double *d, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 }; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)d; sign = L[_0] & 0x80000000L; if ((L[_0] & 0x7ff00000) == 0x7ff00000) { /* Infinity or NaN */ + if (bufsize < 10) + return 0; if (L[_0] & 0xfffff || L[_1]) { return strcp(buf, "NaN"); } @@ -78,12 +85,11 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize) ex = 1; ex -= 0x3ff + 52; mode = 2; - if (ndig <= 0) { - if (bufsize < 25) - return 0; + if (ndig <= 0) mode = 0; - } i = STRTOG_Normal; - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + if (sign) + i = STRTOG_Normal | STRTOG_Neg; + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_ffmt.c b/gdtoa/g_ffmt.c index 9b2c5fea6..30b53ae7e 100644 --- a/gdtoa/g_ffmt.c +++ b/gdtoa/g_ffmt.c @@ -33,19 +33,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize; +g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; size_t bufsize; #else -g_ffmt(char *buf, float *f, int ndig, unsigned bufsize) +g_ffmt(char *buf, float *f, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0, 6 }; char *b, *s, *se; ULong bits[1], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)f; @@ -83,6 +88,6 @@ g_ffmt(char *buf, float *f, int ndig, unsigned bufsize) mode = 0; } i = STRTOG_Normal; - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_xLfmt.c b/gdtoa/g_xLfmt.c index a2a993b59..5cda8d59e 100644 --- a/gdtoa/g_xLfmt.c +++ b/gdtoa/g_xLfmt.c @@ -49,19 +49,24 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_xLfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], *L, sign; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (ULong*)V; @@ -103,6 +108,6 @@ g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/g_xfmt.c b/gdtoa/g_xfmt.c index c51a16dce..a0baa518c 100644 --- a/gdtoa/g_xfmt.c +++ b/gdtoa/g_xfmt.c @@ -53,20 +53,25 @@ THIS SOFTWARE. char* #ifdef KR_headers -g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize; +g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize; #else -g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) +g_xfmt(char *buf, void *V, int ndig, size_t bufsize) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; char *b, *s, *se; ULong bits[2], sign; UShort *L; int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif if (ndig < 0) ndig = 0; - if (bufsize < (unsigned)(ndig + 10)) + if (bufsize < (size_t)(ndig + 10)) return 0; L = (UShort *)V; @@ -76,14 +81,14 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) if ( (ex = L[_0] & 0x7fff) !=0) { if (ex == 0x7fff) { /* Infinity or NaN */ - if (bits[0] | bits[1]) - b = strcp(buf, "NaN"); - else { + if (!bits[0] && bits[1]== 0x80000000) { b = buf; if (sign) *b++ = '-'; b = strcp(b, "Infinity"); } + else + b = strcp(buf, "NaN"); return b; } i = STRTOG_Normal; @@ -109,6 +114,6 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize) return 0; mode = 0; } - s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); - return g__fmt(buf, s, se, decpt, sign); + s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return g__fmt(buf, s, se, decpt, sign, bufsize); } diff --git a/gdtoa/gdtoa.c b/gdtoa/gdtoa.c index 7e8d2b2bf..a4759968a 100644 --- a/gdtoa/gdtoa.c +++ b/gdtoa/gdtoa.c @@ -30,7 +30,6 @@ THIS SOFTWARE. * with " at " changed at "@" and " dot " changed to "."). */ #include "gdtoaimp.h" -#include static Bigint * #ifdef KR_headers @@ -62,7 +61,7 @@ bitstob(ULong *bits, int nbits, int *bbits) *x++ = (*bits >> 16) & ALL_ON; #endif } while(++bits <= be); - i = (int)(x - x0); + i = x - x0; while(!x0[--i]) if (!i) { b->wds = 0; @@ -116,14 +115,15 @@ gdtoa FPI *fpi; int be; ULong *bits; int *kindp, mode, ndigits, *decpt; char **rve; #else - (CONST FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve) + (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve) #endif { /* Arguments ndigits and decpt are similar to the second and third arguments of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to INT_MAX. + then *decpt is set to 9999. + be = exponent: value = (integer represented by bits) * (2 to the power of be). mode: 0 ==> shortest string that yields d when read in @@ -159,8 +159,8 @@ gdtoa Long L; Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; double d2, ds; - U d, eps; char *s, *s0; + U d, eps; #ifndef MULTIPLE_THREADS if (dtoa_result) { @@ -177,10 +177,10 @@ gdtoa case STRTOG_Denormal: break; case STRTOG_Infinite: - *decpt = INT_MAX; + *decpt = -32768; return nrv_alloc("Infinity", rve, 8); case STRTOG_NaN: - *decpt = INT_MAX; + *decpt = -32768; return nrv_alloc("NaN", rve, 3); default: return 0; @@ -199,21 +199,21 @@ gdtoa return nrv_alloc("0", rve, 1); } - dval(d) = b2d(b, &i); + dval(&d) = b2d(b, &i); i = be + bbits - 1; - word0(d) &= Frac_mask1; - word0(d) |= Exp_11; + word0(&d) &= Frac_mask1; + word0(&d) |= Exp_11; #ifdef IBM - if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) - dval(d) /= 1 << j; + if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) + dval(&d) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2) * - * This suggests computing an approximation k to log10(d) by + * This suggests computing an approximation k to log10(&d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); @@ -233,7 +233,7 @@ gdtoa i <<= 2; i += j; #endif - ds = (dval(d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; /* correct assumption about exponent range */ if ((j = i) < 0) @@ -248,13 +248,13 @@ gdtoa #ifdef IBM j = be + bbits - 1; if ( (j1 = j & 3) !=0) - dval(d) *= 1 << j1; - word0(d) += j << Exp_shift - 2 & Exp_mask; + dval(&d) *= 1 << j1; + word0(&d) += j << Exp_shift - 2 & Exp_mask; #else - word0(d) += (be + bbits - 1) << Exp_shift; + word0(&d) += (be + bbits - 1) << Exp_shift; #endif if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) + if (dval(&d) < tens[k]) k--; k_check = 0; } @@ -284,11 +284,14 @@ gdtoa mode -= 4; try_quick = 0; } + else if (i >= -4 - Emin || i < Emin) + try_quick = 0; leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ switch(mode) { case 0: case 1: - ilim = ilim1 = -1; i = (int)(nbits * .30103) + 3; ndigits = 0; break; @@ -330,10 +333,10 @@ gdtoa /* Try to get by with floating-point arithmetic. */ i = 0; - d2 = dval(d); + d2 = dval(&d); #ifdef IBM - if ( (j = 11 - hi0bits(word0(d) & Frac_mask)) !=0) - dval(d) /= 1 << j; + if ( (j = 11 - hi0bits(word0(&d) & Frac_mask)) !=0) + dval(&d) /= 1 << j; #endif k0 = k; ilim0 = ilim; @@ -344,7 +347,7 @@ gdtoa if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; + dval(&d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) @@ -356,30 +359,30 @@ gdtoa else { ds = 1.; if ( (j1 = -k) !=0) { - dval(d) *= tens[j1 & 0xf]; + dval(&d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; - dval(d) *= bigtens[i]; + dval(&d) *= bigtens[i]; } } } - if (k_check && dval(d) < 1. && ilim > 0) { + if (k_check && dval(&d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - dval(d) *= 10.; + dval(&d) *= 10.; ieps++; } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) goto one_digit; - if (dval(d) < -dval(eps)) + if (dval(&d) < -dval(&eps)) goto no_digits; goto fast_failed; } @@ -388,42 +391,40 @@ gdtoa /* Use Steele & White method of only * generating digits needed. */ - dval(eps) = ds*0.5/tens[ilim-1] - dval(eps); + dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps); for(i = 0;;) { - L = (Long)(dval(d)/ds); - dval(d) -= L*ds; + L = (Long)(dval(&d)/ds); + dval(&d) -= L*ds; *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) { - if (dval(d)) + if (dval(&d) < dval(&eps)) { + if (dval(&d)) inex = STRTOG_Inexlo; goto ret1; } - if (ds - dval(d) < dval(eps)) + if (ds - dval(&d) < dval(&eps)) goto bump_up; if (++i >= ilim) break; - dval(eps) *= 10.; - dval(d) *= 10.; + dval(&eps) *= 10.; + dval(&d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(d) *= 10.) { - if ( (L = (Long)(dval(d)/ds)) !=0) - dval(d) -= L*ds; + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + if ( (L = (Long)(dval(&d)/ds)) !=0) + dval(&d) -= L*ds; *s++ = '0' + (int)L; if (i == ilim) { ds *= 0.5; - if (dval(d) > ds + dval(eps)) + if (dval(&d) > ds + dval(&eps)) goto bump_up; - else if (dval(d) < ds - dval(eps)) { - while(*--s == '0'){} - s++; - if (dval(d)) + else if (dval(&d) < ds - dval(&eps)) { + if (dval(&d)) inex = STRTOG_Inexlo; - goto ret1; + goto clear_trailing0; } break; } @@ -433,34 +434,34 @@ gdtoa #endif fast_failed: s = s0; - dval(d) = d2; + dval(&d) = d2; k = k0; ilim = ilim0; } /* Do we have a "small" integer? */ - if (be >= 0 && k <= Int_max) { + if (be >= 0 && k <= fpi->int_max) { /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) + if (ilim < 0 || dval(&d) <= 5*ds) goto no_digits; goto one_digit; } - for(i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d) / ds); + dval(&d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { + if (dval(&d) < 0) { L--; - dval(d) += ds; + dval(&d) += ds; } #endif *s++ = '0' + (int)L; - if (dval(d) == 0.) + if (dval(&d) == 0.) break; if (i == ilim) { if (rdir) { @@ -469,8 +470,13 @@ gdtoa inex = STRTOG_Inexlo; goto ret1; } - dval(d) += dval(d); - if (dval(d) > ds || dval(d) == ds && L & 1) { + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { bump_up: inex = STRTOG_Inexhi; while(*--s == '9') @@ -481,8 +487,12 @@ gdtoa } ++*s++; } - else + else { inex = STRTOG_Inexlo; + clear_trailing0: + while(*--s == '0'){} + ++s; + } break; } } @@ -493,13 +503,15 @@ gdtoa m5 = b5; mhi = mlo = 0; if (leftright) { - if (mode < 2) { - i = nbits - bbits; - if (be - i++ < fpi->emin) - /* denormal */ - i = be - fpi->emin + 1; + i = nbits - bbits; + if (be - i++ < fpi->emin && mode != 3 && mode != 5) { + /* denormal */ + i = be - fpi->emin + 1; + if (mode >= 2 && ilim > 0 && ilim < i) + goto small_ilim; } - else { + else if (mode >= 2) { + small_ilim: j = ilim - 1; if (m5 >= j) m5 -= j; @@ -560,28 +572,11 @@ gdtoa * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ -#ifdef Pack_32 - if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) !=0) - i = 32 - i; -#else - if ( (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) !=0) - i = 16 - i; -#endif - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) + i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask; + m2 += i; + if ((b2 += i) > 0) b = lshift(b, b2); - if (s2 > 0) + if ((s2 += i) > 0) S = lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { @@ -646,11 +641,11 @@ gdtoa goto ret; } #endif - if (j < 0 || j == 0 && !mode + if (j < 0 || (j == 0 && !mode #ifndef ROUND_BIASED && !(bits[0] & 1) #endif - ) { + )) { if (rdir && (b->wds > 1 || b->x[0])) { if (rdir == 2) { inex = STRTOG_Inexlo; @@ -673,7 +668,11 @@ gdtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); - if ((j1 > 0 || j1 == 0 && dig & 1) +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else + if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif && dig++ == '9') goto round_9_up; inex = STRTOG_Inexhi; @@ -718,13 +717,18 @@ gdtoa /* Round off last digit */ if (rdir) { - if (rdir == 2 || b->wds <= 1 && !b->x[0]) + if (rdir == 2 || (b->wds <= 1 && !b->x[0])) goto chopzeros; goto roundoff; } b = lshift(b, 1); j = cmp(b, S); - if (j > 0 || j == 0 && dig & 1) { +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { roundoff: inex = STRTOG_Inexhi; while(*--s == '9') @@ -740,7 +744,7 @@ gdtoa if (b->wds > 1 || b->x[0]) inex = STRTOG_Inexlo; while(*--s == '0'){} - s++; + ++s; } ret: Bfree(S); diff --git a/gdtoa/gdtoa.h b/gdtoa/gdtoa.h index 2707ff7df..49c637beb 100644 --- a/gdtoa/gdtoa.h +++ b/gdtoa/gdtoa.h @@ -66,16 +66,13 @@ THIS SOFTWARE. #else #include "arith.h" #endif +#include /* for size_t */ -/* [RH] On 64-bit Unix systems, long is a 64-bit type. I do not that is - * is what is desired here, so I sacrifice compatibility with systems - * that use 16-bit ints (oh no!) and make Long an int instead. - */ #ifndef Long -typedef int Long; +#define Long int #endif #ifndef ULong -typedef unsigned int ULong; +typedef unsigned Long ULong; #endif #ifndef UShort typedef unsigned short UShort; @@ -111,9 +108,9 @@ typedef unsigned short UShort; /* The following may be or-ed into one of the above values. */ - STRTOG_Neg = 0x08, - STRTOG_Inexlo = 0x10, - STRTOG_Inexhi = 0x20, + STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */ + STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */ + STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */ STRTOG_Inexact = 0x30, STRTOG_Underflow= 0x40, STRTOG_Overflow = 0x80 @@ -126,6 +123,7 @@ FPI { int emax; int rounding; int sudden_underflow; + int int_max; } FPI; enum { /* FPI.rounding values: same as FLT_ROUNDS */ @@ -135,29 +133,31 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */ FPI_Round_down = 3 }; -// Our strtod is not the CRT's strtod. -#include -#define strtod mystrtod - #ifdef __cplusplus extern "C" { #endif extern char* dtoa ANSI((double d, int mode, int ndigits, int *decpt, int *sign, char **rve)); -extern char* gdtoa ANSI((CONST FPI *fpi, int be, ULong *bits, int *kindp, +extern char* gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)); extern void freedtoa ANSI((char*)); extern float strtof ANSI((CONST char *, char **)); extern double strtod ANSI((CONST char *, char **)); -extern int strtodg ANSI((CONST char*, char**, CONST FPI*, Long*, ULong*)); +extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); -extern char* g_ddfmt ANSI((char*, double*, int, unsigned)); -extern char* g_dfmt ANSI((char*, double*, int, unsigned)); -extern char* g_ffmt ANSI((char*, float*, int, unsigned)); -extern char* g_Qfmt ANSI((char*, void*, int, unsigned)); -extern char* g_xfmt ANSI((char*, void*, int, unsigned)); -extern char* g_xLfmt ANSI((char*, void*, int, unsigned)); +extern char* g_ddfmt ANSI((char*, double*, int, size_t)); +extern char* g_ddfmt_p ANSI((char*, double*, int, size_t, int)); +extern char* g_dfmt ANSI((char*, double*, int, size_t)); +extern char* g_dfmt_p ANSI((char*, double*, int, size_t, int)); +extern char* g_ffmt ANSI((char*, float*, int, size_t)); +extern char* g_ffmt_p ANSI((char*, float*, int, size_t, int)); +extern char* g_Qfmt ANSI((char*, void*, int, size_t)); +extern char* g_Qfmt_p ANSI((char*, void*, int, size_t, int)); +extern char* g_xfmt ANSI((char*, void*, int, size_t)); +extern char* g_xfmt_p ANSI((char*, void*, int, size_t, int)); +extern char* g_xLfmt ANSI((char*, void*, int, size_t)); +extern char* g_xLfmt_p ANSI((char*, void*, int, size_t, int)); extern int strtoId ANSI((CONST char*, char**, double*, double*)); extern int strtoIdd ANSI((CONST char*, char**, double*, double*)); diff --git a/gdtoa/gdtoa_fltrnds.h b/gdtoa/gdtoa_fltrnds.h new file mode 100644 index 000000000..33e5f9e53 --- /dev/null +++ b/gdtoa/gdtoa_fltrnds.h @@ -0,0 +1,18 @@ + FPI *fpi, fpi1; + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ + fpi = &fpi0; + if (Rounding != 1) { + fpi1 = fpi0; + fpi = &fpi1; + fpi1.rounding = Rounding; + } diff --git a/gdtoa/gdtoaimp.h b/gdtoa/gdtoaimp.h index f93e03ef5..4dea69e56 100644 --- a/gdtoa/gdtoaimp.h +++ b/gdtoa/gdtoaimp.h @@ -89,12 +89,18 @@ THIS SOFTWARE. * #define IBM for IBM mainframe-style floating-point arithmetic. * #define VAX for VAX-style floating-point arithmetic (D_floating). * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa. + * computation of dtoa and gdtoa. This will cause modes 4 and 5 to be + * treated the same as modes 2 and 3 for some inputs. * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines * that use extended-precision instructions to compute rounded * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic + * that rounds toward +Infinity. + * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased + * rounding when the underlying floating-point arithmetic uses + * unbiased rounding. This prevent using ordinary floating-point + * arithmetic when the result could be computed with one rounding error. * #define Inaccurate_Divide for IEEE-format with correctly rounded * products but inaccurate quotients, e.g., for Intel i860. * #define NO_LONG_LONG on machines that do not have a "long long" @@ -113,7 +119,12 @@ THIS SOFTWARE. * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) * if memory is available and otherwise does something you deem * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. + * directly -- and assumed always to succeed. Similarly, if you + * want something other than the system's free() to be called to + * recycle memory acquired from MALLOC, #define FREE to be the + * name of the alternate routine. (FREE or free is only called in + * pathological cases, e.g., in a gdtoa call after a gdtoa return in + * mode 3 with thousands of digits requested.) * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making * memory allocations from a private pool of memory when possible. * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, @@ -126,8 +137,10 @@ THIS SOFTWARE. * conversions of IEEE doubles in single-threaded executions with * 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). + * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK + * #defined automatically on IEEE systems. On such systems, + * when INFNAN_CHECK is #defined, strtod checks + * for Infinity and NaN (case insensitively). * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, * strtodg also accepts (case insensitively) strings of the form * NaN(x), where x is a string of hexadecimal digits (optionally @@ -151,7 +164,7 @@ THIS SOFTWARE. * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. * #define IMPRECISE_INEXACT if you do not care about the setting of * the STRTOG_Inexact bits in the special case of doing IEEE double - * precision conversions (which could also be done by the strtog in + * precision conversions (which could also be done by the strtod in * dtoa.c). * #define NO_HEX_FP to disable recognition of C9x's hexadecimal * floating-point constants. @@ -220,6 +233,10 @@ THIS SOFTWARE. #include "gd_qnan.h" #endif +#ifdef Honor_FLT_ROUNDS +#include +#endif + #ifdef DEBUG #include "stdio.h" #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} @@ -229,13 +246,13 @@ THIS SOFTWARE. #include "string.h" #ifdef KR_headers -#define KR_VOID char +#define Char char #else -#define KR_VOID void +#define Char void #endif #ifdef MALLOC -extern KR_VOID *MALLOC ANSI((size_t)); +extern Char *MALLOC ANSI((size_t)); #else #define MALLOC malloc #endif @@ -307,19 +324,19 @@ extern "C" { #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -#error Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. #endif typedef union { double d; ULong L[2]; } U; #ifdef IEEE_8087 -#define word0(x) x.L[1] -#define word1(x) x.L[0] +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] #else -#define word0(x) x.L[0] -#define word1(x) x.L[1] +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] #endif -#define dval(x) x.d +#define dval(x) (x)->d /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is @@ -433,6 +450,11 @@ typedef union { double d; ULong L[2]; } U; #ifndef IEEE_Arith #define ROUND_BIASED +#else +#ifdef ROUND_BIASED_without_Round_Up +#undef ROUND_BIASED +#define ROUND_BIASED +#endif #endif #ifdef RND_PRODQUOT @@ -488,12 +510,12 @@ extern double rnd_prod(double, double), rnd_quot(double, double); #define ALL_ON 0xffff #endif -#ifndef MULTIPLE_THREADS +//#ifndef MULTIPLE_THREADS #define ACQUIRE_DTOA_LOCK(n) /*nothing*/ #define FREE_DTOA_LOCK(n) /*nothing*/ -#endif +//#endif -#define Kmax (sizeof(size_t) << 3) +#define Kmax 9 struct Bigint { @@ -516,12 +538,15 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); #define Balloc Balloc_D2A #define Bfree Bfree_D2A +#define InfName InfName_D2A +#define NanName NanName_D2A #define ULtoQ ULtoQ_D2A #define ULtof ULtof_D2A #define ULtod ULtod_D2A #define ULtodd ULtodd_D2A #define ULtox ULtox_D2A #define ULtoxL ULtoxL_D2A +#define add_nanbits add_nanbits_D2A #define any_on any_on_D2A #define b2d b2d_D2A #define bigtens bigtens_D2A @@ -560,9 +585,11 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); #define trailz trailz_D2A #define ulp ulp_D2A + extern char *add_nanbits ANSI((char*, size_t, ULong*, int)); extern char *dtoa_result; extern CONST double bigtens[], tens[], tinytens[]; extern unsigned char hexdig[]; + extern const char *InfName[6], *NanName[3]; extern Bigint *Balloc ANSI((int)); extern void Bfree ANSI((Bigint*)); @@ -577,14 +604,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); extern int cmp ANSI((Bigint*, Bigint*)); extern void copybits ANSI((ULong*, int, Bigint*)); extern Bigint *d2b ANSI((double, int*, int*)); - extern int decrement ANSI((Bigint*)); + extern void decrement ANSI((Bigint*)); extern Bigint *diff ANSI((Bigint*, Bigint*)); extern char *dtoa ANSI((double d, int mode, int ndigits, int *decpt, int *sign, char **rve)); - extern char *g__fmt ANSI((char*, char*, char*, int, ULong)); - extern int gethex ANSI((CONST char**, CONST FPI*, Long*, Bigint**, int)); + extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t)); + extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int)); extern void hexdig_init_D2A(Void); - extern int hexnan ANSI((CONST char**, CONST FPI*, ULong*)); + extern int hexnan ANSI((CONST char**, FPI*, ULong*)); extern int hi0bits_D2A ANSI((ULong)); extern Bigint *i2b ANSI((int)); extern Bigint *increment ANSI((Bigint*)); @@ -599,14 +626,14 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); extern double ratio ANSI((Bigint*, Bigint*)); extern void rshift ANSI((Bigint*, int)); extern char *rv_alloc ANSI((int)); - extern Bigint *s2b ANSI((CONST char*, int, int, ULong)); + extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int)); extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); - extern int strtoIg ANSI((CONST char*, char**, CONST FPI*, Long*, Bigint**, int*)); + extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*)); extern double strtod ANSI((const char *s00, char **se)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); - extern double ulp ANSI((double)); + extern double ulp ANSI((U*)); #ifdef __cplusplus } @@ -621,6 +648,10 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t)); * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) */ #ifdef IEEE_Arith +#ifndef NO_INFNAN_CHECK +#undef INFNAN_CHECK +#define INFNAN_CHECK +#endif #ifdef IEEE_MC68k #define _0 0 #define _1 1 diff --git a/gdtoa/gethex.c b/gdtoa/gethex.c index 7273a6c3b..72da9d326 100644 --- a/gdtoa/gethex.c +++ b/gdtoa/gethex.c @@ -40,22 +40,34 @@ THIS SOFTWARE. gethex(sp, fpi, exp, bp, sign) CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; #else -gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) +gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) #endif { Bigint *b; CONST unsigned char *decpt, *s0, *s, *s1; - int esign, havedig, irv, k, n, nbits, up, zret; + int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; ULong L, lostbits, *x; Long e, e1; #ifdef USE_LOCALE - unsigned char decimalpoint = *localeconv()->decimal_point; + int i; +#ifdef NO_LOCALE_CACHE + const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; #else -#define decimalpoint '.' + const unsigned char *decimalpoint; + static unsigned char *decimalpoint_cache; + if (!(s0 = decimalpoint_cache)) { + s0 = (unsigned char*)localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif #endif - if (!hexdig['0']) - hexdig_init_D2A(); + /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ + *bp = 0; havedig = 0; s0 = *(CONST unsigned char **)sp + 2; while(s0[havedig] == '0') @@ -65,11 +77,21 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) decpt = 0; zret = 0; e = 0; - if (!hexdig[*s]) { + if (hexdig[*s]) + havedig++; + else { zret = 1; - if (*s != decimalpoint) +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s != '.') goto pcheck; decpt = ++s; +#endif if (!hexdig[*s]) goto pcheck; while(*s == '0') @@ -81,19 +103,28 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) } while(hexdig[*s]) s++; - if (*s == decimalpoint && !decpt) { +#ifdef USE_LOCALE + if (*s == *decimalpoint && !decpt) { + for(i = 1; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s == '.' && !decpt) { decpt = ++s; +#endif while(hexdig[*s]) s++; - } + }/*}*/ if (decpt) e = -(((Long)(s-decpt)) << 2); pcheck: s1 = s; + big = esign = 0; switch(*s) { case 'p': case 'P': - esign = 0; switch(*++s) { case '-': esign = 1; @@ -106,29 +137,87 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) break; } e1 = n - 0x10; - while((n = hexdig[*++s]) !=0 && n <= 0x19) + while((n = hexdig[*++s]) !=0 && n <= 0x19) { + if (e1 & 0xf8000000) + big = 1; e1 = 10*e1 + n - 0x10; + } if (esign) e1 = -e1; e += e1; } *sp = (char*)s; - if (zret) { - if (!havedig) - *sp = s0 - 1; + if (!havedig) + *sp = (char*)s0 - 1; + if (zret) return STRTOG_Zero; + if (big) { + if (esign) { + switch(fpi->rounding) { + case FPI_Round_up: + if (sign) + break; + goto ret_tiny; + case FPI_Round_down: + if (!sign) + break; + goto ret_tiny; + } + goto retz; + ret_tiny: + b = Balloc(0); + b->wds = 1; + b->x[0] = 1; + goto dret; + } + switch(fpi->rounding) { + case FPI_Round_near: + goto ovfl1; + case FPI_Round_up: + if (!sign) + goto ovfl1; + goto ret_big; + case FPI_Round_down: + if (sign) + goto ovfl1; + goto ret_big; + } + ret_big: + nbits = fpi->nbits; + n0 = n = nbits >> kshift; + if (nbits & kmask) + ++n; + for(j = n, k = 0; j >>= 1; ++k); + *bp = b = Balloc(k); + b->wds = n; + for(j = 0; j < n0; ++j) + b->x[j] = ALL_ON; + if (n > n0) + b->x[j] = ULbits >> (ULbits - (nbits & kmask)); + *exp = fpi->emin; + return STRTOG_Normal | STRTOG_Inexlo; } - n = (int)(s1 - s0 - 1); - for(k = 0; n > 7; n >>= 1) + n = s1 - s0 - 1; + for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) k++; b = Balloc(k); x = b->x; n = 0; L = 0; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i+1]; ++i); +#endif while(s1 > s0) { - if (*--s1 == decimalpoint) +#ifdef USE_LOCALE + if (*--s1 == decimalpoint[i]) { + s1 -= i; continue; - if (n == 32) { + } +#else + if (*--s1 == '.') + continue; +#endif + if (n == ULbits) { *x++ = L; L = 0; n = 0; @@ -137,8 +226,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) n += 4; } *x++ = L; - b->wds = n = (int)(x - b->x); - n = 32*n - hi0bits(L); + b->wds = n = x - b->x; + n = ULbits*n - hi0bits(L); nbits = fpi->nbits; lostbits = 0; x = b->x; @@ -149,7 +238,7 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) k = n - 1; if (x[k>>kshift] & 1 << (k & kmask)) { lostbits = 2; - if (k > 1 && any_on(b,k-1)) + if (k > 0 && any_on(b,k)) lostbits = 3; } } @@ -165,7 +254,10 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) if (e > fpi->emax) { ovfl: Bfree(b); - *bp = 0; + ovfl1: +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; } irv = STRTOG_Normal; @@ -185,15 +277,22 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) case FPI_Round_down: if (sign) { one_bit: - *exp = fpi->emin; x[0] = b->wds = 1; + dret: *bp = b; + *exp = fpi->emin; +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Denormal | STRTOG_Inexhi | STRTOG_Underflow; } } Bfree(b); - *bp = 0; + retz: +#ifndef NO_ERRNO + errno = ERANGE; +#endif return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; } k = n - 1; @@ -214,7 +313,7 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) break; case FPI_Round_near: if (lostbits & 2 - && (lostbits & 1) | x[0] & 1) + && (lostbits | x[0]) & 1) up = 1; break; case FPI_Round_up: @@ -233,8 +332,8 @@ gethex( CONST char **sp, CONST FPI *fpi, Long *exp, Bigint **bp, int sign) irv = STRTOG_Normal; } else if (b->wds > k - || (n = nbits & kmask) !=0 - && hi0bits(x[k-1]) < 32-n) { + || ((n = nbits & kmask) !=0 + && hi0bits(x[k-1]) < 32-n)) { rshift(b,1); if (++e > fpi->emax) goto ovfl; diff --git a/gdtoa/gmisc.c b/gdtoa/gmisc.c index 988d3bfbb..8270ef944 100644 --- a/gdtoa/gmisc.c +++ b/gdtoa/gmisc.c @@ -60,7 +60,7 @@ rshift(Bigint *b, int k) while(x < xe) *x1++ = *x++; } - if ((b->wds = (int)(x1 - b->x)) == 0) + if ((b->wds = x1 - b->x) == 0) b->x[0] = 0; } diff --git a/gdtoa/hd_init.c b/gdtoa/hd_init.c index fa6e18dee..d79ae2ec8 100644 --- a/gdtoa/hd_init.c +++ b/gdtoa/hd_init.c @@ -31,6 +31,7 @@ THIS SOFTWARE. #include "gdtoaimp.h" +#if 0 unsigned char hexdig[256]; static void @@ -46,10 +47,31 @@ htinit(unsigned char *h, unsigned char *s, int inc) } void -hexdig_init_D2A(Void) +hexdig_init_D2A(Void) /* Use of hexdig_init omitted 20121220 to avoid a */ + /* race condition when multiple threads are used. */ { #define USC (unsigned char *) htinit(hexdig, USC "0123456789", 0x10); htinit(hexdig, USC "abcdef", 0x10 + 10); htinit(hexdig, USC "ABCDEF", 0x10 + 10); } +#else + unsigned char hexdig[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; +#endif diff --git a/gdtoa/hexnan.c b/gdtoa/hexnan.c index 0ee127f56..80721e97a 100644 --- a/gdtoa/hexnan.c +++ b/gdtoa/hexnan.c @@ -54,15 +54,14 @@ L_shift(ULong *x, ULong *x1, int i) hexnan(sp, fpi, x0) CONST char **sp; FPI *fpi; ULong *x0; #else -hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) +hexnan( CONST char **sp, FPI *fpi, ULong *x0) #endif { ULong c, h, *x, *x1, *xe; CONST char *s; int havedig, hd0, i, nbits; - if (!hexdig['0']) - hexdig_init_D2A(); + /**** if (!hexdig['0']) hexdig_init_D2A(); ****/ nbits = fpi->nbits; x = x0 + (nbits >> kshift); if (nbits & kmask) @@ -72,12 +71,15 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) havedig = hd0 = i = 0; s = *sp; /* allow optional initial 0x or 0X */ - while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') + while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') { + if (!c) + goto retnan; ++s; + } if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') && *(CONST unsigned char*)(s+3) > ' ') s += 2; - while(c = *(CONST unsigned char*)++s) { + while((c = *(CONST unsigned char*)++s)) { if (!(h = hexdig[c])) { if (c <= ' ') { if (hd0 < havedig) { @@ -92,8 +94,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) x1 = x; i = 0; } - while(*(CONST unsigned char*)(s+1) <= ' ') + while((c = *(CONST unsigned char*)(s+1)) <= ' ') { + if (!c) + goto retnan; ++s; + } if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') && *(CONST unsigned char*)(s+3) > ' ') s += 2; @@ -107,10 +112,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) do { if (/*(*/ c == ')') { *sp = s + 1; - break; + goto break2; } - } while(c = *++s); + } while((c = *++s)); #endif + retnan: return STRTOG_NaN; } havedig++; @@ -120,8 +126,11 @@ hexnan( CONST char **sp, CONST FPI *fpi, ULong *x0) i = 1; *--x = 0; } - *x = (*x << 4) | h & 0xf; + *x = (*x << 4) | (h & 0xf); } +#ifndef GDTOA_NON_PEDANTIC_NANCHECK + break2: +#endif if (!havedig) return STRTOG_NaN; if (x < x1 && i < 8) diff --git a/gdtoa/misc.c b/gdtoa/misc.c index 51f8f52fe..d13046732 100644 --- a/gdtoa/misc.c +++ b/gdtoa/misc.c @@ -38,11 +38,6 @@ THIS SOFTWARE. #endif #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#ifdef MULTIPLE_THREADS -static void ACQUIRE_DTOA_LOCK(int n); -static void FREE_DTOA_LOCK(int n); #endif Bigint * @@ -60,7 +55,9 @@ Balloc #endif ACQUIRE_DTOA_LOCK(0); - if ( (rv = freelist[k]) !=0) { + /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ + /* but this case seems very unlikely. */ + if (k <= Kmax && (rv = freelist[k]) !=0) { freelist[k] = rv->next; } else { @@ -70,7 +67,7 @@ Balloc #else len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) /sizeof(double); - if (pmem_next - private_mem + len <= PRIVATE_mem) { + if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { rv = (Bigint*)pmem_next; pmem_next += len; } @@ -94,10 +91,18 @@ Bfree #endif { if (v) { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); + if (v->k > Kmax) +#ifdef FREE + FREE((void*)v); +#else + free((void*)v); +#endif + else { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } } } @@ -109,8 +114,8 @@ lo0bits (ULong *y) #endif { - register int k; - register ULong x = *y; + int k; + ULong x = *y; if (x & 7) { if (x & 1) @@ -209,12 +214,12 @@ multadd int hi0bits_D2A #ifdef KR_headers - (x) register ULong x; + (x) ULong x; #else - (register ULong x) + (ULong x) #endif { - register int k = 0; + int k = 0; if (!(x & 0xffff0000)) { k = 16; @@ -621,8 +626,8 @@ b2d #ifdef VAX ULong d0, d1; #else -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) #endif xa0 = a->x; @@ -635,16 +640,16 @@ b2d *e = 32 - k; #ifdef Pack_32 if (k < Ebits) { - d0 = Exp_1 | y >> Ebits - k; + d0 = Exp_1 | y >> (Ebits - k); w = xa > xa0 ? *--xa : 0; - d1 = y << (32-Ebits) + k | w >> Ebits - k; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); goto ret_d; } z = xa > xa0 ? *--xa : 0; if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> 32 - k; + d0 = Exp_1 | y << k | z >> (32 - k); y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> 32 - k; + d1 = z << k | y >> (32 - k); } else { d0 = Exp_1 | y; @@ -668,10 +673,10 @@ b2d #endif ret_d: #ifdef VAX - word0(d) = d0 >> 16 | d0 << 16; - word1(d) = d1 >> 16 | d1 << 16; + word0(&d) = d0 >> 16 | d0 << 16; + word1(&d) = d1 >> 16 | d1 << 16; #endif - return dval(d); + return dval(&d); } #undef d0 #undef d1 @@ -679,29 +684,28 @@ b2d Bigint * d2b #ifdef KR_headers - (d, e, bits) double d; int *e, *bits; + (dd, e, bits) double dd; int *e, *bits; #else - (double _d, int *e, int *bits) + (double dd, int *e, int *bits) #endif { Bigint *b; + U d; #ifndef Sudden_Underflow int i; #endif int de, k; ULong *x, y, z; - U d; #ifdef VAX ULong d0, d1; #else -#define d0 word0(d) -#define d1 word1(d) +#define d0 word0(&d) +#define d1 word1(&d) #endif - - dval(d) = _d; + d.d = dd; #ifdef VAX - d0 = word0(d) >> 16 | word0(d) << 16; - d1 = word1(d) >> 16 | word1(d) << 16; + d0 = word0(&d) >> 16 | word0(&d) << 16; + d1 = word1(&d) >> 16 | word1(&d) << 16; #endif #ifdef Pack_32 @@ -725,7 +729,7 @@ d2b #ifdef Pack_32 if ( (y = d1) !=0) { if ( (k = lo0bits(&y)) !=0) { - x[0] = y | z << 32 - k; + x[0] = y | z << (32 - k); z >>= k; } else @@ -736,10 +740,6 @@ d2b b->wds = (x[1] = z) !=0 ? 2 : 1; } else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow @@ -798,7 +798,7 @@ d2b #endif #ifdef IBM *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); + *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask); #else *e = de - Bias - (P-1) + k; *bits = P - k; @@ -851,71 +851,25 @@ strcp_D2A(a, b) char *a; char *b; strcp_D2A(char *a, CONST char *b) #endif { - while(*a = *b++) + while((*a = *b++)) a++; return a; } #ifdef NO_STRING_H - KR_VOID * + Char * #ifdef KR_headers -memcpy_D2A(a, b, len) char *a; char *b; size_t len; +memcpy_D2A(a, b, len) Char *a; Char *b; size_t len; #else memcpy_D2A(void *a1, void *b1, size_t len) #endif { - register char *a = (char*)a1, *ae = a + len; - register char *b = (char*)b1, *a0 = a; + char *a = (char*)a1, *ae = a + len; + char *b = (char*)b1, *a0 = a; while(a < ae) *a++ = *b++; return a0; } #endif /* NO_STRING_H */ - - -#ifdef MULTIPLE_THREADS -#ifdef _WIN32 - -#undef Bias -#define WIN32_LEAN_AND_MEAN -#include - -static CRITICAL_SECTION dtoa_lock[2]; -static int did_init; - -void ACQUIRE_DTOA_LOCK(int n) -{ - if (!did_init) - { - did_init = 1; - InitializeCriticalSection(&dtoa_lock[0]); - InitializeCriticalSection(&dtoa_lock[1]); - } - EnterCriticalSection(&dtoa_lock[n]); -} - -void FREE_DTOA_LOCK(int n) -{ - LeaveCriticalSection(&dtoa_lock[n]); -} - -#else - -#include - -static pthread_mutex_t dtoa_lock[2] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; - -void ACQUIRE_DTOA_LOCK(int n) -{ - pthread_mutex_lock(&dtoa_lock[n]); -} - -void FREE_DTOA_LOCK(int n) -{ - pthread_mutex_unlock(&dtoa_lock[n]); -} - -#endif -#endif diff --git a/gdtoa/qnan.c b/gdtoa/qnan.c index 118e74921..ea7e8745b 100644 --- a/gdtoa/qnan.c +++ b/gdtoa/qnan.c @@ -55,11 +55,19 @@ typedef unsigned Long Ulong; #ifdef IEEE_8087 #define _0 1 #define _1 0 +#define _3 3 +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) +static int perm[4] = { 0, 1, 2, 3 }; +#endif #define HAVE_IEEE #endif #ifdef IEEE_MC68k #define _0 0 #define _1 1 +#define _3 0 +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) +static int perm[4] = { 3, 2, 1, 0 }; +#endif #define HAVE_IEEE #endif @@ -79,31 +87,32 @@ main(void) #endif } U; U a, b, c; +#if defined(Gen_ld_QNAN) && !defined(NO_LONG_LONG) int i; +#endif a.L[0] = b.L[0] = 0x7f800000; c.f = a.f - b.f; - printf("#define f_QNAN 0x%lx\n", UL c.L[0]); + printf("#define f_QNAN 0x%lx\n", UL (c.L[0] & 0x7fffffff)); a.L[_0] = b.L[_0] = 0x7ff00000; a.L[_1] = b.L[_1] = 0; c.d = a.d - b.d; /* quiet NaN */ - printf("#define d_QNAN0 0x%lx\n", UL c.L[0]); - printf("#define d_QNAN1 0x%lx\n", UL c.L[1]); -#ifdef NO_LONG_LONG - for(i = 0; i < 4; i++) - printf("#define ld_QNAN%d 0xffffffff\n", i); - for(i = 0; i < 5; i++) - printf("#define ldus_QNAN%d 0xffff\n", i); -#else - b.D = c.D = a.d; - if (printf("") < 0) - c.D = 37; /* never executed; just defeat optimization */ - a.L[2] = a.L[3] = 0; - a.D = b.D - c.D; - for(i = 0; i < 4; i++) - printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[i]); - for(i = 0; i < 5; i++) - printf("#define ldus_QNAN%d 0x%x\n", i, a.u[i]); + c.L[_0] &= 0x7fffffff; + printf("#define d_QNAN0 0x%lx\n", UL c.L[_0]); + printf("#define d_QNAN1 0x%lx\n", UL c.L[_1]); +#ifndef NO_LONG_LONG +#ifdef Gen_ld_QNAN + if (sizeof(a.D) >= 16) { + b.D = c.D = a.d; + if (printf("") < 0) + c.D = 37; /* never executed; just defeat optimization */ + a.L[0] = a.L[1] = a.L[2] = a.L[3] = 0; + a.D = b.D - c.D; + a.L[_3] &= 0x7fffffff; + for(i = 0; i < 4; i++) + printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[perm[i]]); + } +#endif #endif #endif /* HAVE_IEEE */ return 0; diff --git a/gdtoa/smisc.c b/gdtoa/smisc.c index 858024c9e..f4dbafb21 100644 --- a/gdtoa/smisc.c +++ b/gdtoa/smisc.c @@ -34,9 +34,9 @@ THIS SOFTWARE. Bigint * s2b #ifdef KR_headers - (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9; + (s, nd0, nd, y9, dplen) CONST char *s; int dplen, nd0, nd; ULong y9; #else - (CONST char *s, int nd0, int nd, ULong y9) + (CONST char *s, int nd0, int nd, ULong y9, int dplen) #endif { Bigint *b; @@ -60,10 +60,10 @@ s2b s += 9; do b = multadd(b, 10, *s++ - '0'); while(++i < nd0); - s++; + s += dplen; } else - s += 10; + s += dplen + 9; for(; i < nd; i++) b = multadd(b, 10, *s++ - '0'); return b; @@ -80,30 +80,30 @@ ratio U da, db; int k, ka, kb; - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); k = ka - kb + ULbits*(a->wds - b->wds); #ifdef IBM if (k > 0) { - word0(da) += (k >> 2)*Exp_msk1; + word0(&da) += (k >> 2)*Exp_msk1; if (k &= 3) - dval(da) *= 1 << k; + dval(&da) *= 1 << k; } else { k = -k; - word0(db) += (k >> 2)*Exp_msk1; + word0(&db) += (k >> 2)*Exp_msk1; if (k &= 3) - dval(db) *= 1 << k; + dval(&db) *= 1 << k; } #else if (k > 0) - word0(da) += k*Exp_msk1; + word0(&da) += k*Exp_msk1; else { k = -k; - word0(db) += k*Exp_msk1; + word0(&db) += k*Exp_msk1; } #endif - return dval(da) / dval(db); + return dval(&da) / dval(&db); } #ifdef INFNAN_CHECK diff --git a/gdtoa/strtoIQ.c b/gdtoa/strtoIQ.c index 000fa3645..9ce5120e6 100644 --- a/gdtoa/strtoIQ.c +++ b/gdtoa/strtoIQ.c @@ -38,7 +38,7 @@ strtoIQ(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIQ(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; + static FPI fpi = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoId.c b/gdtoa/strtoId.c index d34a278ee..1c97d382d 100644 --- a/gdtoa/strtoId.c +++ b/gdtoa/strtoId.c @@ -38,7 +38,7 @@ strtoId(s, sp, f0, f1) CONST char *s; char **sp; double *f0, *f1; strtoId(CONST char *s, char **sp, double *f0, double *f1) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIdd.c b/gdtoa/strtoIdd.c index 921597fe7..40b7936bc 100644 --- a/gdtoa/strtoIdd.c +++ b/gdtoa/strtoIdd.c @@ -39,9 +39,9 @@ strtoIdd(CONST char *s, char **sp, double *f0, double *f1) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif Long exp[2]; Bigint *B[2]; diff --git a/gdtoa/strtoIf.c b/gdtoa/strtoIf.c index b937ff079..65ecab2e0 100644 --- a/gdtoa/strtoIf.c +++ b/gdtoa/strtoIf.c @@ -38,7 +38,7 @@ strtoIf(s, sp, f0, f1) CONST char *s; char **sp; float *f0, *f1; strtoIf(CONST char *s, char **sp, float *f0, float *f1) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIg.c b/gdtoa/strtoIg.c index fd181fc9b..6a17760cf 100644 --- a/gdtoa/strtoIg.c +++ b/gdtoa/strtoIg.c @@ -35,7 +35,7 @@ THIS SOFTWARE. #ifdef KR_headers strtoIg(s00, se, fpi, exp, B, rvp) CONST char *s00; char **se; FPI *fpi; Long *exp; Bigint **B; int *rvp; #else -strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int *rvp) +strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp) #endif { Bigint *b, *b1; @@ -61,16 +61,20 @@ strtoIg(CONST char *s00, char **se, CONST FPI *fpi, Long *exp, Bigint **B, int * if (rv & STRTOG_Inexlo) { swap = 0; b1 = increment(b1); - if (fpi->sudden_underflow - && (rv & STRTOG_Retmask) == STRTOG_Zero) { - b1->x[0] = 0; - b1->x[nw1] = 1L << nb11; - rv1 += STRTOG_Normal - STRTOG_Zero; - rv1 &= ~STRTOG_Underflow; + if ((rv & STRTOG_Retmask) == STRTOG_Zero) { + if (fpi->sudden_underflow) { + b1->x[0] = 0; + b1->x[nw1] = 1L << nb11; + rv1 += STRTOG_Normal - STRTOG_Zero; + rv1 &= ~STRTOG_Underflow; + goto swapcheck; + } + rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero; + rv1 |= STRTOG_Inexhi | STRTOG_Denormal; goto swapcheck; } if (b1->wds > nw - || nb1 && b1->x[nw1] & 1L << nb1) { + || (nb1 && b1->x[nw1] & 1L << nb1)) { if (++e1 > fpi->emax) rv1 = STRTOG_Infinite | STRTOG_Inexhi; rshift(b1, 1); diff --git a/gdtoa/strtoIx.c b/gdtoa/strtoIx.c index 8e972c976..783a631f0 100644 --- a/gdtoa/strtoIx.c +++ b/gdtoa/strtoIx.c @@ -38,7 +38,7 @@ strtoIx(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIx(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtoIxL.c b/gdtoa/strtoIxL.c index 86dbc744a..869bfd16f 100644 --- a/gdtoa/strtoIxL.c +++ b/gdtoa/strtoIxL.c @@ -38,7 +38,7 @@ strtoIxL(s, sp, a, b) CONST char *s; char **sp; void *a; void *b; strtoIxL(CONST char *s, char **sp, void *a, void *b) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; Long exp[2]; Bigint *B[2]; int k, rv[2]; diff --git a/gdtoa/strtod.c b/gdtoa/strtod.c index 1f01921a4..3c2230053 100644 --- a/gdtoa/strtod.c +++ b/gdtoa/strtod.c @@ -42,24 +42,43 @@ THIS SOFTWARE. #ifndef NO_IEEE_Scale #define Avoid_Underflow #undef tinytens -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ +/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */ /* flag unnecessarily. It leads to a song and dance at the end of strtod. */ static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, - 9007199254740992.e-256 + 9007199254740992.*9007199254740992.e-256 }; #endif #endif -#include - #ifdef Honor_FLT_ROUNDS -#define Rounding rounding #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else #define Rounding Flt_Rounds #endif +#ifdef Avoid_Underflow /*{*/ + static double +sulp +#ifdef KR_headers + (x, scale) U *x; int scale; +#else + (U *x, int scale) +#endif +{ + U u; + double rv; + int i; + + rv = ulp(x); + if (!scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) + return rv; /* Is there an example where i <= 0 ? */ + word0(&u) = Exp_1 + (i << Exp_shift); + word1(&u) = 0; + return rv * u.d; + } +#endif /*}*/ + double strtod #ifdef KR_headers @@ -74,21 +93,55 @@ strtod int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; CONST char *s, *s0, *s1; - double aadj, adj; - U rv, rv0, aadj1; + double aadj; Long L; + U adj, aadj1, rv, rv0; ULong y, z; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; +#ifdef Avoid_Underflow + ULong Lsb, Lsb1; +#endif #ifdef SET_INEXACT int inexact, oldinexact; #endif -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif +#ifdef USE_LOCALE /*{{*/ +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + int dplen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static int dplen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + dplen = strlen(s0); + } + decimalpoint = (char*)s0; +#endif /*NO_LOCALE_CACHE*/ +#else /*USE_LOCALE}{*/ +#define dplen 1 +#endif /*USE_LOCALE}}*/ + +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ - //_control87(_PC_53, _MCW_PC); sign = nz0 = nz = decpt = 0; - dval(rv) = 0.; + dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': sign = 1; @@ -111,22 +164,18 @@ strtod } break2: if (*s == '0') { -#ifndef NO_HEX_FP +#ifndef NO_HEX_FP /*{*/ { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { case 'x': case 'X': { -#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) +#ifdef Honor_FLT_ROUNDS FPI fpi1 = fpi; - switch(fegetround()) { - case FE_TOWARDZERO: fpi1.rounding = 0; break; - case FE_UPWARD: fpi1.rounding = 2; break; - case FE_DOWNWARD: fpi1.rounding = 3; - } + fpi1.rounding = Rounding; #else #define fpi1 fpi #endif @@ -146,7 +195,7 @@ strtod goto ret; } } -#endif +#endif /*}*/ nz0 = 1; while(*++s == '0') ; if (!*s) @@ -161,13 +210,17 @@ strtod z = 10*z + c - '0'; nd0 = nd; #ifdef USE_LOCALE - if (c == *localeconv()->decimal_point) + if (c == *decimalpoint) { + for(i = 1; decimalpoint[i]; ++i) + if (s[i] != decimalpoint[i]) + goto dig_done; + s += i; + c = *s; #else - if (c == '.') -#endif - { - decpt = 1; + if (c == '.') { c = *++s; +#endif + decpt = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -196,7 +249,7 @@ strtod nz = 0; } } - } + }/*}*/ dig_done: e = 0; if (c == 'e' || c == 'E') { @@ -240,7 +293,7 @@ strtod #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static CONST FPI fpinan = /* only 52 explicit bits */ + static FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -250,8 +303,8 @@ strtod --s; if (!match(&s,"inity")) ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; + word0(&rv) = 0x7ff00000; + word1(&rv) = 0; goto ret; } break; @@ -262,13 +315,13 @@ strtod if (*s == '(' /*)*/ && hexnan(&s, &fpinan, bits) == STRTOG_NaNbits) { - word0(rv) = 0x7ff00000 | bits[1]; - word1(rv) = bits[0]; + word0(&rv) = 0x7ff00000 | bits[1]; + word1(&rv) = bits[0]; } else { #endif - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; + word0(&rv) = NAN_WORD0; + word1(&rv) = NAN_WORD1; #ifndef No_Hex_NaN } #endif @@ -292,13 +345,13 @@ strtod if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; } bd0 = 0; if (nd <= DBL_DIG @@ -310,6 +363,7 @@ strtod ) { if (!e) goto ret; +#ifndef ROUND_BIASED_without_Round_Up if (e > 0) { if (e <= Ten_pmax) { #ifdef VAX @@ -318,11 +372,11 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; #endif } @@ -334,25 +388,25 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif e -= i; - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: - word0(rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(rv), tens[e]); - if ((word0(rv) & Exp_mask) + word0(&rv) -= P*Exp_msk1; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if ((word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; #else - /* rv = */ rounded_product(dval(rv), tens[e]); + /* rv = */ rounded_product(dval(&rv), tens[e]); #endif goto ret; } @@ -362,14 +416,15 @@ strtod #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + rv.d = -rv.d; sign = 0; } #endif - /* rv = */ rounded_quotient(dval(rv), tens[-e]); + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif +#endif /* ROUND_BIASED_without_Round_Up */ } e1 += nd - k; @@ -383,12 +438,12 @@ strtod scale = 0; #endif #ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { + if (Rounding >= 2) { if (sign) - rounding = rounding == 2 ? 0 : 2; + Rounding = Rounding == 2 ? 0 : 2; else - if (rounding != 2) - rounding = 0; + if (Rounding != 2) + Rounding = 0; } #endif #endif /*IEEE_Arith*/ @@ -397,67 +452,73 @@ strtod if (e1 > 0) { if ( (i = e1 & 15) !=0) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith #ifdef Honor_FLT_ROUNDS - switch(rounding) { + switch(Rounding) { case 0: /* toward 0 */ case 3: /* toward -infinity */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; break; default: - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; } #else /*Honor_FLT_ROUNDS*/ - word0(rv) = Exp_mask; - word1(rv) = 0; + word0(&rv) = Exp_mask; + word1(&rv) = 0; #endif /*Honor_FLT_ROUNDS*/ #ifdef SET_INEXACT /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e300; + dval(&rv0) *= dval(&rv0); #endif #else /*IEEE_Arith*/ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; #endif /*IEEE_Arith*/ - if (bd0) - goto retfree; + range_err: + if (bd0) { + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + } +#ifndef NO_ERRNO + errno = ERANGE; +#endif goto ret; } e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; /* The last multiplication could overflow. */ - word0(rv) -= P*Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) + word0(&rv) -= P*Exp_msk1; + dval(&rv) *= bigtens[j]; + if ((z = word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; } else - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ( (i = e1 & 15) !=0) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; @@ -466,44 +527,39 @@ strtod scale = 2*P; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) + dval(&rv) *= tinytens[j]; + if (scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { - word1(rv) = 0; + word1(&rv) = 0; if (j >= 53) - word0(rv) = (P+2)*Exp_msk1; + word0(&rv) = (P+2)*Exp_msk1; else - word0(rv) &= 0xffffffff << j-32; + word0(&rv) &= 0xffffffff << (j-32); } else - word1(rv) &= 0xffffffff << j; + word1(&rv) &= 0xffffffff << j; } #else for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2.*dval(rv0); - dval(rv) *= tinytens[j]; + dval(&rv0) = dval(&rv); + dval(&rv) *= tinytens[j]; + if (!dval(&rv)) { + dval(&rv) = 2.*dval(&rv0); + dval(&rv) *= tinytens[j]; #endif - if (!dval(rv)) { + if (!dval(&rv)) { undfl: - dval(rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - if (bd0) - goto retfree; - goto ret; + dval(&rv) = 0.; + goto range_err; } #ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; /* The refinement below will clean * this approximation up. */ @@ -516,12 +572,12 @@ strtod /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + bd0 = s2b(s0, nd0, nd, y, dplen); for(;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ + bb = d2b(dval(&rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { @@ -538,16 +594,23 @@ strtod bd2 -= bbe; bs2 = bb2; #ifdef Honor_FLT_ROUNDS - if (rounding != 1) + if (Rounding != 1) bs2++; #endif #ifdef Avoid_Underflow + Lsb = LSB; + Lsb1 = 0; j = bbe - scale; i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; + j = P + 1 - bbbits; + if (i < Emin) { /* denormal */ + i = Emin - i; + j -= i; + if (i < 32) + Lsb <<= i; + else + Lsb1 = Lsb << (i-32); + } #else /*Avoid_Underflow*/ #ifdef Sudden_Underflow #ifdef IBM @@ -557,7 +620,7 @@ strtod #endif #else /*Sudden_Underflow*/ j = bbe; - i = j + bbbits - 1; /* logb(rv) */ + i = j + bbbits - 1; /* logb(&rv) */ if (i < Emin) /* denormal */ j += P - Emin; else @@ -596,7 +659,7 @@ strtod delta->sign = 0; i = cmp(delta, bs); #ifdef Honor_FLT_ROUNDS - if (rounding != 1) { + if (Rounding != 1) { if (i < 0) { /* Error is less than an ulp */ if (!delta->x[0] && delta->wds <= 1) { @@ -606,17 +669,17 @@ strtod #endif break; } - if (rounding) { + if (Rounding) { if (dsign) { - adj = 1.; + dval(&adj) = 1.; goto apply_adj; } } else if (!dsign) { - adj = -1.; - if (!word1(rv) - && !(word0(rv) & Frac_mask)) { - y = word0(rv) & Exp_mask; + dval(&adj) = -1.; + if (!word1(&rv) + && !(word0(&rv) & Frac_mask)) { + y = word0(&rv) & Exp_mask; #ifdef Avoid_Underflow if (!scale || y > 2*P*Exp_msk1) #else @@ -625,63 +688,66 @@ strtod { delta = lshift(delta,Log2P); if (cmp(delta, bs) <= 0) - adj = -0.5; + dval(&adj) = -0.5; } } apply_adj: #ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) + if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; + word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - dval(rv) += adj*ulp(dval(rv)); - word0(rv) -= P*Exp_msk1; + word0(&rv) += P*Exp_msk1; + dval(&rv) += adj*ulp(&rv); + word0(&rv) -= P*Exp_msk1; } else #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ - dval(rv) += adj*ulp(dval(rv)); + dval(&rv) += adj.d*ulp(&rv); } break; } - adj = ratio(delta, bs); - if (adj < 1.) - adj = 1.; - if (adj <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ - y = adj; - if (y != adj) { - if (!((rounding>>1) ^ dsign)) + dval(&adj) = ratio(delta, bs); + if (adj.d < 1.) + dval(&adj) = 1.; + if (adj.d <= 0x7ffffffe) { + /* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */ + y = adj.d; + if (y != adj.d) { + if (!((Rounding>>1) ^ dsign)) y++; - adj = y; + dval(&adj) = y; } } #ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; + if (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) + word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - adj *= ulp(dval(rv)); + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + word0(&rv) += P*Exp_msk1; + dval(&adj) *= ulp(&rv); if (dsign) - dval(rv) += adj; + dval(&rv) += adj; else - dval(rv) -= adj; - word0(rv) -= P*Exp_msk1; + dval(&rv) -= adj; + word0(&rv) -= P*Exp_msk1; goto cont; } #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; + dval(&adj) *= ulp(&rv); + if (dsign) { + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; + dval(&rv) += adj.d; + } else - dval(rv) -= adj; + dval(&rv) -= adj.d; goto cont; } #endif /*Honor_FLT_ROUNDS*/ @@ -690,12 +756,12 @@ strtod /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask #ifdef IEEE_Arith #ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 + || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 #else - || (word0(rv) & Exp_mask) <= Exp_msk1 + || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif #endif ) { @@ -720,32 +786,34 @@ strtod if (i == 0) { /* exactly half-way between */ if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( + if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 + && word1(&rv) == ( #ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) + (scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; + word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1 #ifdef IBM | Exp_msk1 >> 4 #endif ; - word1(rv) = 0; + word1(&rv) = 0; #ifdef Avoid_Underflow dsign = 0; #endif break; } } - else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; #ifdef IBM if (L < Exp_msk1) #else @@ -760,7 +828,7 @@ strtod #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (scale) { - L = word0(rv) & Exp_mask; + L = word0(&rv) & Exp_mask; if (L <= (2*P+1)*Exp_msk1) { if (L > (P+2)*Exp_msk1) /* round even ==> */ @@ -771,10 +839,10 @@ strtod } } #endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; + L = (word0(&rv) & Exp_mask) - Exp_msk1; +#endif /*Sudden_Underflow}}*/ + word0(&rv) = L | Bndry_mask1; + word1(&rv) = 0xffffffff; #ifdef IBM goto cont; #else @@ -782,16 +850,33 @@ strtod #endif } #ifndef ROUND_BIASED - if (!(word1(rv) & LSB)) +#ifdef Avoid_Underflow + if (Lsb1) { + if (!(word0(&rv) & Lsb1)) + break; + } + else if (!(word1(&rv) & Lsb)) + break; +#else + if (!(word1(&rv) & LSB)) break; +#endif #endif if (dsign) - dval(rv) += ulp(dval(rv)); +#ifdef Avoid_Underflow + dval(&rv) += sulp(&rv, scale); +#else + dval(&rv) += ulp(&rv); +#endif #ifndef ROUND_BIASED else { - dval(rv) -= ulp(dval(rv)); +#ifdef Avoid_Underflow + dval(&rv) -= sulp(&rv, scale); +#else + dval(&rv) -= ulp(&rv); +#endif #ifndef Sudden_Underflow - if (!dval(rv)) + if (!dval(&rv)) goto undfl; #endif } @@ -803,14 +888,14 @@ strtod } if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) - aadj = dval(aadj1) = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { + aadj = dval(&aadj1) = 1.; + else if (word1(&rv) || word0(&rv) & Bndry_mask) { #ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) + if (word1(&rv) == Tiny1 && !word0(&rv)) goto undfl; #endif aadj = 1.; - dval(aadj1) = -1.; + dval(&aadj1) = -1.; } else { /* special case -- power of FLT_RADIX to be */ @@ -820,45 +905,45 @@ strtod aadj = 1./FLT_RADIX; else aadj *= 0.5; - dval(aadj1) = -aadj; + dval(&aadj1) = -aadj; } } else { aadj *= 0.5; - dval(aadj1) = dsign ? aadj : -aadj; + dval(&aadj1) = dsign ? aadj : -aadj; #ifdef Check_FLT_ROUNDS switch(Rounding) { case 2: /* towards +infinity */ - aadj1 -= 0.5; + dval(&aadj1) -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ - aadj1 += 0.5; + dval(&aadj1) += 0.5; } #else if (Flt_Rounds == 0) - dval(aadj1) += 0.5; + dval(&aadj1) += 0.5; #endif /*Check_FLT_ROUNDS*/ } - y = word0(rv) & Exp_mask; + y = word0(&rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(rv0) = dval(rv); - word0(rv) -= P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= + dval(&rv0) = dval(&rv); + word0(&rv) -= P*Exp_msk1; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += dval(&adj); + if ((word0(&rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; + word0(&rv) = Big0; + word1(&rv) = Big1; goto cont; } else - word0(rv) += P*Exp_msk1; + word0(&rv) += P*Exp_msk1; } else { #ifdef Avoid_Underflow @@ -867,58 +952,58 @@ strtod if ((z = (ULong)aadj) <= 0) z = 1; aadj = z; - dval(aadj1) = dsign ? aadj : -aadj; + dval(&aadj1) = dsign ? aadj : -aadj; } - word0(aadj1) += (2*P+1)*Exp_msk1 - y; + word0(&aadj1) += (2*P+1)*Exp_msk1 - y; } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += dval(&adj); #else #ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P*Exp_msk1; - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { + dval(&rv0) = dval(&rv); + word0(&rv) += P*Exp_msk1; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; #ifdef IBM - if ((word0(rv) & Exp_mask) < P*Exp_msk1) + if ((word0(&rv) & Exp_mask) < P*Exp_msk1) #else - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) + if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) #endif { - if (word0(rv0) == Tiny0 - && word1(rv0) == Tiny1) + if (word0(&rv0) == Tiny0 + && word1(&rv0) == Tiny1) goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; + word0(&rv) = Tiny0; + word1(&rv) = Tiny1; goto cont; } else - word0(rv) -= P*Exp_msk1; + word0(&rv) -= P*Exp_msk1; } else { - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; } #else /*Sudden_Underflow*/ - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., + /* Compute dval(&adj) so that the IEEE rounding rules will + * correctly round rv + dval(&adj) in some half-way cases. + * If rv * ulp(&rv) is denormalized (i.e., * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid * trouble from bits lost to denormalization; * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - aadj1 = (double)(int)(aadj + 0.5); + dval(&aadj1) = (double)(int)(aadj + 0.5); if (!dsign) - aadj1 = -aadj1; + dval(&aadj1) = -dval(&aadj1); } - adj = aadj1 * ulp(dval(rv)); - dval(rv) += adj; + dval(&adj) = dval(&aadj1) * ulp(&rv); + dval(&rv) += adj; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } - z = word0(rv) & Exp_mask; + z = word0(&rv) & Exp_mask; #ifndef SET_INEXACT #ifdef Avoid_Underflow if (!scale) @@ -928,7 +1013,7 @@ strtod L = (Long)aadj; aadj -= L; /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } @@ -942,12 +1027,17 @@ strtod Bfree(bs); Bfree(delta); } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; + word0(&rv0) = Exp_1 + (70 << Exp_shift); + word1(&rv0) = 0; + dval(&rv0) += 1.; } } else if (!oldinexact) @@ -955,32 +1045,30 @@ strtod #endif #ifdef Avoid_Underflow if (scale) { - word0(rv0) = Exp_1 - 2*P*Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); + word0(&rv0) = Exp_1 - 2*P*Exp_msk1; + word1(&rv0) = 0; + dval(&rv) *= dval(&rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) +#ifdef IEEE_Arith + if (!(word0(&rv) & Exp_mask)) +#else + if (word0(&rv) == 0 && word1(&rv) == 0) +#endif errno = ERANGE; #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { + if (inexact && !(word0(&rv) & Exp_mask)) { /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); + dval(&rv0) = 1e-300; + dval(&rv0) *= dval(&rv0); } #endif - retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); ret: if (se) *se = (char *)s; - return sign ? -dval(rv) : dval(rv); + return sign ? -dval(&rv) : dval(&rv); } diff --git a/gdtoa/strtodI.c b/gdtoa/strtodI.c index 992702e25..0b7b8a45c 100644 --- a/gdtoa/strtodI.c +++ b/gdtoa/strtodI.c @@ -33,16 +33,16 @@ THIS SOFTWARE. static double #ifdef KR_headers -ulpdown(d) double *d; +ulpdown(d) U *d; #else -ulpdown(double *d) +ulpdown(U *d) #endif { double u; - ULong *L = (ULong*)d; + ULong *L = d->L; - u = ulp(*d); - if (!(L[_1] | L[_0] & 0xfffff) + u = ulp(d); + if (!(L[_1] | (L[_0] & 0xfffff)) && (L[_0] & 0x7ff00000) > 0x00100000) u *= 0.5; return u; @@ -55,14 +55,10 @@ strtodI(s, sp, dd) CONST char *s; char **sp; double *dd; strtodI(CONST char *s, char **sp, double *dd) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2], sign; Long exp; int j, k; - typedef union { - double d[2]; - ULong L[4]; - } U; U *u; k = strtodg(s, sp, &fpi, &exp, bits); @@ -70,17 +66,17 @@ strtodI(CONST char *s, char **sp, double *dd) sign = k & STRTOG_Neg ? 0x80000000L : 0; switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: - u->d[0] = u->d[1] = 0.; + dval(&u[0]) = dval(&u[1]) = 0.; break; case STRTOG_Zero: - u->d[0] = u->d[1] = 0.; + dval(&u[0]) = dval(&u[1]) = 0.; #ifdef Sudden_Underflow if (k & STRTOG_Inexact) { if (sign) - u->L[_0] = 0x80100000L; + word0(&u[0]) = 0x80100000L; else - u->L[2+_0] = 0x100000L; + word0(&u[1]) = 0x100000L; } break; #else @@ -88,80 +84,80 @@ strtodI(CONST char *s, char **sp, double *dd) #endif case STRTOG_Denormal: - u->L[_1] = bits[0]; - u->L[_0] = bits[1]; + word1(&u[0]) = bits[0]; + word0(&u[0]) = bits[1]; goto contain; case STRTOG_Normal: - u->L[_1] = bits[0]; - u->L[_0] = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); + word1(&u[0]) = bits[0]; + word0(&u[0]) = (bits[1] & ~0x100000) | ((exp + 0x3ff + 52) << 20); contain: j = k & STRTOG_Inexact; if (sign) { - u->L[_0] |= sign; + word0(&u[0]) |= sign; j = STRTOG_Inexact - j; } switch(j) { case STRTOG_Inexlo: #ifdef Sudden_Underflow if ((u->L[_0] & 0x7ff00000) < 0x3500000) { - u->L[2+_0] = u->L[_0] + 0x3500000; - u->L[2+_1] = u->L[_1]; - u->d[1] += ulp(u->d[1]); - u->L[2+_0] -= 0x3500000; - if (!(u->L[2+_0] & 0x7ff00000)) { - u->L[2+_0] = sign; - u->L[2+_1] = 0; + word0(&u[1]) = word0(&u[0]) + 0x3500000; + word1(&u[1]) = word1(&u[0]); + dval(&u[1]) += ulp(&u[1]); + word0(&u[1]) -= 0x3500000; + if (!(word0(&u[1]) & 0x7ff00000)) { + word0(&u[1]) = sign; + word1(&u[1]) = 0; } } else #endif - u->d[1] = u->d[0] + ulp(u->d[0]); + dval(&u[1]) = dval(&u[0]) + ulp(&u[0]); break; case STRTOG_Inexhi: - u->d[1] = u->d[0]; + dval(&u[1]) = dval(&u[0]); #ifdef Sudden_Underflow - if ((u->L[_0] & 0x7ff00000) < 0x3500000) { - u->L[_0] += 0x3500000; - u->d[0] -= ulpdown(u->d); - u->L[_0] -= 0x3500000; - if (!(u->L[_0] & 0x7ff00000)) { - u->L[_0] = sign; - u->L[_1] = 0; + if ((word0(&u[0]) & 0x7ff00000) < 0x3500000) { + word0(&u[0]) += 0x3500000; + dval(&u[0]) -= ulpdown(u); + word0(&u[0]) -= 0x3500000; + if (!(word0(&u[0]) & 0x7ff00000)) { + word0(&u[0]) = sign; + word1(&u[0]) = 0; } } else #endif - u->d[0] -= ulpdown(u->d); + dval(&u[0]) -= ulpdown(u); break; default: - u->d[1] = u->d[0]; + dval(&u[1]) = dval(&u[0]); } break; case STRTOG_Infinite: - u->L[_0] = u->L[2+_0] = sign | 0x7ff00000; - u->L[_1] = u->L[2+_1] = 0; + word0(&u[0]) = word0(&u[1]) = sign | 0x7ff00000; + word1(&u[0]) = word1(&u[1]) = 0; if (k & STRTOG_Inexact) { if (sign) { - u->L[2+_0] = 0xffefffffL; - u->L[2+_1] = 0xffffffffL; + word0(&u[1]) = 0xffefffffL; + word1(&u[1]) = 0xffffffffL; } else { - u->L[_0] = 0x7fefffffL; - u->L[_1] = 0xffffffffL; + word0(&u[0]) = 0x7fefffffL; + word1(&u[0]) = 0xffffffffL; } } break; case STRTOG_NaN: - u->L[0] = u->L[2] = d_QNAN0; - u->L[1] = u->L[3] = d_QNAN1; + u->L[0] = (u+1)->L[0] = d_QNAN0; + u->L[1] = (u+1)->L[1] = d_QNAN1; break; case STRTOG_NaNbits: - u->L[_0] = u->L[2+_0] = 0x7ff00000 | sign | bits[1]; - u->L[_1] = u->L[2+_1] = bits[0]; + word0(&u[0]) = word0(&u[1]) = 0x7ff00000 | sign | bits[1]; + word1(&u[0]) = word1(&u[1]) = bits[0]; } return k; } diff --git a/gdtoa/strtodg.c b/gdtoa/strtodg.c index 2d154148d..c2e3365c7 100644 --- a/gdtoa/strtodg.c +++ b/gdtoa/strtodg.c @@ -89,7 +89,7 @@ increment(Bigint *b) return b; } - int + void #ifdef KR_headers decrement(b) Bigint *b; #else @@ -119,7 +119,6 @@ decrement(Bigint *b) *x++ = y & 0xffff; } while(borrow && x < xe); #endif - return STRTOG_Inexlo; } static int @@ -173,9 +172,9 @@ set_ones(Bigint *b, int n) rvOK #ifdef KR_headers (d, fpi, exp, bits, exact, rd, irv) - double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv; + U *d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv; #else - (double d, CONST FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv) + (U *d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv) #endif { Bigint *b; @@ -183,7 +182,7 @@ rvOK int bdif, e, j, k, k1, nb, rv; carry = rv = 0; - b = d2b(d, &e, &bdif); + b = d2b(dval(d), &e, &bdif); bdif -= nb = fpi->nbits; e += bdif; if (bdif <= 0) { @@ -206,9 +205,9 @@ rvOK goto ret; } switch(rd) { - case 1: + case 1: /* round down (toward -Infinity) */ goto trunc; - case 2: + case 2: /* round up (toward +Infinity) */ break; default: /* round near */ k = bdif - 1; @@ -292,15 +291,12 @@ rvOK static int #ifdef KR_headers -mantbits(d) double d; +mantbits(d) U *d; #else -mantbits(double _d) +mantbits(U *d) #endif { ULong L; - U d; - - dval(d) = _d; #ifdef VAX L = word1(d) << 16 | word1(d) >> 16; if (L) @@ -322,7 +318,7 @@ strtodg (s00, se, fpi, exp, bits) CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; #else - (CONST char *s00, char **se, CONST FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) #endif { int abe, abits, asub; @@ -332,14 +328,35 @@ strtodg int sudden_underflow; CONST char *s, *s0, *s1; double adj0, tol; - U adj, rv; Long L; - ULong y, z; + U adj, rv; + ULong *b, *be, y, z; Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; +#ifdef USE_LOCALE /*{{*/ +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + int dplen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static int dplen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + dplen = strlen(s0); + } + decimalpoint = (char*)s0; +#endif /*NO_LOCALE_CACHE*/ +#else /*USE_LOCALE}{*/ +#define dplen 1 +#endif /*USE_LOCALE}}*/ irv = STRTOG_Zero; denorm = sign = nz0 = nz = 0; - dval(rv) = 0.; + dval(&rv) = 0.; rvb = 0; nbits = fpi->nbits; for(s = s00;;s++) switch(*s) { @@ -394,13 +411,17 @@ strtodg z = 10*z + c - '0'; nd0 = nd; #ifdef USE_LOCALE - if (c == *localeconv()->decimal_point) + if (c == *decimalpoint) { + for(i = 1; decimalpoint[i]; ++i) + if (s[i] != decimalpoint[i]) + goto dig_done; + s += i; + c = *s; #else - if (c == '.') -#endif - { - decpt = 1; + if (c == '.') { c = *++s; +#endif + decpt = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -429,7 +450,7 @@ strtodg nz = 0; } } - } + }/*}*/ dig_done: e = 0; if (c == 'e' || c == 'E') { @@ -527,13 +548,13 @@ strtodg if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(rv) = y; + dval(&rv) = y; if (k > 9) - dval(rv) = tens[k - 9] * dval(rv) + z; + dval(&rv) = tens[k - 9] * dval(&rv) + z; bd0 = 0; if (nbits <= P && nd <= DBL_DIG) { if (!e) { - if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv)) + if (rvOK(&rv, fpi, exp, bits, 1, rd, &irv)) goto ret; } else if (e > 0) { @@ -541,9 +562,9 @@ strtodg #ifdef VAX goto vax_ovfl_check; #else - i = fivesbits[e] + mantbits(dval(rv)) <= P; - /* rv = */ rounded_product(dval(rv), tens[e]); - if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv)) + i = fivesbits[e] + mantbits(&rv) <= P; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if (rvOK(&rv, fpi, exp, bits, i, rd, &irv)) goto ret; e1 -= e; goto rv_notOK; @@ -556,32 +577,32 @@ strtodg */ e2 = e - i; e1 -= i; - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: - dval(adj) = dval(rv); - word0(adj) -= P*Exp_msk1; - /* adj = */ rounded_product(dval(adj), tens[e2]); - if ((word0(adj) & Exp_mask) + dval(&adj) = dval(&rv); + word0(&adj) -= P*Exp_msk1; + /* adj = */ rounded_product(dval(&adj), tens[e2]); + if ((word0(&adj) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto rv_notOK; - word0(adj) += P*Exp_msk1; - dval(rv) = dval(adj); + word0(&adj) += P*Exp_msk1; + dval(&rv) = dval(&adj); #else - /* rv = */ rounded_product(dval(rv), tens[e2]); + /* rv = */ rounded_product(dval(&rv), tens[e2]); #endif - if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv)) + if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) goto ret; e1 -= e2; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(rv), tens[-e]); - if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv)) + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); + if (rvOK(&rv, fpi, exp, bits, 0, rd, &irv)) goto ret; e1 -= e; } @@ -595,45 +616,45 @@ strtodg e2 = 0; if (e1 > 0) { if ( (i = e1 & 15) !=0) - dval(rv) *= tens[i]; + dval(&rv) *= tens[i]; if (e1 &= ~15) { e1 >>= 4; - while(e1 >= (1 << n_bigtens-1)) { - e2 += ((word0(rv) & Exp_mask) + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; - dval(rv) *= bigtens[n_bigtens-1]; - e1 -= 1 << n_bigtens-1; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= bigtens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); } - e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= bigtens[j]; + dval(&rv) *= bigtens[j]; } } else if (e1 < 0) { e1 = -e1; if ( (i = e1 & 15) !=0) - dval(rv) /= tens[i]; + dval(&rv) /= tens[i]; if (e1 &= ~15) { e1 >>= 4; - while(e1 >= (1 << n_bigtens-1)) { - e2 += ((word0(rv) & Exp_mask) + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; - dval(rv) *= tinytens[n_bigtens-1]; - e1 -= 1 << n_bigtens-1; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= tinytens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); } - e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias; - word0(rv) &= ~Exp_mask; - word0(rv) |= Bias << Exp_shift1; + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) - dval(rv) *= tinytens[j]; + dval(&rv) *= tinytens[j]; } } #ifdef IBM @@ -644,7 +665,7 @@ strtodg */ e2 <<= 2; #endif - rvb = d2b(dval(rv), &rve, &rvbits); /* rv = rvb * 2^rve */ + rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */ rve += e2; if ((j = rvbits - nbits) > 0) { rshift(rvb, j); @@ -688,7 +709,7 @@ strtodg /* Put digits into bd: true value = bd * 10^e */ - bd0 = s2b(s0, nd0, nd, y); + bd0 = s2b(s0, nd0, nd, y, dplen); for(;;) { bd = Balloc(bd0->k); @@ -822,7 +843,7 @@ strtodg } else irv = STRTOG_Normal | STRTOG_Inexhi; - if (bbbits < nbits && !denorm || !(rvb->x[0] & 1)) + if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1)) break; if (dsign) { rvb = increment(rvb); @@ -839,7 +860,7 @@ strtodg } break; } - if ((dval(adj) = ratio(delta, bs)) <= 2.) { + if ((dval(&adj) = ratio(delta, bs)) <= 2.) { adj1: inex = STRTOG_Inexlo; if (dsign) { @@ -853,15 +874,15 @@ strtodg irv = STRTOG_Underflow | STRTOG_Inexlo; break; } - adj0 = dval(adj) = 1.; + adj0 = dval(&adj) = 1.; } else { - adj0 = dval(adj) *= 0.5; + adj0 = dval(&adj) *= 0.5; if (dsign) { asub = 0; inex = STRTOG_Inexlo; } - if (dval(adj) < 2147483647.) { + if (dval(&adj) < 2147483647.) { L = (Long)adj0; adj0 -= L; switch(rd) { @@ -880,12 +901,12 @@ strtodg inex = STRTOG_Inexact - inex; } } - dval(adj) = L; + dval(&adj) = L; } } y = rve + rvbits; - /* adj *= ulp(dval(rv)); */ + /* adj *= ulp(dval(&rv)); */ /* if (asub) rv -= adj; else rv += adj; */ if (!denorm && rvbits < nbits) { @@ -893,7 +914,7 @@ strtodg rve -= j; rvbits = nbits; } - ab = d2b(dval(adj), &abe, &abits); + ab = d2b(dval(&adj), &abe, &abits); if (abe < 0) rshift(ab, -abe); else if (abe > 0) @@ -947,15 +968,15 @@ strtodg z = rve + rvbits; if (y == z && L) { /* Can we stop now? */ - tol = dval(adj) * 5e-16; /* > max rel error */ - dval(adj) = adj0 - .5; - if (dval(adj) < -tol) { + tol = dval(&adj) * 5e-16; /* > max rel error */ + dval(&adj) = adj0 - .5; + if (dval(&adj) < -tol) { if (adj0 > tol) { irv |= inex; break; } } - else if (dval(adj) > tol && adj0 < 1. - tol) { + else if (dval(&adj) > tol && adj0 < 1. - tol) { irv |= inex; break; } @@ -980,6 +1001,29 @@ strtodg Bfree(bd0); Bfree(delta); if (rve > fpi->emax) { + switch(fpi->rounding & 3) { + case FPI_Round_near: + goto huge; + case FPI_Round_up: + if (!sign) + goto huge; + break; + case FPI_Round_down: + if (sign) + goto huge; + } + /* Round to largest representable magnitude */ + Bfree(rvb); + rvb = 0; + irv = STRTOG_Normal | STRTOG_Inexlo; + *exp = fpi->emax; + b = bits; + be = b + ((fpi->nbits + 31) >> 5); + while(b < be) + *b++ = -1; + if ((j = fpi->nbits & 0x1f)) + *--be >>= (32 - j); + goto ret; huge: rvb->wds = 0; irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; @@ -994,12 +1038,19 @@ strtodg if (sudden_underflow) { rvb->wds = 0; irv = STRTOG_Underflow | STRTOG_Inexlo; +#ifndef NO_ERRNO + errno = ERANGE; +#endif } else { irv = (irv & ~STRTOG_Retmask) | (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero); - if (irv & STRTOG_Inexact) + if (irv & STRTOG_Inexact) { irv |= STRTOG_Underflow; +#ifndef NO_ERRNO + errno = ERANGE; +#endif + } } } if (se) diff --git a/gdtoa/strtodnrp.c b/gdtoa/strtodnrp.c index 3d0297f52..19a769f0b 100644 --- a/gdtoa/strtodnrp.c +++ b/gdtoa/strtodnrp.c @@ -44,7 +44,7 @@ strtod(s, sp) CONST char *s; char **sp; strtod(CONST char *s, char **sp) #endif { - static CONST FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtof.c b/gdtoa/strtof.c index 561264a1d..a8beb3520 100644 --- a/gdtoa/strtof.c +++ b/gdtoa/strtof.c @@ -38,13 +38,18 @@ strtof(s, sp) CONST char *s; char **sp; strtof(CONST char *s, char **sp) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; union { ULong L[1]; float f; } u; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -53,7 +58,7 @@ strtof(CONST char *s, char **sp) case STRTOG_Normal: case STRTOG_NaNbits: - u.L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + u.L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: diff --git a/gdtoa/strtopQ.c b/gdtoa/strtopQ.c index 9eefd768f..2acf7e910 100644 --- a/gdtoa/strtopQ.c +++ b/gdtoa/strtopQ.c @@ -49,6 +49,9 @@ THIS SOFTWARE. #define _3 0 #endif + extern ULong NanDflt_Q_D2A[4]; + + int #ifdef KR_headers strtopQ(s, sp, V) CONST char *s; char **sp; void *V; @@ -56,13 +59,18 @@ strtopQ(s, sp, V) CONST char *s; char **sp; void *V; strtopQ(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; ULong *L = (ULong*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -90,10 +98,10 @@ strtopQ(CONST char *s, char **sp, void *V) break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; - L[3] = ld_QNAN3; + L[_0] = NanDflt_Q_D2A[3]; + L[_1] = NanDflt_Q_D2A[2]; + L[_2] = NanDflt_Q_D2A[1]; + L[_3] = NanDflt_Q_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; diff --git a/gdtoa/strtopd.c b/gdtoa/strtopd.c index 4c8bbaf42..0fb35daea 100644 --- a/gdtoa/strtopd.c +++ b/gdtoa/strtopd.c @@ -38,12 +38,17 @@ strtopd(s, sp, d) char *s; char **sp; double *d; strtopd(CONST char *s, char **sp, double *d) #endif { - static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; ULong bits[2]; Long exp; int k; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi0, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); ULtod((ULong*)d, bits, exp, k); return k; } diff --git a/gdtoa/strtopdd.c b/gdtoa/strtopdd.c index d2c6d9b89..738372d88 100644 --- a/gdtoa/strtopdd.c +++ b/gdtoa/strtopdd.c @@ -39,9 +39,9 @@ strtopdd(CONST char *s, char **sp, double *dd) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif ULong bits[4]; Long exp; @@ -51,8 +51,13 @@ strtopdd(CONST char *s, char **sp, double *dd) ULong L[4]; } U; U *u; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - rv = strtodg(s, sp, &fpi, &exp, bits); + rv = strtodg(s, sp, fpi, &exp, bits); u = (U*)dd; switch(rv & STRTOG_Retmask) { case STRTOG_NoNumber: @@ -62,8 +67,8 @@ strtopdd(CONST char *s, char **sp, double *dd) case STRTOG_Normal: u->L[_1] = (bits[1] >> 21 | bits[2] << 11) & 0xffffffffL; - u->L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff - | exp + 0x3ff + 105 << 20; + u->L[_0] = (bits[2] >> 21) | ((bits[3] << 11) & 0xfffff) + | ((exp + 0x3ff + 105) << 20); exp += 0x3ff + 52; if (bits[1] &= 0x1fffff) { i = hi0bits(bits[1]) - 11; @@ -74,7 +79,7 @@ strtopdd(CONST char *s, char **sp, double *dd) else exp -= i; if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> 32-i; + bits[1] = bits[1] << i | bits[0] >> (32-i); bits[0] = bits[0] << i & 0xffffffffL; } } @@ -87,11 +92,11 @@ strtopdd(CONST char *s, char **sp, double *dd) else exp -= i; if (i < 32) { - bits[1] = bits[0] >> 32 - i; + bits[1] = bits[0] >> (32 - i); bits[0] = bits[0] << i & 0xffffffffL; } else { - bits[1] = bits[0] << i - 32; + bits[1] = bits[0] << (i - 32); bits[0] = 0; } } @@ -100,7 +105,7 @@ strtopdd(CONST char *s, char **sp, double *dd) break; } u->L[2+_1] = bits[0]; - u->L[2+_0] = bits[1] & 0xfffff | exp << 20; + u->L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); break; case STRTOG_Denormal: @@ -119,10 +124,10 @@ strtopdd(CONST char *s, char **sp, double *dd) nearly_normal: i = hi0bits(bits[3]) - 11; /* i >= 12 */ j = 32 - i; - u->L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff - | 65 - i << 20; + u->L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) + | ((65 - i) << 20); u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - u->L[2+_0] = bits[1] & (1L << j) - 1; + u->L[2+_0] = bits[1] & ((1L << j) - 1); u->L[2+_1] = bits[0]; break; @@ -131,34 +136,34 @@ strtopdd(CONST char *s, char **sp, double *dd) if (i < 0) { j = -i; i += 32; - u->L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20; - u->L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - u->L[2+_0] = bits[1] & (1L << j) - 1; + u->L[_0] = (bits[2] >> j & 0xfffff) | (33 + j) << 20; + u->L[_1] = ((bits[2] << i) | (bits[1] >> j)) & 0xffffffffL; + u->L[2+_0] = bits[1] & ((1L << j) - 1); u->L[2+_1] = bits[0]; break; } if (i == 0) { - u->L[_0] = bits[2] & 0xfffff | 33 << 20; + u->L[_0] = (bits[2] & 0xfffff) | (33 << 20); u->L[_1] = bits[1]; u->L[2+_0] = 0; u->L[2+_1] = bits[0]; break; } j = 32 - i; - u->L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff - | j + 1 << 20; + u->L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) + | ((j + 1) << 20); u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & (1L << j) - 1; + u->L[2+_1] = bits[0] & ((1L << j) - 1); break; hardly_normal: j = 11 - hi0bits(bits[1]); i = 32 - j; - u->L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20; + u->L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); u->L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; u->L[2+_0] = 0; - u->L[2+_1] = bits[0] & (1L << j) - 1; + u->L[2+_1] = bits[0] & ((1L << j) - 1); break; case STRTOG_Infinite: diff --git a/gdtoa/strtopf.c b/gdtoa/strtopf.c index 806e14f6f..23ca5cbe5 100644 --- a/gdtoa/strtopf.c +++ b/gdtoa/strtopf.c @@ -38,12 +38,17 @@ strtopf(s, sp, f) CONST char *s; char **sp; float *f; strtopf(CONST char *s, char **sp, float *f) #endif { - static CONST FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1], *L; Long exp; int k; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); L = (ULong*)f; switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: @@ -53,7 +58,7 @@ strtopf(CONST char *s, char **sp, float *f) case STRTOG_Normal: case STRTOG_NaNbits: - L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: diff --git a/gdtoa/strtopx.c b/gdtoa/strtopx.c index ecd0b3991..32192c572 100644 --- a/gdtoa/strtopx.c +++ b/gdtoa/strtopx.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern UShort NanDflt_ldus_D2A[5]; + #undef _0 #undef _1 @@ -58,13 +60,18 @@ strtopx(s, sp, V) CONST char *s; char **sp; void *V; strtopx(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; ULong bits[2]; Long exp; int k; UShort *L = (UShort*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -87,15 +94,16 @@ strtopx(CONST char *s, char **sp, void *V) case STRTOG_Infinite: L[_0] = 0x7fff; - L[_1] = L[_2] = L[_3] = L[_4] = 0; + L[_1] = 0x8000; + L[_2] = L[_3] = L[_4] = 0; break; case STRTOG_NaN: - L[0] = ldus_QNAN0; - L[1] = ldus_QNAN1; - L[2] = ldus_QNAN2; - L[3] = ldus_QNAN3; - L[4] = ldus_QNAN4; + L[_4] = NanDflt_ldus_D2A[0]; + L[_3] = NanDflt_ldus_D2A[1]; + L[_2] = NanDflt_ldus_D2A[2]; + L[_1] = NanDflt_ldus_D2A[3]; + L[_0] = NanDflt_ldus_D2A[4]; } if (k & STRTOG_Neg) L[_0] |= 0x8000; diff --git a/gdtoa/strtopxL.c b/gdtoa/strtopxL.c index 00810fa35..6166c1e62 100644 --- a/gdtoa/strtopxL.c +++ b/gdtoa/strtopxL.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_xL_D2A[3]; + #undef _0 #undef _1 @@ -54,13 +56,18 @@ strtopxL(s, sp, V) CONST char *s; char **sp; void *V; strtopxL(CONST char *s, char **sp, void *V) #endif { - static CONST FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; ULong bits[2]; Long exp; int k; ULong *L = (ULong*)V; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif - k = strtodg(s, sp, &fpi, &exp, bits); + k = strtodg(s, sp, fpi, &exp, bits); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -77,13 +84,14 @@ strtopxL(CONST char *s, char **sp, void *V) case STRTOG_Infinite: L[_0] = 0x7fff << 16; - L[_1] = L[_2] = 0; + L[_1] = 0x80000000; + L[_2] = 0; break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; + L[_0] = NanDflt_xL_D2A[2]; + L[_1] = NanDflt_xL_D2A[1]; + L[_2] = NanDflt_xL_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; diff --git a/gdtoa/strtorQ.c b/gdtoa/strtorQ.c index 1cb157890..f5fd7bba9 100644 --- a/gdtoa/strtorQ.c +++ b/gdtoa/strtorQ.c @@ -49,6 +49,8 @@ THIS SOFTWARE. #define _3 0 #endif + extern ULong NanDflt_Q_D2A[4]; + void #ifdef KR_headers ULtoQ(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -83,10 +85,10 @@ ULtoQ(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; - L[3] = ld_QNAN3; + L[_0] = NanDflt_Q_D2A[3]; + L[_1] = NanDflt_Q_D2A[2]; + L[_2] = NanDflt_Q_D2A[1]; + L[_3] = NanDflt_Q_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -99,9 +101,8 @@ strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorQ(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[4]; Long exp; int k; diff --git a/gdtoa/strtord.c b/gdtoa/strtord.c index 1aa7aefe3..dd0769698 100644 --- a/gdtoa/strtord.c +++ b/gdtoa/strtord.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_d_D2A[2]; + void #ifdef KR_headers ULtod(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -61,8 +63,8 @@ ULtod(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = d_QNAN0; - L[1] = d_QNAN1; + L[_0] = NanDflt_d_D2A[1]; + L[_1] = NanDflt_d_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -75,9 +77,8 @@ strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; strtord(CONST char *s, char **sp, int rounding, double *d) #endif { - static CONST FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtordd.c b/gdtoa/strtordd.c index 5b505f1b8..62152dbd4 100644 --- a/gdtoa/strtordd.c +++ b/gdtoa/strtordd.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_d_D2A[2]; + void #ifdef KR_headers ULtodd(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -48,8 +50,8 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) case STRTOG_Normal: L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL; - L[_0] = bits[2] >> 21 | bits[3] << 11 & 0xfffff - | exp + 0x3ff + 105 << 20; + L[_0] = (bits[2] >> 21) | (bits[3] << 11 & 0xfffff) + | ((exp + 0x3ff + 105) << 20); exp += 0x3ff + 52; if (bits[1] &= 0x1fffff) { i = hi0bits(bits[1]) - 11; @@ -60,7 +62,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) else exp -= i; if (i > 0) { - bits[1] = bits[1] << i | bits[0] >> 32-i; + bits[1] = bits[1] << i | bits[0] >> (32-i); bits[0] = bits[0] << i & (ULong)0xffffffffL; } } @@ -73,11 +75,11 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) else exp -= i; if (i < 32) { - bits[1] = bits[0] >> 32 - i; + bits[1] = bits[0] >> (32 - i); bits[0] = bits[0] << i & (ULong)0xffffffffL; } else { - bits[1] = bits[0] << i - 32; + bits[1] = bits[0] << (i - 32); bits[0] = 0; } } @@ -86,7 +88,7 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) break; } L[2+_1] = bits[0]; - L[2+_0] = bits[1] & 0xfffff | exp << 20; + L[2+_0] = (bits[1] & 0xfffff) | (exp << 20); break; case STRTOG_Denormal: @@ -105,10 +107,10 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) nearly_normal: i = hi0bits(bits[3]) - 11; /* i >= 12 */ j = 32 - i; - L[_0] = (bits[3] << i | bits[2] >> j) & 0xfffff - | 65 - i << 20; + L[_0] = ((bits[3] << i | bits[2] >> j) & 0xfffff) + | ((65 - i) << 20); L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & ((ULong)1L << j) - 1; + L[2+_0] = bits[1] & (((ULong)1L << j) - 1); L[2+_1] = bits[0]; break; @@ -117,34 +119,34 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) if (i < 0) { j = -i; i += 32; - L[_0] = bits[2] >> j & 0xfffff | (33 + j) << 20; + L[_0] = (bits[2] >> j & 0xfffff) | ((33 + j) << 20); L[_1] = (bits[2] << i | bits[1] >> j) & 0xffffffffL; - L[2+_0] = bits[1] & ((ULong)1L << j) - 1; + L[2+_0] = bits[1] & (((ULong)1L << j) - 1); L[2+_1] = bits[0]; break; } if (i == 0) { - L[_0] = bits[2] & 0xfffff | 33 << 20; + L[_0] = (bits[2] & 0xfffff) | (33 << 20); L[_1] = bits[1]; L[2+_0] = 0; L[2+_1] = bits[0]; break; } j = 32 - i; - L[_0] = (bits[2] << i | bits[1] >> j) & 0xfffff - | j + 1 << 20; + L[_0] = (((bits[2] << i) | (bits[1] >> j)) & 0xfffff) + | ((j + 1) << 20); L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; L[2+_0] = 0; - L[2+_1] = bits[0] & (1L << j) - 1; + L[2+_1] = bits[0] & ((1L << j) - 1); break; hardly_normal: j = 11 - hi0bits(bits[1]); i = 32 - j; - L[_0] = bits[1] >> j & 0xfffff | j + 1 << 20; + L[_0] = (bits[1] >> j & 0xfffff) | ((j + 1) << 20); L[_1] = (bits[1] << i | bits[0] >> j) & 0xffffffffL; L[2+_0] = 0; - L[2+_1] = bits[0] & ((ULong)1L << j) - 1; + L[2+_1] = bits[0] & (((ULong)1L << j) - 1); break; case STRTOG_Infinite: @@ -153,16 +155,17 @@ ULtodd(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = L[2] = d_QNAN0; - L[1] = L[3] = d_QNAN1; + L[_0] = L[_0+2] = NanDflt_d_D2A[1]; + L[_1] = L[_1+2] = NanDflt_d_D2A[0]; break; case STRTOG_NaNbits: - L[_1] = (bits[1] >> 21 | bits[2] << 11) & (ULong)0xffffffffL; - L[_0] = bits[2] >> 21 | bits[3] << 11 - | (ULong)0x7ff00000L; - L[2+_1] = bits[0]; - L[2+_0] = bits[1] | (ULong)0x7ff00000L; + L[_1] = (bits[1] >> 20 | bits[2] << 12) & (ULong)0xffffffffL; + L[_0] = bits[2] >> 20 | bits[3] << 12; + L[_0] |= (L[_1] | L[_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; + L[2+_1] = bits[0] & (ULong)0xffffffffL; + L[2+_0] = bits[1] & 0xfffffL; + L[2+_0] |= (L[2+_1] | L[2+_0]) ? (ULong)0x7ff00000L : (ULong)0x7ff80000L; } if (k & STRTOG_Neg) { L[_0] |= 0x80000000L; @@ -178,12 +181,11 @@ strtordd(CONST char *s, char **sp, int rounding, double *dd) #endif { #ifdef Sudden_Underflow - static CONST FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; + static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 }; #else - static CONST FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; + static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 }; #endif - CONST FPI *fpi; - FPI fpi1; + FPI *fpi, fpi1; ULong bits[4]; Long exp; int k; diff --git a/gdtoa/strtorf.c b/gdtoa/strtorf.c index 3892d68d6..99b4ab710 100644 --- a/gdtoa/strtorf.c +++ b/gdtoa/strtorf.c @@ -31,6 +31,8 @@ THIS SOFTWARE. #include "gdtoaimp.h" + extern ULong NanDflt_f_D2A[1]; + void #ifdef KR_headers ULtof(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -46,7 +48,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k) case STRTOG_Normal: case STRTOG_NaNbits: - L[0] = bits[0] & 0x7fffff | exp + 0x7f + 23 << 23; + L[0] = (bits[0] & 0x7fffff) | ((exp + 0x7f + 23) << 23); break; case STRTOG_Denormal: @@ -58,7 +60,7 @@ ULtof(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_NaN: - L[0] = f_QNAN; + L[0] = NanDflt_f_D2A[0]; } if (k & STRTOG_Neg) L[0] |= 0x80000000L; @@ -71,9 +73,8 @@ strtorf(s, sp, rounding, f) CONST char *s; char **sp; int rounding; float *f; strtorf(CONST char *s, char **sp, int rounding, float *f) #endif { - static CONST FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + FPI *fpi, fpi1; ULong bits[1]; Long exp; int k; diff --git a/gdtoa/strtorx.c b/gdtoa/strtorx.c index cc3c0700f..994ce8e63 100644 --- a/gdtoa/strtorx.c +++ b/gdtoa/strtorx.c @@ -51,6 +51,8 @@ THIS SOFTWARE. #define _4 0 #endif + extern UShort NanDflt_ldus_D2A[5]; + void #ifdef KR_headers ULtox(L, bits, exp, k) UShort *L; ULong *bits; Long exp; int k; @@ -80,15 +82,16 @@ ULtox(UShort *L, ULong *bits, Long exp, int k) case STRTOG_Infinite: L[_0] = 0x7fff; - L[_1] = L[_2] = L[_3] = L[_4] = 0; + L[_1] = 0x8000; + L[_2] = L[_3] = L[_4] = 0; break; case STRTOG_NaN: - L[0] = ldus_QNAN0; - L[1] = ldus_QNAN1; - L[2] = ldus_QNAN2; - L[3] = ldus_QNAN3; - L[4] = ldus_QNAN4; + L[_4] = NanDflt_ldus_D2A[0]; + L[_3] = NanDflt_ldus_D2A[1]; + L[_2] = NanDflt_ldus_D2A[2]; + L[_1] = NanDflt_ldus_D2A[3]; + L[_0] = NanDflt_ldus_D2A[4]; } if (k & STRTOG_Neg) L[_0] |= 0x8000; @@ -101,9 +104,8 @@ strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorx(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/strtorxL.c b/gdtoa/strtorxL.c index ffcafa907..bac4a0bb1 100644 --- a/gdtoa/strtorxL.c +++ b/gdtoa/strtorxL.c @@ -47,6 +47,8 @@ THIS SOFTWARE. #define _2 0 #endif + extern ULong NanDflt_xL_D2A[3]; + void #ifdef KR_headers ULtoxL(L, bits, exp, k) ULong *L; ULong *bits; Long exp; int k; @@ -69,14 +71,15 @@ ULtoxL(ULong *L, ULong *bits, Long exp, int k) break; case STRTOG_Infinite: - L[_0] = 0x7fff << 16; - L[_1] = L[_2] = 0; + L[_0] = 0x7fff0000; + L[_1] = 0x80000000; + L[_2] = 0; break; case STRTOG_NaN: - L[0] = ld_QNAN0; - L[1] = ld_QNAN1; - L[2] = ld_QNAN2; + L[_0] = NanDflt_xL_D2A[2]; + L[_1] = NanDflt_xL_D2A[1]; + L[_2] = NanDflt_xL_D2A[0]; } if (k & STRTOG_Neg) L[_0] |= 0x80000000L; @@ -89,9 +92,8 @@ strtorxL(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; strtorxL(CONST char *s, char **sp, int rounding, void *L) #endif { - static CONST FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; - CONST FPI *fpi; - FPI fpi1; + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; + FPI *fpi, fpi1; ULong bits[2]; Long exp; int k; diff --git a/gdtoa/ulp.c b/gdtoa/ulp.c index 27639d19e..17e9f862c 100644 --- a/gdtoa/ulp.c +++ b/gdtoa/ulp.c @@ -34,15 +34,14 @@ THIS SOFTWARE. double ulp #ifdef KR_headers - (x) double x; + (x) U *x; #else - (double _x) + (U *x) #endif { Long L; - U x, a; + U a; - dval(x) = _x; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; #ifndef Sudden_Underflow if (L > 0) { @@ -50,22 +49,22 @@ ulp #ifdef IBM L |= Exp_msk1 >> 4; #endif - word0(a) = L; - word1(a) = 0; + word0(&a) = L; + word1(&a) = 0; #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; + word0(&a) = 0x80000 >> L; + word1(&a) = 0; } else { - word0(a) = 0; + word0(&a) = 0; L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; + word1(&a) = L >= 31 ? 1 : 1 << (31 - L); } } #endif - return dval(a); + return dval(&a); } From b3f5de356f14e2026cc9e5738e8b58e22e7daa44 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sun, 5 Jan 2014 15:46:11 -0500 Subject: [PATCH 095/247] - Fixed: SBarInfo's gamemode command used to ignore unknowns (for cross compatibility). On top of restoring the old behavior, generate a warning for only the first ignored instance. --- src/g_shared/sbarinfo_commands.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index febf32b80..5a0718f18 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1639,10 +1639,20 @@ class CommandGameMode : public SBarInfoCommandFlowControl void Parse(FScanner &sc, bool fullScreenOffsets) { + static bool warnUnknown = true; do { sc.MustGetToken(TK_Identifier); - modes |= static_cast (1<= 0) + modes |= static_cast (1< Date: Sun, 5 Jan 2014 19:50:09 -0500 Subject: [PATCH 096/247] =?UTF-8?q?-=20Fixed:=20All=20clang=205.0=20warnin?= =?UTF-8?q?gs.=20-=20Renamed=20autostart/autozend=20since=20Xcode=E2=80=99?= =?UTF-8?q?s=20build=20process=20links=20in=20strictly=20alphabetical=20or?= =?UTF-8?q?der.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jpeg-6b/CMakeLists.txt | 2 +- src/CMakeLists.txt | 8 +++--- src/{autostart.cpp => __autostart.cpp} | 0 src/c_console.cpp | 2 -- src/files.cpp | 4 +-- src/fragglescript/t_fspic.cpp | 1 + src/g_shared/sbarinfo.cpp | 2 ++ src/menu/joystickmenu.cpp | 12 ++++----- src/menu/menu.h | 1 - src/menu/optionmenu.cpp | 5 ---- src/menu/optionmenuitems.h | 22 ++++++++--------- src/nodebuild.cpp | 4 --- src/oplsynth/music_opldumper_mididevice.cpp | 2 +- src/oplsynth/muslib.h | 2 +- src/oplsynth/opl.h | 1 - src/p_acs.cpp | 6 ++++- src/p_interaction.cpp | 2 -- src/p_sectors.cpp | 2 -- src/r_main.cpp | 4 --- src/r_plane.cpp | 2 +- src/sdl/crashcatcher.c | 2 +- src/sdl/i_system.cpp | 2 +- src/sdl/iwadpicker_cocoa.mm | 27 ++++++++++++--------- src/sound/i_musicinterns.h | 2 +- src/sound/music_mus_opl.cpp | 2 +- src/v_video.cpp | 2 +- src/v_video.h | 5 ++-- src/win32/fb_d3d9.cpp | 5 ---- src/win32/fb_ddraw.cpp | 5 ---- src/win32/win32iface.h | 2 -- src/{autozend.cpp => zzautozend.cpp} | 0 31 files changed, 57 insertions(+), 81 deletions(-) rename src/{autostart.cpp => __autostart.cpp} (100%) rename src/{autozend.cpp => zzautozend.cpp} (100%) diff --git a/jpeg-6b/CMakeLists.txt b/jpeg-6b/CMakeLists.txt index 21096465e..dd5055f9b 100644 --- a/jpeg-6b/CMakeLists.txt +++ b/jpeg-6b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required( VERSION 2.4 ) make_release_only() if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -fomit-frame-pointer" ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) add_library( jpeg diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2bf5a5a8c..4f27c70e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -412,7 +412,7 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE set( CMAKE_CXX_FLAGS_MINSIZEREL "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_MINSIZEREL}" ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" ) - set( CMAKE_CXX_FLAGS "-Wall -Wno-unused -Wextra -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) # Remove extra warnings when using the official DirectX headers. # Also, TDM-GCC 4.4.0 no longer accepts glibc-style printf formats as valid, @@ -748,7 +748,7 @@ set( NOT_COMPILED_SOURCE_FILES add_executable( zdoom WIN32 ${HEADER_FILES} ${NOT_COMPILED_SOURCE_FILES} - autostart.cpp + __autostart.cpp ${ASM_SOURCES} ${SYSTEM_SOURCES} ${X86_SOURCES} @@ -1052,7 +1052,7 @@ add_executable( zdoom WIN32 r_data/renderstyle.cpp r_data/r_interpolate.cpp r_data/r_translate.cpp - autozend.cpp + zzautozend.cpp ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) @@ -1160,7 +1160,7 @@ source_group("Render Data\\Textures" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h) source_group("Resource Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/resourcefiles/.+") source_group("SDL Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sdl/.+") -source_group("SFML" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") +source_group("SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+") source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_shared/.+") source_group("Versioning" FILES version.h win32/zdoom.rc) source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+") diff --git a/src/autostart.cpp b/src/__autostart.cpp similarity index 100% rename from src/autostart.cpp rename to src/__autostart.cpp diff --git a/src/c_console.cpp b/src/c_console.cpp index 0c02d0489..c25a460fe 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -610,8 +610,6 @@ static int FlushLines (const char *start, const char *stop) break; } } - if (i != TopLine) - i = i; return i; } diff --git a/src/files.cpp b/src/files.cpp index 80f0f8303..d7dfc2cbe 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -370,8 +370,8 @@ extern "C" void bz_internal_error (int errcode) // //========================================================================== -static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } -static void SzFree(void *p, void *address) { p = p; free(address); } +static void *SzAlloc(void *, size_t size) { return malloc(size); } +static void SzFree(void *, void *address) { free(address); } ISzAlloc g_Alloc = { SzAlloc, SzFree }; FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip) diff --git a/src/fragglescript/t_fspic.cpp b/src/fragglescript/t_fspic.cpp index d5e6e5aec..9da3cf15c 100644 --- a/src/fragglescript/t_fspic.cpp +++ b/src/fragglescript/t_fspic.cpp @@ -73,6 +73,7 @@ public: ~DHUDPicManager() {} void Serialize(FArchive & ar); virtual void DoDraw (int linenum, int x, int y, int hudheight, float translucent); + void DoDraw (int, int, int, bool, int) { assert(false); } } ; IMPLEMENT_CLASS(DHUDPicManager) diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 3e1c364e2..a738a5aad 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -303,6 +303,8 @@ class SBarInfoMainBlock : public SBarInfoCommandFlowControl int Alpha() const { return currentAlpha; } // Same as Draw but takes into account ForceScaled and temporarily sets the scaling if needed. void DrawAux(const SBarInfoMainBlock *block, DSBarInfo *statusBar, int xOffset, int yOffset, int alpha); + // Silence hidden overload warning since this is a special use class. + using SBarInfoCommandFlowControl::Draw; void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, int xOffset, int yOffset, int alpha) { this->xOffset = xOffset; diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 6be728865..a7d950ed5 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -74,12 +74,12 @@ public: { } - double GetValue() + double GetSliderValue() { return SELECTED_JOYSTICK->GetSensitivity(); } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetSensitivity(float(val)); } @@ -104,14 +104,14 @@ public: mNeg = 1; } - double GetValue() + double GetSliderValue() { double d = SELECTED_JOYSTICK->GetAxisScale(mAxis); mNeg = d < 0? -1:1; return d; } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg)); } @@ -136,14 +136,14 @@ public: mNeg = 1; } - double GetValue() + double GetSliderValue() { double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis); mNeg = d < 0? -1:1; return d; } - void SetValue(double val) + void SetSliderValue(double val) { SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg)); } diff --git a/src/menu/menu.h b/src/menu/menu.h index 1388a33bb..3712c9065 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -553,7 +553,6 @@ public: } ~FOptionMenuItem(); - virtual bool CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y); virtual int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected); virtual bool Selectable(); virtual int GetIndent(); diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index 08489fe23..eff53fc49 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -468,11 +468,6 @@ FOptionMenuItem::~FOptionMenuItem() if (mLabel != NULL) delete [] mLabel; } -bool FOptionMenuItem::CheckCoordinate(FOptionMenuDescriptor *desc, int x, int y) -{ - return false; -} - int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) { return indent; diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index ff3eb016a..439ed7ffc 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -560,8 +560,8 @@ public: mSliderShort = 0; } - virtual double GetValue() = 0; - virtual void SetValue(double val) = 0; + virtual double GetSliderValue() = 0; + virtual void SetSliderValue(double val) = 0; //============================================================================= // @@ -614,14 +614,14 @@ public: { drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); mDrawX = indent + CURSORSPACE; - DrawSlider (mDrawX, y, mMin, mMax, GetValue(), mShowValue, indent); + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); return indent; } //============================================================================= bool MenuEvent (int mkey, bool fromcontroller) { - double value = GetValue(); + double value = GetSliderValue(); if (mkey == MKEY_Left) { @@ -635,7 +635,7 @@ public: { return FOptionMenuItem::MenuEvent(mkey, fromcontroller); } - SetValue(clamp(value, mMin, mMax)); + SetSliderValue(clamp(value, mMin, mMax)); S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); return true; } @@ -662,9 +662,9 @@ public: x = clamp(x, slide_left, slide_right); double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left); - if (v != GetValue()) + if (v != GetSliderValue()) { - SetValue(v); + SetSliderValue(v); //S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE); } if (type == DMenu::MOUSE_Click) @@ -692,7 +692,7 @@ public: mCVar = FindCVar(menu, NULL); } - double GetValue() + double GetSliderValue() { if (mCVar != NULL) { @@ -704,7 +704,7 @@ public: } } - void SetValue(double val) + void SetSliderValue(double val) { if (mCVar != NULL) { @@ -732,12 +732,12 @@ public: mPVal = pVal; } - double GetValue() + double GetSliderValue() { return *mPVal; } - void SetValue(double val) + void SetSliderValue(double val) { *mPVal = (float)val; } diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index c13527d87..be5d0591d 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -504,10 +504,6 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int nosplitters = true; } } - else - { - pseg = pseg; - } } seg = pseg->next; diff --git a/src/oplsynth/music_opldumper_mididevice.cpp b/src/oplsynth/music_opldumper_mididevice.cpp index 0bb9ac14d..74bef0677 100644 --- a/src/oplsynth/music_opldumper_mididevice.cpp +++ b/src/oplsynth/music_opldumper_mididevice.cpp @@ -139,7 +139,7 @@ DiskWriterIO::~DiskWriterIO() // //========================================================================== -int DiskWriterIO::OPLinit(uint numchips, bool dontcare) +int DiskWriterIO::OPLinit(uint numchips, bool, bool) { // If the file extension is unknown or not present, the default format // is RAW. Otherwise, you can use DRO. diff --git a/src/oplsynth/muslib.h b/src/oplsynth/muslib.h index 404ce1e63..6cfb5bd55 100644 --- a/src/oplsynth/muslib.h +++ b/src/oplsynth/muslib.h @@ -195,7 +195,7 @@ struct DiskWriterIO : public OPLio DiskWriterIO(const char *filename); ~DiskWriterIO(); - int OPLinit(uint numchips, bool notused=false); + int OPLinit(uint numchips, bool notused=false, bool notused2=false); void OPLdeinit(); void OPLwriteReg(int which, uint reg, uchar data); void SetClockRate(double samples_per_tick); diff --git a/src/oplsynth/opl.h b/src/oplsynth/opl.h index eb46c9955..661258a26 100644 --- a/src/oplsynth/opl.h +++ b/src/oplsynth/opl.h @@ -15,7 +15,6 @@ public: virtual void WriteReg(int reg, int v) = 0; virtual void Update(float *buffer, int length) = 0; virtual void SetPanning(int c, float left, float right) = 0; - virtual FString GetVoiceString() { return FString(); } }; OPLEmul *YM3812Create(bool stereo); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index fa9e6d9c9..fd168f9ba 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6807,12 +6807,16 @@ scriptwait: break; case PCD_PRINTBINARY: -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6)))) || defined(__clang__) #define HAS_DIAGNOSTIC_PRAGMA #endif #ifdef HAS_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wformat-invalid-specifier" +#else #pragma GCC diagnostic ignored "-Wformat=" +#endif #pragma GCC diagnostic ignored "-Wformat-extra-args" #endif work.AppendFormat ("%B", STACK(1)); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 47ed87888..4be8ed627 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -364,8 +364,6 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { static int dieticks[MAXPLAYERS]; int pnum = int(this->player-players); - if (dieticks[pnum] == gametic) - gametic=gametic; dieticks[pnum] = gametic; fprintf (debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, this->player->cheats&CF_PREDICTING?"predicting":"real"); diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index d90466fec..699350839 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -230,8 +230,6 @@ fixed_t sector_t::FindNextLowestFloor (vertex_t **v) const check = lines[i]; if (NULL != (other = getNextSector (check, this))) { - if (other - sectors == 6) - other = other; ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); if (ofloor < floor && floor - ofloor < heightdiff && !IsLinked(other, false)) diff --git a/src/r_main.cpp b/src/r_main.cpp index edb13d326..a726bc714 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -706,10 +706,6 @@ void R_EnterMirror (drawseg_t *ds, int depth) R_EnterMirror (drawsegs + WallMirrors[mirrorsAtStart], depth + 1); } } - else - { - depth = depth; - } viewangle = startang; viewx = startx; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 986d99203..07bbbbe6a 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -560,7 +560,7 @@ static visplane_t *new_visplane (unsigned hash) { check = (visplane_t *)M_Malloc (sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); memset(check, 0, sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); - check->bottom = &check->top[MAXWIDTH+2]; + check->bottom = check->top + MAXWIDTH+2; } else if (NULL == (freetail = freetail->next)) { diff --git a/src/sdl/crashcatcher.c b/src/sdl/crashcatcher.c index 37511f63a..a4f68d9a3 100644 --- a/src/sdl/crashcatcher.c +++ b/src/sdl/crashcatcher.c @@ -192,7 +192,7 @@ static size_t safe_write(int fd, const void *buf, size_t len) static void crash_catcher(int signum, siginfo_t *siginfo, void *context) { - ucontext_t *ucontext = (ucontext_t*)context; + //ucontext_t *ucontext = (ucontext_t*)context; pid_t dbg_pid; int fd[2]; diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 03cbd74bf..6bd95d6e7 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -719,7 +719,7 @@ bool I_WriteIniFailed () static const char *pattern; -#if defined(__APPLE__) && !defined(__llvm__) +#if defined(__APPLE__) && !defined(__MAC_10_8) static int matchfile (struct dirent *ent) #else static int matchfile (const struct dirent *ent) diff --git a/src/sdl/iwadpicker_cocoa.mm b/src/sdl/iwadpicker_cocoa.mm index a0469ac7a..06f84098a 100644 --- a/src/sdl/iwadpicker_cocoa.mm +++ b/src/sdl/iwadpicker_cocoa.mm @@ -48,13 +48,16 @@ enum static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Class to convert the IWAD data into a form that Cocoa can use. -@interface IWADTableData : NSObject// +@interface IWADTableData : NSObject +#ifdef __MAC_10_6 + +#endif { NSMutableArray *data; } - (void)dealloc; -- (IWADTableData *)init:(WadStuff *) wads:(int) numwads; +- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads; - (int)numberOfRowsInTableView:(NSTableView *)aTableView; - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; @@ -69,7 +72,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [super dealloc]; } -- (IWADTableData *)init:(WadStuff *) wads:(int) numwads +- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads { data = [[NSMutableArray alloc] initWithCapacity:numwads]; @@ -116,13 +119,13 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; - (void)buttonPressed:(id) sender; - (void)doubleClicked:(id) sender; -- (void)makeLabel:(NSTextField *)label:(const char*) str; -- (int)pickIWad:(WadStuff *)wads:(int) numwads:(bool) showwin:(int) defaultiwad; +- (void)makeLabel:(NSTextField *)label withString:(const char*) str; +- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad; @end @implementation IWADPicker -- (void)buttonPressed:(id) sender; +- (void)buttonPressed:(id) sender { if(sender == cancelButton) cancelled = true; @@ -131,7 +134,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [app stopModal]; } -- (void)doubleClicked:(id) sender; +- (void)doubleClicked:(id) sender { if ([sender clickedRow] >= 0) { @@ -142,7 +145,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Apparently labels in Cocoa are uneditable text fields, so lets make this a // little more automated. -- (void)makeLabel:(NSTextField *)label:(const char*) str +- (void)makeLabel:(NSTextField *)label withString:(const char*) str { [label setStringValue:[NSString stringWithUTF8String:str]]; [label setBezeled:NO]; @@ -151,7 +154,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [label setSelectable:NO]; } -- (int)pickIWad:(WadStuff *)wads:(int) numwads:(bool) showwin:(int) defaultiwad +- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad { cancelled = false; @@ -163,7 +166,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; [window setTitle:windowTitle]; NSTextField *description = [[NSTextField alloc] initWithFrame:NSMakeRect(22, 379, 412, 50)]; - [self makeLabel:description:"ZDoom found more than one IWAD\nSelect from the list below to determine which one to use:"]; + [self makeLabel:description withString:"ZDoom found more than one IWAD\nSelect from the list below to determine which one to use:"]; [[window contentView] addSubview:description]; [description release]; @@ -171,7 +174,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; //NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 103, 412, 288)]; NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 50, 412, 341)]; NSTableView *iwadTable = [[NSTableView alloc] initWithFrame:[iwadScroller bounds]]; - IWADTableData *tableData = [[IWADTableData alloc] init:wads:numwads]; + IWADTableData *tableData = [[IWADTableData alloc] init:wads num:numwads]; for(int i = 0;i < NUM_COLUMNS;i++) { NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithUTF8String:tableHeaders[i]]]; @@ -242,7 +245,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad) { IWADPicker *picker = [IWADPicker alloc]; - int ret = [picker pickIWad:wads:numwads:showwin:defaultiwad]; + int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad]; [picker release]; return ret; } diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 3c1134c63..fa04cfa51 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -709,7 +709,7 @@ class OPLMUSDumper : public OPLMUSSong { public: OPLMUSDumper(const OPLMUSSong *original, const char *filename); - void Play(bool looping); + void Play(bool looping, int); }; // CD track/disk played through the multimedia system ----------------------- diff --git a/src/sound/music_mus_opl.cpp b/src/sound/music_mus_opl.cpp index 156094e1b..fb0d78df5 100644 --- a/src/sound/music_mus_opl.cpp +++ b/src/sound/music_mus_opl.cpp @@ -100,7 +100,7 @@ OPLMUSDumper::OPLMUSDumper(const OPLMUSSong *original, const char *filename) { } -void OPLMUSDumper::Play(bool looping) +void OPLMUSDumper::Play(bool looping, int) { Music->Dump(); } diff --git a/src/v_video.cpp b/src/v_video.cpp index 855b9fda3..fa94cd49f 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -795,7 +795,7 @@ bool DSimpleCanvas::IsValid () // //========================================================================== -bool DSimpleCanvas::Lock () +bool DSimpleCanvas::Lock (bool) { if (LockCount == 0) { diff --git a/src/v_video.h b/src/v_video.h index 09022d9ff..b0885f360 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -157,8 +157,7 @@ public: virtual bool IsValid (); // Access control - virtual bool Lock () = 0; // Returns true if the surface was lost since last time - virtual bool Lock (bool usesimplecanvas) { return Lock(); } + virtual bool Lock (bool buffered=true) = 0; // Returns true if the surface was lost since last time virtual void Unlock () = 0; virtual bool IsLocked () { return Buffer != NULL; } // Returns true if the surface is locked @@ -287,7 +286,7 @@ public: ~DSimpleCanvas (); bool IsValid (); - bool Lock (); + bool Lock (bool buffered=true); void Unlock (); protected: diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 648104271..ac8102cd2 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1033,11 +1033,6 @@ bool D3DFB::IsFullscreen () // //========================================================================== -bool D3DFB::Lock () -{ - return Lock(true); -} - bool D3DFB::Lock (bool buffered) { if (LockCount++ > 0) diff --git a/src/win32/fb_ddraw.cpp b/src/win32/fb_ddraw.cpp index 9fb65c2a7..71d37d564 100644 --- a/src/win32/fb_ddraw.cpp +++ b/src/win32/fb_ddraw.cpp @@ -815,11 +815,6 @@ HRESULT DDrawFB::GetHR () return LastHR; } -bool DDrawFB::Lock () -{ - return Lock (false); -} - bool DDrawFB::Lock (bool useSimpleCanvas) { static int lock_num; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 07151fb02..2704de0fa 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -148,7 +148,6 @@ public: ~DDrawFB (); bool IsValid (); - bool Lock (); bool Lock (bool buffer); void Unlock (); void ForceBuffering (bool force); @@ -231,7 +230,6 @@ public: ~D3DFB (); bool IsValid (); - bool Lock (); bool Lock (bool buffered); void Unlock (); void Update (); diff --git a/src/autozend.cpp b/src/zzautozend.cpp similarity index 100% rename from src/autozend.cpp rename to src/zzautozend.cpp From fa516c5ee6a1d13ee65484e309a8b3d8a492f1b5 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 7 Jan 2014 00:55:32 -0500 Subject: [PATCH 097/247] - For some reason __MAC_10_6 is defined in the 10.5 SDK so use MAC_OS_X_VERSION_MAX to check SDK version instead. --- src/sdl/i_system.cpp | 2 +- src/sdl/iwadpicker_cocoa.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 6bd95d6e7..465735103 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -719,7 +719,7 @@ bool I_WriteIniFailed () static const char *pattern; -#if defined(__APPLE__) && !defined(__MAC_10_8) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1080 static int matchfile (struct dirent *ent) #else static int matchfile (const struct dirent *ent) diff --git a/src/sdl/iwadpicker_cocoa.mm b/src/sdl/iwadpicker_cocoa.mm index 06f84098a..3b414d5e8 100644 --- a/src/sdl/iwadpicker_cocoa.mm +++ b/src/sdl/iwadpicker_cocoa.mm @@ -49,7 +49,7 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; // Class to convert the IWAD data into a form that Cocoa can use. @interface IWADTableData : NSObject -#ifdef __MAC_10_6 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 #endif { From 44c4736de3d49dd0c451504c5544d5692d30828a Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Fri, 10 Jan 2014 02:16:41 -0500 Subject: [PATCH 098/247] - Ignore unknown properties in the GAMEINFO lump instead of throwing an error. --- src/d_main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index f0e7e7676..86a9fad11 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1861,6 +1861,15 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char sc.MustGetString(); DoomStartupInfo.Song = sc.String; } + else + { + // Silently ignore unknown properties + do + { + sc.MustGetAnyToken(); + } + while(sc.CheckToken(',')); + } } return iwad; } From 6db974918a67fafd081954714b922e7b2e1d4d30 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 12 Jan 2014 18:39:19 +1300 Subject: [PATCH 099/247] Treat packets from unknown nodes differently Instead of trying to decompress packets from unknown connections (and failing them anyway), they are now reported and discarded without doing anything else. --- src/i_net.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i_net.cpp b/src/i_net.cpp index 2c01f407d..889688b48 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -293,7 +293,7 @@ void PacketGet (void) return; } } - else if (c > 0) + else if (node >= 0 && c > 0) { doomcom.data[0] = TransmitBuffer[0] & ~NCMD_COMPRESSED; if (TransmitBuffer[0] & NCMD_COMPRESSED) @@ -316,6 +316,12 @@ void PacketGet (void) memcpy(doomcom.data + 1, TransmitBuffer + 1, c - 1); } } + else if (c > 0) + { //The packet is not from any in-game node, so we might as well discard it. + Printf("Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + doomcom.remotenode = -1; + return; + } doomcom.remotenode = node; doomcom.datalength = (short)c; From 812f2d92300f5f49701dd602fab605f0979ee2ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Jan 2014 12:02:02 +0100 Subject: [PATCH 100/247] - removed all unneeded files from gdtoa/CMakeLists.txt because some compilers seem to throw duplicate symbol errors when strtod gets included. --- gdtoa/CMakeLists.txt | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 7a1304d0f..72a365bbf 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -41,45 +41,8 @@ add_library( gdtoa ${GEN_FP_FILES} dmisc.c dtoa.c - g_Qfmt.c - g__fmt.c - g_ddfmt.c - g_dfmt.c - g_ffmt.c - g_xLfmt.c - g_xfmt.c - gdtoa.c - gethex.c - gmisc.c - hd_init.c - hexnan.c misc.c - smisc.c - strtoIQ.c - strtoId.c - strtoIdd.c - strtoIf.c - strtoIg.c - strtoIx.c - strtoIxL.c - strtod.c - strtodI.c - strtodg.c - strtof.c - strtopQ.c - strtopd.c - strtopdd.c - strtopf.c - strtopx.c - strtopxL.c - strtorQ.c - strtord.c - strtordd.c - strtorf.c - strtorx.c - strtorxL.c - sum.c - ulp.c) + ) target_link_libraries( gdtoa ) if( GEN_FP_DEPS ) add_dependencies( gdtoa ${GEN_FP_DEPS} ) From 2501dc6df68e749094b4517a48c81f9a7b4fe1d2 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Mon, 13 Jan 2014 01:48:31 +0100 Subject: [PATCH 101/247] Fixed signed overflow issue, which caused a non-intended aggressive optimization by GCC 4.8. Also, negative values of the 'limit' parameter in both ACS UniqueTID() and in 'utid' CCMD are ignored and replaced by 0. --- src/p_acs.cpp | 2 +- src/p_mobj.cpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 582385c48..962b70049 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4933,7 +4933,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const break; case ACSF_UniqueTID: - return P_FindUniqueTID(argCount > 0 ? args[0] : 0, argCount > 1 ? args[1] : 0); + return P_FindUniqueTID(argCount > 0 ? args[0] : 0, (argCount > 1 && args[1] >= 0) ? args[1] : 0); case ACSF_IsTIDUsed: return P_IsTIDUsed(args[0]); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 03bbb4d8d..6602a11a5 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2722,12 +2722,16 @@ int P_FindUniqueTID(int start_tid, int limit) if (start_tid != 0) { // Do a linear search. - limit = start_tid + limit - 1; - if (limit < start_tid) - { // If it overflowed, clamp to INT_MAX - limit = INT_MAX; + int end_tid = start_tid; + if (start_tid > 0 && limit > INT_MAX - start_tid + 1) + { // If 'limit+start_tid-1' overflows, clamp 'end_tid' to INT_MAX + end_tid = INT_MAX; } - for (tid = start_tid; tid <= limit; ++tid) + else + { + end_tid += limit-1; + } + for (tid = start_tid; tid <= end_tid; ++tid) { if (tid != 0 && !P_IsTIDUsed(tid)) { @@ -2765,7 +2769,7 @@ CCMD(utid) { Printf("%d\n", P_FindUniqueTID(argv.argc() > 1 ? atoi(argv[1]) : 0, - argv.argc() > 2 ? atoi(argv[2]) : 0)); + (argv.argc() > 2 && atoi(argv[2]) >= 0) ? atoi(argv[2]) : 0)); } //========================================================================== From f51fcd90b3f08333fc9c2935cfedfc4c8026a7d9 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Fri, 17 Jan 2014 18:57:52 +0100 Subject: [PATCH 102/247] - Fixed scanf in IWAD picker without GTK If you try to kill the program with Ctrl-C, it would run the first IWAD available in the list instead of closing it. --- src/sdl/i_system.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index def35606a..b078e6507 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -684,8 +684,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) printf ("%d. %s (%s)\n", i+1, wads[i].Name.GetChars(), filepart); } printf ("Which one? "); - scanf ("%d", &i); - if (i > numwads) + if (scanf ("%d", &i) != 1 || i > numwads) return -1; return i-1; } From aafea851f0fa334efaaafe1271b15dbdb5330854 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Fri, 17 Jan 2014 19:11:29 +0100 Subject: [PATCH 103/247] - Remove clang check from GCC-related workaround It caused a clang warning/error regarding the non-existing flags '-fno-tree-dominator-opts' and '-fno-tree-fre'. --- src/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54a72aeae..f43a6a97c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -989,10 +989,11 @@ if( NOT WIN32 ) COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make ) endif( NOT WIN32 ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) # GCC misoptimizes this file set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" ) - +endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) # Need to enable intrinsics for this file. if( SSE_MATTERS ) set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" ) From 884928687dc12967bbb336ee27c09c5396c42896 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Fri, 17 Jan 2014 19:27:12 +0100 Subject: [PATCH 104/247] - Fixed overflow checking in some viewpitch code --- src/g_game.cpp | 4 ++-- src/r_utility.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 081ffdb53..4ba535a00 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -775,7 +775,7 @@ void G_AddViewPitch (int look) else if (look > 0) { // Avoid overflowing - if (LocalViewPitch + look <= LocalViewPitch) + if (LocalViewPitch > INT_MAX - look) { LocalViewPitch = 0x78000000; } @@ -787,7 +787,7 @@ void G_AddViewPitch (int look) else if (look < 0) { // Avoid overflowing - if (LocalViewPitch + look >= LocalViewPitch) + if (LocalViewPitch < INT_MIN - look) { LocalViewPitch = -0x78000000; } diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 0b51578ed..19ddaa972 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -602,7 +602,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi if (delta > 0) { // Avoid overflowing viewpitch (can happen when a netgame is stalled) - if (viewpitch + delta <= viewpitch) + if (viewpitch > INT_MAX - delta) { viewpitch = player->MaxPitch; } @@ -614,7 +614,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi else if (delta < 0) { // Avoid overflowing viewpitch (can happen when a netgame is stalled) - if (viewpitch + delta >= viewpitch) + if (viewpitch < INT_MIN - delta) { viewpitch = player->MinPitch; } From b329a34a583933394788bd464ffaddfb0375f169 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Fri, 17 Jan 2014 23:36:59 +0100 Subject: [PATCH 105/247] - Fixed some cmake --warn-uninitialized messages --- CMakeLists.txt | 5 +++++ src/CMakeLists.txt | 25 +++++++++++++++++++++++++ tools/updaterevision/CMakeLists.txt | 2 ++ 3 files changed, 32 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0858ecab5..c30fd1b58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,11 @@ if( MSVC ) string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} ) string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) +else( MSVC ) + set( REL_LINKER_FLAGS "" ) + set( ALL_C_FLAGS "" ) + set( REL_C_FLAGS "" ) + set( DEB_C_FLAGS "" ) endif( MSVC ) set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54a72aeae..b83b6dae6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,6 +50,20 @@ set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41" "15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03" "02" "01" "00" ) set( MAJOR_VERSIONS "44" "34" "28" "26" "24" "22" "20" ) + +if( NOT FMOD_DIR_VERSIONS ) + set( FMOD_DIR_VERSIONS "" ) +endif( NOT FMOD_DIR_VERSIONS ) +if( NOT FMOD_VERSIONS ) + set( FMOD_VERSIONS "" ) +endif( NOT FMOD_VERSIONS ) +if( NOT FMOD_LOCAL_INC_DIRS ) + set( FMOD_LOCAL_INC_DIRS "" ) +endif( NOT FMOD_LOCAL_INC_DIRS ) +if( NOT FMOD_LOCAL_LIB_DIRS ) + set( FMOD_LOCAL_LIB_DIRS "" ) +endif( NOT FMOD_LOCAL_LIB_DIRS ) + set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" ) foreach( majver ${MAJOR_VERSIONS} ) foreach( minver ${MINOR_VERSIONS} ) @@ -62,6 +76,10 @@ foreach( majver ${MAJOR_VERSIONS} ) endforeach( dir ${FMOD_DIR_VERSIONS} ) endforeach( majver ${MAJOR_VERSIONS} ) +if( NOT ZDOOM_LIBS ) + set( ZDOOM_LIBS "" ) +endif( NOT ZDOOM_LIBS ) + if( WIN32 ) if( X64 ) set( WIN_TYPE Win64 ) @@ -346,12 +364,16 @@ if( NOT NO_ASM ) endif( UNIX ) if( WIN32 ) set( FIXRTEXT fixrtext ) + else( WIN32 ) + set( FIXRTEXT "" ) endif( WIN32 ) message( STATUS "Selected assembler: ${ASSEMBLER}" ) MACRO( ADD_ASM_FILE indir infile ) set( ASM_OUTPUT_${infile} "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir}/${infile}${ASM_OUTPUT_EXTENSION}" ) if( WIN32 ) set( FIXRTEXT_${infile} COMMAND ${FIXRTEXT} "${ASM_OUTPUT_${infile}}" ) + else( WIN32 ) + set( FIXRTEXT_${infile} COMMAND "" ) endif( WIN32 ) add_custom_command( OUTPUT ${ASM_OUTPUT_${infile}} COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir} @@ -567,6 +589,9 @@ endif( WIN32 ) if( NO_ASM ) add_definitions( -DNOASM ) else( NO_ASM ) + if( NOT ASM_SOURCES ) + set( ASM_SOURCES "" ) + endif( NOT ASM_SOURCES ) if( X64 ) ADD_ASM_FILE( asm_x86_64 tmap3 ) else( X64 ) diff --git a/tools/updaterevision/CMakeLists.txt b/tools/updaterevision/CMakeLists.txt index d985b9e3f..be6167f94 100644 --- a/tools/updaterevision/CMakeLists.txt +++ b/tools/updaterevision/CMakeLists.txt @@ -15,6 +15,8 @@ if( WIN32 ) set( TRUSTINFO trustinfo.rc ) endif( MSVC_VERSION GREATER 1399 ) endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) +else( WIN32 ) + set( TRUSTINFO "" ) endif( WIN32 ) add_executable( updaterevision updaterevision.c ${TRUSTINFO} ) From 70717cd2fab2183ce27e7eedfc03e77806d76d24 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sat, 18 Jan 2014 02:21:49 +0100 Subject: [PATCH 106/247] - Cover the ASM_SOURCES fix for NO_ASM users too --- src/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b83b6dae6..badd2c3b1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -586,12 +586,13 @@ else( WIN32 ) endif( APPLE ) endif( WIN32 ) +if( NOT ASM_SOURCES ) + set( ASM_SOURCES "" ) +endif( NOT ASM_SOURCES ) + if( NO_ASM ) add_definitions( -DNOASM ) else( NO_ASM ) - if( NOT ASM_SOURCES ) - set( ASM_SOURCES "" ) - endif( NOT ASM_SOURCES ) if( X64 ) ADD_ASM_FILE( asm_x86_64 tmap3 ) else( X64 ) From 6f7885210ba804d6f2ad6f5e8c03467ad983fc82 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Tue, 26 Nov 2013 17:58:55 -0500 Subject: [PATCH 107/247] - Fixed: Some setups require the dynamic linking library to be linked explicitly, so specify it when using DYN_FLUIDSYNTH --- src/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54a72aeae..4ced0062f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -506,12 +506,14 @@ message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${FMOD_LIBRARY}" ) include_directories( "${ZLIB_INCLUDE_DIR}" "${FMOD_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" ) -if( FLUIDSYNTH_FOUND ) - if( NOT DYN_FLUIDSYNTH) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) - include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) - endif( NOT DYN_FLUIDSYNTH ) -endif( FLUIDSYNTH_FOUND ) +if( NOT DYN_FLUIDSYNTH) + if( FLUIDSYNTH_FOUND ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) + include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) + endif( FLUIDSYNTH_FOUND ) +else( NOT DYN_FLUIDSYNTH ) + set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} ) +endif( NOT DYN_FLUIDSYNTH ) # Start defining source files for ZDoom From e5d7077d743073c5780087ee1d0b3082674f5f5d Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 15:09:12 -0500 Subject: [PATCH 108/247] - Fixed: Shareware games couldn't bother with the actor has no frames errors since we don't load mods. - Fixed: Heretic shareware used a different border for the statusbar. --- src/p_mobj.cpp | 6 ++++++ wadsrc/static/mapinfo/hereticsw.txt | 1 + 2 files changed, 7 insertions(+) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 03bbb4d8d..37110e388 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4639,6 +4639,12 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) if (defaults->SpawnState == NULL || sprites[defaults->SpawnState->sprite].numframes == 0) { + // We don't load mods for shareware games so we'll just ignore + // missing actors. Heretic needs this since the shareware includes + // the retail weapons in Deathmatch. + if (gameinfo.flags & GI_SHAREWARE) + return NULL; + Printf ("%s at (%i, %i) has no frames\n", i->TypeName.GetChars(), mthing->x>>FRACBITS, mthing->y>>FRACBITS); i = PClass::FindClass("Unknown"); diff --git a/wadsrc/static/mapinfo/hereticsw.txt b/wadsrc/static/mapinfo/hereticsw.txt index 89b6c0762..5a37ccbef 100644 --- a/wadsrc/static/mapinfo/hereticsw.txt +++ b/wadsrc/static/mapinfo/hereticsw.txt @@ -4,5 +4,6 @@ gameinfo { finalepage = "ORDER" infopage = "ORDER", "HELP1", "HELP2", "CREDIT" + borderflat = "FLOOR04" } From 7af8b78b9fa5ec066cc6ed7a01d041850e36b07f Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 15:18:35 -0500 Subject: [PATCH 109/247] - Applied Chilly's patch to fix excessive name change notifications. --- src/d_netinfo.cpp | 2 +- src/menu/playermenu.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 12fb187ae..d2dbc862d 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -861,7 +861,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) val.String = CleanseString(value.LockBuffer()); (*cvar_ptr)->SetGenericRep(val, CVAR_String); value.UnlockBuffer(); - if (keyname == NAME_Name && update && oldname != value) + if (keyname == NAME_Name && update && oldname.Compare (value)) { Printf("%s is now known as %s\n", oldname.GetChars(), value.GetChars()); } diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 641b0699f..58b08fc38 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -996,7 +996,10 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller) // item specific handling comes here case NAME_Playerbox: - PlayerNameChanged(li); + if (mkey == MKEY_Input) + { + PlayerNameChanged(li); + } break; case NAME_Team: From ebcd0e9c49fc7eb4b284e623244fffb5417c638b Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 15:40:48 -0500 Subject: [PATCH 110/247] - Removed redundant expression in R_FindPlane. --- src/r_plane.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 986d99203..be650bf91 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -607,8 +607,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl // same visplane, then only the floor sky will be drawn. plane.c = height.c; plane.ic = height.ic; - isskybox = skybox != NULL && !skybox->bInSkybox && - (skybox->bAlways || picnum == skyflatnum); + isskybox = skybox != NULL && !skybox->bInSkybox; } else if (skybox != NULL && skybox->bAlways && !skybox->bInSkybox) { From 919b9283005a7431cc8c78aabaa1fe0181f6f275 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 15:45:11 -0500 Subject: [PATCH 111/247] - Fixed: Taking an item in a Strife dialog didn't account for items that have the keep depleted flag set. --- src/p_conversation.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 6493bca36..09f2d49d6 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -655,7 +655,14 @@ static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount item->Amount -= amount; if (item->Amount <= 0) { - item->Destroy (); + if (item->ItemFlags & IF_KEEPDEPLETED) + { + item->Amount = 0; + } + else + { + item->Destroy (); + } } } } From 75fd674d31c53aa68a2e84ad74c0b2310069d084 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 16:20:52 -0500 Subject: [PATCH 112/247] - If the player doesn't have ` bound to open the console, don't close it with that key. --- src/c_console.cpp | 7 +++++++ src/doomdef.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/c_console.cpp b/src/c_console.cpp index e5d3d97ab..e20229605 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -41,6 +41,7 @@ #include "version.h" #include "g_game.h" +#include "c_bind.h" #include "c_console.h" #include "c_cvars.h" #include "c_dispatch.h" @@ -1698,6 +1699,12 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) break; case '`': + // Check to see if we have ` bound to the console before accepting + // it as a way to close the console. + if (Bindings.GetBinding(KEY_GRAVE).CompareNoCase("toggleconsole")) + { + break; + } case GK_ESCAPE: // Close console and clear command line. But if we're in the // fullscreen console mode, there's nothing to fall back on diff --git a/src/doomdef.h b/src/doomdef.h index 675923b4a..e08c3044d 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -130,6 +130,7 @@ enum ESkillLevels #define KEY_F10 0x44 // DIK_F10 #define KEY_F11 0x57 // DIK_F11 #define KEY_F12 0x58 // DIK_F12 +#define KEY_GRAVE 0x29 // DIK_GRAVE #define KEY_BACKSPACE 0x0e // DIK_BACK From 811a75ebf659fc81969126b8bd1ece82a3e23371 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 18 Jan 2014 17:54:46 -0500 Subject: [PATCH 113/247] - Minor adjustments to SDL joystick code so that all axes have at least a small deadzone so that button mapping works properly. --- src/sdl/i_joystick.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sdl/i_joystick.cpp b/src/sdl/i_joystick.cpp index 48ae0e385..7a529861f 100644 --- a/src/sdl/i_joystick.cpp +++ b/src/sdl/i_joystick.cpp @@ -1,8 +1,12 @@ #include #include "doomdef.h" +#include "templates.h" #include "m_joy.h" +// Very small deadzone so that floating point magic doesn't happen +#define MIN_DEADZONE 0.000001f + class SDLInputJoystick: public IJoystickConfig { public: @@ -65,7 +69,7 @@ public: void SetAxisDeadZone(int axis, float zone) { - Axes[axis].DeadZone = zone; + Axes[axis].DeadZone = clamp(zone, MIN_DEADZONE, 1.f); } void SetAxisMap(int axis, EJoyAxis gameaxis) { @@ -83,7 +87,7 @@ public: } bool IsAxisDeadZoneDefault(int axis) { - return Axes[axis].DeadZone == 0.0f; + return Axes[axis].DeadZone <= MIN_DEADZONE; } bool IsAxisMapDefault(int axis) { @@ -105,7 +109,7 @@ public: info.Name.Format("Axis %d", i+1); else info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); - info.DeadZone = 0.0f; + info.DeadZone = MIN_DEADZONE; info.Multiplier = 1.0f; info.Value = 0.0; info.ButtonValue = 0; @@ -141,7 +145,7 @@ public: { buttonstate = 0; - Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32768.0; + Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); // Map button to axis From 0442c51d54d351ef0f497191be91c7410cc96e2c Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 21 Jan 2014 19:41:29 -0600 Subject: [PATCH 114/247] Fix building with old VC++ 2005 projects. - Also needed to comment out strtod declarations in gdtoaimp.h and gdtoa.h --- gdtoa/gdtoa.h | 4 +- gdtoa/gdtoa.vcproj | 1216 ++++++++++++++++++++++++++++++++++++++++++++ gdtoa/gdtoaimp.h | 2 +- zdoom.vcproj | 24 +- 4 files changed, 1231 insertions(+), 15 deletions(-) diff --git a/gdtoa/gdtoa.h b/gdtoa/gdtoa.h index 49c637beb..8b7390a28 100644 --- a/gdtoa/gdtoa.h +++ b/gdtoa/gdtoa.h @@ -142,8 +142,8 @@ extern char* dtoa ANSI((double d, int mode, int ndigits, int *decpt, extern char* gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, int *decpt, char **rve)); extern void freedtoa ANSI((char*)); -extern float strtof ANSI((CONST char *, char **)); -extern double strtod ANSI((CONST char *, char **)); +//extern float strtof ANSI((CONST char *, char **)); +//extern double strtod ANSI((CONST char *, char **)); extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); extern char* g_ddfmt ANSI((char*, double*, int, size_t)); diff --git a/gdtoa/gdtoa.vcproj b/gdtoa/gdtoa.vcproj index 7195c1457..3ac6ce39d 100644 --- a/gdtoa/gdtoa.vcproj +++ b/gdtoa/gdtoa.vcproj @@ -293,50 +293,434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -482,14 +486,6 @@ RelativePath=".\src\am_map.cpp" > - - - - @@ -1094,6 +1090,10 @@ RelativePath=".\src\zstring.cpp" > + + Date: Tue, 21 Jan 2014 19:48:46 -0600 Subject: [PATCH 115/247] Add more stuff to .gitignore --- .gitignore | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index e27cd5a59..cfa4882e6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ /release_gcc /dumb/vc6/dumb_static/release /dumb/vc6/dumb_static/debug +/dumb/vc6/dumb_static/x64 /DOOMSTATS.TXT /src/gitinfo.h /src/sc_man_scanner.h @@ -25,5 +26,14 @@ /tools/*/*.exe /tools/lemon/build /tools/re2c/build +/tools/updaterevision/x64/ +/tools/zipdir/x64 /wadsrc/*.pk3 /build_vc2013 +/bzip2/x64/ +/disasm.txt +/game-music-emu/x64/ +/gdtoa/x64/ +/jpeg-6b/x64/ +/lzma/x64/ +/zlib/x64/ From 4e53df8bca5e0dad98c6bdac9b1b5d9acf479d1d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 26 Jan 2014 14:32:44 +0100 Subject: [PATCH 116/247] - fixed: The 'load' command in GAMEINFO only worked if the filename contained a slash. --- src/d_main.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 5dd186cd0..6c938ef53 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1807,19 +1807,23 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char // Try looking for the wad in the same directory as the .wad // before looking for it in the current directory. + FString checkpath; if (lastSlash != NULL) { - FString checkpath(fn, (lastSlash - fn) + 1); + checkpath = FString(fn, (lastSlash - fn) + 1); checkpath += sc.String; - - if (!FileExists (checkpath)) - { - pos += D_AddFile(pwads, sc.String, true, pos); - } - else - { - pos += D_AddFile(pwads, checkpath, true, pos); - } + } + else + { + checkpath = sc.String; + } + if (!FileExists(checkpath)) + { + pos += D_AddFile(pwads, sc.String, true, pos); + } + else + { + pos += D_AddFile(pwads, checkpath, true, pos); } } while (sc.CheckToken(',')); From 8b02bb55aa3561eeb06bf4cc6320b609f7af26b4 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 30 Jan 2014 20:30:40 -0600 Subject: [PATCH 117/247] Fix compiling with FMOD 4.36 - That stuff I thought that went poof in FMOD Ex 4.37 was apparently already gone in 4.36. --- src/sound/fmodsound.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 4bdc43081..18f4cbb8f 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -63,7 +63,7 @@ extern HWND Window; #include "cmdlib.h" #include "s_sound.h" -#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43800 +#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43600 #error You are trying to compile with an unsupported version of FMOD. #endif @@ -858,7 +858,7 @@ bool FMODSoundRenderer::Init() result = Sys->setDriver(driver); } result = Sys->getDriver(&driver); -#if FMOD_VERSION >= 0x43700 +#if FMOD_VERSION >= 0x43600 // We were built with an FMOD that only returns the control panel frequency result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &speakermode); Driver_MaxFrequency = Driver_MinFrequency; @@ -1043,7 +1043,7 @@ bool FMODSoundRenderer::Init() } // Create DSP units for underwater effect -#if FMOD_VERSION < 0x43701 +#if FMOD_VERSION < 0x43600 result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP); if (result != FMOD_OK) { @@ -1106,7 +1106,7 @@ bool FMODSoundRenderer::Init() WaterLP->setActive(false); WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp); WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2); -#if FMOD_VERSION < 0x43701 +#if FMOD_VERSION < 0x43600 if (WaterReverb != NULL) { FMOD::DSPConnection *dry; From 3cff307e7756aae6e0f8c255f5a8a6eaf28270ec Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 4 Feb 2014 19:36:29 -0600 Subject: [PATCH 118/247] Add Get/SetLineActivation ACS functions --- src/p_acs.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 26b62be70..1ed89f783 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4251,6 +4251,8 @@ enum EACSFunctions ACSF_CheckFont, ACSF_DropItem, ACSF_CheckFlag, + ACSF_SetLineActivation, + ACSF_GetLineActivation, // ZDaemon ACSF_GetTeamScore = 19620, // (int team) @@ -5296,6 +5298,26 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) break; } + case ACSF_SetLineActivation: + if (argCount >= 2) + { + int line = -1; + + while ((line = P_FindLineFromID(args[0], line)) >= 0) + { + lines[line].activation = args[1]; + } + } + break; + + case ACSF_GetLineActivation: + if (argCount > 0) + { + int line = P_FindLineFromID(args[0], -1); + return line >= 0 ? lines[line].activation : 0; + } + break; + default: break; } From 0db82f02cfb7bdd555a2a45d605bb7af600163a0 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Wed, 12 Feb 2014 20:30:37 +1300 Subject: [PATCH 119/247] P_HitWater ignore extra floors below real floor P_HitWater incorrectly assumed extra floors were always above the real floor. --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d97a091ea..7dc8a3f46 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5169,7 +5169,7 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z } } planez = rover->bottom.plane->ZatPoint(x, y); - if (planez < z) return false; + if (planez < z && !(planez < thing->floorz)) return false; } #endif hsec = sec->GetHeightSec(); From dd5f2731282a27f811f1c8a5989028dd7922d52b Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae Date: Fri, 14 Feb 2014 05:10:48 +0400 Subject: [PATCH 120/247] Added possibly missing brackets --- src/g_strife/a_entityboss.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 58a88121e..fafb3b862 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -91,7 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) fixed_t SpawnX = spot->x; fixed_t SpawnY = spot->y; - fixed_t SpawnZ = spot->z + self->tracer? 70*FRACUNIT : 0; + fixed_t SpawnZ = spot->z + (self->tracer? 70*FRACUNIT : 0); an = self->angle >> ANGLETOFINESHIFT; second = Spawn("EntitySecond", SpawnX + FixedMul (secondRadius, finecosine[an]), From 02cd6eebf443579bd9ade2e1396400ab49bd398d Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Sun, 16 Feb 2014 18:29:01 +0100 Subject: [PATCH 121/247] A_Log formatted text Make DECORATE version of Log consistent with ACS version. --- src/thingdef/thingdef_codeptr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d48b18a2a..f2c738fb9 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2205,7 +2205,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) ACTION_PARAM_STRING(text, 0); if (text[0] == '$') text = GStrings(text+1); - Printf("%s\n", text); + FString formatted = strbin1(text); + Printf("%s\n", formatted.GetChars()); ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! } From d7478bcd683d609404ae664342de6e6b7ed94ac2 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 18 Feb 2014 00:40:14 +0100 Subject: [PATCH 122/247] New Freedoom names - Added freedoom2.wad as valid alias name (freedoom1.wad already existed). - Renamed titles to Freedoom: Phase 1 and Freedoom: Phase 2. - Reordered to put Phase 1 above Phase 2 in the IWAD picker. --- wadsrc/static/iwadinfo.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index e47951d31..a2f8ef6c0 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -189,7 +189,7 @@ IWad IWad { - Name = "Freedoom" + Name = "Freedoom: Phase 2" Autoname = "Freedoom" Game = "Doom" Config = "Doom" @@ -200,7 +200,7 @@ IWad IWad { - Name = "Ultimate Freedoom" + Name = "Freedoom: Phase 1" Autoname = "Freedoom1" Game = "Doom" Config = "Doom" @@ -348,9 +348,10 @@ Names "strife1.wad" "strife0.wad" "strife.wad" - "freedoom.wad" "freedoom1.wad" + "freedoom2.wad" "freedoomu.wad" + "freedoom.wad" "freedm.wad" "blasphem.wad" "blasphemer.wad" From 5c23ffb7bc2b6f2c56dcb23a0caf19d3eb7c6f65 Mon Sep 17 00:00:00 2001 From: Alex Qyoun-ae Date: Fri, 14 Feb 2014 05:10:48 +0400 Subject: [PATCH 123/247] Added possibly missing brackets --- src/g_strife/a_entityboss.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp index 58a88121e..fafb3b862 100644 --- a/src/g_strife/a_entityboss.cpp +++ b/src/g_strife/a_entityboss.cpp @@ -91,7 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath) fixed_t SpawnX = spot->x; fixed_t SpawnY = spot->y; - fixed_t SpawnZ = spot->z + self->tracer? 70*FRACUNIT : 0; + fixed_t SpawnZ = spot->z + (self->tracer? 70*FRACUNIT : 0); an = self->angle >> ANGLETOFINESHIFT; second = Spawn("EntitySecond", SpawnX + FixedMul (secondRadius, finecosine[an]), From 18f2644162734b98b1aa83798eef9940deab32b8 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Sun, 16 Feb 2014 18:29:01 +0100 Subject: [PATCH 124/247] A_Log formatted text Make DECORATE version of Log consistent with ACS version. --- src/thingdef/thingdef_codeptr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d48b18a2a..f2c738fb9 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2205,7 +2205,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log) ACTION_PARAM_STRING(text, 0); if (text[0] == '$') text = GStrings(text+1); - Printf("%s\n", text); + FString formatted = strbin1(text); + Printf("%s\n", formatted.GetChars()); ACTION_SET_RESULT(false); // Prints should never set the result for inventory state chains! } From 5c2620986ea67646a45bf1f0cc7f5e8fee0aa251 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 18 Feb 2014 00:40:14 +0100 Subject: [PATCH 125/247] New Freedoom names - Added freedoom2.wad as valid alias name (freedoom1.wad already existed). - Renamed titles to Freedoom: Phase 1 and Freedoom: Phase 2. - Reordered to put Phase 1 above Phase 2 in the IWAD picker. --- wadsrc/static/iwadinfo.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index e47951d31..a2f8ef6c0 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -189,7 +189,7 @@ IWad IWad { - Name = "Freedoom" + Name = "Freedoom: Phase 2" Autoname = "Freedoom" Game = "Doom" Config = "Doom" @@ -200,7 +200,7 @@ IWad IWad { - Name = "Ultimate Freedoom" + Name = "Freedoom: Phase 1" Autoname = "Freedoom1" Game = "Doom" Config = "Doom" @@ -348,9 +348,10 @@ Names "strife1.wad" "strife0.wad" "strife.wad" - "freedoom.wad" "freedoom1.wad" + "freedoom2.wad" "freedoomu.wad" + "freedoom.wad" "freedm.wad" "blasphem.wad" "blasphemer.wad" From 732ee11da1a539fdf68074c2e748d84873728a83 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Sun, 23 Feb 2014 23:07:10 +0100 Subject: [PATCH 126/247] Some DOSBox Raw OPL v2 indices were off by one. This caused access violation errors on perfectly fine DRO files. For reference, scoredata[20] is the hardware type (OPL2, dual OPL2, or OPL3). --- src/oplsynth/opl_mus_player.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 335e6d66e..43a129b14 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -104,16 +104,19 @@ fail: delete[] scoredata; } else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0)) { - if (scoredata[20] != 0) - { - Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); - goto fail; - } + bool okay = true; if (scoredata[21] != 0) { - Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); - goto fail; + Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); + okay = false; } + if (scoredata[22] != 0) + { + Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); + okay = false; + } + if (!okay) + goto fail; RawPlayer = DosBox2; SamplesPerTick = OPL_SAMPLE_RATE / 1000; int headersize = 0x1A + scoredata[0x19]; From 9dacc9cc8d466e53d3f946dffc1e3601d1cac120 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Mon, 24 Feb 2014 05:07:37 +0100 Subject: [PATCH 127/247] The wrong value was used here. This caused crashes on some files (notably MBELLS from Cosmo and NUBC from Body Count) in my port of this code to SLADE 3. --- src/oplsynth/opl_mus_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 43a129b14..319eb8319 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -267,7 +267,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes) { for (i = 0; i < io->NumChips; ++i) { - io->chips[i]->Update(samples1, samplesleft); + io->chips[i]->Update(samples1, numsamples); } OffsetSamples(samples1, numsamples << stereoshift); } From c7301a0fbbb738b84f4281308bdb06380ab256b8 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Sun, 23 Feb 2014 23:07:10 +0100 Subject: [PATCH 128/247] Some DOSBox Raw OPL v2 indices were off by one. This caused access violation errors on perfectly fine DRO files. For reference, scoredata[20] is the hardware type (OPL2, dual OPL2, or OPL3). --- src/oplsynth/opl_mus_player.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 335e6d66e..43a129b14 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -104,16 +104,19 @@ fail: delete[] scoredata; } else if (((DWORD *)scoredata)[2] == MAKE_ID(2,0,0,0)) { - if (scoredata[20] != 0) - { - Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); - goto fail; - } + bool okay = true; if (scoredata[21] != 0) { - Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); - goto fail; + Printf("Unsupported DOSBox Raw OPL format %d\n", scoredata[20]); + okay = false; } + if (scoredata[22] != 0) + { + Printf("Unsupported DOSBox Raw OPL compression %d\n", scoredata[21]); + okay = false; + } + if (!okay) + goto fail; RawPlayer = DosBox2; SamplesPerTick = OPL_SAMPLE_RATE / 1000; int headersize = 0x1A + scoredata[0x19]; From d430c18574fd6d72c751f869c4b3cd3312990b46 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Mon, 24 Feb 2014 05:07:37 +0100 Subject: [PATCH 129/247] The wrong value was used here. This caused crashes on some files (notably MBELLS from Cosmo and NUBC from Body Count) in my port of this code to SLADE 3. --- src/oplsynth/opl_mus_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 43a129b14..319eb8319 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -267,7 +267,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes) { for (i = 0; i < io->NumChips; ++i) { - io->chips[i]->Update(samples1, samplesleft); + io->chips[i]->Update(samples1, numsamples); } OffsetSamples(samples1, numsamples << stereoshift); } From 0f7ad00d9a0ab45b75840f98df059712b48ac394 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 15:48:41 -0600 Subject: [PATCH 130/247] Ignore the minor version number when checking for DRO v1 files - There exist files where the first word of the version number for DRO v1 files is not 0 but something else completely. (Maybe it's not actually a version number?) Assume they are valid v1 files as long as the second word is a 1. --- src/oplsynth/opl_mus_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oplsynth/opl_mus_player.cpp b/src/oplsynth/opl_mus_player.cpp index 319eb8319..a528c10e2 100644 --- a/src/oplsynth/opl_mus_player.cpp +++ b/src/oplsynth/opl_mus_player.cpp @@ -96,7 +96,7 @@ fail: delete[] scoredata; else if (((DWORD *)scoredata)[0] == MAKE_ID('D','B','R','A') && ((DWORD *)scoredata)[1] == MAKE_ID('W','O','P','L')) { - if (((DWORD *)scoredata)[2] == MAKE_ID(0,0,1,0)) + if (LittleShort(((WORD *)scoredata)[5]) == 1) { RawPlayer = DosBox1; SamplesPerTick = OPL_SAMPLE_RATE / 1000; From 7052d4e14e31328b5f14803b3aca20860f9a7e45 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 16:18:10 -0600 Subject: [PATCH 131/247] Fixed: userinfo_t::SkinChanged() was unaware of player classes --- src/d_netinfo.cpp | 10 +++++----- src/d_player.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index d2dbc862d..41ad683fe 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -387,7 +387,7 @@ void D_SetupUserInfo () { // Some cvars don't copy their original value directly. case NAME_Team: coninfo->TeamChanged(team); break; - case NAME_Skin: coninfo->SkinChanged(skin); break; + case NAME_Skin: coninfo->SkinChanged(skin, players[consoleplayer].CurrentPlayerClass); break; case NAME_Gender: coninfo->GenderChanged(gender); break; case NAME_PlayerClass: coninfo->PlayerClassChanged(playerclass); break; // The rest do. @@ -447,9 +447,9 @@ int userinfo_t::TeamChanged(int team) return team; } -int userinfo_t::SkinChanged(const char *skinname) +int userinfo_t::SkinChanged(const char *skinname, int playerclass) { - int skinnum = R_FindSkin(skinname, 0); + int skinnum = R_FindSkin(skinname, playerclass); *static_cast((*this)[NAME_Skin]) = skinnum; return skinnum; } @@ -821,7 +821,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) break; case NAME_Skin: - info->SkinChanged(value); + info->SkinChanged(value, players[pnum].CurrentPlayerClass); if (players[pnum].mo != NULL) { if (players[pnum].cls != NULL && @@ -958,7 +958,7 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info) switch (name) { case NAME_Team: info.TeamChanged(atoi(str)); break; - case NAME_Skin: info.SkinChanged(str); break; + case NAME_Skin: info.SkinChanged(str, 0); break; case NAME_PlayerClass: info.PlayerClassChanged(str); break; default: val.String = str; diff --git a/src/d_player.h b/src/d_player.h index f6f7674d7..e104a55b6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -332,7 +332,7 @@ struct userinfo_t : TMap void Reset(); int TeamChanged(int team); - int SkinChanged(const char *skinname); + int SkinChanged(const char *skinname, int playerclass); int SkinNumChanged(int skinnum); int GenderChanged(const char *gendername); int PlayerClassChanged(const char *classname); From db4763b14a0bfa0196ce41a96e96f5e724927291 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 16:27:57 -0600 Subject: [PATCH 132/247] Delay skin setting on save load until player class is known. - Fixed: Loading players from savegames set the skin before their current class was retrieved, so they could not validate their skins with the correct class. --- src/d_netinfo.cpp | 28 +++++++++------------------- src/d_player.h | 4 ++-- src/p_user.cpp | 18 +++++++++++++++--- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 41ad683fe..ae2da8018 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -941,14 +941,21 @@ void WriteUserInfo(FArchive &arc, userinfo_t &info) arc << name; } -void ReadUserInfo(FArchive &arc, userinfo_t &info) +void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin) { FName name; FBaseCVar **cvar; char *str = NULL; UCVarValue val; + if (SaveVersion < 4253) + { + ReadCompatibleUserInfo(arc, info); + return; + } + info.Reset(); + skin = NULL; for (arc << name; name != NAME_None; arc << name) { cvar = info.CheckKey(name); @@ -958,7 +965,7 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info) switch (name) { case NAME_Team: info.TeamChanged(atoi(str)); break; - case NAME_Skin: info.SkinChanged(str, 0); break; + case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known case NAME_PlayerClass: info.PlayerClassChanged(str); break; default: val.String = str; @@ -973,23 +980,6 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info) } } -FArchive &operator<< (FArchive &arc, userinfo_t &info) -{ - if (SaveVersion < 4253) - { - ReadCompatibleUserInfo(arc, info); - } - else if (arc.IsStoring()) - { - WriteUserInfo(arc, info); - } - else - { - ReadUserInfo(arc, info); - } - return arc; -} - CCMD (playerinfo) { if (argv.argc() < 2) diff --git a/src/d_player.h b/src/d_player.h index e104a55b6..122ab20f0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -342,8 +342,8 @@ struct userinfo_t : TMap int ColorSetChanged(int setnum); }; -FArchive &operator<< (FArchive &arc, userinfo_t &info); - +void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin); +void WriteUserInfo(FArchive &arc, userinfo_t &info); // // Extended player object info: player_t diff --git a/src/p_user.cpp b/src/p_user.cpp index 901f6cfaa..80b175802 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2742,14 +2742,22 @@ void P_UnPredictPlayer () void player_t::Serialize (FArchive &arc) { int i; + FString skinname; arc << cls << mo << camera << playerstate - << cmd - << userinfo - << DesiredFOV << FOV + << cmd; + if (arc.IsLoading()) + { + ReadUserInfo(arc, userinfo, skinname); + } + else + { + WriteUserInfo(arc, userinfo); + } + arc << DesiredFOV << FOV << viewz << viewheight << deltaviewheight @@ -2900,6 +2908,10 @@ void player_t::Serialize (FArchive &arc) oldbuttons = ~0; original_oldbuttons = ~0; } + if (skinname.IsNotEmpty()) + { + userinfo.SkinChanged(skinname, CurrentPlayerClass); + } } From a60918f601aa6bd094568340b26906f0f03772ae Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 17:43:28 -0600 Subject: [PATCH 133/247] Add NoPushWindowCheck compatibility flag - For maps like xtheateriii that expect non-blocking push lines to activate when you are standing on them and run into a completely different line, there is now this compatiblity.txt-only flag. --- src/compatibility.cpp | 1 + src/doomdef.h | 1 + src/p_map.cpp | 2 +- wadsrc/static/compatibility.txt | 7 ++++++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index dca0d3485..7339a0f19 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -106,6 +106,7 @@ static FCompatOption Options[] = { "ignoreteleporttags", BCOMPATF_BADTELEPORTERS, SLOT_BCOMPAT }, { "rebuildnodes", BCOMPATF_REBUILDNODES, SLOT_BCOMPAT }, { "linkfrozenprops", BCOMPATF_LINKFROZENPROPS, SLOT_BCOMPAT }, + { "disablepushwindowcheck", BCOMPATF_NOWINDOWCHECK, SLOT_BCOMPAT }, // list copied from g_mapinfo.cpp { "shorttex", COMPATF_SHORTTEX, SLOT_COMPAT }, diff --git a/src/doomdef.h b/src/doomdef.h index e08c3044d..6ef9fcd04 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -351,6 +351,7 @@ enum BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior BCOMPATF_REBUILDNODES = 1 << 5, // Force node rebuild BCOMPATF_LINKFROZENPROPS = 1 << 6, // Clearing PROP_TOTALLYFROZEN or PROP_FROZEN also clears the other + BCOMPATF_NOWINDOWCHECK = 1 << 7, // Disable the window check in CheckForPushSpecial() }; // phares 3/20/98: diff --git a/src/p_map.cpp b/src/p_map.cpp index 8b0b605c6..02ab1a1ab 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1640,7 +1640,7 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool wind { if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) { - if (windowcheck && line->backsector != NULL) + if (windowcheck && !(ib_compatflags & BCOMPATF_NOWINDOWCHECK) && line->backsector != NULL) { // Make sure this line actually blocks us and is not a window // or similar construct we are standing inside of. fixed_t fzt = line->frontsector->ceilingplane.ZatPoint(mobj->x, mobj->y); diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 4b75dfaba..e2516a30d 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -375,4 +375,9 @@ D62DCA9EC226DE49108D5DD9271F7631 // Cheogsh 2 map04 setthingz 1647 528 setthingz 1648 528 setthingz 1649 528 -} \ No newline at end of file +} + +B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01 +{ + DisablePushWindowCheck +} From 5a5fb9b3d19372d9323ba31fa5689fc95f94250b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 18:16:18 -0600 Subject: [PATCH 134/247] Clamp xy angle range in P_SetSlope() - This function just assumed that every xy angle passed to it was within the range [0,360). This is obviously bad, since anything outside that range can result in accessing data outside the range of the finecosine and finesine tables. --- src/p_slopes.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_slopes.cpp b/src/p_slopes.cpp index 07ddf2e0d..af0ad7a20 100644 --- a/src/p_slopes.cpp +++ b/src/p_slopes.cpp @@ -178,6 +178,12 @@ void P_SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi, } zang >>= ANGLETOFINESHIFT; + // Sanitize xyangi to [0,360) range + xyangi = xyangi % 360; + if (xyangi < 0) + { + xyangi = 360 + xyangi; + } xyang = (angle_t)Scale (xyangi, ANGLE_90, 90 << ANGLETOFINESHIFT); FVector3 norm; @@ -446,11 +452,11 @@ void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt, const int *oldve P_VavoomSlope(sec, mt->thingid, x, y, mt->z, mt->type & 1); } else if (mt->type <= THING_SlopeCeilingPointLine) - { + { // THING_SlopeFloorPointLine and THING_SlopCeilingPointLine P_SlopeLineToPoint (mt->args[0], x, y, z, mt->type & 1); } else - { + { // THING_SetFloorSlope and THING_SetCeilingSlope P_SetSlope (refplane, mt->type & 1, mt->angle, mt->args[0], x, y, z); } mt->type = 0; From 1d4f4b25d74fccc8f4c5e42811707e0606ce7adb Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Mon, 24 Feb 2014 19:01:36 -0600 Subject: [PATCH 135/247] Don't free replaced textures that are used as patches. - Fixed: If a part of a multipatch texture is replaced by a HIRESTEX version, the original patch must not be deleted, since the multipatch texture still needs it for compositing. --- src/textures/multipatchtexture.cpp | 6 ++++-- src/textures/texture.cpp | 2 +- src/textures/texturemanager.cpp | 2 +- src/textures/textures.h | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index fd2b59fb1..4f327309d 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -244,7 +244,6 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl Height = SAFESHORT(mtexture.d->height); strncpy (Name, (const char *)mtexture.d->name, 8); Name[8] = 0; - CalcBitSize (); xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; @@ -280,6 +279,10 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl NumParts--; i--; } + else + { + Parts[i].Texture->bKeepAround = true; + } if (strife) mpatch.s++; else @@ -859,7 +862,6 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d { pnames.Read (patchlookup[i].Name, 8); patchlookup[i].Name[8] = 0; - FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); if (j.isValid()) { diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 093bf303b..0434aaaa4 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -146,7 +146,7 @@ FTexture::FTexture (const char *name, int lumpnum) : LeftOffset(0), TopOffset(0), WidthBits(0), HeightBits(0), xScale(FRACUNIT), yScale(FRACUNIT), SourceLump(lumpnum), UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false), - bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), + bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0), bComplex(false), bMultiPatch(false), bKeepAround(false), Rotations(0xFFFF), SkyOffset(0), Width(0), Height(0), WidthMask(0), Native(NULL) { id.SetInvalid(); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index f28026f19..48f3ff9e0 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -428,7 +428,7 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b Textures[index].Texture = newtexture; newtexture->id = oldtexture->id; - if (free) + if (free && !oldtexture->bKeepAround) { delete oldtexture; } diff --git a/src/textures/textures.h b/src/textures/textures.h index 100ba31e9..837c62689 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -177,6 +177,7 @@ public: // fully composited before subjected to any kind of postprocessing instead of // doing it per patch. BYTE bMultiPatch:1; // This is a multipatch texture (we really could use real type info for textures...) + BYTE bKeepAround:1; // This texture was used as part of a multi-patch texture. Do not free it. WORD Rotations; SWORD SkyOffset; From 1fb757f6f120e2b7d09213b5da3f4976e1443868 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sat, 1 Mar 2014 22:27:40 +0100 Subject: [PATCH 136/247] - Fixed useless 'array != NULL' check. - 'notranslate != NULL' is completely useless, because 'notranslate' is an array, hence removed. - I interpreted 'SbarInfoScript != NULL' as a typo, since 1)in the next expression inside the condition there's a dereference to 'SBarInfoScript[SCRIPT_CUSTOM]' and 2)'SBarInfoScript[SCRIPT_CUSTOM]' is checked against 'NULL', in line 352, and then dereferenced when introducing 'cstype'. --- src/g_level.cpp | 2 +- src/v_font.cpp | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 0b07ae2b5..cf40b5099 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -387,7 +387,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) StatusBar->NewGame (); setsizeneeded = true; - if (gameinfo.gametype == GAME_Strife || (SBarInfoScript != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife)) + if (gameinfo.gametype == GAME_Strife || (SBarInfoScript[SCRIPT_CUSTOM] != NULL && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife)) { // Set the initial quest log text for Strife. for (i = 0; i < MAXPLAYERS; ++i) diff --git a/src/v_font.cpp b/src/v_font.cpp index d34b08be5..abd7f494c 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2009,26 +2009,20 @@ void FSpecialFont::LoadTranslations() } // exclude the non-translated colors from the translation calculation - if (notranslate != NULL) - { - for (i = 0; i < 256; i++) - if (notranslate[i]) - usedcolors[i] = false; - } + for (i = 0; i < 256; i++) + if (notranslate[i]) + usedcolors[i] = false; TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity); // Map all untranslated colors into the table of used colors - if (notranslate != NULL) + for (i = 0; i < 256; i++) { - for (i = 0; i < 256; i++) + if (notranslate[i]) { - if (notranslate[i]) - { - PatchRemap[i] = TotalColors; - identity[TotalColors] = i; - TotalColors++; - } + PatchRemap[i] = TotalColors; + identity[TotalColors] = i; + TotalColors++; } } From 79abe2d4e9e4b913c43a05c84396dbbc496441b1 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 3 Mar 2014 01:00:47 +1300 Subject: [PATCH 137/247] Made onground a player property "onground" was a global, despite being treated as a player property and crossed with instances from other players or prediction. --- src/d_player.h | 1 + src/p_user.cpp | 26 +++++++++++++++++--------- src/version.h | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 4da0e9d10..f50db97b1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -434,6 +434,7 @@ public: TObjPtr PremorphWeapon; // ready weapon before morphing int chickenPeck; // chicken peck countdown int jumpTics; // delay the next jump for a moment + bool onground; // Identifies if this player is on the ground or other object int respawn_time; // [RH] delay respawning until this tic TObjPtr camera; // [RH] Whose eyes this player sees through diff --git a/src/p_user.cpp b/src/p_user.cpp index e1b0210ef..90d0dd6cf 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -210,8 +210,6 @@ CCMD (playerclasses) // 16 pixels of bob #define MAXBOB 0x100000 -bool onground; - FArchive &operator<< (FArchive &arc, player_t *&p) { return arc.SerializePointer (players, (BYTE **)&p, sizeof(*players)); @@ -268,6 +266,7 @@ player_t::player_t() PremorphWeapon(0), chickenPeck(0), jumpTics(0), + onground(0), respawn_time(0), camera(0), air_finished(0), @@ -375,6 +374,7 @@ player_t &player_t::operator=(const player_t &p) PremorphWeapon = p.PremorphWeapon; chickenPeck = p.chickenPeck; jumpTics = p.jumpTics; + onground = p.onground; respawn_time = p.respawn_time; camera = p.camera; air_finished = p.air_finished; @@ -1747,7 +1747,7 @@ void P_CalcHeight (player_t *player) { player->bob = 0; } - else if ((player->mo->flags & MF_NOGRAVITY) && !onground) + else if ((player->mo->flags & MF_NOGRAVITY) && !player->onground) { player->bob = FRACUNIT / 2; } @@ -1872,7 +1872,7 @@ void P_MovePlayer (player_t *player) mo->angle += cmd->ucmd.yaw << 16; } - onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2); + player->onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2); // killough 10/98: // @@ -1890,7 +1890,7 @@ void P_MovePlayer (player_t *player) movefactor = P_GetMoveFactor (mo, &friction); bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR; - if (!onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel) + if (!player->onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel) { // [RH] allow very limited movement if not on ground. movefactor = FixedMul (movefactor, level.aircontrol); @@ -2061,12 +2061,12 @@ void P_DeathThink (player_t *player) P_MovePsprites (player); - onground = (player->mo->z <= player->mo->floorz); + player->onground = (player->mo->z <= player->mo->floorz); if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk))) { // Flying bloody skull or flying ice chunk player->viewheight = 6 * FRACUNIT; player->deltaviewheight = 0; - if (onground) + if (player->onground) { if (player->mo->pitch > -(int)ANGLE_1*19) { @@ -2365,7 +2365,7 @@ void P_PlayerThink (player_t *player) if (player->jumpTics != 0) { player->jumpTics--; - if (onground && player->jumpTics < -18) + if (player->onground && player->jumpTics < -18) { player->jumpTics = 0; } @@ -2465,7 +2465,7 @@ void P_PlayerThink (player_t *player) { player->mo->velz = 3*FRACUNIT; } - else if (level.IsJumpingAllowed() && onground && player->jumpTics == 0) + else if (level.IsJumpingAllowed() && player->onground && player->jumpTics == 0) { fixed_t jumpvelz = player->mo->JumpZ * 35 / TICRATE; @@ -2877,6 +2877,14 @@ void player_t::Serialize (FArchive &arc) { settings_controller = (this - players == Net_Arbitrator); } + if (SaveVersion >= 4505) + { + arc << onground; + } + else + { + onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2); + } if (isbot) { diff --git a/src/version.h b/src/version.h index 66e2f8938..1e328b312 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4504 +#define SAVEVER 4505 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) From f44dc926e6880777f96f884b42e4dd95f665b097 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 9 Mar 2014 10:02:07 +0100 Subject: [PATCH 138/247] - fixed uniqueTid logic - patch by Edward-San. --- src/p_mobj.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7dc8a3f46..168d686fe 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2726,16 +2726,15 @@ int P_FindUniqueTID(int start_tid, int limit) if (start_tid != 0) { // Do a linear search. - int end_tid = start_tid; - if (start_tid > 0 && limit > INT_MAX - start_tid + 1) - { // If 'limit+start_tid-1' overflows, clamp 'end_tid' to INT_MAX - end_tid = INT_MAX; + if (start_tid > INT_MAX-limit+1) + { // If 'limit+start_tid-1' overflows, clamp 'limit' to INT_MAX + limit = INT_MAX; } else { - end_tid += limit-1; + limit += start_tid-1; } - for (tid = start_tid; tid <= end_tid; ++tid) + for (tid = start_tid; tid <= limit; ++tid) { if (tid != 0 && !P_IsTIDUsed(tid)) { From 9dad8bdbbed9a7d8c0779b926613825ec8a92374 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Thu, 13 Mar 2014 18:27:39 +1300 Subject: [PATCH 139/247] Clear old camera from previous level The sound code could accidentally reference an old invalid camera during level spawn --- src/g_level.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_level.cpp b/src/g_level.cpp index cf40b5099..65bde08d8 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1084,6 +1084,7 @@ void G_StartTravel () { AActor *pawn = players[i].mo; AInventory *inv; + players[i].camera = NULL; // Only living players travel. Dead ones get a new body on the new level. if (players[i].health > 0) From 40771d22a53dec3f023eae8252f3aaa204267fb1 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 15 Mar 2014 04:15:30 +1300 Subject: [PATCH 140/247] Player prediction fixes in PIT_CheckThing Player prediction could end up executing functions for TOUCHY things or modify velocities when BLASTED, among other things. --- src/p_map.cpp | 66 +++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/p_map.cpp b/src/p_map.cpp index d900c2a46..45eb0d95c 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -914,34 +914,34 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } } - // touchy object is alive, toucher is solid - if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 && - // Thing is an armed mine or a sentient thing - (thing->flags6 & MF6_ARMED || thing->IsSentient()) && - // either different classes or players - (thing->player || thing->GetClass() != tm.thing->GetClass()) && - // or different species if DONTHARMSPECIES - (!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) && - // touches vertically - thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z && - // prevents lost souls from exploding when fired by pain elementals - (thing->master != tm.thing && tm.thing->master != thing)) - // Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species - // but different classes trigger the touchiness, but that seems less straightforwards. + if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) { - thing->flags6 &= ~MF6_ARMED; // Disarm - P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object - return true; - } + // touchy object is alive, toucher is solid + if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 && + // Thing is an armed mine or a sentient thing + (thing->flags6 & MF6_ARMED || thing->IsSentient()) && + // either different classes or players + (thing->player || thing->GetClass() != tm.thing->GetClass()) && + // or different species if DONTHARMSPECIES + (!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) && + // touches vertically + thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z && + // prevents lost souls from exploding when fired by pain elementals + (thing->master != tm.thing && tm.thing->master != thing)) + // Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species + // but different classes trigger the touchiness, but that seems less straightforwards. + { + thing->flags6 &= ~MF6_ARMED; // Disarm + P_DamageMobj(thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object + return true; + } - // Check for MF6_BUMPSPECIAL - // By default, only players can activate things by bumping into them - if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL) - || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER)) - || ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE)) - ) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away - { - if (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING)) + // Check for MF6_BUMPSPECIAL + // By default, only players can activate things by bumping into them + if ((thing->flags6 & MF6_BUMPSPECIAL) && ((tm.thing->player != NULL) + || ((thing->activationtype & THINGSPEC_MonsterTrigger) && (tm.thing->flags3 & MF3_ISMONSTER)) + || ((thing->activationtype & THINGSPEC_MissileTrigger) && (tm.thing->flags & MF_MISSILE)) + ) && (level.maptime > thing->lastbump)) // Leave the bumper enough time to go away { if (P_ActivateThingSpecial(thing, tm.thing)) thing->lastbump = level.maptime + TICRATE; @@ -955,6 +955,17 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) tm.thing->BlockingMobj = NULL; return res; } + + // [ED850] Player Prediction ends here. There is nothing else they could/should do. + if (tm.thing->player != NULL && (tm.thing->player->cheats & CF_PREDICTING)) + { + solid = (thing->flags & MF_SOLID) && + !(thing->flags & MF_NOCLIP) && + ((tm.thing->flags & MF_SOLID) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS)); + + return !solid || unblocking; + } + // Check for blasted thing running into another if ((tm.thing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE)) { @@ -1203,8 +1214,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) } return false; // don't traverse any more } - if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH) && - (tm.thing->player == NULL || !(tm.thing->player->cheats & CF_PREDICTING))) + if (thing->flags2 & MF2_PUSHABLE && !(tm.thing->flags2 & MF2_CANNOTPUSH)) { // Push thing if (thing->lastpush != tm.PushTime) { From 6aa56202b635c7928c1d7601ac43a8d6340d7e6b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 15 Mar 2014 13:17:22 +0200 Subject: [PATCH 141/247] Fix two issues with GL nodes handling Fix inability to load GL nodes for maps with names longer than 5 characters. Fix inability to load GL nodes from external GWA files. --- src/p_glnodes.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index b07d50aed..a8fa04c34 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -724,9 +724,10 @@ static bool DoLoadGLNodes(FileReader ** lumps) static bool MatchHeader(const char * label, const char * hdata) { - if (!memcmp(hdata, "LEVEL=", 6) == 0) + if (memcmp(hdata, "LEVEL=", 6) == 0) { size_t labellen = strlen(label); + labellen = MIN(size_t(8), labellen); if (strnicmp(hdata+6, label, labellen)==0 && (hdata[6+labellen]==0xa || hdata[6+labellen]==0xd)) @@ -771,7 +772,7 @@ static int FindGLNodesInWAD(int labellump) if (Wads.GetLumpFile(lump)==wadfile) { FMemLump mem = Wads.ReadLump(lump); - if (MatchHeader(Wads.GetLumpFullName(labellump), (const char *)mem.GetMem())) return true; + if (MatchHeader(Wads.GetLumpFullName(labellump), (const char *)mem.GetMem())) return lump; } } } @@ -781,7 +782,7 @@ static int FindGLNodesInWAD(int labellump) //=========================================================================== // -// FindGLNodesInWAD +// FindGLNodesInFile // // Looks for GL nodes in the same WAD as the level itself // Function returns the lump number within the file. Returns -1 if the input @@ -929,13 +930,13 @@ bool P_LoadGLNodes(MapData * map) result=true; for(unsigned i=0; i<4;i++) { - if (strnicmp(f_gwa->GetLump(i)->Name, check[i], 8)) + if (strnicmp(f_gwa->GetLump(i+1)->Name, check[i], 8)) { result=false; break; } else - gwalumps[i] = f_gwa->GetLump(i)->NewReader(); + gwalumps[i] = f_gwa->GetLump(i+1)->NewReader(); } if (result) result = DoLoadGLNodes(gwalumps); } From 3c8e9b6dc06cc0fbd2cfeed77e48f58c5438d327 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 16 Mar 2014 12:29:04 +0200 Subject: [PATCH 142/247] Fix incorrect Maulotaur melee attack sound It was STFHIT instead of STFPOW --- wadsrc/static/sndinfo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/sndinfo.txt b/wadsrc/static/sndinfo.txt index 49c6279b0..5508cd89b 100644 --- a/wadsrc/static/sndinfo.txt +++ b/wadsrc/static/sndinfo.txt @@ -634,7 +634,7 @@ $limit misc/spawn 1 // minotaur/sight minsit -minotaur/melee stfhit +minotaur/melee stfpow minotaur/attack1 minat1 minotaur/attack2 minat2 minotaur/attack3 minat3 From 5789ac624549907a7ff4c86edce5142083290876 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sun, 16 Mar 2014 13:21:08 +0100 Subject: [PATCH 143/247] - Fixed new[]/delete mismatch in FNodeBuilder Found with address sanitizer. --- src/nodebuild.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index be5d0591d..f3ceec17d 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -90,7 +90,7 @@ FNodeBuilder::~FNodeBuilder() } if (OldVertexTable != NULL) { - delete OldVertexTable; + delete[] OldVertexTable; } } From 6a958b032c2d060bf07530aa314c1173a457c9f6 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 18 Mar 2014 12:29:14 +0200 Subject: [PATCH 144/247] Add NOBLOOD flag to Heresiarch actor Heresiarch entity in vanilla Hexen doesn't spawn blood when hit --- wadsrc/static/actors/hexen/heresiarch.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/actors/hexen/heresiarch.txt b/wadsrc/static/actors/hexen/heresiarch.txt index 999f50540..5a77240fc 100644 --- a/wadsrc/static/actors/hexen/heresiarch.txt +++ b/wadsrc/static/actors/hexen/heresiarch.txt @@ -18,6 +18,7 @@ ACTOR Heresiarch 10080 native +NOTARGET +NOICEDEATH +DEFLECT + +NOBLOOD SeeSound "SorcererSight" PainSound "SorcererPain" DeathSound "SorcererDeathScream" From 697ef02871d10c8cd01be7f445eb6f46681fd73f Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Fri, 28 Mar 2014 00:17:32 +1300 Subject: [PATCH 145/247] Added StencilColor to Set/GetActorProperty --- src/p_acs.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1ed89f783..0a29f48e8 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3529,7 +3529,8 @@ enum APROP_ReactionTime = 37, APROP_MeleeRange = 38, APROP_ViewHeight = 39, - APROP_AttackZOffset = 40 + APROP_AttackZOffset = 40, + APROP_StencilColor = 41 }; // These are needed for ACS's APROP_RenderStyle @@ -3755,6 +3756,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value) static_cast(actor)->AttackZOffset = value; break; + case APROP_StencilColor: + actor->SetShade(value); + break; + default: // do nothing. break; @@ -3852,6 +3857,7 @@ int DLevelScript::GetActorProperty (int tid, int property, const SDWORD *stack, case APROP_ActiveSound: return GlobalACSStrings.AddString(actor->ActiveSound, stack, stackdepth); case APROP_Species: return GlobalACSStrings.AddString(actor->GetSpecies(), stack, stackdepth); case APROP_NameTag: return GlobalACSStrings.AddString(actor->GetTag(), stack, stackdepth); + case APROP_StencilColor:return actor->fillcolor; default: return 0; } From d7a2435703f56ce36c00892f31c3a582bb947b7d Mon Sep 17 00:00:00 2001 From: crimsondusk Date: Thu, 27 Mar 2014 16:34:32 +0200 Subject: [PATCH 146/247] - the ACS functions GetSectorFloorZ and GetSectorCeilingZ now interpret tag=0 as 'any sector' and return the z height of whatever sector is at those coordinates. --- src/p_acs.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 1ed89f783..10aa79bec 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -7874,14 +7874,22 @@ scriptwait: case PCD_GETSECTORCEILINGZ: // Arguments are (tag, x, y). If you don't use slopes, then (x, y) don't // really matter and can be left as (0, 0) if you like. + // [Dusk] If tag = 0, then this returns the z height at whatever sector + // is in x, y. { - int secnum = P_FindSectorFromTag (STACK(3), -1); + int tag = STACK(3); + int secnum; + fixed_t x = STACK(2) << FRACBITS; + fixed_t y = STACK(1) << FRACBITS; fixed_t z = 0; + if (tag != 0) + secnum = P_FindSectorFromTag (tag, -1); + else + secnum = P_PointInSector (x, y) - sectors; + if (secnum >= 0) { - fixed_t x = STACK(2) << FRACBITS; - fixed_t y = STACK(1) << FRACBITS; if (pcd == PCD_GETSECTORFLOORZ) { z = sectors[secnum].floorplane.ZatPoint (x, y); From a97b068ed7df7ff0f04d521b69f5d81392a3e8ee Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 30 Mar 2014 13:27:27 +0300 Subject: [PATCH 147/247] Enable fighting between different types of gargoyles and golems In vanilla Heretic: - Gargoyles are able to fight with Fire Gargoyles - Golems are able to fight with Nitro Golems, both regular and ghosted versions --- wadsrc/static/actors/heretic/hereticimp.txt | 1 + wadsrc/static/actors/heretic/mummy.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/wadsrc/static/actors/heretic/hereticimp.txt b/wadsrc/static/actors/heretic/hereticimp.txt index 25f64a2ea..2659d248a 100644 --- a/wadsrc/static/actors/heretic/hereticimp.txt +++ b/wadsrc/static/actors/heretic/hereticimp.txt @@ -82,6 +82,7 @@ ACTOR HereticImpLeader : HereticImp 5 { Game Heretic SpawnID 7 + Species "HereticImpLeader" Health 80 -MISSILEMORE AttackSound "himp/leaderattack" diff --git a/wadsrc/static/actors/heretic/mummy.txt b/wadsrc/static/actors/heretic/mummy.txt index c6cc2389b..af4ff0c23 100644 --- a/wadsrc/static/actors/heretic/mummy.txt +++ b/wadsrc/static/actors/heretic/mummy.txt @@ -55,6 +55,7 @@ ACTOR MummyLeader : Mummy 45 { Game Heretic SpawnID 2 + Species "MummyLeader" Health 100 Painchance 64 Obituary "$OB_MUMMYLEADER" @@ -89,6 +90,7 @@ ACTOR MummyLeaderGhost : MummyLeader 46 { Game Heretic SpawnID 9 + Species "MummyLeaderGhost" +SHADOW +GHOST RenderStyle Translucent From c47d77228d08840503aeeb7c4acd9e431193b9e1 Mon Sep 17 00:00:00 2001 From: crimsondusk Date: Sun, 30 Mar 2014 21:27:05 +0300 Subject: [PATCH 148/247] - increased updaterevision's buffer sizes to prevent GIT_BRANCH from cut short --- tools/updaterevision/updaterevision.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/updaterevision/updaterevision.c b/tools/updaterevision/updaterevision.c index 90127130a..6ccf174d0 100644 --- a/tools/updaterevision/updaterevision.c +++ b/tools/updaterevision/updaterevision.c @@ -34,7 +34,7 @@ void stripnl(char *str) int main(int argc, char **argv) { - char vertag[64], lastlog[64], lasthash[64], *hash = NULL; + char vertag[128], lastlog[128], lasthash[128], *hash = NULL; FILE *stream = NULL; int gotrev = 0, needupdate = 1; From 79f6e77e2ba617e3496f7178a94811dbabad3092 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 31 Mar 2014 23:49:21 +1300 Subject: [PATCH 149/247] Remove garbage characters from info CCMD --- src/p_mobj.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 168d686fe..545052af8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6167,25 +6167,25 @@ void PrintMiscActorInfo(AActor *query) static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans", "OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"}; - Printf("%s @ %p has the following flags:\n\tflags: %x", query->GetTag(), query, query->flags); + Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags); for (flagi = 0; flagi <= 31; flagi++) if (query->flags & 1<flags2); + Printf("\n flags2: %x", query->flags2); for (flagi = 0; flagi <= 31; flagi++) if (query->flags2 & 1<flags3); + Printf("\n flags3: %x", query->flags3); for (flagi = 0; flagi <= 31; flagi++) if (query->flags3 & 1<flags4); + Printf("\n flags4: %x", query->flags4); for (flagi = 0; flagi <= 31; flagi++) if (query->flags4 & 1<flags5); + Printf("\n flags5: %x", query->flags5); for (flagi = 0; flagi <= 31; flagi++) if (query->flags5 & 1<flags6); + Printf("\n flags6: %x", query->flags6); for (flagi = 0; flagi <= 31; flagi++) if (query->flags6 & 1<flags7); + Printf("\nflags7: %x", query->flags7); for (flagi = 0; flagi <= 31; flagi++) if (query->flags7 & 1< Date: Mon, 31 Mar 2014 23:57:43 +1300 Subject: [PATCH 150/247] Missed space in flags7 line. --- src/p_mobj.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 545052af8..75df3bb3e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2936,7 +2936,7 @@ bool AActor::IsOkayToAttack (AActor *link) if (P_CheckSight (this, link)) { // AMageStaffFX2::IsOkayToAttack had an extra check here, generalized with a flag, - // to only allow the check to succeed if the enemy was in a ~84° FOV of the player + // to only allow the check to succeed if the enemy was in a ~84� FOV of the player if (flags3 & MF3_SCREENSEEKER) { angle_t angle = R_PointToAngle2(Friend->x, @@ -6185,7 +6185,7 @@ void PrintMiscActorInfo(AActor *query) Printf("\n flags6: %x", query->flags6); for (flagi = 0; flagi <= 31; flagi++) if (query->flags6 & 1<flags7); + Printf("\n flags7: %x", query->flags7); for (flagi = 0; flagi <= 31; flagi++) if (query->flags7 & 1< Date: Mon, 31 Mar 2014 16:39:34 +0200 Subject: [PATCH 151/247] fixed: APROP_StencilColor was not implemented for CheckActorProperty. --- src/p_acs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 0a29f48e8..5f6af9408 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3904,6 +3904,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_MeleeRange: case APROP_ViewHeight: case APROP_AttackZOffset: + case APROP_StencilColor: return (GetActorProperty(tid, property, NULL, 0) == value); // Boolean values need to compare to a binary version of value From be33d2894ac59be3d8424f145113cb8248645b2f Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Tue, 1 Apr 2014 23:05:08 +1300 Subject: [PATCH 152/247] Fixed prediction thinglist order restoration Prediction didn't take sector_thinglist and thinglist order into account. This notably broke the order in which things were damaged. --- src/p_user.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 8 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index 90d0dd6cf..f792cf1d1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -65,6 +65,8 @@ CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static player_t PredictionPlayerBackup; static BYTE PredictionActorBackup[sizeof(AActor)]; static TArray PredictionTouchingSectorsBackup; +static TArray PredictionSectorListBackup; +static TArray PredictionSector_sprev_Backup; // [GRB] Custom player classes TArray PlayerClasses; @@ -2661,15 +2663,41 @@ void P_PredictPlayer (player_t *player) player->cheats |= CF_PREDICTING; // The ordering of the touching_sectorlist needs to remain unchanged + // Also store a copy of all previous sector_thinglist nodes msecnode_t *mnode = act->touching_sectorlist; + msecnode_t *snode; + PredictionSector_sprev_Backup.Clear(); PredictionTouchingSectorsBackup.Clear (); while (mnode != NULL) { PredictionTouchingSectorsBackup.Push (mnode->m_sector); + + for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext) + { + if (snode->m_thing == act) + { + PredictionSector_sprev_Backup.Push(snode->m_sprev); + break; + } + } + mnode = mnode->m_tnext; } + // Keep an ordered list off all actors in the linked sector. + PredictionSectorListBackup.Clear(); + if (!(act->flags & MF_NOSECTOR)) + { + AActor *link = act->Sector->thinglist; + + while (link != NULL) + { + PredictionSectorListBackup.Push(link); + link = link->snext; + } + } + // Blockmap ordering also needs to stay the same, so unlink the block nodes // without releasing them. (They will be used again in P_UnpredictPlayer). FBlockNode *block = act->BlockNode; @@ -2701,6 +2729,7 @@ void P_UnPredictPlayer () if (player->cheats & CF_PREDICTING) { + unsigned int i; AActor *act = player->mo; AActor *savedcamera = player->camera; @@ -2710,23 +2739,93 @@ void P_UnPredictPlayer () // could cause it to change during prediction. player->camera = savedcamera; - act->UnlinkFromWorld (); - memcpy (&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act)); + act->UnlinkFromWorld(); + memcpy(&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x - (BYTE *)act)); // Make the sector_list match the player's touching_sectorlist before it got predicted. - P_DelSeclist (sector_list); + P_DelSeclist(sector_list); sector_list = NULL; - for (unsigned int i = PredictionTouchingSectorsBackup.Size (); i-- > 0; ) + for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - sector_list = P_AddSecnode (PredictionTouchingSectorsBackup[i], act, sector_list); + sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list); } // The blockmap ordering needs to remain unchanged, too. Right now, act has the right // pointers, so temporarily set its MF_NOBLOCKMAP flag so that LinkToWorld() does not // mess with them. - act->flags |= MF_NOBLOCKMAP; - act->LinkToWorld (); - act->flags &= ~MF_NOBLOCKMAP; + { + DWORD keepflags = act->flags; + act->flags |= MF_NOBLOCKMAP; + act->LinkToWorld(); + act->flags = keepflags; + } + + // Restore sector links. + if (!(act->flags & MF_NOSECTOR)) + { + sector_t *sec = act->Sector; + AActor *me, *next; + AActor **link;// , **prev; + + // The thinglist is just a pointer chain. We are restoring the exact same things, so we can NULL the head safely + sec->thinglist = NULL; + + // [ED850] It doesn't look like I need this method. I'll keep it just incase something crops up, however. + /*for (i = PredictionSectorListBackup.Size(); i-- > 0;) + { + me = PredictionSectorListBackup[i]; + prev = me->sprev; + next = me->snext; + + if (prev != NULL) // prev will be NULL if this actor gets deleted due to cleaning up from a broken savegame + { + if ((*prev = next)) // unlink from sector list + next->sprev = prev; + me->snext = NULL; + me->sprev = (AActor **)(size_t)0xBeefCafe; // Woo! Bug-catching value! + } + }*/ + + for (i = PredictionSectorListBackup.Size(); i-- > 0;) + { + me = PredictionSectorListBackup[i]; + link = &sec->thinglist; + next = *link; + if ((me->snext = next)) + next->sprev = &me->snext; + me->sprev = link; + *link = me; + } + + // Restore sector thinglist order + for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) + { + msecnode_t *snode; + + for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext) + { + // If we were already the head, none of this is needed + if (snode->m_thing == act && PredictionSector_sprev_Backup[i]) + { + if (snode->m_sprev) + snode->m_sprev->m_snext = snode->m_snext; + else + snode->m_sector->touching_thinglist = snode->m_snext; + if (snode->m_snext) + snode->m_snext->m_sprev = snode->m_sprev; + + snode->m_sprev = PredictionSector_sprev_Backup[i]; + + // At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us. + if (snode->m_sprev->m_snext) + snode->m_sprev->m_snext->m_sprev = snode; + snode->m_snext = snode->m_sprev->m_snext; + snode->m_sprev->m_snext = snode; + break; + } + } + } + } // Now fix the pointers in the blocknode chain FBlockNode *block = act->BlockNode; From 546ae759fdf3abb27f01f0b70ff550e703d917b0 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Wed, 2 Apr 2014 21:12:10 +1300 Subject: [PATCH 153/247] Cleanup old prediction fix development code --- src/p_user.cpp | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index f792cf1d1..ea7b315d8 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2770,22 +2770,6 @@ void P_UnPredictPlayer () // The thinglist is just a pointer chain. We are restoring the exact same things, so we can NULL the head safely sec->thinglist = NULL; - // [ED850] It doesn't look like I need this method. I'll keep it just incase something crops up, however. - /*for (i = PredictionSectorListBackup.Size(); i-- > 0;) - { - me = PredictionSectorListBackup[i]; - prev = me->sprev; - next = me->snext; - - if (prev != NULL) // prev will be NULL if this actor gets deleted due to cleaning up from a broken savegame - { - if ((*prev = next)) // unlink from sector list - next->sprev = prev; - me->snext = NULL; - me->sprev = (AActor **)(size_t)0xBeefCafe; // Woo! Bug-catching value! - } - }*/ - for (i = PredictionSectorListBackup.Size(); i-- > 0;) { me = PredictionSectorListBackup[i]; @@ -2797,15 +2781,18 @@ void P_UnPredictPlayer () *link = me; } + msecnode_t *snode; + // Restore sector thinglist order for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - msecnode_t *snode; + // If we were already the head node, then nothing needs to change + if (PredictionSector_sprev_Backup[i] == NULL) + continue; for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext) { - // If we were already the head, none of this is needed - if (snode->m_thing == act && PredictionSector_sprev_Backup[i]) + if (snode->m_thing == act) { if (snode->m_sprev) snode->m_sprev->m_snext = snode->m_snext; From 3670acbe63f07583d03c165055303f3e76ddc398 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 08:44:33 -0500 Subject: [PATCH 154/247] Don't compile some unused DUMB tables spotted by Clang --- dumb/src/it/itrender.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dumb/src/it/itrender.c b/dumb/src/it/itrender.c index 4f3d50dfa..d4678ab4f 100644 --- a/dumb/src/it/itrender.c +++ b/dumb/src/it/itrender.c @@ -3950,6 +3950,7 @@ static int delta_to_note(float delta, int base) return (int)note; } +#if 0 // Period table for Protracker octaves 0-5: static const unsigned short ProTrackerPeriodTable[6*12] = { @@ -3981,6 +3982,7 @@ static const unsigned short ProTrackerTunedPeriods[16*12] = 1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920, 1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914 }; +#endif static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) { @@ -4400,6 +4402,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) int dumb_it_max_to_mix = 64; +#if 0 static const int aiMODVol[] = { 0, @@ -4425,6 +4428,7 @@ static const int aiPTMVolScaled[] = 836, 847, 859, 870, 881, 897, 908, 916, 927, 939, 950, 962, 969, 983, 1005, 1024 }; +#endif static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, double volume) { From 4406578522f991e7f1edcc54a38aa788993edec7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 08:46:47 -0500 Subject: [PATCH 155/247] Fixed: DSMF loader wrote outside filename array's bounds --- dumb/src/it/readdsmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dumb/src/it/readdsmf.c b/dumb/src/it/readdsmf.c index 5db09a75c..be545a678 100644 --- a/dumb/src/it/readdsmf.c +++ b/dumb/src/it/readdsmf.c @@ -31,8 +31,8 @@ static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, const unsigned char int flags; memcpy( sample->filename, data, 13 ); - sample->filename[ 14 ] = 0; - + sample->filename[ 13 ] = 0; + flags = data[ 13 ] | ( data[ 14 ] << 8 ); sample->default_volume = data[ 15 ]; sample->length = data[ 16 ] | ( data[ 17 ] << 8 ) | ( data[ 18 ] << 16 ) | ( data[ 19 ] << 24 ); From 1d1289722f14bea9f32fbaad3a0c7a151f838c66 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 08:50:09 -0500 Subject: [PATCH 156/247] Change , to && in 2 for loops in Oktalyzer loader - For something like i < n_chnnels, j < 4 , the first condition is completely unused, so why put it in the for loop at all? I assume these are supposed to be binary-and and not sequences. --- dumb/src/it/readokt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dumb/src/it/readokt.c b/dumb/src/it/readokt.c index 078929c5c..b662e55c4 100644 --- a/dumb/src/it/readokt.c +++ b/dumb/src/it/readokt.c @@ -486,7 +486,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f) /* And finally, the sample data */ k = get_chunk_count(mod, DUMB_ID('S','B','O','D')); - for (i = 0, j = 0; i < (unsigned)sigdata->n_samples, j < k; i++) { + for (i = 0, j = 0; i < (unsigned)sigdata->n_samples && j < k; i++) { if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) { chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j); if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) { @@ -503,7 +503,7 @@ static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f) chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0); - for (i = 0, j = 0; i < n_channels, j < 4; j++) { + for (i = 0, j = 0; i < n_channels && j < 4; j++) { k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1]; l = (j == 1 || j == 2) ? 48 : 16; if (k == 0) { From fbddfbe57658cc3d94d32dc86ecc3b3903ce1858 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 09:18:00 -0500 Subject: [PATCH 157/247] Upgrade game-music-emu to version 0.6.0 --- game-music-emu/CMakeLists.txt | 139 ++++++++++++++--------- game-music-emu/changes.txt | 44 ++++++++ game-music-emu/design.txt | 2 +- game-music-emu/gme.txt | 118 +++----------------- game-music-emu/gme/Ay_Apu.cpp | 12 +- game-music-emu/gme/Ay_Apu.h | 3 +- game-music-emu/gme/Ay_Cpu.cpp | 17 +-- game-music-emu/gme/Ay_Cpu.h | 2 +- game-music-emu/gme/Ay_Emu.cpp | 18 +-- game-music-emu/gme/Ay_Emu.h | 3 +- game-music-emu/gme/Blip_Buffer.cpp | 34 ++++-- game-music-emu/gme/CMakeLists.txt | 153 ++++++++++++++++++++++++++ game-music-emu/gme/Classic_Emu.cpp | 10 +- game-music-emu/gme/Classic_Emu.h | 2 +- game-music-emu/gme/Data_Reader.cpp | 17 ++- game-music-emu/gme/Data_Reader.h | 3 +- game-music-emu/gme/Dual_Resampler.cpp | 14 ++- game-music-emu/gme/Dual_Resampler.h | 2 +- game-music-emu/gme/Effects_Buffer.cpp | 2 +- game-music-emu/gme/Effects_Buffer.h | 2 +- game-music-emu/gme/Fir_Resampler.cpp | 6 +- game-music-emu/gme/Fir_Resampler.h | 12 +- game-music-emu/gme/Gb_Apu.cpp | 2 +- game-music-emu/gme/Gb_Cpu.cpp | 7 +- game-music-emu/gme/Gb_Cpu.h | 2 +- game-music-emu/gme/Gbs_Emu.cpp | 23 ++-- game-music-emu/gme/Gbs_Emu.h | 2 +- game-music-emu/gme/Gme_File.cpp | 6 +- game-music-emu/gme/Gme_File.h | 2 +- game-music-emu/gme/Gym_Emu.cpp | 2 +- game-music-emu/gme/Gym_Emu.h | 2 +- game-music-emu/gme/Hes_Apu.cpp | 10 +- game-music-emu/gme/Hes_Apu.h | 2 +- game-music-emu/gme/Hes_Cpu.cpp | 16 +-- game-music-emu/gme/Hes_Cpu.h | 2 +- game-music-emu/gme/Hes_Emu.cpp | 16 +-- game-music-emu/gme/Hes_Emu.h | 2 +- game-music-emu/gme/Kss_Cpu.cpp | 17 +-- game-music-emu/gme/Kss_Cpu.h | 2 +- game-music-emu/gme/Kss_Emu.cpp | 14 +-- game-music-emu/gme/Kss_Emu.h | 3 +- game-music-emu/gme/Kss_Scc_Apu.cpp | 2 +- game-music-emu/gme/Kss_Scc_Apu.h | 2 +- game-music-emu/gme/M3u_Playlist.cpp | 10 +- game-music-emu/gme/M3u_Playlist.h | 4 +- game-music-emu/gme/Multi_Buffer.cpp | 2 +- game-music-emu/gme/Music_Emu.cpp | 12 +- game-music-emu/gme/Music_Emu.h | 23 +++- game-music-emu/gme/Nes_Apu.cpp | 2 +- game-music-emu/gme/Nes_Cpu.cpp | 8 +- game-music-emu/gme/Nes_Cpu.h | 2 +- game-music-emu/gme/Nes_Fme7_Apu.cpp | 4 +- game-music-emu/gme/Nes_Fme7_Apu.h | 6 +- game-music-emu/gme/Nsf_Emu.cpp | 10 +- game-music-emu/gme/Nsf_Emu.h | 2 +- game-music-emu/gme/Nsfe_Emu.cpp | 12 +- game-music-emu/gme/Nsfe_Emu.h | 2 +- game-music-emu/gme/Sap_Apu.cpp | 8 +- game-music-emu/gme/Sap_Apu.h | 2 +- game-music-emu/gme/Sap_Cpu.cpp | 8 +- game-music-emu/gme/Sap_Cpu.h | 2 +- game-music-emu/gme/Sap_Emu.cpp | 14 +-- game-music-emu/gme/Sap_Emu.h | 2 +- game-music-emu/gme/Sms_Apu.cpp | 2 +- game-music-emu/gme/Snes_Spc.cpp | 4 +- game-music-emu/gme/Snes_Spc.h | 35 +++--- game-music-emu/gme/Spc_Cpu.cpp | 15 +-- game-music-emu/gme/Spc_Cpu.h | 18 +-- game-music-emu/gme/Spc_Dsp.cpp | 9 +- game-music-emu/gme/Spc_Dsp.h | 14 +-- game-music-emu/gme/Spc_Emu.cpp | 44 ++++++-- game-music-emu/gme/Spc_Emu.h | 7 +- game-music-emu/gme/Spc_Filter.cpp | 83 ++++++++++++++ game-music-emu/gme/Spc_Filter.h | 53 +++++++++ game-music-emu/gme/Vgm_Emu.cpp | 15 ++- game-music-emu/gme/Vgm_Emu.h | 2 +- game-music-emu/gme/Vgm_Emu_Impl.cpp | 4 +- game-music-emu/gme/Vgm_Emu_Impl.h | 2 +- game-music-emu/gme/Ym2413_Emu.cpp | 2 +- game-music-emu/gme/Ym2413_Emu.h | 2 +- game-music-emu/gme/Ym2612_Emu.cpp | 2 +- game-music-emu/gme/Ym2612_Emu.h | 2 +- game-music-emu/gme/blargg_common.h | 41 +++++-- game-music-emu/gme/blargg_config.h | 20 +++- game-music-emu/gme/blargg_endian.h | 114 +++++++++++-------- game-music-emu/gme/blargg_source.h | 44 +++++++- game-music-emu/gme/gb_cpu_io.h | 10 +- game-music-emu/gme/gme.cpp | 144 ++++++++++++++---------- game-music-emu/gme/gme.h | 112 ++++++++----------- game-music-emu/gme/gme_types.h | 21 ++++ game-music-emu/gme/gme_types.h.in | 23 ++++ game-music-emu/gme/hes_cpu_io.h | 2 +- game-music-emu/gme/nes_cpu_io.h | 2 +- game-music-emu/gme/sap_cpu_io.h | 2 +- game-music-emu/readme.txt | 53 +++++---- 95 files changed, 1139 insertions(+), 650 deletions(-) create mode 100644 game-music-emu/gme/CMakeLists.txt create mode 100644 game-music-emu/gme/Spc_Filter.cpp create mode 100644 game-music-emu/gme/Spc_Filter.h create mode 100644 game-music-emu/gme/gme_types.h create mode 100644 game-music-emu/gme/gme_types.h.in diff --git a/game-music-emu/CMakeLists.txt b/game-music-emu/CMakeLists.txt index f880023ab..d0cc7af5f 100644 --- a/game-music-emu/CMakeLists.txt +++ b/game-music-emu/CMakeLists.txt @@ -1,5 +1,15 @@ -cmake_minimum_required( VERSION 2.4 ) -include( CheckCXXCompilerFlag ) +# CMake project definition file. +project(libgme) + +include (CheckCXXCompilerFlag) + +# When version is changed, also change the one in gme/gme.h to match +set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version") + +# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't. +# Of course, 2.4 might work, in which case you're welcome to drop +# down the requirement, but I can't test that. +cmake_minimum_required(VERSION 2.6 FATAL_ERROR) make_release_only() @@ -19,51 +29,80 @@ if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE endif( HAVE_NO_ARRAY_BOUNDS ) endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) -add_library( gme - gme/Blip_Buffer.cpp - gme/Classic_Emu.cpp - gme/Data_Reader.cpp - gme/Dual_Resampler.cpp - gme/Effects_Buffer.cpp - gme/Fir_Resampler.cpp - gme/gme.cpp - gme/Gme_File.cpp - gme/M3u_Playlist.cpp - gme/Multi_Buffer.cpp - gme/Music_Emu.cpp - - gme/Ay_Apu.cpp - gme/Ay_Cpu.cpp - gme/Ay_Emu.cpp - gme/Gb_Apu.cpp - gme/Gb_Cpu.cpp - gme/Gb_Oscs.cpp - gme/Gbs_Emu.cpp - gme/Gym_Emu.cpp - gme/Hes_Apu.cpp - gme/Hes_Cpu.cpp - gme/Hes_Emu.cpp - gme/Kss_Cpu.cpp - gme/Kss_Emu.cpp - gme/Kss_Scc_Apu.cpp - gme/Nes_Apu.cpp - gme/Nes_Cpu.cpp - gme/Nes_Fme7_Apu.cpp - gme/Nes_Namco_Apu.cpp - gme/Nes_Oscs.cpp - gme/Nes_Vrc6_Apu.cpp - gme/Nsf_Emu.cpp - gme/Nsfe_Emu.cpp - gme/Sap_Apu.cpp - gme/Sap_Cpu.cpp - gme/Sap_Emu.cpp - gme/Sms_Apu.cpp - gme/Snes_Spc.cpp - gme/Spc_Cpu.cpp - gme/Spc_Dsp.cpp - gme/Spc_Emu.cpp - gme/Vgm_Emu.cpp - gme/Vgm_Emu_Impl.cpp - gme/Ym2413_Emu.cpp - gme/Ym2612_Emu.cpp ) -target_link_libraries( gme ) + + +# Default emulators to build (all of them! ;) +if (NOT DEFINED USE_GME_AY) + SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation") +endif() + +if (NOT DEFINED USE_GME_GBS) + SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation") +endif() + +if (NOT DEFINED USE_GME_GYM) + SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation") +endif() + +if (NOT DEFINED USE_GME_HES) + SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation") +endif() + +if (NOT DEFINED USE_GME_KSS) + SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation") +endif() + +if (NOT DEFINED USE_GME_NSF) + SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation") +endif() + +if (NOT DEFINED USE_GME_NSFE) + SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation") +endif() + +if (NOT DEFINED USE_GME_SAP) + SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation") +endif() + +if (NOT DEFINED USE_GME_SPC) + SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation") +endif() + +if (NOT DEFINED USE_GME_VGM) + SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation") +endif() + +if (USE_GME_NSFE AND NOT USE_GME_NSF) + MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --") + SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE) +endif() + +# Check for GCC "visibility" support. +if (CMAKE_COMPILER_IS_GNUCXX) + check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY) + set (ENABLE_VISIBILITY OFF) + if (__LIBGME_TEST_VISIBILITY) + # get the gcc version + exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info) + string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}") + + # gcc <4.1 had poor support for symbol visibility + if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1")) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set (ENABLE_VISIBILITY ON) + add_definitions (-DLIBGME_VISIBILITY) + + # GCC >= 4.2 also correctly supports making inline members have hidden + # visibility by default. + if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2")) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") + endif() + endif() + endif() # test visibility +endif (CMAKE_COMPILER_IS_GNUCXX) + +# Cache this result +set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility") + +# Shared library defined here +add_subdirectory(gme) diff --git a/game-music-emu/changes.txt b/game-music-emu/changes.txt index 0405b5904..3e422988c 100644 --- a/game-music-emu/changes.txt +++ b/game-music-emu/changes.txt @@ -1,6 +1,50 @@ Game_Music_Emu Change Log ------------------------- +Game_Music_Emu 0.6.0 +-------------------- + +- Note: A 0.5.6 release was referenced but never tagged or packaged. + +- SPC improvements: + - Switched to newer snes_spc 0.9.0 for SPC emulation. Uses fast DSP. + - Fixed Spc_Emu::gain(). + - Fixed support for files <0x10200 bytes. + +- Other bugfixes: + - Fixed a couple of GBS bugs, one involving access of memory after + realloc. + - Blip_Buffer works on systems where 'double' is a single-precision + floating-point type. + - Fix uninitialized buffer size in dual_resampler. + - Compilation warnings squashed out as of clang 3.3-pre and gcc 4.7.2. + +- API changes/additions: + - Removed documentation of C++ interface, as the C interface in gme.h is + the only supported one. + - Added gme_enable_accuracy() for enabling more accurate sound emulation + options (currently affects SPC only). + +- Build system improvements: + - Add pkg_config support. + - Fix build on case-insensitive systems. + - Allow for install on Cygwin. + - Fix install on multilib systems, such as many 64-bit distros (CMake must + be able to figure out your system's libsuffix, if any). + - C++ implementation symbols are not leaked into the resultant library + file (requires symbol visibility support). + +- Sample player improvements: + - Can toggle fast/accurate emulation (with the 'A' key). + +Game_Music_Emu 0.5.5 +-------------------- +- CMake build support has been added. You can build Game_Music_Emu as +a shared library and install it so that you do not have to include your +own copy if you know libgme will be present on your target system. +Requires CMake 2.6 or higher. + + Game_Music_Emu 0.5.2 -------------------- - *TONS* of changes and improvements. You should re-read the new header diff --git a/game-music-emu/design.txt b/game-music-emu/design.txt index 8c8c65b14..d42cadb12 100644 --- a/game-music-emu/design.txt +++ b/game-music-emu/design.txt @@ -1,4 +1,4 @@ -Game_Music_Emu 0.5.2 Design +Game_Music_Emu 0.6.0 Design --------------------------- This might be slightly out-of-date at times, but will be a big help in understanding the library implementation. diff --git a/game-music-emu/gme.txt b/game-music-emu/gme.txt index 2c963d8e3..98971f787 100644 --- a/game-music-emu/gme.txt +++ b/game-music-emu/gme.txt @@ -1,15 +1,14 @@ -Game_Music_Emu 0.5.2 +Game_Music_Emu 0.6.0 -------------------- Author : Shay Green Website: http://www.slack.net/~ant/libs/ Forum : http://groups.google.com/group/blargg-sound-libs +Source : https://code.google.com/p/game-music-emu/ License: GNU Lesser General Public License (LGPL) Contents -------- * Overview -* C and C++ interfaces -* Function reference * Error handling * Emulator types * M3U playlist support @@ -21,7 +20,6 @@ Contents * Modular construction * Obscure features * Solving problems -* Deprecated features * Thanks @@ -62,56 +60,15 @@ deleted with gme_set_user_cleanup() Refer to gme.h for a comprehensive summary of features. -C and C++ interfaces --------------------- -While the library is written in C++, an extensive C interface is -provided in gme.h. This C interface will be referred to throughout this -documentation unless a feature is only available in the full C++ -interface. All C interface functions and other names have the gme_ -prefix, so you can recognize a C++-only feature by the lack of gme_ in -the names used (contact me if you'd like a feature added to the C -interface). If you're building a shared library, I highly recommend -sticking to the C interface only, because it will be more stable between -releases of the library than the C++ interface. Finally, the C and C++ -interfaces can be freely mixed without problems. Compare demo/basics.c -with demo/cpp_basics.cpp to see how the C and C++ interfaces translate -between each other. - - -Function reference ------------------- -Read the following header files for a complete reference to functions -and features. The second group of header files can only be used in C++. - -blargg_config.h Library configuration -gme.h C interface (also usable from C++) - -Gme_File.h File loading and track information -Music_Emu.h Track playback and adjustments -Data_Reader.h Custom data readers -Effects_Buffer.h Sound buffer with adjustable stereo echo and panning -M3u_Playlist.h M3U playlist support -Gbs_Emu.h GBS equalizer settings -Nsf_Emu.h NSF equalizer settings -Spc_Emu.h SPC surround disable -Vgm_Emu.h VGM oversampling disable and custom buffer query - - Error handling -------------- -Functions which can fail have a return type of gme_err_t (blargg_err_t -in the C++ interfaces), which is a pointer to an error string (const -char*). If a function is successful it returns NULL. Errors that you can -easily avoid are checked with debug assertions; gme_err_t return values -are only used for genuine run-time errors that can't be easily predicted -in advance (out of memory, I/O errors, incompatible file data). Your -code should check all error values. - -To improve usability for C programmers, C++ programmers unfamiliar with -exceptions, and compatibility with older C++ compilers, the library does -*not* throw any C++ exceptions and uses malloc() instead of the standard -operator new. This means that you *must* check for NULL when creating a -library object with the new operator. +Functions which can fail have a return type of gme_err_t, which is a +pointer to an error string (const char*). If a function is successful it +returns NULL. Errors that you can easily avoid are checked with debug +assertions; gme_err_t return values are only used for genuine run-time +errors that can't be easily predicted in advance (out of memory, I/O +errors, incompatible file data). Your code should check all error +values. When loading a music file in the wrong emulator or trying to load a non-music file, gme_wrong_file_type is returned. You can check for this @@ -154,7 +111,9 @@ If you want to remove support for some music types to reduce your executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to support just NSF and GBS, use this: - #define GME_TYPE_LIST gme_nsf_type, gme_gbs_type + #define GME_TYPE_LIST \ + gme_nsf_type,\ + gme_gbs_type M3U playlist support @@ -271,40 +230,6 @@ create an emulator, you can use the following methods of loading: error = gme_load_custom( emu, my_read, file_size, my_data ); -* If you must load the file data into memory yourself, you can have the -library use your data directly *without* making a copy. If you do this, -you must not free the data until you're done playing the file. - - error = emu->load_mem( pointer, size ); - -* If you've already read the first bytes of a file (perhaps to determine -the file type) and want to avoid seeking back to the beginning for -performance reasons, use Remaining_Reader: - - Std_File_Reader in; - error = in.open( file_path ); - - char header [4]; - error = in.read( &header, sizeof header ); - ... - - Remaining_Reader rem( &header, sizeof header, &in ); - error = emu->load( rem ); - -If you merely need access to a file's header after loading, use the -emulator-specific header() functions, after casting the Music_Emu -pointer to the specific emulator's type. This example examines the -chip_flags field of the header if it's an NSF file: - - if ( music_emu->type() == gme_nsf_type ) - { - Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu; - if ( nsf_emu->header().chip_flags & 0x01 ) - ... - } - -Contact me if you want more information about loading files. - Sound parameters ---------------- @@ -437,21 +362,6 @@ separate threads. * If all else fails, see if the demos work. -Deprecated features -------------------- -The following functions and other features have been deprecated and will -be removed in a future release of the library. Alternatives to the -deprecated features are listed to the right. - -Music_Emu::error_count() warning() -load( header, reader ) see "Loading file data" above -Spc_Emu::trailer() track_info() -Spc_Emu::trailer_size() -Gym_Emu::track_length() track_info() -Vgm_Emu::gd3_data() track_info() -Nsfe_Emu::disable_playlist() clear_playlist() - - Thanks ------ Big thanks to Chris Moeller (kode54) for help with library testing and @@ -461,4 +371,6 @@ Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz, nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using, and giving feedback for the library in their respective game music -players. +players. More recently, Lucas Paul and Michael Pyne have helped nudge the +library into a public repository and get its interface more stable for use +in shared libraries. diff --git a/game-music-emu/gme/Ay_Apu.cpp b/game-music-emu/gme/Ay_Apu.cpp index 8c1c43a0f..c1405231d 100644 --- a/game-music-emu/gme/Ay_Apu.cpp +++ b/game-music-emu/gme/Ay_Apu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Ay_Apu.h" @@ -123,8 +123,8 @@ void Ay_Apu::write_data_( int addr, int data ) if ( (unsigned) addr >= 14 ) { - #ifdef dprintf - dprintf( "Wrote to I/O port %02X\n", (int) addr ); + #ifdef debug_printf + debug_printf( "Wrote to I/O port %02X\n", (int) addr ); #endif } @@ -220,7 +220,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time ) end_time = final_end_time; //if ( !(regs [12] | regs [11]) ) - // dprintf( "Used envelope period 0\n" ); + // debug_printf( "Used envelope period 0\n" ); } else if ( !volume ) { @@ -250,7 +250,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time ) ntime = start_time + old_noise_delay; noise_lfsr = old_noise_lfsr; //if ( (regs [6] & 0x1F) == 0 ) - // dprintf( "Used noise period 0\n" ); + // debug_printf( "Used noise period 0\n" ); } // The following efficiently handles several cases (least demanding first): @@ -299,7 +299,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time ) while ( ntime <= end ) // must advance *past* time to avoid hang { int changed = noise_lfsr + 1; - noise_lfsr = ((blargg_ulong)-(blargg_long)(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1); + noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1); if ( changed & 2 ) { delta = -delta; diff --git a/game-music-emu/gme/Ay_Apu.h b/game-music-emu/gme/Ay_Apu.h index 31956939e..b031f0473 100644 --- a/game-music-emu/gme/Ay_Apu.h +++ b/game-music-emu/gme/Ay_Apu.h @@ -1,6 +1,6 @@ // AY-3-8910 sound chip emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef AY_APU_H #define AY_APU_H @@ -50,7 +50,6 @@ private: Blip_Buffer* output; } oscs [osc_count]; blip_time_t last_time; - byte latch; byte regs [reg_count]; struct { diff --git a/game-music-emu/gme/Ay_Cpu.cpp b/game-music-emu/gme/Ay_Cpu.cpp index b4487d9c9..825320d08 100644 --- a/game-music-emu/gme/Ay_Cpu.cpp +++ b/game-music-emu/gme/Ay_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ /* Last validated with zexall 2006.11.21 5:26 PM @@ -807,6 +807,7 @@ possibly_out_of_time: case 0xCB: unsigned data2; data2 = INSTR( 1 ); + (void) data2; // TODO is this the same as data in all cases? pc++; switch ( data ) { @@ -1047,7 +1048,7 @@ possibly_out_of_time: blargg_ulong sum = temp + (flags & C01); flags = ~data >> 2 & N02; if ( flags ) - sum = (blargg_ulong)-(blargg_long)sum; + sum = -sum; sum += rp.hl; temp ^= rp.hl; temp ^= sum; @@ -1252,7 +1253,7 @@ possibly_out_of_time: case 0x4F: // LD R,A SET_R( rg.a ); - dprintf( "LD R,A not supported\n" ); + debug_printf( "LD R,A not supported\n" ); warning = true; goto loop; @@ -1262,7 +1263,7 @@ possibly_out_of_time: case 0x5F: // LD A,R rg.a = GET_R(); - dprintf( "LD A,R not supported\n" ); + debug_printf( "LD A,R not supported\n" ); warning = true; ld_ai_common: flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04); @@ -1285,7 +1286,7 @@ possibly_out_of_time: goto loop; default: - dprintf( "Opcode $ED $%02X not supported\n", data ); + debug_printf( "Opcode $ED $%02X not supported\n", data ); warning = true; goto loop; } @@ -1545,7 +1546,7 @@ possibly_out_of_time: } default: - dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); + debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); warning = true; goto loop; } @@ -1634,7 +1635,7 @@ possibly_out_of_time: } default: - dprintf( "Unnecessary DD/FD prefix encountered\n" ); + debug_printf( "Unnecessary DD/FD prefix encountered\n" ); warning = true; pc--; goto loop; @@ -1643,7 +1644,7 @@ possibly_out_of_time: } } - dprintf( "Unhandled main opcode: $%02X\n", opcode ); + debug_printf( "Unhandled main opcode: $%02X\n", opcode ); assert( false ); halt: diff --git a/game-music-emu/gme/Ay_Cpu.h b/game-music-emu/gme/Ay_Cpu.h index 07241d5e6..cd3d66747 100644 --- a/game-music-emu/gme/Ay_Cpu.h +++ b/game-music-emu/gme/Ay_Cpu.h @@ -1,6 +1,6 @@ // Z80 CPU emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef AY_CPU_H #define AY_CPU_H diff --git a/game-music-emu/gme/Ay_Emu.cpp b/game-music-emu/gme/Ay_Emu.cpp index 090b5ef82..43670d1bd 100644 --- a/game-music-emu/gme/Ay_Emu.cpp +++ b/game-music-emu/gme/Ay_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Ay_Emu.h" @@ -47,8 +47,8 @@ Ay_Emu::~Ay_Emu() { } static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size ) { - long pos = long(ptr - (byte const*) file.header); - long file_size = long(file.end - (byte const*) file.header); + long pos = ptr - (byte const*) file.header; + long file_size = file.end - (byte const*) file.header; assert( (unsigned long) pos <= (unsigned long) file_size - 2 ); int offset = (BOOST::int16_t) get_be16( ptr ); if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) ) @@ -207,11 +207,11 @@ blargg_err_t Ay_Emu::start_track_( int track ) if ( len > blargg_ulong (file.end - in) ) { set_warning( "Missing file data" ); - len = unsigned(file.end - in); + len = file.end - in; } - //dprintf( "addr: $%04X, len: $%04X\n", addr, len ); + //debug_printf( "addr: $%04X, len: $%04X\n", addr, len ); if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data - dprintf( "Block addr in ROM\n" ); + debug_printf( "Block addr in ROM\n" ); memcpy( mem.ram + addr, in, len ); if ( file.end - blocks < 8 ) @@ -242,7 +242,7 @@ blargg_err_t Ay_Emu::start_track_( int track ) }; memcpy( mem.ram, passive, sizeof passive ); unsigned play_addr = get_be16( more_data + 4 ); - //dprintf( "Play: $%04X\n", play_addr ); + //debug_printf( "Play: $%04X\n", play_addr ); if ( play_addr ) { memcpy( mem.ram, active, sizeof active ); @@ -315,7 +315,7 @@ void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data ) } } - dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data ); + debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data ); return; enable_cpc: @@ -356,7 +356,7 @@ int ay_cpu_in( Ay_Cpu*, unsigned addr ) if ( (addr & 0xFF) == 0xFE ) return 0xFF; // other values break some beeper tunes - dprintf( "Unmapped IN : $%04X\n", addr ); + debug_printf( "Unmapped IN : $%04X\n", addr ); return 0xFF; } diff --git a/game-music-emu/gme/Ay_Emu.h b/game-music-emu/gme/Ay_Emu.h index ba8445d31..86b020487 100644 --- a/game-music-emu/gme/Ay_Emu.h +++ b/game-music-emu/gme/Ay_Emu.h @@ -1,6 +1,6 @@ // Sinclair Spectrum AY music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef AY_EMU_H #define AY_EMU_H @@ -46,7 +46,6 @@ protected: private: file_t file; - unsigned play_addr; cpu_time_t play_period; cpu_time_t next_play; Blip_Buffer* beeper_output; diff --git a/game-music-emu/gme/Blip_Buffer.cpp b/game-music-emu/gme/Blip_Buffer.cpp index 9dc89ea8d..2b88cd4f8 100644 --- a/game-music-emu/gme/Blip_Buffer.cpp +++ b/game-music-emu/gme/Blip_Buffer.cpp @@ -233,18 +233,32 @@ static void gen_sinc( float* out, int count, double oversample, double treble, d double const to_angle = PI / 2 / maxh / oversample; for ( int i = 0; i < count; i++ ) { - double angle = ((i - count) * 2 + 1) * to_angle; - double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle ); - double cos_nc_angle = cos( maxh * cutoff * angle ); - double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle ); - double cos_angle = cos( angle ); + double angle = ((i - count) * 2 + 1) * to_angle; + double angle_maxh = angle * maxh; + double angle_maxh_mid = angle_maxh * cutoff; - c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle; - double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle); - double b = 2.0 - cos_angle - cos_angle; - double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle; + double y = maxh; - out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d + // 0 to Fs/2*cutoff, flat + if ( angle_maxh_mid ) // unstable at t=0 + y *= sin( angle_maxh_mid ) / angle_maxh_mid; + + // Fs/2*cutoff to Fs/2, logarithmic rolloff + double cosa = cos( angle ); + double den = 1 + rolloff * (rolloff - cosa - cosa); + + // Becomes unstable when rolloff is near 1.0 and t is near 0, + // which is the only time den becomes small + if ( den > 1e-13 ) + { + double num = + (cos( angle_maxh - angle ) * rolloff - cos( angle_maxh )) * pow_a_n - + cos( angle_maxh_mid - angle ) * rolloff + cos( angle_maxh_mid ); + + y = y * cutoff + num / den; + } + + out [i] = (float) y; } } diff --git a/game-music-emu/gme/CMakeLists.txt b/game-music-emu/gme/CMakeLists.txt new file mode 100644 index 000000000..73a14befb --- /dev/null +++ b/game-music-emu/gme/CMakeLists.txt @@ -0,0 +1,153 @@ +# List of source files required by libgme and any emulators +# This is not 100% accurate (Fir_Resampler for instance) but +# you'll be OK. +set(libgme_SRCS Blip_Buffer.cpp + Classic_Emu.cpp + Data_Reader.cpp + Dual_Resampler.cpp + Effects_Buffer.cpp + Fir_Resampler.cpp + gme.cpp + Gme_File.cpp + M3u_Playlist.cpp + Multi_Buffer.cpp + Music_Emu.cpp + ) + +# Ay_Apu is very popular around here +if (USE_GME_AY OR USE_GME_KSS) + set(libgme_SRCS ${libgme_SRCS} + Ay_Apu.cpp + ) +endif() + +# so is Ym2612_Emu +if (USE_GME_VGM OR USE_GME_GYM) + set(libgme_SRCS ${libgme_SRCS} + Ym2612_Emu.cpp + ) +endif() + +# But none are as popular as Sms_Apu +if (USE_GME_VGM OR USE_GME_GYM OR USE_GME_KSS) + set(libgme_SRCS ${libgme_SRCS} + Sms_Apu.cpp + ) +endif() + +if (USE_GME_AY) + set(libgme_SRCS ${libgme_SRCS} + # Ay_Apu.cpp included earlier + Ay_Cpu.cpp + Ay_Emu.cpp + ) +endif() + +if (USE_GME_GBS) + set(libgme_SRCS ${libgme_SRCS} + Gb_Apu.cpp + Gb_Cpu.cpp + Gb_Oscs.cpp + Gbs_Emu.cpp + ) +endif() + +if (USE_GME_GYM) + set(libgme_SRCS ${libgme_SRCS} + # Sms_Apu.cpp included earlier + # Ym2612_Emu.cpp included earlier + Gym_Emu.cpp + ) +endif() + +if (USE_GME_HES) + set(libgme_SRCS ${libgme_SRCS} + Hes_Apu.cpp + Hes_Cpu.cpp + Hes_Emu.cpp + ) +endif() + +if (USE_GME_KSS) + set(libgme_SRCS ${libgme_SRCS} + # Ay_Apu.cpp included earlier + # Sms_Apu.cpp included earlier + Kss_Cpu.cpp + Kss_Emu.cpp + Kss_Scc_Apu.cpp + ) +endif() + +if (USE_GME_NSF OR USE_GME_NSFE) + set(libgme_SRCS ${libgme_SRCS} + Nes_Apu.cpp + Nes_Cpu.cpp + Nes_Fme7_Apu.cpp + Nes_Namco_Apu.cpp + Nes_Oscs.cpp + Nes_Vrc6_Apu.cpp + Nsf_Emu.cpp + ) +endif() + +if (USE_GME_NSFE) + set(libgme_SRCS ${libgme_SRCS} + Nsfe_Emu.cpp + ) +endif() + +if (USE_GME_SAP) + set(libgme_SRCS ${libgme_SRCS} + Sap_Apu.cpp + Sap_Cpu.cpp + Sap_Emu.cpp + ) +endif() + +if (USE_GME_SPC) + set(libgme_SRCS ${libgme_SRCS} + Snes_Spc.cpp + Spc_Cpu.cpp + Spc_Dsp.cpp + Spc_Emu.cpp + Spc_Filter.cpp + ) +endif() + +if (USE_GME_VGM) + set(libgme_SRCS ${libgme_SRCS} + # Sms_Apu.cpp included earlier + # Ym2612_Emu.cpp included earlier + Vgm_Emu.cpp + Vgm_Emu_Impl.cpp + Ym2413_Emu.cpp + ) +endif() + +# These headers are part of the generic gme interface. +set (EXPORTED_HEADERS gme.h) + +# Run during cmake phase, so this is available during make +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gme_types.h.in + ${CMAKE_CURRENT_BINARY_DIR}/gme_types.h) + +# On some platforms we may need to change headers or whatnot based on whether +# we're building the library or merely using the library. The following is +# only defined when building the library to allow us to tell which is which. +add_definitions(-DBLARGG_BUILD_DLL) + +# For the gme_types.h +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Add library to be compiled. +add_library(gme ${libgme_SRCS}) + +# The version is the release. The "soversion" is the API version. As long +# as only build fixes are performed (i.e. no backwards-incompatible changes +# to the API), the SOVERSION should be the same even when bumping up VERSION. +# The way gme.h is designed, SOVERSION should very rarely be bumped, if ever. +# Hopefully the API can stay compatible with old versions. +#set_target_properties(gme +# PROPERTIES VERSION ${GME_VERSION} +# SOVERSION 0) +target_link_libraries(gme) diff --git a/game-music-emu/gme/Classic_Emu.cpp b/game-music-emu/gme/Classic_Emu.cpp index 622a5154f..42bb2fbe2 100644 --- a/game-music-emu/gme/Classic_Emu.cpp +++ b/game-music-emu/gme/Classic_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Classic_Emu.h" @@ -176,9 +176,9 @@ void Rom_Data_::set_addr_( long addr, int unit ) if ( 0 ) { - dprintf( "addr: %X\n", addr ); - dprintf( "file_size: %d\n", file_size_ ); - dprintf( "rounded: %d\n", rounded ); - dprintf( "mask: $%X\n", mask ); + debug_printf( "addr: %X\n", addr ); + debug_printf( "file_size: %d\n", file_size_ ); + debug_printf( "rounded: %d\n", rounded ); + debug_printf( "mask: $%X\n", mask ); } } diff --git a/game-music-emu/gme/Classic_Emu.h b/game-music-emu/gme/Classic_Emu.h index 8cd822ca2..99e99afbe 100644 --- a/game-music-emu/gme/Classic_Emu.h +++ b/game-music-emu/gme/Classic_Emu.h @@ -1,6 +1,6 @@ // Common aspects of emulators which use Blip_Buffer for sound output -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef CLASSIC_EMU_H #define CLASSIC_EMU_H diff --git a/game-music-emu/gme/Data_Reader.cpp b/game-music-emu/gme/Data_Reader.cpp index 8c4d8d0e1..5bbfbf551 100644 --- a/game-music-emu/gme/Data_Reader.cpp +++ b/game-music-emu/gme/Data_Reader.cpp @@ -1,15 +1,12 @@ // File_Extractor 0.4.0. http://www.slack.net/~ant/ -#define _CRT_SECURE_NO_WARNINGS -#define IN_GME 1 - -#include -#include -#include - #include "Data_Reader.h" #include "blargg_endian.h" +#include +#include +#include + /* Copyright (C) 2005-2006 Shay Green. This module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -92,11 +89,11 @@ Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r ) in = r; } -long Remaining_Reader::remain() const { return long(header_end - header + in->remain()); } +long Remaining_Reader::remain() const { return header_end - header + in->remain(); } long Remaining_Reader::read_first( void* out, long count ) { - long first = long(header_end - header); + long first = header_end - header; if ( first ) { if ( first > count ) @@ -213,7 +210,7 @@ long Std_File_Reader::size() const long Std_File_Reader::read_avail( void* p, long s ) { - return (long)fread( p, 1, s, (FILE*) file_ ); + return fread( p, 1, s, (FILE*) file_ ); } blargg_err_t Std_File_Reader::read( void* p, long s ) diff --git a/game-music-emu/gme/Data_Reader.h b/game-music-emu/gme/Data_Reader.h index e6321eb04..acf571f67 100644 --- a/game-music-emu/gme/Data_Reader.h +++ b/game-music-emu/gme/Data_Reader.h @@ -5,7 +5,6 @@ #define DATA_READER_H #include "blargg_common.h" -#include "gme.h" // Supports reading and finding out how many bytes are remaining class Data_Reader { @@ -117,7 +116,7 @@ private: // Invokes callback function to read data. Size of data must be specified in advance. class Callback_Reader : public Data_Reader { public: - typedef const char* (GMEAPI *callback_t)( void* data, void* out, int count ); + typedef const char* (*callback_t)( void* data, void* out, int count ); Callback_Reader( callback_t, long size, void* data = 0 ); public: long read_avail( void*, long ); diff --git a/game-music-emu/gme/Dual_Resampler.cpp b/game-music-emu/gme/Dual_Resampler.cpp index fe2085803..1c2cc36e2 100644 --- a/game-music-emu/gme/Dual_Resampler.cpp +++ b/game-music-emu/gme/Dual_Resampler.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Dual_Resampler.h" @@ -20,7 +20,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ unsigned const resampler_extra = 256; -Dual_Resampler::Dual_Resampler() { } +Dual_Resampler::Dual_Resampler() : + sample_buf_size(0), + oversamples_per_frame(-1), + buf_pos(-1), + resampler_size(0) +{ +} Dual_Resampler::~Dual_Resampler() { } @@ -62,10 +68,10 @@ void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out ) assert( blip_buf.samples_avail() == pair_count ); resampler.write( new_count ); - + long count = resampler.read( sample_buf.begin(), sample_buf_size ); assert( count == (long) sample_buf_size ); - + mix_samples( blip_buf, out ); blip_buf.remove_samples( pair_count ); } diff --git a/game-music-emu/gme/Dual_Resampler.h b/game-music-emu/gme/Dual_Resampler.h index 61beb8a08..6dc8dcfc2 100644 --- a/game-music-emu/gme/Dual_Resampler.h +++ b/game-music-emu/gme/Dual_Resampler.h @@ -1,6 +1,6 @@ // Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators. -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef DUAL_RESAMPLER_H #define DUAL_RESAMPLER_H diff --git a/game-music-emu/gme/Effects_Buffer.cpp b/game-music-emu/gme/Effects_Buffer.cpp index 730f8e94c..6af9c14be 100644 --- a/game-music-emu/gme/Effects_Buffer.cpp +++ b/game-music-emu/gme/Effects_Buffer.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Effects_Buffer.h" diff --git a/game-music-emu/gme/Effects_Buffer.h b/game-music-emu/gme/Effects_Buffer.h index eb0aa67a3..832c44b06 100644 --- a/game-music-emu/gme/Effects_Buffer.h +++ b/game-music-emu/gme/Effects_Buffer.h @@ -1,6 +1,6 @@ // Multi-channel effects buffer with panning, echo and reverb -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef EFFECTS_BUFFER_H #define EFFECTS_BUFFER_H diff --git a/game-music-emu/gme/Fir_Resampler.cpp b/game-music-emu/gme/Fir_Resampler.cpp index 56ca47801..7a6600be8 100644 --- a/game-music-emu/gme/Fir_Resampler.cpp +++ b/game-music-emu/gme/Fir_Resampler.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Fir_Resampler.h" @@ -156,7 +156,7 @@ int Fir_Resampler_::input_needed( blargg_long output_count ) const output_count -= 2; } - long input_extra = long(input_count - (write_pos - &buf [(width_ - 1) * stereo])); + long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]); if ( input_extra < 0 ) input_extra = 0; return input_extra; @@ -186,7 +186,7 @@ int Fir_Resampler_::avail_( blargg_long input_count ) const int Fir_Resampler_::skip_input( long count ) { - int remain = int(write_pos - buf.begin()); + int remain = write_pos - buf.begin(); int max_count = remain - width_ * stereo; if ( count > max_count ) count = max_count; diff --git a/game-music-emu/gme/Fir_Resampler.h b/game-music-emu/gme/Fir_Resampler.h index 36006de79..a1bb67781 100644 --- a/game-music-emu/gme/Fir_Resampler.h +++ b/game-music-emu/gme/Fir_Resampler.h @@ -1,6 +1,6 @@ // Finite impulse response (FIR) resampler with adjustable FIR size -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef FIR_RESAMPLER_H #define FIR_RESAMPLER_H @@ -31,7 +31,7 @@ public: void clear(); // Number of input samples that can be written - int max_write() const { return int(buf.end() - write_pos); } + int max_write() const { return buf.end() - write_pos; } // Pointer to place to write input samples sample_t* buffer() { return write_pos; } @@ -40,7 +40,7 @@ public: void write( long count ); // Number of input samples in buffer - int written() const { return int(write_pos - &buf [write_offset]); } + int written() const { return write_pos - &buf [write_offset]; } // Skip 'count' input samples. Returns number of samples actually skipped. int skip_input( long count ); @@ -51,7 +51,7 @@ public: int input_needed( blargg_long count ) const; // Number of output samples available - int avail() const { return avail_( blargg_long(write_pos - &buf [width_ * stereo]) ); } + int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); } public: ~Fir_Resampler_(); @@ -161,11 +161,11 @@ int Fir_Resampler::read( sample_t* out_begin, blargg_long count ) imp_phase = res - remain; - int left = int(write_pos - in); + int left = write_pos - in; write_pos = &buf [left]; memmove( buf.begin(), in, left * sizeof *in ); - return int(out - out_begin); + return out - out_begin; } #endif diff --git a/game-music-emu/gme/Gb_Apu.cpp b/game-music-emu/gme/Gb_Apu.cpp index 932ebb838..866594ddf 100644 --- a/game-music-emu/gme/Gb_Apu.cpp +++ b/game-music-emu/gme/Gb_Apu.cpp @@ -271,7 +271,7 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data ) } else { - //dprintf( "APU powered on\n" ); + //debug_printf( "APU powered on\n" ); } } } diff --git a/game-music-emu/gme/Gb_Cpu.cpp b/game-music-emu/gme/Gb_Cpu.cpp index bc7ac1876..b0128ea4c 100644 --- a/game-music-emu/gme/Gb_Cpu.cpp +++ b/game-music-emu/gme/Gb_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Gb_Cpu.h" @@ -89,11 +89,6 @@ unsigned const n_flag = 0x40; unsigned const h_flag = 0x20; unsigned const c_flag = 0x10; -#ifdef _MSC_VER -// warning C4101: 'blargg_failed_' : unreferenced local variable -// -- produced by the BOOST_STATIC_ASSERT line below -#pragma warning(disable:4101) -#endif bool Gb_Cpu::run( blargg_long cycle_count ) { state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr; diff --git a/game-music-emu/gme/Gb_Cpu.h b/game-music-emu/gme/Gb_Cpu.h index 953fbaf50..0994cec29 100644 --- a/game-music-emu/gme/Gb_Cpu.h +++ b/game-music-emu/gme/Gb_Cpu.h @@ -1,7 +1,7 @@ // Nintendo Game Boy CPU emulator // Treats every instruction as taking 4 cycles -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef GB_CPU_H #define GB_CPU_H diff --git a/game-music-emu/gme/Gbs_Emu.cpp b/game-music-emu/gme/Gbs_Emu.cpp index 83aefb424..05a0b9935 100644 --- a/game-music-emu/gme/Gbs_Emu.cpp +++ b/game-music-emu/gme/Gbs_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Gbs_Emu.h" @@ -18,8 +18,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "blargg_source.h" -Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000, 0, 0, 0, 0, 0, 0, 0, 0 }; -Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300, 0, 0, 0, 0, 0, 0, 0, 0 }; +Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = + Music_Emu::make_equalizer( -47.0, 2000 ); +Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = + Music_Emu::make_equalizer( 0.0, 300 ); Gbs_Emu::Gbs_Emu() { @@ -39,8 +41,7 @@ Gbs_Emu::Gbs_Emu() set_max_initial_silence( 21 ); set_gain( 1.2 ); - static equalizer_t const eq = { -1.0, 120, 0, 0, 0, 0, 0, 0, 0, 0 }; - set_equalizer( eq ); + set_equalizer( make_equalizer( -1.0, 120 ) ); } Gbs_Emu::~Gbs_Emu() { } @@ -151,7 +152,7 @@ void Gbs_Emu::set_bank( int n ) { // TODO: what is the correct behavior? Current Game & Watch Gallery // rip requires that this have no effect or set to bank 1. - //dprintf( "Selected ROM bank 0\n" ); + //debug_printf( "Selected ROM bank 0\n" ); return; //n = 1; } @@ -212,11 +213,11 @@ blargg_err_t Gbs_Emu::start_track_( int track ) for ( int i = 0; i < (int) sizeof sound_data; i++ ) apu.write_register( 0, i + apu.start_addr, sound_data [i] ); - cpu::reset( rom.unmapped() ); - unsigned load_addr = get_le16( header_.load_addr ); - cpu::rst_base = load_addr; rom.set_addr( load_addr ); + cpu::rst_base = load_addr; + + cpu::reset( rom.unmapped() ); cpu::map_code( ram_addr, 0x10000 - ram_addr, ram ); cpu::map_code( 0, bank_size, rom.at_addr( 0 ) ); @@ -265,13 +266,13 @@ blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int ) } else if ( cpu::r.pc > 0xFFFF ) { - dprintf( "PC wrapped around\n" ); + debug_printf( "PC wrapped around\n" ); cpu::r.pc &= 0xFFFF; } else { set_warning( "Emulation error (illegal/unsupported instruction)" ); - dprintf( "Bad opcode $%.2x at $%.4x\n", + debug_printf( "Bad opcode $%.2x at $%.4x\n", (int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc ); cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF; cpu_time += 6; diff --git a/game-music-emu/gme/Gbs_Emu.h b/game-music-emu/gme/Gbs_Emu.h index 6cc6b474b..b233a2b4f 100644 --- a/game-music-emu/gme/Gbs_Emu.h +++ b/game-music-emu/gme/Gbs_Emu.h @@ -1,6 +1,6 @@ // Nintendo Game Boy GBS music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef GBS_EMU_H #define GBS_EMU_H diff --git a/game-music-emu/gme/Gme_File.cpp b/game-music-emu/gme/Gme_File.cpp index 2d3a140e0..995f56b1c 100644 --- a/game-music-emu/gme/Gme_File.cpp +++ b/game-music-emu/gme/Gme_File.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Gme_File.h" @@ -60,8 +60,8 @@ blargg_err_t Gme_File::load_mem_( byte const* data, long size ) blargg_err_t Gme_File::load_( Data_Reader& in ) { RETURN_ERR( file_data.resize( in.remain() ) ); - RETURN_ERR( in.read( file_data.begin(), (long)file_data.size() ) ); - return load_mem_( file_data.begin(), (long)file_data.size() ); + RETURN_ERR( in.read( file_data.begin(), file_data.size() ) ); + return load_mem_( file_data.begin(), file_data.size() ); } // public load functions call this at beginning diff --git a/game-music-emu/gme/Gme_File.h b/game-music-emu/gme/Gme_File.h index f0e94302c..2d0a57344 100644 --- a/game-music-emu/gme/Gme_File.h +++ b/game-music-emu/gme/Gme_File.h @@ -1,6 +1,6 @@ // Common interface to game music file loading and information -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef GME_FILE_H #define GME_FILE_H diff --git a/game-music-emu/gme/Gym_Emu.cpp b/game-music-emu/gme/Gym_Emu.cpp index de34f64eb..f149aebb5 100644 --- a/game-music-emu/gme/Gym_Emu.cpp +++ b/game-music-emu/gme/Gym_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Gym_Emu.h" diff --git a/game-music-emu/gme/Gym_Emu.h b/game-music-emu/gme/Gym_Emu.h index 0f7a0e39c..1e4ed8b3e 100644 --- a/game-music-emu/gme/Gym_Emu.h +++ b/game-music-emu/gme/Gym_Emu.h @@ -1,7 +1,7 @@ // Sega Genesis/Mega Drive GYM music file emulator // Includes with PCM timing recovery to improve sample quality. -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef GYM_EMU_H #define GYM_EMU_H diff --git a/game-music-emu/gme/Hes_Apu.cpp b/game-music-emu/gme/Hes_Apu.cpp index cfb171d5b..9c7f515d6 100644 --- a/game-music-emu/gme/Hes_Apu.cpp +++ b/game-music-emu/gme/Hes_Apu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Hes_Apu.h" @@ -106,10 +106,10 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time ) unsigned noise_lfsr = this->noise_lfsr; do { - int new_dac = 0x1F & (unsigned)-(signed)(noise_lfsr >> 1 & 1); + int new_dac = 0x1F & -(noise_lfsr >> 1 & 1); // Implemented using "Galios configuration" // TODO: find correct LFSR algorithm - noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & (unsigned)-(signed)(noise_lfsr & 1)); + noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1)); //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1)); int delta = new_dac - dac; if ( delta ) @@ -158,7 +158,7 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time ) //period = 0x1000 * 2; period = 1; //if ( !(volume_0 | volume_1) ) - // dprintf( "Used period 0\n" ); + // debug_printf( "Used period 0\n" ); } // maintain phase when silent @@ -295,7 +295,7 @@ void Hes_Apu::write_data( blip_time_t time, int addr, int data ) case 0x809: if ( !(data & 0x80) && (data & 0x03) != 0 ) - dprintf( "HES LFO not supported\n" ); + debug_printf( "HES LFO not supported\n" ); } } } diff --git a/game-music-emu/gme/Hes_Apu.h b/game-music-emu/gme/Hes_Apu.h index ca0c932fd..89dde02cd 100644 --- a/game-music-emu/gme/Hes_Apu.h +++ b/game-music-emu/gme/Hes_Apu.h @@ -1,6 +1,6 @@ // Turbo Grafx 16 (PC Engine) PSG sound chip emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef HES_APU_H #define HES_APU_H diff --git a/game-music-emu/gme/Hes_Cpu.cpp b/game-music-emu/gme/Hes_Cpu.cpp index 2615a0bb9..4bfe8faff 100644 --- a/game-music-emu/gme/Hes_Cpu.cpp +++ b/game-music-emu/gme/Hes_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Hes_Cpu.h" @@ -148,7 +148,7 @@ loop: /* static long count; if ( count == 1844 ) Debugger(); - if ( s.base != correct ) dprintf( "%ld\n", count ); + if ( s.base != correct ) debug_printf( "%ld\n", count ); count++; */ } @@ -741,7 +741,7 @@ possibly_out_of_time: ARITH_ADDR_MODES( 0x65 ) // ADC adc_imm: { if ( status & st_d ) - dprintf( "Decimal mode not supported\n" ); + debug_printf( "Decimal mode not supported\n" ); fint16 carry = c >> 8 & 1; fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend status &= ~st_v; @@ -1085,7 +1085,7 @@ possibly_out_of_time: goto loop; } delayed_cli: - dprintf( "Delayed CLI not supported\n" ); // TODO: implement + debug_printf( "Delayed CLI not supported\n" ); // TODO: implement goto loop; } @@ -1100,7 +1100,7 @@ possibly_out_of_time: s_time += delta; if ( s_time < 0 ) goto loop; - dprintf( "Delayed SEI not supported\n" ); // TODO: implement + debug_printf( "Delayed SEI not supported\n" ); // TODO: implement goto loop; } @@ -1145,7 +1145,7 @@ possibly_out_of_time: goto loop; case 0x54: // CSL - dprintf( "CSL not supported\n" ); + debug_printf( "CSL not supported\n" ); illegal_encountered = true; goto loop; @@ -1154,7 +1154,7 @@ possibly_out_of_time: case 0xF4: { // SET //fuint16 operand = GET_MSB(); - dprintf( "SET not handled\n" ); + debug_printf( "SET not handled\n" ); //switch ( data ) //{ //} @@ -1233,7 +1233,7 @@ possibly_out_of_time: default: assert( (unsigned) opcode <= 0xFF ); - dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 ); + debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 ); illegal_encountered = true; goto loop; } diff --git a/game-music-emu/gme/Hes_Cpu.h b/game-music-emu/gme/Hes_Cpu.h index 536e732f8..d46a0b8a8 100644 --- a/game-music-emu/gme/Hes_Cpu.h +++ b/game-music-emu/gme/Hes_Cpu.h @@ -1,6 +1,6 @@ // PC Engine CPU emulator for use with HES music files -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef HES_CPU_H #define HES_CPU_H diff --git a/game-music-emu/gme/Hes_Emu.cpp b/game-music-emu/gme/Hes_Emu.cpp index 2306e705d..e3c700dbc 100644 --- a/game-music-emu/gme/Hes_Emu.cpp +++ b/game-music-emu/gme/Hes_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Hes_Emu.h" @@ -273,12 +273,12 @@ void Hes_Emu::cpu_write_vdp( int addr, int data ) } else { - dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data ); + debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data ); } break; case 3: - dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data ); + debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data ); break; } } @@ -325,7 +325,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data ) run_until( time ); irq.disables = data; if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values - dprintf( "Int mask: $%02X\n", data ); + debug_printf( "Int mask: $%02X\n", data ); break; case 0x1403: @@ -344,7 +344,7 @@ void Hes_Emu::cpu_write_( hes_addr_t addr, int data ) return; default: - dprintf( "unmapped write $%04X <- $%02X\n", addr, data ); + debug_printf( "unmapped write $%04X <- $%02X\n", addr, data ); return; #endif } @@ -368,14 +368,14 @@ int Hes_Emu::cpu_read_( hes_addr_t addr ) case 0x0002: case 0x0003: - dprintf( "VDP read not supported: %d\n", addr ); + debug_printf( "VDP read not supported: %d\n", addr ); return 0; case 0x0C01: //return timer.enabled; // TODO: remove? case 0x0C00: run_until( time ); - dprintf( "Timer count read\n" ); + debug_printf( "Timer count read\n" ); return (unsigned) (timer.count - 1) / timer_base; case 0x1402: @@ -396,7 +396,7 @@ int Hes_Emu::cpu_read_( hes_addr_t addr ) break; default: - dprintf( "unmapped read $%04X\n", addr ); + debug_printf( "unmapped read $%04X\n", addr ); #endif } diff --git a/game-music-emu/gme/Hes_Emu.h b/game-music-emu/gme/Hes_Emu.h index 9951eb6a2..b4e20fd67 100644 --- a/game-music-emu/gme/Hes_Emu.h +++ b/game-music-emu/gme/Hes_Emu.h @@ -1,6 +1,6 @@ // TurboGrafx-16/PC Engine HES music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef HES_EMU_H #define HES_EMU_H diff --git a/game-music-emu/gme/Kss_Cpu.cpp b/game-music-emu/gme/Kss_Cpu.cpp index c943a01fe..a2068efc4 100644 --- a/game-music-emu/gme/Kss_Cpu.cpp +++ b/game-music-emu/gme/Kss_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ /* Last validated with zexall 2006.11.14 2:19 PM @@ -841,6 +841,7 @@ possibly_out_of_time: case 0xCB: unsigned data2; data2 = instr [1]; + (void) data2; // TODO is this the same as data in all cases? pc++; switch ( data ) { @@ -1084,7 +1085,7 @@ possibly_out_of_time: blargg_ulong sum = temp + (flags & C01); flags = ~data >> 2 & N02; if ( flags ) - sum = (blargg_ulong)-(blargg_long)sum; + sum = -sum; sum += rp.hl; temp ^= rp.hl; temp ^= sum; @@ -1289,7 +1290,7 @@ possibly_out_of_time: case 0x4F: // LD R,A SET_R( rg.a ); - dprintf( "LD R,A not supported\n" ); + debug_printf( "LD R,A not supported\n" ); warning = true; goto loop; @@ -1299,7 +1300,7 @@ possibly_out_of_time: case 0x5F: // LD A,R rg.a = GET_R(); - dprintf( "LD A,R not supported\n" ); + debug_printf( "LD A,R not supported\n" ); warning = true; ld_ai_common: flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04); @@ -1322,7 +1323,7 @@ possibly_out_of_time: goto loop; default: - dprintf( "Opcode $ED $%02X not supported\n", data ); + debug_printf( "Opcode $ED $%02X not supported\n", data ); warning = true; goto loop; } @@ -1583,7 +1584,7 @@ possibly_out_of_time: } default: - dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); + debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 ); warning = true; goto loop; } @@ -1672,7 +1673,7 @@ possibly_out_of_time: } default: - dprintf( "Unnecessary DD/FD prefix encountered\n" ); + debug_printf( "Unnecessary DD/FD prefix encountered\n" ); warning = true; pc--; goto loop; @@ -1681,7 +1682,7 @@ possibly_out_of_time: } } - dprintf( "Unhandled main opcode: $%02X\n", opcode ); + debug_printf( "Unhandled main opcode: $%02X\n", opcode ); assert( false ); hit_idle_addr: diff --git a/game-music-emu/gme/Kss_Cpu.h b/game-music-emu/gme/Kss_Cpu.h index 6297d1000..aec24e9d5 100644 --- a/game-music-emu/gme/Kss_Cpu.h +++ b/game-music-emu/gme/Kss_Cpu.h @@ -1,6 +1,6 @@ // Z80 CPU emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef KSS_CPU_H #define KSS_CPU_H diff --git a/game-music-emu/gme/Kss_Emu.cpp b/game-music-emu/gme/Kss_Emu.cpp index 3176aece7..def6ee199 100644 --- a/game-music-emu/gme/Kss_Emu.cpp +++ b/game-music-emu/gme/Kss_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Kss_Emu.h" @@ -230,9 +230,9 @@ blargg_err_t Kss_Emu::start_track_( int track ) bank_count = max_banks; set_warning( "Bank data missing" ); } - //dprintf( "load_size : $%X\n", load_size ); - //dprintf( "bank_size : $%X\n", bank_size ); - //dprintf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F ); + //debug_printf( "load_size : $%X\n", load_size ); + //debug_printf( "bank_size : $%X\n", bank_size ); + //debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F ); ram [idle_addr] = 0xFF; cpu::reset( unmapped_write, unmapped_read ); @@ -301,7 +301,7 @@ void Kss_Emu::cpu_write( unsigned addr, int data ) return; } - dprintf( "LD ($%04X),$%02X\n", addr, data ); + debug_printf( "LD ($%04X),$%02X\n", addr, data ); } void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data ) @@ -358,7 +358,7 @@ void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data ) #endif } - dprintf( "OUT $%04X,$%02X\n", addr, data ); + debug_printf( "OUT $%04X,$%02X\n", addr, data ); } int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr ) @@ -368,7 +368,7 @@ int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr ) //{ //} - dprintf( "IN $%04X\n", addr ); + debug_printf( "IN $%04X\n", addr ); return 0; } diff --git a/game-music-emu/gme/Kss_Emu.h b/game-music-emu/gme/Kss_Emu.h index 4d8463abd..e457f7311 100644 --- a/game-music-emu/gme/Kss_Emu.h +++ b/game-music-emu/gme/Kss_Emu.h @@ -1,6 +1,6 @@ // MSX computer KSS music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef KSS_EMU_H #define KSS_EMU_H @@ -68,7 +68,6 @@ private: void update_gain(); unsigned scc_enabled; // 0 or 0xC000 - byte const* bank_data; int bank_count; void set_bank( int logical, int physical ); blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); } diff --git a/game-music-emu/gme/Kss_Scc_Apu.cpp b/game-music-emu/gme/Kss_Scc_Apu.cpp index 1660ac3da..1ab14bd00 100644 --- a/game-music-emu/gme/Kss_Scc_Apu.cpp +++ b/game-music-emu/gme/Kss_Scc_Apu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Kss_Scc_Apu.h" diff --git a/game-music-emu/gme/Kss_Scc_Apu.h b/game-music-emu/gme/Kss_Scc_Apu.h index 03a6a1080..c8c69f118 100644 --- a/game-music-emu/gme/Kss_Scc_Apu.h +++ b/game-music-emu/gme/Kss_Scc_Apu.h @@ -1,6 +1,6 @@ // Konami SCC sound chip emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef KSS_SCC_APU_H #define KSS_SCC_APU_H diff --git a/game-music-emu/gme/M3u_Playlist.cpp b/game-music-emu/gme/M3u_Playlist.cpp index f5d38893a..bbe52b1a7 100644 --- a/game-music-emu/gme/M3u_Playlist.cpp +++ b/game-music-emu/gme/M3u_Playlist.cpp @@ -1,6 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ - -#define IN_GME 1 +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "M3u_Playlist.h" #include "Music_Emu.h" @@ -54,9 +52,9 @@ blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); } -gme_err_t GMEAPI gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); } +BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); } -gme_err_t GMEAPI gme_load_m3u_data( Music_Emu* me, const void* data, long size ) +BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size ) { Mem_File_Reader in( data, size ); return me->load_m3u( in ); @@ -409,7 +407,7 @@ blargg_err_t M3u_Playlist::parse() blargg_err_t M3u_Playlist::load( Data_Reader& in ) { RETURN_ERR( data.resize( in.remain() + 1 ) ); - RETURN_ERR( in.read( data.begin(), long(data.size() - 1) ) ); + RETURN_ERR( in.read( data.begin(), data.size() - 1 ) ); return parse(); } diff --git a/game-music-emu/gme/M3u_Playlist.h b/game-music-emu/gme/M3u_Playlist.h index a13387945..e764cb936 100644 --- a/game-music-emu/gme/M3u_Playlist.h +++ b/game-music-emu/gme/M3u_Playlist.h @@ -1,6 +1,6 @@ // M3U playlist file parser, with support for subtrack information -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef M3U_PLAYLIST_H #define M3U_PLAYLIST_H @@ -43,7 +43,7 @@ public: int repeat; // count }; entry_t const& operator [] ( int i ) const { return entries [i]; } - int size() const { return (int)entries.size(); } + int size() const { return entries.size(); } void clear(); diff --git a/game-music-emu/gme/Multi_Buffer.cpp b/game-music-emu/gme/Multi_Buffer.cpp index ecd8f8add..57f93b317 100644 --- a/game-music-emu/gme/Multi_Buffer.cpp +++ b/game-music-emu/gme/Multi_Buffer.cpp @@ -114,7 +114,7 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count ) if ( count ) { int bufs_used = stereo_added | was_stereo; - //dprintf( "%X\n", bufs_used ); + //debug_printf( "%X\n", bufs_used ); if ( bufs_used <= 1 ) { mix_mono( out, count ); diff --git a/game-music-emu/gme/Music_Emu.cpp b/game-music-emu/gme/Music_Emu.cpp index b0f3f71d5..30b25dcfc 100644 --- a/game-music-emu/gme/Music_Emu.cpp +++ b/game-music-emu/gme/Music_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Music_Emu.h" @@ -24,7 +24,8 @@ int const silence_threshold = 0x10; long const fade_block_size = 512; int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift) -Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180, 0, 0, 0, 0, 0, 0, 0, 0 }; +Music_Emu::equalizer_t const Music_Emu::tv_eq = + Music_Emu::make_equalizer( -8.0, 180 ); void Music_Emu::clear_track_vars() { @@ -305,7 +306,7 @@ static long count_silence( Music_Emu::sample_t* begin, long size ) Music_Emu::sample_t* p = begin + size; while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { } *begin = first; - return size - long(p - begin); + return size - (p - begin); } // fill internal buffer and check it for silence @@ -340,14 +341,14 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out ) assert( emu_time >= out_time ); // prints nifty graph of how far ahead we are when searching for silence - //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" ); + //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" ); long pos = 0; if ( silence_count ) { // during a run of silence, run emulator at >=2x speed so it gets ahead long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time; - while ( emu_time < ahead_time && !(buf_remain || emu_track_ended_) ) + while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) ) fill_buf(); // fill with silence @@ -404,6 +405,7 @@ blargg_err_t Gme_Info_::set_sample_rate_( long ) { return 0; } void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu void Gme_Info_::post_load_() { Gme_File::post_load_(); } // skip Music_Emu void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); } +void Gme_Info_::enable_accuracy_( bool ) { check( false ); } void Gme_Info_::mute_voices_( int ) { check( false ); } void Gme_Info_::set_tempo_( double ) { } blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; } diff --git a/game-music-emu/gme/Music_Emu.h b/game-music-emu/gme/Music_Emu.h index 6a2eaa110..b96f4b611 100644 --- a/game-music-emu/gme/Music_Emu.h +++ b/game-music-emu/gme/Music_Emu.h @@ -1,6 +1,6 @@ // Common interface to game music file emulators -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef MUSIC_EMU_H #define MUSIC_EMU_H @@ -82,6 +82,10 @@ public: // on others this has no effect. Should be called only once *before* set_sample_rate(). virtual void set_buffer( Multi_Buffer* ) { } + // Enables/disables accurate emulation options, if any are supported. Might change + // equalizer settings. + void enable_accuracy( bool enable = true ); + // Sound equalization (treble/bass) // Frequency equalizer parameters (see gme.txt) @@ -93,6 +97,14 @@ public: // Set frequency equalizer parameters void set_equalizer( equalizer_t const& ); + + // Construct equalizer of given treble/bass settings + static const equalizer_t make_equalizer( double treble, double bass ) + { + const Music_Emu::equalizer_t e = { treble, bass, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + return e; + } // Equalizer settings for TV speaker static equalizer_t const tv_eq; @@ -111,7 +123,8 @@ protected: void remute_voices(); virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0; - virtual void set_equalizer_( equalizer_t const& ) { }; + virtual void set_equalizer_( equalizer_t const& ) { } + virtual void enable_accuracy_( bool /* enable */ ) { } virtual void mute_voices_( int mask ) = 0; virtual void set_tempo_( double ) = 0; virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this @@ -160,8 +173,8 @@ private: void emu_play( long count, sample_t* out ); Multi_Buffer* effects_buffer; - friend GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int ); - friend GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double ); + friend Music_Emu* gme_new_emu( gme_type_t, int ); + friend void gme_set_stereo_depth( Music_Emu*, double ); }; // base class for info-only derivations @@ -169,6 +182,7 @@ struct Gme_Info_ : Music_Emu { virtual blargg_err_t set_sample_rate_( long sample_rate ); virtual void set_equalizer_( equalizer_t const& ); + virtual void enable_accuracy_( bool ); virtual void mute_voices_( int mask ); virtual void set_tempo_( double ); virtual blargg_err_t start_track_( int ); @@ -189,6 +203,7 @@ inline int Music_Emu::current_track() const { return current_track_; } inline bool Music_Emu::track_ended() const { return track_ended_; } inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; } +inline void Music_Emu::enable_accuracy( bool b ) { enable_accuracy_( b ); } inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; } inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); } inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; } diff --git a/game-music-emu/gme/Nes_Apu.cpp b/game-music-emu/gme/Nes_Apu.cpp index 8daf5d0e1..68edb446d 100644 --- a/game-music-emu/gme/Nes_Apu.cpp +++ b/game-music-emu/gme/Nes_Apu.cpp @@ -385,7 +385,7 @@ int Nes_Apu::read_status( nes_time_t time ) irq_changed(); } - //dprintf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result ); + //debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result ); return result; } diff --git a/game-music-emu/gme/Nes_Cpu.cpp b/game-music-emu/gme/Nes_Cpu.cpp index 480b4aa48..ac548d0ff 100644 --- a/game-music-emu/gme/Nes_Cpu.cpp +++ b/game-music-emu/gme/Nes_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Nes_Cpu.h" @@ -921,7 +921,7 @@ imm##op: goto loop; status &= ~st_i; handle_cli: { - //dprintf( "CLI at %d\n", TIME ); + //debug_printf( "CLI at %d\n", TIME ); this->r.status = status; // update externally-visible I flag blargg_long delta = s.base - irq_time_; if ( delta <= 0 ) @@ -944,7 +944,7 @@ imm##op: // TODO: implement delayed_cli: - dprintf( "Delayed CLI not emulated\n" ); + debug_printf( "Delayed CLI not emulated\n" ); goto loop; } @@ -960,7 +960,7 @@ imm##op: if ( s_time < 0 ) goto loop; - dprintf( "Delayed SEI not emulated\n" ); + debug_printf( "Delayed SEI not emulated\n" ); goto loop; } diff --git a/game-music-emu/gme/Nes_Cpu.h b/game-music-emu/gme/Nes_Cpu.h index 94286708d..c139e069f 100644 --- a/game-music-emu/gme/Nes_Cpu.h +++ b/game-music-emu/gme/Nes_Cpu.h @@ -1,6 +1,6 @@ // NES 6502 CPU emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef NES_CPU_H #define NES_CPU_H diff --git a/game-music-emu/gme/Nes_Fme7_Apu.cpp b/game-music-emu/gme/Nes_Fme7_Apu.cpp index c058f6b1f..bc8ca7f48 100644 --- a/game-music-emu/gme/Nes_Fme7_Apu.cpp +++ b/game-music-emu/gme/Nes_Fme7_Apu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Nes_Fme7_Apu.h" @@ -56,7 +56,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time ) // check for unsupported mode #ifndef NDEBUG if ( (mode & 011) <= 001 && vol_mode & 0x1F ) - dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n", + debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n", mode, vol_mode & 0x1F ); #endif diff --git a/game-music-emu/gme/Nes_Fme7_Apu.h b/game-music-emu/gme/Nes_Fme7_Apu.h index eb60af038..9069bd06a 100644 --- a/game-music-emu/gme/Nes_Fme7_Apu.h +++ b/game-music-emu/gme/Nes_Fme7_Apu.h @@ -1,6 +1,6 @@ // Sunsoft FME-7 sound emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef NES_FME7_APU_H #define NES_FME7_APU_H @@ -97,8 +97,8 @@ inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data ) { if ( (unsigned) latch >= reg_count ) { - #ifdef dprintf - dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch ); + #ifdef debug_printf + debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch ); #endif return; } diff --git a/game-music-emu/gme/Nsf_Emu.cpp b/game-music-emu/gme/Nsf_Emu.cpp index 59d9b98cf..eab4bfbfd 100644 --- a/game-music-emu/gme/Nsf_Emu.cpp +++ b/game-music-emu/gme/Nsf_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Nsf_Emu.h" @@ -31,8 +31,10 @@ int const fme7_flag = 0x20; long const clock_divisor = 12; -Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = { -1.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 }; -Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 }; +Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = + Music_Emu::make_equalizer( -1.0, 80 ); +Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = + Music_Emu::make_equalizer( -15.0, 80 ); int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr ) { @@ -442,7 +444,7 @@ void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data ) // memory mapper? if ( addr == 0xFFF8 ) return; - dprintf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data ); + debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data ); } #endif } diff --git a/game-music-emu/gme/Nsf_Emu.h b/game-music-emu/gme/Nsf_Emu.h index fcce66a1e..0b001686c 100644 --- a/game-music-emu/gme/Nsf_Emu.h +++ b/game-music-emu/gme/Nsf_Emu.h @@ -1,6 +1,6 @@ // Nintendo NES/Famicom NSF music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef NSF_EMU_H #define NSF_EMU_H diff --git a/game-music-emu/gme/Nsfe_Emu.cpp b/game-music-emu/gme/Nsfe_Emu.cpp index a81b18865..824a1a240 100644 --- a/game-music-emu/gme/Nsfe_Emu.cpp +++ b/game-music-emu/gme/Nsfe_Emu.cpp @@ -1,6 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ - -#define _CRT_SECURE_NO_WARNINGS +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Nsfe_Emu.h" @@ -37,7 +35,7 @@ inline void Nsfe_Info::unload() void Nsfe_Info::disable_playlist( bool b ) { playlist_disabled = b; - info.track_count = (byte)playlist.size(); + info.track_count = playlist.size(); if ( !info.track_count || playlist_disabled ) info.track_count = actual_track_count_; } @@ -137,7 +135,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) blargg_long size = get_le32( block_header [0] ); blargg_long tag = get_le32( block_header [1] ); - //dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) ); + //debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) ); switch ( tag ) { @@ -173,7 +171,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) blargg_vector chars; blargg_vector strs; RETURN_ERR( read_strs( in, size, chars, strs ) ); - int n = (int)strs.size(); + int n = strs.size(); if ( n > 3 ) copy_str( strs [3], info.dumper, sizeof info.dumper ); @@ -192,7 +190,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) case BLARGG_4CHAR('e','m','i','t'): RETURN_ERR( track_times.resize( size / 4 ) ); - RETURN_ERR( in.read( track_times.begin(), (long)track_times.size() * 4 ) ); + RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) ); break; case BLARGG_4CHAR('l','b','l','t'): diff --git a/game-music-emu/gme/Nsfe_Emu.h b/game-music-emu/gme/Nsfe_Emu.h index 00ac40399..32b05d55e 100644 --- a/game-music-emu/gme/Nsfe_Emu.h +++ b/game-music-emu/gme/Nsfe_Emu.h @@ -1,6 +1,6 @@ // Nintendo NES/Famicom NSFE music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef NSFE_EMU_H #define NSFE_EMU_H diff --git a/game-music-emu/gme/Sap_Apu.cpp b/game-music-emu/gme/Sap_Apu.cpp index 4ad7db11c..ecac3dafd 100644 --- a/game-music-emu/gme/Sap_Apu.cpp +++ b/game-music-emu/gme/Sap_Apu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Sap_Apu.h" @@ -30,7 +30,7 @@ static void gen_poly( blargg_ulong mask, int count, byte* out ) { // implemented using "Galios configuration" bits |= (n & 1) << b; - n = (n >> 1) ^ (mask & (blargg_ulong)-(blargg_long)(n & 1)); + n = (n >> 1) ^ (mask & -(n & 1)); } while ( b++ < 7 ); *out++ = bits; @@ -66,7 +66,7 @@ Sap_Apu_Impl::Sap_Apu_Impl() blargg_ulong rev = n & 1; for ( int i = 1; i < poly5_len; i++ ) rev |= (n >> i & 1) << (poly5_len - i); - dprintf( "poly5: 0x%08lX\n", rev ); + debug_printf( "poly5: 0x%08lX\n", rev ); } } @@ -114,7 +114,7 @@ inline void Sap_Apu::calc_periods() period = (period - 6) * divider; if ( (osc [-1].regs [1] & 0x1F) > 0x10 ) - dprintf( "Use of slave channel in 16-bit mode not supported\n" ); + debug_printf( "Use of slave channel in 16-bit mode not supported\n" ); } } osc->period = period; diff --git a/game-music-emu/gme/Sap_Apu.h b/game-music-emu/gme/Sap_Apu.h index c71ce31ed..8cdd7e50c 100644 --- a/game-music-emu/gme/Sap_Apu.h +++ b/game-music-emu/gme/Sap_Apu.h @@ -1,6 +1,6 @@ // Atari POKEY sound chip emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef SAP_APU_H #define SAP_APU_H diff --git a/game-music-emu/gme/Sap_Cpu.cpp b/game-music-emu/gme/Sap_Cpu.cpp index 10dc60618..fd9112769 100644 --- a/game-music-emu/gme/Sap_Cpu.cpp +++ b/game-music-emu/gme/Sap_Cpu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Sap_Cpu.h" @@ -889,7 +889,7 @@ imm##op: goto loop; } delayed_cli: - dprintf( "Delayed CLI not emulated\n" ); + debug_printf( "Delayed CLI not emulated\n" ); goto loop; } @@ -904,7 +904,7 @@ imm##op: s_time += delta; if ( s_time < 0 ) goto loop; - dprintf( "Delayed SEI not emulated\n" ); + debug_printf( "Delayed SEI not emulated\n" ); goto loop; } @@ -945,7 +945,7 @@ handle_brk: goto idle_done; pc++; result_ = 4; - dprintf( "BRK executed\n" ); + debug_printf( "BRK executed\n" ); interrupt: { diff --git a/game-music-emu/gme/Sap_Cpu.h b/game-music-emu/gme/Sap_Cpu.h index 433a4e3d3..ea42c7a80 100644 --- a/game-music-emu/gme/Sap_Cpu.h +++ b/game-music-emu/gme/Sap_Cpu.h @@ -1,6 +1,6 @@ // Atari 6502 CPU emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef SAP_CPU_H #define SAP_CPU_H diff --git a/game-music-emu/gme/Sap_Emu.cpp b/game-music-emu/gme/Sap_Emu.cpp index dfee3de72..cb52714f9 100644 --- a/game-music-emu/gme/Sap_Emu.cpp +++ b/game-music-emu/gme/Sap_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Sap_Emu.h" @@ -119,7 +119,7 @@ static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out char const* tag = (char const*) in; while ( in < line_end && *in > ' ' ) in++; - int tag_len = int((char const*) in - tag); + int tag_len = (char const*) in - tag; while ( in < line_end && *in <= ' ' ) in++; @@ -256,7 +256,7 @@ blargg_err_t Sap_Emu::load_mem_( byte const* in, long size ) set_warning( info.warning ); set_track_count( info.track_count ); - set_voice_count( Sap_Apu::osc_count << (int)info.stereo ); + set_voice_count( Sap_Apu::osc_count << info.stereo ); apu_impl.volume( gain() ); return setup_buffer( 1773447 ); @@ -315,8 +315,8 @@ inline void Sap_Emu::call_init( int track ) case 'C': r.a = 0x70; - r.x = (BOOST::uint8_t)(info.music_addr&0xFF); - r.y = (BOOST::uint8_t)(info.music_addr >> 8); + r.x = info.music_addr&0xFF; + r.y = info.music_addr >> 8; run_routine( info.play_addr + 3 ); r.a = 0; r.x = track; @@ -336,7 +336,7 @@ blargg_err_t Sap_Emu::start_track_( int track ) { unsigned start = get_le16( in ); unsigned end = get_le16( in + 2 ); - //dprintf( "Block $%04X-$%04X\n", start, end ); + //debug_printf( "Block $%04X-$%04X\n", start, end ); in += 4; if ( end < start ) { @@ -390,7 +390,7 @@ void Sap_Emu::cpu_write_( sap_addr_t addr, int data ) } if ( (addr & ~0x0010) != 0xD20F || data != 0x03 ) - dprintf( "Unmapped write $%04X <- $%02X\n", addr, data ); + debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data ); } inline void Sap_Emu::call_play() diff --git a/game-music-emu/gme/Sap_Emu.h b/game-music-emu/gme/Sap_Emu.h index 4878faa66..5b0dc47df 100644 --- a/game-music-emu/gme/Sap_Emu.h +++ b/game-music-emu/gme/Sap_Emu.h @@ -1,6 +1,6 @@ // Atari XL/XE SAP music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef SAP_EMU_H #define SAP_EMU_H diff --git a/game-music-emu/gme/Sms_Apu.cpp b/game-music-emu/gme/Sms_Apu.cpp index be226f8f9..b41fdec41 100644 --- a/game-music-emu/gme/Sms_Apu.cpp +++ b/game-music-emu/gme/Sms_Apu.cpp @@ -141,7 +141,7 @@ void Sms_Noise::run( blip_time_t time, blip_time_t end_time ) do { int changed = shifter + 1; - shifter = (feedback & (unsigned)-(signed)(shifter & 1)) ^ (shifter >> 1); + shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1); if ( changed & 2 ) // true if bits 0 and 1 differ { delta = -delta; diff --git a/game-music-emu/gme/Snes_Spc.cpp b/game-music-emu/gme/Snes_Spc.cpp index d23e2bbe9..de5585ffc 100644 --- a/game-music-emu/gme/Snes_Spc.cpp +++ b/game-music-emu/gme/Snes_Spc.cpp @@ -1,6 +1,6 @@ // SPC emulation support: init, sample buffering, reset, SPC loading -// snes_spc 0.9.0. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Snes_Spc.h" @@ -303,7 +303,7 @@ void Snes_Spc::set_output( sample_t* out, int size ) assert( out <= out_end ); } - dsp.set_output( out, int(out_end - out) ); + dsp.set_output( out, out_end - out ); } else { diff --git a/game-music-emu/gme/Snes_Spc.h b/game-music-emu/gme/Snes_Spc.h index 93a593cc0..d6c4e8135 100644 --- a/game-music-emu/gme/Snes_Spc.h +++ b/game-music-emu/gme/Snes_Spc.h @@ -1,6 +1,6 @@ // SNES SPC-700 APU emulator -// snes_spc 0.9.0 +// Game_Music_Emu 0.6.0 #ifndef SNES_SPC_H #define SNES_SPC_H @@ -66,10 +66,7 @@ public: // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. enum { tempo_unit = 0x100 }; void set_tempo( int ); - - enum { gain_unit = Spc_Dsp::gain_unit }; - void set_gain( int gain ); - + // SPC music files // Loads SPC data into emulator @@ -107,6 +104,22 @@ public: bool check_kon(); #endif +public: + // TODO: document + struct regs_t + { + int pc; + int a; + int x; + int y; + int psw; + int sp; + }; + regs_t& smp_regs() { return m.cpu_regs; } + + uint8_t* smp_ram() { return m.ram.ram; } + + void run_until( time_t t ) { run_until_( t ); } public: BLARGG_DISABLE_NOTHROW @@ -146,15 +159,7 @@ private: uint8_t smp_regs [2] [reg_count]; - struct - { - int pc; - int a; - int x; - int y; - int psw; - int sp; - } cpu_regs; + regs_t cpu_regs; rel_time_t dsp_time; time_t spc_time; @@ -271,8 +276,6 @@ inline void Snes_Spc::write_port( time_t t, int port, int data ) run_until_( t ) [0x10 + port] = data; } -inline void Snes_Spc::set_gain( int gain ) { dsp.set_gain( gain ); } - inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); } inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); } diff --git a/game-music-emu/gme/Spc_Cpu.cpp b/game-music-emu/gme/Spc_Cpu.cpp index d59f778da..90f60ed29 100644 --- a/game-music-emu/gme/Spc_Cpu.cpp +++ b/game-music-emu/gme/Spc_Cpu.cpp @@ -1,6 +1,6 @@ // Core SPC emulation: CPU, timers, SMP registers, memory -// snes_spc 0.9.0. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Snes_Spc.h" @@ -176,7 +176,7 @@ inline void Snes_Spc::dsp_write( int data, rel_time_t time ) if ( REGS [r_dspaddr] <= 0x7F ) dsp.write( REGS [r_dspaddr], data ); else if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to DSP register > $7F\n" ); + debug_printf( "SPC wrote to DSP register > $7F\n" ); } @@ -277,8 +277,9 @@ static unsigned char const glitch_probs [3] [256] = }; #endif -// divided into multiple functions to keep rarely-used functionality separate -// so often-used functionality can be optimized better by compiler +// Read/write handlers are divided into multiple functions to keep rarely-used +// functionality separate so often-used functionality can be optimized better +// by compiler. // If write isn't preceded by read, data has this added to it int const no_read_before_write = 0x2000; @@ -302,7 +303,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) t->next_time == time + TIMER_MUL( t, 1 ) && ((period - 1) | ~0x0F) & period ) { - //dprintf( "SPC pathological timer target write\n" ); + //debug_printf( "SPC pathological timer target write\n" ); // If the period is 3, 5, or 9, there's a probability this behavior won't occur, // based on the previous period @@ -331,7 +332,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) case r_t1out: case r_t2out: if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); + debug_printf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); if ( data < no_read_before_write / 2 ) run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; @@ -345,7 +346,7 @@ void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) case r_test: if ( (uint8_t) data != 0x0A ) - dprintf( "SPC wrote to test register\n" ); + debug_printf( "SPC wrote to test register\n" ); break; case r_control: diff --git a/game-music-emu/gme/Spc_Cpu.h b/game-music-emu/gme/Spc_Cpu.h index e1b4b17b8..4742e0990 100644 --- a/game-music-emu/gme/Spc_Cpu.h +++ b/game-music-emu/gme/Spc_Cpu.h @@ -1,4 +1,4 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ /* Copyright (C) 2004-2007 Shay Green. This module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser @@ -16,7 +16,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #if SPC_MORE_ACCURACY #define SUSPICIOUS_OPCODE( name ) ((void) 0) #else - #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) + #define SUSPICIOUS_OPCODE( name ) debug_printf( "SPC: suspicious opcode: " name "\n" ) #endif #define CPU_READ( time, offset, addr )\ @@ -69,7 +69,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define READ_PROG16( addr ) GET_LE16( ram + (addr) ) #define SET_PC( n ) (pc = ram + (n)) -#define GET_PC() (int(pc - ram)) +#define GET_PC() (pc - ram) #define READ_PC( pc ) (*(pc)) #define READ_PC16( pc ) GET_LE16( pc ) @@ -77,7 +77,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define SPC_NO_SP_WRAPAROUND 0 #define SET_SP( v ) (sp = ram + 0x101 + (v)) -#define GET_SP() (int(sp - 0x101 - ram)) +#define GET_SP() (sp - 0x101 - ram) #if SPC_NO_SP_WRAPAROUND #define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) @@ -87,7 +87,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #else #define PUSH16( data )\ {\ - int addr = int((sp -= 2) - ram);\ + int addr = (sp -= 2) - ram;\ if ( addr > 0x100 )\ {\ SET_LE16( sp, data );\ @@ -242,7 +242,7 @@ loop: BRANCH( (uint8_t) nz ) case 0x3F:{// CALL - int old_addr = int(GET_PC() + 2); + int old_addr = GET_PC() + 2; SET_PC( READ_PC16( pc ) ); PUSH16( old_addr ); goto loop; @@ -256,7 +256,7 @@ loop: } #else { - int addr = int(sp - ram); + int addr = sp - ram; SET_PC( GET_LE16( sp ) ); sp += 2; if ( addr < 0x1FF ) @@ -1184,7 +1184,7 @@ loop: { addr &= 0xFFFF; SET_PC( addr ); - dprintf( "SPC: PC wrapped around\n" ); + debug_printf( "SPC: PC wrapped around\n" ); goto loop; } } @@ -1205,7 +1205,7 @@ stop: // Uncache registers if ( GET_PC() >= 0x10000 ) - dprintf( "SPC: PC wrapped around\n" ); + debug_printf( "SPC: PC wrapped around\n" ); m.cpu_regs.pc = (uint16_t) GET_PC(); m.cpu_regs.sp = ( uint8_t) GET_SP(); m.cpu_regs.a = ( uint8_t) a; diff --git a/game-music-emu/gme/Spc_Dsp.cpp b/game-music-emu/gme/Spc_Dsp.cpp index 41c79c152..0a84bfe16 100644 --- a/game-music-emu/gme/Spc_Dsp.cpp +++ b/game-music-emu/gme/Spc_Dsp.cpp @@ -1,4 +1,4 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Spc_Dsp.h" @@ -155,7 +155,7 @@ inline void Spc_Dsp::init_counter() // counters start out with this synchronization m.counters [0] = 1; m.counters [1] = 0; - m.counters [2] = -0x20; + m.counters [2] = -0x20u; m.counters [3] = 0x0B; int n = 2; @@ -606,8 +606,8 @@ skip_brr: } // Sound out - int l = (((main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14) * m.gain) >> 8; - int r = (((main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14) * m.gain) >> 8; + int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14; + int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14; CLAMP16( l ); CLAMP16( r ); @@ -641,7 +641,6 @@ void Spc_Dsp::mute_voices( int mask ) void Spc_Dsp::init( void* ram_64k ) { m.ram = (uint8_t*) ram_64k; - set_gain( gain_unit ); mute_voices( 0 ); disable_surround( false ); set_output( 0, 0 ); diff --git a/game-music-emu/gme/Spc_Dsp.h b/game-music-emu/gme/Spc_Dsp.h index 14b131ac1..401af020a 100644 --- a/game-music-emu/gme/Spc_Dsp.h +++ b/game-music-emu/gme/Spc_Dsp.h @@ -1,12 +1,12 @@ // Fast SNES SPC-700 DSP emulator (about 3x speed of accurate one) -// snes_spc 0.9.0 +// Game_Music_Emu 0.6.0 #ifndef SPC_DSP_H #define SPC_DSP_H #include "blargg_common.h" -class Spc_Dsp { +struct Spc_Dsp { public: typedef BOOST::uint8_t uint8_t; @@ -51,10 +51,7 @@ public: // If true, prevents channels and global volumes from being phase-negated void disable_surround( bool disable = true ); - - enum { gain_unit = 0x100 }; - void set_gain( int gain ); - + // State // Resets DSP and uses supplied values to initialize registers @@ -140,7 +137,6 @@ private: // non-emulation state uint8_t* ram; // 64K shared RAM between DSP and SMP int mute_mask; - int gain; int surround_threshold; sample_t* out; sample_t* out_end; @@ -158,7 +154,7 @@ private: #include -inline int Spc_Dsp::sample_count() const { return int(m.out - m.out_begin); } +inline int Spc_Dsp::sample_count() const { return m.out - m.out_begin; } inline int Spc_Dsp::read( int addr ) const { @@ -204,8 +200,6 @@ inline void Spc_Dsp::write( int addr, int data ) } } -inline void Spc_Dsp::set_gain( int gain ) { m.gain = gain; } - inline void Spc_Dsp::disable_surround( bool disable ) { m.surround_threshold = disable ? 0 : -0x4000; diff --git a/game-music-emu/gme/Spc_Emu.cpp b/game-music-emu/gme/Spc_Emu.cpp index 7f6e72faf..b3c20f317 100644 --- a/game-music-emu/gme/Spc_Emu.cpp +++ b/game-music-emu/gme/Spc_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Spc_Emu.h" @@ -19,6 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "blargg_source.h" +// TODO: support Spc_Filter's bass + Spc_Emu::Spc_Emu() { set_type( gme_spc_type ); @@ -54,7 +56,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out ) byte const* in = begin + 8; if ( end - in > info_size ) { - dprintf( "Extra data after SPC xid6 info\n" ); + debug_printf( "Extra data after SPC xid6 info\n" ); end = in + info_size; } @@ -114,7 +116,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out ) default: if ( id < 0x01 || (id > 0x07 && id < 0x10) || (id > 0x14 && id < 0x30) || id > 0x36 ) - dprintf( "Unknown SPC xid6 block: %X\n", (int) id ); + debug_printf( "Unknown SPC xid6 block: %X\n", (int) id ); break; } if ( field ) @@ -134,7 +136,7 @@ static void get_spc_xid6( byte const* begin, long size, track_info_t* out ) { // ...but some files have no padding in = unaligned; - dprintf( "SPC info tag wasn't properly padded to align\n" ); + debug_printf( "SPC info tag wasn't properly padded to align\n" ); break; } } @@ -226,14 +228,14 @@ struct Spc_File : Gme_Info_ { RETURN_ERR( xid6.resize( xid6_size ) ); RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) ); - RETURN_ERR( in.read( xid6.begin(), (long)xid6.size() ) ); + RETURN_ERR( in.read( xid6.begin(), xid6.size() ) ); } return 0; } blargg_err_t track_info_( track_info_t* out, int ) const { - get_spc_info( header, xid6.begin(), (long)xid6.size(), out ); + get_spc_info( header, xid6.begin(), xid6.size(), out ); return 0; } }; @@ -244,12 +246,13 @@ static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; } static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 }; gme_type_t const gme_spc_type = &gme_spc_type_; + // Setup blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate ) { RETURN_ERR( apu.init() ); - apu.set_gain( (int) (gain() * Snes_Spc::gain_unit) ); + enable_accuracy( false ); if ( sample_rate != native_sample_rate ) { RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) ); @@ -258,6 +261,12 @@ blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate ) return 0; } +void Spc_Emu::enable_accuracy_( bool b ) +{ + Music_Emu::enable_accuracy_( b ); + filter.enable( b ); +} + void Spc_Emu::mute_voices_( int m ) { Music_Emu::mute_voices_( m ); @@ -277,17 +286,29 @@ blargg_err_t Spc_Emu::load_mem_( byte const* in, long size ) // Emulation -void Spc_Emu::set_tempo_( double t ) { apu.set_tempo( (int) (t * Snes_Spc::tempo_unit) ); } +void Spc_Emu::set_tempo_( double t ) +{ + apu.set_tempo( (int) (t * apu.tempo_unit) ); +} blargg_err_t Spc_Emu::start_track_( int track ) { RETURN_ERR( Music_Emu::start_track_( track ) ); resampler.clear(); + filter.clear(); RETURN_ERR( apu.load_spc( file_data, file_size ) ); + filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) ); apu.clear_echo(); return 0; } +blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] ) +{ + RETURN_ERR( apu.play( count, out ) ); + filter.run( out, count ); + return 0; +} + blargg_err_t Spc_Emu::skip_( long count ) { if ( sample_rate() != native_sample_rate ) @@ -299,7 +320,10 @@ blargg_err_t Spc_Emu::skip_( long count ) // TODO: shouldn't skip be adjusted for the 64 samples read afterwards? if ( count > 0 ) + { RETURN_ERR( apu.skip( count ) ); + filter.clear(); + } // eliminate pop due to resampler const int resampler_latency = 64; @@ -310,7 +334,7 @@ blargg_err_t Spc_Emu::skip_( long count ) blargg_err_t Spc_Emu::play_( long count, sample_t* out ) { if ( sample_rate() == native_sample_rate ) - return apu.play( count, out ); + return play_and_filter( count, out ); long remain = count; while ( remain > 0 ) @@ -319,7 +343,7 @@ blargg_err_t Spc_Emu::play_( long count, sample_t* out ) if ( remain > 0 ) { long n = resampler.max_write(); - RETURN_ERR( apu.play( n, resampler.buffer() ) ); + RETURN_ERR( play_and_filter( n, resampler.buffer() ) ); resampler.write( n ); } } diff --git a/game-music-emu/gme/Spc_Emu.h b/game-music-emu/gme/Spc_Emu.h index 0c4a7fb27..09063f123 100644 --- a/game-music-emu/gme/Spc_Emu.h +++ b/game-music-emu/gme/Spc_Emu.h @@ -1,12 +1,13 @@ // Super Nintendo SPC music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef SPC_EMU_H #define SPC_EMU_H #include "Fir_Resampler.h" #include "Music_Emu.h" #include "Snes_Spc.h" +#include "Spc_Filter.h" class Spc_Emu : public Music_Emu { public: @@ -65,11 +66,15 @@ protected: blargg_err_t skip_( long ); void mute_voices_( int ); void set_tempo_( double ); + void enable_accuracy_( bool ); private: byte const* file_data; long file_size; Fir_Resampler<24> resampler; + SPC_Filter filter; Snes_Spc apu; + + blargg_err_t play_and_filter( long count, sample_t out [] ); }; inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); } diff --git a/game-music-emu/gme/Spc_Filter.cpp b/game-music-emu/gme/Spc_Filter.cpp new file mode 100644 index 000000000..0f2d18a83 --- /dev/null +++ b/game-music-emu/gme/Spc_Filter.cpp @@ -0,0 +1,83 @@ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ + +#include "Spc_Filter.h" + +#include + +/* Copyright (C) 2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } + +SPC_Filter::SPC_Filter() +{ + enabled = true; + gain = gain_unit; + bass = bass_norm; + clear(); +} + +void SPC_Filter::run( short* io, int count ) +{ + require( (count & 1) == 0 ); // must be even + + int const gain = this->gain; + if ( enabled ) + { + int const bass = this->bass; + chan_t* c = &ch [2]; + do + { + // cache in registers + int sum = (--c)->sum; + int pp1 = c->pp1; + int p1 = c->p1; + + for ( int i = 0; i < count; i += 2 ) + { + // Low-pass filter (two point FIR with coeffs 0.25, 0.75) + int f = io [i] + p1; + p1 = io [i] * 3; + + // High-pass filter ("leaky integrator") + int delta = f - pp1; + pp1 = f; + int s = sum >> (gain_bits + 2); + sum += (delta * gain) - (sum >> bass); + + // Clamp to 16 bits + if ( (short) s != s ) + s = (s >> 31) ^ 0x7FFF; + + io [i] = (short) s; + } + + c->p1 = p1; + c->pp1 = pp1; + c->sum = sum; + ++io; + } + while ( c != ch ); + } + else if ( gain != gain_unit ) + { + short* const end = io + count; + while ( io < end ) + { + int s = (*io * gain) >> gain_bits; + if ( (short) s != s ) + s = (s >> 31) ^ 0x7FFF; + *io++ = (short) s; + } + } +} diff --git a/game-music-emu/gme/Spc_Filter.h b/game-music-emu/gme/Spc_Filter.h new file mode 100644 index 000000000..5cdcc3606 --- /dev/null +++ b/game-music-emu/gme/Spc_Filter.h @@ -0,0 +1,53 @@ +// Simple low-pass and high-pass filter to better match sound output of a SNES + +// Game_Music_Emu 0.6.0 +#ifndef SPC_FILTER_H +#define SPC_FILTER_H + +#include "blargg_common.h" + +struct SPC_Filter { +public: + + // Filters count samples of stereo sound in place. Count must be a multiple of 2. + typedef short sample_t; + void run( sample_t* io, int count ); + +// Optional features + + // Clears filter to silence + void clear(); + + // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit + // are fine, since output is clamped to 16-bit sample range. + enum { gain_unit = 0x100 }; + void set_gain( int gain ); + + // Enables/disables filtering (when disabled, gain is still applied) + void enable( bool b ); + + // Sets amount of bass (logarithmic scale) + enum { bass_none = 0 }; + enum { bass_norm = 8 }; // normal amount + enum { bass_max = 31 }; + void set_bass( int bass ); + +public: + SPC_Filter(); + BLARGG_DISABLE_NOTHROW +private: + enum { gain_bits = 8 }; + int gain; + int bass; + bool enabled; + struct chan_t { int p1, pp1, sum; }; + chan_t ch [2]; +}; + +inline void SPC_Filter::enable( bool b ) { enabled = b; } + +inline void SPC_Filter::set_gain( int g ) { gain = g; } + +inline void SPC_Filter::set_bass( int b ) { bass = b; } + +#endif diff --git a/game-music-emu/gme/Vgm_Emu.cpp b/game-music-emu/gme/Vgm_Emu.cpp index fe4be10a5..5c6bc7cda 100644 --- a/game-music-emu/gme/Vgm_Emu.cpp +++ b/game-music-emu/gme/Vgm_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Vgm_Emu.h" @@ -36,8 +36,7 @@ Vgm_Emu::Vgm_Emu() set_silence_lookahead( 1 ); // tracks should already be trimmed - static equalizer_t const eq = { -14.0, 80, 0, 0, 0, 0, 0, 0, 0, 0 }; - set_equalizer( eq ); + set_equalizer( make_equalizer( -14.0, 80 ) ); } Vgm_Emu::~Vgm_Emu() { } @@ -58,7 +57,7 @@ static byte const* skip_gd3_str( byte const* in, byte const* end ) static byte const* get_gd3_str( byte const* in, byte const* end, char* field ) { byte const* mid = skip_gd3_str( in, end ); - int len = int(mid - in) / 2 - 1; + int len = (mid - in) / 2 - 1; if ( len > 0 ) { len = min( len, (int) Gme_File::max_field_ ); @@ -109,7 +108,7 @@ byte const* Vgm_Emu::gd3_data( int* size ) const return 0; byte const* gd3 = data + header_size + gd3_offset; - long gd3_size = check_gd3_header( gd3, long(data_end - gd3) ); + long gd3_size = check_gd3_header( gd3, data_end - gd3 ); if ( !gd3_size ) return 0; @@ -185,7 +184,7 @@ struct Vgm_File : Gme_Info_ if ( gd3_size ) { RETURN_ERR( gd3.resize( gd3_size ) ); - RETURN_ERR( in.read( gd3.begin(), (long)gd3.size() ) ); + RETURN_ERR( in.read( gd3.begin(), gd3.size() ) ); } } return 0; @@ -218,8 +217,8 @@ void Vgm_Emu::set_tempo_( double t ) { vgm_rate = (long) (44100 * t + 0.5); blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 ); - //dprintf( "blip_time_factor: %ld\n", blip_time_factor ); - //dprintf( "vgm_rate: %ld\n", vgm_rate ); + //debug_printf( "blip_time_factor: %ld\n", blip_time_factor ); + //debug_printf( "vgm_rate: %ld\n", vgm_rate ); // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only) //blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 ); //vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 ); diff --git a/game-music-emu/gme/Vgm_Emu.h b/game-music-emu/gme/Vgm_Emu.h index 7a82fd109..65895afaa 100644 --- a/game-music-emu/gme/Vgm_Emu.h +++ b/game-music-emu/gme/Vgm_Emu.h @@ -1,6 +1,6 @@ // Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef VGM_EMU_H #define VGM_EMU_H diff --git a/game-music-emu/gme/Vgm_Emu_Impl.cpp b/game-music-emu/gme/Vgm_Emu_Impl.cpp index a2d7c93e5..60dc099fe 100644 --- a/game-music-emu/gme/Vgm_Emu_Impl.cpp +++ b/game-music-emu/gme/Vgm_Emu_Impl.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Vgm_Emu.h" @@ -244,7 +244,7 @@ int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t* int pairs = min_pairs; while ( (pairs = to_fm_time( vgm_time )) < min_pairs ) vgm_time++; - //dprintf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs ); + //debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs ); if ( ym2612.enabled() ) { diff --git a/game-music-emu/gme/Vgm_Emu_Impl.h b/game-music-emu/gme/Vgm_Emu_Impl.h index 4d387d090..b50094a01 100644 --- a/game-music-emu/gme/Vgm_Emu_Impl.h +++ b/game-music-emu/gme/Vgm_Emu_Impl.h @@ -1,6 +1,6 @@ // Low-level parts of Vgm_Emu -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef VGM_EMU_IMPL_H #define VGM_EMU_IMPL_H diff --git a/game-music-emu/gme/Ym2413_Emu.cpp b/game-music-emu/gme/Ym2413_Emu.cpp index ede673045..d1c7a71b1 100644 --- a/game-music-emu/gme/Ym2413_Emu.cpp +++ b/game-music-emu/gme/Ym2413_Emu.cpp @@ -1,7 +1,7 @@ // Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Ym2413_Emu.h" diff --git a/game-music-emu/gme/Ym2413_Emu.h b/game-music-emu/gme/Ym2413_Emu.h index 98a2a48e1..53ce38a96 100644 --- a/game-music-emu/gme/Ym2413_Emu.h +++ b/game-music-emu/gme/Ym2413_Emu.h @@ -1,6 +1,6 @@ // YM2413 FM sound chip emulator interface -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef YM2413_EMU_H #define YM2413_EMU_H diff --git a/game-music-emu/gme/Ym2612_Emu.cpp b/game-music-emu/gme/Ym2612_Emu.cpp index 41ebb093d..5ea5c9a24 100644 --- a/game-music-emu/gme/Ym2612_Emu.cpp +++ b/game-music-emu/gme/Ym2612_Emu.cpp @@ -1,4 +1,4 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ // Based on Gens 2.10 ym2612.c diff --git a/game-music-emu/gme/Ym2612_Emu.h b/game-music-emu/gme/Ym2612_Emu.h index 383ac72d7..51cff6586 100644 --- a/game-music-emu/gme/Ym2612_Emu.h +++ b/game-music-emu/gme/Ym2612_Emu.h @@ -1,6 +1,6 @@ // YM2612 FM sound chip emulator interface -// Game_Music_Emu 0.5.2 +// Game_Music_Emu 0.6.0 #ifndef YM2612_EMU_H #define YM2612_EMU_H diff --git a/game-music-emu/gme/blargg_common.h b/game-music-emu/gme/blargg_common.h index e48d6469b..ed218a8da 100644 --- a/game-music-emu/gme/blargg_common.h +++ b/game-music-emu/gme/blargg_common.h @@ -15,6 +15,13 @@ #ifndef BLARGG_COMMON_H #define BLARGG_COMMON_H +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if __GNUC__ >= 3 || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + // STATIC_CAST(T,expr): Used in place of static_cast (expr) #ifndef STATIC_CAST #define STATIC_CAST(T,expr) ((T) (expr)) @@ -54,10 +61,11 @@ public: }; #ifndef BLARGG_DISABLE_NOTHROW - #if __cplusplus < 199711 - #define BLARGG_THROWS( spec ) - #else + // throw spec mandatory in ISO C++ if operator new can return NULL + #if __cplusplus >= 199711 || __GNUC__ >= 3 #define BLARGG_THROWS( spec ) throw spec + #else + #define BLARGG_THROWS( spec ) #endif #define BLARGG_DISABLE_NOTHROW \ void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ @@ -68,6 +76,7 @@ public: #define BLARGG_NEW new (std::nothrow) #endif +// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) #define BLARGG_4CHAR( a, b, c, d ) \ ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) @@ -110,18 +119,17 @@ public: #endif // blargg_long/blargg_ulong = at least 32 bits, int if it's big enough -#include -#if INT_MAX >= 0x7FFFFFFF - typedef int blargg_long; -#else +#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF typedef long blargg_long; +#else + typedef int blargg_long; #endif -#if UINT_MAX >= 0xFFFFFFFF - typedef unsigned blargg_ulong; -#else +#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF typedef unsigned long blargg_ulong; +#else + typedef unsigned blargg_ulong; #endif // BOOST::int8_t etc. @@ -171,5 +179,18 @@ public: }; #endif +#if __GNUC__ >= 3 + #define BLARGG_DEPRECATED __attribute__ ((deprecated)) +#else + #define BLARGG_DEPRECATED +#endif + +// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib. +// During development, BLARGG_PURE( x ) expands to = 0; +// virtual int func() BLARGG_PURE( { return 0; } ) +#ifndef BLARGG_PURE + #define BLARGG_PURE( def ) def +#endif + #endif #endif diff --git a/game-music-emu/gme/blargg_config.h b/game-music-emu/gme/blargg_config.h index 5967b0fbe..377dd2d8c 100644 --- a/game-music-emu/gme/blargg_config.h +++ b/game-music-emu/gme/blargg_config.h @@ -6,9 +6,22 @@ // Uncomment to use zlib for transparent decompression of gzipped files //#define HAVE_ZLIB_H -// Uncomment to support only the listed game music types. See gme_type_list.cpp -// for a list of all types. -//#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type +// Uncomment and edit list to support only the listed game music types, +// so that the others don't get linked in at all. +/* +#define GME_TYPE_LIST \ + gme_ay_type,\ + gme_gbs_type,\ + gme_gym_type,\ + gme_hes_type,\ + gme_kss_type,\ + gme_nsf_type,\ + gme_nsfe_type,\ + gme_sap_type,\ + gme_spc_type,\ + gme_vgm_type,\ + gme_vgz_type +*/ // Uncomment to enable platform-specific optimizations //#define BLARGG_NONPORTABLE 1 @@ -27,5 +40,4 @@ #include "config.h" #endif - #endif diff --git a/game-music-emu/gme/blargg_endian.h b/game-music-emu/gme/blargg_endian.h index 671655654..ba09e067e 100644 --- a/game-music-emu/gme/blargg_endian.h +++ b/game-music-emu/gme/blargg_endian.h @@ -1,20 +1,20 @@ // CPU Byte Order Utilities -// Game_Music_Emu 0.5.2 #ifndef BLARGG_ENDIAN #define BLARGG_ENDIAN #include "blargg_common.h" // BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) +#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64) #define BLARGG_CPU_X86 1 #define BLARGG_CPU_CISC 1 #endif -#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) +#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \ + defined (__POWERPC__) || defined (__powerc) #define BLARGG_CPU_POWERPC 1 + #define BLARGG_CPU_RISC 1 #endif // BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only @@ -36,10 +36,10 @@ #endif #if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__mips__) || defined (__sparc__) || BLARGG_CPU_POWERPC || \ + defined (__sparc__) || BLARGG_CPU_POWERPC || \ (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) #define BLARGG_BIG_ENDIAN 1 -#else +#elif !defined (__mips__) // No endian specified; assume little-endian, since it's most common #define BLARGG_LITTLE_ENDIAN 1 #endif @@ -64,45 +64,60 @@ inline void blargg_verify_byte_order() #endif } -inline unsigned get_le16( void const* p ) { - return ((unsigned char const*) p) [1] * 0x100u + - ((unsigned char const*) p) [0]; +inline unsigned get_le16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [1] << 8 | + (unsigned) ((unsigned char const*) p) [0]; } -inline unsigned get_be16( void const* p ) { - return ((unsigned char const*) p) [0] * 0x100u + - ((unsigned char const*) p) [1]; + +inline unsigned get_be16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [0] << 8 | + (unsigned) ((unsigned char const*) p) [1]; } -inline blargg_ulong get_le32( void const* p ) { - return ((unsigned char const*) p) [3] * 0x01000000u + - ((unsigned char const*) p) [2] * 0x00010000u + - ((unsigned char const*) p) [1] * 0x00000100u + - ((unsigned char const*) p) [0]; + +inline blargg_ulong get_le32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | + (blargg_ulong) ((unsigned char const*) p) [2] << 16 | + (blargg_ulong) ((unsigned char const*) p) [1] << 8 | + (blargg_ulong) ((unsigned char const*) p) [0]; } -inline blargg_ulong get_be32( void const* p ) { - return ((unsigned char const*) p) [0] * 0x01000000u + - ((unsigned char const*) p) [1] * 0x00010000u + - ((unsigned char const*) p) [2] * 0x00000100u + - ((unsigned char const*) p) [3]; + +inline blargg_ulong get_be32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | + (blargg_ulong) ((unsigned char const*) p) [1] << 16 | + (blargg_ulong) ((unsigned char const*) p) [2] << 8 | + (blargg_ulong) ((unsigned char const*) p) [3]; } -inline void set_le16( void* p, unsigned n ) { + +inline void set_le16( void* p, unsigned n ) +{ ((unsigned char*) p) [1] = (unsigned char) (n >> 8); ((unsigned char*) p) [0] = (unsigned char) n; } -inline void set_be16( void* p, unsigned n ) { + +inline void set_be16( void* p, unsigned n ) +{ ((unsigned char*) p) [0] = (unsigned char) (n >> 8); ((unsigned char*) p) [1] = (unsigned char) n; } -inline void set_le32( void* p, blargg_ulong n ) { - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + +inline void set_le32( void* p, blargg_ulong n ) +{ ((unsigned char*) p) [0] = (unsigned char) n; + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); } -inline void set_be32( void* p, blargg_ulong n ) { - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + +inline void set_be32( void* p, blargg_ulong n ) +{ ((unsigned char*) p) [3] = (unsigned char) n; + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); } #if BLARGG_NONPORTABLE @@ -117,30 +132,41 @@ inline void set_be32( void* p, blargg_ulong n ) { #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #endif - - #if BLARGG_CPU_POWERPC && defined (__MWERKS__) - // PowerPC has special byte-reversed instructions - // to do: assumes that PowerPC is running in big-endian mode - // to do: implement for other compilers which don't support these macros - #define GET_LE16( addr ) (__lhbrx( (addr), 0 )) - #define GET_LE32( addr ) (__lwbrx( (addr), 0 )) - #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 )) - #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 )) + + #if BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + #if defined (__MWERKS__) + #define GET_LE16( addr ) (__lhbrx( addr, 0 )) + #define GET_LE32( addr ) (__lwbrx( addr, 0 )) + #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) + #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) + #elif defined (__GNUC__) + #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;}) + #define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;}) + #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) + #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) + #endif + #endif #endif #endif #ifndef GET_LE16 #define GET_LE16( addr ) get_le16( addr ) - #define GET_LE32( addr ) get_le32( addr ) #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) #define SET_LE32( addr, data ) set_le32( addr, data ) #endif #ifndef GET_BE16 #define GET_BE16( addr ) get_be16( addr ) - #define GET_BE32( addr ) get_be32( addr ) #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) #define SET_BE32( addr, data ) set_be32( addr, data ) #endif diff --git a/game-music-emu/gme/blargg_source.h b/game-music-emu/gme/blargg_source.h index 945bf3498..b011777ad 100644 --- a/game-music-emu/gme/blargg_source.h +++ b/game-music-emu/gme/blargg_source.h @@ -1,4 +1,8 @@ -// Included at the beginning of library source files, after all other #include lines +/* Included at the beginning of library source files, after all other #include lines. +Sets up helpful macros and services used in my source code. They don't need +module an annoying module prefix on their names since they are defined after +all other #include lines. */ + #ifndef BLARGG_SOURCE_H #define BLARGG_SOURCE_H @@ -16,10 +20,10 @@ // Like printf() except output goes to debug log file. Might be defined to do // nothing (not even evaluate its arguments). -// void dprintf( const char* format, ... ); -inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ +// void debug_printf( const char* format, ... ); +static inline void blargg_dprintf_( const char*, ... ) { } +#undef debug_printf +#define debug_printf (1) ? (void) 0 : blargg_dprintf_ // If enabled, evaluate expr and if false, make debug log entry with source file // and line. Meant for finding situations that should be examined further, but that @@ -42,9 +46,25 @@ inline void blargg_dprintf_( const char*, ... ) { } #undef min #undef max +#define DEF_MIN_MAX( type ) \ + static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ + static inline type max( type x, type y ) { if ( y < x ) return x; return y; } + +DEF_MIN_MAX( int ) +DEF_MIN_MAX( unsigned ) +DEF_MIN_MAX( long ) +DEF_MIN_MAX( unsigned long ) +DEF_MIN_MAX( float ) +DEF_MIN_MAX( double ) + +#undef DEF_MIN_MAX + +/* // using const references generates crappy code, and I am currenly only using these // for built-in types, so they take arguments by value +// TODO: remove +inline int min( int x, int y ) template inline T min( T x, T y ) { @@ -60,17 +80,29 @@ inline T max( T x, T y ) return y; return x; } +*/ // TODO: good idea? bad idea? #undef byte #define byte byte_ typedef unsigned char byte; +// Setup compiler defines useful for exporting required public API symbols in gme.cpp +#ifndef BLARGG_EXPORT + #if defined (_WIN32) && defined(BLARGG_BUILD_DLL) + #define BLARGG_EXPORT __declspec(dllexport) + #elif defined (LIBGME_VISIBILITY) + #define BLARGG_EXPORT __attribute__((visibility ("default"))) + #else + #define BLARGG_EXPORT + #endif +#endif + // deprecated #define BLARGG_CHECK_ALLOC CHECK_ALLOC #define BLARGG_RETURN_ERR RETURN_ERR -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check +// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check #ifdef BLARGG_SOURCE_BEGIN #include BLARGG_SOURCE_BEGIN #endif diff --git a/game-music-emu/gme/gb_cpu_io.h b/game-music-emu/gme/gb_cpu_io.h index ada99eadc..8bd69aa2d 100644 --- a/game-music-emu/gme/gb_cpu_io.h +++ b/game-music-emu/gme/gb_cpu_io.h @@ -10,9 +10,9 @@ int Gbs_Emu::cpu_read( gb_addr_t addr ) result = apu.read_register( clock(), addr ); #ifndef NDEBUG else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 ) - dprintf( "Read from unmapped memory $%.4x\n", (unsigned) addr ); + debug_printf( "Read from unmapped memory $%.4x\n", (unsigned) addr ); else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 ) - dprintf( "Unhandled I/O read 0x%4X\n", (unsigned) addr ); + debug_printf( "Unhandled I/O read 0x%4X\n", (unsigned) addr ); #endif return result; } @@ -38,7 +38,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data ) ram [offset] = 0xFF; //if ( addr == 0xFFFF ) - // dprintf( "Wrote interrupt mask\n" ); + // debug_printf( "Wrote interrupt mask\n" ); } } else if ( (addr ^ 0x2000) <= 0x2000 - 1 ) @@ -48,7 +48,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data ) #ifndef NDEBUG else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 ) { - dprintf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr ); + debug_printf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr ); } #endif } @@ -59,7 +59,7 @@ void Gbs_Emu::cpu_write( gb_addr_t addr, int data ) #define CPU_READ_FAST_( emu, addr, time, out ) \ {\ out = READ_PROG( addr );\ - if ( unsigned (addr - Gb_Apu::start_addr) <= Gb_Apu::register_count )\ + if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )\ out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\ else\ check( out == emu->cpu_read( addr ) );\ diff --git a/game-music-emu/gme/gme.cpp b/game-music-emu/gme/gme.cpp index c9154c7a4..c05f25eb4 100644 --- a/game-music-emu/gme/gme.cpp +++ b/game-music-emu/gme/gme.cpp @@ -1,9 +1,8 @@ -// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ - -#define IN_GME 1 +// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ #include "Music_Emu.h" +#include "gme_types.h" #if !GME_DISABLE_STEREO_DEPTH #include "Effects_Buffer.h" #endif @@ -24,32 +23,51 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "blargg_source.h" -#ifndef GME_TYPE_LIST - -// Default list of all supported game music types (copy this to blargg_config.h -// if you want to modify it) -#define GME_TYPE_LIST \ - gme_ay_type,\ - gme_gbs_type,\ - gme_gym_type,\ - gme_hes_type,\ - gme_kss_type,\ - gme_nsf_type,\ - gme_nsfe_type,\ - gme_sap_type,\ - gme_spc_type,\ - gme_vgm_type,\ - gme_vgz_type - -#endif - -gme_type_t const* GMEAPI gme_type_list() +BLARGG_EXPORT gme_type_t const* gme_type_list() { - static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 }; + static gme_type_t const gme_type_list_ [] = { +#ifdef GME_TYPE_LIST + GME_TYPE_LIST, +#else + #ifdef USE_GME_AY + gme_ay_type, + #endif + #ifdef USE_GME_GBS + gme_gbs_type, + #endif + #ifdef USE_GME_GYM + gme_gym_type, + #endif + #ifdef USE_GME_HES + gme_hes_type, + #endif + #ifdef USE_GME_KSS + gme_kss_type, + #endif + #ifdef USE_GME_NSF + gme_nsf_type, + #endif + #ifdef USE_GME_NSFE + gme_nsfe_type, + #endif + #ifdef USE_GME_SAP + gme_sap_type, + #endif + #ifdef USE_GME_SPC + gme_spc_type, + #endif + #ifdef USE_GME_VGM + gme_vgm_type, + gme_vgz_type, + #endif +#endif + 0 + }; + return gme_type_list_; } -const char* GMEAPI gme_identify_header( void const* header ) +BLARGG_EXPORT const char* gme_identify_header( void const* header ) { switch ( get_be32( header ) ) { @@ -78,7 +96,7 @@ static void to_uppercase( const char* in, int len, char* out ) *out = 0; // extension too long } -gme_type_t GMEAPI gme_identify_extension( const char* extension_ ) +BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ ) { char const* end = strrchr( extension_, '.' ); if ( end ) @@ -93,7 +111,7 @@ gme_type_t GMEAPI gme_identify_extension( const char* extension_ ) return 0; } -gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out ) +BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out ) { *type_out = gme_identify_extension( path ); // TODO: don't examine header if file has extension? @@ -108,7 +126,7 @@ gme_err_t GMEAPI gme_identify_file( const char* path, gme_type_t* type_out ) return 0; } -gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ) +BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ) { require( (data || !size) && out ); *out = 0; @@ -132,7 +150,7 @@ gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, in return err; } -GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int sample_rate ) +BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate ) { require( path && out ); *out = 0; @@ -169,7 +187,7 @@ GMEEXPORT gme_err_t GMEAPI gme_open_file( const char* path, Music_Emu** out, int return err; } -Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate ) +BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate ) { if ( type ) { @@ -202,27 +220,27 @@ Music_Emu* GMEAPI gme_new_emu( gme_type_t type, int rate ) return 0; } -gme_err_t GMEAPI gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); } +BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); } -gme_err_t GMEAPI gme_load_data( Music_Emu* me, void const* data, long size ) +BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size ) { Mem_File_Reader in( data, size ); return me->load( in ); } -gme_err_t GMEAPI gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data ) +BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data ) { Callback_Reader in( func, size, data ); return me->load( in ); } -void GMEAPI gme_delete( Music_Emu* me ) { delete me; } +BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; } -gme_type_t GMEAPI gme_type( Music_Emu const* me ) { return me->type(); } +BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); } -const char* GMEAPI gme_warning( Music_Emu* me ) { return me->warning(); } +BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); } -int GMEAPI gme_track_count( Music_Emu const* me ) { return me->track_count(); } +BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); } struct gme_info_t_ : gme_info_t { @@ -231,7 +249,7 @@ struct gme_info_t_ : gme_info_t BLARGG_DISABLE_NOTHROW }; -gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int track ) +BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track ) { *out = NULL; @@ -297,12 +315,12 @@ gme_err_t GMEAPI gme_track_info( Music_Emu const* me, gme_info_t** out, int trac return 0; } -void GMEAPI gme_free_info( gme_info_t* info ) +BLARGG_EXPORT void gme_free_info( gme_info_t* info ) { delete STATIC_CAST(gme_info_t_*,info); } -void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth ) +BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth ) { #if !GME_DISABLE_STEREO_DEPTH if ( me->effects_buffer ) @@ -310,24 +328,26 @@ void GMEAPI gme_set_stereo_depth( Music_Emu* me, double depth ) #endif } -void* GMEAPI gme_user_data ( Music_Emu const* me ) { return me->user_data(); } -void GMEAPI gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); } -void GMEAPI gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); } +BLARGG_EXPORT void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); } +BLARGG_EXPORT void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); } +BLARGG_EXPORT void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); } -gme_err_t GMEAPI gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); } -gme_err_t GMEAPI gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); } -gme_err_t GMEAPI gme_skip ( Music_Emu* me, long n ) { return me->skip( n ); } -void GMEAPI gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); } -int GMEAPI gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } -int GMEAPI gme_tell ( Music_Emu const* me ) { return me->tell(); } -gme_err_t GMEAPI gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } -int GMEAPI gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } -void GMEAPI gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); } -void GMEAPI gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } -void GMEAPI gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); } -void GMEAPI gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); } +BLARGG_EXPORT gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); } +BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); } +BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); } +BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } +BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); } +BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } +BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } +BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); } +BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } +BLARGG_EXPORT void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); } +BLARGG_EXPORT void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); } +BLARGG_EXPORT void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( enabled ); } +BLARGG_EXPORT void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); } +BLARGG_EXPORT int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; } -void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) +BLARGG_EXPORT void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) { Music_Emu::equalizer_t e = me->equalizer(); e.treble = eq->treble; @@ -335,16 +355,22 @@ void GMEAPI gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) me->set_equalizer( e ); } -void GMEAPI gme_equalizer( Music_Emu const* me, gme_equalizer_t* out ) +BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out ) { - gme_equalizer_t e = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gme_equalizer_t e = gme_equalizer_t(); // Default-init all fields to 0.0f e.treble = me->equalizer().treble; e.bass = me->equalizer().bass; *out = e; } -const char* GMEAPI gme_voice_name( Music_Emu const* me, int i ) +BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i ) { assert( (unsigned) i < (unsigned) me->voice_count() ); return me->voice_names() [i]; } + +BLARGG_EXPORT const char* gme_type_system( gme_type_t type ) +{ + assert( type ); + return type->system; +} diff --git a/game-music-emu/gme/gme.h b/game-music-emu/gme/gme.h index 5e9470d02..1f2a2d150 100644 --- a/game-music-emu/gme/gme.h +++ b/game-music-emu/gme/gme.h @@ -1,33 +1,15 @@ /* Game music emulator library C interface (also usable from C++) */ -/* Game_Music_Emu 0.5.2 */ +/* Game_Music_Emu 0.6.0 */ #ifndef GME_H #define GME_H -#ifdef _MSC_VER -#define GMEAPI __stdcall -#else -#define GMEAPI -#endif - -#if defined(_MSC_VER) && defined(GME_DLL) -#define GMEEXPORT __declspec(dllexport) -#define GMEIMPORT __declspec(dllimport) -#if IN_GME -#define GMEDLL GMEEXPORT -#else -#define GMEDLL GMEIMPORT -#endif -#else -#define GMEEXPORT -#define GMEIMPORT -#define GMEDLL -#endif - #ifdef __cplusplus extern "C" { #endif +#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */ + /* Error string returned by library functions, or NULL if no error (success) */ typedef const char* gme_err_t; @@ -38,38 +20,35 @@ typedef struct Music_Emu Music_Emu; /******** Basic operations ********/ /* Create emulator and load game music file/data into it. Sets *out to new emulator. */ -GMEDLL gme_err_t GMEAPI gme_open_file( const char path [], Music_Emu** out, int sample_rate ); +gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate ); /* Number of tracks available */ -GMEDLL int GMEAPI gme_track_count( Music_Emu const* ); +int gme_track_count( Music_Emu const* ); /* Start a track, where 0 is the first track */ -GMEDLL gme_err_t GMEAPI gme_start_track( Music_Emu*, int index ); +gme_err_t gme_start_track( Music_Emu*, int index ); /* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */ -GMEDLL gme_err_t GMEAPI gme_play( Music_Emu*, int count, short out [] ); - -/* Skip n samples */ -GMEDLL gme_err_t GMEAPI gme_skip( Music_Emu*, long n ); +gme_err_t gme_play( Music_Emu*, int count, short out [] ); /* Finish using emulator and free memory */ -GMEDLL void GMEAPI gme_delete( Music_Emu* ); +void gme_delete( Music_Emu* ); /******** Track position/length ********/ /* Set time to start fading track out. Once fade ends track_ended() returns true. Fade time can be changed while track is playing. */ -GMEDLL void GMEAPI gme_set_fade( Music_Emu*, int start_msec ); +void gme_set_fade( Music_Emu*, int start_msec ); /* True if a track has reached its end */ -GMEDLL int GMEAPI gme_track_ended( Music_Emu const* ); +int gme_track_ended( Music_Emu const* ); /* Number of milliseconds (1000 = one second) played since beginning of track */ -GMEDLL int GMEAPI gme_tell( Music_Emu const* ); +int gme_tell( Music_Emu const* ); /* Seek to new time in track. Seeking backwards or far forward can take a while. */ -GMEDLL gme_err_t GMEAPI gme_seek( Music_Emu*, int msec ); +gme_err_t gme_seek( Music_Emu*, int msec ); /******** Informational ********/ @@ -80,22 +59,22 @@ enum { gme_info_only = -1 }; /* Most recent warning string, or NULL if none. Clears current warning after returning. Warning is also cleared when loading a file and starting a track. */ -GMEDLL const char* GMEAPI gme_warning( Music_Emu* ); +const char* gme_warning( Music_Emu* ); /* Load m3u playlist file (must be done after loading music) */ -GMEDLL gme_err_t GMEAPI gme_load_m3u( Music_Emu*, const char path [] ); +gme_err_t gme_load_m3u( Music_Emu*, const char path [] ); /* Clear any loaded m3u playlist and any internal playlist that the music format supports (NSFE for example). */ -GMEDLL void GMEAPI gme_clear_playlist( Music_Emu* ); +void gme_clear_playlist( Music_Emu* ); /* Gets information for a particular track (length, name, author, etc.). Must be freed after use. */ typedef struct gme_info_t gme_info_t; -GMEDLL gme_err_t GMEAPI gme_track_info( Music_Emu const*, gme_info_t** out, int track ); +gme_err_t gme_track_info( Music_Emu const*, gme_info_t** out, int track ); /* Frees track information */ -GMEDLL void GMEAPI gme_free_info( gme_info_t* ); +void gme_free_info( gme_info_t* ); struct gme_info_t { @@ -127,30 +106,31 @@ struct gme_info_t /* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for GYM, SPC, and Sega Genesis VGM music */ -GMEDLL void GMEAPI gme_set_stereo_depth( Music_Emu*, double depth ); +void gme_set_stereo_depth( Music_Emu*, double depth ); /* Disable automatic end-of-track detection and skipping of silence at beginning if ignore is true */ -GMEDLL void GMEAPI gme_ignore_silence( Music_Emu*, int ignore ); +void gme_ignore_silence( Music_Emu*, int ignore ); /* Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. Track length as returned by track_info() assumes a tempo of 1.0. */ -GMEDLL void GMEAPI gme_set_tempo( Music_Emu*, double tempo ); +void gme_set_tempo( Music_Emu*, double tempo ); /* Number of voices used by currently loaded file */ -GMEDLL int GMEAPI gme_voice_count( Music_Emu const* ); +int gme_voice_count( Music_Emu const* ); /* Name of voice i, from 0 to gme_voice_count() - 1 */ -GMEDLL const char* GMEAPI gme_voice_name( Music_Emu const*, int i ); +const char* gme_voice_name( Music_Emu const*, int i ); /* Mute/unmute voice i, where voice 0 is first voice */ -GMEDLL void GMEAPI gme_mute_voice( Music_Emu*, int index, int mute ); +void gme_mute_voice( Music_Emu*, int index, int mute ); /* Set muting state of all voices at once using a bit mask, where -1 mutes all voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */ -GMEDLL void GMEAPI gme_mute_voices( Music_Emu*, int muting_mask ); +void gme_mute_voices( Music_Emu*, int muting_mask ); /* Frequency equalizer parameters (see gme.txt) */ +/* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */ typedef struct gme_equalizer_t { double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */ @@ -160,11 +140,13 @@ typedef struct gme_equalizer_t } gme_equalizer_t; /* Get current frequency equalizater parameters */ -GMEDLL void GMEAPI gme_equalizer( Music_Emu const*, gme_equalizer_t* out ); +void gme_equalizer( Music_Emu const*, gme_equalizer_t* out ); /* Change frequency equalizer parameters */ -GMEDLL void GMEAPI gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq ); +void gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq ); +/* Enables/disables most accurate sound emulation options */ +void gme_enable_accuracy( Music_Emu*, int enabled ); /******** Game music types ********/ @@ -187,17 +169,17 @@ extern const gme_type_t gme_vgz_type; /* Type of this emulator */ -GMEDLL gme_type_t GMEAPI gme_type( Music_Emu const* ); +gme_type_t gme_type( Music_Emu const* ); /* Pointer to array of all music types, with NULL entry at end. Allows a player linked to this library to support new music types without having to be updated. */ -GMEDLL gme_type_t const* GMEAPI gme_type_list(); +gme_type_t const* gme_type_list(); /* Name of game system for this music file type */ -GMEDLL const char* GMEAPI gme_type_system( gme_type_t ); +const char* gme_type_system( gme_type_t ); /* True if this music file type supports multiple tracks */ -GMEDLL int GMEAPI gme_type_multitrack( gme_type_t ); +int gme_type_multitrack( gme_type_t ); /******** Advanced file loading ********/ @@ -206,50 +188,50 @@ GMEDLL int GMEAPI gme_type_multitrack( gme_type_t ); extern const char* const gme_wrong_file_type; /* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */ -GMEDLL gme_err_t GMEAPI gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ); +gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ); /* Determine likely game music type based on first four bytes of file. Returns string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if file header is not recognized. */ -GMEDLL const char* GMEAPI gme_identify_header( void const* header ); +const char* gme_identify_header( void const* header ); /* Get corresponding music type for file path or extension passed in. */ -GMEDLL gme_type_t GMEAPI gme_identify_extension( const char path_or_extension [] ); +gme_type_t gme_identify_extension( const char path_or_extension [] ); /* Determine file type based on file's extension or header (if extension isn't recognized). Sets *type_out to type, or 0 if unrecognized or error. */ -GMEDLL gme_err_t GMEAPI gme_identify_file( const char path [], gme_type_t* type_out ); +gme_err_t gme_identify_file( const char path [], gme_type_t* type_out ); /* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need track information, pass gme_info_only for sample_rate. */ -GMEDLL Music_Emu* GMEAPI gme_new_emu( gme_type_t, int sample_rate ); +Music_Emu* gme_new_emu( gme_type_t, int sample_rate ); /* Load music file into emulator */ -GMEDLL gme_err_t GMEAPI gme_load_file( Music_Emu*, const char path [] ); +gme_err_t gme_load_file( Music_Emu*, const char path [] ); /* Load music file from memory into emulator. Makes a copy of data passed. */ -GMEDLL gme_err_t GMEAPI gme_load_data( Music_Emu*, void const* data, long size ); +gme_err_t gme_load_data( Music_Emu*, void const* data, long size ); /* Load music file using custom data reader function that will be called to read file data. Most emulators load the entire file in one read call. */ -typedef gme_err_t (GMEAPI *gme_reader_t)( void* your_data, void* out, int count ); -GMEDLL gme_err_t GMEAPI gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data ); +typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count ); +gme_err_t gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data ); /* Load m3u playlist file from memory (must be done after loading music) */ -GMEDLL gme_err_t GMEAPI gme_load_m3u_data( Music_Emu*, void const* data, long size ); +gme_err_t gme_load_m3u_data( Music_Emu*, void const* data, long size ); /******** User data ********/ /* Set/get pointer to data you want to associate with this emulator. You can use this for whatever you want. */ -GMEDLL void GMEAPI gme_set_user_data( Music_Emu*, void* new_user_data ); -GMEDLL void* GMEAPI gme_user_data( Music_Emu const* ); +void gme_set_user_data( Music_Emu*, void* new_user_data ); +void* gme_user_data( Music_Emu const* ); /* Register cleanup function to be called when deleting emulator, or NULL to clear it. Passes user_data to cleanup function. */ -typedef void (GMEAPI *gme_user_cleanup_t)( void* user_data ); -GMEDLL void GMEAPI gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func ); +typedef void (*gme_user_cleanup_t)( void* user_data ); +void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func ); #ifdef __cplusplus diff --git a/game-music-emu/gme/gme_types.h b/game-music-emu/gme/gme_types.h new file mode 100644 index 000000000..06226f4aa --- /dev/null +++ b/game-music-emu/gme/gme_types.h @@ -0,0 +1,21 @@ +#ifndef GME_TYPES_H +#define GME_TYPES_H + +/* + * This is a default gme_types.h for use when *not* using + * CMake. If CMake is in use gme_types.h.in will be + * processed instead. + */ +#define USE_GME_AY +#define USE_GME_GBS +#define USE_GME_GYM +#define USE_GME_HES +#define USE_GME_KSS +#define USE_GME_NSF +#define USE_GME_NSFE +#define USE_GME_SAP +#define USE_GME_SPC +/* VGM and VGZ are a package deal */ +#define USE_GME_VGM + +#endif /* GME_TYPES_H */ diff --git a/game-music-emu/gme/gme_types.h.in b/game-music-emu/gme/gme_types.h.in new file mode 100644 index 000000000..4829b3e16 --- /dev/null +++ b/game-music-emu/gme/gme_types.h.in @@ -0,0 +1,23 @@ +#ifndef GME_TYPES_H +#define GME_TYPES_H + +/* CMake will either define the following to 1, or #undef it, + * depending on the options passed to CMake. This is used to + * conditionally compile in the various emulator types. + * + * See gme_type_list() in gme.cpp + */ + +#cmakedefine USE_GME_AY +#cmakedefine USE_GME_GBS +#cmakedefine USE_GME_GYM +#cmakedefine USE_GME_HES +#cmakedefine USE_GME_KSS +#cmakedefine USE_GME_NSF +#cmakedefine USE_GME_NSFE +#cmakedefine USE_GME_SAP +#cmakedefine USE_GME_SPC +/* VGM and VGZ are a package deal */ +#cmakedefine USE_GME_VGM + +#endif /* GME_TYPES_H */ diff --git a/game-music-emu/gme/hes_cpu_io.h b/game-music-emu/gme/hes_cpu_io.h index b3d71dad4..ce60ce8ef 100644 --- a/game-music-emu/gme/hes_cpu_io.h +++ b/game-music-emu/gme/hes_cpu_io.h @@ -44,7 +44,7 @@ inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank ) default: if ( bank != 0xFF ) - dprintf( "Unmapped bank $%02X\n", bank ); + debug_printf( "Unmapped bank $%02X\n", bank ); return rom.unmapped(); } diff --git a/game-music-emu/gme/nes_cpu_io.h b/game-music-emu/gme/nes_cpu_io.h index 4bae37931..68ce9b6ff 100644 --- a/game-music-emu/gme/nes_cpu_io.h +++ b/game-music-emu/gme/nes_cpu_io.h @@ -34,7 +34,7 @@ int Nsf_Emu::cpu_read( nes_addr_t addr ) result = addr >> 8; // simulate open bus if ( addr != 0x2002 ) - dprintf( "Read unmapped $%.4X\n", (unsigned) addr ); + debug_printf( "Read unmapped $%.4X\n", (unsigned) addr ); exit: return result; diff --git a/game-music-emu/gme/sap_cpu_io.h b/game-music-emu/gme/sap_cpu_io.h index 8c2f6dd09..d009d0d9b 100644 --- a/game-music-emu/gme/sap_cpu_io.h +++ b/game-music-emu/gme/sap_cpu_io.h @@ -20,7 +20,7 @@ void Sap_Emu::cpu_write( sap_addr_t addr, int data ) int Sap_Emu::cpu_read( sap_addr_t addr ) { if ( (addr & 0xF900) == 0xD000 ) - dprintf( "Unmapped read $%04X\n", addr ); + debug_printf( "Unmapped read $%04X\n", addr ); return mem.ram [addr]; } #endif diff --git a/game-music-emu/readme.txt b/game-music-emu/readme.txt index e3470bfa1..b7451da9f 100644 --- a/game-music-emu/readme.txt +++ b/game-music-emu/readme.txt @@ -1,4 +1,4 @@ -Game_Music_Emu 0.5.2: Game Music Emulators +Game_Music_Emu 0.6.0: Game Music Emulators ------------------------------------------ Game_Music_Emu is a collection of video game music file emulators that support the following formats and systems: @@ -14,7 +14,7 @@ SPC Super Nintendo/Super Famicom VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro Features: -* Can be used in C and C++ code +* C interface for use in C, C++, and other compatible languages * High emphasis has been placed on making the library very easy to use * One set of common functions work with all emulators the same way * Several code examples, including music player using SDL @@ -42,8 +42,17 @@ License: GNU Lesser General Public License (LGPL) Getting Started --------------- Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and -all source files in gme/. Be sure "test.nsf" is in the same directory. -Running the program should generate the recording "out.wav". +all source files in gme/. If you have CMake 2.6 or later, execute + + run cmake + cd demo + run make + +Be sure "test.nsf" is in the same directory as the program. Running it +should generate the recording "out.wav". + +A slightly more extensive demo application is available in the player/ +directory. It requires SDL to build. Read gme.txt for more information. Post to the discussion forum for assistance. @@ -55,16 +64,17 @@ gme.txt General notes about the library changes.txt Changes made since previous releases design.txt Library design notes license.txt GNU Lesser General Public License +CMakeLists.txt CMake build rules test.nsf Test file for NSF emulator test.m3u Test m3u playlist for features.c demo demo/ basics.c Records NSF file to wave sound file - cpp_basics.cpp C++ version of basics.c features.c Demonstrates many additional features Wave_Writer.h WAVE sound file writer used for demo output Wave_Writer.cpp + CMakeLists.txt CMake build rules player/ Player using the SDL multimedia library player.cpp Simple music player with waveform display @@ -72,22 +82,13 @@ player/ Player using the SDL multimedia library Music_Player.h Audio_Scope.cpp Audio waveform scope Audio_Scope.h + CMakeLists.txt CMake build rules gme/ blargg_config.h Library configuration (modify this file as needed) - gme.h C interface (also usable in C++, and simpler too) + gme.h Library interface header file gme.cpp - - Gme_File.h File loading and track information - Music_Emu.h Track playback and adjustments - Data_Reader.h Custom data readers - - Effects_Buffer.h Sound buffer with stereo echo and panning - Effects_Buffer.cpp - - M3u_Playlist.h M3U playlist support - M3u_Playlist.cpp Ay_Emu.h ZX Spectrum AY emulator Ay_Emu.cpp @@ -113,7 +114,7 @@ gme/ Hes_Cpu.h hes_cpu_io.h Hes_Emu.cpp - + Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator Kss_Emu.cpp Kss_Cpu.cpp @@ -180,26 +181,36 @@ gme/ Dual_Resampler.h Fir_Resampler.cpp Fir_Resampler.h - + + M3u_Playlist.h M3U playlist support + M3u_Playlist.cpp + + Effects_Buffer.h Sound buffer with stereo echo and panning + Effects_Buffer.cpp + blargg_common.h Common files needed by all emulators blargg_endian.h blargg_source.h Blip_Buffer.cpp Blip_Buffer.h + Gme_File.h Gme_File.cpp + Music_Emu.h Music_Emu.cpp Classic_Emu.h Classic_Emu.cpp Multi_Buffer.h Multi_Buffer.cpp + Data_Reader.h Data_Reader.cpp + + CMakeLists.txt CMake build rules Legal ----- -Game_Music_Emu library copyright (C) 2003-2006 Shay Green. -SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin. +Game_Music_Emu library copyright (C) 2003-2009 Shay Green. Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville. --- +-- Shay Green From 43fe317dbe81545685807423784e945bc1ae2a74 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 16:28:29 -0500 Subject: [PATCH 158/247] Use flexible array members for structs that end with var-sized arrays - Since Clang++, G++, and VC++ all support this extension (even though it's technically officially only part of C99), use it. It lets Clang's array- bounds checker know that these are meant to be accessed out of their so-called "bounds". --- src/r_plane.cpp | 4 ++-- src/r_plane.h | 2 +- src/stringtable.cpp | 6 +++--- src/textures/textures.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 143b302e9..6572c1f0b 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -558,8 +558,8 @@ static visplane_t *new_visplane (unsigned hash) if (check == NULL) { - check = (visplane_t *)M_Malloc (sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); - memset(check, 0, sizeof(*check) + sizeof(*check->top)*(MAXWIDTH*2)); + check = (visplane_t *)M_Malloc (sizeof(*check) + 3 + sizeof(*check->top)*(MAXWIDTH*2)); + memset(check, 0, sizeof(*check) + 3 + sizeof(*check->top)*(MAXWIDTH*2)); check->bottom = check->top + MAXWIDTH+2; } else if (NULL == (freetail = freetail->next)) diff --git a/src/r_plane.h b/src/r_plane.h index 7ad711bcc..231fa3ad4 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -63,7 +63,7 @@ struct visplane_s unsigned short *bottom; // [RH] bottom and top arrays are dynamically unsigned short pad; // allocated immediately after the - unsigned short top[3]; // visplane. + unsigned short top[]; // visplane. }; typedef struct visplane_s visplane_t; diff --git a/src/stringtable.cpp b/src/stringtable.cpp index f575dca17..47cf00fae 100644 --- a/src/stringtable.cpp +++ b/src/stringtable.cpp @@ -55,7 +55,7 @@ struct FStringTable::StringEntry StringEntry *Next; char *Name; BYTE PassNum; - char String[2]; + char String[]; }; FStringTable::FStringTable () @@ -283,7 +283,7 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p } if (entry == NULL || cmpval > 0) { - entry = (StringEntry *)M_Malloc (sizeof(*entry) + strText.Len() + strName.Len()); + entry = (StringEntry *)M_Malloc (sizeof(*entry) + strText.Len() + strName.Len() + 2); entry->Next = *pentry; *pentry = entry; strcpy (entry->String, strText.GetChars()); @@ -409,7 +409,7 @@ void FStringTable::SetString (const char *name, const char *newString) size_t namelen = strlen (name); // Create a new string entry - StringEntry *entry = (StringEntry *)M_Malloc (sizeof(*entry) + newlen + namelen); + StringEntry *entry = (StringEntry *)M_Malloc (sizeof(*entry) + newlen + namelen + 2); strcpy (entry->String, newString); strcpy (entry->Name = entry->String + newlen + 1, name); entry->PassNum = 0; diff --git a/src/textures/textures.h b/src/textures/textures.h index 837c62689..da5f559ae 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -119,7 +119,7 @@ struct patch_t SWORD height; SWORD leftoffset; // pixels to the left of origin SWORD topoffset; // pixels below the origin - DWORD columnofs[8]; // only [width] used + DWORD columnofs[]; // only [width] used // the [0] is &columnofs[width] }; From fc97584c696ac4b7ab988b978f9fa5798ad21a5d Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 16:50:20 -0500 Subject: [PATCH 159/247] Disable warning C4200 on VC++ - This warning is about using zero-sized arrays in structs (aka flexible member arrays). It's standard-enough for our purposes, so don't warn about it, since neither GCC nor Clang do. --- src/doomtype.h | 4 ++++ src/textures/textures.h | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 31f96d2ab..d201ca71d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -34,6 +34,10 @@ // source files, so we can't use it. So define PATH_MAX to be what MAX_PATH // currently is: #define PATH_MAX 260 + +// Disable warning about using unsized arrays in structs. It supports it just +// fine, and so do Clang and GCC, but the latter two don't warn about it. +#pragma warning(disable:4200) #endif #include diff --git a/src/textures/textures.h b/src/textures/textures.h index da5f559ae..2992d8a46 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -107,8 +107,6 @@ struct FDoorAnimation FName CloseSound; }; - - // Patches. // A patch holds one or more columns. // Patches are used for sprites and all masked pictures, and we compose From 138e7ff749281ee33960a16b34163db4783f4919 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 17:16:40 -0500 Subject: [PATCH 160/247] Redo GME warning-silencing that was undone by commit fbddfbe57 --- game-music-emu/gme/Ay_Apu.cpp | 2 +- game-music-emu/gme/Ay_Cpu.cpp | 8 +++---- game-music-emu/gme/Ay_Emu.cpp | 6 ++--- game-music-emu/gme/Data_Reader.cpp | 8 ++++--- game-music-emu/gme/Dual_Resampler.cpp | 4 ++-- game-music-emu/gme/Fir_Resampler.cpp | 4 ++-- game-music-emu/gme/Fir_Resampler.h | 10 ++++----- game-music-emu/gme/Gb_Cpu.cpp | 8 ++++++- game-music-emu/gme/Gme_File.cpp | 4 ++-- game-music-emu/gme/Hes_Apu.cpp | 4 ++-- game-music-emu/gme/Kss_Cpu.cpp | 8 +++---- game-music-emu/gme/M3u_Playlist.cpp | 2 +- game-music-emu/gme/M3u_Playlist.h | 2 +- game-music-emu/gme/Multi_Buffer.cpp | 12 +++++----- game-music-emu/gme/Music_Emu.cpp | 2 +- game-music-emu/gme/Nsfe_Emu.cpp | 8 ++++--- game-music-emu/gme/Sap_Apu.cpp | 2 +- game-music-emu/gme/Sap_Emu.cpp | 8 +++---- game-music-emu/gme/Sms_Apu.cpp | 2 +- game-music-emu/gme/Snes_Spc.cpp | 2 +- game-music-emu/gme/Spc_Cpu.h | 8 +++---- game-music-emu/gme/Spc_Dsp.cpp | 2 +- game-music-emu/gme/Spc_Dsp.h | 2 +- game-music-emu/gme/Spc_Emu.cpp | 4 ++-- game-music-emu/gme/Vgm_Emu.cpp | 6 ++--- game-music-emu/gme/Ym2612_Emu.cpp | 32 +++++++++++++-------------- game-music-emu/gme/gme.cpp | 2 +- 27 files changed, 86 insertions(+), 76 deletions(-) diff --git a/game-music-emu/gme/Ay_Apu.cpp b/game-music-emu/gme/Ay_Apu.cpp index c1405231d..d58d839fe 100644 --- a/game-music-emu/gme/Ay_Apu.cpp +++ b/game-music-emu/gme/Ay_Apu.cpp @@ -299,7 +299,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time ) while ( ntime <= end ) // must advance *past* time to avoid hang { int changed = noise_lfsr + 1; - noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1); + noise_lfsr = ((blargg_ulong)-(blargg_long)(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1); if ( changed & 2 ) { delta = -delta; diff --git a/game-music-emu/gme/Ay_Cpu.cpp b/game-music-emu/gme/Ay_Cpu.cpp index 825320d08..cdc3947f6 100644 --- a/game-music-emu/gme/Ay_Cpu.cpp +++ b/game-music-emu/gme/Ay_Cpu.cpp @@ -469,7 +469,7 @@ possibly_out_of_time: add_hl_data: { blargg_ulong sum = rp.hl + data; data ^= rp.hl; - rp.hl = sum; + rp.hl = (uint16_t)sum; flags = (flags & (S80 | Z40 | V04)) | (sum >> 16) | (sum >> 8 & (F20 | F08)) | @@ -719,7 +719,7 @@ possibly_out_of_time: flags = (flags & (S80 | Z40 | P04)) | (temp & (F20 | F08)) | (temp >> 8); - rg.a = temp; + rg.a = (uint8_t)temp; goto loop; } @@ -1048,7 +1048,7 @@ possibly_out_of_time: blargg_ulong sum = temp + (flags & C01); flags = ~data >> 2 & N02; if ( flags ) - sum = -sum; + sum = (blargg_ulong)-(blargg_long)sum; sum += rp.hl; temp ^= rp.hl; temp ^= sum; @@ -1056,7 +1056,7 @@ possibly_out_of_time: (temp >> 8 & H10) | (sum >> 8 & (S80 | F20 | F08)) | ((temp - -0x8000) >> 14 & V04); - rp.hl = sum; + rp.hl = (uint16_t)sum; if ( (uint16_t) sum ) goto loop; flags |= Z40; diff --git a/game-music-emu/gme/Ay_Emu.cpp b/game-music-emu/gme/Ay_Emu.cpp index 43670d1bd..565559441 100644 --- a/game-music-emu/gme/Ay_Emu.cpp +++ b/game-music-emu/gme/Ay_Emu.cpp @@ -47,8 +47,8 @@ Ay_Emu::~Ay_Emu() { } static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size ) { - long pos = ptr - (byte const*) file.header; - long file_size = file.end - (byte const*) file.header; + long pos = long(ptr - (byte const*) file.header); + long file_size = long(file.end - (byte const*) file.header); assert( (unsigned long) pos <= (unsigned long) file_size - 2 ); int offset = (BOOST::int16_t) get_be16( ptr ); if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) ) @@ -207,7 +207,7 @@ blargg_err_t Ay_Emu::start_track_( int track ) if ( len > blargg_ulong (file.end - in) ) { set_warning( "Missing file data" ); - len = file.end - in; + len = unsigned(file.end - in); } //debug_printf( "addr: $%04X, len: $%04X\n", addr, len ); if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data diff --git a/game-music-emu/gme/Data_Reader.cpp b/game-music-emu/gme/Data_Reader.cpp index 5bbfbf551..67fc8aefd 100644 --- a/game-music-emu/gme/Data_Reader.cpp +++ b/game-music-emu/gme/Data_Reader.cpp @@ -1,5 +1,7 @@ // File_Extractor 0.4.0. http://www.slack.net/~ant/ +#define _CRT_SECURE_NO_WARNINGS + #include "Data_Reader.h" #include "blargg_endian.h" @@ -89,11 +91,11 @@ Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r ) in = r; } -long Remaining_Reader::remain() const { return header_end - header + in->remain(); } +long Remaining_Reader::remain() const { return long(header_end - header + in->remain()); } long Remaining_Reader::read_first( void* out, long count ) { - long first = header_end - header; + long first = long(header_end - header); if ( first ) { if ( first > count ) @@ -210,7 +212,7 @@ long Std_File_Reader::size() const long Std_File_Reader::read_avail( void* p, long s ) { - return fread( p, 1, s, (FILE*) file_ ); + return (long)fread( p, 1, s, (FILE*) file_ ); } blargg_err_t Std_File_Reader::read( void* p, long s ) diff --git a/game-music-emu/gme/Dual_Resampler.cpp b/game-music-emu/gme/Dual_Resampler.cpp index 1c2cc36e2..149f6d6af 100644 --- a/game-music-emu/gme/Dual_Resampler.cpp +++ b/game-music-emu/gme/Dual_Resampler.cpp @@ -127,8 +127,8 @@ void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out ) r = 0x7FFF - (r >> 24); in += 2; - out [0] = l; - out [1] = r; + out [0] = (dsample_t)l; + out [1] = (dsample_t)r; out += 2; } diff --git a/game-music-emu/gme/Fir_Resampler.cpp b/game-music-emu/gme/Fir_Resampler.cpp index 7a6600be8..fa426c78c 100644 --- a/game-music-emu/gme/Fir_Resampler.cpp +++ b/game-music-emu/gme/Fir_Resampler.cpp @@ -186,8 +186,8 @@ int Fir_Resampler_::avail_( blargg_long input_count ) const int Fir_Resampler_::skip_input( long count ) { - int remain = write_pos - buf.begin(); - int max_count = remain - width_ * stereo; + int remain = int(write_pos - buf.begin()); + int max_count = int(remain - width_ * stereo); if ( count > max_count ) count = max_count; diff --git a/game-music-emu/gme/Fir_Resampler.h b/game-music-emu/gme/Fir_Resampler.h index a1bb67781..6cd1c218d 100644 --- a/game-music-emu/gme/Fir_Resampler.h +++ b/game-music-emu/gme/Fir_Resampler.h @@ -31,7 +31,7 @@ public: void clear(); // Number of input samples that can be written - int max_write() const { return buf.end() - write_pos; } + int max_write() const { return int(buf.end() - write_pos); } // Pointer to place to write input samples sample_t* buffer() { return write_pos; } @@ -40,7 +40,7 @@ public: void write( long count ); // Number of input samples in buffer - int written() const { return write_pos - &buf [write_offset]; } + int written() const { return int(write_pos - &buf [write_offset]); } // Skip 'count' input samples. Returns number of samples actually skipped. int skip_input( long count ); @@ -51,7 +51,7 @@ public: int input_needed( blargg_long count ) const; // Number of output samples available - int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); } + int avail() const { return avail_( blargg_long(write_pos - &buf [width_ * stereo] )); } public: ~Fir_Resampler_(); @@ -161,11 +161,11 @@ int Fir_Resampler::read( sample_t* out_begin, blargg_long count ) imp_phase = res - remain; - int left = write_pos - in; + int left = int(write_pos - in); write_pos = &buf [left]; memmove( buf.begin(), in, left * sizeof *in ); - return out - out_begin; + return int(out - out_begin); } #endif diff --git a/game-music-emu/gme/Gb_Cpu.cpp b/game-music-emu/gme/Gb_Cpu.cpp index b0128ea4c..bfae186e9 100644 --- a/game-music-emu/gme/Gb_Cpu.cpp +++ b/game-music-emu/gme/Gb_Cpu.cpp @@ -89,6 +89,12 @@ unsigned const n_flag = 0x40; unsigned const h_flag = 0x20; unsigned const c_flag = 0x10; +#ifdef _MSC_VER +// warning C4101: 'blargg_failed_' : unreferenced local variable +// -- produced by the BOOST_STATIC_ASSERT line below +#pragma warning(disable:4101) +#endif + bool Gb_Cpu::run( blargg_long cycle_count ) { state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr; @@ -711,7 +717,7 @@ loop: temp += prev; flags &= z_flag; add_16_hl: - rp.hl = temp; + rp.hl = (uint16_t)temp; add_16_comm: flags |= (temp >> 12) & c_flag; flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag; diff --git a/game-music-emu/gme/Gme_File.cpp b/game-music-emu/gme/Gme_File.cpp index 995f56b1c..912a9adc1 100644 --- a/game-music-emu/gme/Gme_File.cpp +++ b/game-music-emu/gme/Gme_File.cpp @@ -60,8 +60,8 @@ blargg_err_t Gme_File::load_mem_( byte const* data, long size ) blargg_err_t Gme_File::load_( Data_Reader& in ) { RETURN_ERR( file_data.resize( in.remain() ) ); - RETURN_ERR( in.read( file_data.begin(), file_data.size() ) ); - return load_mem_( file_data.begin(), file_data.size() ); + RETURN_ERR( in.read( file_data.begin(), (long)file_data.size() ) ); + return load_mem_( file_data.begin(), (long)file_data.size() ); } // public load functions call this at beginning diff --git a/game-music-emu/gme/Hes_Apu.cpp b/game-music-emu/gme/Hes_Apu.cpp index 9c7f515d6..56b59dd77 100644 --- a/game-music-emu/gme/Hes_Apu.cpp +++ b/game-music-emu/gme/Hes_Apu.cpp @@ -106,10 +106,10 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time ) unsigned noise_lfsr = this->noise_lfsr; do { - int new_dac = 0x1F & -(noise_lfsr >> 1 & 1); + int new_dac = 0x1F & (unsigned)-(int)(noise_lfsr >> 1 & 1); // Implemented using "Galios configuration" // TODO: find correct LFSR algorithm - noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1)); + noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & (unsigned)-(int)(noise_lfsr & 1)); //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1)); int delta = new_dac - dac; if ( delta ) diff --git a/game-music-emu/gme/Kss_Cpu.cpp b/game-music-emu/gme/Kss_Cpu.cpp index a2068efc4..74230bf71 100644 --- a/game-music-emu/gme/Kss_Cpu.cpp +++ b/game-music-emu/gme/Kss_Cpu.cpp @@ -503,7 +503,7 @@ possibly_out_of_time: add_hl_data: { blargg_ulong sum = rp.hl + data; data ^= rp.hl; - rp.hl = sum; + rp.hl = (uint16_t)sum; flags = (flags & (S80 | Z40 | V04)) | (sum >> 16) | (sum >> 8 & (F20 | F08)) | @@ -753,7 +753,7 @@ possibly_out_of_time: flags = (flags & (S80 | Z40 | P04)) | (temp & (F20 | F08)) | (temp >> 8); - rg.a = temp; + rg.a = (uint8_t)temp; goto loop; } @@ -1085,7 +1085,7 @@ possibly_out_of_time: blargg_ulong sum = temp + (flags & C01); flags = ~data >> 2 & N02; if ( flags ) - sum = -sum; + sum = (blargg_ulong)-(blargg_long)sum; sum += rp.hl; temp ^= rp.hl; temp ^= sum; @@ -1093,7 +1093,7 @@ possibly_out_of_time: (temp >> 8 & H10) | (sum >> 8 & (S80 | F20 | F08)) | ((temp - -0x8000) >> 14 & V04); - rp.hl = sum; + rp.hl = (uint16_t)sum; if ( (uint16_t) sum ) goto loop; flags |= Z40; diff --git a/game-music-emu/gme/M3u_Playlist.cpp b/game-music-emu/gme/M3u_Playlist.cpp index bbe52b1a7..ffd7d82c3 100644 --- a/game-music-emu/gme/M3u_Playlist.cpp +++ b/game-music-emu/gme/M3u_Playlist.cpp @@ -407,7 +407,7 @@ blargg_err_t M3u_Playlist::parse() blargg_err_t M3u_Playlist::load( Data_Reader& in ) { RETURN_ERR( data.resize( in.remain() + 1 ) ); - RETURN_ERR( in.read( data.begin(), data.size() - 1 ) ); + RETURN_ERR( in.read( data.begin(), long(data.size() - 1) ) ); return parse(); } diff --git a/game-music-emu/gme/M3u_Playlist.h b/game-music-emu/gme/M3u_Playlist.h index e764cb936..fe90dd9f8 100644 --- a/game-music-emu/gme/M3u_Playlist.h +++ b/game-music-emu/gme/M3u_Playlist.h @@ -43,7 +43,7 @@ public: int repeat; // count }; entry_t const& operator [] ( int i ) const { return entries [i]; } - int size() const { return entries.size(); } + int size() const { return int(entries.size()); } void clear(); diff --git a/game-music-emu/gme/Multi_Buffer.cpp b/game-music-emu/gme/Multi_Buffer.cpp index 57f93b317..b86142f63 100644 --- a/game-music-emu/gme/Multi_Buffer.cpp +++ b/game-music-emu/gme/Multi_Buffer.cpp @@ -171,8 +171,8 @@ void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count ) BLIP_READER_NEXT( left, bass ); BLIP_READER_NEXT( right, bass ); - out [0] = l; - out [1] = r; + out [0] = (blip_sample_t)l; + out [1] = (blip_sample_t)r; out += 2; } @@ -201,8 +201,8 @@ void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count BLIP_READER_NEXT( left, bass ); BLIP_READER_NEXT( right, bass ); - out [0] = l; - out [1] = r; + out [0] = (blip_sample_t)l; + out [1] = (blip_sample_t)r; out += 2; } @@ -223,8 +223,8 @@ void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count ) s = 0x7FFF - (s >> 24); BLIP_READER_NEXT( center, bass ); - out [0] = s; - out [1] = s; + out [0] = (blip_sample_t)s; + out [1] = (blip_sample_t)s; out += 2; } diff --git a/game-music-emu/gme/Music_Emu.cpp b/game-music-emu/gme/Music_Emu.cpp index 30b25dcfc..d0dbe77a8 100644 --- a/game-music-emu/gme/Music_Emu.cpp +++ b/game-music-emu/gme/Music_Emu.cpp @@ -348,7 +348,7 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out ) { // during a run of silence, run emulator at >=2x speed so it gets ahead long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time; - while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) ) + while ( emu_time < ahead_time && !(buf_remain || emu_track_ended_) ) fill_buf(); // fill with silence diff --git a/game-music-emu/gme/Nsfe_Emu.cpp b/game-music-emu/gme/Nsfe_Emu.cpp index 824a1a240..5559bca9b 100644 --- a/game-music-emu/gme/Nsfe_Emu.cpp +++ b/game-music-emu/gme/Nsfe_Emu.cpp @@ -1,5 +1,7 @@ // Game_Music_Emu 0.6.0. http://www.slack.net/~ant/ +#define _CRT_SECURE_NO_WARNINGS + #include "Nsfe_Emu.h" #include "blargg_endian.h" @@ -35,7 +37,7 @@ inline void Nsfe_Info::unload() void Nsfe_Info::disable_playlist( bool b ) { playlist_disabled = b; - info.track_count = playlist.size(); + info.track_count = (byte)playlist.size(); if ( !info.track_count || playlist_disabled ) info.track_count = actual_track_count_; } @@ -171,7 +173,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) blargg_vector chars; blargg_vector strs; RETURN_ERR( read_strs( in, size, chars, strs ) ); - int n = strs.size(); + int n = (int)strs.size(); if ( n > 3 ) copy_str( strs [3], info.dumper, sizeof info.dumper ); @@ -190,7 +192,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) case BLARGG_4CHAR('e','m','i','t'): RETURN_ERR( track_times.resize( size / 4 ) ); - RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) ); + RETURN_ERR( in.read( track_times.begin(), (long)track_times.size() * 4 ) ); break; case BLARGG_4CHAR('l','b','l','t'): diff --git a/game-music-emu/gme/Sap_Apu.cpp b/game-music-emu/gme/Sap_Apu.cpp index ecac3dafd..daf72ed4a 100644 --- a/game-music-emu/gme/Sap_Apu.cpp +++ b/game-music-emu/gme/Sap_Apu.cpp @@ -30,7 +30,7 @@ static void gen_poly( blargg_ulong mask, int count, byte* out ) { // implemented using "Galios configuration" bits |= (n & 1) << b; - n = (n >> 1) ^ (mask & -(n & 1)); + n = (n >> 1) ^ (mask & (blargg_ulong)-(blargg_long)(n & 1)); } while ( b++ < 7 ); *out++ = bits; diff --git a/game-music-emu/gme/Sap_Emu.cpp b/game-music-emu/gme/Sap_Emu.cpp index cb52714f9..31bce6a90 100644 --- a/game-music-emu/gme/Sap_Emu.cpp +++ b/game-music-emu/gme/Sap_Emu.cpp @@ -119,7 +119,7 @@ static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out char const* tag = (char const*) in; while ( in < line_end && *in > ' ' ) in++; - int tag_len = (char const*) in - tag; + int tag_len = int((char const*) in - tag); while ( in < line_end && *in <= ' ' ) in++; @@ -256,7 +256,7 @@ blargg_err_t Sap_Emu::load_mem_( byte const* in, long size ) set_warning( info.warning ); set_track_count( info.track_count ); - set_voice_count( Sap_Apu::osc_count << info.stereo ); + set_voice_count( Sap_Apu::osc_count << (int)info.stereo ); apu_impl.volume( gain() ); return setup_buffer( 1773447 ); @@ -315,8 +315,8 @@ inline void Sap_Emu::call_init( int track ) case 'C': r.a = 0x70; - r.x = info.music_addr&0xFF; - r.y = info.music_addr >> 8; + r.x = (BOOST::uint8_t)(info.music_addr&0xFF); + r.y = (BOOST::uint8_t)(info.music_addr >> 8); run_routine( info.play_addr + 3 ); r.a = 0; r.x = track; diff --git a/game-music-emu/gme/Sms_Apu.cpp b/game-music-emu/gme/Sms_Apu.cpp index b41fdec41..be226f8f9 100644 --- a/game-music-emu/gme/Sms_Apu.cpp +++ b/game-music-emu/gme/Sms_Apu.cpp @@ -141,7 +141,7 @@ void Sms_Noise::run( blip_time_t time, blip_time_t end_time ) do { int changed = shifter + 1; - shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1); + shifter = (feedback & (unsigned)-(signed)(shifter & 1)) ^ (shifter >> 1); if ( changed & 2 ) // true if bits 0 and 1 differ { delta = -delta; diff --git a/game-music-emu/gme/Snes_Spc.cpp b/game-music-emu/gme/Snes_Spc.cpp index de5585ffc..26574223d 100644 --- a/game-music-emu/gme/Snes_Spc.cpp +++ b/game-music-emu/gme/Snes_Spc.cpp @@ -303,7 +303,7 @@ void Snes_Spc::set_output( sample_t* out, int size ) assert( out <= out_end ); } - dsp.set_output( out, out_end - out ); + dsp.set_output( out, int(out_end - out) ); } else { diff --git a/game-music-emu/gme/Spc_Cpu.h b/game-music-emu/gme/Spc_Cpu.h index 4742e0990..0ce7af7de 100644 --- a/game-music-emu/gme/Spc_Cpu.h +++ b/game-music-emu/gme/Spc_Cpu.h @@ -69,7 +69,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define READ_PROG16( addr ) GET_LE16( ram + (addr) ) #define SET_PC( n ) (pc = ram + (n)) -#define GET_PC() (pc - ram) +#define GET_PC() (int(pc - ram)) #define READ_PC( pc ) (*(pc)) #define READ_PC16( pc ) GET_LE16( pc ) @@ -77,7 +77,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define SPC_NO_SP_WRAPAROUND 0 #define SET_SP( v ) (sp = ram + 0x101 + (v)) -#define GET_SP() (sp - 0x101 - ram) +#define GET_SP() (int(sp - 0x101 - ram)) #if SPC_NO_SP_WRAPAROUND #define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) @@ -87,7 +87,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #else #define PUSH16( data )\ {\ - int addr = (sp -= 2) - ram;\ + int addr = int((sp -= 2) - ram);\ if ( addr > 0x100 )\ {\ SET_LE16( sp, data );\ @@ -256,7 +256,7 @@ loop: } #else { - int addr = sp - ram; + int addr = int(sp - ram); SET_PC( GET_LE16( sp ) ); sp += 2; if ( addr < 0x1FF ) diff --git a/game-music-emu/gme/Spc_Dsp.cpp b/game-music-emu/gme/Spc_Dsp.cpp index 0a84bfe16..ac0baed6b 100644 --- a/game-music-emu/gme/Spc_Dsp.cpp +++ b/game-music-emu/gme/Spc_Dsp.cpp @@ -155,7 +155,7 @@ inline void Spc_Dsp::init_counter() // counters start out with this synchronization m.counters [0] = 1; m.counters [1] = 0; - m.counters [2] = -0x20u; + m.counters [2] = -0x20; m.counters [3] = 0x0B; int n = 2; diff --git a/game-music-emu/gme/Spc_Dsp.h b/game-music-emu/gme/Spc_Dsp.h index 401af020a..3cec1bd91 100644 --- a/game-music-emu/gme/Spc_Dsp.h +++ b/game-music-emu/gme/Spc_Dsp.h @@ -154,7 +154,7 @@ private: #include -inline int Spc_Dsp::sample_count() const { return m.out - m.out_begin; } +inline int Spc_Dsp::sample_count() const { return int(m.out - m.out_begin); } inline int Spc_Dsp::read( int addr ) const { diff --git a/game-music-emu/gme/Spc_Emu.cpp b/game-music-emu/gme/Spc_Emu.cpp index b3c20f317..341b53f9d 100644 --- a/game-music-emu/gme/Spc_Emu.cpp +++ b/game-music-emu/gme/Spc_Emu.cpp @@ -228,14 +228,14 @@ struct Spc_File : Gme_Info_ { RETURN_ERR( xid6.resize( xid6_size ) ); RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) ); - RETURN_ERR( in.read( xid6.begin(), xid6.size() ) ); + RETURN_ERR( in.read( xid6.begin(), (long)xid6.size() ) ); } return 0; } blargg_err_t track_info_( track_info_t* out, int ) const { - get_spc_info( header, xid6.begin(), xid6.size(), out ); + get_spc_info( header, xid6.begin(), (long)xid6.size(), out ); return 0; } }; diff --git a/game-music-emu/gme/Vgm_Emu.cpp b/game-music-emu/gme/Vgm_Emu.cpp index 5c6bc7cda..0f6001aae 100644 --- a/game-music-emu/gme/Vgm_Emu.cpp +++ b/game-music-emu/gme/Vgm_Emu.cpp @@ -57,7 +57,7 @@ static byte const* skip_gd3_str( byte const* in, byte const* end ) static byte const* get_gd3_str( byte const* in, byte const* end, char* field ) { byte const* mid = skip_gd3_str( in, end ); - int len = (mid - in) / 2 - 1; + int len = int(mid - in) / 2 - 1; if ( len > 0 ) { len = min( len, (int) Gme_File::max_field_ ); @@ -108,7 +108,7 @@ byte const* Vgm_Emu::gd3_data( int* size ) const return 0; byte const* gd3 = data + header_size + gd3_offset; - long gd3_size = check_gd3_header( gd3, data_end - gd3 ); + long gd3_size = check_gd3_header( gd3, long(data_end - gd3) ); if ( !gd3_size ) return 0; @@ -184,7 +184,7 @@ struct Vgm_File : Gme_Info_ if ( gd3_size ) { RETURN_ERR( gd3.resize( gd3_size ) ); - RETURN_ERR( in.read( gd3.begin(), gd3.size() ) ); + RETURN_ERR( in.read( gd3.begin(), (long)gd3.size() ) ); } } return 0; diff --git a/game-music-emu/gme/Ym2612_Emu.cpp b/game-music-emu/gme/Ym2612_Emu.cpp index 5ea5c9a24..4f9d84271 100644 --- a/game-music-emu/gme/Ym2612_Emu.cpp +++ b/game-music-emu/gme/Ym2612_Emu.cpp @@ -11,7 +11,7 @@ #include #include -/* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */ +/* Copyright (C) 2002 Stephane Dallongeville (gens AT consolemul.com) */ /* Copyright (C) 2004-2006 Shay Green. This module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -44,9 +44,9 @@ struct slot_t int MUL; // parametre "multiple de frequence" int TL; // Total Level = volume lorsque l'enveloppe est au plus haut int TLL; // Total Level ajusted - int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression + int SLL; // Sustin Level (ajusted) = volume oEl'enveloppe termine sa premiere phase de regression int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe - int KSR; // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer + int KSR; // Key Scale Rate = cette valeur est calculee par rapport Ela frequence actuelle, elle va influer // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite ! int SEG; // Type enveloppe SSG int env_xor; @@ -58,24 +58,24 @@ struct slot_t const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR]) int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16]) int Finc; // frequency step = pas d'incrementation du compteur-frequence - // plus le pas est grand, plus la frequence est aïgu (ou haute) + // plus le pas est grand, plus la frequence est aEu (ou haute) int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ... // en fonction de la valeur de cette variable, on va appeler une fonction permettant - // de mettre à jour l'enveloppe courante. - int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe + // de mettre Ejour l'enveloppe courante. + int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir oEl'on se trouve dans l'enveloppe int Einc; // Envelope step courant int Ecmp; // Envelope counter limite pour la prochaine phase int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque - // cette valeur est egal à AR[KSR] + // cette valeur est egal EAR[KSR] int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression - // cette valeur est egal à DR[KSR] + // cette valeur est egal EDR[KSR] int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue - // cette valeur est egal à SR[KSR] + // cette valeur est egal ESR[KSR] int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement - // cette valeur est egal à RR[KSR] - int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree - // d'un autre ou carrement à la sortie de la voie + // cette valeur est egal ERR[KSR] + int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot El'entree + // d'un autre ou carrement Ela sortie de la voie int INd; // input data of the slot = donnees en entree du slot int ChgEnM; // Change envelop mask. int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO @@ -102,10 +102,10 @@ struct state_t { int TimerBase; // TimerBase calculation int Status; // YM2612 Status (timer overflow) - int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter + int TimerA; // timerA limit = valeur jusqu'Elaquelle le timer A doit compter int TimerAL; int TimerAcnt; // timerA counter = valeur courante du Timer A - int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter + int TimerB; // timerB limit = valeur jusqu'Elaquelle le timer B doit compter int TimerBL; int TimerBcnt; // timerB counter = valeur courante du Timer B int Mode; // Mode actuel des voie 3 et 6 (normal / special) @@ -1255,7 +1255,7 @@ void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out ) if ( YM2612.Mode & 3 ) run_timer( pair_count ); - // Mise à jour des pas des compteurs-frequences s'ils ont ete modifies + // Mise Ejour des pas des compteurs-frequences s'ils ont ete modifies for ( int chi = 0; chi < channel_count; chi++ ) { @@ -1277,7 +1277,7 @@ void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out ) int ksr = ch.KC [i2] >> sl.KSR_S; // keycode attenuation sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL; if (sl.KSR != ksr) // si le KSR a change alors - { // les differents taux pour l'enveloppe sont mis à jour + { // les differents taux pour l'enveloppe sont mis Ejour sl.KSR = ksr; sl.EincA = sl.AR [ksr]; diff --git a/game-music-emu/gme/gme.cpp b/game-music-emu/gme/gme.cpp index c05f25eb4..990fee345 100644 --- a/game-music-emu/gme/gme.cpp +++ b/game-music-emu/gme/gme.cpp @@ -343,7 +343,7 @@ BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } BLARGG_EXPORT void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); } BLARGG_EXPORT void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); } -BLARGG_EXPORT void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( enabled ); } +BLARGG_EXPORT void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( !!enabled ); } BLARGG_EXPORT void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); } BLARGG_EXPORT int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; } From 1d52d75fab2929dcaac4e75ebadbed253e410d40 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 17:23:18 -0500 Subject: [PATCH 161/247] Add new GME files to VC++ 2005 project --- game-music-emu/game-music-emu.vcproj | 272 ++++++++++++++------------- 1 file changed, 142 insertions(+), 130 deletions(-) diff --git a/game-music-emu/game-music-emu.vcproj b/game-music-emu/game-music-emu.vcproj index 00b05d5fd..8ded6444a 100644 --- a/game-music-emu/game-music-emu.vcproj +++ b/game-music-emu/game-music-emu.vcproj @@ -80,6 +80,69 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -703,6 +707,10 @@ RelativePath=".\gme\Gme_File.h" > + + @@ -823,6 +831,10 @@ RelativePath=".\gme\Spc_Emu.h" > + + From f429510cd1ca373f366422761800a55ce4490d8f Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 17:26:59 -0500 Subject: [PATCH 162/247] We're building GME static, so don't do any DLL magic on Win32 --- game-music-emu/gme/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game-music-emu/gme/CMakeLists.txt b/game-music-emu/gme/CMakeLists.txt index 73a14befb..10544d721 100644 --- a/game-music-emu/gme/CMakeLists.txt +++ b/game-music-emu/gme/CMakeLists.txt @@ -134,7 +134,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gme_types.h.in # On some platforms we may need to change headers or whatnot based on whether # we're building the library or merely using the library. The following is # only defined when building the library to allow us to tell which is which. -add_definitions(-DBLARGG_BUILD_DLL) +#add_definitions(-DBLARGG_BUILD_DLL) # For the gme_types.h include_directories(${CMAKE_CURRENT_BINARY_DIR}) From 940794929c2a0d31a3bc8d82354e19ead8dee8df Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 3 Apr 2014 17:51:15 -0500 Subject: [PATCH 163/247] Remove more VC++ warnings --- src/p_acs.cpp | 2 +- src/p_mobj.cpp | 2 +- src/x86.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d8fdf13d2..4909a79d6 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -7893,7 +7893,7 @@ scriptwait: if (tag != 0) secnum = P_FindSectorFromTag (tag, -1); else - secnum = P_PointInSector (x, y) - sectors; + secnum = int(P_PointInSector (x, y) - sectors); if (secnum >= 0) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 75df3bb3e..eb214279d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2138,7 +2138,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz) fixed_t oldz = mo->z; fixed_t grav = mo->GetGravity(); -// +// // check for smooth step up // if (mo->player && mo->player->mo == mo && mo->z < mo->floorz) diff --git a/src/x86.cpp b/src/x86.cpp index e03b4795e..ec36aae93 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -57,7 +57,7 @@ void CheckCPUID(CPUInfo *cpu) #if defined(_M_IX86) || defined(__i386__) // Old 486s do not have CPUID, so we must test for its presence. // This code is adapted from the samples in AMD's document - // entitled "AMD-K6™ MMX Processor Multimedia Extensions." + // entitled "AMD-K6 MMX Processor Multimedia Extensions." #ifndef __GNUC__ __asm { From 878dcdc0a46315227ee1d558ead5dbc538f34e55 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 6 Apr 2014 12:56:51 +0300 Subject: [PATCH 164/247] Fix loading of lumps from directory on OS X Use POSIX-compliant opendir() / readdir() functions instead fts_open() / fts_read() Unlike Linux version, on OS X fts_read() inserts extra slash character between source directory and traversed entry paths --- src/resourcefiles/file_directory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index e9076ae9b..024ef0633 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -198,7 +198,7 @@ int FDirectory::AddDirectory(const char *dirpath) return count; } -#elif defined(__sun) +#elif defined(__sun) || defined(__APPLE__) int FDirectory::AddDirectory(const char *dirpath) { From ca93e04de37cb9f105c7c8d0106868013b403395 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 7 Apr 2014 23:23:55 +1200 Subject: [PATCH 165/247] Added GetActorPowerupTics ACS function --- src/p_acs.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 4909a79d6..4cb34defa 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4260,6 +4260,7 @@ enum EACSFunctions ACSF_CheckFlag, ACSF_SetLineActivation, ACSF_GetLineActivation, + ACSF_GetActorPowerupTics, // ZDaemon ACSF_GetTeamScore = 19620, // (int team) @@ -5325,6 +5326,27 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } break; + case ACSF_GetActorPowerupTics: + if (argCount >= 2) + { + const PClass *powerupclass = PClass::FindClass(FBehavior::StaticLookupString(args[1])); + if (powerupclass == NULL || !RUNTIME_CLASS(APowerup)->IsAncestorOf(powerupclass)) + { + Printf("'%s' is not a type of Powerup.\n", FBehavior::StaticLookupString(args[1])); + return 0; + } + + AActor *actor = SingleActorFromTID(args[0], activator); + if (actor != NULL) + { + APowerup* powerup = (APowerup*)actor->FindInventory(powerupclass); + if (powerup != NULL) + return powerup->EffectTics; + } + return 0; + } + break; + default: break; } From 580094a7924ea586bc0c789e55d51aa3dc3f2287 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Thu, 10 Apr 2014 12:32:23 +0200 Subject: [PATCH 166/247] More editing flags PSX-inspired flags to change the render styles of monsters (and other things). --- src/doomdata.h | 12 +++++++++++- src/namedef.h | 5 +++++ src/p_mobj.cpp | 22 ++++++++++++++++++++++ src/p_udmf.cpp | 35 +++++++++++++++++++++++++++++++++++ src/p_xlat.cpp | 3 +++ wadsrc/static/xlat/defines.i | 3 ++- wadsrc/static/xlat/strife.txt | 1 + 7 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/doomdata.h b/src/doomdata.h index 55903170a..8ba831082 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -192,9 +192,10 @@ enum EMapLineFlags // These are flags that use different values internally ML_RESERVED_ETERNITY = 0x0800, // [RH] Extra flags for Strife - ML_TRANSLUCENT_STRIFE = 0x1000, ML_RAILING_STRIFE = 0x0200, ML_BLOCK_FLOATERS_STRIFE = 0x0400, + ML_TRANSPARENT_STRIFE = 0x0800, + ML_TRANSLUCENT_STRIFE = 0x1000, }; @@ -385,6 +386,15 @@ enum EMapThingFlags MTF_SECRET = 0x080000, // Secret pickup MTF_NOINFIGHTING = 0x100000, + + // PSX Doom and Doom 64 effects + + MTF_TRANS = 0x200000, // 50% alpha + MTF_ADD = 0x400000, // 100% additive + MTF_SUBTRACT = 0x800000, // 100% subtractive + MTF_SPECTRE = 0x1000000, // 25% additive + MTF_DOUBLEHEALTH = 0x2000000, // Double hit points + // BOOM and DOOM compatible versions of some of the above BTF_NOTSINGLE = 0x0010, // (TF_COOPERATIVE|TF_DEATHMATCH) diff --git a/src/namedef.h b/src/namedef.h index 644d0deb4..50853f7ce 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -373,6 +373,11 @@ xx(Friend) xx(Strifeally) xx(Standing) xx(Countsecret) +//xx(Transparent) defined below for linedefs +//xx(Additive) already defined for invisibility types +xx(Subtractive) +xx(Spectre) +xx(Doublehealth) xx(Blocking) xx(Blockmonsters) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index eb214279d..2bf242cd2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4022,6 +4022,24 @@ void AActor::HandleSpawnFlags () RenderStyle = STYLE_Translucent; alpha = TRANSLUC25; } + else if (SpawnFlags & MTF_TRANS) + { + RenderStyle = STYLE_Translucent; + alpha = TRANSLUC50; + } + else if (SpawnFlags & MTF_ADD) + { + RenderStyle = STYLE_Add; + } + else if (SpawnFlags & MTF_SUBTRACT) + { + RenderStyle = STYLE_Subtract; + } + else if (SpawnFlags & MTF_SPECTRE) + { + RenderStyle = STYLE_Add; + alpha = TRANSLUC25; + } else if (SpawnFlags & MTF_ALTSHADOW) { RenderStyle = STYLE_None; @@ -4035,6 +4053,10 @@ void AActor::HandleSpawnFlags () level.total_secrets++; } } + if (SpawnFlags & MTF_DOUBLEHEALTH) + { + health *= 2; + } } void AActor::BeginPlay () diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index fc5964737..bc58aaef7 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -632,6 +632,31 @@ public: Flag(th->flags, MTF_SECRET, key); break; + case NAME_Transparent: + CHECK_N(Zd | Zdt) + Flag(th->flags, MTF_TRANS, key); + break; + + case NAME_Additive: + CHECK_N(Zd | Zdt) + Flag(th->flags, MTF_ADD, key); + break; + + case NAME_Subtractive: + CHECK_N(Zd | Zdt) + Flag(th->flags, MTF_SUBTRACT, key); + break; + + case NAME_Spectre: + CHECK_N(Zd | Zdt) + Flag(th->flags, MTF_SPECTRE, key); + break; + + case NAME_Doublehealth: + CHECK_N(Zd | Zdt) + Flag(th->flags, MTF_DOUBLEHEALTH, key); + break; + default: if (0 == strnicmp("user_", key.GetChars(), 5)) { // Custom user key - Sets an actor's user variable directly @@ -686,6 +711,7 @@ public: { bool passuse = false; bool strifetrans = false; + bool strifetrans2 = false; FString arg0str, arg1str; memset(ld, 0, sizeof(*ld)); @@ -803,6 +829,11 @@ public: strifetrans = CheckBool(key); continue; + case NAME_Transparent: + CHECK_N(St | Zd | Zdt | Va) + strifetrans2 = CheckBool(key); + continue; + case NAME_Passuse: CHECK_N(Dm | Zd | Zdt | Va) passuse = CheckBool(key); @@ -965,6 +996,10 @@ public: { ld->Alpha = FRACUNIT * 3/4; } + if (strifetrans2 && ld->Alpha == FRACUNIT) + { + ld->Alpha = FRACUNIT * 1/4; + } if (ld->sidedef[0] == NULL) { ld->sidedef[0] = (side_t*)(intptr_t)(1); diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index 7ece27ae8..be2d154c3 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -89,6 +89,9 @@ void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) case -2: ld->Alpha = FRACUNIT*3/4; break; + case -3: + ld->Alpha = FRACUNIT / 4; + break; default: newflags |= LineFlagTranslations[i].newvalue; break; diff --git a/wadsrc/static/xlat/defines.i b/wadsrc/static/xlat/defines.i index 60d582f70..0acc2465e 100644 --- a/wadsrc/static/xlat/defines.i +++ b/wadsrc/static/xlat/defines.i @@ -239,5 +239,6 @@ enum // ML_PASSTHROUGH = -1, - ML_TRANSLUCENT = -2 + ML_TRANSLUCENT = -2, + ML_TRANSPARENT = -3, } \ No newline at end of file diff --git a/wadsrc/static/xlat/strife.txt b/wadsrc/static/xlat/strife.txt index 710fa1fad..159933c80 100644 --- a/wadsrc/static/xlat/strife.txt +++ b/wadsrc/static/xlat/strife.txt @@ -363,5 +363,6 @@ lineflag 7 = ML_DONTDRAW; lineflag 8 = ML_MAPPED; lineflag 9 = ML_RAILING; lineflag 10 = ML_BLOCK_FLOATERS; +lineflag 11 = ML_TRANSPARENT; lineflag 12 = ML_TRANSLUCENT; From 4cac599b8899abd3385eeef4bece05c619d8aedc Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Fri, 11 Apr 2014 00:58:59 +0200 Subject: [PATCH 167/247] Less flags, more generic properties --- src/actor.h | 1 + src/doomdata.h | 17 ++++----- src/namedef.h | 22 +++++++++--- src/p_enemy.cpp | 2 +- src/p_mobj.cpp | 70 ++++++++++++++++++++++--------------- src/p_udmf.cpp | 91 +++++++++++++++++++++++++++++++++++++++++-------- src/version.h | 2 +- 7 files changed, 147 insertions(+), 58 deletions(-) diff --git a/src/actor.h b/src/actor.h index f8b583101..d3cba0041 100644 --- a/src/actor.h +++ b/src/actor.h @@ -873,6 +873,7 @@ public: TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) fixed_t SpawnPoint[3]; // For nightmare respawn WORD SpawnAngle; + int StartHealth; BYTE WeaveIndexXY; // Separated from special2 because it's used by globally accessible functions. BYTE WeaveIndexZ; int skillrespawncount; diff --git a/src/doomdata.h b/src/doomdata.h index 8ba831082..9cedf8cdc 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -345,6 +345,15 @@ struct FMapThing int args[5]; int Conversation; fixed_t gravity; + fixed_t alpha; + DWORD fillcolor; + fixed_t scaleX; + fixed_t scaleY; + int health; + int score; + short pitch; + short roll; + DWORD RenderStyle; void Serialize (FArchive &); }; @@ -387,14 +396,6 @@ enum EMapThingFlags MTF_SECRET = 0x080000, // Secret pickup MTF_NOINFIGHTING = 0x100000, - // PSX Doom and Doom 64 effects - - MTF_TRANS = 0x200000, // 50% alpha - MTF_ADD = 0x400000, // 100% additive - MTF_SUBTRACT = 0x800000, // 100% subtractive - MTF_SPECTRE = 0x1000000, // 25% additive - MTF_DOUBLEHEALTH = 0x2000000, // Double hit points - // BOOM and DOOM compatible versions of some of the above BTF_NOTSINGLE = 0x0010, // (TF_COOPERATIVE|TF_DEATHMATCH) diff --git a/src/namedef.h b/src/namedef.h index 50853f7ce..017f29932 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -31,6 +31,18 @@ xx(Fuzzy) xx(Opaque) xx(Stencil) +// Render styles +xx(Normal) +xx(SoulTrans) +xx(OptFuzzy) +xx(Add) +xx(Shaded) +xx(TranslucentStencil) +xx(Shadow) +xx(Subtract) +xx(Subtractive) +xx(FillColor) + // Healingradius types xx(Mana) xx(Armor) @@ -373,11 +385,11 @@ xx(Friend) xx(Strifeally) xx(Standing) xx(Countsecret) -//xx(Transparent) defined below for linedefs -//xx(Additive) already defined for invisibility types -xx(Subtractive) -xx(Spectre) -xx(Doublehealth) +xx(Score) +xx(Roll) +xx(Scale) +xx(ScaleX) +xx(ScaleY) xx(Blocking) xx(Blockmonsters) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index df1698837..39cd0813c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2648,7 +2648,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) corpsehit->flags5 = info->flags5; corpsehit->flags6 = info->flags6; corpsehit->flags7 = info->flags7; - corpsehit->health = info->health; + corpsehit->health = corpsehit->SpawnHealth(); corpsehit->target = NULL; corpsehit->lastenemy = NULL; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2bf242cd2..291f51a94 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -219,8 +219,12 @@ void AActor::Serialize (FArchive &arc) << threshold << player << SpawnPoint[0] << SpawnPoint[1] << SpawnPoint[2] - << SpawnAngle - << skillrespawncount + << SpawnAngle; + if (SaveVersion >= 4506) + { + arc << StartHealth; + } + arc << skillrespawncount << tracer << floorclip << tid @@ -4022,24 +4026,6 @@ void AActor::HandleSpawnFlags () RenderStyle = STYLE_Translucent; alpha = TRANSLUC25; } - else if (SpawnFlags & MTF_TRANS) - { - RenderStyle = STYLE_Translucent; - alpha = TRANSLUC50; - } - else if (SpawnFlags & MTF_ADD) - { - RenderStyle = STYLE_Add; - } - else if (SpawnFlags & MTF_SUBTRACT) - { - RenderStyle = STYLE_Subtract; - } - else if (SpawnFlags & MTF_SPECTRE) - { - RenderStyle = STYLE_Add; - alpha = TRANSLUC25; - } else if (SpawnFlags & MTF_ALTSHADOW) { RenderStyle = STYLE_None; @@ -4053,10 +4039,6 @@ void AActor::HandleSpawnFlags () level.total_secrets++; } } - if (SpawnFlags & MTF_DOUBLEHEALTH) - { - health *= 2; - } } void AActor::BeginPlay () @@ -4811,11 +4793,42 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) } } + // Set various UDMF options + if (mthing->alpha != -1) + { + DPrintf("Setting alpha to %f", FIXED2FLOAT(mthing->alpha)); + mobj->alpha = mthing->alpha; + } + if (mthing->RenderStyle != STYLE_Count) + mobj->RenderStyle = (ERenderStyle)mthing->RenderStyle; + if (mthing->scaleX) + mobj->scaleX = FixedMul(mthing->scaleX, mobj->scaleX); + if (mthing->scaleY) + mobj->scaleY = FixedMul(mthing->scaleY, mobj->scaleY); + if (mthing->pitch) + mobj->pitch = ANGLE_1 * mthing->pitch; + if (mthing->roll) + mobj->roll = ANGLE_1 * mthing->roll; + if (mthing->score) + mobj->Score = mthing->score; + if (mthing->fillcolor) + mobj->fillcolor = mthing->fillcolor; + mobj->BeginPlay (); if (!(mobj->ObjectFlags & OF_EuthanizeMe)) { mobj->LevelSpawned (); } + + if (mthing->health > 0) + mobj->health *= mthing->health; + else + mobj->health = -mthing->health; + if (mthing->health == 0) + mobj->Die(NULL, NULL); + else if (mthing->health != 1) + mobj->StartHealth = mobj->health; + return mobj; } @@ -6038,18 +6051,19 @@ void AActor::SetIdle() int AActor::SpawnHealth() { - if (!(flags3 & MF3_ISMONSTER) || GetDefault()->health == 0) + int defhealth = StartHealth ? StartHealth : GetDefault()->health; + if (!(flags3 & MF3_ISMONSTER) || defhealth == 0) { - return GetDefault()->health; + return defhealth; } else if (flags & MF_FRIENDLY) { - int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_FriendlyHealth)); + int adj = FixedMul(defhealth, G_SkillProperty(SKILLP_FriendlyHealth)); return (adj <= 0) ? 1 : adj; } else { - int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_MonsterHealth)); + int adj = FixedMul(defhealth, G_SkillProperty(SKILLP_MonsterHealth)); return (adj <= 0) ? 1 : adj; } } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index bc58aaef7..ae3f94f87 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -476,6 +476,9 @@ public: memset(th, 0, sizeof(*th)); th->gravity = FRACUNIT; + th->RenderStyle = STYLE_Count; + th->alpha = -1; + th->health = 1; sc.MustGetToken('{'); while (!sc.CheckToken('}')) { @@ -632,29 +635,87 @@ public: Flag(th->flags, MTF_SECRET, key); break; - case NAME_Transparent: - CHECK_N(Zd | Zdt) - Flag(th->flags, MTF_TRANS, key); + case NAME_Renderstyle: + { + FName style = CheckString(key); + switch (style) + { + case NAME_None: + th->RenderStyle = STYLE_None; + break; + default: + case NAME_Normal: + th->RenderStyle = STYLE_Normal; + break; + case NAME_Fuzzy: + th->RenderStyle = STYLE_Fuzzy; + break; + case NAME_SoulTrans: + th->RenderStyle = STYLE_SoulTrans; + break; + case NAME_OptFuzzy: + th->RenderStyle = STYLE_OptFuzzy; + break; + case NAME_Stencil: + th->RenderStyle = STYLE_Stencil; + break; + case NAME_Translucent: + th->RenderStyle = STYLE_Translucent; + break; + case NAME_Add: + case NAME_Additive: + th->RenderStyle = STYLE_Add; + break; + case NAME_Shaded: + th->RenderStyle = STYLE_Shaded; + break; + case NAME_TranslucentStencil: + th->RenderStyle = STYLE_TranslucentStencil; + break; + case NAME_Shadow: + th->RenderStyle = STYLE_Shadow; + break; + case NAME_Subtract: + case NAME_Subtractive: + th->RenderStyle = STYLE_Subtract; + break; + } + } break; - case NAME_Additive: - CHECK_N(Zd | Zdt) - Flag(th->flags, MTF_ADD, key); + case NAME_Alpha: + th->alpha = CheckFixed(key); break; - case NAME_Subtractive: - CHECK_N(Zd | Zdt) - Flag(th->flags, MTF_SUBTRACT, key); + case NAME_FillColor: + th->fillcolor = CheckInt(key); + + case NAME_Health: + th->health = CheckInt(key); break; - case NAME_Spectre: - CHECK_N(Zd | Zdt) - Flag(th->flags, MTF_SPECTRE, key); + case NAME_Score: + th->score = CheckInt(key); break; - case NAME_Doublehealth: - CHECK_N(Zd | Zdt) - Flag(th->flags, MTF_DOUBLEHEALTH, key); + case NAME_Pitch: + th->pitch = (short)CheckInt(key); + break; + + case NAME_Roll: + th->roll = (short)CheckInt(key); + break; + + case NAME_ScaleX: + th->scaleX = CheckFixed(key); + break; + + case NAME_ScaleY: + th->scaleY = CheckFixed(key); + break; + + case NAME_Scale: + th->scaleX = th->scaleY = CheckFixed(key); break; default: diff --git a/src/version.h b/src/version.h index 1e328b312..27bfe1021 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4505 +#define SAVEVER 4506 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) From 101107b1e5ea3f498747f31291d10694d7dbe09f Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Sat, 12 Apr 2014 10:55:10 +0200 Subject: [PATCH 168/247] Updated documentation --- specs/udmf_zdoom.txt | 20 ++++++++++++++++++++ src/p_udmf.cpp | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 3241bf4c8..d7face672 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -117,6 +117,8 @@ Note: All fields default to false unless mentioned otherwise. locknumber = ; // Line special is locked arg0str = ; // Alternate string-based version of arg0 + transparent = ; // true = line is a Strife transparent line (alpha 0.25) + * Note about arg0str For lines with ACS specials (80-86 and 226), if arg0str is present and non-null, it @@ -207,6 +209,21 @@ Note: All fields default to false unless mentioned otherwise. arg0str = ; // Alternate string-based version of arg0 gravity = ; // Set per-actor gravity. Positive values are multiplied with the class's property, // negative values are used as their absolute. Default = 1.0. + + health = ; // Set per-actor health. Positive values are multiplied with the class's property, + // negative values are used as their absolute. Default = 1. + + renderstyle = ; // Set per-actor render style, overriding the class default. Possible values can be "normal", + // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", + // "translucent", "fuzzy", "optfuzzy", "soultrans". Default is an empty string for no change. + fillcolor = ; // Fill color used by the "stencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. + alpha = ; // Translucency of this actor (if applicable to renderstyle), default is 1.0. + score = ; // Score value of this actor, overriding the class default if not null. Default = 0. + pitch = ; // Pitch of thing in degrees. Default = 0 (horizontal). + roll = ; // Pitch of thing in degrees. Default = 0 (horizontal). + scalex = ; // Vertical scaling on thing. Default = 0 (ignored). + scaley = ; // Horizontal scaling on thing. Default = 0 (ignored). + scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). * Note about arg0str @@ -335,6 +352,9 @@ Added arg0str thing property. 1.21 09.08.2013 Added waterzone sector property. +1.22 12.04.2014 +Added transparent line property (to be folded back to core UDMF standard), and health, score, renderstyle, fillcolor, alpha, scale, scalex, scaley, pitch and roll thing properties. + =============================================================================== EOF =============================================================================== diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index ae3f94f87..6af777b36 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -643,7 +643,6 @@ public: case NAME_None: th->RenderStyle = STYLE_None; break; - default: case NAME_Normal: th->RenderStyle = STYLE_Normal; break; @@ -679,6 +678,8 @@ public: case NAME_Subtractive: th->RenderStyle = STYLE_Subtract; break; + default: + break; } } break; From 42708386138aea39d712df72b80a410e92243b4a Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 12 Apr 2014 22:02:19 +1200 Subject: [PATCH 169/247] CANRAISE state definition CANRAISE state for allowing a monster to be resurrected without an infinite frame --- src/info.h | 5 +++++ src/p_enemy.cpp | 5 +++-- src/thingdef/thingdef_states.cpp | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/info.h b/src/info.h index 24bbb5fea..9a316c78d 100644 --- a/src/info.h +++ b/src/info.h @@ -76,6 +76,7 @@ struct FState BYTE SameFrame:1; // Ignore Frame (except when spawning actor) BYTE Fast:1; BYTE NoDelay:1; // Spawn states executes its action normally + BYTE CanRaise:1; // Allows a monster to be resurrected without waiting for an infinate frame int ParameterIndex; inline int GetFrame() const @@ -114,6 +115,10 @@ struct FState { return NoDelay; } + inline bool GetCanRaise() const + { + return CanRaise; + } inline void SetFrame(BYTE frame) { Frame = frame - 'A'; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index df1698837..8b1dd951b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2527,8 +2527,9 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) if (!(corpsehit->flags & MF_CORPSE) ) continue; // not a monster - if (corpsehit->tics != -1) - continue; // not lying still yet + if (corpsehit->tics != -1 && // not lying still yet + !corpsehit->state->GetCanRaise()) // or not ready to be raised yet + continue; raisestate = corpsehit->FindState(NAME_Raise); if (raisestate == NULL) diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 1d643e33c..5cc2de1c0 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -313,6 +313,11 @@ do_stop: sc.MustGetStringName(")"); continue; } + if (sc.Compare("CANRAISE")) + { + state.CanRaise = true; + continue; + } // Make the action name lowercase strlwr (sc.String); From 745b147d185f38d710649c61aceac68a93fbbc3e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Apr 2014 16:40:53 +0200 Subject: [PATCH 170/247] - fixed typo in xlat files (they don't use exactly C syntax.) --- wadsrc/static/xlat/defines.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/xlat/defines.i b/wadsrc/static/xlat/defines.i index 0acc2465e..04c8b21cc 100644 --- a/wadsrc/static/xlat/defines.i +++ b/wadsrc/static/xlat/defines.i @@ -240,5 +240,5 @@ enum // ML_PASSTHROUGH = -1, ML_TRANSLUCENT = -2, - ML_TRANSPARENT = -3, + ML_TRANSPARENT = -3 } \ No newline at end of file From e5578934ad711fa2e38369f1bbe9e1eb36fc191e Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 17:16:33 +0200 Subject: [PATCH 171/247] Init new non-0 fields for non-UDMF maps. --- src/p_mobj.cpp | 3 --- src/p_setup.cpp | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 291f51a94..2a26d7ef0 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4795,10 +4795,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) // Set various UDMF options if (mthing->alpha != -1) - { - DPrintf("Setting alpha to %f", FIXED2FLOAT(mthing->alpha)); mobj->alpha = mthing->alpha; - } if (mthing->RenderStyle != STYLE_Count) mobj->RenderStyle = (ERenderStyle)mthing->RenderStyle; if (mthing->scaleX) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 315da4ffc..b2d007f97 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1764,6 +1764,9 @@ void P_LoadThings (MapData * map) mti[i].Conversation = 0; mti[i].SkillFilter = MakeSkill(flags); mti[i].ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes + mti[i].RenderStyle = STYLE_Count; + mti[i].alpha = -1; + mti[i].health = 1; flags &= ~MTF_SKILLMASK; mti[i].flags = (short)((flags & 0xf) | 0x7e0); if (gameinfo.gametype == GAME_Strife) From 8e3360453fa5d90cbfda05e28817060d8f98dde3 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 17:18:55 +0200 Subject: [PATCH 172/247] Hexen too. --- src/p_setup.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index b2d007f97..f56d761f2 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1840,6 +1840,9 @@ void P_LoadThings2 (MapData * map) mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); mti[i].Conversation = 0; mti[i].gravity = FRACUNIT; + mti[i].RenderStyle = STYLE_Count; + mti[i].alpha = -1; + mti[i].health = 1; } delete[] mtp; } From 6f2fd8edbfec14a62a6a96ddf3b1050ab3ad9bcb Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 17:22:56 +0200 Subject: [PATCH 173/247] Hexen also needs to init 0 fields. --- src/p_setup.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f56d761f2..c14fcdec0 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1843,6 +1843,7 @@ void P_LoadThings2 (MapData * map) mti[i].RenderStyle = STYLE_Count; mti[i].alpha = -1; mti[i].health = 1; + mti[i].fillcolor = 0 = mti[i].scaleX = mti[i].scaleY = mti[i].score = 0; } delete[] mtp; } From c54f5571ea174c19022354eb35dd3704d08f5ac8 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 17:24:01 +0200 Subject: [PATCH 174/247] Typo. --- src/p_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index c14fcdec0..77b9b077b 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1843,7 +1843,7 @@ void P_LoadThings2 (MapData * map) mti[i].RenderStyle = STYLE_Count; mti[i].alpha = -1; mti[i].health = 1; - mti[i].fillcolor = 0 = mti[i].scaleX = mti[i].scaleY = mti[i].score = 0; + mti[i].fillcolor = mti[i].scaleX = mti[i].scaleY = mti[i].score = 0; } delete[] mtp; } From 83182b703de94b7645026db155e979bf0535d778 Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 21:01:49 +0200 Subject: [PATCH 175/247] Added slow monsters, the inverse of fast monsters This is a skill setting only, no "always slow" or "never slow" actor flags, and no DM flags. --- src/actor.h | 1 + src/g_level.h | 2 ++ src/g_skill.cpp | 9 +++++++++ src/info.h | 1 + src/p_mobj.cpp | 11 ++++++++++- src/thingdef/thingdef_states.cpp | 5 +++++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/actor.h b/src/actor.h index d3cba0041..21057d86c 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1008,6 +1008,7 @@ public: bool SetState (FState *newstate, bool nofunction=false); virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true); bool isFast(); + bool isSlow(); void SetIdle(); void ClearCounters(); diff --git a/src/g_level.h b/src/g_level.h index c431b9695..4a84e6871 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -554,6 +554,7 @@ enum ESkillProperty SKILLP_NoPain, SKILLP_ArmorFactor, SKILLP_EasyKey, + SKILLP_SlowMonsters, }; int G_SkillProperty(ESkillProperty prop); const char * G_SkillName(); @@ -568,6 +569,7 @@ struct FSkillInfo fixed_t AmmoFactor, DoubleAmmoFactor, DropAmmoFactor; fixed_t DamageFactor; bool FastMonsters; + bool SlowMonsters; bool DisableCheats; bool AutoUseHealth; diff --git a/src/g_skill.cpp b/src/g_skill.cpp index 46b9a1702..ddfdbb4cc 100644 --- a/src/g_skill.cpp +++ b/src/g_skill.cpp @@ -64,6 +64,7 @@ void FMapInfoParser::ParseSkill () skill.DropAmmoFactor = -1; skill.DamageFactor = FRACUNIT; skill.FastMonsters = false; + skill.SlowMonsters = false; skill.DisableCheats = false; skill.EasyBossBrain = false; skill.EasyKey = false; @@ -118,6 +119,10 @@ void FMapInfoParser::ParseSkill () { skill.FastMonsters = true; } + else if (sc.Compare ("slowmonsters")) + { + skill.SlowMonsters = true; + } else if (sc.Compare ("disablecheats")) { skill.DisableCheats = true; @@ -336,6 +341,9 @@ int G_SkillProperty(ESkillProperty prop) case SKILLP_FastMonsters: return AllSkills[gameskill].FastMonsters || (dmflags & DF_FAST_MONSTERS); + case SKILLP_SlowMonsters: + return AllSkills[gameskill].SlowMonsters; + case SKILLP_Respawn: if (dmflags & DF_MONSTERS_RESPAWN && AllSkills[gameskill].RespawnCounter==0) return TICRATE * gameinfo.defaultrespawntime; @@ -433,6 +441,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other) DropAmmoFactor = other.DropAmmoFactor; DamageFactor = other.DamageFactor; FastMonsters = other.FastMonsters; + SlowMonsters = other.SlowMonsters; DisableCheats = other.DisableCheats; AutoUseHealth = other.AutoUseHealth; EasyBossBrain = other.EasyBossBrain; diff --git a/src/info.h b/src/info.h index 9a316c78d..51c4bd629 100644 --- a/src/info.h +++ b/src/info.h @@ -77,6 +77,7 @@ struct FState BYTE Fast:1; BYTE NoDelay:1; // Spawn states executes its action normally BYTE CanRaise:1; // Allows a monster to be resurrected without waiting for an infinate frame + BYTE Slow:1; // Inverse of fast int ParameterIndex; inline int GetFrame() const diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 291f51a94..f82cf9bce 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -405,7 +405,7 @@ bool AActor::InStateSequence(FState * newstate, FState * basestate) // // Get the actual duration of the next state // We are using a state flag now to indicate a state that should be -// accelerated in Fast mode. +// accelerated in Fast mode or slowed in Slow mode. // //========================================================================== @@ -416,6 +416,10 @@ int AActor::GetTics(FState * newstate) { return tics - (tics>>1); } + else if (isSlow() && newstate->Slow) + { + return tics<<1; + } return tics; } @@ -4082,6 +4086,11 @@ bool AActor::isFast() return !!G_SkillProperty(SKILLP_FastMonsters); } +bool AActor::isSlow() +{ + return !!G_SkillProperty(SKILLP_SlowMonsters); +} + void AActor::Activate (AActor *activator) { if ((flags3 & MF3_ISMONSTER) && (health > 0 || (flags & MF_ICECORPSE))) diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp index 5cc2de1c0..6a28e54cd 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -275,6 +275,11 @@ do_stop: state.Fast = true; continue; } + if (sc.Compare("SLOW")) + { + state.Slow = true; + continue; + } if (sc.Compare("NODELAY")) { if (bag.statedef.GetStateLabelIndex(NAME_Spawn) == bag.statedef.GetStateCount()) From 94d47efbb5fa2b7269b50858a9dda9307c436ebb Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 15 Apr 2014 21:02:20 +0200 Subject: [PATCH 176/247] Added slow monsters to Strife's easiest skill --- wadsrc/static/mapinfo/strife.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt index 83c2285e6..5a25f3779 100644 --- a/wadsrc/static/mapinfo/strife.txt +++ b/wadsrc/static/mapinfo/strife.txt @@ -238,6 +238,7 @@ skill baby AmmoFactor = 2 DamageFactor = 0.5 EasyBossBrain + SlowMonsters SpawnFilter = Baby PicName = "M_JKILL" Name = "$SSKILL_BABY" From 48b926e5b47cf2380db412b6c08e8c7aeec1138a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Apr 2014 09:53:07 +0200 Subject: [PATCH 177/247] - check +logfile explicitly at the start of execution. Due to the custom CVAR rewrite it would get called so late that it'd miss half of the log. - added version check for Windows 8. I also would have liked to add 8.1 but due to some incredibly stupid changes in the version API it's no longer possible to reliably retrieve the correct Windows version for later builds. --- src/c_cmds.cpp | 26 ++++++++++++++++---------- src/c_dispatch.h | 2 ++ src/d_main.cpp | 7 +++++++ src/win32/i_system.cpp | 12 ++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index cdf615ef4..0e7adb8ef 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -441,27 +441,33 @@ CCMD (exec) } } +void execLogfile(const char *fn) +{ + if ((Logfile = fopen(fn, "w"))) + { + const char *timestr = myasctime(); + Printf("Log started: %s\n", timestr); + } + else + { + Printf("Could not start log\n"); + } +} + CCMD (logfile) { - const char *timestr = myasctime (); if (Logfile) { - Printf ("Log stopped: %s\n", timestr); + const char *timestr = myasctime(); + Printf("Log stopped: %s\n", timestr); fclose (Logfile); Logfile = NULL; } if (argv.argc() >= 2) { - if ( (Logfile = fopen (argv[1], "w")) ) - { - Printf ("Log started: %s\n", timestr); - } - else - { - Printf ("Could not start log\n"); - } + execLogfile(argv[1]); } } diff --git a/src/c_dispatch.h b/src/c_dispatch.h index 96dc50644..f4518608d 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -168,4 +168,6 @@ extern unsigned int MakeKey (const char *s); extern unsigned int MakeKey (const char *s, size_t len); extern unsigned int SuperFastHash (const char *data, size_t len); +void execLogfile(const char *fn); + #endif //__C_DISPATCH_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index 6c938ef53..695e7e517 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2223,6 +2223,13 @@ void D_DoomMain (void) FString *args; int argcount; + // +logfile gets checked too late to catch the full startup log in the logfile so do some extra check for it here. + FString logfile = Args->TakeValue("+logfile"); + if (logfile != NULL) + { + execLogfile(logfile); + } + D_DoomInit(); PClass::StaticInit (); atterm(FinalGC); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index a82cb65f9..4690c253d 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -581,6 +581,18 @@ void I_DetectOS(void) osname = "Server 2008 R2"; } } + else if (info.dwMinorVersion == 2) + { + // Microsoft broke this API for 8.1 so without jumping through hoops it won't be possible anymore to detect never versions aside from the build number, especially for older compilers. + if (info.wProductType == VER_NT_WORKSTATION) + { + osname = "8 (or higher)"; + } + else + { + osname = "Server 2012 (or higher)"; + } + } } break; From d855bd66b301ebd8ad969e6816a4c190d9e3ec8f Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Thu, 17 Apr 2014 00:46:33 +1200 Subject: [PATCH 178/247] Fixed P_LookForPlayers scanning redundancies - Players could be scanned multiple times, repeating expensive tests - Players could be skipped completely and become invisible as a result --- src/p_enemy.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 8b1dd951b..3be53cd64 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1542,7 +1542,6 @@ bool P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) { int c; - int stop; int pnum; player_t* player; bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true; @@ -1615,20 +1614,22 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) { pnum = actor->LastLookPlayerNumber; } - stop = (pnum - 1) & (MAXPLAYERS-1); for (;;) { - pnum = (pnum + 1) & (MAXPLAYERS-1); - if (!playeringame[pnum]) - continue; - - if (actor->TIDtoHate == 0) + // [ED850] Each and every player should only ever be checked once. + if (c++ < MAXPLAYERS) { - actor->LastLookPlayerNumber = pnum; - } + pnum = (pnum + 1) & (MAXPLAYERS - 1); + if (!playeringame[pnum]) + continue; - if (++c == MAXPLAYERS-1 || pnum == stop) + if (actor->TIDtoHate == 0) + { + actor->LastLookPlayerNumber = pnum; + } + } + else { // done looking if (actor->target == NULL) From 897d87a6a3841a0e484cc5de1e1b411848a3c6a8 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Thu, 17 Apr 2014 01:13:18 +1200 Subject: [PATCH 179/247] Invisibility would could P_LookForPlayers early --- src/p_enemy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 3be53cd64..e187dfb7c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1693,11 +1693,11 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) && P_AproxDistance (player->mo->velx, player->mo->vely) < 5*FRACUNIT) { // Player is sneaking - can't detect - return false; + continue; } if (pr_lookforplayers() < 225) { // Player isn't sneaking, but still didn't detect - return false; + continue; } } } From 60fe07df7451176803f4fe28b42160d02a72bd9c Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Thu, 17 Apr 2014 17:42:16 +0200 Subject: [PATCH 180/247] Added slow states to relevant Strife monsters Namely, acolyte, shadow acolyte, reaver, stalker, and turret. Info on which states needed the slow flag was obtained with Quasar's permission by looking at G_InitNew() in g_game.c and the info.c state tables from Chocolate Strife. Also added fast flag to acolyte states that needed it, based on the same source. --- wadsrc/static/actors/strife/acolyte.txt | 16 ++++++++-------- wadsrc/static/actors/strife/crusader.txt | 19 ++++++++----------- wadsrc/static/actors/strife/reaver.txt | 12 ++++++------ wadsrc/static/actors/strife/stalker.txt | 12 ++++++------ wadsrc/static/actors/strife/strifestuff.txt | 4 ++-- 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/wadsrc/static/actors/strife/acolyte.txt b/wadsrc/static/actors/strife/acolyte.txt index 1d04147f0..3ca1dec62 100644 --- a/wadsrc/static/actors/strife/acolyte.txt +++ b/wadsrc/static/actors/strife/acolyte.txt @@ -39,16 +39,16 @@ ACTOR Acolyte : StrifeHumanoid AGRD ABCDABCD 5 A_Wander Loop See: - AGRD A 6 A_AcolyteBits - AGRD BCD 6 A_Chase + AGRD A 6 Fast Slow A_AcolyteBits + AGRD BCD 6 Fast Slow A_Chase Loop Missile: - AGRD E 8 A_FaceTarget - AGRD FE 4 A_ShootGun - AGRD F 6 A_ShootGun + AGRD E 8 Fast Slow A_FaceTarget + AGRD FE 4 Fast Slow A_ShootGun + AGRD F 6 Fast Slow A_ShootGun Goto See Pain: - AGRD O 8 A_Pain + AGRD O 8 Fast Slow A_Pain Goto See Death: AGRD G 4 @@ -170,8 +170,8 @@ ACTOR AcolyteShadow : Acolyte 58 AGRD A 6 A_BeShadowyFoe Goto Super::See+1 Pain: - AGRD O 0 A_SetShadow - AGRD O 8 A_Pain + AGRD O 0 Fast Slow A_SetShadow + AGRD O 8 Fast Slow A_Pain Goto See } } diff --git a/wadsrc/static/actors/strife/crusader.txt b/wadsrc/static/actors/strife/crusader.txt index 36d89ed57..7f7a0d0c5 100644 --- a/wadsrc/static/actors/strife/crusader.txt +++ b/wadsrc/static/actors/strife/crusader.txt @@ -42,19 +42,16 @@ ACTOR Crusader 3005 ROB2 AABBCCDD 3 A_Chase Loop Missile: - ROB2 E 3 A_FaceTarget - ROB2 F 2 Bright A_CrusaderChoose - ROB2 E 2 Bright A_CrusaderSweepLeft - ROB2 F 3 Bright A_CrusaderSweepLeft - ROB2 E 2 Bright A_CrusaderSweepLeft - ROB2 F 2 Bright A_CrusaderSweepLeft - ROB2 E 2 Bright A_CrusaderSweepRight - ROB2 F 2 Bright A_CrusaderSweepRight - ROB2 E 2 Bright A_CrusaderSweepRight - ROB2 F 2 A_CrusaderRefire + ROB2 E 3 Slow A_FaceTarget + ROB2 F 2 Slow Bright A_CrusaderChoose + ROB2 E 2 Slow Bright A_CrusaderSweepLeft + ROB2 F 3 Slow Bright A_CrusaderSweepLeft + ROB2 EF 2 Slow Bright A_CrusaderSweepLeft + ROB2 EFE 2 Slow Bright A_CrusaderSweepRight + ROB2 F 2 Slow A_CrusaderRefire Loop Pain: - ROB2 D 1 A_Pain + ROB2 D 1 Slow A_Pain Goto See Death: ROB2 G 3 A_Scream diff --git a/wadsrc/static/actors/strife/reaver.txt b/wadsrc/static/actors/strife/reaver.txt index 23439b9ba..a69947373 100644 --- a/wadsrc/static/actors/strife/reaver.txt +++ b/wadsrc/static/actors/strife/reaver.txt @@ -32,16 +32,16 @@ ACTOR Reaver 3001 ROB1 BBCCDDEE 3 A_Chase Loop Melee: - ROB1 H 6 A_FaceTarget - ROB1 I 8 A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") - ROB1 H 6 + ROB1 H 6 Slow A_FaceTarget + ROB1 I 8 Slow A_CustomMeleeAttack(random[ReaverMelee](1,8)*3, "reaver/blade") + ROB1 H 6 Slow Goto See Missile: - ROB1 F 8 A_FaceTarget - ROB1 G 11 BRIGHT A_ReaverRanged + ROB1 F 8 Slow A_FaceTarget + ROB1 G 11 Slow BRIGHT A_ReaverRanged Goto See Pain: - ROB1 A 2 + ROB1 A 2 Slow ROB1 A 2 A_Pain Goto See Death: diff --git a/wadsrc/static/actors/strife/stalker.txt b/wadsrc/static/actors/strife/stalker.txt index 80732131e..0a537c762 100644 --- a/wadsrc/static/actors/strife/stalker.txt +++ b/wadsrc/static/actors/strife/stalker.txt @@ -45,14 +45,14 @@ ACTOR Stalker 186 STLK J 10 A_Look Loop See: - STLK A 1 A_StalkerChaseDecide - STLK ABB 3 A_Chase - STLK C 3 A_StalkerWalk - STLK C 3 A_Chase + STLK A 1 Slow A_StalkerChaseDecide + STLK ABB 3 Slow A_Chase + STLK C 3 Slow A_StalkerWalk + STLK C 3 Slow A_Chase Loop Melee: - STLK J 3 A_FaceTarget - STLK K 3 A_StalkerAttack + STLK J 3 Slow A_FaceTarget + STLK K 3 Slow A_StalkerAttack SeeFloor: STLK J 3 A_StalkerWalk STLK KK 3 A_Chase diff --git a/wadsrc/static/actors/strife/strifestuff.txt b/wadsrc/static/actors/strife/strifestuff.txt index b0f4024f4..ef762cbb6 100644 --- a/wadsrc/static/actors/strife/strifestuff.txt +++ b/wadsrc/static/actors/strife/strifestuff.txt @@ -1786,8 +1786,8 @@ ACTOR CeilingTurret 27 Loop Missile: Pain: - TURT B 4 A_ShootGun - TURT D 3 A_SentinelRefire + TURT B 4 Slow A_ShootGun + TURT D 3 Slow A_SentinelRefire TURT A 4 A_SentinelRefire Loop Death: From 1c50b5dd6f764eb70f29624cead70a929ffeab9c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 20 Apr 2014 13:37:59 +0300 Subject: [PATCH 181/247] Fixed initialization of Hexen-style things Recently added pitch and roll members were not initialized with zeroes when loading Hexen-style maps At least, hitscan attack can be fired in random direction because of this --- src/p_setup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 77b9b077b..c564d1aa7 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1826,6 +1826,8 @@ void P_LoadThings2 (MapData * map) for(int i = 0; i< numthings; i++) { + memset (&mti[i], 0, sizeof(mti[i])); + mti[i].thingid = LittleShort(mth[i].thingid); mti[i].x = LittleShort(mth[i].x)<> MTF_CLASS_SHIFT; mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); - mti[i].Conversation = 0; mti[i].gravity = FRACUNIT; mti[i].RenderStyle = STYLE_Count; mti[i].alpha = -1; mti[i].health = 1; - mti[i].fillcolor = mti[i].scaleX = mti[i].scaleY = mti[i].score = 0; } delete[] mtp; } From 265917c923bb33bac32d91ad15ebbf79b1d169dc Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 22 Apr 2014 13:31:55 +0200 Subject: [PATCH 182/247] Add shadow and subtract styles to ACS. There is a matching pull request for rheit/acs. --- src/p_acs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 4cb34defa..1c84c9401 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3546,6 +3546,8 @@ static const int LegacyRenderStyleIndices[] = 65, // STYLE_Add, 66, // STYLE_Shaded, 67, // STYLE_TranslucentStencil, + 68, // STYLE_Shadow, + 69, // STYLE_Subtract, -1 }; From 7c3660087ed7fc1db18c0ae38285a14f6f5a5c9f Mon Sep 17 00:00:00 2001 From: Gaerzi Date: Tue, 22 Apr 2014 13:32:33 +0200 Subject: [PATCH 183/247] Restore shadow renderstyle. It was accidentally lost in r3085. --- src/thingdef/thingdef_properties.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 61ab5b968..4e4fb4218 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -796,11 +796,13 @@ DEFINE_PROPERTY(renderstyle, S, Actor) { PROP_STRING_PARM(str, 0); static const char * renderstyles[]={ - "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL", "TRANSLUCENT", "ADD", "SHADED", "SUBTRACT", NULL }; + "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL", + "TRANSLUCENT", "ADD", "SHADED", "SHADOW", "SUBTRACT", NULL }; static const int renderstyle_values[]={ STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, - STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, STYLE_Subtract}; + STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, + STYLE_Shadow, STYLE_Subtract}; // make this work for old style decorations, too. if (!strnicmp(str, "style_", 6)) str+=6; From 3fa89b4e9fb9579b2b77927997dbc41c4cc876e8 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 27 Apr 2014 10:18:50 +0300 Subject: [PATCH 184/247] Fixed crash on attempt to load corrupted data file Instance of FileReader is no longer destructed when header of data file is valid but complete loading of file fails Loading of truncated .zip file is the simplest test case --- src/resourcefiles/file_7z.cpp | 2 ++ src/resourcefiles/file_grp.cpp | 2 ++ src/resourcefiles/file_pak.cpp | 2 ++ src/resourcefiles/file_rff.cpp | 2 ++ src/resourcefiles/file_wad.cpp | 2 ++ src/resourcefiles/file_zip.cpp | 2 ++ 6 files changed, 12 insertions(+) diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index 8b1c23b67..5c9289242 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -351,6 +351,8 @@ FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new F7ZFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_grp.cpp b/src/resourcefiles/file_grp.cpp index dc4c97812..63738d7e6 100644 --- a/src/resourcefiles/file_grp.cpp +++ b/src/resourcefiles/file_grp.cpp @@ -147,6 +147,8 @@ FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FGrpFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_pak.cpp b/src/resourcefiles/file_pak.cpp index 099e8046c..9ea01767b 100644 --- a/src/resourcefiles/file_pak.cpp +++ b/src/resourcefiles/file_pak.cpp @@ -139,6 +139,8 @@ FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FPakFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_rff.cpp b/src/resourcefiles/file_rff.cpp index 2e6a3bc5a..682df985d 100644 --- a/src/resourcefiles/file_rff.cpp +++ b/src/resourcefiles/file_rff.cpp @@ -260,6 +260,8 @@ FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FRFFFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index ea8cac15b..384290782 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -651,6 +651,8 @@ FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FWadFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 101b51982..7ae0e90a5 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -423,6 +423,8 @@ FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet) { FResourceFile *rf = new FZipFile(filename, file); if (rf->Open(quiet)) return rf; + + rf->Reader = NULL; // to avoid destruction of reader delete rf; } } From 6b26b710b84110b4f96e27da59dc9c8329948e86 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 27 Apr 2014 10:23:20 +0300 Subject: [PATCH 185/247] Added simple check for unsupported compression method in .7z files --- src/resourcefiles/file_7z.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index 5c9289242..a00626774 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -293,6 +293,21 @@ bool F7ZFile::Open(bool quiet) } // Resize the lump record array to its actual size NumLumps -= skipped; + + if (NumLumps > 0) + { + // Quick check for unsupported compression method + + TArray temp; + temp.Resize(Lumps[0].LumpSize); + + if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) + { + if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename); + return false; + } + } + if (!quiet) Printf(", %d lumps\n", NumLumps); // Entries in archives are sorted alphabetically From 3af7d8a245a3d8c310fb8077a14ecaec36df1714 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 27 Apr 2014 13:05:40 +0300 Subject: [PATCH 186/247] Added support for LZMA2 compression method in .7z archives Updated LZMA SDK to version 9.20 http://www.7-zip.org/sdk.html http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2 --- lzma/C/7z.h | 203 ++++++++++++++ lzma/C/7zBuf.h | 10 +- lzma/C/7zCrc.c | 77 ++++-- lzma/C/7zCrc.h | 13 +- lzma/C/7zCrcOpt.c | 34 +++ lzma/C/7zDec.c | 470 +++++++++++++++++++++++++++++++++ lzma/C/{Archive/7z => }/7zIn.c | 366 +++++++++++++++++++------ lzma/C/7zStream.c | 8 +- lzma/C/7zVersion.h | 8 +- lzma/C/Alloc.c | 127 --------- lzma/C/Alloc.h | 32 --- lzma/C/Archive/7z/7zDecode.c | 254 ------------------ lzma/C/Archive/7z/7zDecode.h | 13 - lzma/C/Archive/7z/7zExtract.c | 93 ------- lzma/C/Archive/7z/7zExtract.h | 41 --- lzma/C/Archive/7z/7zHeader.c | 6 - lzma/C/Archive/7z/7zHeader.h | 57 ---- lzma/C/Archive/7z/7zIn.h | 41 --- lzma/C/Archive/7z/7zItem.c | 127 --------- lzma/C/Archive/7z/7zItem.h | 84 ------ lzma/C/Bcj2.h | 10 +- lzma/C/Bra.c | 133 ++++++++++ lzma/C/Bra.h | 10 +- lzma/C/CpuArch.c | 168 ++++++++++++ lzma/C/CpuArch.h | 118 +++++++-- lzma/C/LzFind.c | 20 +- lzma/C/LzFind.h | 16 +- lzma/C/LzFindMt.c | 34 +-- lzma/C/LzFindMt.h | 16 +- lzma/C/LzHash.h | 6 +- lzma/C/Lzma2Dec.c | 356 +++++++++++++++++++++++++ lzma/C/Lzma2Dec.h | 84 ++++++ lzma/C/LzmaDec.c | 14 +- lzma/C/LzmaDec.h | 22 +- lzma/C/LzmaEnc.c | 103 ++++---- lzma/C/LzmaEnc.h | 14 +- lzma/C/LzmaLib.c | 46 ---- lzma/C/LzmaLib.h | 135 ---------- lzma/C/Threads.c | 294 +++------------------ lzma/C/Threads.h | 162 +++--------- lzma/C/Types.h | 70 ++++- lzma/CMakeLists.txt | 28 +- lzma/history.txt | 35 +++ lzma/lzma.txt | 34 +-- lzma/lzmalib.vcproj | 80 ++---- src/resourcefiles/file_7z.cpp | 30 ++- 46 files changed, 2310 insertions(+), 1792 deletions(-) create mode 100644 lzma/C/7z.h create mode 100644 lzma/C/7zCrcOpt.c create mode 100644 lzma/C/7zDec.c rename lzma/C/{Archive/7z => }/7zIn.c (75%) delete mode 100644 lzma/C/Alloc.c delete mode 100644 lzma/C/Alloc.h delete mode 100644 lzma/C/Archive/7z/7zDecode.c delete mode 100644 lzma/C/Archive/7z/7zDecode.h delete mode 100644 lzma/C/Archive/7z/7zExtract.c delete mode 100644 lzma/C/Archive/7z/7zExtract.h delete mode 100644 lzma/C/Archive/7z/7zHeader.c delete mode 100644 lzma/C/Archive/7z/7zHeader.h delete mode 100644 lzma/C/Archive/7z/7zIn.h delete mode 100644 lzma/C/Archive/7z/7zItem.c delete mode 100644 lzma/C/Archive/7z/7zItem.h create mode 100644 lzma/C/Bra.c create mode 100644 lzma/C/CpuArch.c create mode 100644 lzma/C/Lzma2Dec.c create mode 100644 lzma/C/Lzma2Dec.h delete mode 100644 lzma/C/LzmaLib.c delete mode 100644 lzma/C/LzmaLib.h mode change 100644 => 100755 lzma/history.txt mode change 100644 => 100755 lzma/lzma.txt diff --git a/lzma/C/7z.h b/lzma/C/7z.h new file mode 100644 index 000000000..b7edd3ba5 --- /dev/null +++ b/lzma/C/7z.h @@ -0,0 +1,203 @@ +/* 7z.h -- 7z interface +2010-03-11 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zBuf.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttributes, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy +}; + +typedef struct +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + UInt64 MethodID; + CBuf Props; +} CSzCoderInfo; + +void SzCoderInfo_Init(CSzCoderInfo *p); +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBindPair; + +typedef struct +{ + CSzCoderInfo *Coders; + CSzBindPair *BindPairs; + UInt32 *PackStreams; + UInt64 *UnpackSizes; + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + int UnpackCRCDefined; + UInt32 UnpackCRC; + + UInt32 NumUnpackStreams; +} CSzFolder; + +void SzFolder_Init(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); +UInt64 SzFolder_GetUnpackSize(CSzFolder *p); + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + CNtfsFileTime MTime; + UInt64 Size; + UInt32 Crc; + UInt32 Attrib; + Byte HasStream; + Byte IsDir; + Byte IsAnti; + Byte CrcDefined; + Byte MTimeDefined; + Byte AttribDefined; +} CSzFileItem; + +void SzFile_Init(CSzFileItem *p); + +typedef struct +{ + UInt64 *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + CSzFolder *Folders; + CSzFileItem *Files; + UInt32 NumPackStreams; + UInt32 NumFolders; + UInt32 NumFiles; +} CSzAr; + +void SzAr_Init(CSzAr *p); +void SzAr_Free(CSzAr *p, ISzAlloc *alloc); + + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 *FolderStartPackStreamIndex; + UInt64 *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; + + size_t *FileNameOffsets; /* in 2-byte steps */ + CBuf FileNames; /* UTF-16-LE */ +} CSzArEx; + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); + +EXTERN_C_END + +#endif diff --git a/lzma/C/7zBuf.h b/lzma/C/7zBuf.h index 49b2354bd..88ff0c2f2 100644 --- a/lzma/C/7zBuf.h +++ b/lzma/C/7zBuf.h @@ -1,11 +1,15 @@ /* 7zBuf.h -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { Byte *data; @@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/7zCrc.c b/lzma/C/7zCrc.c index 92c47de0d..5801dabfc 100644 --- a/lzma/C/7zCrc.c +++ b/lzma/C/7zCrc.c @@ -1,35 +1,74 @@ /* 7zCrc.c -- CRC32 calculation -2008-08-05 -Igor Pavlov -Public domain */ +2009-11-23 : Igor Pavlov : Public domain */ #include "7zCrc.h" +#include "CpuArch.h" #define kCrcPoly 0xEDB88320 -UInt32 g_CrcTable[256]; -void MY_FAST_CALL CrcGenerateTable(void) +#ifdef MY_CPU_LE +#define CRC_NUM_TABLES 8 +#else +#define CRC_NUM_TABLES 1 +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +static CRC_FUNC g_CrcUpdate; +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +#if CRC_NUM_TABLES == 1 + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#else + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); + +#endif + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +void MY_FAST_CALL CrcGenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; - int j; + unsigned j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } -} - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) -{ - const Byte *p = (const Byte *)data; - for (; size > 0 ; size--, p++) - v = CRC_UPDATE_BYTE(v, *p); - return v; -} - -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) -{ - return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; + #if CRC_NUM_TABLES == 1 + g_CrcUpdate = CrcUpdateT1; + #else + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + g_CrcUpdate = CrcUpdateT4; + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif + #endif } diff --git a/lzma/C/7zCrc.h b/lzma/C/7zCrc.h index ae230991e..4a1ec38c9 100644 --- a/lzma/C/7zCrc.h +++ b/lzma/C/7zCrc.h @@ -1,24 +1,25 @@ /* 7zCrc.h -- CRC32 calculation -2008-03-13 -Igor Pavlov -Public domain */ +2009-11-21 : Igor Pavlov : Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H -#include - #include "Types.h" +EXTERN_C_BEGIN + extern UInt32 g_CrcTable[]; +/* Call CrcGenerateTable one time before other CRC functions */ void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF -#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); +EXTERN_C_END + #endif diff --git a/lzma/C/7zCrcOpt.c b/lzma/C/7zCrcOpt.c new file mode 100644 index 000000000..6205d7161 --- /dev/null +++ b/lzma/C/7zCrcOpt.c @@ -0,0 +1,34 @@ +/* 7zCrcOpt.c -- CRC32 calculation : optimized version +2009-11-23 : Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_LE + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x300 + (v & 0xFF)] ^ + table[0x200 + ((v >> 8) & 0xFF)] ^ + table[0x100 + ((v >> 16) & 0xFF)] ^ + table[0x000 + ((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + return CrcUpdateT4(v, data, size, table); +} + +#endif diff --git a/lzma/C/7zDec.c b/lzma/C/7zDec.c new file mode 100644 index 000000000..338680747 --- /dev/null +++ b/lzma/C/7zDec.c @@ -0,0 +1,470 @@ +/* 7zDec.c -- Decoding from 7z folder +2010-11-02 : Igor Pavlov : Public domain */ + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn p; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(void *pp) +{ + CByteInToLook *p = (CByteInToLook *)pp; + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = p->cur - p->begin; + p->processed += size; + p->res = p->inStream->Skip(p->inStream, size); + size = (1 << 25); + p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.p.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (coder->Props.size != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = coder->Props.data[0]; + UInt32 memSize = GetUi32(coder->Props.data + 1); + if (order < PPMD7_MIN_ORDER || + order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + CPpmd7z_RangeDec rc; + Ppmd7z_RangeDec_CreateVTable(&rc); + rc.Stream = &s.p; + if (!Ppmd7z_RangeDec_Init(&rc)) + res = SZ_ERROR_DATA; + else if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else + { + SizeT i; + for (i = 0; i < outSize; i++) + { + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); + if (s.extra || sym < 0) + break; + outBuffer[i] = (Byte)sym; + } + if (i != outSize) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + res = SZ_ERROR_DATA; + } + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) + { + if (state.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (coder->Props.size != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) + { + if (state.decoder.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(inStream->Skip((void *)inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch(m) + { + case k_Copy: + case k_LZMA: + case k_LZMA2: + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumInStreams == 1 && + c->NumOutStreams == 1 && + c->MethodID <= (UInt32)0xFFFFFFFF && + IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + if (f->NumCoders == 2) + { + CSzCoderInfo *c = &f->Coders[1]; + if (c->MethodID > (UInt32)0xFFFFFFFF || + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || + f->NumBindPairs != 1 || + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) || + !IS_SUPPORTED_CODER(&f->Coders[2]) || + !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 || + f->PackStreams[0] != 2 || + f->PackStreams[1] != 6 || + f->PackStreams[2] != 1 || + f->PackStreams[3] != 0 || + f->NumBindPairs != 3 || + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + return SZ_ERROR_UNSUPPORTED; +} + +static UInt64 GetSum(const UInt64 *values, UInt32 index) +{ + UInt64 sum = 0; + UInt32 i; + for (i = 0; i < index; i++) + sum += values[i]; + return sum; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = folder->UnpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); + if (temp == 0 && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = GetSum(packSizes, si); + inSize = packSizes[si]; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else + { + #ifdef _7ZIP_PPMD_SUPPPORT + RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = GetSum(packSizes, 1); + UInt64 s3Size = packSizes[1]; + SRes res; + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); + if (tempBuf[2] == 0 && tempSizes[2] != 0) + return SZ_ERROR_MEM; + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); + RINOK(res) + + res = Bcj2_Decode( + tempBuf3, tempSize3, + tempBuf[0], tempSizes[0], + tempBuf[1], tempSizes[1], + tempBuf[2], tempSizes[2], + outBuffer, outSize); + RINOK(res) + } + else + { + if (ci != 1) + return SZ_ERROR_UNSUPPORTED; + switch(coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + return SZ_OK; +} + +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) +{ + Byte *tempBuf[3] = { 0, 0, 0}; + int i; + SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + for (i = 0; i < 3; i++) + IAlloc_Free(allocMain, tempBuf[i]); + return res; +} diff --git a/lzma/C/Archive/7z/7zIn.c b/lzma/C/7zIn.c similarity index 75% rename from lzma/C/Archive/7z/7zIn.c rename to lzma/C/7zIn.c index 75b0bcd1d..f1a44928e 100644 --- a/lzma/C/Archive/7z/7zIn.c +++ b/lzma/C/7zIn.c @@ -1,17 +1,134 @@ /* 7zIn.c -- 7z Input functions -2008-12-31 : Igor Pavlov : Public domain */ +2010-10-29 : Igor Pavlov : Public domain */ -#include "../../7zCrc.h" -#include "../../CpuArch.h" +#include -#include "7zDecode.h" -#include "7zIn.h" +#include "7z.h" +#include "7zCrc.h" +#include "CpuArch.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 +void SzCoderInfo_Init(CSzCoderInfo *p) +{ + Buf_Init(&p->Props); +} + +void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) +{ + Buf_Free(&p->Props, alloc); + SzCoderInfo_Init(p); +} + +void SzFolder_Init(CSzFolder *p) +{ + p->Coders = 0; + p->BindPairs = 0; + p->PackStreams = 0; + p->UnpackSizes = 0; + p->NumCoders = 0; + p->NumBindPairs = 0; + p->NumPackStreams = 0; + p->UnpackCRCDefined = 0; + p->UnpackCRC = 0; + p->NumUnpackStreams = 0; +} + +void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Coders) + for (i = 0; i < p->NumCoders; i++) + SzCoderInfo_Free(&p->Coders[i], alloc); + IAlloc_Free(alloc, p->Coders); + IAlloc_Free(alloc, p->BindPairs); + IAlloc_Free(alloc, p->PackStreams); + IAlloc_Free(alloc, p->UnpackSizes); + SzFolder_Init(p); +} + +UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < p->NumCoders; i++) + result += p->Coders[i].NumOutStreams; + return result; +} + +int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +UInt64 SzFolder_GetUnpackSize(CSzFolder *p) +{ + int i = (int)SzFolder_GetNumOutStreams(p); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolder_FindBindPairForOutStream(p, i) < 0) + return p->UnpackSizes[i]; + /* throw 1; */ + return 0; +} + +void SzFile_Init(CSzFileItem *p) +{ + p->HasStream = 1; + p->IsDir = 0; + p->IsAnti = 0; + p->CrcDefined = 0; + p->MTimeDefined = 0; +} + +void SzAr_Init(CSzAr *p) +{ + p->PackSizes = 0; + p->PackCRCsDefined = 0; + p->PackCRCs = 0; + p->Folders = 0; + p->Files = 0; + p->NumPackStreams = 0; + p->NumFolders = 0; + p->NumFiles = 0; +} + +void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + UInt32 i; + if (p->Folders) + for (i = 0; i < p->NumFolders; i++) + SzFolder_Free(&p->Folders[i], alloc); + + IAlloc_Free(alloc, p->PackSizes); + IAlloc_Free(alloc, p->PackCRCsDefined); + IAlloc_Free(alloc, p->PackCRCs); + IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->Files); + SzAr_Init(p); +} + + void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); @@ -19,6 +136,8 @@ void SzArEx_Init(CSzArEx *p) p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + Buf_Init(&p->FileNames); } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) @@ -27,6 +146,10 @@ void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); + + IAlloc_Free(alloc, p->FileNameOffsets); + Buf_Free(&p->FileNames, alloc); + SzAr_Free(&p->db, alloc); SzArEx_Init(p); } @@ -488,11 +611,11 @@ static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; - MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); + MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { - CBindPair *bp = folder->BindPairs + i; + CSzBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } @@ -780,81 +903,38 @@ static SRes SzReadStreamsInfo( } } -Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} -static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) +static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes) { UInt32 i; + size_t pos = 0; for (i = 0; i < numFiles; i++) { - UInt32 len = 0; - UInt32 pos = 0; - CSzFileItem *file = files + i; - while (pos + 2 <= sd->Size) + sizes[i] = pos; + for (;;) { - int numAdds; - UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - len++; - if (value == 0) + if (pos >= size) + return SZ_ERROR_ARCHIVE; + if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0) break; - if (value < 0x80) - continue; - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2; - if (value >= 0xDC00) - return SZ_ERROR_ARCHIVE; - if (pos + 2 > sd->Size) - return SZ_ERROR_ARCHIVE; - c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - if (c2 < 0xDC00 || c2 >= 0xE000) - return SZ_ERROR_ARCHIVE; - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - len += numAdds; - } - - MY_ALLOC(char, file->Name, (size_t)len, alloc); - - len = 0; - while (2 <= sd->Size) - { - int numAdds; - UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - if (value < 0x80) - { - file->Name[len++] = (char)value; - if (value == 0) - break; - continue; - } - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); - do - { - numAdds--; - file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); - } - while (numAdds > 0); - - len += numAdds; + pos++; } + pos++; } - return SZ_OK; + sizes[i] = pos; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; } static SRes SzReadHeader2( @@ -920,7 +1000,8 @@ static SRes SzReadHeader2( if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); - + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); @@ -930,8 +1011,17 @@ static SRes SzReadHeader2( { case k7zIdName: { + size_t namesSize; RINOK(SzReadSwitch(sd)); - RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) + namesSize = (size_t)size - 1; + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + if (!Buf_Create(&p->FileNames, namesSize, allocMain)) + return SZ_ERROR_MEM; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames.data, sd->Data, namesSize); + RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) + RINOK(SzSkeepDataSize(sd, namesSize)); break; } case k7zIdEmptyStream: @@ -948,6 +1038,25 @@ static SRes SzReadHeader2( RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } + case k7zIdWinAttributes: + { + RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); + RINOK(SzReadSwitch(sd)); + for (i = 0; i < numFiles; i++) + { + CSzFileItem *f = &files[i]; + Byte defined = (*lwtVector)[i]; + f->AttribDefined = defined; + f->Attrib = 0; + if (defined) + { + RINOK(SzReadUInt32(sd, &f->Attrib)); + } + } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; + break; + } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); @@ -964,6 +1073,8 @@ static SRes SzReadHeader2( RINOK(SzReadUInt32(sd, &f->MTime.High)); } } + IAlloc_Free(allocTemp, *lwtVector); + *lwtVector = NULL; break; } default: @@ -988,8 +1099,8 @@ static SRes SzReadHeader2( { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; - file->FileCRC = (*digests)[sizeIndex]; - file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; + file->Crc = (*digests)[sizeIndex]; + file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else @@ -1000,7 +1111,8 @@ static SRes SzReadHeader2( file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; - file->FileCRCDefined = 0; + file->Crc = 0; + file->CrcDefined = 0; } } } @@ -1066,7 +1178,7 @@ static SRes SzReadAndDecodePackedStreams2( if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; - res = SzDecode(p->PackSizes, folder, + res = SzFolder_Decode(folder, p->PackSizes, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); @@ -1106,12 +1218,16 @@ static SRes SzArEx_Open2( ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; + Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; + startArcPos = 0; + RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) @@ -1123,7 +1239,7 @@ static SRes SzArEx_Open2( nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = k7zStartHeaderSize; + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; @@ -1140,13 +1256,13 @@ static SRes SzArEx_Open2( { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1202,3 +1318,85 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAl SzArEx_Free(p, allocMain); return res; } + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CSzFolder *folder = p->db.Folders + folderIndex; + UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); + size_t unpackSize = (size_t)unpackSizeSpec; + UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *outBuffer); + *outBuffer = 0; + + RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*outBuffer == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzFolder_Decode(folder, + p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], + inStream, startOffset, + *outBuffer, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (folder->UnpackCRCDefined) + { + if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt32 i; + CSzFileItem *fileItem = p->db.Files + fileIndex; + *offset = 0; + for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)p->db.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) + res = SZ_ERROR_CRC; + } + return res; +} diff --git a/lzma/C/7zStream.c b/lzma/C/7zStream.c index a0a2405d0..f0959fb07 100644 --- a/lzma/C/7zStream.c +++ b/lzma/C/7zStream.c @@ -1,5 +1,5 @@ /* 7zStream.c -- 7z Stream functions -2008-11-23 : Igor Pavlov : Public domain */ +2010-03-11 : Igor Pavlov : Public domain */ #include @@ -39,7 +39,7 @@ SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { - void *lookBuf; + const void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); @@ -66,7 +66,7 @@ SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } -static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) +static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; @@ -84,7 +84,7 @@ static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) return res; } -static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) +static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; diff --git a/lzma/C/7zVersion.h b/lzma/C/7zVersion.h index 5a6bcadac..d4ac470e2 100644 --- a/lzma/C/7zVersion.h +++ b/lzma/C/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 4 -#define MY_VER_MINOR 65 +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 #define MY_VER_BUILD 0 -#define MY_VERSION "4.65" -#define MY_DATE "2009-02-03" +#define MY_VERSION "9.20" +#define MY_DATE "2010-11-18" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/lzma/C/Alloc.c b/lzma/C/Alloc.c deleted file mode 100644 index bb24a772b..000000000 --- a/lzma/C/Alloc.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ - -#ifdef _WIN32 -#include -#endif -#include - -#include "Alloc.h" - -/* #define _SZ_ALLOC_DEBUG */ - -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ -#ifdef _SZ_ALLOC_DEBUG -#include -int g_allocCount = 0; -int g_allocCountMid = 0; -int g_allocCountBig = 0; -#endif - -void *MyAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - { - void *p = malloc(size); - fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); - return p; - } - #else - return malloc(size); - #endif -} - -void MyFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); - #endif - free(address); -} - -#ifdef _WIN32 - -void *MidAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void MidFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); - #endif - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#ifndef MEM_LARGE_PAGES -#undef _7ZIP_LARGE_PAGES -#endif - -#ifdef _7ZIP_LARGE_PAGES -SIZE_T g_LargePageSize = 0; -typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); -#endif - -void SetLargePageSize() -{ - #ifdef _7ZIP_LARGE_PAGES - SIZE_T size = 0; - GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); - if (largePageMinimum == 0) - return; - size = largePageMinimum(); - if (size == 0 || (size & (size - 1)) != 0) - return; - g_LargePageSize = size; - #endif -} - - -void *BigAlloc(size_t size) -{ - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); - #endif - - #ifdef _7ZIP_LARGE_PAGES - if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) - { - void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), - MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); - if (res != 0) - return res; - } - #endif - return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); -} - -void BigFree(void *address) -{ - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); - #endif - - if (address == 0) - return; - VirtualFree(address, 0, MEM_RELEASE); -} - -#endif diff --git a/lzma/C/Alloc.h b/lzma/C/Alloc.h deleted file mode 100644 index a396c6b9e..000000000 --- a/lzma/C/Alloc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Alloc.h -- Memory allocation functions -2008-03-13 -Igor Pavlov -Public domain */ - -#ifndef __COMMON_ALLOC_H -#define __COMMON_ALLOC_H - -#include - -void *MyAlloc(size_t size); -void MyFree(void *address); - -#ifdef _WIN32 - -void SetLargePageSize(); - -void *MidAlloc(size_t size); -void MidFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); - -#else - -#define MidAlloc(size) MyAlloc(size) -#define MidFree(address) MyFree(address) -#define BigAlloc(size) MyAlloc(size) -#define BigFree(address) MyFree(address) - -#endif - -#endif diff --git a/lzma/C/Archive/7z/7zDecode.c b/lzma/C/Archive/7z/7zDecode.c deleted file mode 100644 index 097d2ea3c..000000000 --- a/lzma/C/Archive/7z/7zDecode.c +++ /dev/null @@ -1,254 +0,0 @@ -/* 7zDecode.c -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#include - -#include "../../Bcj2.h" -#include "../../Bra.h" -#include "../../LzmaDec.h" -#include "7zDecode.h" - -#define k_Copy 0 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_BCJ2 0x0303011B - -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzmaDec state; - SRes res = SZ_OK; - - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); - state.dic = outBuffer; - state.dicBufSize = outSize; - LzmaDec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; - ELzmaStatus status; - res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) - { - if (state.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - LzmaDec_FreeProbs(&state, allocMain); - return res; -} - -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) -{ - while (inSize > 0) - { - void *inBuf; - size_t curSize = (1 << 18); - if (curSize > inSize) - curSize = (size_t)inSize; - RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); - if (curSize == 0) - return SZ_ERROR_INPUT_EOF; - memcpy(outBuffer, inBuf, curSize); - outBuffer += curSize; - inSize -= curSize; - RINOK(inStream->Skip((void *)inStream, curSize)); - } - return SZ_OK; -} - -#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) -#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) - -SRes CheckSupportedFolder(const CSzFolder *f) -{ - if (f->NumCoders < 1 || f->NumCoders > 4) - return SZ_ERROR_UNSUPPORTED; - if (IS_UNSUPPORTED_CODER(f->Coders[0])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumCoders == 1) - { - if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 2) - { - if (IS_NO_BCJ(f->Coders[1]) || - f->NumPackStreams != 1 || f->PackStreams[0] != 0 || - f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 4) - { - if (IS_UNSUPPORTED_CODER(f->Coders[1]) || - IS_UNSUPPORTED_CODER(f->Coders[2]) || - IS_NO_BCJ2(f->Coders[3])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumPackStreams != 4 || - f->PackStreams[0] != 2 || - f->PackStreams[1] != 6 || - f->PackStreams[2] != 1 || - f->PackStreams[3] != 0 || - f->NumBindPairs != 3 || - f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || - f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || - f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - return SZ_ERROR_UNSUPPORTED; -} - -UInt64 GetSum(const UInt64 *values, UInt32 index) -{ - UInt64 sum = 0; - UInt32 i; - for (i = 0; i < index; i++) - sum += values[i]; - return sum; -} - -SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, - Byte *tempBuf[]) -{ - UInt32 ci; - SizeT tempSizes[3] = { 0, 0, 0}; - SizeT tempSize3 = 0; - Byte *tempBuf3 = 0; - - RINOK(CheckSupportedFolder(folder)); - - for (ci = 0; ci < folder->NumCoders; ci++) - { - CSzCoderInfo *coder = &folder->Coders[ci]; - - if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) - { - UInt32 si = 0; - UInt64 offset; - UInt64 inSize; - Byte *outBufCur = outBuffer; - SizeT outSizeCur = outSize; - if (folder->NumCoders == 4) - { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; - si = indices[ci]; - if (ci < 2) - { - Byte *temp; - outSizeCur = (SizeT)unpackSize; - if (outSizeCur != unpackSize) - return SZ_ERROR_MEM; - temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); - if (temp == 0 && outSizeCur != 0) - return SZ_ERROR_MEM; - outBufCur = tempBuf[1 - ci] = temp; - tempSizes[1 - ci] = outSizeCur; - } - else if (ci == 2) - { - if (unpackSize > outSize) /* check it */ - return SZ_ERROR_PARAM; - tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); - tempSize3 = outSizeCur = (SizeT)unpackSize; - } - else - return SZ_ERROR_UNSUPPORTED; - } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - - if (coder->MethodID == k_Copy) - { - if (inSize != outSizeCur) /* check it */ - return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); - } - else - { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - } - else if (coder->MethodID == k_BCJ) - { - UInt32 state; - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - } - else if (coder->MethodID == k_BCJ2) - { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; - SRes res; - if (ci != 3) - return SZ_ERROR_UNSUPPORTED; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - tempSizes[2] = (SizeT)s3Size; - if (tempSizes[2] != s3Size) - return SZ_ERROR_MEM; - tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); - if (tempBuf[2] == 0 && tempSizes[2] != 0) - return SZ_ERROR_MEM; - res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); - RINOK(res) - - res = Bcj2_Decode( - tempBuf3, tempSize3, - tempBuf[0], tempSizes[0], - tempBuf[1], tempSizes[1], - tempBuf[2], tempSizes[2], - outBuffer, outSize); - RINOK(res) - } - else - return SZ_ERROR_UNSUPPORTED; - } - return SZ_OK; -} - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) -{ - Byte *tempBuf[3] = { 0, 0, 0}; - int i; - SRes res = SzDecode2(packSizes, folder, inStream, startPos, - outBuffer, (SizeT)outSize, allocMain, tempBuf); - for (i = 0; i < 3; i++) - IAlloc_Free(allocMain, tempBuf[i]); - return res; -} diff --git a/lzma/C/Archive/7z/7zDecode.h b/lzma/C/Archive/7z/7zDecode.h deleted file mode 100644 index 9607915bf..000000000 --- a/lzma/C/Archive/7z/7zDecode.h +++ /dev/null @@ -1,13 +0,0 @@ -/* 7zDecode.h -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_DECODE_H -#define __7Z_DECODE_H - -#include "7zItem.h" - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); - -#endif diff --git a/lzma/C/Archive/7z/7zExtract.c b/lzma/C/Archive/7z/7zExtract.c deleted file mode 100644 index 0f957add1..000000000 --- a/lzma/C/Archive/7z/7zExtract.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 7zExtract.c -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#include "../../7zCrc.h" -#include "7zDecode.h" -#include "7zExtract.h" - -SRes SzAr_Extract( - const CSzArEx *p, - ILookInStream *inStream, - UInt32 fileIndex, - UInt32 *blockIndex, - Byte **outBuffer, - size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; - SRes res = SZ_OK; - *offset = 0; - *outSizeProcessed = 0; - if (folderIndex == (UInt32)-1) - { - IAlloc_Free(allocMain, *outBuffer); - *blockIndex = folderIndex; - *outBuffer = 0; - *outBufferSize = 0; - return SZ_OK; - } - - if (*outBuffer == 0 || *blockIndex != folderIndex) - { - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); - size_t unpackSize = (size_t)unpackSizeSpec; - UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); - - if (unpackSize != unpackSizeSpec) - return SZ_ERROR_MEM; - *blockIndex = folderIndex; - IAlloc_Free(allocMain, *outBuffer); - *outBuffer = 0; - - RINOK(LookInStream_SeekTo(inStream, startOffset)); - - if (res == SZ_OK) - { - *outBufferSize = unpackSize; - if (unpackSize != 0) - { - *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); - if (*outBuffer == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) - { - res = SzDecode(p->db.PackSizes + - p->FolderStartPackStreamIndex[folderIndex], folder, - inStream, startOffset, - *outBuffer, unpackSize, allocTemp); - if (res == SZ_OK) - { - if (folder->UnpackCRCDefined) - { - if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) - res = SZ_ERROR_CRC; - } - } - } - } - } - if (res == SZ_OK) - { - UInt32 i; - CSzFileItem *fileItem = p->db.Files + fileIndex; - *offset = 0; - for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) - *offset += (UInt32)p->db.Files[i].Size; - *outSizeProcessed = (size_t)fileItem->Size; - if (*offset + *outSizeProcessed > *outBufferSize) - return SZ_ERROR_FAIL; - { - if (fileItem->FileCRCDefined) - { - if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) - res = SZ_ERROR_CRC; - } - } - } - return res; -} diff --git a/lzma/C/Archive/7z/7zExtract.h b/lzma/C/Archive/7z/7zExtract.h deleted file mode 100644 index e171f4ab8..000000000 --- a/lzma/C/Archive/7z/7zExtract.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 7zExtract.h -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_EXTRACT_H -#define __7Z_EXTRACT_H - -#include "7zIn.h" - -/* - SzExtract extracts file from archive - - *outBuffer must be 0 before first call for each new archive. - - Extracting cache: - If you need to decompress more than one file, you can send - these values from previous call: - *blockIndex, - *outBuffer, - *outBufferSize - You can consider "*outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - If you use external function, you can declare these 3 cache variables - (blockIndex, outBuffer, outBufferSize) as static in that external function. - - Free *outBuffer and set *outBuffer to 0, if you want to flush cache. -*/ - -SRes SzAr_Extract( - const CSzArEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - -#endif diff --git a/lzma/C/Archive/7z/7zHeader.c b/lzma/C/Archive/7z/7zHeader.c deleted file mode 100644 index c44ff4a48..000000000 --- a/lzma/C/Archive/7z/7zHeader.c +++ /dev/null @@ -1,6 +0,0 @@ -/* 7zHeader.c -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zHeader.h" - -Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; diff --git a/lzma/C/Archive/7z/7zHeader.h b/lzma/C/Archive/7z/7zHeader.h deleted file mode 100644 index 1ef8c0196..000000000 --- a/lzma/C/Archive/7z/7zHeader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 7zHeader.h -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_HEADER_H -#define __7Z_HEADER_H - -#include "../../Types.h" - -#define k7zSignatureSize 6 -extern Byte k7zSignature[k7zSignatureSize]; - -#define k7zMajorVersion 0 - -#define k7zStartHeaderSize 0x20 - -enum EIdEnum -{ - k7zIdEnd, - - k7zIdHeader, - - k7zIdArchiveProperties, - - k7zIdAdditionalStreamsInfo, - k7zIdMainStreamsInfo, - k7zIdFilesInfo, - - k7zIdPackInfo, - k7zIdUnpackInfo, - k7zIdSubStreamsInfo, - - k7zIdSize, - k7zIdCRC, - - k7zIdFolder, - - k7zIdCodersUnpackSize, - k7zIdNumUnpackStream, - - k7zIdEmptyStream, - k7zIdEmptyFile, - k7zIdAnti, - - k7zIdName, - k7zIdCTime, - k7zIdATime, - k7zIdMTime, - k7zIdWinAttributes, - k7zIdComment, - - k7zIdEncodedHeader, - - k7zIdStartPos, - k7zIdDummy -}; - -#endif diff --git a/lzma/C/Archive/7z/7zIn.h b/lzma/C/Archive/7z/7zIn.h deleted file mode 100644 index 717fe52c9..000000000 --- a/lzma/C/Archive/7z/7zIn.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 7zIn.h -- 7z Input functions -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_IN_H -#define __7Z_IN_H - -#include "7zHeader.h" -#include "7zItem.h" - -typedef struct -{ - CSzAr db; - - UInt64 startPosAfterHeader; - UInt64 dataPos; - - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; - UInt32 *FileIndexToFolderIndexMap; -} CSzArEx; - -void SzArEx_Init(CSzArEx *p); -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); - -/* -Errors: -SZ_ERROR_NO_ARCHIVE -SZ_ERROR_ARCHIVE -SZ_ERROR_UNSUPPORTED -SZ_ERROR_MEM -SZ_ERROR_CRC -SZ_ERROR_INPUT_EOF -SZ_ERROR_FAIL -*/ - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); - -#endif diff --git a/lzma/C/Archive/7z/7zItem.c b/lzma/C/Archive/7z/7zItem.c deleted file mode 100644 index a11d5008f..000000000 --- a/lzma/C/Archive/7z/7zItem.c +++ /dev/null @@ -1,127 +0,0 @@ -/* 7zItem.c -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zItem.h" - -void SzCoderInfo_Init(CSzCoderInfo *p) -{ - Buf_Init(&p->Props); -} - -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) -{ - Buf_Free(&p->Props, alloc); - SzCoderInfo_Init(p); -} - -void SzFolder_Init(CSzFolder *p) -{ - p->Coders = 0; - p->BindPairs = 0; - p->PackStreams = 0; - p->UnpackSizes = 0; - p->NumCoders = 0; - p->NumBindPairs = 0; - p->NumPackStreams = 0; - p->UnpackCRCDefined = 0; - p->UnpackCRC = 0; - p->NumUnpackStreams = 0; -} - -void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Coders) - for (i = 0; i < p->NumCoders; i++) - SzCoderInfo_Free(&p->Coders[i], alloc); - IAlloc_Free(alloc, p->Coders); - IAlloc_Free(alloc, p->BindPairs); - IAlloc_Free(alloc, p->PackStreams); - IAlloc_Free(alloc, p->UnpackSizes); - SzFolder_Init(p); -} - -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) -{ - UInt32 result = 0; - UInt32 i; - for (i = 0; i < p->NumCoders; i++) - result += p->Coders[i].NumOutStreams; - return result; -} - -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].InIndex == inStreamIndex) - return i; - return -1; -} - - -int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].OutIndex == outStreamIndex) - return i; - return -1; -} - -UInt64 SzFolder_GetUnpackSize(CSzFolder *p) -{ - int i = (int)SzFolder_GetNumOutStreams(p); - if (i == 0) - return 0; - for (i--; i >= 0; i--) - if (SzFolder_FindBindPairForOutStream(p, i) < 0) - return p->UnpackSizes[i]; - /* throw 1; */ - return 0; -} - -void SzFile_Init(CSzFileItem *p) -{ - p->HasStream = 1; - p->IsDir = 0; - p->IsAnti = 0; - p->FileCRCDefined = 0; - p->MTimeDefined = 0; - p->Name = 0; -} - -static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->Name); - SzFile_Init(p); -} - -void SzAr_Init(CSzAr *p) -{ - p->PackSizes = 0; - p->PackCRCsDefined = 0; - p->PackCRCs = 0; - p->Folders = 0; - p->Files = 0; - p->NumPackStreams = 0; - p->NumFolders = 0; - p->NumFiles = 0; -} - -void SzAr_Free(CSzAr *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Folders) - for (i = 0; i < p->NumFolders; i++) - SzFolder_Free(&p->Folders[i], alloc); - if (p->Files) - for (i = 0; i < p->NumFiles; i++) - SzFile_Free(&p->Files[i], alloc); - IAlloc_Free(alloc, p->PackSizes); - IAlloc_Free(alloc, p->PackCRCsDefined); - IAlloc_Free(alloc, p->PackCRCs); - IAlloc_Free(alloc, p->Folders); - IAlloc_Free(alloc, p->Files); - SzAr_Init(p); -} diff --git a/lzma/C/Archive/7z/7zItem.h b/lzma/C/Archive/7z/7zItem.h deleted file mode 100644 index 190b2e2a9..000000000 --- a/lzma/C/Archive/7z/7zItem.h +++ /dev/null @@ -1,84 +0,0 @@ -/* 7zItem.h -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ITEM_H -#define __7Z_ITEM_H - -#include "../../7zBuf.h" - -typedef struct -{ - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; -} CSzCoderInfo; - -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - -typedef struct -{ - UInt32 InIndex; - UInt32 OutIndex; -} CBindPair; - -typedef struct -{ - CSzCoderInfo *Coders; - CBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; - UInt32 NumCoders; - UInt32 NumBindPairs; - UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; -} CSzFolder; - -void SzFolder_Init(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); - -typedef struct CNtfsFileTime -{ - UInt32 Low; - UInt32 High; -} CNtfsFileTime; - -typedef struct CSzFileItem -{ - CNtfsFileTime MTime; - UInt64 Size; - char *Name; - UInt32 FileCRC; - - Byte HasStream; - Byte IsDir; - Byte IsAnti; - Byte FileCRCDefined; - Byte MTimeDefined; -} CSzFileItem; - -void SzFile_Init(CSzFileItem *p); - -typedef struct CSzAr -{ - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; - UInt32 NumPackStreams; - UInt32 NumFolders; - UInt32 NumFiles; -} CSzAr; - -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); - -#endif diff --git a/lzma/C/Bcj2.h b/lzma/C/Bcj2.h index f58e3bcb4..d9d857bc3 100644 --- a/lzma/C/Bcj2.h +++ b/lzma/C/Bcj2.h @@ -1,11 +1,15 @@ /* Bcj2.h -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Conditions: outSize <= FullOutputSize, @@ -27,4 +31,8 @@ int Bcj2_Decode( const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/Bra.c b/lzma/C/Bra.c new file mode 100644 index 000000000..2a0f147b2 --- /dev/null +++ b/lzma/C/Bra.c @@ -0,0 +1,133 @@ +/* Bra.c -- Converters for RISC code +2010-04-16 : Igor Pavlov : Public domain */ + +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 8; + for (i = 0; i <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 dest; + UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 2; + data[i + 2] = (Byte)(dest >> 16); + data[i + 1] = (Byte)(dest >> 8); + data[i + 0] = (Byte)dest; + } + } + return i; +} + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 4; + for (i = 0; i <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 dest; + UInt32 src = + (((UInt32)data[i + 1] & 0x7) << 19) | + ((UInt32)data[i + 0] << 11) | + (((UInt32)data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 1; + + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); + data[i + 0] = (Byte)(dest >> 11); + data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); + data[i + 2] = (Byte)dest; + i += 2; + } + } + return i; +} + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) + { + UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + UInt32 i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || + (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + UInt32 dest; + + src <<= 2; + if (encoding) + dest = ip + i + src; + else + dest = src - (ip + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/lzma/C/Bra.h b/lzma/C/Bra.h index b9018eb99..9c91e332d 100644 --- a/lzma/C/Bra.h +++ b/lzma/C/Bra.h @@ -1,11 +1,15 @@ /* Bra.h -- Branch converters for executables -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. @@ -57,4 +61,8 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/CpuArch.c b/lzma/C/CpuArch.c new file mode 100644 index 000000000..36e7680d9 --- /dev/null +++ b/lzma/C/CpuArch.c @@ -0,0 +1,168 @@ +/* CpuArch.c -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag)); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #else + + __asm__ __volatile__ ( + "cpuid" + : "=a" (*a) , + "=b" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #endif + + #else + + int CPUInfo[4]; + __cpuid(CPUInfo, function); + *a = CPUInfo[0]; + *b = CPUInfo[1]; + *c = CPUInfo[2]; + *d = CPUInfo[3]; + + #endif +} + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +Bool CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + family = x86cpuid_GetFamily(&p); + model = x86cpuid_GetModel(&p); + firm = x86cpuid_GetFirm(&p); + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C)); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +static Bool CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + +Bool CPU_Is_Aes_Supported() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + return (p.c >> 25) & 1; +} + +#endif diff --git a/lzma/C/CpuArch.h b/lzma/C/CpuArch.h index db441641b..0a709bb26 100644 --- a/lzma/C/CpuArch.h +++ b/lzma/C/CpuArch.h @@ -1,29 +1,73 @@ -/* CpuArch.h -2008-08-05 -Igor Pavlov -Public domain */ +/* CpuArch.h -- CPU specific code +2010-10-26: Igor Pavlov : Public domain */ -#ifndef __CPUARCH_H -#define __CPUARCH_H +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "Types.h" + +EXTERN_C_BEGIN /* -LITTLE_ENDIAN_UNALIGN means: - 1) CPU is LITTLE_ENDIAN - 2) it's allowed to make unaligned memory accesses -if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know -about these properties of platform. +MY_CPU_LE means that CPU is LITTLE ENDIAN. +If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. */ -#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) -#define LITTLE_ENDIAN_UNALIGN +#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) +#define MY_CPU_AMD64 #endif -#ifdef LITTLE_ENDIAN_UNALIGN +#if defined(MY_CPU_AMD64) || defined(_M_IA64) +#define MY_CPU_64BIT +#endif + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#if defined(_WIN32) && defined(_M_ARM) +#define MY_CPU_ARM_LE +#endif + +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) +#define MY_CPU_LE_UNALIGN +#endif + +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) +#define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + +#ifdef MY_CPU_LE_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); #define SetUi32(p, d) *(UInt32 *)(p) = (d); +#define SetUi64(p, d) *(UInt64 *)(p) = (d); #else @@ -37,18 +81,24 @@ about these properties of platform. #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) +#define SetUi16(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } + #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } +#define SetUi64(p, d) { UInt64 _x64_ = (d); \ + SetUi32(p, (UInt32)_x64_); \ + SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } + #endif -#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) +#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) -unsigned long _byteswap_ulong(unsigned long); -unsigned __int64 _byteswap_uint64(unsigned __int64); #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) @@ -68,4 +118,38 @@ unsigned __int64 _byteswap_uint64(unsigned __int64); #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) +#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) +#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + #endif diff --git a/lzma/C/LzFind.c b/lzma/C/LzFind.c index e0ebe6235..f6c9e66d5 100644 --- a/lzma/C/LzFind.c +++ b/lzma/C/LzFind.c @@ -1,5 +1,5 @@ /* LzFind.c -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ #include @@ -58,6 +58,17 @@ static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - p->streamPos; + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); @@ -88,6 +99,8 @@ void MatchFinder_MoveBlock(CMatchFinder *p) int MatchFinder_NeedMove(CMatchFinder *p) { + if (p->directInput) + return 0; /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } @@ -112,8 +125,6 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p) p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; - /* p->skipModeBits = 0; */ - p->directInput = 0; p->bigHash = 0; } @@ -177,7 +188,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { - UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 newCyclicBufferSize = historySize + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { @@ -192,7 +203,6 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; - /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { diff --git a/lzma/C/LzFind.h b/lzma/C/LzFind.h index 423d67e0c..7ebdfa446 100644 --- a/lzma/C/LzFind.h +++ b/lzma/C/LzFind.h @@ -1,11 +1,15 @@ /* LzFind.h -- Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-04-22 : Igor Pavlov : Public domain */ -#ifndef __LZFIND_H -#define __LZFIND_H +#ifndef __LZ_FIND_H +#define __LZ_FIND_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef UInt32 CLzRef; typedef struct _CMatchFinder @@ -35,8 +39,8 @@ typedef struct _CMatchFinder UInt32 numHashBytes; int directInput; + size_t directInputRem; int btMode; - /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; @@ -104,4 +108,8 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzFindMt.c b/lzma/C/LzFindMt.c index a67899ab0..db95590c3 100644 --- a/lzma/C/LzFindMt.c +++ b/lzma/C/LzFindMt.c @@ -1,5 +1,5 @@ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ #include "LzHash.h" @@ -97,7 +97,7 @@ void MtSync_Destruct(CMtSync *p) #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } -static SRes MtSync_Create2(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; @@ -119,7 +119,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAdd return SZ_OK; } -static SRes MtSync_Create(CMtSync *p, unsigned (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *obj, UInt32 numBlocks) +static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) @@ -143,7 +143,7 @@ DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) -DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ void HashThreadFunc(CMatchFinderMt *mt) { @@ -451,8 +451,8 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) -static unsigned THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } -static unsigned THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; @@ -711,47 +711,47 @@ UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) return len; } -#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED -#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; -#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER2 { p->btNumAvailBytes--; - SKIP_FOOTER + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(2) + SKIP_HEADER_MT(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(3) + SKIP_HEADER_MT(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { - SKIP_HEADER(4) + SKIP_HEADER_MT(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; - SKIP_FOOTER + SKIP_FOOTER_MT } */ diff --git a/lzma/C/LzFindMt.h b/lzma/C/LzFindMt.h index b7ead2d47..17ed237d6 100644 --- a/lzma/C/LzFindMt.h +++ b/lzma/C/LzFindMt.h @@ -1,11 +1,15 @@ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZFINDMT_H -#define __LZFINDMT_H +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H -#include "Threads.h" #include "LzFind.h" +#include "Threads.h" + +#ifdef __cplusplus +extern "C" { +#endif #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) @@ -94,4 +98,8 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzHash.h b/lzma/C/LzHash.h index c92341750..b2f0e3c24 100644 --- a/lzma/C/LzHash.h +++ b/lzma/C/LzHash.h @@ -1,8 +1,8 @@ /* LzHash.h -- HASH functions for LZ algorithms -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZHASH_H -#define __LZHASH_H +#ifndef __LZ_HASH_H +#define __LZ_HASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) diff --git a/lzma/C/Lzma2Dec.c b/lzma/C/Lzma2Dec.c new file mode 100644 index 000000000..8f2406755 --- /dev/null +++ b/lzma/C/Lzma2Dec.c @@ -0,0 +1,356 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - EOS +00000001 U U - Uncompressed Reset Dic +00000010 U U - Uncompressed No Reset +100uuuuu U U P P - LZMA no reset +101uuuuu U U P P - LZMA reset state +110uuuuu U U P P S - LZMA reset state + new prop +111uuuuu U U P P S - LZMA reset state + new prop + reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) + +#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) +#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) + +#define LZMA2_LCLP_MAX 4 +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +typedef enum +{ + LZMA2_STATE_CONTROL, + LZMA2_STATE_UNPACK0, + LZMA2_STATE_UNPACK1, + LZMA2_STATE_PACK0, + LZMA2_STATE_PACK1, + LZMA2_STATE_PROP, + LZMA2_STATE_DATA, + LZMA2_STATE_DATA_CONT, + LZMA2_STATE_FINISHED, + LZMA2_STATE_ERROR +} ELzma2State; + +static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) +{ + UInt32 dicSize; + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); + props[0] = (Byte)LZMA2_LCLP_MAX; + props[1] = (Byte)(dicSize); + props[2] = (Byte)(dicSize >> 8); + props[3] = (Byte)(dicSize >> 16); + props[4] = (Byte)(dicSize >> 24); + return SZ_OK; +} + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +void Lzma2Dec_Init(CLzma2Dec *p) +{ + p->state = LZMA2_STATE_CONTROL; + p->needInitDic = True; + p->needInitState = True; + p->needInitProp = True; + LzmaDec_Init(&p->decoder); +} + +static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch(p->state) + { + case LZMA2_STATE_CONTROL: + p->control = b; + PRF(printf("\n %4X ", p->decoder.dicPos)); + PRF(printf(" %2X", b)); + if (p->control == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if ((p->control & 0x7F) > 2) + return LZMA2_STATE_ERROR; + p->unpackSize = 0; + } + else + p->unpackSize = (UInt32)(p->control & 0x1F) << 16; + return LZMA2_STATE_UNPACK0; + + case LZMA2_STATE_UNPACK0: + p->unpackSize |= (UInt32)b << 8; + return LZMA2_STATE_UNPACK1; + + case LZMA2_STATE_UNPACK1: + p->unpackSize |= (UInt32)b; + p->unpackSize++; + PRF(printf(" %8d", p->unpackSize)); + return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; + + case LZMA2_STATE_PACK0: + p->packSize = (UInt32)b << 8; + return LZMA2_STATE_PACK1; + + case LZMA2_STATE_PACK1: + p->packSize |= (UInt32)b; + p->packSize++; + PRF(printf(" %8d", p->packSize)); + return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: + (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); + + case LZMA2_STATE_PROP: + { + int lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = b / 5; + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = lc; + p->decoder.prop.lp = lp; + p->needInitProp = False; + return LZMA2_STATE_DATA; + } + } + return LZMA2_STATE_ERROR; +} + +static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) +{ + memcpy(p->dic + p->dicPos, src, size); + p->dicPos += size; + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) + p->checkDicSize = p->prop.dicSize; + p->processedPos += (UInt32)size; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->state != LZMA2_STATE_FINISHED) + { + SizeT dicPos = p->decoder.dicPos; + if (p->state == LZMA2_STATE_ERROR) + return SZ_ERROR_DATA; + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + continue; + } + { + SizeT destSizeCur = dicLimit - dicPos; + SizeT srcSizeCur = inSize - *srcLen; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (p->unpackSize <= destSizeCur) + { + destSizeCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + if (initDic) + p->needInitProp = p->needInitState = True; + else if (p->needInitDic) + return SZ_ERROR_DATA; + p->needInitDic = False; + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (srcSizeCur > destSizeCur) + srcSizeCur = destSizeCur; + + if (srcSizeCur == 0) + return SZ_ERROR_DATA; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->unpackSize -= (UInt32)srcSizeCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SizeT outSizeProcessed; + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + int mode = LZMA2_GET_LZMA_MODE(p); + Bool initDic = (mode == 3); + Bool initState = (mode > 0); + if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) + return SZ_ERROR_DATA; + + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->needInitDic = False; + p->needInitState = False; + p->state = LZMA2_STATE_DATA_CONT; + } + if (srcSizeCur > p->packSize) + srcSizeCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->packSize -= (UInt32)srcSizeCur; + + outSizeProcessed = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outSizeProcessed; + + RINOK(res); + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + return res; + + if (srcSizeCur == 0 && outSizeProcessed == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || + p->unpackSize != 0 || p->packSize != 0) + return SZ_ERROR_DATA; + p->state = LZMA2_STATE_CONTROL; + } + if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + *status = LZMA_STATUS_NOT_FINISHED; + } + } + } + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen, inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT srcSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + if (outSize > p->decoder.dicBufSize - dicPos) + { + outSizeCur = p->decoder.dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); + src += srcSizeCur; + inSize -= srcSizeCur; + *srcLen += srcSizeCur; + outSizeCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzma2Dec decoder; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + Byte props[LZMA_PROPS_SIZE]; + + Lzma2Dec_Construct(&decoder); + + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + decoder.decoder.dic = dest; + decoder.decoder.dicBufSize = outSize; + + RINOK(Lzma2Dec_GetOldProps(prop, props)); + RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); + + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); + *destLen = decoder.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + LzmaDec_FreeProbs(&decoder.decoder, alloc); + return res; +} diff --git a/lzma/C/Lzma2Dec.h b/lzma/C/Lzma2Dec.h new file mode 100644 index 000000000..827698dee --- /dev/null +++ b/lzma/C/Lzma2Dec.h @@ -0,0 +1,84 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2009-05-03 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------- State Interface ---------- */ + +typedef struct +{ + CLzmaDec decoder; + UInt32 packSize; + UInt32 unpackSize; + int state; + Byte control; + Bool needInitDic; + Bool needInitState; + Bool needInitProp; +} CLzma2Dec; + +#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +void Lzma2Dec_Init(CLzma2Dec *p); + + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen or dicLimit). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + SZ_ERROR_DATA - Data error +*/ + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lzma/C/LzmaDec.c b/lzma/C/LzmaDec.c index eb5250174..4fdc11d4b 100644 --- a/lzma/C/LzmaDec.c +++ b/lzma/C/LzmaDec.c @@ -1,5 +1,5 @@ /* LzmaDec.c -- LZMA Decoder -2008-11-06 : Igor Pavlov : Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ #include "LzmaDec.h" @@ -113,12 +113,6 @@ StopCompilingDueBUG #endif -static const Byte kLiteralNextStates[kNumStates * 2] = -{ - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, - 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 -}; - #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. @@ -175,6 +169,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte if (state < kNumLitStates) { + state -= (state < 4) ? state : 3; symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } @@ -182,6 +177,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; symbol = 1; do { @@ -196,9 +192,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte } dic[dicPos++] = (Byte)symbol; processedPos++; - - state = kLiteralNextStates[state]; - /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else @@ -378,7 +371,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; diff --git a/lzma/C/LzmaDec.h b/lzma/C/LzmaDec.h index 9ec549c86..6741a644b 100644 --- a/lzma/C/LzmaDec.h +++ b/lzma/C/LzmaDec.h @@ -1,11 +1,15 @@ /* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMADEC_H -#define __LZMADEC_H +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ @@ -66,13 +70,7 @@ typedef struct #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } -#ifdef __cplusplus -extern "C" { -#endif void LzmaDec_Init(CLzmaDec *p); -#ifdef __cplusplus -} -#endif /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. @@ -132,11 +130,7 @@ LzmaDec_Allocate* can return: SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ - -#ifdef __cplusplus -extern "C" { -#endif - + SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); diff --git a/lzma/C/LzmaEnc.c b/lzma/C/LzmaEnc.c index 529fd98f8..9e6dbdbe2 100644 --- a/lzma/C/LzmaEnc.c +++ b/lzma/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2009-02-02 : Igor Pavlov : Public domain */ +2010-04-16 : Igor Pavlov : Public domain */ #include @@ -13,7 +13,7 @@ #include "LzmaEnc.h" #include "LzFind.h" -#ifdef COMPRESS_MF_MT +#ifndef _7ZIP_ST #include "LzFindMt.h" #endif @@ -66,7 +66,7 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p) if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST ((p->btMode && p->algo) ? 2 : 1); #else 1; @@ -139,7 +139,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos) typedef unsigned CState; -typedef struct _COptimal +typedef struct { UInt32 price; @@ -172,7 +172,7 @@ typedef struct _COptimal #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) -#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 @@ -218,7 +218,7 @@ typedef struct UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; -typedef struct _CRangeEnc +typedef struct { UInt32 range; Byte cache; @@ -232,26 +232,6 @@ typedef struct _CRangeEnc SRes res; } CRangeEnc; -typedef struct _CSeqInStreamBuf -{ - ISeqInStream funcTable; - const Byte *data; - SizeT rem; -} CSeqInStreamBuf; - -static SRes MyRead(void *pp, void *data, size_t *size) -{ - size_t curSize = *size; - CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; - if (p->rem < curSize) - curSize = p->rem; - memcpy(data, p->data, curSize); - p->rem -= curSize; - p->data += curSize; - *size = curSize; - return SZ_OK; -} - typedef struct { CLzmaProb *litProbs; @@ -274,19 +254,19 @@ typedef struct UInt32 state; } CSaveState; -typedef struct _CLzmaEnc +typedef struct { IMatchFinder matchFinder; void *matchFinderObj; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Byte pad[128]; #endif @@ -351,8 +331,7 @@ typedef struct _CLzmaEnc UInt32 dictSize; UInt32 matchFinderCycles; - ISeqInStream *inStream; - CSeqInStreamBuf seqBufInStream; + int needInit; CSaveState saveState; } CLzmaEnc; @@ -416,7 +395,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || - props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) + props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; @@ -449,7 +428,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) p->writeEndMark = props.writeEndMark; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST /* if (newMultiThread != _multiThread) { @@ -1698,7 +1677,7 @@ void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif @@ -1737,7 +1716,7 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); @@ -1754,11 +1733,10 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; - if (p->inStream != 0) + if (p->needInit) { - p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); - p->inStream = 0; + p->needInit = 0; } if (p->finished) @@ -1923,7 +1901,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif @@ -1948,7 +1926,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); @@ -2056,11 +2034,12 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a return SZ_OK; } -static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } @@ -2070,15 +2049,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; + p->matchFinderBase.stream = inStream; + p->needInit = 1; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { - p->seqBufInStream.funcTable.Read = MyRead; - p->seqBufInStream.data = src; - p->seqBufInStream.rem = srcLen; + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, @@ -2086,13 +2066,14 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); - p->inStream = &p->seqBufInStream.funcTable; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); @@ -2101,7 +2082,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp) #endif } -typedef struct _CSeqOutStreamBuf +typedef struct { ISeqOutStream funcTable; Byte *data; @@ -2170,21 +2151,17 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, return res; } -SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, - ISzAlloc *alloc, ISzAlloc *allocBig) +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) { - CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; - #ifdef COMPRESS_MF_MT + #ifndef _7ZIP_ST Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif - RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); - for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); @@ -2200,10 +2177,17 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i } } } - LzmaEnc_Finish(pp); + LzmaEnc_Finish(p); return res; } +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; @@ -2249,8 +2233,11 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte outStream.overflow = False; p->writeEndMark = writeEndMark; - res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, - progress, alloc, allocBig); + + p->rc.outStream = &outStream.funcTable; + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + if (res == SZ_OK) + res = LzmaEnc_Encode2(p, progress); *destLen -= outStream.rem; if (outStream.overflow) diff --git a/lzma/C/LzmaEnc.h b/lzma/C/LzmaEnc.h index e3d84fa35..999f5afff 100644 --- a/lzma/C/LzmaEnc.h +++ b/lzma/C/LzmaEnc.h @@ -1,11 +1,15 @@ /* LzmaEnc.h -- LZMA Encoder -2008-10-04 : Igor Pavlov : Public domain */ +2009-02-07 : Igor Pavlov : Public domain */ -#ifndef __LZMAENC_H -#define __LZMAENC_H +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps @@ -69,4 +73,8 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lzma/C/LzmaLib.c b/lzma/C/LzmaLib.c deleted file mode 100644 index 3e3cf40ae..000000000 --- a/lzma/C/LzmaLib.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LzmaLib.c -- LZMA library wrapper -2008-08-05 -Igor Pavlov -Public domain */ - -#include "LzmaEnc.h" -#include "LzmaDec.h" -#include "Alloc.h" -#include "LzmaLib.h" - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ -) -{ - CLzmaEncProps props; - LzmaEncProps_Init(&props); - props.level = level; - props.dictSize = dictSize; - props.lc = lc; - props.lp = lp; - props.pb = pb; - props.fb = fb; - props.numThreads = numThreads; - - return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, - NULL, &g_Alloc, &g_Alloc); -} - - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, - const unsigned char *props, size_t propsSize) -{ - ELzmaStatus status; - return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); -} diff --git a/lzma/C/LzmaLib.h b/lzma/C/LzmaLib.h deleted file mode 100644 index 849d347e9..000000000 --- a/lzma/C/LzmaLib.h +++ /dev/null @@ -1,135 +0,0 @@ -/* LzmaLib.h -- LZMA library interface -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __LZMALIB_H -#define __LZMALIB_H - -#include "Types.h" - -#ifdef __cplusplus - #define MY_EXTERN_C extern "C" -#else - #define MY_EXTERN_C extern -#endif - -#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL - -#define LZMA_PROPS_SIZE 5 - -/* -RAM requirements for LZMA: - for compression: (dictSize * 11.5 + 6 MB) + state_size - for decompression: dictSize + state_size - state_size = (4 + (1.5 << (lc + lp))) KB - by default (lc=3, lp=0), state_size = 16 KB. - -LZMA properties (5 bytes) format - Offset Size Description - 0 1 lc, lp and pb in encoded form. - 1 4 dictSize (little endian). -*/ - -/* -LzmaCompress ------------- - -outPropsSize - - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. - - LZMA Encoder will use defult values for any parameter, if it is - -1 for any from: level, loc, lp, pb, fb, numThreads - 0 for dictSize - -level - compression level: 0 <= level <= 9; - - level dictSize algo fb - 0: 16 KB 0 32 - 1: 64 KB 0 32 - 2: 256 KB 0 32 - 3: 1 MB 0 32 - 4: 4 MB 0 32 - 5: 16 MB 1 32 - 6: 32 MB 1 32 - 7+: 64 MB 1 64 - - The default value for "level" is 5. - - algo = 0 means fast method - algo = 1 means normal method - -dictSize - The dictionary size in bytes. The maximum value is - 128 MB = (1 << 27) bytes for 32-bit version - 1 GB = (1 << 30) bytes for 64-bit version - The default value is 16 MB = (1 << 24) bytes. - It's recommended to use the dictionary that is larger than 4 KB and - that can be calculated as (1 << N) or (3 << N) sizes. - -lc - The number of literal context bits (high bits of previous literal). - It can be in the range from 0 to 8. The default value is 3. - Sometimes lc=4 gives the gain for big files. - -lp - The number of literal pos bits (low bits of current position for literals). - It can be in the range from 0 to 4. The default value is 0. - The lp switch is intended for periodical data when the period is equal to 2^lp. - For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's - better to set lc=0, if you change lp switch. - -pb - The number of pos bits (low bits of current position). - It can be in the range from 0 to 4. The default value is 2. - The pb switch is intended for periodical data when the period is equal 2^pb. - -fb - Word size (the number of fast bytes). - It can be in the range from 5 to 273. The default value is 32. - Usually, a big number gives a little bit better compression ratio and - slower compression process. - -numThreads - The number of thereads. 1 or 2. The default value is 2. - Fast mode (algo = 0) can use only 1 thread. - -Out: - destLen - processed output size -Returns: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) -*/ - -MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, - unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ - int level, /* 0 <= level <= 9, default = 5 */ - unsigned dictSize, /* default = (1 << 24) */ - int lc, /* 0 <= lc <= 8, default = 3 */ - int lp, /* 0 <= lp <= 4, default = 0 */ - int pb, /* 0 <= pb <= 4, default = 2 */ - int fb, /* 5 <= fb <= 273, default = 32 */ - int numThreads /* 1 or 2, default = 2 */ - ); - -/* -LzmaUncompress --------------- -In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size -Out: - destLen - processed output size - srcLen - processed input size -Returns: - SZ_OK - OK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation arror - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) -*/ - -MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, - const unsigned char *props, size_t propsSize); - -#endif diff --git a/lzma/C/Threads.c b/lzma/C/Threads.c index 64d871abe..4be44fb0f 100644 --- a/lzma/C/Threads.c +++ b/lzma/C/Threads.c @@ -1,13 +1,12 @@ /* Threads.c -- multithreading library -2008-08-05 -Igor Pavlov -Public domain */ +2009-09-20 : Igor Pavlov : Public domain */ + +#ifndef _WIN32_WCE +#include +#endif #include "Threads.h" -#ifdef _WIN32 -#include - static WRes GetError() { DWORD res = GetLastError(); @@ -17,276 +16,69 @@ static WRes GetError() WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } -static WRes MyCloseHandle(HANDLE *h) +WRes HandlePtr_Close(HANDLE *p) { - if (*h != NULL) - if (!CloseHandle(*h)) + if (*p != NULL) + if (!CloseHandle(*p)) return GetError(); - *h = NULL; + *p = NULL; return 0; } -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) +WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ - thread->handle = - /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ - (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); + *p = + #ifdef UNDER_CE + CreateThread(0, 0, func, param, 0, &threadId); + #else + (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + #endif /* maybe we must use errno here, but probably GetLastError() is also OK. */ - return HandleToWRes(thread->handle); + return HandleToWRes(*p); } -WRes WaitObject(HANDLE h) +WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) { - return (WRes)WaitForSingleObject(h, INFINITE); + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); } -WRes Thread_Wait(CThread *thread) +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) { - if (thread->handle == NULL) - return 1; - return WaitObject(thread->handle); + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); } -WRes Thread_Close(CThread *thread) -{ - return MyCloseHandle(&thread->handle); -} - -WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) -{ - p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); - return HandleToWRes(p->handle); -} - -WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) - { return Event_Create(p, TRUE, initialSignaled); } -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) - { return ManualResetEvent_Create(p, 0); } - -WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) - { return Event_Create(p, FALSE, initialSignaled); } -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) - { return AutoResetEvent_Create(p, 0); } - -WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } -WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } -WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } -WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } - - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) -{ - p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); - return HandleToWRes(p->handle); -} - -WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) -{ - return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); -} -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) -{ - return Semaphore_Release(p, (LONG)releaseCount, NULL); -} -WRes Semaphore_Release1(CSemaphore *p) -{ - return Semaphore_ReleaseN(p, 1); -} - -WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } -WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ -#ifndef __GNUC__ + #ifdef _MSC_VER __try -#endif + #endif { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } -#ifndef __GNUC__ + #ifdef _MSC_VER __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } -#endif + #endif return 0; } - -#else - -#include -#include - -#include - -#if defined(__linux__) -#define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP -#endif - - -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *parameter) -{ - pthread_attr_t attr; - int ret; - - thread->_created = 0; - - ret = pthread_attr_init(&attr); - if (ret) return ret; - - ret = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); - if (ret) return ret; - - ret = pthread_create(&thread->_tid, &attr, (void * (*)(void *))startAddress, parameter); - - /* ret2 = */ pthread_attr_destroy(&attr); - - if (ret) return ret; - - thread->_created = 1; - - return 0; // SZ_OK; -} - -WRes Thread_Wait(CThread *thread) -{ - void *thread_return; - int ret; - - if (thread->_created == 0) - return EINVAL; - - ret = pthread_join(thread->_tid,&thread_return); - thread->_created = 0; - - return ret; -} - -WRes Thread_Close(CThread *thread) -{ - if (!thread->_created) return SZ_OK; - - pthread_detach(thread->_tid); - thread->_tid = 0; - thread->_created = 0; - return SZ_OK; -} - -WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) -{ - pthread_mutex_init(&p->_mutex,0); - pthread_cond_init(&p->_cond,0); - p->_manual_reset = manualReset; - p->_state = (initialSignaled ? TRUE : FALSE); - p->_created = 1; - return 0; -} - -WRes Event_Set(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - p->_state = TRUE; - pthread_cond_broadcast(&p->_cond); - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Reset(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - p->_state = FALSE; - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Wait(CEvent *p) { - pthread_mutex_lock(&p->_mutex); - while (p->_state == FALSE) - { - pthread_cond_wait(&p->_cond, &p->_mutex); - } - if (p->_manual_reset == FALSE) - { - p->_state = FALSE; - } - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Event_Close(CEvent *p) { - if (p->_created) - { - p->_created = 0; - pthread_mutex_destroy(&p->_mutex); - pthread_cond_destroy(&p->_cond); - } - return 0; -} - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) -{ - pthread_mutex_init(&p->_mutex,0); - pthread_cond_init(&p->_cond,0); - p->_count = initiallyCount; - p->_maxCount = maxCount; - p->_created = 1; - return 0; -} - -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) -{ - UInt32 newCount; - - if (releaseCount < 1) return EINVAL; - - pthread_mutex_lock(&p->_mutex); - - newCount = p->_count + releaseCount; - if (newCount > p->_maxCount) - { - pthread_mutex_unlock(&p->_mutex); - return EINVAL; - } - p->_count = newCount; - pthread_cond_broadcast(&p->_cond); - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Semaphore_Wait(CSemaphore *p) { - pthread_mutex_lock(&p->_mutex); - while (p->_count < 1) - { - pthread_cond_wait(&p->_cond, &p->_mutex); - } - p->_count--; - pthread_mutex_unlock(&p->_mutex); - return 0; -} - -WRes Semaphore_Close(CSemaphore *p) { - if (p->_created) - { - p->_created = 0; - pthread_mutex_destroy(&p->_mutex); - pthread_cond_destroy(&p->_cond); - } - return 0; -} - -WRes CriticalSection_Init(CCriticalSection * lpCriticalSection) -{ - return pthread_mutex_init(&(lpCriticalSection->_mutex),0); -} - -WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) - { return Event_Create(p, TRUE, initialSignaled); } - -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) - { return ManualResetEvent_Create(p, 0); } - -WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) - { return Event_Create(p, FALSE, initialSignaled); } -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) - { return AutoResetEvent_Create(p, 0); } - -#endif diff --git a/lzma/C/Threads.h b/lzma/C/Threads.h index c895c7e51..6a7afa829 100644 --- a/lzma/C/Threads.h +++ b/lzma/C/Threads.h @@ -1,151 +1,59 @@ /* Threads.h -- multithreading library -2008-11-22 : Igor Pavlov : Public domain */ +2009-03-27 : Igor Pavlov : Public domain */ -#ifndef __7Z_THRESDS_H -#define __7Z_THRESDS_H - -#ifdef _WIN32 -#include -typedef DWORD WRes; +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H #include "Types.h" -typedef struct _CThread -{ - HANDLE handle; -} CThread; +#ifdef __cplusplus +extern "C" { +#endif -#define Thread_Construct(thread) (thread)->handle = NULL -#define Thread_WasCreated(thread) ((thread)->handle != NULL) - +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +typedef HANDLE CThread; +#define Thread_Construct(p) *(p) = NULL +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +#define Thread_Wait(p) Handle_WaitObject(*(p)) typedef unsigned THREAD_FUNC_RET_TYPE; -#define THREAD_FUNC_CALL_TYPE __stdcall +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); -WRes Thread_Wait(CThread *thread); -WRes Thread_Close(CThread *thread); - -typedef struct _CEvent -{ - HANDLE handle; -} CEvent; - +typedef HANDLE CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); -#define Event_Construct(event) (event)->handle = NULL -#define Event_IsCreated(event) ((event)->handle != NULL) - -WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); -WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); -WRes Event_Set(CEvent *event); -WRes Event_Reset(CEvent *event); -WRes Event_Wait(CEvent *event); -WRes Event_Close(CEvent *event); - - -typedef struct _CSemaphore -{ - HANDLE handle; -} CSemaphore; - -#define Semaphore_Construct(p) (p)->handle = NULL - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) (*p) = NULL +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); -WRes Semaphore_Wait(CSemaphore *p); -WRes Semaphore_Close(CSemaphore *p); - typedef CRITICAL_SECTION CCriticalSection; - WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) -#else -typedef int WRes; - -#include "Types.h" -#include - -/* #define DEBUG_SYNCHRO 1 */ - -typedef struct _CThread -{ - pthread_t _tid; - int _created; - -} CThread; - -#define Thread_Construct(thread) (thread)->_created = 0 -#define Thread_WasCreated(thread) ((thread)->_created != 0) - -typedef unsigned THREAD_FUNC_RET_TYPE; -#define THREAD_FUNC_CALL_TYPE -#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE - -WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), void *parameter); -WRes Thread_Wait(CThread *thread); -WRes Thread_Close(CThread *thread); - -typedef struct _CEvent -{ - int _created; - int _manual_reset; - int _state; - pthread_mutex_t _mutex; - pthread_cond_t _cond; -} CEvent; - -typedef CEvent CAutoResetEvent; -typedef CEvent CManualResetEvent; - -#define Event_Construct(event) (event)->_created = 0 -#define Event_IsCreated(event) ((event)->_created) - -WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); -WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); -WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); -WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); -WRes Event_Set(CEvent *event); -WRes Event_Reset(CEvent *event); -WRes Event_Wait(CEvent *event); -WRes Event_Close(CEvent *event); - - -typedef struct _CSemaphore -{ - int _created; - UInt32 _count; - UInt32 _maxCount; - pthread_mutex_t _mutex; - pthread_cond_t _cond; -} CSemaphore; - -#define Semaphore_Construct(p) (p)->_created = 0 - -WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); -WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); -#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) -WRes Semaphore_Wait(CSemaphore *p); -WRes Semaphore_Close(CSemaphore *p); - -typedef struct { - pthread_mutex_t _mutex; -} CCriticalSection; - -WRes CriticalSection_Init(CCriticalSection *p); -#define CriticalSection_Delete(p) pthread_mutex_destroy(&((p)->_mutex)) -#define CriticalSection_Enter(p) pthread_mutex_lock(&((p)->_mutex)) -#define CriticalSection_Leave(p) pthread_mutex_unlock(&((p)->_mutex)) - +#ifdef __cplusplus +} #endif #endif - diff --git a/lzma/C/Types.h b/lzma/C/Types.h index 958b2af2d..834709bb9 100644 --- a/lzma/C/Types.h +++ b/lzma/C/Types.h @@ -1,15 +1,27 @@ /* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ +2010-10-09 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include -#ifdef __cplusplus -extern "C" { +#ifdef _WIN32 +#include #endif +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + #define SZ_OK 0 #define SZ_ERROR_DATA 1 @@ -30,6 +42,12 @@ extern "C" { typedef int SRes; +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif @@ -37,10 +55,8 @@ typedef int SRes; #if defined(__APPLE__) && !__LP64__ #define _LZMA_UINT32_IS_ULONG #endif - -#ifndef ZCONF_H + typedef unsigned char Byte; -#endif typedef short Int16; typedef unsigned short UInt16; @@ -65,9 +81,11 @@ typedef unsigned long UInt64; #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n #else typedef long long int Int64; typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL #endif #endif @@ -83,6 +101,12 @@ typedef int Bool; #define False 0 +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + #ifdef _MSC_VER #if _MSC_VER >= 1300 @@ -92,13 +116,11 @@ typedef int Bool; #endif #define MY_CDECL __cdecl -#define MY_STD_CALL __stdcall -#define MY_FAST_CALL MY_NO_INLINE __fastcall +#define MY_FAST_CALL __fastcall #else #define MY_CDECL -#define MY_STD_CALL #define MY_FAST_CALL #endif @@ -106,6 +128,16 @@ typedef int Bool; /* The following interfaces use first parameter as pointer to structure */ +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); @@ -140,7 +172,7 @@ typedef struct typedef struct { - SRes (*Look)(void *p, void **buf, size_t *size); + SRes (*Look)(void *p, const void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ @@ -205,8 +237,22 @@ typedef struct #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) -#ifdef __cplusplus -} +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + #endif + +EXTERN_C_END #endif diff --git a/lzma/CMakeLists.txt b/lzma/CMakeLists.txt index 019383d42..beebb0fde 100644 --- a/lzma/CMakeLists.txt +++ b/lzma/CMakeLists.txt @@ -7,25 +7,25 @@ if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) set( LZMA_FILES - C/Archive/7z/7zDecode.c - C/Archive/7z/7zExtract.c - C/Archive/7z/7zHeader.c - C/Archive/7z/7zIn.c - C/Archive/7z/7zItem.c C/7zBuf.c C/7zCrc.c + C/7zCrcOpt.c + C/7zDec.c + C/7zIn.c C/7zStream.c - C/Alloc.c - C/Bcj2.c - C/Bra86.c - C/LzFind.c - C/LzFindMt.c - C/LzmaDec.c - C/LzmaEnc.c - C/LzmaLib.c ) + C/Bcj2.c + C/Bra.c + C/Bra86.c + C/CpuArch.c + C/LzFind.c + C/Lzma2Dec.c + C/LzmaDec.c + C/LzmaEnc.c ) if( WIN32 ) - set( LZMA_FILES ${LZMA_FILES} C/Threads.c ) + set( LZMA_FILES ${LZMA_FILES} C/LzFindMt.c C/Threads.c ) +else( WIN32 ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_7ZIP_ST" ) endif( WIN32 ) add_library( lzma ${LZMA_FILES} ) diff --git a/lzma/history.txt b/lzma/history.txt old mode 100644 new mode 100755 index 9bed5ebbe..50ff40f02 --- a/lzma/history.txt +++ b/lzma/history.txt @@ -1,6 +1,41 @@ HISTORY of the LZMA SDK ----------------------- +9.18 beta 2010-11-02 +------------------------- +- New small SFX module for installers (SfxSetup). + + +9.12 beta 2010-03-24 +------------------------- +- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, + if more than 10 threads were used (or more than 20 threads in some modes). + + +9.11 beta 2010-03-15 +------------------------- +- PPMd compression method support + + +9.09 2009-12-12 +------------------------- +- The bug was fixed: + Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c + incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. +- Some bugs were fixed + + +9.06 2009-08-17 +------------------------- +- Some changes in ANSI-C 7z Decoder interfaces. + + +9.04 2009-05-30 +------------------------- +- LZMA2 compression method support +- xz format support + + 4.65 2009-02-03 ------------------------- - Some minor fixes diff --git a/lzma/lzma.txt b/lzma/lzma.txt old mode 100644 new mode 100755 index d4f4af929..579f2ccd8 --- a/lzma/lzma.txt +++ b/lzma/lzma.txt @@ -1,4 +1,4 @@ -LZMA SDK 4.65 +LZMA SDK 9.20 ------------- LZMA SDK provides the documentation, samples, header files, libraries, @@ -20,6 +20,10 @@ LICENSE LZMA SDK is written and placed in the public domain by Igor Pavlov. +Some code in LZMA SDK is based on public domain code from another developers: + 1) PPMd var.H (2001): Dmitry Shkarin + 2) SHA-256: Wei Dai (Crypto++ library) + LZMA SDK Contents ----------------- @@ -33,7 +37,7 @@ LZMA SDK includes: UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory -C++/7zip/Compress/LZMA_Alone +CPP/7zip/Bundles/LzmaCon and call make to recompile it: make -f makefile.gcc clean all @@ -49,6 +53,7 @@ lzma.txt - LZMA SDK description (this file) 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows +7zr.exe - 7-Zip with 7z/lzma/xz support. history.txt - history of the LZMA SDK @@ -66,7 +71,7 @@ C/ - C files LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files - Threads.* - The code for multithreading. + Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) @@ -86,12 +91,6 @@ CPP/ -- CPP files Compress - files related to compression/decompression - Copy - Copy coder - RangeCoder - Range Coder (special code of compression/decompression) - LZMA - LZMA compression/decompression on C++ - LZMA_Alone - file->file LZMA compression/decompression - Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - Archive - files related to archiving Common - common files for archive handling @@ -100,6 +99,7 @@ CPP/ -- CPP files Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. @@ -369,8 +369,8 @@ Interface: propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. @@ -431,7 +431,7 @@ Memory Requirements: { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } @@ -527,7 +527,8 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree }; LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); -If callback function return some error code, LzmaEnc_Encode also returns that code. +If callback function return some error code, LzmaEnc_Encode also returns that code +or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. Single-call RAM->RAM Compression @@ -549,8 +550,8 @@ Return code: -LZMA Defines ------------- +Defines +------- _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. @@ -562,6 +563,9 @@ _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. +_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder. + + C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, diff --git a/lzma/lzmalib.vcproj b/lzma/lzmalib.vcproj index 414e26f8d..3ad1ec149 100644 --- a/lzma/lzmalib.vcproj +++ b/lzma/lzmalib.vcproj @@ -294,16 +294,28 @@ RelativePath=".\C\7zCrc.c" > + + + + + + + + @@ -340,6 +356,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -352,10 +372,6 @@ RelativePath=".\C\7zVersion.h" > - - @@ -380,6 +396,10 @@ RelativePath=".\C\LzHash.h" > + + @@ -388,10 +408,6 @@ RelativePath=".\C\LzmaEnc.h" > - - @@ -401,50 +417,6 @@ > - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index a00626774..a7d173a4e 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -41,12 +41,8 @@ #include "i_system.h" #include "w_wad.h" -extern "C" { -#include "Archive/7z/7zHeader.h" -#include "Archive/7z/7zExtract.h" -#include "Archive/7z/7zIn.h" +#include "7z.h" #include "7zCrc.h" -} //----------------------------------------------------------------------- @@ -151,7 +147,7 @@ struct C7zArchive SRes Extract(UInt32 file_index, char *buffer) { size_t offset, out_size_processed; - SRes res = SzAr_Extract(&DB, &LookStream.s, file_index, + SRes res = SzArEx_Extract(&DB, &LookStream.s, file_index, &BlockIndex, &OutBuffer, &OutBufferSize, &offset, &out_size_processed, &g_Alloc, &g_Alloc); @@ -279,7 +275,27 @@ bool F7ZFile::Open(bool quiet) continue; } - FString name = file->Name; + const size_t nameLength = SzArEx_GetFileNameUtf16(&Archive->DB, i, NULL); + + if (0 == nameLength) + { + ++skipped; + continue; + } + + // Convert UTF-16 filename to plain ASCII + + UInt16* const nameUTF16 = static_cast(alloca(sizeof(UInt16) * nameLength)); + SzArEx_GetFileNameUtf16(&Archive->DB, i, nameUTF16); + + char* const nameASCII = static_cast(alloca(nameLength)); + + for (size_t c = 0; c < nameLength; ++c) + { + nameASCII[c] = static_cast(nameUTF16[c]); + } + + FString name = nameASCII; FixPathSeperator(name); name.ToLower(); From 94c4f38c584bc679f2c278843ae42f85f74a98c1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Apr 2014 01:26:30 +0200 Subject: [PATCH 187/247] - added constants for sound channels 5-7. --- wadsrc/static/actors/constants.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index dee498b6a..a264b4627 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -221,7 +221,10 @@ enum CHAN_VOICE = 2, CHAN_ITEM = 3, CHAN_BODY = 4, - + CHAN_5 = 5, + CHAN_6 = 6, + CHAN_7 = 7, + // modifier flags CHAN_LISTENERZ = 8, CHAN_MAYBE_LOCAL = 16, From 64d4ddf559e7d66b20e11c1b3aeaeed361886dd7 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 28 Apr 2014 11:34:37 +0300 Subject: [PATCH 188/247] Fixed file list in VS2005 project of LZMA library --- lzma/lzmalib.vcproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lzma/lzmalib.vcproj b/lzma/lzmalib.vcproj index 3ad1ec149..b37a52970 100644 --- a/lzma/lzmalib.vcproj +++ b/lzma/lzmalib.vcproj @@ -322,6 +322,10 @@ RelativePath=".\C\Bra86.c" > + + @@ -342,10 +346,6 @@ RelativePath=".\C\LzmaEnc.c" > - - From 76fdb4905f37735956c1a03d7ad9e7e9a86762d4 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 28 Apr 2014 13:06:05 +0300 Subject: [PATCH 189/247] Fixed compilation with updated LZMA library using Visual Studio --- lzma/C/CpuArch.c | 4 ++++ lzma/C/Threads.h | 7 +++++++ lzma/C/Types.h | 10 ---------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lzma/C/CpuArch.c b/lzma/C/CpuArch.c index 36e7680d9..4b319fa88 100644 --- a/lzma/C/CpuArch.c +++ b/lzma/C/CpuArch.c @@ -3,6 +3,10 @@ #include "CpuArch.h" +#ifdef _WIN32 +#include +#endif + #ifdef MY_CPU_X86_OR_AMD64 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) diff --git a/lzma/C/Threads.h b/lzma/C/Threads.h index 6a7afa829..b82214355 100644 --- a/lzma/C/Threads.h +++ b/lzma/C/Threads.h @@ -6,6 +6,13 @@ #include "Types.h" +#ifdef _WIN32 +#include +typedef DWORD WRes; +#else +typedef int WRes; +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/lzma/C/Types.h b/lzma/C/Types.h index 834709bb9..284991104 100644 --- a/lzma/C/Types.h +++ b/lzma/C/Types.h @@ -6,10 +6,6 @@ #include -#ifdef _WIN32 -#include -#endif - #ifndef EXTERN_C_BEGIN #ifdef __cplusplus #define EXTERN_C_BEGIN extern "C" { @@ -42,12 +38,6 @@ EXTERN_C_BEGIN typedef int SRes; -#ifdef _WIN32 -typedef DWORD WRes; -#else -typedef int WRes; -#endif - #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif From d6af8dc352f2f87bcbeda11f932a6fbc574fe883 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 3 May 2014 02:11:16 +1200 Subject: [PATCH 190/247] Added static RNGseed control --- src/d_main.cpp | 9 ++++++++- src/g_level.cpp | 6 +++++- src/m_random.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/m_random.h | 4 ++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 6c938ef53..f677f88b3 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1993,7 +1993,14 @@ static void D_DoomInit() SetLanguageIDs (); - rngseed = I_MakeRNGSeed(); + const char *v = Args->CheckValue("-rngseed"); + if (v) + { + rngseed = staticrngseed = atoi(v); + use_staticrng = true; + } + else + rngseed = I_MakeRNGSeed(); FRandom::StaticClearRandom (); Printf ("M_LoadDefaults: Load system defaults.\n"); diff --git a/src/g_level.cpp b/src/g_level.cpp index 65bde08d8..c721be4e1 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -408,7 +408,11 @@ void G_InitNew (const char *mapname, bool bTitleLevel) if (!savegamerestore) { - if (!netgame) + if (use_staticrng) + { + rngseed = staticrngseed; + } + else if (!netgame) { // [RH] Change the random seed for each new single player game rngseed = rngseed + 1; } diff --git a/src/m_random.cpp b/src/m_random.cpp index 763410111..f1e39faf9 100644 --- a/src/m_random.cpp +++ b/src/m_random.cpp @@ -96,6 +96,42 @@ FRandom M_Random; // Global seed. This is modified predictably to initialize every RNG. DWORD rngseed; +// Static RNG marker. This is only used when the RNG is set for each new game. +DWORD staticrngseed; +bool use_staticrng; + +// Allows checking or staticly setting the global seed. +CCMD(rngseed) +{ + if (argv.argc() == 1) + { + Printf("Usage: rngseed get|set|clear\n"); + return; + } + if (stricmp(argv[1], "get") == 0) + { + Printf("rngseed is %d\n", rngseed); + } + else if (stricmp(argv[1], "set") == 0) + { + if (argv.argc() == 2) + { + Printf("You need to specify a value to set\n"); + } + else + { + staticrngseed = atoi(argv[2]); + use_staticrng = true; + Printf("Static rngseed %d will be set for next game\n", staticrngseed); + } + } + else if (stricmp(argv[1], "clear") == 0) + { + use_staticrng = false; + Printf("Static rngseed cleared\n"); + } +} + // PRIVATE DATA DEFINITIONS ------------------------------------------------ FRandom *FRandom::RNGList; diff --git a/src/m_random.h b/src/m_random.h index 5b124c50e..b5e21c63c 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -215,6 +215,10 @@ private: extern DWORD rngseed; // The starting seed (not part of state) +extern DWORD staticrngseed; // Static rngseed that can be set by the user +extern bool use_staticrng; + + // M_Random can be used for numbers that do not affect gameplay extern FRandom M_Random; From 6183f8125fa4dc00db087b683bc08b8deb68e3d2 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 3 May 2014 02:48:52 +1200 Subject: [PATCH 191/247] Don't change RNG in demos incase they are static --- src/d_main.cpp | 1 + src/g_level.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index f677f88b3..5d36459db 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1998,6 +1998,7 @@ static void D_DoomInit() { rngseed = staticrngseed = atoi(v); use_staticrng = true; + Printf("D_DoomInit: Static RNGseed %d set.\n", rngseed); } else rngseed = I_MakeRNGSeed(); diff --git a/src/g_level.cpp b/src/g_level.cpp index c721be4e1..7b37ad471 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -408,13 +408,11 @@ void G_InitNew (const char *mapname, bool bTitleLevel) if (!savegamerestore) { - if (use_staticrng) + if (!netgame && !demorecording && !demoplayback) { - rngseed = staticrngseed; - } - else if (!netgame) - { // [RH] Change the random seed for each new single player game - rngseed = rngseed + 1; + // [RH] Change the random seed for each new single player game + // [ED850] The demo already sets the RNG. + rngseed = use_staticrng ? staticrngseed : (rngseed + 1); } FRandom::StaticClearRandom (); P_ClearACSVars(true); From 104a07d461bd8f75622a8674a7cb390174c41b9b Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 3 May 2014 03:24:51 +1200 Subject: [PATCH 192/247] Make sure use_staticrng is false if not needed --- src/d_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index 5d36459db..29049b10f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2001,7 +2001,11 @@ static void D_DoomInit() Printf("D_DoomInit: Static RNGseed %d set.\n", rngseed); } else + { rngseed = I_MakeRNGSeed(); + use_staticrng = false; + } + FRandom::StaticClearRandom (); Printf ("M_LoadDefaults: Load system defaults.\n"); From a9f1b54d2db91a3ff28f7198b4c8c5420dc73c42 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 3 May 2014 10:12:25 +0200 Subject: [PATCH 193/247] - fixed: since A_LightGoesOut alters a sector's floor plane it must also alter the TexZ for that sector's floor. --- src/g_strife/a_thingstoblowup.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp index 7d2c1ceee..d27260451 100644 --- a/src/g_strife/a_thingstoblowup.cpp +++ b/src/g_strife/a_thingstoblowup.cpp @@ -89,8 +89,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightGoesOut) sec->SetLightLevel(0); - newheight = sec->FindLowestFloorSurrounding (&spot); + fixed_t oldtheight = sec->floorplane.Zat0(); + newheight = sec->FindLowestFloorSurrounding(&spot); sec->floorplane.d = sec->floorplane.PointToDist (spot, newheight); + fixed_t newtheight = sec->floorplane.Zat0(); + sec->ChangePlaneTexZ(sector_t::floor, newtheight - oldtheight); for (int i = 0; i < 8; ++i) { From 93aa1ea2c4da75918f19b97d9dfead98952b1bd5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 5 May 2014 11:24:20 +0200 Subject: [PATCH 194/247] fixed some issues with reviving monsters - fixed: Thing_Raise didn't properly set the spawn health. - fixed: Thing_Raise did not the CanRaise state flag. - fixed: Reviving a monster must also reset the damage type. - fixed: Thing_Raise reset the actor after calling the raise state, but it should be before, just as the Archvile code is doing. - consolidated some common code of Thing_Raise and Archvile resurrection into AActor methods. --- src/actor.h | 2 + src/p_enemy.cpp | 222 +++++++++++++++++++++-------------------------- src/p_mobj.cpp | 43 +++++++++ src/p_things.cpp | 36 ++------ 4 files changed, 152 insertions(+), 151 deletions(-) diff --git a/src/actor.h b/src/actor.h index 21057d86c..4b7696752 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1011,6 +1011,8 @@ public: bool isSlow(); void SetIdle(); void ClearCounters(); + FState *GetRaiseState(); + void Revive(); FState *FindState (FName label) const { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 14c6b68aa..f84dd13aa 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2525,146 +2525,122 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT)); while ((corpsehit = it.Next())) { - if (!(corpsehit->flags & MF_CORPSE) ) - continue; // not a monster - - if (corpsehit->tics != -1 && // not lying still yet - !corpsehit->state->GetCanRaise()) // or not ready to be raised yet - continue; - - raisestate = corpsehit->FindState(NAME_Raise); - if (raisestate == NULL) - continue; // monster doesn't have a raise state - - if (corpsehit->IsKindOf(RUNTIME_CLASS(APlayerPawn))) - continue; // do not resurrect players - - // use the current actor's radius instead of the Arch Vile's default. - fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius; - - maxdist = corpsehit-> GetDefault()->radius + self->radius; - - if ( abs(corpsehit-> x - viletryx) > maxdist || - abs(corpsehit-> y - viletryy) > maxdist ) - continue; // not actually touching -#ifdef _3DFLOORS - // Let's check if there are floors in between the archvile and its target - sector_t *vilesec = self->Sector; - sector_t *corpsec = corpsehit->Sector; - // We only need to test if at least one of the sectors has a 3D floor. - sector_t *testsec = vilesec->e->XFloor.ffloors.Size() ? vilesec : - (vilesec != corpsec && corpsec->e->XFloor.ffloors.Size()) ? corpsec : NULL; - if (testsec) + FState *raisestate = corpsehit->GetRaiseState(); + if (raisestate != NULL) { - fixed_t zdist1, zdist2; - if (P_Find3DFloor(testsec, corpsehit->x, corpsehit->y, corpsehit->z, false, true, zdist1) - != P_Find3DFloor(testsec, self->x, self->y, self->z, false, true, zdist2)) + // use the current actor's radius instead of the Arch Vile's default. + fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius; + + maxdist = corpsehit->GetDefault()->radius + self->radius; + + if (abs(corpsehit->x - viletryx) > maxdist || + abs(corpsehit->y - viletryy) > maxdist) + continue; // not actually touching +#ifdef _3DFLOORS + // Let's check if there are floors in between the archvile and its target + sector_t *vilesec = self->Sector; + sector_t *corpsec = corpsehit->Sector; + // We only need to test if at least one of the sectors has a 3D floor. + sector_t *testsec = vilesec->e->XFloor.ffloors.Size() ? vilesec : + (vilesec != corpsec && corpsec->e->XFloor.ffloors.Size()) ? corpsec : NULL; + if (testsec) { - // Not on same floor - if (vilesec == corpsec || abs(zdist1 - self->z) > self->height) + fixed_t zdist1, zdist2; + if (P_Find3DFloor(testsec, corpsehit->x, corpsehit->y, corpsehit->z, false, true, zdist1) + != P_Find3DFloor(testsec, self->x, self->y, self->z, false, true, zdist2)) + { + // Not on same floor + if (vilesec == corpsec || abs(zdist1 - self->z) > self->height) continue; + } } - } #endif - corpsehit->velx = corpsehit->vely = 0; - // [RH] Check against real height and radius + corpsehit->velx = corpsehit->vely = 0; + // [RH] Check against real height and radius - fixed_t oldheight = corpsehit->height; - fixed_t oldradius = corpsehit->radius; - int oldflags = corpsehit->flags; + fixed_t oldheight = corpsehit->height; + fixed_t oldradius = corpsehit->radius; + int oldflags = corpsehit->flags; - corpsehit->flags |= MF_SOLID; - corpsehit->height = corpsehit->GetDefault()->height; - bool check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y); - corpsehit->flags = oldflags; - corpsehit->radius = oldradius; - corpsehit->height = oldheight; - if (!check) continue; + corpsehit->flags |= MF_SOLID; + corpsehit->height = corpsehit->GetDefault()->height; + bool check = P_CheckPosition(corpsehit, corpsehit->x, corpsehit->y); + corpsehit->flags = oldflags; + corpsehit->radius = oldradius; + corpsehit->height = oldheight; + if (!check) continue; - // got one! - temp = self->target; - self->target = corpsehit; - A_FaceTarget (self); - if (self->flags & MF_FRIENDLY) - { - // If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend) - // and the Arch-Vile is currently targetting the resurrected monster the target must be cleared. - if (self->lastenemy == temp) self->lastenemy = NULL; - if (self->lastenemy == corpsehit) self->lastenemy = NULL; - if (temp == self->target) temp = NULL; - } - self->target = temp; - - // Make the state the monster enters customizable. - FState * state = self->FindState(NAME_Heal); - if (state != NULL) - { - self->SetState (state); - } - else if (usevilestates) - { - // For Dehacked compatibility this has to use the Arch Vile's - // heal state as a default if the actor doesn't define one itself. - const PClass *archvile = PClass::FindClass("Archvile"); - if (archvile != NULL) + // got one! + temp = self->target; + self->target = corpsehit; + A_FaceTarget(self); + if (self->flags & MF_FRIENDLY) { - self->SetState (archvile->ActorInfo->FindState(NAME_Heal)); + // If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend) + // and the Arch-Vile is currently targetting the resurrected monster the target must be cleared. + if (self->lastenemy == temp) self->lastenemy = NULL; + if (self->lastenemy == corpsehit) self->lastenemy = NULL; + if (temp == self->target) temp = NULL; } - } - S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); - info = corpsehit->GetDefault (); - - if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) - { - corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses - } - if (ib_compatflags & BCOMPATF_VILEGHOSTS) - { - corpsehit->height <<= 2; - // [GZ] This was a commented-out feature, so let's make use of it, - // but only for ghost monsters so that they are visibly different. - if (corpsehit->height == 0) + self->target = temp; + + // Make the state the monster enters customizable. + FState * state = self->FindState(NAME_Heal); + if (state != NULL) { - // Make raised corpses look ghostly - if (corpsehit->alpha > TRANSLUC50) + self->SetState(state); + } + else if (usevilestates) + { + // For Dehacked compatibility this has to use the Arch Vile's + // heal state as a default if the actor doesn't define one itself. + const PClass *archvile = PClass::FindClass("Archvile"); + if (archvile != NULL) { - corpsehit->alpha /= 2; - } - // This will only work if the render style is changed as well. - if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal]) - { - corpsehit->RenderStyle = STYLE_Translucent; + self->SetState(archvile->ActorInfo->FindState(NAME_Heal)); } } - } - else - { - corpsehit->height = info->height; // [RH] Use real mobj height - corpsehit->radius = info->radius; // [RH] Use real radius - } - corpsehit->flags = info->flags; - corpsehit->flags2 = info->flags2; - corpsehit->flags3 = info->flags3; - corpsehit->flags4 = info->flags4; - corpsehit->flags5 = info->flags5; - corpsehit->flags6 = info->flags6; - corpsehit->flags7 = info->flags7; - corpsehit->health = corpsehit->SpawnHealth(); - corpsehit->target = NULL; - corpsehit->lastenemy = NULL; + S_Sound(corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); + info = corpsehit->GetDefault(); - // [RH] If it's a monster, it gets to count as another kill - if (corpsehit->CountsAsKill()) - { - level.total_monsters++; + if (corpsehit->state == corpsehit->FindState(NAME_GenericCrush)) + { + corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses + } + if (ib_compatflags & BCOMPATF_VILEGHOSTS) + { + corpsehit->height <<= 2; + // [GZ] This was a commented-out feature, so let's make use of it, + // but only for ghost monsters so that they are visibly different. + if (corpsehit->height == 0) + { + // Make raised corpses look ghostly + if (corpsehit->alpha > TRANSLUC50) + { + corpsehit->alpha /= 2; + } + // This will only work if the render style is changed as well. + if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal]) + { + corpsehit->RenderStyle = STYLE_Translucent; + } + } + } + else + { + corpsehit->height = info->height; // [RH] Use real mobj height + corpsehit->radius = info->radius; // [RH] Use real radius + } + + corpsehit->Revive(); + + // You are the Archvile's minion now, so hate what it hates + corpsehit->CopyFriendliness(self, false); + corpsehit->SetState(raisestate); + + return true; } - - // You are the Archvile's minion now, so hate what it hates - corpsehit->CopyFriendliness (self, false); - corpsehit->SetState (raisestate); - - return true; } } return false; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f519ba763..05eddf3ab 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6074,6 +6074,49 @@ int AActor::SpawnHealth() } } +FState *AActor::GetRaiseState() +{ + if (!(flags & MF_CORPSE)) + { + return NULL; // not a monster + } + + if (tics != -1 && // not lying still yet + state->GetCanRaise()) // or not ready to be raised yet + { + return NULL; + } + + if (IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + return NULL; // do not resurrect players + } + + return FindState(NAME_Raise); +} + +void AActor::Revive() +{ + AActor *info = GetDefault(); + flags = info->flags; + flags2 = info->flags2; + flags3 = info->flags3; + flags4 = info->flags4; + flags5 = info->flags5; + flags6 = info->flags6; + flags7 = info->flags7; + DamageType = info->DamageType; + health = SpawnHealth(); + target = NULL; + lastenemy = NULL; + + // [RH] If it's a monster, it gets to count as another kill + if (CountsAsKill()) + { + level.total_monsters++; + } +} + FDropItem *AActor::GetDropItems() { unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1; diff --git a/src/p_things.cpp b/src/p_things.cpp index 4828e8cbc..e62c65ae7 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -410,18 +410,11 @@ void P_RemoveThing(AActor * actor) bool P_Thing_Raise(AActor *thing) { - if (thing == NULL) - return false; // not valid - - if (!(thing->flags & MF_CORPSE) ) - return true; // not a corpse - - if (thing->tics != -1) - return true; // not lying still yet - - FState * RaiseState = thing->FindState(NAME_Raise); + FState * RaiseState = thing->GetRaiseState(); if (RaiseState == NULL) + { return true; // monster doesn't have a raise state + } AActor *info = thing->GetDefault (); @@ -443,25 +436,12 @@ bool P_Thing_Raise(AActor *thing) return false; } - S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); - - thing->SetState (RaiseState); - thing->flags = info->flags; - thing->flags2 = info->flags2; - thing->flags3 = info->flags3; - thing->flags4 = info->flags4; - thing->flags5 = info->flags5; - thing->flags6 = info->flags6; - thing->flags7 = info->flags7; - thing->health = info->health; - thing->target = NULL; - thing->lastenemy = NULL; - // [RH] If it's a monster, it gets to count as another kill - if (thing->CountsAsKill()) - { - level.total_monsters++; - } + S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); + + thing->Revive(); + + thing->SetState (RaiseState); return true; } From 90e9937b71b6d846edbd7ae245189e9aa3353039 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 5 May 2014 22:47:48 +1200 Subject: [PATCH 195/247] Stop NetUpdate from corrupting demo playback --- src/d_net.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/d_net.cpp b/src/d_net.cpp index c912d29a2..170e9ed12 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1052,6 +1052,12 @@ void NetUpdate (void) if (singletics) return; // singletic update is synchronous + if (demoplayback) + { + nettics[0] = (maketic / ticdup); + return; // Don't touch netcmd data while playing a demo, as it'll already exist. + } + // If maketic didn't cross a ticdup boundary, only send packets // to players waiting for resends. resendOnly = (maketic / ticdup) == (maketic - i) / ticdup; From fcbb72a4d45760c3f4512cea6d535b7ef12ecb15 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 May 2014 09:59:56 +0200 Subject: [PATCH 196/247] - removed redundant variable. --- src/p_enemy.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index f84dd13aa..bdc72b0c8 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2520,7 +2520,6 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) fixed_t viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]); fixed_t viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]); AActor *corpsehit; - FState *raisestate; FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT)); while ((corpsehit = it.Next())) From 890e9ecdddd36e1075098a3dcbaf0a93f73ddb51 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 7 May 2014 17:18:44 +0200 Subject: [PATCH 197/247] - typo in resurrection code. --- src/p_mobj.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 05eddf3ab..78b1124d4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1,4 +1,5 @@ // Emacs style mode select -*- C++ -*- +// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ @@ -6082,7 +6083,7 @@ FState *AActor::GetRaiseState() } if (tics != -1 && // not lying still yet - state->GetCanRaise()) // or not ready to be raised yet + !state->GetCanRaise()) // or not ready to be raised yet { return NULL; } From 67ebbe3ed4bb2028c8850157d9e551569cc0aaba Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 May 2014 09:15:56 +0200 Subject: [PATCH 198/247] made some changes to turn the CF_INTERPVIEW flag when changing angles into an op-in feature instead of making it automatic. --- src/p_acs.cpp | 8 ++++---- src/p_mobj.cpp | 8 ++++---- src/thingdef/thingdef_codeptr.cpp | 18 ++++++++++-------- wadsrc/static/actors/actor.txt | 2 +- wadsrc/static/actors/constants.txt | 3 ++- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d70cc2c0b..8326d7b82 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -8251,7 +8251,7 @@ scriptwait: { if (activator != NULL) { - activator->SetAngle(STACK(1) << 16); + activator->SetAngle(STACK(1) << 16, false); } } else @@ -8261,7 +8261,7 @@ scriptwait: while ( (actor = iterator.Next ()) ) { - actor->SetAngle(STACK(1) << 16); + actor->SetAngle(STACK(1) << 16, false); } } sp -= 2; @@ -8272,7 +8272,7 @@ scriptwait: { if (activator != NULL) { - activator->SetPitch(STACK(1) << 16); + activator->SetPitch(STACK(1) << 16, false); } } else @@ -8282,7 +8282,7 @@ scriptwait: while ( (actor = iterator.Next ()) ) { - actor->SetPitch(STACK(1) << 16); + actor->SetPitch(STACK(1) << 16, false); } } sp -= 2; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 69d4203fe..2bcae99b0 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2962,24 +2962,24 @@ void AActor::SetShade (int r, int g, int b) fillcolor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b); } -void AActor::SetPitch(int p) +void AActor::SetPitch(int p, bool interpolate) { if (p != pitch) { pitch = p; - if (player != NULL) + if (player != NULL && interpolate) { player->cheats |= CF_INTERPVIEW; } } } -void AActor::SetAngle(angle_t ang) +void AActor::SetAngle(angle_t ang, bool interpolate) { if (ang != angle) { angle = ang; - if (player != NULL) + if (player != NULL && interpolate) { player->cheats |= CF_INTERPVIEW; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d48b18a2a..251a5de91 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3930,12 +3930,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MonsterRefire) // Set actor's angle (in degrees). // //=========================================================================== +enum +{ + SPF_FORCECLAMP = 1, // players always clamp + SPF_INTERPOLATE = 2, +}; + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) { - ACTION_PARAM_START(1); + ACTION_PARAM_START(2); ACTION_PARAM_ANGLE(angle, 0); - self->SetAngle(angle); + ACTION_PARAM_INT(flags, 1) + self->SetAngle(angle, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== @@ -3946,11 +3953,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetAngle) // //=========================================================================== -enum -{ - SPF_FORCECLAMP = 1, // players always clamp -}; - DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) { ACTION_PARAM_START(2); @@ -3973,7 +3975,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) } pitch = clamp(pitch, min, max); } - self->SetPitch(pitch); + self->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); } //=========================================================================== diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 73119c941..1eb00440c 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -289,7 +289,7 @@ ACTOR Actor native //: Thinker action native A_DropWeaponPieces(class p1, class p2, class p3); action native A_PigPain (); action native A_MonsterRefire(int chance, state label); - action native A_SetAngle(float angle = 0); + action native A_SetAngle(float angle = 0, int flags = 0); action native A_SetPitch(float pitch, int flags = 0); action native A_ScaleVelocity(float scale); action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index dee498b6a..b252e3194 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -304,8 +304,9 @@ Const Int WARPF_STOP = 0x80; Const Int WARPF_TOFLOOR = 0x100; Const Int WARPF_TESTONLY = 0x200; -// flags for A_SetPitch +// flags for A_SetPitch/SetAngle const int SPF_FORCECLAMP = 1; +const int SPF_INTERPOLATE = 2; // flags for A_CheckLOF From 2223c12938ab24995a798443bee841b1fa249563 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 May 2014 09:43:58 +0200 Subject: [PATCH 199/247] - added new ChangeActorAngle/ChangeActorPitch ACS functions because the new required 'interpolate' parameter cannot be added to the existing SetActorAngle/SetActorPitch functions without breaking old scripts. --- src/actor.h | 4 +- src/p_acs.cpp | 106 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 36 deletions(-) diff --git a/src/actor.h b/src/actor.h index 4b7696752..0dd20c14f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -765,8 +765,8 @@ public: } // These also set CF_INTERPVIEW for players. - void SetPitch(int p); - void SetAngle(angle_t ang); + void SetPitch(int p, bool interpolate); + void SetAngle(angle_t ang, bool interpolate); const PClass *GetBloodType(int type = 0) const { diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 198ba0cd0..50dd2733b 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4263,6 +4263,18 @@ enum EACSFunctions ACSF_SetLineActivation, ACSF_GetLineActivation, ACSF_GetActorPowerupTics, + ACSF_ChangeActorAngle, + ACSF_ChangeActorPitch, // 80 + + /* Zandronum's - these must be skipped when we reach 99! + -100:ResetMap(0), + -101 : PlayerIsSpectator(1), + -102 : ConsolePlayerNumber(0), + -103 : GetTeamProperty(2), + -104 : GetPlayerLivesLeft(1), + -105 : SetPlayerLivesLeft(2), + -106 : KickFromGame(2), + */ // ZDaemon ACSF_GetTeamScore = 19620, // (int team) @@ -4522,6 +4534,50 @@ static bool DoSpawnDecal(AActor *actor, const FDecalTemplate *tpl, int flags, an angle, distance, !!(flags & SDF_PERMANENT)); } +static void SetActorAngle(AActor *activator, int tid, int angle, bool interpolate) +{ + if (tid == 0) + { + if (activator != NULL) + { + activator->SetAngle(angle << 16, interpolate); + } + } + else + { + FActorIterator iterator(tid); + AActor *actor; + + while ((actor = iterator.Next())) + { + actor->SetAngle(angle << 16, interpolate); + } + } +} + +static void SetActorPitch(AActor *activator, int tid, int angle, bool interpolate) +{ + if (tid == 0) + { + if (activator != NULL) + { + activator->SetPitch(angle << 16, interpolate); + } + } + else + { + FActorIterator iterator(tid); + AActor *actor; + + while ((actor = iterator.Next())) + { + actor->SetPitch(angle << 16, interpolate); + } + } +} + + + int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const SDWORD *stack, int stackdepth) { AActor *actor; @@ -5349,6 +5405,20 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) } break; + case ACSF_ChangeActorAngle: + if (argCount >= 2) + { + SetActorAngle(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); + } + break; + + case ACSF_ChangeActorPitch: + if (argCount >= 2) + { + SetActorPitch(activator, args[0], args[1], argCount > 2 ? !!args[2] : false); + } + break; + default: break; } @@ -8323,44 +8393,12 @@ scriptwait: break; case PCD_SETACTORANGLE: // [GRB] - if (STACK(2) == 0) - { - if (activator != NULL) - { - activator->SetAngle(STACK(1) << 16, false); - } - } - else - { - FActorIterator iterator (STACK(2)); - AActor *actor; - - while ( (actor = iterator.Next ()) ) - { - actor->SetAngle(STACK(1) << 16, false); - } - } + SetActorAngle(activator, STACK(2), STACK(1), false); sp -= 2; break; case PCD_SETACTORPITCH: - if (STACK(2) == 0) - { - if (activator != NULL) - { - activator->SetPitch(STACK(1) << 16, false); - } - } - else - { - FActorIterator iterator (STACK(2)); - AActor *actor; - - while ( (actor = iterator.Next ()) ) - { - actor->SetPitch(STACK(1) << 16, false); - } - } + SetActorPitch(activator, STACK(2), STACK(1), false); sp -= 2; break; From ea7fb936a83d66d520ac45b110b0d74f9f29b136 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 May 2014 10:33:32 +0200 Subject: [PATCH 200/247] - fixed: memory allocation for file names in 7z archives was broken. Changing it to use TArray instead of alloca makes it work. --- src/resourcefiles/file_7z.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index a7d173a4e..53653bb59 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -264,6 +264,8 @@ bool F7ZFile::Open(bool quiet) Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; + TArray nameUTF16; + TArray nameASCII; for (DWORD i = 0; i < NumLumps; ++i) { CSzFileItem *file = &Archive->DB.db.Files[i]; @@ -283,20 +285,16 @@ bool F7ZFile::Open(bool quiet) continue; } - // Convert UTF-16 filename to plain ASCII - - UInt16* const nameUTF16 = static_cast(alloca(sizeof(UInt16) * nameLength)); - SzArEx_GetFileNameUtf16(&Archive->DB, i, nameUTF16); - - char* const nameASCII = static_cast(alloca(nameLength)); - + nameUTF16.Resize(nameLength); + nameASCII.Resize(nameLength); + SzArEx_GetFileNameUtf16(&Archive->DB, i, &nameUTF16[0]); for (size_t c = 0; c < nameLength; ++c) { nameASCII[c] = static_cast(nameUTF16[c]); } + FixPathSeperator(&nameASCII[0]); - FString name = nameASCII; - FixPathSeperator(name); + FString name = &nameASCII[0]; name.ToLower(); lump_p->LumpNameSetup(name); From 458e1b1be2a7e76045849050f32c76b2e5c28d44 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 8 May 2014 11:29:45 +0200 Subject: [PATCH 201/247] - changed sound lookup for ZSDF dialogues so that it first checks the svox/ namespace before using the global one. --- src/p_usdf.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 6ea32b308..2ab52e380 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -310,12 +310,16 @@ class USDFParser : public UDMFParserBase case NAME_Voice: { - FString soundname = (namespace_bits == St? "svox/" : ""); const char * name = CheckString(key); if (name[0] != 0) { + FString soundname = "svox/"; soundname += name; node->SpeakerVoice = FSoundID(S_FindSound(soundname)); + if (node->SpeakerVoice == 0 && namespace_bits == Zd) + { + node->SpeakerVoice = FSoundID(S_FindSound(name)); + } } } break; From 65e8563cf44235725ef0f198f48956eca9f467cf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 11:33:59 +0200 Subject: [PATCH 202/247] replaced all character arrays for lump/texture names in the level_info_t and FLevelLocals structures with FStrings as first preparation for allowing long texture names. --- src/am_map.cpp | 10 ++++++++-- src/c_cmds.cpp | 11 +++++++++-- src/fragglescript/t_load.cpp | 5 +---- src/g_level.cpp | 32 ++++++++++++++------------------ src/g_level.h | 17 +++++++++-------- src/g_mapinfo.cpp | 32 +++++++++++++++----------------- src/menu/readthis.cpp | 6 +++--- src/p_acs.cpp | 6 ++---- src/textures/texturemanager.cpp | 2 +- src/v_draw.cpp | 4 ++-- src/version.h | 2 +- 11 files changed, 65 insertions(+), 62 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index e52d39211..904593dfb 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1316,8 +1316,14 @@ bool AM_clearMarks () void AM_LevelInit () { - const char *autopage = level.info->mapbg[0] == 0? "AUTOPAGE" : (const char*)&level.info->mapbg[0]; - mapback = TexMan.CheckForTexture(autopage, FTexture::TEX_MiscPatch); + if (level.info->MapBackground.Len() == 0) + { + mapback = TexMan.CheckForTexture("AUTOPAGE", FTexture::TEX_MiscPatch); + } + else + { + mapback = TexMan.CheckForTexture(level.info->MapBackground, FTexture::TEX_MiscPatch); + } AM_clearMarks(); diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 0e7adb8ef..7b6f1d195 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -946,8 +946,15 @@ CCMD(changesky) sky1name = argv[1]; if (sky1name[0] != 0) { - strncpy (level.skypic1, sky1name, 8); - sky1texture = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable); + FTextureID newsky = TexMan.GetTexture(sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + if (newsky.Exists()) + { + sky1texture = level.skytexture1 = newsky; + } + else + { + Printf("changesky: Texture '%s' not found\n", sky1name); + } } R_InitSkyMap (); } diff --git a/src/fragglescript/t_load.cpp b/src/fragglescript/t_load.cpp index d9b4f2d04..49458c4be 100644 --- a/src/fragglescript/t_load.cpp +++ b/src/fragglescript/t_load.cpp @@ -183,10 +183,7 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc) sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.skypic1, sc.String, 8); - strncpy(level.skypic2, sc.String, 8); - level.skypic1[8]=level.skypic2[8]=0; - sky2texture = sky1texture = TexMan.GetTexture (sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable); + sky2texture = sky1texture = level.skytexture1 = level.skytexture2 = TexMan.GetTexture (sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); R_InitSkyMap (); } else if (sc.Compare("interpic")) diff --git a/src/g_level.cpp b/src/g_level.cpp index 7b37ad471..814bafcfb 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -870,8 +870,8 @@ void G_DoLoadLevel (int position, bool autosave) // DOOM determines the sky texture to be used // depending on the current episode and the game version. // [RH] Fetch sky parameters from FLevelLocals. - sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky1texture = level.skytexture1; + sky2texture = level.skytexture2; // [RH] Set up details about sky rendering R_InitSkyMap (); @@ -1222,15 +1222,16 @@ void G_InitLevelLocals () level.info = info; level.skyspeed1 = info->skyspeed1; level.skyspeed2 = info->skyspeed2; - strncpy (level.skypic2, info->skypic2, 8); + level.skytexture1 = TexMan.GetTexture(info->SkyPic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + level.skytexture2 = TexMan.GetTexture(info->SkyPic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); level.fadeto = info->fadeto; level.cdtrack = info->cdtrack; level.cdid = info->cdid; level.FromSnapshot = false; if (level.fadeto == 0) { - R_SetDefaultColormap (info->fadetable); - if (strnicmp (info->fadetable, "COLORMAP", 8) != 0) + R_SetDefaultColormap (info->FadeTable); + if (strnicmp (info->FadeTable, "COLORMAP", 8) != 0) { level.flags |= LEVEL_HASFADETABLE; } @@ -1277,11 +1278,6 @@ void G_InitLevelLocals () level.nextmap[10] = 0; strncpy (level.secretmap, info->secretmap, 10); level.secretmap[10] = 0; - strncpy (level.skypic1, info->skypic1, 8); - level.skypic1[8] = 0; - if (!level.skypic2[0]) - strncpy (level.skypic2, level.skypic1, 8); - level.skypic2[8] = 0; compatflags.Callback(); compatflags2.Callback(); @@ -1406,18 +1402,18 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) if (!hubLoad) level.totaltime = i; - if (arc.IsStoring ()) + if (SaveVersion >= 4507) { - arc.WriteName (level.skypic1); - arc.WriteName (level.skypic2); + arc << level.skytexture1 << level.skytexture2; } else { - strncpy (level.skypic1, arc.ReadName(), 8); - strncpy (level.skypic2, arc.ReadName(), 8); - sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - R_InitSkyMap (); + sky1texture = TexMan.GetTexture (arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky2texture = TexMan.GetTexture (arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + } + if (arc.IsLoading()) + { + R_InitSkyMap(); } G_AirControlChanged (); diff --git a/src/g_level.h b/src/g_level.h index 4a84e6871..43644a279 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -38,6 +38,7 @@ #include "doomdef.h" #include "sc_man.h" #include "s_sound.h" +#include "textures/textures.h" struct level_info_t; struct cluster_info_t; @@ -272,12 +273,12 @@ struct level_info_t char pname[9]; char nextmap[11]; char secretmap[11]; - char skypic1[9]; - char skypic2[9]; - char fadetable[9]; - char f1[9]; - char bordertexture[9]; - char mapbg[9]; + FString SkyPic1; + FString SkyPic2; + FString FadeTable; + FString F1Pic; + FString BorderTexture; + FString MapBackground; int cluster; int partime; @@ -406,8 +407,8 @@ struct FLevelLocals int cdtrack; unsigned int cdid; int nextmusic; // For MUSINFO purposes - char skypic1[9]; - char skypic2[9]; + FTextureID skytexture1; + FTextureID skytexture2; float skyspeed1; // Scrolling speed of sky textures, in pixels per ms float skyspeed2; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 04617a068..d8e12e9e4 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -94,8 +94,7 @@ level_info_t *FindLevelInfo (const char *mapname, bool allowdefault) { if (TheDefaultLevelInfo.LevelName.IsEmpty()) { - uppercopy(TheDefaultLevelInfo.skypic1, "SKY1"); - uppercopy(TheDefaultLevelInfo.skypic2, "SKY1"); + TheDefaultLevelInfo.SkyPic2 = TheDefaultLevelInfo.SkyPic1 = "SKY1"; TheDefaultLevelInfo.LevelName = "Unnamed"; } return &TheDefaultLevelInfo; @@ -226,13 +225,12 @@ void P_RemoveDefereds (void) void level_info_t::Reset() { mapname[0] = 0; - mapbg[0] = 0; + MapBackground = ""; levelnum = 0; pname[0] = 0; nextmap[0] = 0; secretmap[0] = 0; - strcpy (skypic1, "-NOFLAT-"); - strcpy (skypic2, "-NOFLAT-"); + SkyPic1 = SkyPic2 = "-NOFLAT-"; cluster = 0; partime = 0; sucktime = 0; @@ -243,10 +241,10 @@ void level_info_t::Reset() flags2 = LEVEL2_LAXMONSTERACTIVATION; Music = ""; LevelName = ""; - strcpy (fadetable, "COLORMAP"); + FadeTable = "COLORMAP"; WallHorizLight = -8; WallVertLight = +8; - f1[0] = 0; + F1Pic = ""; musicorder = 0; snapshot = NULL; snapshotVer = 0; @@ -271,7 +269,7 @@ void level_info_t::Reset() intermusicorder = 0; SoundInfo = ""; SndSeq = ""; - bordertexture[0] = 0; + BorderTexture = ""; teamdamage = 0.f; specialactions.Clear(); DefaultEnvironment = 0; @@ -850,7 +848,7 @@ DEFINE_MAP_OPTION(cluster, true) DEFINE_MAP_OPTION(sky1, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic1); + parse.ParseLumpOrTextureName(info->SkyPic1); if (parse.CheckFloat()) { if (parse.HexenHack) @@ -864,7 +862,7 @@ DEFINE_MAP_OPTION(sky1, true) DEFINE_MAP_OPTION(sky2, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic2); + parse.ParseLumpOrTextureName(info->SkyPic2); if (parse.CheckFloat()) { if (parse.HexenHack) @@ -879,7 +877,7 @@ DEFINE_MAP_OPTION(sky2, true) DEFINE_MAP_OPTION(skybox, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->skypic1); + parse.ParseLumpOrTextureName(info->SkyPic1); info->skyspeed1 = 0; } @@ -939,7 +937,7 @@ DEFINE_MAP_OPTION(intermusic, true) DEFINE_MAP_OPTION(fadetable, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->fadetable); + parse.ParseLumpOrTextureName(info->FadeTable); } DEFINE_MAP_OPTION(evenlighting, true) @@ -1122,13 +1120,13 @@ DEFINE_MAP_OPTION(slideshow, false) DEFINE_MAP_OPTION(bordertexture, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->bordertexture); + parse.ParseLumpOrTextureName(info->BorderTexture); } DEFINE_MAP_OPTION(f1, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->f1); + parse.ParseLumpOrTextureName(info->F1Pic); } DEFINE_MAP_OPTION(teamdamage, true) @@ -1141,7 +1139,7 @@ DEFINE_MAP_OPTION(teamdamage, true) DEFINE_MAP_OPTION(mapbackground, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->mapbg); + parse.ParseLumpOrTextureName(info->MapBackground); } DEFINE_MAP_OPTION(defaultenvironment, false) @@ -1789,9 +1787,9 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i ParseMapDefinition(*levelinfo); // When the second sky is -NOFLAT-, make it a copy of the first sky - if (strcmp (levelinfo->skypic2, "-NOFLAT-") == 0) + if (!levelinfo->SkyPic2.CompareNoCase("-NOFLAT-")) { - strcpy (levelinfo->skypic2, levelinfo->skypic1); + levelinfo->SkyPic2 = levelinfo->SkyPic1; } SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps. } diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index 197981ad3..a00843440 100644 --- a/src/menu/readthis.cpp +++ b/src/menu/readthis.cpp @@ -82,9 +82,9 @@ void DReadThisMenu::Drawer() fixed_t alpha; // Did the mapper choose a custom help page via MAPINFO? - if ((level.info != NULL) && level.info->f1[0] != 0) + if ((level.info != NULL) && level.info->F1Pic.Len() != 0) { - tex = TexMan.FindTexture(level.info->f1); + tex = TexMan.FindTexture(level.info->F1Pic); mScreen = 1; } @@ -122,7 +122,7 @@ bool DReadThisMenu::MenuEvent(int mkey, bool fromcontroller) S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE); mScreen++; mInfoTic = gametic; - if ((level.info != NULL && level.info->f1[0] != 0) || mScreen > int(gameinfo.infoPages.Size())) + if ((level.info != NULL && level.info->F1Pic.Len() != 0) || mScreen > int(gameinfo.infoPages.Size())) { Close(); } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 50dd2733b..04aecaed1 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -8348,13 +8348,11 @@ scriptwait: sky2name = FBehavior::StaticLookupString (STACK(1)); if (sky1name[0] != 0) { - strncpy (level.skypic1, sky1name, 8); - sky1texture = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky1texture = level.skytexture1 = TexMan.GetTexture (sky1name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); } if (sky2name[0] != 0) { - strncpy (level.skypic2, sky2name, 8); - sky2texture = TexMan.GetTexture (sky2name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + sky2texture = level.skytexture2 = TexMan.GetTexture (sky2name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); } R_InitSkyMap (); sp -= 2; diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 48f3ff9e0..cdacb95bd 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1004,7 +1004,7 @@ void FTextureManager::Init() { if (wadlevelinfos[i].flags & LEVEL_DOUBLESKY) { - FTextureID picnum = CheckForTexture (wadlevelinfos[i].skypic1, FTexture::TEX_Wall, false); + FTextureID picnum = CheckForTexture (wadlevelinfos[i].SkyPic1, FTexture::TEX_Wall, false); if (picnum.isValid()) { Textures[picnum.GetIndex()].Texture->SetFrontSkyLayer (); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index cd07b44a1..8472637a2 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1444,9 +1444,9 @@ void V_DrawBorder (int x1, int y1, int x2, int y2) { FTextureID picnum; - if (level.info != NULL && level.info->bordertexture[0] != 0) + if (level.info != NULL && level.info->BorderTexture.Len() != 0) { - picnum = TexMan.CheckForTexture (level.info->bordertexture, FTexture::TEX_Flat); + picnum = TexMan.CheckForTexture (level.info->BorderTexture, FTexture::TEX_Flat); } else { diff --git a/src/version.h b/src/version.h index 27bfe1021..1b4457655 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4506 +#define SAVEVER 4507 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) From fedf9c6a5ba40e4166b9da6874a7454a174d38fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 11:39:25 +0200 Subject: [PATCH 203/247] fixed: if we allow long names for the fade table we must also check for them when the colormap gets loaded. --- src/r_data/colormaps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index c3004a4da..b7e1b904b 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -396,7 +396,7 @@ void R_SetDefaultColormap (const char *name) BYTE unremap[256]; BYTE remap[256]; - lump = Wads.CheckNumForName (name, ns_colormaps); + lump = Wads.CheckNumForFullName (name, true, ns_colormaps); if (lump == -1) lump = Wads.CheckNumForName (name, ns_global); From e718a72b4d3891f1207ab66fe081eb8c733af23b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 11:53:08 +0200 Subject: [PATCH 204/247] fixed: skies should be loaded into the FLevelLocals struct not into the global variables of the renderer. --- src/g_level.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 814bafcfb..47ad66998 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1408,8 +1408,8 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) } else { - sky1texture = TexMan.GetTexture (arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); - sky2texture = TexMan.GetTexture (arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_ReturnFirst); + level.skytexture1 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); + level.skytexture2 = TexMan.GetTexture(arc.ReadName(), FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_ReturnFirst); } if (arc.IsLoading()) { From a05e62f3f7b4d690ebe5398a5c76c7c796bfad36 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 12:44:17 +0200 Subject: [PATCH 205/247] - changed storage of lump and texture names in gameinfo to allow long names (with the exception of view border elements.) --- src/c_console.cpp | 2 +- src/d_main.cpp | 4 ++-- src/g_shared/a_armor.cpp | 4 ++-- src/gi.cpp | 20 +++++++++----------- src/gi.h | 18 +++++++++--------- src/intermission/intermission.cpp | 2 +- src/v_draw.cpp | 2 +- src/wi_stuff.cpp | 4 ++-- src/win32/st_start.cpp | 4 ++-- 9 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/c_console.cpp b/src/c_console.cpp index b21c8c3a6..396b2dfce 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -303,7 +303,7 @@ void C_InitConback() if (!conback.isValid()) { - conback = TexMan.GetTexture (gameinfo.titlePage, FTexture::TEX_MiscPatch); + conback = TexMan.GetTexture (gameinfo.TitlePage, FTexture::TEX_MiscPatch); conshade = MAKEARGB(175,0,0,0); conline = true; } diff --git a/src/d_main.cpp b/src/d_main.cpp index 9f332c68d..93e6368c1 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1234,7 +1234,7 @@ void D_DoAdvanceDemo (void) static char demoname[8] = "DEMO1"; static int democount = 0; static int pagecount; - const char *pagename = NULL; + FString pagename; advancedemo = false; @@ -1299,7 +1299,7 @@ void D_DoAdvanceDemo (void) default: case 0: gamestate = GS_DEMOSCREEN; - pagename = gameinfo.titlePage; + pagename = gameinfo.TitlePage; pagetic = (int)(gameinfo.titleTime * TICRATE); S_ChangeMusic (gameinfo.titleMusic, gameinfo.titleOrder, false); demosequence = 3; diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index 664a56307..6b90a6a78 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -42,9 +42,9 @@ void ABasicArmor::Tick () AbsorbCount = 0; if (!Icon.isValid()) { - const char *icon = gameinfo.ArmorIcon1; + FString icon = gameinfo.ArmorIcon1; - if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2[0] != 0) + if (SavePercent >= gameinfo.Armor2Percent && gameinfo.ArmorIcon2.Len() != 0) icon = gameinfo.ArmorIcon2; if (icon[0] != 0) diff --git a/src/gi.cpp b/src/gi.cpp index d9d58dc9e..851a61fb8 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -271,16 +271,14 @@ void FMapInfoParser::ParseGameInfo() else if(nextKey.CompareNoCase("armoricons") == 0) { sc.MustGetToken(TK_StringConst); - strncpy(gameinfo.ArmorIcon1, sc.String, 8); - gameinfo.ArmorIcon1[8] = 0; + gameinfo.ArmorIcon1 = sc.String; if (sc.CheckToken(',')) { sc.MustGetToken(TK_FloatConst); gameinfo.Armor2Percent = FLOAT2FIXED(sc.Float); sc.MustGetToken(','); sc.MustGetToken(TK_StringConst); - strncpy(gameinfo.ArmorIcon2, sc.String, 8); - gameinfo.ArmorIcon2[8] = 0; + gameinfo.ArmorIcon2 = sc.String; } } else if(nextKey.CompareNoCase("maparrow") == 0) @@ -295,7 +293,7 @@ void FMapInfoParser::ParseGameInfo() else gameinfo.mCheatMapArrow = ""; } // Insert valid keys here. - GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8) + GAMEINFOKEY_STRING(TitlePage, "titlePage") GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false) GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true) GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false) @@ -306,17 +304,17 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_FLOAT(pageTime, "pageTime") GAMEINFOKEY_STRING(chatSound, "chatSound") GAMEINFOKEY_MUSIC(finaleMusic, finaleOrder, "finaleMusic") - GAMEINFOKEY_CSTRING(finaleFlat, "finaleFlat", 8) + GAMEINFOKEY_STRING(FinaleFlat, "finaleFlat") GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true) GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false) GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true) - GAMEINFOKEY_CSTRING(PauseSign, "pausesign", 8) + GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") - GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8) + GAMEINFOKEY_STRING(BorderFlat, "borderFlat") GAMEINFOKEY_FIXED(telefogheight, "telefogheight") GAMEINFOKEY_FIXED(gibfactor, "gibfactor") GAMEINFOKEY_INT(defKickback, "defKickback") - GAMEINFOKEY_CSTRING(SkyFlatName, "SkyFlatName", 8) + GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName") GAMEINFOKEY_STRING(translator, "translator") GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor") GAMEINFOKEY_COLOR(defaultbloodcolor, "defaultbloodcolor") @@ -336,7 +334,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultrespawntime, "defaultrespawntime") GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle") - GAMEINFOKEY_CSTRING(Endoom, "endoom", 8) + GAMEINFOKEY_STRING(Endoom, "endoom") GAMEINFOKEY_INT(player5start, "player5start") GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false) GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true) @@ -347,7 +345,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING(mFontColorHeader, "menufontcolor_header") GAMEINFOKEY_STRING(mFontColorHighlight, "menufontcolor_highlight") GAMEINFOKEY_STRING(mFontColorSelection, "menufontcolor_selection") - GAMEINFOKEY_CSTRING(mBackButton, "menubackbutton", 8) + GAMEINFOKEY_STRING(mBackButton, "menubackbutton") GAMEINFOKEY_INT(TextScreenX, "textscreenx") GAMEINFOKEY_INT(TextScreenY, "textscreeny") GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence") diff --git a/src/gi.h b/src/gi.h index 6b887e1dd..9965b1dd1 100644 --- a/src/gi.h +++ b/src/gi.h @@ -78,7 +78,7 @@ struct gameinfo_t EGameType gametype; FString ConfigName; - char titlePage[9]; + FString TitlePage; bool drawreadthis; bool noloopfinalemusic; bool intermissioncounter; @@ -98,13 +98,13 @@ struct gameinfo_t FString chatSound; FString finaleMusic; int finaleOrder; - char finaleFlat[9]; - char borderFlat[9]; - char SkyFlatName[9]; - char ArmorIcon1[9]; - char ArmorIcon2[9]; - char PauseSign[9]; - char Endoom[9]; + FString FinaleFlat; + FString BorderFlat; + FString SkyFlatName; + FString ArmorIcon1; + FString ArmorIcon2; + FString PauseSign; + FString Endoom; fixed_t Armor2Percent; FString quitSound; gameborder_t *border; @@ -133,7 +133,7 @@ struct gameinfo_t FName mFontColorHeader; FName mFontColorHighlight; FName mFontColorSelection; - char mBackButton[9]; + FString mBackButton; fixed_t gibfactor; int TextScreenX; int TextScreenY; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 91090e432..2a52df58a 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -104,7 +104,7 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) } else { - texname = gameinfo.titlePage; + texname = gameinfo.TitlePage.GetChars(); } } else if (*texname == '$') diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 8472637a2..ecd50ec73 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1450,7 +1450,7 @@ void V_DrawBorder (int x1, int y1, int x2, int y2) } else { - picnum = TexMan.CheckForTexture (gameinfo.borderFlat, FTexture::TEX_Flat); + picnum = TexMan.CheckForTexture (gameinfo.BorderFlat, FTexture::TEX_Flat); } if (picnum.isValid()) diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 7aef939b1..0cf5e7b77 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -314,7 +314,7 @@ static bool IsExMy(const char * name) void WI_LoadBackground(bool isenterpic) { - const char * lumpname = NULL; + const char *lumpname; char buffer[10]; in_anim_t an; lnode_t pt; @@ -399,7 +399,7 @@ void WI_LoadBackground(bool isenterpic) default: // Strife doesn't have an intermission pic so choose something neutral. if (isenterpic) return; - lumpname = gameinfo.borderFlat; + lumpname = gameinfo.BorderFlat; break; } } diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 7ffe846e6..04b52925e 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -1086,12 +1086,12 @@ void ST_Endoom() { if (showendoom == 0) exit(0); - if (gameinfo.Endoom[0] == 0) + if (gameinfo.Endoom.Len() == 0) { exit(0); } - int endoom_lump = Wads.CheckNumForName (gameinfo.Endoom); + int endoom_lump = Wads.CheckNumForFullName (gameinfo.Endoom, true); BYTE endoom_screen[4000]; BYTE *font; From a22670626c1b81a7bb97a2742741f50d7541cd75 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 13:40:02 +0200 Subject: [PATCH 206/247] - expanded names for view border elements. Also fixed the horribly bad implementation of custom borders which modified the DoomBorder elements without ever checking the game being used. --- src/g_shared/shared_sbar.cpp | 12 ++++++------ src/gi.cpp | 29 +++++++++++++---------------- src/gi.h | 33 +++++++++++++++++++++++++++++++-- src/v_draw.cpp | 14 +++++++------- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 547f6534e..7e8e660ee 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1090,12 +1090,12 @@ void DBaseStatusBar::RefreshBackground () const if (setblocks >= 10) { - const gameborder_t *border = gameinfo.border; - FTexture *p; - - p = TexMan[border->b]; - screen->FlatFill(0, y, x, y + p->GetHeight(), p, true); - screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true); + FTexture *p = TexMan[gameinfo.Border.b]; + if (p != NULL) + { + screen->FlatFill(0, y, x, y + p->GetHeight(), p, true); + screen->FlatFill(x2, y, SCREENWIDTH, y + p->GetHeight(), p, true); + } } } } diff --git a/src/gi.cpp b/src/gi.cpp index 851a61fb8..8ab935854 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -51,7 +51,7 @@ const char *GameNames[17] = }; -static gameborder_t DoomBorder = +static staticgameborder_t DoomBorder = { 8, 8, "brdr_tl", "brdr_t", "brdr_tr", @@ -59,7 +59,7 @@ static gameborder_t DoomBorder = "brdr_bl", "brdr_b", "brdr_br" }; -static gameborder_t HereticBorder = +static staticgameborder_t HereticBorder = { 4, 16, "bordtl", "bordt", "bordtr", @@ -67,7 +67,7 @@ static gameborder_t HereticBorder = "bordbl", "bordb", "bordbr" }; -static gameborder_t StrifeBorder = +static staticgameborder_t StrifeBorder = { 8, 8, "brdr_tl", "brdr_t", "brdr_tr", @@ -231,40 +231,37 @@ void FMapInfoParser::ParseGameInfo() } else if(nextKey.CompareNoCase("border") == 0) { - if(sc.CheckToken(TK_Identifier)) + staticgameborder_t *b; + if (sc.CheckToken(TK_Identifier)) { switch(sc.MustMatchString(GameInfoBorders)) { default: - gameinfo.border = &DoomBorder; + b = &DoomBorder; break; case 1: - gameinfo.border = &HereticBorder; + b = &HereticBorder; break; case 2: - gameinfo.border = &StrifeBorder; + b = &StrifeBorder; break; } + gameinfo.Border = *b; } else { // border = {size, offset, tr, t, tl, r, l ,br, b, bl}; - char *graphics[8] = {DoomBorder.tr, DoomBorder.t, DoomBorder.tl, DoomBorder.r, DoomBorder.l, DoomBorder.br, DoomBorder.b, DoomBorder.bl}; + FString *graphics[8] = { &gameinfo.Border.tr, &gameinfo.Border.t, &gameinfo.Border.tl, &gameinfo.Border.r, &gameinfo.Border.l, &gameinfo.Border.br, &gameinfo.Border.b, &gameinfo.Border.bl }; sc.MustGetToken(TK_IntConst); - DoomBorder.offset = sc.Number; + gameinfo.Border.offset = sc.Number; sc.MustGetToken(','); sc.MustGetToken(TK_IntConst); - DoomBorder.size = sc.Number; + gameinfo.Border.size = sc.Number; for(int i = 0;i < 8;i++) { sc.MustGetToken(','); sc.MustGetToken(TK_StringConst); - int len = int(strlen(sc.String)); - if(len > 8) - sc.ScriptError("Border graphic can not be more than 8 characters long.\n"); - memcpy(graphics[i], sc.String, len); - if(len < 8) // end with a null byte if the string is less than 8 chars. - graphics[i][len] = 0; + (*graphics[i]) = sc.String; } } } diff --git a/src/gi.h b/src/gi.h index 9965b1dd1..a1a03b2de 100644 --- a/src/gi.h +++ b/src/gi.h @@ -52,7 +52,7 @@ extern const char *GameNames[17]; -struct gameborder_t +struct staticgameborder_t { BYTE offset; BYTE size; @@ -66,6 +66,35 @@ struct gameborder_t char br[8]; }; +struct gameborder_t +{ + BYTE offset; + BYTE size; + FString tl; + FString t; + FString tr; + FString l; + FString r; + FString bl; + FString b; + FString br; + + gameborder_t &operator=(staticgameborder_t &other) + { + offset = other.offset; + size = other.size; + tl = other.tl; + t = other.t; + tr = other.tr; + l = other.l; + r = other.r; + bl = other.bl; + b = other.b; + br = other.br; + return *this; + } +}; + struct FGIFont { FName fontname; @@ -107,7 +136,7 @@ struct gameinfo_t FString Endoom; fixed_t Armor2Percent; FString quitSound; - gameborder_t *border; + gameborder_t Border; int telefogheight; int defKickback; FString translator; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index ecd50ec73..5db99e674 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1407,7 +1407,7 @@ void V_SetBorderNeedRefresh() void V_DrawFrame (int left, int top, int width, int height) { FTexture *p; - const gameborder_t *border = gameinfo.border; + const gameborder_t *border = &gameinfo.Border; // Sanity check for incomplete gameinfo if (border == NULL) return; @@ -1513,28 +1513,28 @@ static void V_DrawTopBorder () if (viewwidth == SCREENWIDTH) return; - offset = gameinfo.border->offset; + offset = gameinfo.Border.offset; if (viewwindowy < 34) { V_DrawBorder (0, 0, viewwindowx, 34); V_DrawBorder (viewwindowx, 0, viewwindowx + viewwidth, viewwindowy); V_DrawBorder (viewwindowx + viewwidth, 0, SCREENWIDTH, 34); - p = TexMan(gameinfo.border->t); + p = TexMan(gameinfo.Border.t); screen->FlatFill(viewwindowx, viewwindowy - p->GetHeight(), viewwindowx + viewwidth, viewwindowy, p, true); - p = TexMan(gameinfo.border->l); + p = TexMan(gameinfo.Border.l); screen->FlatFill(viewwindowx - p->GetWidth(), viewwindowy, viewwindowx, 35, p, true); - p = TexMan(gameinfo.border->r); + p = TexMan(gameinfo.Border.r); screen->FlatFill(viewwindowx + viewwidth, viewwindowy, viewwindowx + viewwidth + p->GetWidth(), 35, p, true); - p = TexMan(gameinfo.border->tl); + p = TexMan(gameinfo.Border.tl); screen->DrawTexture (p, viewwindowx - offset, viewwindowy - offset, TAG_DONE); - p = TexMan(gameinfo.border->tr); + p = TexMan(gameinfo.Border.tr); screen->DrawTexture (p, viewwindowx + viewwidth, viewwindowy - offset, TAG_DONE); } else From ebd6c18bef6ed7e2508d8ee14cb3b65d1fe587fb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 15:32:54 +0200 Subject: [PATCH 207/247] - missed one texture name field in level_info_t. --- src/g_level.cpp | 4 ++-- src/g_level.h | 2 +- src/g_mapinfo.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 47ad66998..c3e78d223 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -656,7 +656,7 @@ void G_DoCompleted (void) AM_Stop (); wminfo.finished_ep = level.cluster - 1; - wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->pname, FTexture::TEX_MiscPatch)]; + wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->PName, FTexture::TEX_MiscPatch)]; wminfo.current = level.mapname; if (deathmatch && @@ -677,7 +677,7 @@ void G_DoCompleted (void) else { wminfo.next = nextinfo->mapname; - wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->pname, FTexture::TEX_MiscPatch)]; + wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->PName, FTexture::TEX_MiscPatch)]; } } diff --git a/src/g_level.h b/src/g_level.h index 43644a279..85a2ff0e4 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -270,9 +270,9 @@ struct level_info_t int levelnum; char mapname[9]; - char pname[9]; char nextmap[11]; char secretmap[11]; + FString PName; FString SkyPic1; FString SkyPic2; FString FadeTable; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index d8e12e9e4..c261e2f33 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -227,7 +227,7 @@ void level_info_t::Reset() mapname[0] = 0; MapBackground = ""; levelnum = 0; - pname[0] = 0; + PName = ""; nextmap[0] = 0; secretmap[0] = 0; SkyPic1 = SkyPic2 = "-NOFLAT-"; @@ -898,7 +898,7 @@ DEFINE_MAP_OPTION(outsidefog, true) DEFINE_MAP_OPTION(titlepatch, true) { parse.ParseAssign(); - parse.ParseLumpOrTextureName(info->pname); + parse.ParseLumpOrTextureName(info->PName); } DEFINE_MAP_OPTION(partime, true) From ca4179caa3486052a3faac818225cf3dd0d8849b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 20:51:16 +0200 Subject: [PATCH 208/247] - allow texture lookup by full path names. Due to technical limitations this may result in double textures if the same graphics lump is also referenced by its short texture name. --- src/g_shared/sbarinfo_commands.cpp | 2 +- src/resourcefiles/resourcefile.h | 3 ++ src/textures/animations.cpp | 4 +- src/textures/multipatchtexture.cpp | 16 +------- src/textures/texture.cpp | 2 + src/textures/texturemanager.cpp | 64 ++++++++++++++++++------------ src/textures/textures.h | 5 +-- src/v_font.cpp | 13 ------ src/w_wad.cpp | 31 +++++++++++++++ src/w_wad.h | 4 ++ 10 files changed, 84 insertions(+), 60 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index fcd9bae7d..a1912b21e 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -300,7 +300,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl if (flags & DI_ALTERNATEONFAIL) { - SetTruth(texture == NULL || !(texture->GetID().isValid()), block, statusBar); + SetTruth(texture == NULL || texture->UseType == FTexture::TEX_Null, block, statusBar); } } protected: diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index e531ddbb3..517b5eef4 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -6,6 +6,7 @@ #include "files.h" class FResourceFile; +class FTexture; struct FResourceLump { @@ -24,6 +25,7 @@ struct FResourceLump SBYTE RefCount; char * Cache; FResourceFile * Owner; + FTexture * LinkedTexture; int Namespace; FResourceLump() @@ -35,6 +37,7 @@ struct FResourceLump RefCount = 0; Namespace = 0; // ns_global *Name = 0; + LinkedTexture = NULL; } virtual ~FResourceLump(); diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 433baa874..3601646a0 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -551,7 +551,7 @@ void FTextureManager::ParseTime (FScanner &sc, DWORD &min, DWORD &max) void FTextureManager::ParseWarp(FScanner &sc) { - const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; bool isflat = false; bool type2 = sc.Compare ("warp2"); // [GRB] sc.MustGetString (); @@ -616,7 +616,7 @@ void FTextureManager::ParseWarp(FScanner &sc) void FTextureManager::ParseCameraTexture(FScanner &sc) { - const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; int width, height; int fitwidth, fitheight; FString picname; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 4f327309d..124add5db 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -1001,21 +1001,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i if (!texno.isValid()) { - int lumpnum = Wads.CheckNumForFullName(sc.String); - if (lumpnum >= 0) - { - texno = TexMan.FindTextureByLumpNum(lumpnum); - if (texno.isValid ()) - { - part.Texture = TexMan[texno]; - } - else - { - part.Texture = FTexture::CreateTexture("", lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - else if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) + if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) { int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); if (lumpnum >= 0) diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 0434aaaa4..f41f1902d 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -167,6 +167,8 @@ FTexture::FTexture (const char *name, int lumpnum) FTexture::~FTexture () { + FTexture *link = Wads.GetLinkedTexture(SourceLump); + if (link == this) Wads.SetLinkedTexture(SourceLump, NULL); KillNative(); } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index cdacb95bd..0af15d7af 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -224,6 +224,35 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF return FTextureID(firstfound); } + + if (!(flags & TEXMAN_ShortNameOnly)) + { + // We intentionally only look for textures in subdirectories. + // Any graphic being placed in the zip's root directory can not be found by this. + if (strchr(name, '/')) + { + FTexture *const NO_TEXTURE = (FTexture*)-1; + int lump = Wads.CheckNumForFullName(name); + if (lump != NULL) + { + FTexture *tex = Wads.GetLinkedTexture(lump); + if (tex == NO_TEXTURE) return FTextureID(-1); + if (tex != NULL) return tex->id; + tex = FTexture::CreateTexture("", lump, FTexture::TEX_Override); + if (tex != NULL) + { + Wads.SetLinkedTexture(lump, tex); + return AddTexture(tex); + } + else + { + // mark this lump as having no valid texture so that we don't have to retry creating one later. + Wads.SetLinkedTexture(lump, NO_TEXTURE); + } + } + } + } + return FTextureID(-1); } @@ -273,30 +302,6 @@ int FTextureManager::ListTextures (const char *name, TArray &list) return list.Size(); } -//========================================================================== -// -// FTextureManager :: FindTextureByLumpNum -// -//========================================================================== - -FTextureID FTextureManager::FindTextureByLumpNum (int lumpnum) -{ - if (lumpnum < 0) - { - return FTextureID(-1); - } - // This can't use hashing because using ReplaceTexture would break the hash chains. :( - for(unsigned i = 0; i SourceLump == lumpnum) - { - return FTextureID(i); - } - } - return FTextureID(-1); -} - - //========================================================================== // // FTextureManager :: GetTextures @@ -1093,8 +1098,15 @@ void FTextureManager::WriteTexture (FArchive &arc, int picnum) pic = Textures[picnum].Texture; } - arc.WriteName (pic->Name); - arc.WriteCount (pic->UseType); + if (Wads.GetLinkedTexture(pic->SourceLump) == pic) + { + arc.WriteName(Wads.GetLumpFullName(pic->SourceLump)); + } + else + { + arc.WriteName(pic->Name); + } + arc.WriteCount(pic->UseType); } //========================================================================== diff --git a/src/textures/textures.h b/src/textures/textures.h index 2992d8a46..8c41ee844 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -217,7 +217,6 @@ public: virtual int GetSourceLump() { return SourceLump; } virtual FTexture *GetRedirect(bool wantwarped); virtual FTexture *GetRawTexture(); // for FMultiPatchTexture to override - FTextureID GetID() const { return id; } virtual void Unload () = 0; @@ -363,12 +362,12 @@ public: TEXMAN_TryAny = 1, TEXMAN_Overridable = 2, TEXMAN_ReturnFirst = 4, - TEXMAN_AllowSkins = 8 + TEXMAN_AllowSkins = 8, + TEXMAN_ShortNameOnly = 16 }; FTextureID CheckForTexture (const char *name, int usetype, BITFIELD flags=TEXMAN_TryAny); FTextureID GetTexture (const char *name, int usetype, BITFIELD flags=0); - FTextureID FindTextureByLumpNum (int lumpnum); int ListTextures (const char *name, TArray &list); void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false); diff --git a/src/v_font.cpp b/src/v_font.cpp index abd7f494c..5fc2994fb 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2193,19 +2193,6 @@ void V_InitCustomFonts() FTexture **p = &lumplist[*(unsigned char*)sc.String]; sc.MustGetString(); FTextureID texid = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); - if (!texid.Exists()) - { - int lumpno = Wads.CheckNumForFullName (sc.String); - if (lumpno >= 0) - { - texid = TexMan.FindTextureByLumpNum(lumpno); - if (!texid.Exists()) - { - FTexture *tex = FTexture::CreateTexture("", lumpno, FTexture::TEX_MiscPatch); - texid = TexMan.AddTexture(tex); - } - } - } if (texid.Exists()) { *p = TexMan[texid]; diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 11a9b4213..c351de6f8 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -548,6 +548,37 @@ int FWadCollection::GetNumForFullName (const char *name) return i; } +//========================================================================== +// +// link a texture with a given lump +// +//========================================================================== + +void FWadCollection::SetLinkedTexture(int lump, FTexture *tex) +{ + if ((size_t)lump < NumLumps) + { + FResourceLump *reslump = LumpInfo[lump].lump; + reslump->LinkedTexture = tex; + } +} + +//========================================================================== +// +// retrieve linked texture +// +//========================================================================== + +FTexture *FWadCollection::GetLinkedTexture(int lump) +{ + if ((size_t)lump < NumLumps) + { + FResourceLump *reslump = LumpInfo[lump].lump; + return reslump->LinkedTexture; + } + return NULL; +} + //========================================================================== // // W_LumpLength diff --git a/src/w_wad.h b/src/w_wad.h index e0b21b66c..530182147 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -29,6 +29,7 @@ class FResourceFile; struct FResourceLump; +class FTexture; struct wadinfo_t { @@ -171,6 +172,9 @@ public: int CheckNumForFullName (const char *name, int wadfile); int GetNumForFullName (const char *name); + void SetLinkedTexture(int lump, FTexture *tex); + FTexture *GetLinkedTexture(int lump); + void ReadLump (int lump, void *dest); FMemLump ReadLump (int lump); From 30f57c0b8e31dbc703d15180614837a43de08177 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 21:16:06 +0200 Subject: [PATCH 209/247] - added new renderstyles AddStencil and AddShaded. --- src/g_shared/a_artifacts.cpp | 16 ++++++++++++++-- src/namedef.h | 2 ++ src/p_acs.cpp | 2 ++ src/p_udmf.cpp | 6 ++++++ src/r_data/renderstyle.cpp | 28 ++++++++++++++++------------ src/r_data/renderstyle.h | 2 ++ src/thingdef/thingdef_properties.cpp | 4 ++-- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 2ef2b03c5..8891c8674 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -605,7 +605,13 @@ void APowerInvisibility::DoEffect () case (NAME_Stencil): Owner->RenderStyle = STYLE_Stencil; break; - case (NAME_None): + case (NAME_AddStencil) : + Owner->RenderStyle = STYLE_AddStencil; + break; + case (NAME_TranslucentStencil) : + Owner->RenderStyle = STYLE_TranslucentStencil; + break; + case (NAME_None) : case (NAME_Cumulative): case (NAME_Translucent): Owner->RenderStyle = STYLE_Translucent; @@ -685,7 +691,13 @@ int APowerInvisibility::AlterWeaponSprite (visstyle_t *vis) case (NAME_Stencil): vis->RenderStyle = STYLE_Stencil; break; - case (NAME_None): + case (NAME_TranslucentStencil) : + vis->RenderStyle = STYLE_TranslucentStencil; + break; + case (NAME_AddStencil) : + vis->RenderStyle = STYLE_AddStencil; + break; + case (NAME_None) : case (NAME_Cumulative): case (NAME_Translucent): default: diff --git a/src/namedef.h b/src/namedef.h index 017f29932..ba6de104d 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -30,6 +30,7 @@ xx(Cumulative) xx(Fuzzy) xx(Opaque) xx(Stencil) +xx(AddStencil) // Render styles xx(Normal) @@ -37,6 +38,7 @@ xx(SoulTrans) xx(OptFuzzy) xx(Add) xx(Shaded) +xx(AddShaded) xx(TranslucentStencil) xx(Shadow) xx(Subtract) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 04aecaed1..2929bb74b 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3542,6 +3542,8 @@ static const int LegacyRenderStyleIndices[] = 3, // STYLE_SoulTrans, 4, // STYLE_OptFuzzy, 5, // STYLE_Stencil, + 6, // STYLE_AddStencil + 7, // STYLE_AddShaded 64, // STYLE_Translucent 65, // STYLE_Add, 66, // STYLE_Shaded, diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 6af777b36..2fa968502 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -658,6 +658,9 @@ public: case NAME_Stencil: th->RenderStyle = STYLE_Stencil; break; + case NAME_AddStencil: + th->RenderStyle = STYLE_AddStencil; + break; case NAME_Translucent: th->RenderStyle = STYLE_Translucent; break; @@ -668,6 +671,9 @@ public: case NAME_Shaded: th->RenderStyle = STYLE_Shaded; break; + case NAME_AddShaded: + th->RenderStyle = STYLE_AddShaded; + break; case NAME_TranslucentStencil: th->RenderStyle = STYLE_TranslucentStencil; break; diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 660cd8f09..81524aabb 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -47,18 +47,20 @@ CVAR (Int, r_drawfuzz, 1, CVAR_ARCHIVE) #ifndef __APPLE__ FRenderStyle LegacyRenderStyles[STYLE_Count] = { - /* STYLE_None */ {{ STYLEOP_None, STYLEALPHA_Zero, STYLEALPHA_Zero, 0 }}, - /* STYLE_Normal */ {{ STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 }}, - /* STYLE_Fuzzy */ {{ STYLEOP_Fuzz, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 }}, - /* 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 }}, - /* STYLE_Shadow */ {{ STYLEOP_Shadow, 0, 0, 0 }}, - /* STYLE_Subtract*/ {{ STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 }}, + { { STYLEOP_None, STYLEALPHA_Zero, STYLEALPHA_Zero, 0 } }, /* STYLE_None */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 } }, /* STYLE_Normal */ + { { STYLEOP_Fuzz, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_Fuzzy */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_TransSoulsAlpha } }, /* STYLE_SoulTrans */ + { { STYLEOP_FuzzOrAdd, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_OptFuzzy */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_Alpha1 | STYLEF_ColorIsFixed } }, /* STYLE_Stencil */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, 0 } }, /* STYLE_Translucent */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Add */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_Shaded */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed } }, /* STYLE_TranslucentStencil */ + { { STYLEOP_Shadow, 0, 0, 0 } }, /* STYLE_Shadow */ + { { STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Subtract*/ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_ColorIsFixed } }, /* STYLE_AddStencil */ + { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */ }; #else FRenderStyle LegacyRenderStyles[STYLE_Count]; @@ -77,6 +79,8 @@ static const BYTE Styles[STYLE_Count * 4] = STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_InvSrc, STYLEF_ColorIsFixed, STYLEOP_Shadow, 0, 0, 0, STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0, + STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_Alpha1 | STYLEF_ColorIsFixed, + STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed, }; static struct LegacyInit diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index bd589e8c7..3d617eff2 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -50,6 +50,8 @@ enum ERenderStyle STYLE_TranslucentStencil, STYLE_Shadow, STYLE_Subtract, // Actually this is 'reverse subtract' but this is what normal people would expect by 'subtract'. + STYLE_AddStencil, // Fill image interior with alphacolor + STYLE_AddShaded, // Treat patch data as alpha values for alphacolor STYLE_Count }; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 4e4fb4218..3b61bedca 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -797,12 +797,12 @@ DEFINE_PROPERTY(renderstyle, S, Actor) PROP_STRING_PARM(str, 0); static const char * renderstyles[]={ "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL", - "TRANSLUCENT", "ADD", "SHADED", "SHADOW", "SUBTRACT", NULL }; + "TRANSLUCENT", "ADD", "SHADED", "SHADOW", "SUBTRACT", "ADDSTENCIL", "ADDSHADED", NULL }; static const int renderstyle_values[]={ STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy, STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded, - STYLE_Shadow, STYLE_Subtract}; + STYLE_Shadow, STYLE_Subtract, STYLE_AddStencil, STYLE_AddShaded}; // make this work for old style decorations, too. if (!strnicmp(str, "style_", 6)) str+=6; From e49e926bd95a95f963859878fbb2d2fdc074b60d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 21:26:51 +0200 Subject: [PATCH 210/247] - added option to ASectorAction to remove itself upon triggering by setting the STANDSTILL flag on the map thing. --- src/g_shared/a_sectoraction.cpp | 84 +++++++++++++++++++-------------- src/r_defs.h | 5 +- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index ed73b5ae7..570818e19 100644 --- a/src/g_shared/a_sectoraction.cpp +++ b/src/g_shared/a_sectoraction.cpp @@ -82,10 +82,22 @@ void ASectorAction::Deactivate (AActor *source) flags2 |= MF2_DORMANT; // Projectiles can trigger } -bool ASectorAction::TriggerAction (AActor *triggerer, int activationType) +bool ASectorAction::TriggerAction(AActor *triggerer, int activationType) +{ + if (DoTriggerAction(triggerer, activationType)) + { + if (flags4 & MF4_STANDSTILL) + { + Destroy(); + } + } + return false; +} + +bool ASectorAction::DoTriggerAction (AActor *triggerer, int activationType) { if (tracer != NULL) - return barrier_cast(tracer)->TriggerAction (triggerer, activationType); + return barrier_cast(tracer)->DoTriggerAction (triggerer, activationType); else return false; } @@ -93,7 +105,7 @@ bool ASectorAction::TriggerAction (AActor *triggerer, int activationType) bool ASectorAction::CheckTrigger (AActor *triggerer) const { if (special && - (triggerer->player || + ((triggerer->player && !(flags & MF_FRIENDLY)) || ((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) || ((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS)))) { @@ -110,16 +122,16 @@ class ASecActEnter : public ASectorAction { DECLARE_CLASS (ASecActEnter, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEnter) -bool ASecActEnter::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEnter::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Enter) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when leaving sector -------------------------------------------- @@ -128,16 +140,16 @@ class ASecActExit : public ASectorAction { DECLARE_CLASS (ASecActExit, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActExit) -bool ASecActExit::TriggerAction (AActor *triggerer, int activationType) +bool ASecActExit::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Exit) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when hitting sector's floor ------------------------------------ @@ -146,7 +158,7 @@ class ASecActHitFloor : public ASectorAction { DECLARE_CLASS (ASecActHitFloor, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; // Skull Tag uses 9999 for a special that is triggered whenever @@ -154,10 +166,10 @@ public: IMPLEMENT_CLASS (ASecActHitFloor) -bool ASecActHitFloor::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitFloor::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitFloor) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when hitting sector's ceiling ---------------------------------- @@ -166,16 +178,16 @@ class ASecActHitCeil : public ASectorAction { DECLARE_CLASS (ASecActHitCeil, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActHitCeil) -bool ASecActHitCeil::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitCeil::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitCeiling) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when using inside sector --------------------------------------- @@ -184,16 +196,16 @@ class ASecActUse : public ASectorAction { DECLARE_CLASS (ASecActUse, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActUse) -bool ASecActUse::TriggerAction (AActor *triggerer, int activationType) +bool ASecActUse::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_Use) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when using a sector's wall ------------------------------------- @@ -202,16 +214,16 @@ class ASecActUseWall : public ASectorAction { DECLARE_CLASS (ASecActUseWall, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActUseWall) -bool ASecActUseWall::TriggerAction (AActor *triggerer, int activationType) +bool ASecActUseWall::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_UseWall) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -220,16 +232,16 @@ class ASecActEyesDive : public ASectorAction { DECLARE_CLASS (ASecActEyesDive, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesDive) -bool ASecActEyesDive::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesDive::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesDive) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go above fake floor ---------------------------------- @@ -238,16 +250,16 @@ class ASecActEyesSurface : public ASectorAction { DECLARE_CLASS (ASecActEyesSurface, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesSurface) -bool ASecActEyesSurface::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesSurface::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesSurface) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -256,16 +268,16 @@ class ASecActEyesBelowC : public ASectorAction { DECLARE_CLASS (ASecActEyesBelowC, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesBelowC) -bool ASecActEyesBelowC::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesBelowC::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesBelowC) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go above fake floor ---------------------------------- @@ -274,16 +286,16 @@ class ASecActEyesAboveC : public ASectorAction { DECLARE_CLASS (ASecActEyesAboveC, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActEyesAboveC) -bool ASecActEyesAboveC::TriggerAction (AActor *triggerer, int activationType) +bool ASecActEyesAboveC::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_EyesAboveC) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } // Triggered when eyes go below fake floor ---------------------------------- @@ -292,14 +304,14 @@ class ASecActHitFakeFloor : public ASectorAction { DECLARE_CLASS (ASecActHitFakeFloor, ASectorAction) public: - bool TriggerAction (AActor *triggerer, int activationType); + bool DoTriggerAction (AActor *triggerer, int activationType); }; IMPLEMENT_CLASS (ASecActHitFakeFloor) -bool ASecActHitFakeFloor::TriggerAction (AActor *triggerer, int activationType) +bool ASecActHitFakeFloor::DoTriggerAction (AActor *triggerer, int activationType) { bool didit = (activationType & SECSPAC_HitFakeFloor) ? CheckTrigger (triggerer) : false; - return didit | Super::TriggerAction (triggerer, activationType); + return didit | Super::DoTriggerAction (triggerer, activationType); } diff --git a/src/r_defs.h b/src/r_defs.h index c2f3e5b34..2e9c0876b 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -198,9 +198,10 @@ public: void BeginPlay (); void Activate (AActor *source); void Deactivate (AActor *source); - virtual bool TriggerAction (AActor *triggerer, int activationType); + bool TriggerAction(AActor *triggerer, int activationType); protected: - bool CheckTrigger (AActor *triggerer) const; + virtual bool DoTriggerAction(AActor *triggerer, int activationType); + bool CheckTrigger(AActor *triggerer) const; }; class ASkyViewpoint; From 24886b6734523df3c5b8847afb3465465299f839 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 13 May 2014 23:16:13 +0200 Subject: [PATCH 211/247] - removed the last static character arrays from FLevelLocals. --- src/c_cmds.cpp | 19 +++++--------- src/d_net.cpp | 2 +- src/fragglescript/t_load.cpp | 6 ++--- src/g_game.cpp | 8 +++--- src/g_hexen/a_heresiarch.cpp | 2 +- src/g_level.cpp | 41 +++++++++++++----------------- src/g_level.h | 6 ++--- src/g_shared/sbarinfo_commands.cpp | 2 +- src/g_shared/shared_sbar.cpp | 2 +- src/p_acs.cpp | 12 ++++----- src/p_lnspec.cpp | 10 ++++---- src/p_setup.cpp | 2 +- src/p_setup.h | 2 +- src/p_spec.h | 4 +-- src/st_stuff.cpp | 2 +- src/statistics.cpp | 5 ++-- src/win32/i_main.cpp | 6 +---- src/zstring.h | 4 +++ 18 files changed, 61 insertions(+), 74 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 7b6f1d195..89005dbc7 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -986,14 +986,10 @@ CCMD(nextmap) TEXTCOLOR_NORMAL " is for single-player only.\n"); return; } - char *next = NULL; - if (*level.nextmap) - next = level.nextmap; - - if (next != NULL && strncmp(next, "enDSeQ", 6)) + if (level.NextMap.Len() > 0 && level.NextMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(next); + G_DeferedInitNew(level.NextMap); } else { @@ -1016,12 +1012,9 @@ CCMD(nextsecret) } char *next = NULL; - if (*level.secretmap) - next = level.secretmap; - - if (next != NULL && strncmp(next, "enDSeQ", 6)) + if (level.NextSecretMap.Len() > 0 && level.NextSecretMap.Compare("enDSeQ", 6)) { - G_DeferedInitNew(next); + G_DeferedInitNew(level.NextSecretMap); } else { @@ -1107,8 +1100,8 @@ static void PrintSecretString(const char *string, bool thislevel) CCMD(secret) { - const char *mapname = argv.argc() < 2? level.mapname : argv[1]; - bool thislevel = !stricmp(mapname, level.mapname); + const char *mapname = argv.argc() < 2? level.MapName.GetChars() : argv[1]; + bool thislevel = !stricmp(mapname, level.MapName); bool foundsome = false; int lumpno=Wads.CheckNumForName("SECRETS"); diff --git a/src/d_net.cpp b/src/d_net.cpp index 170e9ed12..a2e0798b2 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2573,7 +2573,7 @@ static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int arg[i] = argval; } } - P_StartScript(pawn, NULL, snum, level.mapname, arg, MIN(countof(arg), argn), ACS_NET | always); + P_StartScript(pawn, NULL, snum, level.MapName, arg, MIN(countof(arg), argn), ACS_NET | always); } void Net_SkipCommand (int type, BYTE **stream) diff --git a/src/fragglescript/t_load.cpp b/src/fragglescript/t_load.cpp index 49458c4be..eedb68f7c 100644 --- a/src/fragglescript/t_load.cpp +++ b/src/fragglescript/t_load.cpp @@ -202,15 +202,13 @@ void FScriptLoader::ParseInfoCmd(char *line, FString &scriptsrc) { sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.nextmap, sc.String, 8); - level.nextmap[8]=0; + level.NextMap = sc.String; } else if (sc.Compare("nextsecret")) { sc.MustGetStringName("="); sc.MustGetString(); - strncpy(level.secretmap, sc.String, 8); - level.secretmap[8]=0; + level.NextSecretMap = sc.String; } else if (sc.Compare("drown")) { diff --git a/src/g_game.cpp b/src/g_game.cpp index 7875d9c3b..045b331bf 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1621,7 +1621,7 @@ void G_DoReborn (int playernum, bool freshbot) { // Reload the level from scratch bool indemo = demoplayback; BackupSaveName = ""; - G_InitNew (level.mapname, false); + G_InitNew (level.MapName, false); demoplayback = indemo; // gameaction = ga_loadlevel; } @@ -2027,7 +2027,7 @@ static void PutSaveComment (FILE *file) // Get level name //strcpy (comment, level.level_name); - mysnprintf(comment, countof(comment), "%s - %s", level.mapname, level.LevelName.GetChars()); + mysnprintf(comment, countof(comment), "%s - %s", level.MapName.GetChars(), level.LevelName.GetChars()); len = (WORD)strlen (comment); comment[len] = '\n'; @@ -2088,7 +2088,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio M_AppendPNGText (stdfile, "Engine", GAMESIG); M_AppendPNGText (stdfile, "ZDoom Save Version", SAVESIG); M_AppendPNGText (stdfile, "Title", description); - M_AppendPNGText (stdfile, "Current Map", level.mapname); + M_AppendPNGText (stdfile, "Current Map", level.MapName); PutSaveWads (stdfile); PutSaveComment (stdfile); @@ -2289,7 +2289,7 @@ void G_BeginRecording (const char *startmap) if (startmap == NULL) { - startmap = level.mapname; + startmap = level.MapName; } demo_p = demobuffer; diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index b5bbced2f..15e6da9c1 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -88,7 +88,7 @@ void AHeresiarch::Die (AActor *source, AActor *inflictor, int dmgflags) if (script != 0) { - P_StartScript (this, NULL, script, level.mapname, NULL, 0, 0); + P_StartScript (this, NULL, script, level.MapName, NULL, 0, 0); } } diff --git a/src/g_level.cpp b/src/g_level.cpp index c3e78d223..7cbbef6e0 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -445,10 +445,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) bglobal.Init (); } - if (mapname != level.mapname) - { - strcpy (level.mapname, mapname); - } + level.MapName = mapname; if (bTitleLevel) { gamestate = GS_TITLELEVEL; @@ -491,9 +488,9 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill { // end the game levelname = NULL; - if (!strncmp(level.nextmap, "enDSeQ",6)) + if (!level.NextMap.Compare("enDSeQ",6)) { - levelname = level.nextmap; // If there is already an end sequence please leave it alone! + nextlevel = level.NextMap; // If there is already an end sequence please leave it alone! } else { @@ -596,18 +593,18 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill const char *G_GetExitMap() { - return level.nextmap; + return level.NextMap; } const char *G_GetSecretExitMap() { - const char *nextmap = level.nextmap; + const char *nextmap = level.NextMap; - if (level.secretmap[0] != 0) + if (level.NextSecretMap.Len() > 0) { - if (P_CheckMapData(level.secretmap)) + if (P_CheckMapData(level.NextSecretMap)) { - nextmap = level.secretmap; + nextmap = level.NextSecretMap; } } return nextmap; @@ -641,7 +638,7 @@ void G_DoCompleted (void) if (gamestate == GS_TITLELEVEL) { - strncpy (level.mapname, nextlevel, 255); + level.MapName = nextlevel; G_DoLoadLevel (startpos, false); startpos = 0; viewactive = true; @@ -650,20 +647,20 @@ void G_DoCompleted (void) // [RH] Mark this level as having been visited if (!(level.flags & LEVEL_CHANGEMAPCHEAT)) - FindLevelInfo (level.mapname)->flags |= LEVEL_VISITED; + FindLevelInfo (level.MapName)->flags |= LEVEL_VISITED; if (automapactive) AM_Stop (); wminfo.finished_ep = level.cluster - 1; wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->PName, FTexture::TEX_MiscPatch)]; - wminfo.current = level.mapname; + wminfo.current = level.MapName; if (deathmatch && (dmflags & DF_SAME_LEVEL) && !(level.flags & LEVEL_CHANGEMAPCHEAT)) { - wminfo.next = level.mapname; + wminfo.next = level.MapName; wminfo.LName1 = wminfo.LName0; } else @@ -850,7 +847,7 @@ void G_DoLoadLevel (int position, bool autosave) "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" "\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", - level.mapname, level.LevelName.GetChars()); + level.MapName.GetChars(), level.LevelName.GetChars()); if (wipegamestate == GS_LEVEL) wipegamestate = GS_FORCEWIPE; @@ -899,7 +896,7 @@ void G_DoLoadLevel (int position, bool autosave) } level.maptime = 0; - P_SetupLevel (level.mapname, position); + P_SetupLevel (level.MapName, position); AM_LevelInit(); @@ -1056,7 +1053,7 @@ void G_DoWorldDone (void) } else { - strncpy (level.mapname, nextlevel, 255); + level.MapName = nextlevel; } G_StartTravel (); G_DoLoadLevel (startpos, true); @@ -1217,7 +1214,7 @@ void G_InitLevelLocals () level.flags = 0; level.flags2 = 0; - info = FindLevelInfo (level.mapname); + info = FindLevelInfo (level.MapName); level.info = info; level.skyspeed1 = info->skyspeed1; @@ -1274,10 +1271,8 @@ void G_InitLevelLocals () level.musicorder = info->musicorder; level.LevelName = level.info->LookupLevelName(); - strncpy (level.nextmap, info->nextmap, 10); - level.nextmap[10] = 0; - strncpy (level.secretmap, info->secretmap, 10); - level.secretmap[10] = 0; + level.NextMap = info->nextmap; + level.NextSecretMap = info->secretmap; compatflags.Callback(); compatflags2.Callback(); diff --git a/src/g_level.h b/src/g_level.h index 85a2ff0e4..cd1e9e60d 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -391,9 +391,9 @@ struct FLevelLocals int levelnum; int lumpnum; FString LevelName; - char mapname[256]; // the lump name (E1M1, MAP01, etc) - char nextmap[11]; // go here when using the regular exit - char secretmap[11]; // map to go to when used secret exit + FString MapName; // the lump name (E1M1, MAP01, etc) + FString NextMap; // go here when using the regular exit + FString NextSecretMap; // map to go to when used secret exit EMapType maptype; DWORD flags; diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index a1912b21e..629c31cb4 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -830,7 +830,7 @@ class CommandDrawString : public SBarInfoCommand if(level.lumpnum != cache) { cache = level.lumpnum; - str = level.mapname; + str = level.MapName; str.ToUpper(); RealignString(); } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 7e8e660ee..6b2f609b7 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -131,7 +131,7 @@ void ST_FormatMapName(FString &mapname, const char *mapnamecolor) if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub)) { - mapname << level.mapname << ": "; + mapname << level.MapName << ": "; } mapname << mapnamecolor << level.LevelName; } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2929bb74b..bd8c53edf 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6981,7 +6981,7 @@ scriptwait: break; case PRINTNAME_LEVEL: - work += level.mapname; + work += level.MapName; break; case PRINTNAME_SKILL: @@ -8950,7 +8950,7 @@ EXTERN_CVAR (Bool, sv_cheats) int P_StartScript (AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags) { - if (map == NULL || 0 == strnicmp (level.mapname, map, 8)) + if (map == NULL || 0 == strnicmp (level.MapName, map, 8)) { FBehavior *module = NULL; const ScriptPtr *scriptdata; @@ -9003,17 +9003,17 @@ int P_StartScript (AActor *who, line_t *where, int script, const char *map, cons return false; } -void P_SuspendScript (int script, char *map) +void P_SuspendScript (int script, const char *map) { - if (strnicmp (level.mapname, map, 8)) + if (strnicmp (level.MapName, map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defsuspend, script, NULL, 0, NULL); else SetScriptState (script, DLevelScript::SCRIPT_Suspended); } -void P_TerminateScript (int script, char *map) +void P_TerminateScript (int script, const char *map) { - if (strnicmp (level.mapname, map, 8)) + if (strnicmp (level.MapName, map, 8)) addDefered (FindLevelInfo (map), acsdefered_t::defterminate, script, NULL, 0, NULL); else SetScriptState (script, DLevelScript::SCRIPT_PleaseRemove); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 12c877116..d94a16fbb 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1644,7 +1644,7 @@ FUNC(LS_ACS_Execute) if (arg1 == 0) { - mapname = level.mapname; + mapname = level.MapName; } else if ((info = FindLevelByNum(arg1)) != NULL) { @@ -1667,7 +1667,7 @@ FUNC(LS_ACS_ExecuteAlways) if (arg1 == 0) { - mapname = level.mapname; + mapname = level.MapName; } else if ((info = FindLevelByNum(arg1)) != NULL) { @@ -1707,7 +1707,7 @@ FUNC(LS_ACS_ExecuteWithResult) int args[4] = { arg1, arg2, arg3, arg4 }; int flags = (backSide ? ACS_BACKSIDE : 0) | ACS_ALWAYS | ACS_WANTRESULT; - return P_StartScript (it, ln, arg0, level.mapname, args, 4, flags); + return P_StartScript (it, ln, arg0, level.MapName, args, 4, flags); } FUNC(LS_ACS_Suspend) @@ -1716,7 +1716,7 @@ FUNC(LS_ACS_Suspend) level_info_t *info; if (arg1 == 0) - P_SuspendScript (arg0, level.mapname); + P_SuspendScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) P_SuspendScript (arg0, info->mapname); @@ -1729,7 +1729,7 @@ FUNC(LS_ACS_Terminate) level_info_t *info; if (arg1 == 0) - P_TerminateScript (arg0, level.mapname); + P_TerminateScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) P_TerminateScript (arg0, info->mapname); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index c564d1aa7..4f1329f85 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3559,7 +3559,7 @@ void P_FreeExtraLevelData() // // [RH] position indicates the start spot to spawn at -void P_SetupLevel (char *lumpname, int position) +void P_SetupLevel (const char *lumpname, int position) { cycle_t times[20]; FMapThing *buildthings; diff --git a/src/p_setup.h b/src/p_setup.h index 4a41a76f9..ee26f4c57 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -103,7 +103,7 @@ bool P_CheckMapData(const char * mapname); // [RH] The only parameter used is mapname, so I removed playermask and skill. // On September 1, 1998, I added the position to indicate which set // of single-player start spots should be spawned in the level. -void P_SetupLevel (char *mapname, int position); +void P_SetupLevel (const char *mapname, int position); void P_FreeLevelData(); void P_FreeExtraLevelData(); diff --git a/src/p_spec.h b/src/p_spec.h index 57d216972..f8dad701b 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -902,8 +902,8 @@ bool EV_TeleportSector (int tag, int source_tid, int dest_tid, bool fog, int gro #define ACS_NET 8 int P_StartScript (AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags); -void P_SuspendScript (int script, char *map); -void P_TerminateScript (int script, char *map); +void P_SuspendScript (int script, const char *map); +void P_TerminateScript (int script, const char *map); void P_DoDeferedScripts (void); // diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp index 8679e967c..84982300c 100644 --- a/src/st_stuff.cpp +++ b/src/st_stuff.cpp @@ -484,7 +484,7 @@ static bool Cht_ChangeStartSpot (cheatseq_t *cheat) { char cmd[64]; - mysnprintf (cmd, countof(cmd), "changemap %s %c", level.mapname, cheat->Args[0]); + mysnprintf (cmd, countof(cmd), "changemap %s %c", level.MapName.GetChars(), cheat->Args[0]); C_DoCommand (cmd); return true; } diff --git a/src/statistics.cpp b/src/statistics.cpp index 81cd88983..acd8440e8 100644 --- a/src/statistics.cpp +++ b/src/statistics.cpp @@ -408,12 +408,13 @@ static void StoreLevelStats() { for(i=0;i Date: Wed, 14 May 2014 00:52:16 +0200 Subject: [PATCH 212/247] - removed 8 character limit for map names. --- src/g_level.cpp | 26 +++++++++++---------- src/g_level.h | 10 ++++---- src/g_mapinfo.cpp | 59 +++++++++++++++++++++++------------------------ src/p_acs.cpp | 2 +- src/p_lnspec.cpp | 10 ++++---- src/p_setup.cpp | 5 ++-- src/zstring.cpp | 9 +++++++- src/zstring.h | 1 + 8 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 7cbbef6e0..74a92edb5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -506,12 +506,14 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill if (nextredir != NULL) { nextinfo = nextredir; - levelname = nextinfo->mapname; } } + nextlevel = nextinfo->MapName; + } + else + { + nextlevel = levelname; } - - if (levelname != NULL) nextlevel = levelname; if (nextSkill != -1) NextSkill = nextSkill; @@ -673,7 +675,7 @@ void G_DoCompleted (void) } else { - wminfo.next = nextinfo->mapname; + wminfo.next = nextinfo->MapName; wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->PName, FTexture::TEX_MiscPatch)]; } } @@ -1271,8 +1273,8 @@ void G_InitLevelLocals () level.musicorder = info->musicorder; level.LevelName = level.info->LookupLevelName(); - level.NextMap = info->nextmap; - level.NextSecretMap = info->secretmap; + level.NextMap = info->NextMap; + level.NextSecretMap = info->NextSecretMap; compatflags.Callback(); compatflags2.Callback(); @@ -1616,7 +1618,7 @@ static void writeMapName (FArchive &arc, const char *name) static void writeSnapShot (FArchive &arc, level_info_t *i) { arc << i->snapshotVer; - writeMapName (arc, i->mapname); + writeMapName (arc, i->MapName); i->snapshot->Serialize (arc); } @@ -1654,7 +1656,7 @@ void G_WriteSnapshots (FILE *file) { arc = new FPNGChunkArchive (file, VIST_ID); } - writeMapName (*arc, wadlevelinfos[i].mapname); + writeMapName (*arc, wadlevelinfos[i].MapName); } } @@ -1793,7 +1795,7 @@ CCMD(listsnapshots) { unsigned int comp, uncomp; snapshot->GetSizes(comp, uncomp); - Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].mapname, comp, uncomp); + Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), comp, uncomp); } } } @@ -1805,7 +1807,7 @@ CCMD(listsnapshots) static void writeDefereds (FArchive &arc, level_info_t *i) { - writeMapName (arc, i->mapname); + writeMapName (arc, i->MapName); arc << i->defered; } @@ -1917,11 +1919,11 @@ CCMD(listmaps) for(unsigned i = 0; i < wadlevelinfos.Size(); i++) { level_info_t *info = &wadlevelinfos[i]; - MapData *map = P_OpenMapData(info->mapname, true); + MapData *map = P_OpenMapData(info->MapName, true); if (map != NULL) { - Printf("%s: '%s' (%s)\n", info->mapname, info->LookupLevelName().GetChars(), + Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), Wads.GetWadName(Wads.GetLumpFile(map->lumpnum))); delete map; } diff --git a/src/g_level.h b/src/g_level.h index cd1e9e60d..ebd52c8f6 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -83,7 +83,7 @@ struct FMapInfoParser void ParseLumpOrTextureName(FString &name); void ParseCluster(); - void ParseNextMap(char *mapname); + void ParseNextMap(FString &mapname); level_info_t *ParseMapHeader(level_info_t &defaultinfo); void ParseMapDefinition(level_info_t &leveldef); void ParseGameInfo(); @@ -269,9 +269,9 @@ struct level_info_t { int levelnum; - char mapname[9]; - char nextmap[11]; - char secretmap[11]; + FString MapName; + FString NextMap; + FString NextSecretMap; FString PName; FString SkyPic1; FString SkyPic2; @@ -313,7 +313,7 @@ struct level_info_t // Redirection: If any player is carrying the specified item, then // you go to the RedirectMap instead of this one. FName RedirectType; - char RedirectMap[9]; + FString RedirectMapName; FString EnterPic; FString ExitPic; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index c261e2f33..874a659c6 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -71,9 +71,10 @@ extern TMap HexenMusic; static int FindWadLevelInfo (const char *name) { for (unsigned int i = 0; i < wadlevelinfos.Size(); i++) - if (!strnicmp (name, wadlevelinfos[i].mapname, 8)) + { + if (!wadlevelinfos[i].MapName.CompareNoCase(name)) return i; - + } return -1; } @@ -144,7 +145,7 @@ bool CheckWarpTransMap (FString &mapname, bool substitute) level_info_t *lev = FindLevelByWarpTrans (atoi (&mapname[4])); if (lev != NULL) { - mapname = lev->mapname; + mapname = lev->MapName; return true; } else if (substitute) @@ -224,12 +225,12 @@ void P_RemoveDefereds (void) void level_info_t::Reset() { - mapname[0] = 0; + MapName = ""; MapBackground = ""; levelnum = 0; PName = ""; - nextmap[0] = 0; - secretmap[0] = 0; + NextMap = ""; + NextSecretMap = ""; SkyPic1 = SkyPic2 = "-NOFLAT-"; cluster = 0; partime = 0; @@ -262,7 +263,7 @@ void level_info_t::Reset() compatmask = compatmask2 = 0; Translator = ""; RedirectType = 0; - RedirectMap[0] = 0; + RedirectMapName = ""; EnterPic = ""; ExitPic = ""; InterMusic = ""; @@ -299,17 +300,17 @@ FString level_info_t::LookupLevelName() char checkstring[32]; // Strip out the header from the localized string - if (mapname[0] == 'E' && mapname[2] == 'M') + if (MapName.Len() > 3 && MapName[0] == 'E' && MapName[2] == 'M') { - mysnprintf (checkstring, countof(checkstring), "%s: ", mapname); + mysnprintf (checkstring, countof(checkstring), "%s: ", MapName); } - else if (mapname[0] == 'M' && mapname[1] == 'A' && mapname[2] == 'P') + else if (MapName.Len() > 3 && MapName[0] == 'M' && MapName[1] == 'A' && MapName[2] == 'P') { - mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(mapname + 3)); + mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(&MapName[3])); } - else if (mapname[0] == 'L' && mapname[1] == 'E' && mapname[2] == 'V' && mapname[3] == 'E' && mapname[4] == 'L') + else if (MapName.Len() > 5 && MapName[0] == 'L' && MapName[1] == 'E' && MapName[2] == 'V' && MapName[3] == 'E' && MapName[4] == 'L') { - mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(mapname + 5)); + mysnprintf (checkstring, countof(checkstring), "%d: ", atoi(&MapName[5])); } thename = strstr (lookedup, checkstring); if (thename == NULL) @@ -372,9 +373,9 @@ level_info_t *level_info_t::CheckLevelRedirect () if (playeringame[i] && players[i].mo->FindInventory (type)) { // check for actual presence of the map. - if (P_CheckMapData(RedirectMap)) + if (P_CheckMapData(RedirectMapName)) { - return FindLevelInfo(RedirectMap); + return FindLevelInfo(RedirectMapName); } break; } @@ -391,7 +392,7 @@ level_info_t *level_info_t::CheckLevelRedirect () bool level_info_t::isValid() { - return mapname[0] != 0 || this == &TheDefaultLevelInfo; + return MapName.Len() != 0 || this == &TheDefaultLevelInfo; } //========================================================================== @@ -764,29 +765,27 @@ void FMapInfoParser::ParseCluster() // //========================================================================== -void FMapInfoParser::ParseNextMap(char *mapname) +void FMapInfoParser::ParseNextMap(FString &mapname) { if (sc.CheckNumber()) { if (HexenHack) { - mysnprintf (mapname, 9, "&wt@%02d", sc.Number); + mapname.Format("&wt@%02d", sc.Number); } else { - mysnprintf (mapname, 9, "MAP%02d", sc.Number); + mapname.Format("MAP%02d", sc.Number); } } else { - *mapname = 0; sc.MustGetString(); - strncpy (mapname, sc.String, 8); - mapname[8] = 0; + mapname = sc.String; FName seq = CheckEndSequence(); if (seq != NAME_None) { - mysnprintf(mapname, 11, "enDSeQ%04x", int(seq)); + mapname.Format("enDSeQ%04x", int(seq)); } } } @@ -807,19 +806,19 @@ DEFINE_MAP_OPTION(levelnum, true) DEFINE_MAP_OPTION(next, true) { parse.ParseAssign(); - parse.ParseNextMap(info->nextmap); + parse.ParseNextMap(info->NextMap); } DEFINE_MAP_OPTION(secretnext, true) { parse.ParseAssign(); - parse.ParseNextMap(info->secretmap); + parse.ParseNextMap(info->NextSecretMap); } DEFINE_MAP_OPTION(secret, true) // Just an alias for secretnext, for Vavoom compatibility { parse.ParseAssign(); - parse.ParseNextMap(info->secretmap); + parse.ParseNextMap(info->NextSecretMap); } DEFINE_MAP_OPTION(cluster, true) @@ -1072,7 +1071,7 @@ DEFINE_MAP_OPTION(redirect, true) parse.sc.MustGetString(); info->RedirectType = parse.sc.String; parse.ParseComma(); - parse.ParseLumpOrTextureName(info->RedirectMap); + parse.ParseNextMap(info->RedirectMapName); } DEFINE_MAP_OPTION(sndseq, true) @@ -1522,8 +1521,8 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) } - uppercopy (levelinfo->mapname, mapname); - levelinfo->mapname[8] = 0; + levelinfo->MapName = mapname; + levelinfo->MapName.ToUpper(); sc.MustGetString (); if (sc.String[0] == '$') { @@ -1543,7 +1542,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) // Set up levelnum now so that you can use Teleport_NewMap specials // to teleport to maps with standard names without needing a levelnum. - levelinfo->levelnum = GetDefaultLevelNum(levelinfo->mapname); + levelinfo->levelnum = GetDefaultLevelNum(levelinfo->MapName); // Does this map have a song defined via SNDINFO's $map command? // Set that as this map's default music if it does. diff --git a/src/p_acs.cpp b/src/p_acs.cpp index bd8c53edf..9469da06e 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -8942,7 +8942,7 @@ static void addDefered (level_info_t *i, acsdefered_t::EType type, int script, c def->playernum = -1; } i->defered = def; - DPrintf ("%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->mapname); + DPrintf ("%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->MapName.GetChars()); } } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index d94a16fbb..7cb5ca7e6 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -863,7 +863,7 @@ FUNC(LS_Teleport_NewMap) if (info && CheckIfExitIsGood (it, info)) { - G_ChangeLevel(info->mapname, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); + G_ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); return true; } } @@ -1648,7 +1648,7 @@ FUNC(LS_ACS_Execute) } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->mapname; + mapname = info->MapName; } else { @@ -1671,7 +1671,7 @@ FUNC(LS_ACS_ExecuteAlways) } else if ((info = FindLevelByNum(arg1)) != NULL) { - mapname = info->mapname; + mapname = info->MapName; } else { @@ -1718,7 +1718,7 @@ FUNC(LS_ACS_Suspend) if (arg1 == 0) P_SuspendScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) - P_SuspendScript (arg0, info->mapname); + P_SuspendScript (arg0, info->MapName); return true; } @@ -1731,7 +1731,7 @@ FUNC(LS_ACS_Terminate) if (arg1 == 0) P_TerminateScript (arg0, level.MapName); else if ((info = FindLevelByNum (arg1)) ) - P_TerminateScript (arg0, info->mapname); + P_TerminateScript (arg0, info->MapName); return true; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 4f1329f85..c2aa47faa 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -272,11 +272,12 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) FString fmt; int lump_wad; int lump_map; - int lump_name; + int lump_name = -1; // Check for both *.wad and *.map in order to load Build maps // as well. The higher one will take precedence. - lump_name = Wads.CheckNumForName(mapname); + // Names with more than 8 characters will only be checked as .wad and .map. + if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); lump_wad = Wads.CheckNumForFullName(fmt); fmt.Format("maps/%s.map", mapname); diff --git a/src/zstring.cpp b/src/zstring.cpp index dc171f398..14d19f46f 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -349,7 +349,14 @@ FString &FString::AppendCStrPart (const char *tail, size_t tailLen) return *this; } -void FString::Truncate (long newlen) +FString &FString::CopyCStrPart(const char *tail, size_t tailLen) +{ + ReallocBuffer(tailLen); + StrCopy(Chars, tail, tailLen); + return *this; +} + +void FString::Truncate(long newlen) { if (newlen >= 0 && newlen < (long)Len()) { diff --git a/src/zstring.h b/src/zstring.h index 874417a09..1736f3421 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -167,6 +167,7 @@ public: FString &operator += (char tail); FString &operator += (const FName &name) { return *this += name.GetChars(); } FString &AppendCStrPart (const char *tail, size_t tailLen); + FString &CopyCStrPart(const char *tail, size_t tailLen); FString &operator << (const FString &tail) { return *this += tail; } FString &operator << (const char *tail) { return *this += tail; } From fdfcb728a970113548f6aafb425fc77eacecdfad Mon Sep 17 00:00:00 2001 From: Shawn Walker Date: Tue, 13 May 2014 22:50:39 -0700 Subject: [PATCH 213/247] - make it easier to spot patch definition errors in console log --- src/textures/multipatchtexture.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 124add5db..d72391341 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -47,6 +47,7 @@ #include "colormatcher.h" #include "v_palette.h" #include "v_video.h" +#include "v_text.h" #include "m_fixed.h" #include "textures/textures.h" #include "r_data/colormaps.h" @@ -275,7 +276,7 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; if (Parts[i].Texture == NULL) { - Printf ("Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); + Printf (TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); NumParts--; i--; } @@ -1018,7 +1019,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i } if (part.Texture == NULL) { - if (!silent) Printf("Unknown patch '%s' in texture '%s'\n", sc.String, Name); + if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); } sc.MustGetStringName(","); sc.MustGetNumber(); From 8c052818b7acdc428a590a0c0cd8922d5c7aeb94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 10:27:40 +0200 Subject: [PATCH 214/247] - fixed: long texture name lookup did not work with TEXMAN_TryAny. --- src/textures/texturemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 0af15d7af..9ff67803d 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -220,8 +220,8 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF { if (firsttype == FTexture::TEX_Null) return FTextureID(0); if (firsttype == FTexture::TEX_FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0); + return FTextureID(firstfound); } - return FTextureID(firstfound); } From 47a9dab56d74fe021f454bccec91e57715f6db94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 12:16:33 +0200 Subject: [PATCH 215/247] - allow setting sector planes' plane equations directly from UDMF. --- specs/udmf_zdoom.txt | 14 +++++++++- src/namedef.h | 9 ++++++ src/p_udmf.cpp | 65 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index d7face672..1128b2e55 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -37,7 +37,7 @@ In addition to the base specification ZDoom recognizes the following lumps between the TEXTMAP and ENDMAP lumps: BEHAVIOR = contains compiled ACS code - DIALOGUE = contains compiled Strife conversation scripts. + DIALOGUE = contains compiled Strife or USDF conversation scripts. ZNODES = Nodes (must be stored as extended GL nodes. Compression is allowed but deprecated for portability reasons.) BLOCKMAP = blockmap. It is recommended not to include this lump in UDMF maps. @@ -166,6 +166,14 @@ Note: All fields default to false unless mentioned otherwise. yscaleceiling = ; // Y texture scale of ceiling texture, Default = 1.0. rotationfloor = ; // Rotation of floor texture in degrees, Default = 0.0. rotationceiling = ; // Rotation of ceiling texture in degrees, Default = 0.0. + ceilingplane_a = ; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. + ceilingplane_b = ; // 'heightceiling' will still be used to calculate texture alignment. + ceilingplane_c = ; // The plane equation will only be used if all 4 values are given. + ceilingplane_d = ; + floorplane_a = ; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. + floorplane_b = ; // 'heightfloor' will still be used to calculate texture alignment. + floorplane_c = ; // The plane equation will only be used if all 4 values are given. + floorplane_d = ; lightfloor = ; // The floor's light level. Default is 0. lightceiling = ; // The ceiling's light level. Default is 0. lightfloorabsolute = ; // true = 'lightfloor' is an absolute value. Default is @@ -355,6 +363,10 @@ Added waterzone sector property. 1.22 12.04.2014 Added transparent line property (to be folded back to core UDMF standard), and health, score, renderstyle, fillcolor, alpha, scale, scalex, scaley, pitch and roll thing properties. +1.24 14.05.2014 +Added plane equations for sector slopes. (Please read carefully to ensure proper use!) +Changed language describing the DIALOGUE lump to mention USDF as an option. + =============================================================================== EOF =============================================================================== diff --git a/src/namedef.h b/src/namedef.h index ba6de104d..a4c8da638 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -488,6 +488,15 @@ xx(blockhitscan) xx(Renderstyle) +xx(ceilingplane_a) +xx(ceilingplane_b) +xx(ceilingplane_c) +xx(ceilingplane_d) +xx(floorplane_a) +xx(floorplane_b) +xx(floorplane_c) +xx(floorplane_d) + // USDF keywords xx(Amount) xx(Text) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 2fa968502..0c380160d 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1245,6 +1245,7 @@ public: int lightcolor = -1; int fadecolor = -1; int desaturation = -1; + int fplaneflags = 0, cplaneflags = 0; memset(sec, 0, sizeof(*sec)); sec->lightlevel = 160; @@ -1446,6 +1447,48 @@ public: Flag(sec->MoreFlags, SECF_UNDERWATER, key); break; + case NAME_floorplane_a: + fplaneflags |= 1; + sec->floorplane.a = CheckFixed(key); + break; + + case NAME_floorplane_b: + fplaneflags |= 2; + sec->floorplane.b = CheckFixed(key); + break; + + case NAME_floorplane_c: + fplaneflags |= 4; + sec->floorplane.c = CheckFixed(key); + sec->floorplane.ic = FixedDiv(FRACUNIT, sec->floorplane.c); + break; + + case NAME_floorplane_d: + fplaneflags |= 8; + sec->floorplane.d = CheckFixed(key); + break; + + case NAME_ceilingplane_a: + cplaneflags |= 1; + sec->ceilingplane.a = CheckFixed(key); + break; + + case NAME_ceilingplane_b: + cplaneflags |= 2; + sec->ceilingplane.b = CheckFixed(key); + break; + + case NAME_ceilingplane_c: + cplaneflags |= 4; + sec->ceilingplane.c = CheckFixed(key); + sec->ceilingplane.ic = FixedDiv(FRACUNIT, sec->ceilingplane.c); + break; + + case NAME_ceilingplane_d: + cplaneflags |= 8; + sec->ceilingplane.d = CheckFixed(key); + break; + default: break; } @@ -1457,12 +1500,22 @@ public: } sec->secretsector = !!(sec->special&SECRET_MASK); - sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor); - sec->floorplane.c = FRACUNIT; - sec->floorplane.ic = FRACUNIT; - sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling); - sec->ceilingplane.c = -FRACUNIT; - sec->ceilingplane.ic = -FRACUNIT; + + // Reset the planes to their defaults if not all of the plane equation's parameters were found. + if (fplaneflags != 15) + { + sec->floorplane.a = sec->floorplane.b = 0; + sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor); + sec->floorplane.c = FRACUNIT; + sec->floorplane.ic = FRACUNIT; + } + if (cplaneflags != 15) + { + sec->ceilingplane.a = sec->ceilingplane.b = 0; + sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling); + sec->ceilingplane.c = -FRACUNIT; + sec->ceilingplane.ic = -FRACUNIT; + } if (lightcolor == -1 && fadecolor == -1 && desaturation == -1) { From 388f09f786d5ab3927d3bb6d76895b043a18bdb6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 12:54:03 +0200 Subject: [PATCH 216/247] - fixed: In Heretic corpses do not get crunched to gibs, they just get their size reduced to 0. Handled by a new gameinfo flag. This also gets set for Chex quest which has the gib sprite replaced by something different. Using a Crush state will override this global flag. --- src/gi.cpp | 1 + src/gi.h | 1 + src/p_mobj.cpp | 10 ++++++++++ wadsrc/static/mapinfo/chex.txt | 1 + wadsrc/static/mapinfo/heretic.txt | 1 + 5 files changed, 14 insertions(+) diff --git a/src/gi.cpp b/src/gi.cpp index 8ab935854..4e64dd425 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -323,6 +323,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic") GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis") GAMEINFOKEY_BOOL(swapmenu, "swapmenu") + GAMEINFOKEY_BOOL(dontcrunchcorpses, "dontcrunchcorpses") GAMEINFOKEY_BOOL(intermissioncounter, "intermissioncounter") GAMEINFOKEY_BOOL(nightmarefast, "nightmarefast") GAMEINFOKEY_COLOR(dimcolor, "dimcolor") diff --git a/src/gi.h b/src/gi.h index a1a03b2de..bbfbe73ff 100644 --- a/src/gi.h +++ b/src/gi.h @@ -113,6 +113,7 @@ struct gameinfo_t bool intermissioncounter; bool nightmarefast; bool swapmenu; + bool dontcrunchcorpses; TArray creditPages; TArray finalePages; TArray infoPages; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c6a7fd35c..72679ef71 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1010,6 +1010,16 @@ bool AActor::Grind(bool items) if ((flags & MF_CORPSE) && !(flags3 & MF3_DONTGIB) && (health <= 0)) { FState * state = FindState(NAME_Crush); + + // In Heretic and Chex Quest we don't change the actor's sprite, just its size. + if (state == NULL && gameinfo.dontcrunchcorpses) + { + flags &= ~MF_SOLID; + flags3 |= MF3_DONTGIB; + height = radius = 0; + return false; + } + bool isgeneric = false; // ZDoom behavior differs from standard as crushed corpses cannot be raised. // The reason for the change was originally because of a problem with players, diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index edc5b4f29..e29eeeb4d 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -40,6 +40,7 @@ gameinfo definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 + dontcrunchcorpses = 1 endoom = "ENDOOM" player5start = 4001 drawreadthis = true diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index 196e81c50..d372466f5 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -56,6 +56,7 @@ gameinfo nightmarefast = true pausesign = "PAUSED" gibfactor = 0.5 + dontcrunchcorpses = true cursorpic = "herecurs" textscreenx = 20 textscreeny = 5 From 51ed68dc7243cf00c285526a8009a2fa2d4c427d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 13:02:04 +0200 Subject: [PATCH 217/247] - forgot to save this... --- wadsrc/static/mapinfo/chex.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index e29eeeb4d..1edaf9256 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -40,7 +40,7 @@ gameinfo definventorymaxamount = 25 defaultrespawntime = 12 defaultdropstyle = 1 - dontcrunchcorpses = 1 + dontcrunchcorpses = true endoom = "ENDOOM" player5start = 4001 drawreadthis = true From 85fb8c4326a0f5ca010f0495275d04ccd4d8860e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 13:04:47 +0200 Subject: [PATCH 218/247] - fixed: _M_X64 macro was misnamed _M_IX64. --- src/nodebuild.h | 2 +- src/x86.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nodebuild.h b/src/nodebuild.h index 81c7b1345..ce68c4682 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -347,7 +347,7 @@ inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const #ifdef DISABLE_SSE return ClassifyLine2 (node, v1, v2, sidev); #else -#if defined(__SSE2__) || defined(_M_IX64) +#if defined(__SSE2__) || defined(_M_X64) // If compiling with SSE2 support everywhere, just use the SSE2 version. return ClassifyLineSSE2 (node, v1, v2, sidev); #elif defined(_MSC_VER) && _MSC_VER < 1300 diff --git a/src/x86.cpp b/src/x86.cpp index ec36aae93..89d88333d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -299,7 +299,7 @@ void DoBlending_SSE2(const PalEntry *from, PalEntry *to, int count, int r, int g } #endif -#if defined(__amd64__) || defined(_M_IX64) +#if defined(__amd64__) || defined(_M_X64) long long color; blending256 = _mm_set_epi64x(0x10001000100ll, 0x10001000100ll); From 802a47876602251c9c7ec6bd7f63da21c3d24165 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 14:03:15 +0200 Subject: [PATCH 219/247] - Heretic doesn't really need dontcrunchcorpses because there was already some alternative handling for that situation. --- wadsrc/static/mapinfo/heretic.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index d372466f5..196e81c50 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -56,7 +56,6 @@ gameinfo nightmarefast = true pausesign = "PAUSED" gibfactor = 0.5 - dontcrunchcorpses = true cursorpic = "herecurs" textscreenx = 20 textscreeny = 5 From 2944e4f6ae8601ca567baafbe9b6e80daae138a3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 14:08:14 +0200 Subject: [PATCH 220/247] - fixed some Linux issues with recent changes. --- src/sdl/i_main.cpp | 6 +----- src/textures/texturemanager.cpp | 2 +- src/wi_stuff.cpp | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 1736305d8..db6979330 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -172,11 +172,7 @@ static int DoomSpecificInfo (char *buffer, char *end) } else { - char name[9]; - - strncpy (name, level.mapname, 8); - name[8] = 0; - p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", name); + p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName); if (!viewactive) { diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 9ff67803d..aa9ef706b 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -233,7 +233,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF { FTexture *const NO_TEXTURE = (FTexture*)-1; int lump = Wads.CheckNumForFullName(name); - if (lump != NULL) + if (lump >= 0) { FTexture *tex = Wads.GetLinkedTexture(lump); if (tex == NO_TEXTURE) return FTextureID(-1); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 0cf5e7b77..982668566 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -314,7 +314,7 @@ static bool IsExMy(const char * name) void WI_LoadBackground(bool isenterpic) { - const char *lumpname; + const char *lumpname = NULL; char buffer[10]; in_anim_t an; lnode_t pt; From adcdc11360c9672105c9c8fabb989247d1f2cd40 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 15:44:05 +0200 Subject: [PATCH 221/247] - GCC compile fix. --- src/sdl/i_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index db6979330..3c721ae51 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -172,7 +172,7 @@ static int DoomSpecificInfo (char *buffer, char *end) } else { - p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName); + p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars()); if (!viewactive) { From e3cd144af9692192accb853691a6ccf4a6d5ae2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 14 May 2014 17:27:22 +0200 Subject: [PATCH 222/247] - one last GCC compile problem. --- src/g_mapinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 874a659c6..7203fdb51 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -302,7 +302,7 @@ FString level_info_t::LookupLevelName() // Strip out the header from the localized string if (MapName.Len() > 3 && MapName[0] == 'E' && MapName[2] == 'M') { - mysnprintf (checkstring, countof(checkstring), "%s: ", MapName); + mysnprintf (checkstring, countof(checkstring), "%s: ", MapName.GetChars()); } else if (MapName.Len() > 3 && MapName[0] == 'M' && MapName[1] == 'A' && MapName[2] == 'P') { From bf6a193e5bc3806131e0f7b9493274003c142bed Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 15 May 2014 20:29:36 +0200 Subject: [PATCH 223/247] - fixed: The episode parser was still truncating its map names to 8 characters. --- src/g_level.h | 2 +- src/g_mapinfo.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/g_level.h b/src/g_level.h index ebd52c8f6..0cd366798 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -79,7 +79,7 @@ struct FMapInfoParser bool ParseLookupName(FString &dest); void ParseMusic(FString &name, int &order); - void ParseLumpOrTextureName(char *name); + //void ParseLumpOrTextureName(char *name); void ParseLumpOrTextureName(FString &name); void ParseCluster(); diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 7203fdb51..b7aa77e1c 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -622,12 +622,14 @@ bool FMapInfoParser::ParseLookupName(FString &dest) // //========================================================================== +/* void FMapInfoParser::ParseLumpOrTextureName(char *name) { sc.MustGetString(); uppercopy(name, sc.String); name[8]=0; } +*/ void FMapInfoParser::ParseLumpOrTextureName(FString &name) { @@ -1572,7 +1574,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) void FMapInfoParser::ParseEpisodeInfo () { unsigned int i; - char map[9]; + FString map; FString pic; FString name; bool remove = false; @@ -1583,15 +1585,14 @@ void FMapInfoParser::ParseEpisodeInfo () // Get map name sc.MustGetString (); - uppercopy (map, sc.String); - map[8] = 0; + map = sc.String; if (sc.CheckString ("teaser")) { sc.MustGetString (); if (gameinfo.flags & GI_SHAREWARE) { - uppercopy (map, sc.String); + map = sc.String; } } From 25f4af734fa73006fa48c6463ce09c9b84aa1368 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 May 2014 10:56:23 +0200 Subject: [PATCH 224/247] - fixed: ACS's check...Texture functions must use the same search flags as the texture initialization code in p_setup.cpp and p_udmf.cpp. It also should not create textures that don't exist yet. We are only doing a comparison so it's not relevant if the texture exists or not. --- src/p_acs.cpp | 4 +++- src/textures/texturemanager.cpp | 1 + src/textures/textures.h | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 9469da06e..981870a36 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3944,7 +3944,9 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b { return 0; } - FTexture *tex = TexMan.FindTexture(FBehavior::StaticLookupString(string)); + FTexture *tex = TexMan.FindTexture(FBehavior::StaticLookupString(string), FTexture::TEX_Flat, + FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_DontCreate); + if (tex == NULL) { // If the texture we want to check against doesn't exist, then // they're obviously not the same. diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index aa9ef706b..6fb963e42 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -238,6 +238,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF FTexture *tex = Wads.GetLinkedTexture(lump); if (tex == NO_TEXTURE) return FTextureID(-1); if (tex != NULL) return tex->id; + if (flags & TEXMAN_DontCreate) return FTextureID(-1); // we only want to check, there's no need to create a texture if we don't have one yet. tex = FTexture::CreateTexture("", lump, FTexture::TEX_Override); if (tex != NULL) { diff --git a/src/textures/textures.h b/src/textures/textures.h index 8c41ee844..15c9bce5c 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -363,7 +363,8 @@ public: TEXMAN_Overridable = 2, TEXMAN_ReturnFirst = 4, TEXMAN_AllowSkins = 8, - TEXMAN_ShortNameOnly = 16 + TEXMAN_ShortNameOnly = 16, + TEXMAN_DontCreate = 32 }; FTextureID CheckForTexture (const char *name, int usetype, BITFIELD flags=TEXMAN_TryAny); From d3dcc04666f8179b16ef4fd8624ac68ec441f3b8 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sat, 17 May 2014 00:35:27 +1200 Subject: [PATCH 225/247] Fix nettic run-out at end of demo playback --- src/d_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index a2e0798b2..f1b476108 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1054,7 +1054,7 @@ void NetUpdate (void) if (demoplayback) { - nettics[0] = (maketic / ticdup); + resendto[0] = nettics[0] = (maketic / ticdup); return; // Don't touch netcmd data while playing a demo, as it'll already exist. } From e92032e8ffe73da1ce3fe61c94fc2f7e447a09d7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 May 2014 22:48:37 +0200 Subject: [PATCH 226/247] - fixed: The map setup code was still truncating texture names in several places. --- src/doomdata.h | 8 ++++++++ src/p_setup.cpp | 50 ++++++++++++++++++++++++------------------------- src/p_udmf.cpp | 26 ++++++++++++------------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/doomdata.h b/src/doomdata.h index 9cedf8cdc..215c2a263 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -85,6 +85,14 @@ struct mapsidedef_t short sector; // Front sector, towards viewer. }; +struct intmapsidedef_t +{ + FString toptexture; + FString bottomtexture; + FString midtexture; +}; + + // A LineDef, as used for editing, and as input to the BSP builder. struct maplinedef_t { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index c2aa47faa..a6462f31c 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -577,13 +577,11 @@ void MapData::GetChecksum(BYTE cksum[16]) // //=========================================================================== -static void SetTexture (side_t *side, int position, const char *name8, FMissingTextureTracker &track) +static void SetTexture (side_t *side, int position, const char *name, FMissingTextureTracker &track) { static const char *positionnames[] = { "top", "middle", "bottom" }; static const char *sidenames[] = { "first", "second" }; - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; + FTextureID texture = TexMan.CheckForTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -619,12 +617,17 @@ static void SetTexture (side_t *side, int position, const char *name8, FMissingT // //=========================================================================== -void SetTexture (sector_t *sector, int index, int position, const char *name8, FMissingTextureTracker &track) +void SetTexture (sector_t *sector, int index, int position, const char *name, FMissingTextureTracker &track, bool truncate) { static const char *positionnames[] = { "floor", "ceiling" }; - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; + char name8[9]; + if (truncate) + { + strncpy(name8, name, 8); + name8[8] = 0; + name = name8; + } + FTextureID texture = TexMan.CheckForTexture (name, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -674,11 +677,8 @@ static void SummarizeMissingTextures(const FMissingTextureTracker &missing) // //=========================================================================== -static void SetTexture (side_t *side, int position, DWORD *blend, char *name8) +static void SetTexture (side_t *side, int position, DWORD *blend, const char *name) { - char name[9]; - strncpy (name, name8, 8); - name[8] = 0; FTextureID texture; if ((*blend = R_ColormapNumForName (name)) == 0) { @@ -705,12 +705,9 @@ static void SetTexture (side_t *side, int position, DWORD *blend, char *name8) side->SetTexture(position, texture); } -static void SetTextureNoErr (side_t *side, int position, DWORD *color, char *name8, bool *validcolor, bool isFog) +static void SetTextureNoErr (side_t *side, int position, DWORD *color, const char *name, bool *validcolor, bool isFog) { - char name[9]; FTextureID texture; - strncpy (name, name8, 8); - name[8] = 0; *validcolor = false; texture = TexMan.CheckForTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny); @@ -1515,8 +1512,8 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->ceilingplane.d = ss->GetPlaneTexZ(sector_t::ceiling); ss->ceilingplane.c = -FRACUNIT; ss->ceilingplane.ic = -FRACUNIT; - SetTexture(ss, i, sector_t::floor, ms->floorpic, missingtex); - SetTexture(ss, i, sector_t::ceiling, ms->ceilingpic, missingtex); + SetTexture(ss, i, sector_t::floor, ms->floorpic, missingtex, true); + SetTexture(ss, i, sector_t::ceiling, ms->ceilingpic, missingtex, true); ss->lightlevel = LittleShort(ms->lightlevel); if (map->HasBehavior) ss->special = LittleShort(ms->special); @@ -2473,11 +2470,8 @@ int P_DetermineTranslucency (int lumpnum) return newcolor.r; } -void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex) +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &missingtex) { - char name[9]; - name[8] = 0; - switch (special) { case Transfer_Heights: // variable colormap via 242 linedef @@ -2503,7 +2497,6 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapside SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture, &foggood, true); SetTextureNoErr (sd, side_t::top, &color, msd->toptexture, &colorgood, false); - strncpy (name, msd->midtexture, 8); SetTexture(sd, side_t::mid, msd->midtexture, missingtex); if (colorgood | foggood) @@ -2534,8 +2527,7 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapside case Sector_Set3DFloor: if (msd->toptexture[0]=='#') { - strncpy (name, msd->toptexture, 8); - sd->SetTexture(side_t::top, FNullTextureID() +(-strtol(name+1, NULL, 10))); // store the alpha as a negative texture index + sd->SetTexture(side_t::top, FNullTextureID() +(-strtol(&msd->toptexture[1], NULL, 10))); // store the alpha as a negative texture index // This will be sorted out by the 3D-floor code later. } else @@ -2629,7 +2621,13 @@ void P_LoadSideDefs2 (MapData *map, FMissingTextureTracker &missingtex) { sd->sector = sec = §ors[LittleShort(msd->sector)]; } - P_ProcessSideTextures(!map->HasBehavior, sd, sec, msd, + + intmapsidedef_t imsd; + imsd.toptexture.CopyCStrPart(msd->toptexture, 8); + imsd.midtexture.CopyCStrPart(msd->midtexture, 8); + imsd.bottomtexture.CopyCStrPart(msd->bottomtexture, 8); + + P_ProcessSideTextures(!map->HasBehavior, sd, sec, &imsd, sidetemp[i].a.special, sidetemp[i].a.tag, &sidetemp[i].a.alpha, missingtex); } delete[] msdf; diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 0c380160d..19dfdf08c 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -118,8 +118,8 @@ enum // namespace for each game }; -void SetTexture (sector_t *sector, int index, int position, const char *name8, FMissingTextureTracker &); -void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &); +void SetTexture (sector_t *sector, int index, int position, const char *name, FMissingTextureTracker &, bool truncate); +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, intmapsidedef_t *msd, int special, int tag, short *alpha, FMissingTextureTracker &); void P_AdjustLine (line_t *ld); void P_FinishLoadingLineDef(line_t *ld, int alpha); void SpawnMapThing(int index, FMapThing *mt, int position); @@ -394,7 +394,7 @@ class UDMFParser : public UDMFParserBase TArray ParsedLines; TArray ParsedSides; - TArray ParsedSideTextures; + TArray ParsedSideTextures; TArray ParsedSectors; TArray ParsedVertices; TArray ParsedVertexDatas; @@ -1089,14 +1089,14 @@ public: // //=========================================================================== - void ParseSidedef(side_t *sd, mapsidedef_t *sdt, int index) + void ParseSidedef(side_t *sd, intmapsidedef_t *sdt, int index) { fixed_t texofs[2]={0,0}; memset(sd, 0, sizeof(*sd)); - strncpy(sdt->bottomtexture, "-", 8); - strncpy(sdt->toptexture, "-", 8); - strncpy(sdt->midtexture, "-", 8); + sdt->bottomtexture = "-"; + sdt->toptexture = "-"; + sdt->midtexture = "-"; sd->SetTextureXScale(FRACUNIT); sd->SetTextureYScale(FRACUNIT); @@ -1115,15 +1115,15 @@ public: continue; case NAME_Texturetop: - strncpy(sdt->toptexture, CheckString(key), 8); + sdt->toptexture = CheckString(key); continue; case NAME_Texturebottom: - strncpy(sdt->bottomtexture, CheckString(key), 8); + sdt->bottomtexture = CheckString(key); continue; case NAME_Texturemiddle: - strncpy(sdt->midtexture, CheckString(key), 8); + sdt->midtexture = CheckString(key); continue; case NAME_Sector: @@ -1287,11 +1287,11 @@ public: continue; case NAME_Texturefloor: - SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex); + SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex, false); continue; case NAME_Textureceiling: - SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex); + SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex, false); continue; case NAME_Lightlevel: @@ -1799,7 +1799,7 @@ public: else if (sc.Compare("sidedef")) { side_t si; - mapsidedef_t st; + intmapsidedef_t st; ParseSidedef(&si, &st, ParsedSides.Size()); ParsedSides.Push(si); ParsedSideTextures.Push(st); From ff7913ace8156cd8bfda3533f3afcb77897d1646 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 May 2014 09:46:58 +0200 Subject: [PATCH 227/247] - fixed: When a level gets loaded the renderer's sky variables need to be set. --- src/g_level.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/g_level.cpp b/src/g_level.cpp index 74a92edb5..8c97a399c 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1410,6 +1410,8 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) } if (arc.IsLoading()) { + sky1texture = level.skytexture1; + sky2texture = level.skytexture2; R_InitSkyMap(); } From 26b1abe3dab611001b49ce717853b0accd8c5516 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 18 May 2014 18:37:34 +1200 Subject: [PATCH 228/247] Fix netgame arbitration with long map lump names --- src/d_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index f1b476108..1600d9102 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1385,7 +1385,7 @@ bool DoArbitrate (void *userdata) stream = &netbuffer[4]; s = ReadString (&stream); - startmap = FString(s, 8); + startmap = FString(s, strlen(s)); delete[] s; rngseed = ReadLong (&stream); C_ReadCVars (&stream); From cfef89486740cdfca0682dcc60caf2b3cdb5bbc9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 May 2014 09:41:13 +0200 Subject: [PATCH 229/247] This can be done better... --- src/d_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 1600d9102..60a2b61c4 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1385,7 +1385,7 @@ bool DoArbitrate (void *userdata) stream = &netbuffer[4]; s = ReadString (&stream); - startmap = FString(s, strlen(s)); + startmap = s; delete[] s; rngseed = ReadLong (&stream); C_ReadCVars (&stream); From 4acc04ce68f37a1340de81f0d754fe8951fa47ca Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 18 May 2014 10:05:35 +0200 Subject: [PATCH 230/247] - don't truncate map names stored in demos. --- src/g_game.cpp | 28 +++++++++++++++++----------- src/version.h | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 045b331bf..65fa5733d 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2302,11 +2302,10 @@ void G_BeginRecording (const char *startmap) WriteWord (DEMOGAMEVERSION, &demo_p); // Write ZDoom version *demo_p++ = 2; // Write minimum version needed to use this demo. *demo_p++ = 3; // (Useful?) - for (i = 0; i < 8; i++) // Write name of map demo was recorded on. - { - *demo_p++ = startmap[i]; - } - WriteLong (rngseed, &demo_p); // Write RNG seed + + strcpy((char*)demo_p, startmap); // Write name of map demo was recorded on. + demo_p += strlen(startmap) + 1; + WriteLong(rngseed, &demo_p); // Write RNG seed *demo_p++ = consoleplayer; FinishChunk (&demo_p); @@ -2385,7 +2384,7 @@ CCMD (timedemo) // [RH] Process all the information in a FORM ZDEM // until a BODY chunk is entered. -bool G_ProcessIFFDemo (char *mapname) +bool G_ProcessIFFDemo (FString &mapname) { bool headerHit = false; bool bodyHit = false; @@ -2441,9 +2440,16 @@ bool G_ProcessIFFDemo (char *mapname) Printf ("Demo requires a newer version of ZDoom!\n"); return true; } - memcpy (mapname, demo_p, 8); // Read map name - mapname[8] = 0; - demo_p += 8; + if (demover >= 0x21a) + { + mapname = (char*)demo_p; + demo_p += mapname.Len() + 1; + } + else + { + mapname = FString((char*)demo_p, 8); + demo_p += 8; + } rngseed = ReadLong (&demo_p); // Only reset the RNG if this demo is not in conjunction with a savegame. if (mapname[0] != 0) @@ -2525,7 +2531,7 @@ bool G_ProcessIFFDemo (char *mapname) void G_DoPlayDemo (void) { - char mapname[9]; + FString mapname; int demolump; gameaction = ga_nothing; @@ -2578,7 +2584,7 @@ void G_DoPlayDemo (void) // don't spend a lot of time in loadlevel precache = false; demonew = true; - if (mapname[0] != 0) + if (mapname.Len() != 0) { G_InitNew (mapname, false); } diff --git a/src/version.h b/src/version.h index 1b4457655..8e853057a 100644 --- a/src/version.h +++ b/src/version.h @@ -61,7 +61,7 @@ const char *GetVersionString(); // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x219 +#define DEMOGAMEVERSION 0x21A // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. From 59885b856deb34fe11928a3ca1277ad8315af028 Mon Sep 17 00:00:00 2001 From: Shawn Walker Date: Sun, 18 May 2014 15:38:46 -0700 Subject: [PATCH 231/247] - remove texture name length limits for udmf maps --- src/p_doors.cpp | 2 +- src/r_data/sprites.cpp | 6 +- src/textures/buildtexture.cpp | 2 +- src/textures/canvastexture.cpp | 3 +- src/textures/imgztexture.cpp | 1 - src/textures/multipatchtexture.cpp | 2666 ++++++++++++++-------------- src/textures/texture.cpp | 12 +- src/textures/texturemanager.cpp | 46 +- src/textures/textures.h | 6 +- src/textures/tgatexture.cpp | 1 - src/w_wad.cpp | 12 +- src/w_wad.h | 3 +- 12 files changed, 1383 insertions(+), 1377 deletions(-) diff --git a/src/p_doors.cpp b/src/p_doors.cpp index b530f688d..7c6952d7f 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -297,7 +297,7 @@ void DDoor::DoorSound(bool raise, DSeqNode *curseq) const continue; FTexture *tex = TexMan[line->sidedef[0]->GetTexture(side_t::top)]; - texname = tex? tex->Name : NULL; + texname = tex ? tex->Name.GetChars() : NULL; if (texname != NULL && texname[0] == 'D' && texname[1] == 'O' && texname[2] == 'R') { switch (texname[3]) diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 012abb2f6..604619403 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -249,6 +249,8 @@ static void R_InstallSprite (int num) // letter/number appended. // The rotation character can be 0 to signify no rotations. // +#define TEX_DWNAME(tex) MAKE_ID(tex->Name[0], tex->Name[1], tex->Name[2], tex->Name[3]) + void R_InitSpriteDefs () { struct Hasher @@ -272,7 +274,7 @@ void R_InitSpriteDefs () FTexture *tex = TexMan.ByIndex(i); if (tex->UseType == FTexture::TEX_Sprite && strlen(tex->Name) >= 6) { - size_t bucket = tex->dwName % smax; + size_t bucket = TEX_DWNAME(tex) % smax; hashes[i].Next = hashes[bucket].Head; hashes[bucket].Head = i; } @@ -352,7 +354,7 @@ void R_InitSpriteDefs () while (hash != -1) { FTexture *tex = TexMan[hash]; - if (tex->dwName == intname) + if (TEX_DWNAME(tex) == intname) { bool res = R_InstallSpriteLump (FTextureID(hash), tex->Name[4] - 'A', tex->Name[5], false); diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index e534ca9c8..ee5f66fab 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -78,7 +78,7 @@ FBuildTexture::FBuildTexture (int tilenum, const BYTE *pixels, int width, int he LeftOffset = left; TopOffset = top; CalcBitSize (); - mysnprintf (Name, countof(Name), "BTIL%04d", tilenum); + Name.Format("BTIL%04d", tilenum); UseType = TEX_Build; } diff --git a/src/textures/canvastexture.cpp b/src/textures/canvastexture.cpp index a6e1918df..8bfd1946b 100644 --- a/src/textures/canvastexture.cpp +++ b/src/textures/canvastexture.cpp @@ -41,8 +41,7 @@ FCanvasTexture::FCanvasTexture (const char *name, int width, int height) { - strncpy (Name, name, 8); - Name[8] = 0; + Name = name; Width = width; Height = height; LeftOffset = TopOffset = 0; diff --git a/src/textures/imgztexture.cpp b/src/textures/imgztexture.cpp index 36f954b95..153880d67 100644 --- a/src/textures/imgztexture.cpp +++ b/src/textures/imgztexture.cpp @@ -106,7 +106,6 @@ FIMGZTexture::FIMGZTexture (int lumpnum, WORD w, WORD h, SWORD l, SWORD t) : FTexture(NULL, lumpnum), Pixels(0), Spans(0) { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; Width = w; Height = h; LeftOffset = l; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index d72391341..c51f30168 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -1,1332 +1,1336 @@ -/* -** multipatchtexture.cpp -** Texture class for standard Doom multipatch textures -** -**--------------------------------------------------------------------------- -** Copyright 2004-2006 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. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -#include "doomtype.h" -#include "files.h" -#include "w_wad.h" -#include "i_system.h" -#include "gi.h" -#include "st_start.h" -#include "sc_man.h" -#include "templates.h" -#include "r_data/r_translate.h" -#include "bitmap.h" -#include "colormatcher.h" -#include "v_palette.h" -#include "v_video.h" -#include "v_text.h" -#include "m_fixed.h" -#include "textures/textures.h" -#include "r_data/colormaps.h" - -// On the Alpha, accessing the shorts directly if they aren't aligned on a -// 4-byte boundary causes unaligned access warnings. Why it does this at -// all and only while initing the textures is beyond me. - -#ifdef ALPHA -#define SAFESHORT(s) ((short)(((BYTE *)&(s))[0] + ((BYTE *)&(s))[1] * 256)) -#else -#define SAFESHORT(s) LittleShort(s) -#endif - - - -//-------------------------------------------------------------------------- -// -// Data structures for the TEXTUREx lumps -// -//-------------------------------------------------------------------------- - -// -// Each texture is composed of one or more patches, with patches being lumps -// stored in the WAD. The lumps are referenced by number, and patched into -// the rectangular texture space using origin and possibly other attributes. -// -struct mappatch_t -{ - SWORD originx; - SWORD originy; - SWORD patch; - SWORD stepdir; - SWORD colormap; -}; - -// -// A wall texture is a list of patches which are to be combined in a -// predefined order. -// -struct maptexture_t -{ +/* +** multipatchtexture.cpp +** Texture class for standard Doom multipatch textures +** +**--------------------------------------------------------------------------- +** Copyright 2004-2006 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include "doomtype.h" +#include "files.h" +#include "w_wad.h" +#include "i_system.h" +#include "gi.h" +#include "st_start.h" +#include "sc_man.h" +#include "templates.h" +#include "r_data/r_translate.h" +#include "bitmap.h" +#include "colormatcher.h" +#include "v_palette.h" +#include "v_video.h" +#include "v_text.h" +#include "m_fixed.h" +#include "textures/textures.h" +#include "r_data/colormaps.h" + +// On the Alpha, accessing the shorts directly if they aren't aligned on a +// 4-byte boundary causes unaligned access warnings. Why it does this at +// all and only while initing the textures is beyond me. + +#ifdef ALPHA +#define SAFESHORT(s) ((short)(((BYTE *)&(s))[0] + ((BYTE *)&(s))[1] * 256)) +#else +#define SAFESHORT(s) LittleShort(s) +#endif + + + +//-------------------------------------------------------------------------- +// +// Data structures for the TEXTUREx lumps +// +//-------------------------------------------------------------------------- + +// +// Each texture is composed of one or more patches, with patches being lumps +// stored in the WAD. The lumps are referenced by number, and patched into +// the rectangular texture space using origin and possibly other attributes. +// +struct mappatch_t +{ + SWORD originx; + SWORD originy; + SWORD patch; + SWORD stepdir; + SWORD colormap; +}; + +// +// A wall texture is a list of patches which are to be combined in a +// predefined order. +// +struct maptexture_t +{ BYTE name[8]; - WORD Flags; // [RH] Was unused - BYTE ScaleX; // [RH] Scaling (8 is normal) - BYTE ScaleY; // [RH] Same as above - SWORD width; - SWORD height; - BYTE columndirectory[4]; // OBSOLETE - SWORD patchcount; - mappatch_t patches[1]; -}; - -#define MAPTEXF_WORLDPANNING 0x8000 - -// Strife uses versions of the above structures that remove all unused fields - -struct strifemappatch_t -{ - SWORD originx; - SWORD originy; - SWORD patch; -}; - -// -// A wall texture is a list of patches which are to be combined in a -// predefined order. -// -struct strifemaptexture_t -{ - BYTE name[8]; - WORD Flags; // [RH] Was unused - BYTE ScaleX; // [RH] Scaling (8 is normal) - BYTE ScaleY; // [RH] Same as above - SWORD width; - SWORD height; - SWORD patchcount; - strifemappatch_t patches[1]; -}; - - -//========================================================================== -// -// In-memory representation of a single PNAMES lump entry -// -//========================================================================== - -struct FPatchLookup -{ - char Name[9]; - FTexture *Texture; -}; - - -//========================================================================== -// -// A texture defined in a TEXTURE1 or TEXTURE2 lump -// -//========================================================================== - -class FMultiPatchTexture : public FTexture -{ -public: - FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); - FMultiPatchTexture (FScanner &sc, int usetype); - ~FMultiPatchTexture (); - - const BYTE *GetColumn (unsigned int column, const Span **spans_out); - const BYTE *GetPixels (); - FTextureFormat GetFormat(); - bool UseBasePalette() ; - void Unload (); - virtual void SetFrontSkyLayer (); - - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - int GetSourceLump() { return DefinitionLump; } - FTexture *GetRedirect(bool wantwarped); - FTexture *GetRawTexture(); - -protected: - BYTE *Pixels; - Span **Spans; - int DefinitionLump; - - struct TexPart - { - SWORD OriginX, OriginY; - BYTE Rotate; - BYTE op; - FRemapTable *Translation; - PalEntry Blend; - FTexture *Texture; - fixed_t Alpha; - - TexPart(); - }; - - int NumParts; - TexPart *Parts; - bool bRedirect:1; - bool bTranslucentPatches:1; - - void MakeTexture (); - -private: - void CheckForHacks (); - void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); -}; - -//========================================================================== -// -// FMultiPatchTexture :: FMultiPatchTexture -// -//========================================================================== - -FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) -{ - union - { - const maptexture_t *d; - const strifemaptexture_t *s; - } - mtexture; - - union - { - const mappatch_t *d; - const strifemappatch_t *s; - } - mpatch; - - int i; - - mtexture.d = (const maptexture_t *)texdef; - bMultiPatch = true; - - if (strife) - { - NumParts = SAFESHORT(mtexture.s->patchcount); - } - else - { - NumParts = SAFESHORT(mtexture.d->patchcount); - } - - if (NumParts < 0) - { - I_FatalError ("Bad texture directory"); - } - - UseType = FTexture::TEX_Wall; - Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; - Width = SAFESHORT(mtexture.d->width); - Height = SAFESHORT(mtexture.d->height); - strncpy (Name, (const char *)mtexture.d->name, 8); - Name[8] = 0; - CalcBitSize (); - - xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; - yScale = mtexture.d->ScaleY ? mtexture.d->ScaleY*(FRACUNIT/8) : FRACUNIT; - - if (mtexture.d->Flags & MAPTEXF_WORLDPANNING) - { - bWorldPanning = true; - } - - if (strife) - { - mpatch.s = &mtexture.s->patches[0]; - } - else - { - mpatch.d = &mtexture.d->patches[0]; - } - - for (i = 0; i < NumParts; ++i) - { - if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) - { - I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", - maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); - } - Parts[i].OriginX = LittleShort(mpatch.d->originx); - Parts[i].OriginY = LittleShort(mpatch.d->originy); - Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; - if (Parts[i].Texture == NULL) - { - Printf (TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); - NumParts--; - i--; - } - else - { - Parts[i].Texture->bKeepAround = true; - } - if (strife) - mpatch.s++; - else - mpatch.d++; - } - if (NumParts == 0) - { - Printf ("Texture %s is left without any patches\n", Name); - } - - CheckForHacks (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height) - { - bRedirect = true; - } - } - DefinitionLump = deflumpnum; -} - -//========================================================================== -// -// FMultiPatchTexture :: ~FMultiPatchTexture -// -//========================================================================== - -FMultiPatchTexture::~FMultiPatchTexture () -{ - Unload (); - if (Parts != NULL) - { - for(int i=0; iSetFrontSkyLayer (); - } - bNoRemap0 = true; -} - -//========================================================================== -// -// FMultiPatchTexture :: Unload -// -//========================================================================== - -void FMultiPatchTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } -} - -//========================================================================== -// -// FMultiPatchTexture :: GetPixels -// -//========================================================================== - -const BYTE *FMultiPatchTexture::GetPixels () -{ - if (bRedirect) - { - return Parts->Texture->GetPixels (); - } - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetColumn -// -//========================================================================== - -const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (bRedirect) - { - return Parts->Texture->GetColumn (column, spans_out); - } - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - if (Spans == NULL) - { - Spans = CreateSpans (Pixels); - } - *spans_out = Spans[column]; - } - return Pixels + column*Height; -} - - -//========================================================================== -// -// GetBlendMap -// -//========================================================================== - -BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork) -{ - - switch (blend.a==0 ? int(blend) : -1) - { - case BLEND_ICEMAP: - return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap; - - default: - if (blend >= BLEND_SPECIALCOLORMAP1 && blend < BLEND_SPECIALCOLORMAP1 + SpecialColormaps.Size()) - { - return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap; - } - else if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31) - { - return DesaturateColormap[blend - BLEND_DESATURATE1]; - } - else - { - blendwork[0]=0; - if (blend.a == 255) - { - for(int i=1;i<256;i++) - { - int rr = (blend.r * GPalette.BaseColors[i].r) / 255; - int gg = (blend.g * GPalette.BaseColors[i].g) / 255; - int bb = (blend.b * GPalette.BaseColors[i].b) / 255; - - blendwork[i] = ColorMatcher.Pick(rr, gg, bb); - } - return blendwork; - } - else if (blend.a != 0) - { - for(int i=1;i<256;i++) - { - int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255; - int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255; - int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255; - - blendwork[i] = ColorMatcher.Pick(rr, gg, bb); - } - return blendwork; - } - } - } - return NULL; -} - -//========================================================================== -// -// FMultiPatchTexture :: MakeTexture -// -//========================================================================== - -void FMultiPatchTexture::MakeTexture () -{ - // Add a little extra space at the end if the texture's height is not - // a power of 2, in case somebody accidentally makes it repeat vertically. - int numpix = Width * Height + (1 << HeightBits) - Height; - BYTE blendwork[256]; - bool hasTranslucent = false; - - Pixels = new BYTE[numpix]; - memset (Pixels, 0, numpix); - - for (int i = 0; i < NumParts; ++i) - { - if (Parts[i].op != OP_COPY) - { - hasTranslucent = true; - } - } - - if (!hasTranslucent) - { - for (int i = 0; i < NumParts; ++i) - { - if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - - BYTE *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; - { - if (Parts[i].Blend != 0) - { - trans = GetBlendMap(Parts[i].Blend, blendwork); - } - Parts[i].Texture->CopyToBlock (Pixels, Width, Height, - Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); - } - } - } - else - { - // In case there are translucent patches let's do the composition in - // True color to keep as much precision as possible before downconverting to the palette. - BYTE *buffer = new BYTE[Width * Height * 4]; - memset(buffer, 0, Width * Height * 4); - FillBuffer(buffer, Width * 4, Height, TEX_RGB); - for(int y = 0; y < Height; y++) - { - BYTE *in = buffer + Width * y * 4; - BYTE *out = Pixels + y; - for (int x = 0; x < Width; x++) - { - if (*out == 0 && in[3] != 0) - { - *out = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3]; - } - out += Height; - in += 4; - } - } - delete [] buffer; - } -} - -//=========================================================================== -// -// FMultipatchTexture::CopyTrueColorPixels -// -// Preserves the palettes of each individual patch -// -//=========================================================================== - -int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) -{ - int retv = -1; - - if (bRedirect) - { // Redirect straight to the real texture's routine. - return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf); - } - - if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE))) - { // We are doing some sort of fancy stuff to the destination bitmap, so composite to - // a temporary bitmap, and copy that. - FBitmap tbmp; - if (tbmp.Create(Width, Height)) - { - retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0)); - bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height, - 4, tbmp.GetPitch(), rotate, CF_BGRA, inf); - } - return retv; - } - - // When compositing a multipatch texture with multipatch parts, - // drawing must be restricted to the actual area which is covered by this texture. - FClipRect saved_cr = bmp->GetClipRect(); - bmp->IntersectClipRect(x, y, Width, Height); - - if (inf != NULL && inf->op == OP_OVERWRITE) - { - bmp->Zero(); - } - - for(int i = 0; i < NumParts; i++) - { - int ret = -1; - FCopyInfo info; - - if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - - memset (&info, 0, sizeof(info)); - info.alpha = Parts[i].Alpha; - info.invalpha = FRACUNIT - info.alpha; - info.op = ECopyOp(Parts[i].op); - PalEntry b = Parts[i].Blend; - if (b.a == 0 && b != BLEND_NONE) - { - info.blend = EBlend(b.d); - } - else if (b.a != 0) - { - if (b.a == 255) - { - info.blendcolor[0] = b.r * FRACUNIT / 255; - info.blendcolor[1] = b.g * FRACUNIT / 255; - info.blendcolor[2] = b.b * FRACUNIT / 255; - info.blend = BLEND_MODULATE; - } - else - { - fixed_t blendalpha = b.a * FRACUNIT / 255; - info.blendcolor[0] = b.r * blendalpha; - info.blendcolor[1] = b.g * blendalpha; - info.blendcolor[2] = b.b * blendalpha; - info.blendcolor[3] = FRACUNIT - blendalpha; - info.blend = BLEND_OVERLAY; - } - } - - if (Parts[i].Translation != NULL) - { // Using a translation forces downconversion to the base palette - ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); - } - else - { - ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); - } - - if (ret > retv) retv = ret; - } - // Restore previous clipping rectangle. - bmp->SetClipRect(saved_cr); - return retv; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetFormat -// -// only returns 'paletted' if all patches use the base palette. -// -//========================================================================== - -FTextureFormat FMultiPatchTexture::GetFormat() -{ - if (bComplex) return TEX_RGB; - if (NumParts == 1) return Parts[0].Texture->GetFormat(); - return UseBasePalette() ? TEX_Pal : TEX_RGB; -} - - -//=========================================================================== -// -// FMultipatchTexture::UseBasePalette -// -// returns true if all patches in the texture use the unmodified base -// palette. -// -//=========================================================================== - -bool FMultiPatchTexture::UseBasePalette() -{ - if (bComplex) return false; - for(int i=0;iUseBasePalette()) return false; - } - return true; -} - -//========================================================================== -// -// FMultiPatchTexture :: CheckForHacks -// -//========================================================================== - -void FMultiPatchTexture::CheckForHacks () -{ - if (NumParts <= 0) - { - return; - } - - // Heretic sky textures are marked as only 128 pixels tall, - // even though they are really 200 pixels tall. - if (gameinfo.gametype == GAME_Heretic && - Name[0] == 'S' && - Name[1] == 'K' && - Name[2] == 'Y' && - Name[4] == 0 && - Name[3] >= '1' && - Name[3] <= '3' && - Height == 128) - { - Height = 200; - HeightBits = 8; - return; - } - - // The Doom E1 sky has its patch's y offset at -8 instead of 0. - if (gameinfo.gametype == GAME_Doom && - !(gameinfo.flags & GI_MAPxx) && - NumParts == 1 && - Height == 128 && - Parts->OriginY == -8 && - Name[0] == 'S' && - Name[1] == 'K' && - Name[2] == 'Y' && - Name[3] == '1' && - Name[4] == 0) - { - Parts->OriginY = 0; - return; - } - - // BIGDOOR7 in Doom also has patches at y offset -4 instead of 0. - if (gameinfo.gametype == GAME_Doom && - !(gameinfo.flags & GI_MAPxx) && - NumParts == 2 && - Height == 128 && - Parts[0].OriginY == -4 && - Parts[1].OriginY == -4 && - Name[0] == 'B' && - Name[1] == 'I' && - Name[2] == 'G' && - Name[3] == 'D' && - Name[4] == 'O' && - Name[5] == 'O' && - Name[6] == 'R' && - Name[7] == '7') - { - Parts[0].OriginY = 0; - Parts[1].OriginY = 0; - return; - } - - // [RH] Some wads (I forget which!) have single-patch textures 256 - // pixels tall that have patch lengths recorded as 0. I can't think of - // any good reason for them to do this, and since I didn't make note - // of which wad made me hack in support for them, the hack is gone - // because I've added support for DeePsea's true tall patches. - // - // Okay, I found a wad with crap patches: Pleiades.wad's sky patches almost - // fit this description and are a big mess, but they're not single patch! - if (Height == 256) - { - int i; - - // All patches must be at the top of the texture for this fix - for (i = 0; i < NumParts; ++i) - { - if (Parts[i].OriginY != 0) - { - break; - } - } - - if (i == NumParts) - { - for (i = 0; i < NumParts; ++i) - { - Parts[i].Texture->HackHack(256); - } - } - } -} - -//========================================================================== -// -// FMultiPatchTexture :: GetRedirect -// -//========================================================================== - -FTexture *FMultiPatchTexture::GetRedirect(bool wantwarped) -{ - return bRedirect ? Parts->Texture : this; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetRawTexture -// -// Doom ignored all compositing of mid-sided textures on two-sided lines. -// Since these textures had to be single-patch in Doom, that essentially -// means it ignores their Y offsets. -// -// If this texture is composed of only one patch, return that patch. -// Otherwise, return this texture, since Doom wouldn't have been able to -// draw it anyway. -// -//========================================================================== - -FTexture *FMultiPatchTexture::GetRawTexture() -{ - return NumParts == 1 ? Parts->Texture : this; -} - -//========================================================================== -// -// FMultiPatchTexture :: TexPart :: TexPart -// -//========================================================================== - -FMultiPatchTexture::TexPart::TexPart() -{ - OriginX = OriginY = 0; - Rotate = 0; - Texture = NULL; - Translation = NULL; - Blend = 0; - Alpha = FRACUNIT; - op = OP_COPY; -} - -//========================================================================== -// -// FTextureManager :: AddTexturesLump -// -//========================================================================== - -void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1) -{ - FPatchLookup *patchlookup; - int i; - DWORD numpatches; - - if (firstdup == 0) - { - firstdup = (int)Textures.Size(); - } - - { - FWadLump pnames = Wads.OpenLumpNum (patcheslump); - - pnames >> numpatches; - - // Check whether the amount of names reported is correct. - if ((signed)numpatches < 0) - { - Printf("Corrupt PNAMES lump found (negative amount of entries reported)"); - return; - } - - // Check whether the amount of names reported is correct. - int lumplength = Wads.LumpLength(patcheslump); - if (numpatches > DWORD((lumplength-4)/8)) - { - Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", - numpatches, lumplength, (lumplength-4)/8); - // Truncate but continue reading. Who knows how many such lumps exist? - numpatches = (lumplength-4)/8; - } - - // Catalog the patches these textures use so we know which - // textures they represent. - patchlookup = (FPatchLookup *)alloca (numpatches * sizeof(*patchlookup)); - - for (DWORD i = 0; i < numpatches; ++i) - { - pnames.Read (patchlookup[i].Name, 8); - patchlookup[i].Name[8] = 0; - FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); - if (j.isValid()) - { - patchlookup[i].Texture = Textures[j.GetIndex()].Texture; - } - else - { - // Shareware Doom has the same PNAMES lump as the registered - // Doom, so printing warnings for patches that don't really - // exist isn't such a good idea. - //Printf ("Patch %s not found.\n", patchlookup[i].Name); - patchlookup[i].Texture = NULL; - } - } - } - - bool isStrife = false; - const DWORD *maptex, *directory; - DWORD maxoff; - int numtextures; - DWORD offset = 0; // Shut up, GCC! - - maptex = (const DWORD *)lumpdata; - numtextures = LittleLong(*maptex); - maxoff = lumpsize; - - if (maxoff < DWORD(numtextures+1)*4) - { - Printf ("Texture directory is too short"); - return; - } - - // Scan the texture lump to decide if it contains Doom or Strife textures - for (i = 0, directory = maptex+1; i < numtextures; ++i) - { - offset = LittleLong(directory[i]); - if (offset > maxoff) - { - Printf ("Bad texture directory"); - return; - } - - maptexture_t *tex = (maptexture_t *)((BYTE *)maptex + offset); - - // There is bizzarely a Doom editing tool that writes to the - // first two elements of columndirectory, so I can't check those. - if (SAFESHORT(tex->patchcount) < 0 || - tex->columndirectory[2] != 0 || - tex->columndirectory[3] != 0) - { - isStrife = true; - break; - } - } - - - // Textures defined earlier in the lump take precedence over those defined later, - // but later TEXTUREx lumps take precedence over earlier ones. - for (i = 1, directory = maptex; i <= numtextures; ++i) - { - if (i == 1 && texture1) - { - // The very first texture is just a dummy. Copy its dimensions to texture 0. - // It still needs to be created in case someone uses it by name. - offset = LittleLong(directory[1]); - const maptexture_t *tex = (const maptexture_t *)((const BYTE *)maptex + offset); - FDummyTexture *tex0 = static_cast(Textures[0].Texture); - tex0->SetSize (SAFESHORT(tex->width), SAFESHORT(tex->height)); - } - - offset = LittleLong(directory[i]); - if (offset > maxoff) - { - Printf ("Bad texture directory"); - return; - } - - // If this texture was defined already in this lump, skip it - // This could cause problems with animations that use the same name for intermediate - // textures. Should I be worried? - int j; - for (j = (int)Textures.Size() - 1; j >= firstdup; --j) - { - if (strnicmp (Textures[j].Texture->Name, (const char *)maptex + offset, 8) == 0) - break; - } - if (j + 1 == firstdup) - { - FMultiPatchTexture *tex = new FMultiPatchTexture ((const BYTE *)maptex + offset, patchlookup, numpatches, isStrife, deflumpnum); - if (i == 1 && texture1) - { - tex->UseType = FTexture::TEX_FirstDefined; - } - TexMan.AddTexture (tex); - StartScreen->Progress(); - } - } -} - - -//========================================================================== -// -// FTextureManager :: AddTexturesLumps -// -//========================================================================== - -void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) -{ - int firstdup = (int)Textures.Size(); - - if (lump1 >= 0) - { - FMemLump texdir = Wads.ReadLump (lump1); - AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump1), lump1, patcheslump, firstdup, true); - } - if (lump2 >= 0) - { - FMemLump texdir = Wads.ReadLump (lump2); - AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump2), lump2, patcheslump, firstdup, false); - } -} - - -//========================================================================== -// -// -// -//========================================================================== - -void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) -{ - FString patchname; - sc.MustGetString(); - - FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); - int Mirror = 0; - - if (!texno.isValid()) - { - if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) - { - int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); - if (lumpnum >= 0) - { - part.Texture = FTexture::CreateTexture(lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - } - else - { - part.Texture = TexMan[texno]; - bComplex |= part.Texture->bComplex; - } - if (part.Texture == NULL) - { - if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); - } - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.OriginX = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.OriginY = sc.Number; - - if (sc.CheckString("{")) - { - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (sc.Compare("flipx")) - { - Mirror |= 1; - } - else if (sc.Compare("flipy")) - { - Mirror |= 2; - } - else if (sc.Compare("rotate")) - { - sc.MustGetNumber(); - sc.Number = (((sc.Number + 90)%360)-90); - if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90) - { - sc.ScriptError("Rotation must be a multiple of 90 degrees."); - } - part.Rotate = (sc.Number / 90) & 3; - } - else if (sc.Compare("Translation")) - { - int match; - - bComplex = true; - if (part.Translation != NULL) delete part.Translation; - part.Translation = NULL; - part.Blend = 0; - static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL }; - sc.MustGetString(); - - match = sc.MatchString(maps); - if (match >= 0) - { - part.Blend = BLEND_SPECIALCOLORMAP1 + match; - } - else if (sc.Compare("ICE")) - { - part.Blend = BLEND_ICEMAP; - } - else if (sc.Compare("DESATURATE")) - { - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30); - } - else - { - sc.UnGet(); - part.Translation = new FRemapTable; - part.Translation->MakeIdentity(); - do - { - sc.MustGetString(); - part.Translation->AddToTranslation(sc.String); - } - while (sc.CheckString(",")); - } - - } - else if (sc.Compare("Colormap")) - { - float r1,g1,b1; - float r2,g2,b2; - - sc.MustGetFloat(); - r1 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - g1 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - b1 = (float)sc.Float; - if (!sc.CheckString(",")) - { - part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1); - } - else - { - sc.MustGetFloat(); - r2 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - g2 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - b2 = (float)sc.Float; - part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2); - } - } - else if (sc.Compare("Blend")) - { - bComplex = true; - if (part.Translation != NULL) delete part.Translation; - part.Translation = NULL; - part.Blend = 0; - - if (!sc.CheckNumber()) - { - sc.MustGetString(); - part.Blend = V_GetColor(NULL, sc.String); - } - else - { - int r,g,b; - - r = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - g = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - b = sc.Number; - sc.MustGetStringName(","); - part.Blend = MAKERGB(r, g, b); - } - // Blend.a may never be 0 here. - if (sc.CheckString(",")) - { - sc.MustGetFloat(); - if (sc.Float > 0.f) - part.Blend.a = clamp(int(sc.Float*255), 1, 254); - else - part.Blend = 0; - } - else part.Blend.a = 255; - } - else if (sc.Compare("alpha")) - { - sc.MustGetFloat(); - part.Alpha = clamp(FLOAT2FIXED(sc.Float), 0, FRACUNIT); - // bComplex is not set because it is only needed when the style is not OP_COPY. - } - else if (sc.Compare("style")) - { - static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL }; - sc.MustGetString(); - part.op = sc.MustMatchString(styles); - bComplex |= (part.op != OP_COPY); - bTranslucentPatches = bComplex; - } - else if (sc.Compare("useoffsets")) - { - if (part.Texture != NULL) - { - part.OriginX -= part.Texture->LeftOffset; - part.OriginY -= part.Texture->TopOffset; - } - } - } - } - if (Mirror & 2) - { - part.Rotate = (part.Rotate + 2) & 3; - Mirror ^= 1; - } - if (Mirror & 1) - { - part.Rotate |= 4; - } -} - -//========================================================================== -// -// Constructor for text based multipatch definitions -// -//========================================================================== - -FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) -{ - TArray parts; - bool bSilent = false; - - bMultiPatch = true; - sc.SetCMode(true); - sc.MustGetString(); - const char* textureName = NULL; - if (sc.Compare("optional")) - { - bSilent = true; - sc.MustGetString(); - if (sc.Compare(",")) - { - // this is not right. Apparently a texture named 'optional' is being defined right now... - sc.UnGet(); - textureName = "optional"; - bSilent = false; - } - } - uppercopy(Name, !textureName ? sc.String : textureName); - Name[8] = 0; - sc.MustGetStringName(","); - sc.MustGetNumber(); - Width = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - Height = sc.Number; - UseType = usetype; - - if (sc.CheckString("{")) - { - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (sc.Compare("XScale")) - { - sc.MustGetFloat(); - xScale = FLOAT2FIXED(sc.Float); - if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); - } - else if (sc.Compare("YScale")) - { - sc.MustGetFloat(); - yScale = FLOAT2FIXED(sc.Float); - if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); - } - else if (sc.Compare("WorldPanning")) - { - bWorldPanning = true; - } - else if (sc.Compare("NullTexture")) - { - UseType = FTexture::TEX_Null; - } - else if (sc.Compare("NoDecals")) - { - bNoDecals = true; - } - else if (sc.Compare("Patch")) - { - TexPart part; - ParsePatch(sc, part, bSilent, TEX_WallPatch); - if (part.Texture != NULL) parts.Push(part); - part.Texture = NULL; - part.Translation = NULL; - } - else if (sc.Compare("Graphic")) - { - TexPart part; - ParsePatch(sc, part, bSilent, TEX_MiscPatch); - if (part.Texture != NULL) parts.Push(part); - part.Texture = NULL; - part.Translation = NULL; - } - else if (sc.Compare("Offset")) - { - sc.MustGetNumber(); - LeftOffset = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - TopOffset = sc.Number; - } - else - { - sc.ScriptError("Unknown texture property '%s'", sc.String); - } - } - - NumParts = parts.Size(); - Parts = new TexPart[NumParts]; - memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); - - //CalcBitSize (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height && - Parts->Rotate == 0 && - !bComplex) - { - bRedirect = true; - } - } - } - - if (Width <= 0 || Height <= 0) - { - UseType = FTexture::TEX_Null; - Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); - Width = Height = 1; - } - CalcBitSize (); - - - sc.SetCMode(false); -} - - - -void FTextureManager::ParseXTexture(FScanner &sc, int usetype) -{ - FTexture *tex = new FMultiPatchTexture(sc, usetype); - TexMan.AddTexture (tex); -} + WORD Flags; // [RH] Was unused + BYTE ScaleX; // [RH] Scaling (8 is normal) + BYTE ScaleY; // [RH] Same as above + SWORD width; + SWORD height; + BYTE columndirectory[4]; // OBSOLETE + SWORD patchcount; + mappatch_t patches[1]; +}; + +#define MAPTEXF_WORLDPANNING 0x8000 + +// Strife uses versions of the above structures that remove all unused fields + +struct strifemappatch_t +{ + SWORD originx; + SWORD originy; + SWORD patch; +}; + +// +// A wall texture is a list of patches which are to be combined in a +// predefined order. +// +struct strifemaptexture_t +{ + BYTE name[8]; + WORD Flags; // [RH] Was unused + BYTE ScaleX; // [RH] Scaling (8 is normal) + BYTE ScaleY; // [RH] Same as above + SWORD width; + SWORD height; + SWORD patchcount; + strifemappatch_t patches[1]; +}; + + +//========================================================================== +// +// In-memory representation of a single PNAMES lump entry +// +//========================================================================== + +struct FPatchLookup +{ + FString Name; + FTexture *Texture; +}; + + +//========================================================================== +// +// A texture defined in a TEXTURE1 or TEXTURE2 lump +// +//========================================================================== + +class FMultiPatchTexture : public FTexture +{ +public: + FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); + FMultiPatchTexture (FScanner &sc, int usetype); + ~FMultiPatchTexture (); + + const BYTE *GetColumn (unsigned int column, const Span **spans_out); + const BYTE *GetPixels (); + FTextureFormat GetFormat(); + bool UseBasePalette() ; + void Unload (); + virtual void SetFrontSkyLayer (); + + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); + int GetSourceLump() { return DefinitionLump; } + FTexture *GetRedirect(bool wantwarped); + FTexture *GetRawTexture(); + +protected: + BYTE *Pixels; + Span **Spans; + int DefinitionLump; + + struct TexPart + { + SWORD OriginX, OriginY; + BYTE Rotate; + BYTE op; + FRemapTable *Translation; + PalEntry Blend; + FTexture *Texture; + fixed_t Alpha; + + TexPart(); + }; + + int NumParts; + TexPart *Parts; + bool bRedirect:1; + bool bTranslucentPatches:1; + + void MakeTexture (); + +private: + void CheckForHacks (); + void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); +}; + +//========================================================================== +// +// FMultiPatchTexture :: FMultiPatchTexture +// +//========================================================================== + +FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +{ + union + { + const maptexture_t *d; + const strifemaptexture_t *s; + } + mtexture; + + union + { + const mappatch_t *d; + const strifemappatch_t *s; + } + mpatch; + + int i; + + mtexture.d = (const maptexture_t *)texdef; + bMultiPatch = true; + + if (strife) + { + NumParts = SAFESHORT(mtexture.s->patchcount); + } + else + { + NumParts = SAFESHORT(mtexture.d->patchcount); + } + + if (NumParts < 0) + { + I_FatalError ("Bad texture directory"); + } + + UseType = FTexture::TEX_Wall; + Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; + Width = SAFESHORT(mtexture.d->width); + Height = SAFESHORT(mtexture.d->height); + Name = (char *)mtexture.d->name; + CalcBitSize (); + + xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; + yScale = mtexture.d->ScaleY ? mtexture.d->ScaleY*(FRACUNIT/8) : FRACUNIT; + + if (mtexture.d->Flags & MAPTEXF_WORLDPANNING) + { + bWorldPanning = true; + } + + if (strife) + { + mpatch.s = &mtexture.s->patches[0]; + } + else + { + mpatch.d = &mtexture.d->patches[0]; + } + + for (i = 0; i < NumParts; ++i) + { + if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) + { + I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", + maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); + } + Parts[i].OriginX = LittleShort(mpatch.d->originx); + Parts[i].OriginY = LittleShort(mpatch.d->originy); + Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; + if (Parts[i].Texture == NULL) + { + Printf (TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); + NumParts--; + i--; + } + else + { + Parts[i].Texture->bKeepAround = true; + } + if (strife) + mpatch.s++; + else + mpatch.d++; + } + if (NumParts == 0) + { + Printf ("Texture %s is left without any patches\n", Name); + } + + CheckForHacks (); + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height) + { + bRedirect = true; + } + } + DefinitionLump = deflumpnum; +} + +//========================================================================== +// +// FMultiPatchTexture :: ~FMultiPatchTexture +// +//========================================================================== + +FMultiPatchTexture::~FMultiPatchTexture () +{ + Unload (); + if (Parts != NULL) + { + for(int i=0; iSetFrontSkyLayer (); + } + bNoRemap0 = true; +} + +//========================================================================== +// +// FMultiPatchTexture :: Unload +// +//========================================================================== + +void FMultiPatchTexture::Unload () +{ + if (Pixels != NULL) + { + delete[] Pixels; + Pixels = NULL; + } +} + +//========================================================================== +// +// FMultiPatchTexture :: GetPixels +// +//========================================================================== + +const BYTE *FMultiPatchTexture::GetPixels () +{ + if (bRedirect) + { + return Parts->Texture->GetPixels (); + } + if (Pixels == NULL) + { + MakeTexture (); + } + return Pixels; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetColumn +// +//========================================================================== + +const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out) +{ + if (bRedirect) + { + return Parts->Texture->GetColumn (column, spans_out); + } + if (Pixels == NULL) + { + MakeTexture (); + } + if ((unsigned)column >= (unsigned)Width) + { + if (WidthMask + 1 == Width) + { + column &= WidthMask; + } + else + { + column %= Width; + } + } + if (spans_out != NULL) + { + if (Spans == NULL) + { + Spans = CreateSpans (Pixels); + } + *spans_out = Spans[column]; + } + return Pixels + column*Height; +} + + +//========================================================================== +// +// GetBlendMap +// +//========================================================================== + +BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork) +{ + + switch (blend.a==0 ? int(blend) : -1) + { + case BLEND_ICEMAP: + return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap; + + default: + if (blend >= BLEND_SPECIALCOLORMAP1 && blend < BLEND_SPECIALCOLORMAP1 + SpecialColormaps.Size()) + { + return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap; + } + else if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31) + { + return DesaturateColormap[blend - BLEND_DESATURATE1]; + } + else + { + blendwork[0]=0; + if (blend.a == 255) + { + for(int i=1;i<256;i++) + { + int rr = (blend.r * GPalette.BaseColors[i].r) / 255; + int gg = (blend.g * GPalette.BaseColors[i].g) / 255; + int bb = (blend.b * GPalette.BaseColors[i].b) / 255; + + blendwork[i] = ColorMatcher.Pick(rr, gg, bb); + } + return blendwork; + } + else if (blend.a != 0) + { + for(int i=1;i<256;i++) + { + int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255; + int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255; + int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255; + + blendwork[i] = ColorMatcher.Pick(rr, gg, bb); + } + return blendwork; + } + } + } + return NULL; +} + +//========================================================================== +// +// FMultiPatchTexture :: MakeTexture +// +//========================================================================== + +void FMultiPatchTexture::MakeTexture () +{ + // Add a little extra space at the end if the texture's height is not + // a power of 2, in case somebody accidentally makes it repeat vertically. + int numpix = Width * Height + (1 << HeightBits) - Height; + BYTE blendwork[256]; + bool hasTranslucent = false; + + Pixels = new BYTE[numpix]; + memset (Pixels, 0, numpix); + + for (int i = 0; i < NumParts; ++i) + { + if (Parts[i].op != OP_COPY) + { + hasTranslucent = true; + } + } + + if (!hasTranslucent) + { + for (int i = 0; i < NumParts; ++i) + { + if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. + + BYTE *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; + { + if (Parts[i].Blend != 0) + { + trans = GetBlendMap(Parts[i].Blend, blendwork); + } + Parts[i].Texture->CopyToBlock (Pixels, Width, Height, + Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); + } + } + } + else + { + // In case there are translucent patches let's do the composition in + // True color to keep as much precision as possible before downconverting to the palette. + BYTE *buffer = new BYTE[Width * Height * 4]; + memset(buffer, 0, Width * Height * 4); + FillBuffer(buffer, Width * 4, Height, TEX_RGB); + for(int y = 0; y < Height; y++) + { + BYTE *in = buffer + Width * y * 4; + BYTE *out = Pixels + y; + for (int x = 0; x < Width; x++) + { + if (*out == 0 && in[3] != 0) + { + *out = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3]; + } + out += Height; + in += 4; + } + } + delete [] buffer; + } +} + +//=========================================================================== +// +// FMultipatchTexture::CopyTrueColorPixels +// +// Preserves the palettes of each individual patch +// +//=========================================================================== + +int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) +{ + int retv = -1; + + if (bRedirect) + { // Redirect straight to the real texture's routine. + return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf); + } + + if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE))) + { // We are doing some sort of fancy stuff to the destination bitmap, so composite to + // a temporary bitmap, and copy that. + FBitmap tbmp; + if (tbmp.Create(Width, Height)) + { + retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0)); + bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height, + 4, tbmp.GetPitch(), rotate, CF_BGRA, inf); + } + return retv; + } + + // When compositing a multipatch texture with multipatch parts, + // drawing must be restricted to the actual area which is covered by this texture. + FClipRect saved_cr = bmp->GetClipRect(); + bmp->IntersectClipRect(x, y, Width, Height); + + if (inf != NULL && inf->op == OP_OVERWRITE) + { + bmp->Zero(); + } + + for(int i = 0; i < NumParts; i++) + { + int ret = -1; + FCopyInfo info; + + if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. + + memset (&info, 0, sizeof(info)); + info.alpha = Parts[i].Alpha; + info.invalpha = FRACUNIT - info.alpha; + info.op = ECopyOp(Parts[i].op); + PalEntry b = Parts[i].Blend; + if (b.a == 0 && b != BLEND_NONE) + { + info.blend = EBlend(b.d); + } + else if (b.a != 0) + { + if (b.a == 255) + { + info.blendcolor[0] = b.r * FRACUNIT / 255; + info.blendcolor[1] = b.g * FRACUNIT / 255; + info.blendcolor[2] = b.b * FRACUNIT / 255; + info.blend = BLEND_MODULATE; + } + else + { + fixed_t blendalpha = b.a * FRACUNIT / 255; + info.blendcolor[0] = b.r * blendalpha; + info.blendcolor[1] = b.g * blendalpha; + info.blendcolor[2] = b.b * blendalpha; + info.blendcolor[3] = FRACUNIT - blendalpha; + info.blend = BLEND_OVERLAY; + } + } + + if (Parts[i].Translation != NULL) + { // Using a translation forces downconversion to the base palette + ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); + } + else + { + ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); + } + + if (ret > retv) retv = ret; + } + // Restore previous clipping rectangle. + bmp->SetClipRect(saved_cr); + return retv; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetFormat +// +// only returns 'paletted' if all patches use the base palette. +// +//========================================================================== + +FTextureFormat FMultiPatchTexture::GetFormat() +{ + if (bComplex) return TEX_RGB; + if (NumParts == 1) return Parts[0].Texture->GetFormat(); + return UseBasePalette() ? TEX_Pal : TEX_RGB; +} + + +//=========================================================================== +// +// FMultipatchTexture::UseBasePalette +// +// returns true if all patches in the texture use the unmodified base +// palette. +// +//=========================================================================== + +bool FMultiPatchTexture::UseBasePalette() +{ + if (bComplex) return false; + for(int i=0;iUseBasePalette()) return false; + } + return true; +} + +//========================================================================== +// +// FMultiPatchTexture :: CheckForHacks +// +//========================================================================== + +void FMultiPatchTexture::CheckForHacks () +{ + if (NumParts <= 0) + { + return; + } + + // Heretic sky textures are marked as only 128 pixels tall, + // even though they are really 200 pixels tall. + if (gameinfo.gametype == GAME_Heretic && + Name[0] == 'S' && + Name[1] == 'K' && + Name[2] == 'Y' && + Name[4] == 0 && + Name[3] >= '1' && + Name[3] <= '3' && + Height == 128) + { + Height = 200; + HeightBits = 8; + return; + } + + // The Doom E1 sky has its patch's y offset at -8 instead of 0. + if (gameinfo.gametype == GAME_Doom && + !(gameinfo.flags & GI_MAPxx) && + NumParts == 1 && + Height == 128 && + Parts->OriginY == -8 && + Name[0] == 'S' && + Name[1] == 'K' && + Name[2] == 'Y' && + Name[3] == '1' && + Name[4] == 0) + { + Parts->OriginY = 0; + return; + } + + // BIGDOOR7 in Doom also has patches at y offset -4 instead of 0. + if (gameinfo.gametype == GAME_Doom && + !(gameinfo.flags & GI_MAPxx) && + NumParts == 2 && + Height == 128 && + Parts[0].OriginY == -4 && + Parts[1].OriginY == -4 && + Name[0] == 'B' && + Name[1] == 'I' && + Name[2] == 'G' && + Name[3] == 'D' && + Name[4] == 'O' && + Name[5] == 'O' && + Name[6] == 'R' && + Name[7] == '7') + { + Parts[0].OriginY = 0; + Parts[1].OriginY = 0; + return; + } + + // [RH] Some wads (I forget which!) have single-patch textures 256 + // pixels tall that have patch lengths recorded as 0. I can't think of + // any good reason for them to do this, and since I didn't make note + // of which wad made me hack in support for them, the hack is gone + // because I've added support for DeePsea's true tall patches. + // + // Okay, I found a wad with crap patches: Pleiades.wad's sky patches almost + // fit this description and are a big mess, but they're not single patch! + if (Height == 256) + { + int i; + + // All patches must be at the top of the texture for this fix + for (i = 0; i < NumParts; ++i) + { + if (Parts[i].OriginY != 0) + { + break; + } + } + + if (i == NumParts) + { + for (i = 0; i < NumParts; ++i) + { + Parts[i].Texture->HackHack(256); + } + } + } +} + +//========================================================================== +// +// FMultiPatchTexture :: GetRedirect +// +//========================================================================== + +FTexture *FMultiPatchTexture::GetRedirect(bool wantwarped) +{ + return bRedirect ? Parts->Texture : this; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetRawTexture +// +// Doom ignored all compositing of mid-sided textures on two-sided lines. +// Since these textures had to be single-patch in Doom, that essentially +// means it ignores their Y offsets. +// +// If this texture is composed of only one patch, return that patch. +// Otherwise, return this texture, since Doom wouldn't have been able to +// draw it anyway. +// +//========================================================================== + +FTexture *FMultiPatchTexture::GetRawTexture() +{ + return NumParts == 1 ? Parts->Texture : this; +} + +//========================================================================== +// +// FMultiPatchTexture :: TexPart :: TexPart +// +//========================================================================== + +FMultiPatchTexture::TexPart::TexPart() +{ + OriginX = OriginY = 0; + Rotate = 0; + Texture = NULL; + Translation = NULL; + Blend = 0; + Alpha = FRACUNIT; + op = OP_COPY; +} + +//========================================================================== +// +// FTextureManager :: AddTexturesLump +// +//========================================================================== + +void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1) +{ + FPatchLookup *patchlookup = NULL; + int i; + DWORD numpatches; + + if (firstdup == 0) + { + firstdup = (int)Textures.Size(); + } + + { + FWadLump pnames = Wads.OpenLumpNum (patcheslump); + + pnames >> numpatches; + + // Check whether the amount of names reported is correct. + if ((signed)numpatches < 0) + { + Printf("Corrupt PNAMES lump found (negative amount of entries reported)"); + return; + } + + // Check whether the amount of names reported is correct. + int lumplength = Wads.LumpLength(patcheslump); + if (numpatches > DWORD((lumplength-4)/8)) + { + Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", + numpatches, lumplength, (lumplength-4)/8); + // Truncate but continue reading. Who knows how many such lumps exist? + numpatches = (lumplength-4)/8; + } + + // Catalog the patches these textures use so we know which + // textures they represent. + patchlookup = new FPatchLookup[numpatches]; + for (DWORD i = 0; i < numpatches; ++i) + { + char pname[9]; + pnames.Read (pname, 8); + pname[8] = '\0'; + patchlookup[i].Name = pname; + FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); + if (j.isValid()) + { + patchlookup[i].Texture = Textures[j.GetIndex()].Texture; + } + else + { + // Shareware Doom has the same PNAMES lump as the registered + // Doom, so printing warnings for patches that don't really + // exist isn't such a good idea. + //Printf ("Patch %s not found.\n", patchlookup[i].Name); + patchlookup[i].Texture = NULL; + } + } + } + + bool isStrife = false; + const DWORD *maptex, *directory; + DWORD maxoff; + int numtextures; + DWORD offset = 0; // Shut up, GCC! + + maptex = (const DWORD *)lumpdata; + numtextures = LittleLong(*maptex); + maxoff = lumpsize; + + if (maxoff < DWORD(numtextures+1)*4) + { + Printf ("Texture directory is too short"); + delete[] patchlookup; + return; + } + + // Scan the texture lump to decide if it contains Doom or Strife textures + for (i = 0, directory = maptex+1; i < numtextures; ++i) + { + offset = LittleLong(directory[i]); + if (offset > maxoff) + { + Printf ("Bad texture directory"); + delete[] patchlookup; + return; + } + + maptexture_t *tex = (maptexture_t *)((BYTE *)maptex + offset); + + // There is bizzarely a Doom editing tool that writes to the + // first two elements of columndirectory, so I can't check those. + if (SAFESHORT(tex->patchcount) < 0 || + tex->columndirectory[2] != 0 || + tex->columndirectory[3] != 0) + { + isStrife = true; + break; + } + } + + + // Textures defined earlier in the lump take precedence over those defined later, + // but later TEXTUREx lumps take precedence over earlier ones. + for (i = 1, directory = maptex; i <= numtextures; ++i) + { + if (i == 1 && texture1) + { + // The very first texture is just a dummy. Copy its dimensions to texture 0. + // It still needs to be created in case someone uses it by name. + offset = LittleLong(directory[1]); + const maptexture_t *tex = (const maptexture_t *)((const BYTE *)maptex + offset); + FDummyTexture *tex0 = static_cast(Textures[0].Texture); + tex0->SetSize (SAFESHORT(tex->width), SAFESHORT(tex->height)); + } + + offset = LittleLong(directory[i]); + if (offset > maxoff) + { + Printf ("Bad texture directory"); + delete[] patchlookup; + return; + } + + // If this texture was defined already in this lump, skip it + // This could cause problems with animations that use the same name for intermediate + // textures. Should I be worried? + int j; + for (j = (int)Textures.Size() - 1; j >= firstdup; --j) + { + if (strnicmp (Textures[j].Texture->Name, (const char *)maptex + offset, 8) == 0) + break; + } + if (j + 1 == firstdup) + { + FMultiPatchTexture *tex = new FMultiPatchTexture ((const BYTE *)maptex + offset, patchlookup, numpatches, isStrife, deflumpnum); + if (i == 1 && texture1) + { + tex->UseType = FTexture::TEX_FirstDefined; + } + TexMan.AddTexture (tex); + StartScreen->Progress(); + } + } + delete[] patchlookup; +} + + +//========================================================================== +// +// FTextureManager :: AddTexturesLumps +// +//========================================================================== + +void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) +{ + int firstdup = (int)Textures.Size(); + + if (lump1 >= 0) + { + FMemLump texdir = Wads.ReadLump (lump1); + AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump1), lump1, patcheslump, firstdup, true); + } + if (lump2 >= 0) + { + FMemLump texdir = Wads.ReadLump (lump2); + AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump2), lump2, patcheslump, firstdup, false); + } +} + + +//========================================================================== +// +// +// +//========================================================================== + +void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) +{ + FString patchname; + sc.MustGetString(); + + FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); + int Mirror = 0; + + if (!texno.isValid()) + { + if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) + { + int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); + if (lumpnum >= 0) + { + part.Texture = FTexture::CreateTexture(lumpnum, usetype); + TexMan.AddTexture(part.Texture); + } + } + } + else + { + part.Texture = TexMan[texno]; + bComplex |= part.Texture->bComplex; + } + if (part.Texture == NULL) + { + if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); + } + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginX = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginY = sc.Number; + + if (sc.CheckString("{")) + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("flipx")) + { + Mirror |= 1; + } + else if (sc.Compare("flipy")) + { + Mirror |= 2; + } + else if (sc.Compare("rotate")) + { + sc.MustGetNumber(); + sc.Number = (((sc.Number + 90)%360)-90); + if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90) + { + sc.ScriptError("Rotation must be a multiple of 90 degrees."); + } + part.Rotate = (sc.Number / 90) & 3; + } + else if (sc.Compare("Translation")) + { + int match; + + bComplex = true; + if (part.Translation != NULL) delete part.Translation; + part.Translation = NULL; + part.Blend = 0; + static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL }; + sc.MustGetString(); + + match = sc.MatchString(maps); + if (match >= 0) + { + part.Blend = BLEND_SPECIALCOLORMAP1 + match; + } + else if (sc.Compare("ICE")) + { + part.Blend = BLEND_ICEMAP; + } + else if (sc.Compare("DESATURATE")) + { + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30); + } + else + { + sc.UnGet(); + part.Translation = new FRemapTable; + part.Translation->MakeIdentity(); + do + { + sc.MustGetString(); + part.Translation->AddToTranslation(sc.String); + } + while (sc.CheckString(",")); + } + + } + else if (sc.Compare("Colormap")) + { + float r1,g1,b1; + float r2,g2,b2; + + sc.MustGetFloat(); + r1 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + g1 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + b1 = (float)sc.Float; + if (!sc.CheckString(",")) + { + part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1); + } + else + { + sc.MustGetFloat(); + r2 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + g2 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + b2 = (float)sc.Float; + part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2); + } + } + else if (sc.Compare("Blend")) + { + bComplex = true; + if (part.Translation != NULL) delete part.Translation; + part.Translation = NULL; + part.Blend = 0; + + if (!sc.CheckNumber()) + { + sc.MustGetString(); + part.Blend = V_GetColor(NULL, sc.String); + } + else + { + int r,g,b; + + r = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + g = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + b = sc.Number; + sc.MustGetStringName(","); + part.Blend = MAKERGB(r, g, b); + } + // Blend.a may never be 0 here. + if (sc.CheckString(",")) + { + sc.MustGetFloat(); + if (sc.Float > 0.f) + part.Blend.a = clamp(int(sc.Float*255), 1, 254); + else + part.Blend = 0; + } + else part.Blend.a = 255; + } + else if (sc.Compare("alpha")) + { + sc.MustGetFloat(); + part.Alpha = clamp(FLOAT2FIXED(sc.Float), 0, FRACUNIT); + // bComplex is not set because it is only needed when the style is not OP_COPY. + } + else if (sc.Compare("style")) + { + static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL }; + sc.MustGetString(); + part.op = sc.MustMatchString(styles); + bComplex |= (part.op != OP_COPY); + bTranslucentPatches = bComplex; + } + else if (sc.Compare("useoffsets")) + { + if (part.Texture != NULL) + { + part.OriginX -= part.Texture->LeftOffset; + part.OriginY -= part.Texture->TopOffset; + } + } + } + } + if (Mirror & 2) + { + part.Rotate = (part.Rotate + 2) & 3; + Mirror ^= 1; + } + if (Mirror & 1) + { + part.Rotate |= 4; + } +} + +//========================================================================== +// +// Constructor for text based multipatch definitions +// +//========================================================================== + +FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +{ + TArray parts; + bool bSilent = false; + + bMultiPatch = true; + sc.SetCMode(true); + sc.MustGetString(); + const char* textureName = NULL; + if (sc.Compare("optional")) + { + bSilent = true; + sc.MustGetString(); + if (sc.Compare(",")) + { + // this is not right. Apparently a texture named 'optional' is being defined right now... + sc.UnGet(); + textureName = "optional"; + bSilent = false; + } + } + Name = !textureName ? sc.String : textureName; + Name.ToUpper(); + sc.MustGetStringName(","); + sc.MustGetNumber(); + Width = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + Height = sc.Number; + UseType = usetype; + + if (sc.CheckString("{")) + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("XScale")) + { + sc.MustGetFloat(); + xScale = FLOAT2FIXED(sc.Float); + if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); + } + else if (sc.Compare("YScale")) + { + sc.MustGetFloat(); + yScale = FLOAT2FIXED(sc.Float); + if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); + } + else if (sc.Compare("WorldPanning")) + { + bWorldPanning = true; + } + else if (sc.Compare("NullTexture")) + { + UseType = FTexture::TEX_Null; + } + else if (sc.Compare("NoDecals")) + { + bNoDecals = true; + } + else if (sc.Compare("Patch")) + { + TexPart part; + ParsePatch(sc, part, bSilent, TEX_WallPatch); + if (part.Texture != NULL) parts.Push(part); + part.Texture = NULL; + part.Translation = NULL; + } + else if (sc.Compare("Graphic")) + { + TexPart part; + ParsePatch(sc, part, bSilent, TEX_MiscPatch); + if (part.Texture != NULL) parts.Push(part); + part.Texture = NULL; + part.Translation = NULL; + } + else if (sc.Compare("Offset")) + { + sc.MustGetNumber(); + LeftOffset = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + TopOffset = sc.Number; + } + else + { + sc.ScriptError("Unknown texture property '%s'", sc.String); + } + } + + NumParts = parts.Size(); + Parts = new TexPart[NumParts]; + memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); + + //CalcBitSize (); + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height && + Parts->Rotate == 0 && + !bComplex) + { + bRedirect = true; + } + } + } + + if (Width <= 0 || Height <= 0) + { + UseType = FTexture::TEX_Null; + Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); + Width = Height = 1; + } + CalcBitSize (); + + + sc.SetCMode(false); +} + + + +void FTextureManager::ParseXTexture(FScanner &sc, int usetype) +{ + FTexture *tex = new FMultiPatchTexture(sc, usetype); + TexMan.AddTexture (tex); +} diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index f41f1902d..6ee6ccb0a 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -137,7 +137,10 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype) FTexture * FTexture::CreateTexture (const char *name, int lumpnum, int usetype) { FTexture *tex = CreateTexture(lumpnum, usetype); - if (tex != NULL && name != NULL) uppercopy(tex->Name, name); + if (tex != NULL && name != NULL) { + tex->Name = name; + tex->Name.ToUpper(); + } return tex; } @@ -152,16 +155,16 @@ FTexture::FTexture (const char *name, int lumpnum) id.SetInvalid(); if (name != NULL) { - uppercopy(Name, name); + Name = name; + Name.ToUpper(); } else if (lumpnum < 0) { - *Name = 0; + Name = FString(); } else { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; } } @@ -574,7 +577,6 @@ FDummyTexture::FDummyTexture () HeightBits = 6; WidthBits = 6; WidthMask = 63; - Name[0] = 0; UseType = TEX_Null; } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 6fb963e42..2a10ce0df 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -373,7 +373,7 @@ FTextureID FTextureManager::AddTexture (FTexture *texture) // Later textures take precedence over earlier ones // Textures without name can't be looked for - if (texture->Name[0] != 0) + if (texture->Name[0] != '\0') { bucket = int(MakeKey (texture->Name) % HASH_SIZE); hash = HashFirst[bucket]; @@ -429,7 +429,7 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b FTexture *oldtexture = Textures[index].Texture; - strcpy (newtexture->Name, oldtexture->Name); + newtexture->Name = oldtexture->Name; newtexture->UseType = oldtexture->UseType; Textures[index].Texture = newtexture; @@ -488,9 +488,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) { int firsttx = Wads.GetFirstLump(wadnum); int lasttx = Wads.GetLastLump(wadnum); - char name[9]; - - name[8] = 0; + FString Name; // Go from first to last so that ANIMDEFS work as expected. However, // to avoid duplicates (and to keep earlier entries from overriding @@ -501,9 +499,9 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) { if (Wads.GetLumpNamespace(firsttx) == ns) { - Wads.GetLumpName (name, firsttx); + Wads.GetLumpName (Name, firsttx); - if (Wads.CheckNumForName (name, ns) == firsttx) + if (Wads.CheckNumForName (Name, ns) == firsttx) { CreateTexture (firsttx, usetype); } @@ -511,7 +509,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, int usetype) } else if (ns == ns_flats && Wads.GetLumpFlags(firsttx) & LUMPF_MAYBEFLAT) { - if (Wads.CheckNumForName (name, ns) < firsttx) + if (Wads.CheckNumForName (Name, ns) < firsttx) { CreateTexture (firsttx, usetype); } @@ -531,7 +529,7 @@ void FTextureManager::AddHiresTextures (int wadnum) int firsttx = Wads.GetFirstLump(wadnum); int lasttx = Wads.GetLastLump(wadnum); - char name[9]; + FString Name; TArray tlist; if (firsttx == -1 || lasttx == -1) @@ -539,18 +537,16 @@ void FTextureManager::AddHiresTextures (int wadnum) return; } - name[8] = 0; - for (;firsttx <= lasttx; ++firsttx) { if (Wads.GetLumpNamespace(firsttx) == ns_hires) { - Wads.GetLumpName (name, firsttx); + Wads.GetLumpName (Name, firsttx); - if (Wads.CheckNumForName (name, ns_hires) == firsttx) + if (Wads.CheckNumForName (Name, ns_hires) == firsttx) { tlist.Clear(); - int amount = ListTextures(name, tlist); + int amount = ListTextures(Name, tlist); if (amount == 0) { // A texture with this name does not yet exist @@ -594,14 +590,13 @@ void FTextureManager::AddHiresTextures (int wadnum) void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) { int remapLump, lastLump; - char src[9]; + FString src; bool is32bit; int width, height; int type, mode; TArray tlist; lastLump = 0; - src[8] = '\0'; while ((remapLump = Wads.FindLump(lumpname, &lastLump)) != -1) { @@ -678,7 +673,7 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) FString base = ExtractFileBase(sc.String, false); if (!base.IsEmpty()) { - strncpy(src, base, 8); + src = base.Left(8); int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches); if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); @@ -701,7 +696,7 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) // Replace the entire texture and adjust the scaling and offset factors. newtex->bWorldPanning = true; newtex->SetScaledSize(width, height); - memcpy(newtex->Name, src, sizeof(newtex->Name)); + newtex->Name = src; FTextureID oldtex = TexMan.CheckForTexture(src, FTexture::TEX_MiscPatch); if (oldtex.isValid()) @@ -757,7 +752,7 @@ void FTextureManager::AddPatches (int lumpnum) char name[9]; *file >> numpatches; - name[8] = 0; + name[8] = '\0'; for (i = 0; i < numpatches; ++i) { @@ -839,9 +834,8 @@ void FTextureManager::AddTexturesForWad(int wadnum) for (int i= firsttx; i <= lasttx; i++) { bool skin = false; - char name[9]; - Wads.GetLumpName(name, i); - name[8]=0; + FString Name; + Wads.GetLumpName(Name, i); // Ignore anything not in the global namespace int ns = Wads.GetLumpNamespace(i); @@ -867,20 +861,20 @@ void FTextureManager::AddTexturesForWad(int wadnum) if (Wads.CheckLumpName(i, "BEHAVIOR")) continue; // Don't bother looking at this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns_graphics) != i) continue; + if (Wads.CheckNumForName(Name, ns_graphics) != i) continue; // skip this if it has already been added as a wall patch. - if (CheckForTexture(name, FTexture::TEX_WallPatch, 0).Exists()) continue; + if (CheckForTexture(Name, FTexture::TEX_WallPatch, 0).Exists()) continue; } else if (ns == ns_graphics) { // Don't bother looking this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns_graphics) != i) continue; + if (Wads.CheckNumForName(Name, ns_graphics) != i) continue; } else if (ns >= ns_firstskin) { // Don't bother looking this lump if something later overrides it. - if (Wads.CheckNumForName(name, ns) != i) continue; + if (Wads.CheckNumForName(Name, ns) != i) continue; skin = true; } else continue; diff --git a/src/textures/textures.h b/src/textures/textures.h index 15c9bce5c..9dbd85a55 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -157,11 +157,7 @@ public: int SourceLump; FTextureID id; - union - { - char Name[9]; - DWORD dwName; // Used with sprites - }; + FString Name; BYTE UseType; // This texture's primary purpose BYTE bNoDecals:1; // Decals should not stick to texture diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 374861699..cff89603c 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -145,7 +145,6 @@ FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) : FTexture(NULL, lumpnum), Pixels(0), Spans(0) { Wads.GetLumpName (Name, lumpnum); - Name[8] = 0; Width = hdr->width; Height = hdr->height; // Alpha channel is used only for 32 bit RGBA and paletted images with RGBA palettes. diff --git a/src/w_wad.cpp b/src/w_wad.cpp index c351de6f8..9455817db 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -492,7 +492,7 @@ int FWadCollection::CheckNumForFullName (const char *name, bool trynormal, int n return -1; } - i = FirstLumpIndex_FullName[MakeKey (name) % NumLumps]; + i = FirstLumpIndex_FullName[MakeKey(name) % NumLumps]; while (i != NULL_INDEX && stricmp(name, LumpInfo[i].lump->FullName)) { @@ -1015,6 +1015,16 @@ void FWadCollection::GetLumpName (char *to, int lump) const uppercopy (to, LumpInfo[lump].lump->Name); } +void FWadCollection::GetLumpName(FString &to, int lump) const +{ + if ((size_t)lump >= NumLumps) + to = FString(); + else { + to = LumpInfo[lump].lump->Name; + to.ToUpper(); + } +} + //========================================================================== // // FWadCollection :: GetLumpFullName diff --git a/src/w_wad.h b/src/w_wad.h index 530182147..0a95699f6 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -196,7 +196,8 @@ public: int GetLumpOffset (int lump); // [RH] Returns offset of lump in the wadfile int GetLumpFlags (int lump); // Return the flags for this lump void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy - const char *GetLumpFullName (int lump) const; // [RH] Returns the lump's full name + void FWadCollection::GetLumpName(FString &to, int lump) const; + const char *GetLumpFullName(int lump) const; // [RH] Returns the lump's full name FString GetLumpFullPath (int lump) const; // [RH] Returns wad's name + lump's full name int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to From 582b1990b7f342601a1976c85d0ce2b25343458e Mon Sep 17 00:00:00 2001 From: Shawn Walker Date: Sun, 18 May 2014 16:00:31 -0700 Subject: [PATCH 232/247] - restore original line endings --- src/textures/multipatchtexture.cpp | 2670 ++++++++++++++-------------- 1 file changed, 1335 insertions(+), 1335 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index c51f30168..84e7385db 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -1,1336 +1,1336 @@ -/* -** multipatchtexture.cpp -** Texture class for standard Doom multipatch textures -** -**--------------------------------------------------------------------------- -** Copyright 2004-2006 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. -**--------------------------------------------------------------------------- -** -** -*/ - -#include -#include "doomtype.h" -#include "files.h" -#include "w_wad.h" -#include "i_system.h" -#include "gi.h" -#include "st_start.h" -#include "sc_man.h" -#include "templates.h" -#include "r_data/r_translate.h" -#include "bitmap.h" -#include "colormatcher.h" -#include "v_palette.h" -#include "v_video.h" -#include "v_text.h" -#include "m_fixed.h" -#include "textures/textures.h" -#include "r_data/colormaps.h" - -// On the Alpha, accessing the shorts directly if they aren't aligned on a -// 4-byte boundary causes unaligned access warnings. Why it does this at -// all and only while initing the textures is beyond me. - -#ifdef ALPHA -#define SAFESHORT(s) ((short)(((BYTE *)&(s))[0] + ((BYTE *)&(s))[1] * 256)) -#else -#define SAFESHORT(s) LittleShort(s) -#endif - - - -//-------------------------------------------------------------------------- -// -// Data structures for the TEXTUREx lumps -// -//-------------------------------------------------------------------------- - -// -// Each texture is composed of one or more patches, with patches being lumps -// stored in the WAD. The lumps are referenced by number, and patched into -// the rectangular texture space using origin and possibly other attributes. -// -struct mappatch_t -{ - SWORD originx; - SWORD originy; - SWORD patch; - SWORD stepdir; - SWORD colormap; -}; - -// -// A wall texture is a list of patches which are to be combined in a -// predefined order. -// -struct maptexture_t -{ +/* +** multipatchtexture.cpp +** Texture class for standard Doom multipatch textures +** +**--------------------------------------------------------------------------- +** Copyright 2004-2006 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. +**--------------------------------------------------------------------------- +** +** +*/ + +#include +#include "doomtype.h" +#include "files.h" +#include "w_wad.h" +#include "i_system.h" +#include "gi.h" +#include "st_start.h" +#include "sc_man.h" +#include "templates.h" +#include "r_data/r_translate.h" +#include "bitmap.h" +#include "colormatcher.h" +#include "v_palette.h" +#include "v_video.h" +#include "v_text.h" +#include "m_fixed.h" +#include "textures/textures.h" +#include "r_data/colormaps.h" + +// On the Alpha, accessing the shorts directly if they aren't aligned on a +// 4-byte boundary causes unaligned access warnings. Why it does this at +// all and only while initing the textures is beyond me. + +#ifdef ALPHA +#define SAFESHORT(s) ((short)(((BYTE *)&(s))[0] + ((BYTE *)&(s))[1] * 256)) +#else +#define SAFESHORT(s) LittleShort(s) +#endif + + + +//-------------------------------------------------------------------------- +// +// Data structures for the TEXTUREx lumps +// +//-------------------------------------------------------------------------- + +// +// Each texture is composed of one or more patches, with patches being lumps +// stored in the WAD. The lumps are referenced by number, and patched into +// the rectangular texture space using origin and possibly other attributes. +// +struct mappatch_t +{ + SWORD originx; + SWORD originy; + SWORD patch; + SWORD stepdir; + SWORD colormap; +}; + +// +// A wall texture is a list of patches which are to be combined in a +// predefined order. +// +struct maptexture_t +{ BYTE name[8]; - WORD Flags; // [RH] Was unused - BYTE ScaleX; // [RH] Scaling (8 is normal) - BYTE ScaleY; // [RH] Same as above - SWORD width; - SWORD height; - BYTE columndirectory[4]; // OBSOLETE - SWORD patchcount; - mappatch_t patches[1]; -}; - -#define MAPTEXF_WORLDPANNING 0x8000 - -// Strife uses versions of the above structures that remove all unused fields - -struct strifemappatch_t -{ - SWORD originx; - SWORD originy; - SWORD patch; -}; - -// -// A wall texture is a list of patches which are to be combined in a -// predefined order. -// -struct strifemaptexture_t -{ - BYTE name[8]; - WORD Flags; // [RH] Was unused - BYTE ScaleX; // [RH] Scaling (8 is normal) - BYTE ScaleY; // [RH] Same as above - SWORD width; - SWORD height; - SWORD patchcount; - strifemappatch_t patches[1]; -}; - - -//========================================================================== -// -// In-memory representation of a single PNAMES lump entry -// -//========================================================================== - -struct FPatchLookup -{ - FString Name; - FTexture *Texture; -}; - - -//========================================================================== -// -// A texture defined in a TEXTURE1 or TEXTURE2 lump -// -//========================================================================== - -class FMultiPatchTexture : public FTexture -{ -public: - FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); - FMultiPatchTexture (FScanner &sc, int usetype); - ~FMultiPatchTexture (); - - const BYTE *GetColumn (unsigned int column, const Span **spans_out); - const BYTE *GetPixels (); - FTextureFormat GetFormat(); - bool UseBasePalette() ; - void Unload (); - virtual void SetFrontSkyLayer (); - - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - int GetSourceLump() { return DefinitionLump; } - FTexture *GetRedirect(bool wantwarped); - FTexture *GetRawTexture(); - -protected: - BYTE *Pixels; - Span **Spans; - int DefinitionLump; - - struct TexPart - { - SWORD OriginX, OriginY; - BYTE Rotate; - BYTE op; - FRemapTable *Translation; - PalEntry Blend; - FTexture *Texture; - fixed_t Alpha; - - TexPart(); - }; - - int NumParts; - TexPart *Parts; - bool bRedirect:1; - bool bTranslucentPatches:1; - - void MakeTexture (); - -private: - void CheckForHacks (); - void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); -}; - -//========================================================================== -// -// FMultiPatchTexture :: FMultiPatchTexture -// -//========================================================================== - -FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) -{ - union - { - const maptexture_t *d; - const strifemaptexture_t *s; - } - mtexture; - - union - { - const mappatch_t *d; - const strifemappatch_t *s; - } - mpatch; - - int i; - - mtexture.d = (const maptexture_t *)texdef; - bMultiPatch = true; - - if (strife) - { - NumParts = SAFESHORT(mtexture.s->patchcount); - } - else - { - NumParts = SAFESHORT(mtexture.d->patchcount); - } - - if (NumParts < 0) - { - I_FatalError ("Bad texture directory"); - } - - UseType = FTexture::TEX_Wall; - Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; - Width = SAFESHORT(mtexture.d->width); - Height = SAFESHORT(mtexture.d->height); - Name = (char *)mtexture.d->name; - CalcBitSize (); - - xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; - yScale = mtexture.d->ScaleY ? mtexture.d->ScaleY*(FRACUNIT/8) : FRACUNIT; - - if (mtexture.d->Flags & MAPTEXF_WORLDPANNING) - { - bWorldPanning = true; - } - - if (strife) - { - mpatch.s = &mtexture.s->patches[0]; - } - else - { - mpatch.d = &mtexture.d->patches[0]; - } - - for (i = 0; i < NumParts; ++i) - { - if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) - { - I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", - maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); - } - Parts[i].OriginX = LittleShort(mpatch.d->originx); - Parts[i].OriginY = LittleShort(mpatch.d->originy); - Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; - if (Parts[i].Texture == NULL) - { - Printf (TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); - NumParts--; - i--; - } - else - { - Parts[i].Texture->bKeepAround = true; - } - if (strife) - mpatch.s++; - else - mpatch.d++; - } - if (NumParts == 0) - { - Printf ("Texture %s is left without any patches\n", Name); - } - - CheckForHacks (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height) - { - bRedirect = true; - } - } - DefinitionLump = deflumpnum; -} - -//========================================================================== -// -// FMultiPatchTexture :: ~FMultiPatchTexture -// -//========================================================================== - -FMultiPatchTexture::~FMultiPatchTexture () -{ - Unload (); - if (Parts != NULL) - { - for(int i=0; iSetFrontSkyLayer (); - } - bNoRemap0 = true; -} - -//========================================================================== -// -// FMultiPatchTexture :: Unload -// -//========================================================================== - -void FMultiPatchTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } -} - -//========================================================================== -// -// FMultiPatchTexture :: GetPixels -// -//========================================================================== - -const BYTE *FMultiPatchTexture::GetPixels () -{ - if (bRedirect) - { - return Parts->Texture->GetPixels (); - } - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetColumn -// -//========================================================================== - -const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (bRedirect) - { - return Parts->Texture->GetColumn (column, spans_out); - } - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - if (Spans == NULL) - { - Spans = CreateSpans (Pixels); - } - *spans_out = Spans[column]; - } - return Pixels + column*Height; -} - - -//========================================================================== -// -// GetBlendMap -// -//========================================================================== - -BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork) -{ - - switch (blend.a==0 ? int(blend) : -1) - { - case BLEND_ICEMAP: - return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap; - - default: - if (blend >= BLEND_SPECIALCOLORMAP1 && blend < BLEND_SPECIALCOLORMAP1 + SpecialColormaps.Size()) - { - return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap; - } - else if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31) - { - return DesaturateColormap[blend - BLEND_DESATURATE1]; - } - else - { - blendwork[0]=0; - if (blend.a == 255) - { - for(int i=1;i<256;i++) - { - int rr = (blend.r * GPalette.BaseColors[i].r) / 255; - int gg = (blend.g * GPalette.BaseColors[i].g) / 255; - int bb = (blend.b * GPalette.BaseColors[i].b) / 255; - - blendwork[i] = ColorMatcher.Pick(rr, gg, bb); - } - return blendwork; - } - else if (blend.a != 0) - { - for(int i=1;i<256;i++) - { - int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255; - int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255; - int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255; - - blendwork[i] = ColorMatcher.Pick(rr, gg, bb); - } - return blendwork; - } - } - } - return NULL; -} - -//========================================================================== -// -// FMultiPatchTexture :: MakeTexture -// -//========================================================================== - -void FMultiPatchTexture::MakeTexture () -{ - // Add a little extra space at the end if the texture's height is not - // a power of 2, in case somebody accidentally makes it repeat vertically. - int numpix = Width * Height + (1 << HeightBits) - Height; - BYTE blendwork[256]; - bool hasTranslucent = false; - - Pixels = new BYTE[numpix]; - memset (Pixels, 0, numpix); - - for (int i = 0; i < NumParts; ++i) - { - if (Parts[i].op != OP_COPY) - { - hasTranslucent = true; - } - } - - if (!hasTranslucent) - { - for (int i = 0; i < NumParts; ++i) - { - if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - - BYTE *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; - { - if (Parts[i].Blend != 0) - { - trans = GetBlendMap(Parts[i].Blend, blendwork); - } - Parts[i].Texture->CopyToBlock (Pixels, Width, Height, - Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); - } - } - } - else - { - // In case there are translucent patches let's do the composition in - // True color to keep as much precision as possible before downconverting to the palette. - BYTE *buffer = new BYTE[Width * Height * 4]; - memset(buffer, 0, Width * Height * 4); - FillBuffer(buffer, Width * 4, Height, TEX_RGB); - for(int y = 0; y < Height; y++) - { - BYTE *in = buffer + Width * y * 4; - BYTE *out = Pixels + y; - for (int x = 0; x < Width; x++) - { - if (*out == 0 && in[3] != 0) - { - *out = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3]; - } - out += Height; - in += 4; - } - } - delete [] buffer; - } -} - -//=========================================================================== -// -// FMultipatchTexture::CopyTrueColorPixels -// -// Preserves the palettes of each individual patch -// -//=========================================================================== - -int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) -{ - int retv = -1; - - if (bRedirect) - { // Redirect straight to the real texture's routine. - return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf); - } - - if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE))) - { // We are doing some sort of fancy stuff to the destination bitmap, so composite to - // a temporary bitmap, and copy that. - FBitmap tbmp; - if (tbmp.Create(Width, Height)) - { - retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0)); - bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height, - 4, tbmp.GetPitch(), rotate, CF_BGRA, inf); - } - return retv; - } - - // When compositing a multipatch texture with multipatch parts, - // drawing must be restricted to the actual area which is covered by this texture. - FClipRect saved_cr = bmp->GetClipRect(); - bmp->IntersectClipRect(x, y, Width, Height); - - if (inf != NULL && inf->op == OP_OVERWRITE) - { - bmp->Zero(); - } - - for(int i = 0; i < NumParts; i++) - { - int ret = -1; - FCopyInfo info; - - if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - - memset (&info, 0, sizeof(info)); - info.alpha = Parts[i].Alpha; - info.invalpha = FRACUNIT - info.alpha; - info.op = ECopyOp(Parts[i].op); - PalEntry b = Parts[i].Blend; - if (b.a == 0 && b != BLEND_NONE) - { - info.blend = EBlend(b.d); - } - else if (b.a != 0) - { - if (b.a == 255) - { - info.blendcolor[0] = b.r * FRACUNIT / 255; - info.blendcolor[1] = b.g * FRACUNIT / 255; - info.blendcolor[2] = b.b * FRACUNIT / 255; - info.blend = BLEND_MODULATE; - } - else - { - fixed_t blendalpha = b.a * FRACUNIT / 255; - info.blendcolor[0] = b.r * blendalpha; - info.blendcolor[1] = b.g * blendalpha; - info.blendcolor[2] = b.b * blendalpha; - info.blendcolor[3] = FRACUNIT - blendalpha; - info.blend = BLEND_OVERLAY; - } - } - - if (Parts[i].Translation != NULL) - { // Using a translation forces downconversion to the base palette - ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); - } - else - { - ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); - } - - if (ret > retv) retv = ret; - } - // Restore previous clipping rectangle. - bmp->SetClipRect(saved_cr); - return retv; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetFormat -// -// only returns 'paletted' if all patches use the base palette. -// -//========================================================================== - -FTextureFormat FMultiPatchTexture::GetFormat() -{ - if (bComplex) return TEX_RGB; - if (NumParts == 1) return Parts[0].Texture->GetFormat(); - return UseBasePalette() ? TEX_Pal : TEX_RGB; -} - - -//=========================================================================== -// -// FMultipatchTexture::UseBasePalette -// -// returns true if all patches in the texture use the unmodified base -// palette. -// -//=========================================================================== - -bool FMultiPatchTexture::UseBasePalette() -{ - if (bComplex) return false; - for(int i=0;iUseBasePalette()) return false; - } - return true; -} - -//========================================================================== -// -// FMultiPatchTexture :: CheckForHacks -// -//========================================================================== - -void FMultiPatchTexture::CheckForHacks () -{ - if (NumParts <= 0) - { - return; - } - - // Heretic sky textures are marked as only 128 pixels tall, - // even though they are really 200 pixels tall. - if (gameinfo.gametype == GAME_Heretic && - Name[0] == 'S' && - Name[1] == 'K' && - Name[2] == 'Y' && - Name[4] == 0 && - Name[3] >= '1' && - Name[3] <= '3' && - Height == 128) - { - Height = 200; - HeightBits = 8; - return; - } - - // The Doom E1 sky has its patch's y offset at -8 instead of 0. - if (gameinfo.gametype == GAME_Doom && - !(gameinfo.flags & GI_MAPxx) && - NumParts == 1 && - Height == 128 && - Parts->OriginY == -8 && - Name[0] == 'S' && - Name[1] == 'K' && - Name[2] == 'Y' && - Name[3] == '1' && - Name[4] == 0) - { - Parts->OriginY = 0; - return; - } - - // BIGDOOR7 in Doom also has patches at y offset -4 instead of 0. - if (gameinfo.gametype == GAME_Doom && - !(gameinfo.flags & GI_MAPxx) && - NumParts == 2 && - Height == 128 && - Parts[0].OriginY == -4 && - Parts[1].OriginY == -4 && - Name[0] == 'B' && - Name[1] == 'I' && - Name[2] == 'G' && - Name[3] == 'D' && - Name[4] == 'O' && - Name[5] == 'O' && - Name[6] == 'R' && - Name[7] == '7') - { - Parts[0].OriginY = 0; - Parts[1].OriginY = 0; - return; - } - - // [RH] Some wads (I forget which!) have single-patch textures 256 - // pixels tall that have patch lengths recorded as 0. I can't think of - // any good reason for them to do this, and since I didn't make note - // of which wad made me hack in support for them, the hack is gone - // because I've added support for DeePsea's true tall patches. - // - // Okay, I found a wad with crap patches: Pleiades.wad's sky patches almost - // fit this description and are a big mess, but they're not single patch! - if (Height == 256) - { - int i; - - // All patches must be at the top of the texture for this fix - for (i = 0; i < NumParts; ++i) - { - if (Parts[i].OriginY != 0) - { - break; - } - } - - if (i == NumParts) - { - for (i = 0; i < NumParts; ++i) - { - Parts[i].Texture->HackHack(256); - } - } - } -} - -//========================================================================== -// -// FMultiPatchTexture :: GetRedirect -// -//========================================================================== - -FTexture *FMultiPatchTexture::GetRedirect(bool wantwarped) -{ - return bRedirect ? Parts->Texture : this; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetRawTexture -// -// Doom ignored all compositing of mid-sided textures on two-sided lines. -// Since these textures had to be single-patch in Doom, that essentially -// means it ignores their Y offsets. -// -// If this texture is composed of only one patch, return that patch. -// Otherwise, return this texture, since Doom wouldn't have been able to -// draw it anyway. -// -//========================================================================== - -FTexture *FMultiPatchTexture::GetRawTexture() -{ - return NumParts == 1 ? Parts->Texture : this; -} - -//========================================================================== -// -// FMultiPatchTexture :: TexPart :: TexPart -// -//========================================================================== - -FMultiPatchTexture::TexPart::TexPart() -{ - OriginX = OriginY = 0; - Rotate = 0; - Texture = NULL; - Translation = NULL; - Blend = 0; - Alpha = FRACUNIT; - op = OP_COPY; -} - -//========================================================================== -// -// FTextureManager :: AddTexturesLump -// -//========================================================================== - -void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1) -{ - FPatchLookup *patchlookup = NULL; - int i; - DWORD numpatches; - - if (firstdup == 0) - { - firstdup = (int)Textures.Size(); - } - - { - FWadLump pnames = Wads.OpenLumpNum (patcheslump); - - pnames >> numpatches; - - // Check whether the amount of names reported is correct. - if ((signed)numpatches < 0) - { - Printf("Corrupt PNAMES lump found (negative amount of entries reported)"); - return; - } - - // Check whether the amount of names reported is correct. - int lumplength = Wads.LumpLength(patcheslump); - if (numpatches > DWORD((lumplength-4)/8)) - { - Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", - numpatches, lumplength, (lumplength-4)/8); - // Truncate but continue reading. Who knows how many such lumps exist? - numpatches = (lumplength-4)/8; - } - - // Catalog the patches these textures use so we know which - // textures they represent. - patchlookup = new FPatchLookup[numpatches]; - for (DWORD i = 0; i < numpatches; ++i) - { - char pname[9]; - pnames.Read (pname, 8); - pname[8] = '\0'; - patchlookup[i].Name = pname; - FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); - if (j.isValid()) - { - patchlookup[i].Texture = Textures[j.GetIndex()].Texture; - } - else - { - // Shareware Doom has the same PNAMES lump as the registered - // Doom, so printing warnings for patches that don't really - // exist isn't such a good idea. - //Printf ("Patch %s not found.\n", patchlookup[i].Name); - patchlookup[i].Texture = NULL; - } - } - } - - bool isStrife = false; - const DWORD *maptex, *directory; - DWORD maxoff; - int numtextures; - DWORD offset = 0; // Shut up, GCC! - - maptex = (const DWORD *)lumpdata; - numtextures = LittleLong(*maptex); - maxoff = lumpsize; - - if (maxoff < DWORD(numtextures+1)*4) - { - Printf ("Texture directory is too short"); - delete[] patchlookup; - return; - } - - // Scan the texture lump to decide if it contains Doom or Strife textures - for (i = 0, directory = maptex+1; i < numtextures; ++i) - { - offset = LittleLong(directory[i]); - if (offset > maxoff) - { - Printf ("Bad texture directory"); - delete[] patchlookup; - return; - } - - maptexture_t *tex = (maptexture_t *)((BYTE *)maptex + offset); - - // There is bizzarely a Doom editing tool that writes to the - // first two elements of columndirectory, so I can't check those. - if (SAFESHORT(tex->patchcount) < 0 || - tex->columndirectory[2] != 0 || - tex->columndirectory[3] != 0) - { - isStrife = true; - break; - } - } - - - // Textures defined earlier in the lump take precedence over those defined later, - // but later TEXTUREx lumps take precedence over earlier ones. - for (i = 1, directory = maptex; i <= numtextures; ++i) - { - if (i == 1 && texture1) - { - // The very first texture is just a dummy. Copy its dimensions to texture 0. - // It still needs to be created in case someone uses it by name. - offset = LittleLong(directory[1]); - const maptexture_t *tex = (const maptexture_t *)((const BYTE *)maptex + offset); - FDummyTexture *tex0 = static_cast(Textures[0].Texture); - tex0->SetSize (SAFESHORT(tex->width), SAFESHORT(tex->height)); - } - - offset = LittleLong(directory[i]); - if (offset > maxoff) - { - Printf ("Bad texture directory"); - delete[] patchlookup; - return; - } - - // If this texture was defined already in this lump, skip it - // This could cause problems with animations that use the same name for intermediate - // textures. Should I be worried? - int j; - for (j = (int)Textures.Size() - 1; j >= firstdup; --j) - { - if (strnicmp (Textures[j].Texture->Name, (const char *)maptex + offset, 8) == 0) - break; - } - if (j + 1 == firstdup) - { - FMultiPatchTexture *tex = new FMultiPatchTexture ((const BYTE *)maptex + offset, patchlookup, numpatches, isStrife, deflumpnum); - if (i == 1 && texture1) - { - tex->UseType = FTexture::TEX_FirstDefined; - } - TexMan.AddTexture (tex); - StartScreen->Progress(); - } - } - delete[] patchlookup; -} - - -//========================================================================== -// -// FTextureManager :: AddTexturesLumps -// -//========================================================================== - -void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) -{ - int firstdup = (int)Textures.Size(); - - if (lump1 >= 0) - { - FMemLump texdir = Wads.ReadLump (lump1); - AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump1), lump1, patcheslump, firstdup, true); - } - if (lump2 >= 0) - { - FMemLump texdir = Wads.ReadLump (lump2); - AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump2), lump2, patcheslump, firstdup, false); - } -} - - -//========================================================================== -// -// -// -//========================================================================== - -void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) -{ - FString patchname; - sc.MustGetString(); - - FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); - int Mirror = 0; - - if (!texno.isValid()) - { - if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) - { - int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); - if (lumpnum >= 0) - { - part.Texture = FTexture::CreateTexture(lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - } - else - { - part.Texture = TexMan[texno]; - bComplex |= part.Texture->bComplex; - } - if (part.Texture == NULL) - { - if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); - } - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.OriginX = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.OriginY = sc.Number; - - if (sc.CheckString("{")) - { - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (sc.Compare("flipx")) - { - Mirror |= 1; - } - else if (sc.Compare("flipy")) - { - Mirror |= 2; - } - else if (sc.Compare("rotate")) - { - sc.MustGetNumber(); - sc.Number = (((sc.Number + 90)%360)-90); - if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90) - { - sc.ScriptError("Rotation must be a multiple of 90 degrees."); - } - part.Rotate = (sc.Number / 90) & 3; - } - else if (sc.Compare("Translation")) - { - int match; - - bComplex = true; - if (part.Translation != NULL) delete part.Translation; - part.Translation = NULL; - part.Blend = 0; - static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL }; - sc.MustGetString(); - - match = sc.MatchString(maps); - if (match >= 0) - { - part.Blend = BLEND_SPECIALCOLORMAP1 + match; - } - else if (sc.Compare("ICE")) - { - part.Blend = BLEND_ICEMAP; - } - else if (sc.Compare("DESATURATE")) - { - sc.MustGetStringName(","); - sc.MustGetNumber(); - part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30); - } - else - { - sc.UnGet(); - part.Translation = new FRemapTable; - part.Translation->MakeIdentity(); - do - { - sc.MustGetString(); - part.Translation->AddToTranslation(sc.String); - } - while (sc.CheckString(",")); - } - - } - else if (sc.Compare("Colormap")) - { - float r1,g1,b1; - float r2,g2,b2; - - sc.MustGetFloat(); - r1 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - g1 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - b1 = (float)sc.Float; - if (!sc.CheckString(",")) - { - part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1); - } - else - { - sc.MustGetFloat(); - r2 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - g2 = (float)sc.Float; - sc.MustGetStringName(","); - sc.MustGetFloat(); - b2 = (float)sc.Float; - part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2); - } - } - else if (sc.Compare("Blend")) - { - bComplex = true; - if (part.Translation != NULL) delete part.Translation; - part.Translation = NULL; - part.Blend = 0; - - if (!sc.CheckNumber()) - { - sc.MustGetString(); - part.Blend = V_GetColor(NULL, sc.String); - } - else - { - int r,g,b; - - r = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - g = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - b = sc.Number; - sc.MustGetStringName(","); - part.Blend = MAKERGB(r, g, b); - } - // Blend.a may never be 0 here. - if (sc.CheckString(",")) - { - sc.MustGetFloat(); - if (sc.Float > 0.f) - part.Blend.a = clamp(int(sc.Float*255), 1, 254); - else - part.Blend = 0; - } - else part.Blend.a = 255; - } - else if (sc.Compare("alpha")) - { - sc.MustGetFloat(); - part.Alpha = clamp(FLOAT2FIXED(sc.Float), 0, FRACUNIT); - // bComplex is not set because it is only needed when the style is not OP_COPY. - } - else if (sc.Compare("style")) - { - static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL }; - sc.MustGetString(); - part.op = sc.MustMatchString(styles); - bComplex |= (part.op != OP_COPY); - bTranslucentPatches = bComplex; - } - else if (sc.Compare("useoffsets")) - { - if (part.Texture != NULL) - { - part.OriginX -= part.Texture->LeftOffset; - part.OriginY -= part.Texture->TopOffset; - } - } - } - } - if (Mirror & 2) - { - part.Rotate = (part.Rotate + 2) & 3; - Mirror ^= 1; - } - if (Mirror & 1) - { - part.Rotate |= 4; - } -} - -//========================================================================== -// -// Constructor for text based multipatch definitions -// -//========================================================================== - -FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) -{ - TArray parts; - bool bSilent = false; - - bMultiPatch = true; - sc.SetCMode(true); - sc.MustGetString(); - const char* textureName = NULL; - if (sc.Compare("optional")) - { - bSilent = true; - sc.MustGetString(); - if (sc.Compare(",")) - { - // this is not right. Apparently a texture named 'optional' is being defined right now... - sc.UnGet(); - textureName = "optional"; - bSilent = false; - } - } - Name = !textureName ? sc.String : textureName; - Name.ToUpper(); - sc.MustGetStringName(","); - sc.MustGetNumber(); - Width = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - Height = sc.Number; - UseType = usetype; - - if (sc.CheckString("{")) - { - while (!sc.CheckString("}")) - { - sc.MustGetString(); - if (sc.Compare("XScale")) - { - sc.MustGetFloat(); - xScale = FLOAT2FIXED(sc.Float); - if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); - } - else if (sc.Compare("YScale")) - { - sc.MustGetFloat(); - yScale = FLOAT2FIXED(sc.Float); - if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); - } - else if (sc.Compare("WorldPanning")) - { - bWorldPanning = true; - } - else if (sc.Compare("NullTexture")) - { - UseType = FTexture::TEX_Null; - } - else if (sc.Compare("NoDecals")) - { - bNoDecals = true; - } - else if (sc.Compare("Patch")) - { - TexPart part; - ParsePatch(sc, part, bSilent, TEX_WallPatch); - if (part.Texture != NULL) parts.Push(part); - part.Texture = NULL; - part.Translation = NULL; - } - else if (sc.Compare("Graphic")) - { - TexPart part; - ParsePatch(sc, part, bSilent, TEX_MiscPatch); - if (part.Texture != NULL) parts.Push(part); - part.Texture = NULL; - part.Translation = NULL; - } - else if (sc.Compare("Offset")) - { - sc.MustGetNumber(); - LeftOffset = sc.Number; - sc.MustGetStringName(","); - sc.MustGetNumber(); - TopOffset = sc.Number; - } - else - { - sc.ScriptError("Unknown texture property '%s'", sc.String); - } - } - - NumParts = parts.Size(); - Parts = new TexPart[NumParts]; - memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); - - //CalcBitSize (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height && - Parts->Rotate == 0 && - !bComplex) - { - bRedirect = true; - } - } - } - - if (Width <= 0 || Height <= 0) - { - UseType = FTexture::TEX_Null; - Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); - Width = Height = 1; - } - CalcBitSize (); - - - sc.SetCMode(false); -} - - - -void FTextureManager::ParseXTexture(FScanner &sc, int usetype) -{ - FTexture *tex = new FMultiPatchTexture(sc, usetype); - TexMan.AddTexture (tex); -} + WORD Flags; // [RH] Was unused + BYTE ScaleX; // [RH] Scaling (8 is normal) + BYTE ScaleY; // [RH] Same as above + SWORD width; + SWORD height; + BYTE columndirectory[4]; // OBSOLETE + SWORD patchcount; + mappatch_t patches[1]; +}; + +#define MAPTEXF_WORLDPANNING 0x8000 + +// Strife uses versions of the above structures that remove all unused fields + +struct strifemappatch_t +{ + SWORD originx; + SWORD originy; + SWORD patch; +}; + +// +// A wall texture is a list of patches which are to be combined in a +// predefined order. +// +struct strifemaptexture_t +{ + BYTE name[8]; + WORD Flags; // [RH] Was unused + BYTE ScaleX; // [RH] Scaling (8 is normal) + BYTE ScaleY; // [RH] Same as above + SWORD width; + SWORD height; + SWORD patchcount; + strifemappatch_t patches[1]; +}; + + +//========================================================================== +// +// In-memory representation of a single PNAMES lump entry +// +//========================================================================== + +struct FPatchLookup +{ + FString Name; + FTexture *Texture; +}; + + +//========================================================================== +// +// A texture defined in a TEXTURE1 or TEXTURE2 lump +// +//========================================================================== + +class FMultiPatchTexture : public FTexture +{ +public: + FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); + FMultiPatchTexture (FScanner &sc, int usetype); + ~FMultiPatchTexture (); + + const BYTE *GetColumn (unsigned int column, const Span **spans_out); + const BYTE *GetPixels (); + FTextureFormat GetFormat(); + bool UseBasePalette() ; + void Unload (); + virtual void SetFrontSkyLayer (); + + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); + int GetSourceLump() { return DefinitionLump; } + FTexture *GetRedirect(bool wantwarped); + FTexture *GetRawTexture(); + +protected: + BYTE *Pixels; + Span **Spans; + int DefinitionLump; + + struct TexPart + { + SWORD OriginX, OriginY; + BYTE Rotate; + BYTE op; + FRemapTable *Translation; + PalEntry Blend; + FTexture *Texture; + fixed_t Alpha; + + TexPart(); + }; + + int NumParts; + TexPart *Parts; + bool bRedirect:1; + bool bTranslucentPatches:1; + + void MakeTexture (); + +private: + void CheckForHacks (); + void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); +}; + +//========================================================================== +// +// FMultiPatchTexture :: FMultiPatchTexture +// +//========================================================================== + +FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +{ + union + { + const maptexture_t *d; + const strifemaptexture_t *s; + } + mtexture; + + union + { + const mappatch_t *d; + const strifemappatch_t *s; + } + mpatch; + + int i; + + mtexture.d = (const maptexture_t *)texdef; + bMultiPatch = true; + + if (strife) + { + NumParts = SAFESHORT(mtexture.s->patchcount); + } + else + { + NumParts = SAFESHORT(mtexture.d->patchcount); + } + + if (NumParts < 0) + { + I_FatalError ("Bad texture directory"); + } + + UseType = FTexture::TEX_Wall; + Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; + Width = SAFESHORT(mtexture.d->width); + Height = SAFESHORT(mtexture.d->height); + Name = (char *)mtexture.d->name; + CalcBitSize (); + + xScale = mtexture.d->ScaleX ? mtexture.d->ScaleX*(FRACUNIT/8) : FRACUNIT; + yScale = mtexture.d->ScaleY ? mtexture.d->ScaleY*(FRACUNIT/8) : FRACUNIT; + + if (mtexture.d->Flags & MAPTEXF_WORLDPANNING) + { + bWorldPanning = true; + } + + if (strife) + { + mpatch.s = &mtexture.s->patches[0]; + } + else + { + mpatch.d = &mtexture.d->patches[0]; + } + + for (i = 0; i < NumParts; ++i) + { + if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) + { + I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", + maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); + } + Parts[i].OriginX = LittleShort(mpatch.d->originx); + Parts[i].OriginY = LittleShort(mpatch.d->originy); + Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; + if (Parts[i].Texture == NULL) + { + Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); + NumParts--; + i--; + } + else + { + Parts[i].Texture->bKeepAround = true; + } + if (strife) + mpatch.s++; + else + mpatch.d++; + } + if (NumParts == 0) + { + Printf ("Texture %s is left without any patches\n", Name); + } + + CheckForHacks (); + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height) + { + bRedirect = true; + } + } + DefinitionLump = deflumpnum; +} + +//========================================================================== +// +// FMultiPatchTexture :: ~FMultiPatchTexture +// +//========================================================================== + +FMultiPatchTexture::~FMultiPatchTexture () +{ + Unload (); + if (Parts != NULL) + { + for(int i=0; iSetFrontSkyLayer (); + } + bNoRemap0 = true; +} + +//========================================================================== +// +// FMultiPatchTexture :: Unload +// +//========================================================================== + +void FMultiPatchTexture::Unload () +{ + if (Pixels != NULL) + { + delete[] Pixels; + Pixels = NULL; + } +} + +//========================================================================== +// +// FMultiPatchTexture :: GetPixels +// +//========================================================================== + +const BYTE *FMultiPatchTexture::GetPixels () +{ + if (bRedirect) + { + return Parts->Texture->GetPixels (); + } + if (Pixels == NULL) + { + MakeTexture (); + } + return Pixels; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetColumn +// +//========================================================================== + +const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spans_out) +{ + if (bRedirect) + { + return Parts->Texture->GetColumn (column, spans_out); + } + if (Pixels == NULL) + { + MakeTexture (); + } + if ((unsigned)column >= (unsigned)Width) + { + if (WidthMask + 1 == Width) + { + column &= WidthMask; + } + else + { + column %= Width; + } + } + if (spans_out != NULL) + { + if (Spans == NULL) + { + Spans = CreateSpans (Pixels); + } + *spans_out = Spans[column]; + } + return Pixels + column*Height; +} + + +//========================================================================== +// +// GetBlendMap +// +//========================================================================== + +BYTE *GetBlendMap(PalEntry blend, BYTE *blendwork) +{ + + switch (blend.a==0 ? int(blend) : -1) + { + case BLEND_ICEMAP: + return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap; + + default: + if (blend >= BLEND_SPECIALCOLORMAP1 && blend < BLEND_SPECIALCOLORMAP1 + SpecialColormaps.Size()) + { + return SpecialColormaps[blend - BLEND_SPECIALCOLORMAP1].Colormap; + } + else if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31) + { + return DesaturateColormap[blend - BLEND_DESATURATE1]; + } + else + { + blendwork[0]=0; + if (blend.a == 255) + { + for(int i=1;i<256;i++) + { + int rr = (blend.r * GPalette.BaseColors[i].r) / 255; + int gg = (blend.g * GPalette.BaseColors[i].g) / 255; + int bb = (blend.b * GPalette.BaseColors[i].b) / 255; + + blendwork[i] = ColorMatcher.Pick(rr, gg, bb); + } + return blendwork; + } + else if (blend.a != 0) + { + for(int i=1;i<256;i++) + { + int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255; + int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255; + int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255; + + blendwork[i] = ColorMatcher.Pick(rr, gg, bb); + } + return blendwork; + } + } + } + return NULL; +} + +//========================================================================== +// +// FMultiPatchTexture :: MakeTexture +// +//========================================================================== + +void FMultiPatchTexture::MakeTexture () +{ + // Add a little extra space at the end if the texture's height is not + // a power of 2, in case somebody accidentally makes it repeat vertically. + int numpix = Width * Height + (1 << HeightBits) - Height; + BYTE blendwork[256]; + bool hasTranslucent = false; + + Pixels = new BYTE[numpix]; + memset (Pixels, 0, numpix); + + for (int i = 0; i < NumParts; ++i) + { + if (Parts[i].op != OP_COPY) + { + hasTranslucent = true; + } + } + + if (!hasTranslucent) + { + for (int i = 0; i < NumParts; ++i) + { + if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. + + BYTE *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; + { + if (Parts[i].Blend != 0) + { + trans = GetBlendMap(Parts[i].Blend, blendwork); + } + Parts[i].Texture->CopyToBlock (Pixels, Width, Height, + Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans); + } + } + } + else + { + // In case there are translucent patches let's do the composition in + // True color to keep as much precision as possible before downconverting to the palette. + BYTE *buffer = new BYTE[Width * Height * 4]; + memset(buffer, 0, Width * Height * 4); + FillBuffer(buffer, Width * 4, Height, TEX_RGB); + for(int y = 0; y < Height; y++) + { + BYTE *in = buffer + Width * y * 4; + BYTE *out = Pixels + y; + for (int x = 0; x < Width; x++) + { + if (*out == 0 && in[3] != 0) + { + *out = RGB32k[in[2]>>3][in[1]>>3][in[0]>>3]; + } + out += Height; + in += 4; + } + } + delete [] buffer; + } +} + +//=========================================================================== +// +// FMultipatchTexture::CopyTrueColorPixels +// +// Preserves the palettes of each individual patch +// +//=========================================================================== + +int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) +{ + int retv = -1; + + if (bRedirect) + { // Redirect straight to the real texture's routine. + return Parts[0].Texture->CopyTrueColorPixels(bmp, x, y, rotate, inf); + } + + if (rotate != 0 || (inf != NULL && ((inf->op != OP_OVERWRITE && inf->op != OP_COPY) || inf->blend != BLEND_NONE))) + { // We are doing some sort of fancy stuff to the destination bitmap, so composite to + // a temporary bitmap, and copy that. + FBitmap tbmp; + if (tbmp.Create(Width, Height)) + { + retv = MAX(retv, CopyTrueColorPixels(&tbmp, 0, 0, 0)); + bmp->CopyPixelDataRGB(x, y, tbmp.GetPixels(), Width, Height, + 4, tbmp.GetPitch(), rotate, CF_BGRA, inf); + } + return retv; + } + + // When compositing a multipatch texture with multipatch parts, + // drawing must be restricted to the actual area which is covered by this texture. + FClipRect saved_cr = bmp->GetClipRect(); + bmp->IntersectClipRect(x, y, Width, Height); + + if (inf != NULL && inf->op == OP_OVERWRITE) + { + bmp->Zero(); + } + + for(int i = 0; i < NumParts; i++) + { + int ret = -1; + FCopyInfo info; + + if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. + + memset (&info, 0, sizeof(info)); + info.alpha = Parts[i].Alpha; + info.invalpha = FRACUNIT - info.alpha; + info.op = ECopyOp(Parts[i].op); + PalEntry b = Parts[i].Blend; + if (b.a == 0 && b != BLEND_NONE) + { + info.blend = EBlend(b.d); + } + else if (b.a != 0) + { + if (b.a == 255) + { + info.blendcolor[0] = b.r * FRACUNIT / 255; + info.blendcolor[1] = b.g * FRACUNIT / 255; + info.blendcolor[2] = b.b * FRACUNIT / 255; + info.blend = BLEND_MODULATE; + } + else + { + fixed_t blendalpha = b.a * FRACUNIT / 255; + info.blendcolor[0] = b.r * blendalpha; + info.blendcolor[1] = b.g * blendalpha; + info.blendcolor[2] = b.b * blendalpha; + info.blendcolor[3] = FRACUNIT - blendalpha; + info.blend = BLEND_OVERLAY; + } + } + + if (Parts[i].Translation != NULL) + { // Using a translation forces downconversion to the base palette + ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation, &info); + } + else + { + ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, &info); + } + + if (ret > retv) retv = ret; + } + // Restore previous clipping rectangle. + bmp->SetClipRect(saved_cr); + return retv; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetFormat +// +// only returns 'paletted' if all patches use the base palette. +// +//========================================================================== + +FTextureFormat FMultiPatchTexture::GetFormat() +{ + if (bComplex) return TEX_RGB; + if (NumParts == 1) return Parts[0].Texture->GetFormat(); + return UseBasePalette() ? TEX_Pal : TEX_RGB; +} + + +//=========================================================================== +// +// FMultipatchTexture::UseBasePalette +// +// returns true if all patches in the texture use the unmodified base +// palette. +// +//=========================================================================== + +bool FMultiPatchTexture::UseBasePalette() +{ + if (bComplex) return false; + for(int i=0;iUseBasePalette()) return false; + } + return true; +} + +//========================================================================== +// +// FMultiPatchTexture :: CheckForHacks +// +//========================================================================== + +void FMultiPatchTexture::CheckForHacks () +{ + if (NumParts <= 0) + { + return; + } + + // Heretic sky textures are marked as only 128 pixels tall, + // even though they are really 200 pixels tall. + if (gameinfo.gametype == GAME_Heretic && + Name[0] == 'S' && + Name[1] == 'K' && + Name[2] == 'Y' && + Name[4] == 0 && + Name[3] >= '1' && + Name[3] <= '3' && + Height == 128) + { + Height = 200; + HeightBits = 8; + return; + } + + // The Doom E1 sky has its patch's y offset at -8 instead of 0. + if (gameinfo.gametype == GAME_Doom && + !(gameinfo.flags & GI_MAPxx) && + NumParts == 1 && + Height == 128 && + Parts->OriginY == -8 && + Name[0] == 'S' && + Name[1] == 'K' && + Name[2] == 'Y' && + Name[3] == '1' && + Name[4] == 0) + { + Parts->OriginY = 0; + return; + } + + // BIGDOOR7 in Doom also has patches at y offset -4 instead of 0. + if (gameinfo.gametype == GAME_Doom && + !(gameinfo.flags & GI_MAPxx) && + NumParts == 2 && + Height == 128 && + Parts[0].OriginY == -4 && + Parts[1].OriginY == -4 && + Name[0] == 'B' && + Name[1] == 'I' && + Name[2] == 'G' && + Name[3] == 'D' && + Name[4] == 'O' && + Name[5] == 'O' && + Name[6] == 'R' && + Name[7] == '7') + { + Parts[0].OriginY = 0; + Parts[1].OriginY = 0; + return; + } + + // [RH] Some wads (I forget which!) have single-patch textures 256 + // pixels tall that have patch lengths recorded as 0. I can't think of + // any good reason for them to do this, and since I didn't make note + // of which wad made me hack in support for them, the hack is gone + // because I've added support for DeePsea's true tall patches. + // + // Okay, I found a wad with crap patches: Pleiades.wad's sky patches almost + // fit this description and are a big mess, but they're not single patch! + if (Height == 256) + { + int i; + + // All patches must be at the top of the texture for this fix + for (i = 0; i < NumParts; ++i) + { + if (Parts[i].OriginY != 0) + { + break; + } + } + + if (i == NumParts) + { + for (i = 0; i < NumParts; ++i) + { + Parts[i].Texture->HackHack(256); + } + } + } +} + +//========================================================================== +// +// FMultiPatchTexture :: GetRedirect +// +//========================================================================== + +FTexture *FMultiPatchTexture::GetRedirect(bool wantwarped) +{ + return bRedirect ? Parts->Texture : this; +} + +//========================================================================== +// +// FMultiPatchTexture :: GetRawTexture +// +// Doom ignored all compositing of mid-sided textures on two-sided lines. +// Since these textures had to be single-patch in Doom, that essentially +// means it ignores their Y offsets. +// +// If this texture is composed of only one patch, return that patch. +// Otherwise, return this texture, since Doom wouldn't have been able to +// draw it anyway. +// +//========================================================================== + +FTexture *FMultiPatchTexture::GetRawTexture() +{ + return NumParts == 1 ? Parts->Texture : this; +} + +//========================================================================== +// +// FMultiPatchTexture :: TexPart :: TexPart +// +//========================================================================== + +FMultiPatchTexture::TexPart::TexPart() +{ + OriginX = OriginY = 0; + Rotate = 0; + Texture = NULL; + Translation = NULL; + Blend = 0; + Alpha = FRACUNIT; + op = OP_COPY; +} + +//========================================================================== +// +// FTextureManager :: AddTexturesLump +// +//========================================================================== + +void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup, bool texture1) +{ + FPatchLookup *patchlookup = NULL; + int i; + DWORD numpatches; + + if (firstdup == 0) + { + firstdup = (int)Textures.Size(); + } + + { + FWadLump pnames = Wads.OpenLumpNum (patcheslump); + + pnames >> numpatches; + + // Check whether the amount of names reported is correct. + if ((signed)numpatches < 0) + { + Printf("Corrupt PNAMES lump found (negative amount of entries reported)"); + return; + } + + // Check whether the amount of names reported is correct. + int lumplength = Wads.LumpLength(patcheslump); + if (numpatches > DWORD((lumplength-4)/8)) + { + Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", + numpatches, lumplength, (lumplength-4)/8); + // Truncate but continue reading. Who knows how many such lumps exist? + numpatches = (lumplength-4)/8; + } + + // Catalog the patches these textures use so we know which + // textures they represent. + patchlookup = new FPatchLookup[numpatches]; + for (DWORD i = 0; i < numpatches; ++i) + { + char pname[9]; + pnames.Read(pname, 8); + pname[8] = '\0'; + patchlookup[i].Name = pname; + FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); + if (j.isValid()) + { + patchlookup[i].Texture = Textures[j.GetIndex()].Texture; + } + else + { + // Shareware Doom has the same PNAMES lump as the registered + // Doom, so printing warnings for patches that don't really + // exist isn't such a good idea. + //Printf ("Patch %s not found.\n", patchlookup[i].Name); + patchlookup[i].Texture = NULL; + } + } + } + + bool isStrife = false; + const DWORD *maptex, *directory; + DWORD maxoff; + int numtextures; + DWORD offset = 0; // Shut up, GCC! + + maptex = (const DWORD *)lumpdata; + numtextures = LittleLong(*maptex); + maxoff = lumpsize; + + if (maxoff < DWORD(numtextures+1)*4) + { + Printf ("Texture directory is too short"); + delete[] patchlookup; + return; + } + + // Scan the texture lump to decide if it contains Doom or Strife textures + for (i = 0, directory = maptex+1; i < numtextures; ++i) + { + offset = LittleLong(directory[i]); + if (offset > maxoff) + { + Printf ("Bad texture directory"); + delete[] patchlookup; + return; + } + + maptexture_t *tex = (maptexture_t *)((BYTE *)maptex + offset); + + // There is bizzarely a Doom editing tool that writes to the + // first two elements of columndirectory, so I can't check those. + if (SAFESHORT(tex->patchcount) < 0 || + tex->columndirectory[2] != 0 || + tex->columndirectory[3] != 0) + { + isStrife = true; + break; + } + } + + + // Textures defined earlier in the lump take precedence over those defined later, + // but later TEXTUREx lumps take precedence over earlier ones. + for (i = 1, directory = maptex; i <= numtextures; ++i) + { + if (i == 1 && texture1) + { + // The very first texture is just a dummy. Copy its dimensions to texture 0. + // It still needs to be created in case someone uses it by name. + offset = LittleLong(directory[1]); + const maptexture_t *tex = (const maptexture_t *)((const BYTE *)maptex + offset); + FDummyTexture *tex0 = static_cast(Textures[0].Texture); + tex0->SetSize (SAFESHORT(tex->width), SAFESHORT(tex->height)); + } + + offset = LittleLong(directory[i]); + if (offset > maxoff) + { + Printf ("Bad texture directory"); + delete[] patchlookup; + return; + } + + // If this texture was defined already in this lump, skip it + // This could cause problems with animations that use the same name for intermediate + // textures. Should I be worried? + int j; + for (j = (int)Textures.Size() - 1; j >= firstdup; --j) + { + if (strnicmp (Textures[j].Texture->Name, (const char *)maptex + offset, 8) == 0) + break; + } + if (j + 1 == firstdup) + { + FMultiPatchTexture *tex = new FMultiPatchTexture ((const BYTE *)maptex + offset, patchlookup, numpatches, isStrife, deflumpnum); + if (i == 1 && texture1) + { + tex->UseType = FTexture::TEX_FirstDefined; + } + TexMan.AddTexture (tex); + StartScreen->Progress(); + } + } + delete[] patchlookup; +} + + +//========================================================================== +// +// FTextureManager :: AddTexturesLumps +// +//========================================================================== + +void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) +{ + int firstdup = (int)Textures.Size(); + + if (lump1 >= 0) + { + FMemLump texdir = Wads.ReadLump (lump1); + AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump1), lump1, patcheslump, firstdup, true); + } + if (lump2 >= 0) + { + FMemLump texdir = Wads.ReadLump (lump2); + AddTexturesLump (texdir.GetMem(), Wads.LumpLength (lump2), lump2, patcheslump, firstdup, false); + } +} + + +//========================================================================== +// +// +// +//========================================================================== + +void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) +{ + FString patchname; + sc.MustGetString(); + + FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); + int Mirror = 0; + + if (!texno.isValid()) + { + if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) + { + int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); + if (lumpnum >= 0) + { + part.Texture = FTexture::CreateTexture(lumpnum, usetype); + TexMan.AddTexture(part.Texture); + } + } + } + else + { + part.Texture = TexMan[texno]; + bComplex |= part.Texture->bComplex; + } + if (part.Texture == NULL) + { + if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); + } + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginX = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginY = sc.Number; + + if (sc.CheckString("{")) + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("flipx")) + { + Mirror |= 1; + } + else if (sc.Compare("flipy")) + { + Mirror |= 2; + } + else if (sc.Compare("rotate")) + { + sc.MustGetNumber(); + sc.Number = (((sc.Number + 90)%360)-90); + if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90) + { + sc.ScriptError("Rotation must be a multiple of 90 degrees."); + } + part.Rotate = (sc.Number / 90) & 3; + } + else if (sc.Compare("Translation")) + { + int match; + + bComplex = true; + if (part.Translation != NULL) delete part.Translation; + part.Translation = NULL; + part.Blend = 0; + static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL }; + sc.MustGetString(); + + match = sc.MatchString(maps); + if (match >= 0) + { + part.Blend = BLEND_SPECIALCOLORMAP1 + match; + } + else if (sc.Compare("ICE")) + { + part.Blend = BLEND_ICEMAP; + } + else if (sc.Compare("DESATURATE")) + { + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30); + } + else + { + sc.UnGet(); + part.Translation = new FRemapTable; + part.Translation->MakeIdentity(); + do + { + sc.MustGetString(); + part.Translation->AddToTranslation(sc.String); + } + while (sc.CheckString(",")); + } + + } + else if (sc.Compare("Colormap")) + { + float r1,g1,b1; + float r2,g2,b2; + + sc.MustGetFloat(); + r1 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + g1 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + b1 = (float)sc.Float; + if (!sc.CheckString(",")) + { + part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1); + } + else + { + sc.MustGetFloat(); + r2 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + g2 = (float)sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + b2 = (float)sc.Float; + part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2); + } + } + else if (sc.Compare("Blend")) + { + bComplex = true; + if (part.Translation != NULL) delete part.Translation; + part.Translation = NULL; + part.Blend = 0; + + if (!sc.CheckNumber()) + { + sc.MustGetString(); + part.Blend = V_GetColor(NULL, sc.String); + } + else + { + int r,g,b; + + r = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + g = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + b = sc.Number; + sc.MustGetStringName(","); + part.Blend = MAKERGB(r, g, b); + } + // Blend.a may never be 0 here. + if (sc.CheckString(",")) + { + sc.MustGetFloat(); + if (sc.Float > 0.f) + part.Blend.a = clamp(int(sc.Float*255), 1, 254); + else + part.Blend = 0; + } + else part.Blend.a = 255; + } + else if (sc.Compare("alpha")) + { + sc.MustGetFloat(); + part.Alpha = clamp(FLOAT2FIXED(sc.Float), 0, FRACUNIT); + // bComplex is not set because it is only needed when the style is not OP_COPY. + } + else if (sc.Compare("style")) + { + static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL }; + sc.MustGetString(); + part.op = sc.MustMatchString(styles); + bComplex |= (part.op != OP_COPY); + bTranslucentPatches = bComplex; + } + else if (sc.Compare("useoffsets")) + { + if (part.Texture != NULL) + { + part.OriginX -= part.Texture->LeftOffset; + part.OriginY -= part.Texture->TopOffset; + } + } + } + } + if (Mirror & 2) + { + part.Rotate = (part.Rotate + 2) & 3; + Mirror ^= 1; + } + if (Mirror & 1) + { + part.Rotate |= 4; + } +} + +//========================================================================== +// +// Constructor for text based multipatch definitions +// +//========================================================================== + +FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) +: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +{ + TArray parts; + bool bSilent = false; + + bMultiPatch = true; + sc.SetCMode(true); + sc.MustGetString(); + const char* textureName = NULL; + if (sc.Compare("optional")) + { + bSilent = true; + sc.MustGetString(); + if (sc.Compare(",")) + { + // this is not right. Apparently a texture named 'optional' is being defined right now... + sc.UnGet(); + textureName = "optional"; + bSilent = false; + } + } + Name = !textureName ? sc.String : textureName; + Name.ToUpper(); + sc.MustGetStringName(","); + sc.MustGetNumber(); + Width = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + Height = sc.Number; + UseType = usetype; + + if (sc.CheckString("{")) + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("XScale")) + { + sc.MustGetFloat(); + xScale = FLOAT2FIXED(sc.Float); + if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); + } + else if (sc.Compare("YScale")) + { + sc.MustGetFloat(); + yScale = FLOAT2FIXED(sc.Float); + if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); + } + else if (sc.Compare("WorldPanning")) + { + bWorldPanning = true; + } + else if (sc.Compare("NullTexture")) + { + UseType = FTexture::TEX_Null; + } + else if (sc.Compare("NoDecals")) + { + bNoDecals = true; + } + else if (sc.Compare("Patch")) + { + TexPart part; + ParsePatch(sc, part, bSilent, TEX_WallPatch); + if (part.Texture != NULL) parts.Push(part); + part.Texture = NULL; + part.Translation = NULL; + } + else if (sc.Compare("Graphic")) + { + TexPart part; + ParsePatch(sc, part, bSilent, TEX_MiscPatch); + if (part.Texture != NULL) parts.Push(part); + part.Texture = NULL; + part.Translation = NULL; + } + else if (sc.Compare("Offset")) + { + sc.MustGetNumber(); + LeftOffset = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + TopOffset = sc.Number; + } + else + { + sc.ScriptError("Unknown texture property '%s'", sc.String); + } + } + + NumParts = parts.Size(); + Parts = new TexPart[NumParts]; + memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); + + //CalcBitSize (); + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height && + Parts->Rotate == 0 && + !bComplex) + { + bRedirect = true; + } + } + } + + if (Width <= 0 || Height <= 0) + { + UseType = FTexture::TEX_Null; + Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); + Width = Height = 1; + } + CalcBitSize (); + + + sc.SetCMode(false); +} + + + +void FTextureManager::ParseXTexture(FScanner &sc, int usetype) +{ + FTexture *tex = new FMultiPatchTexture(sc, usetype); + TexMan.AddTexture (tex); +} From 8ec95dc58eba6a0197b733ff2a6f7a3dc5b6b36b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 20 May 2014 10:14:44 +0200 Subject: [PATCH 233/247] - fixed a few places in the savegame code where map names were still truncated to 8 characters. --- src/g_level.cpp | 109 ++++++++++++++++++++++++++---------------------- src/version.h | 2 +- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 8c97a399c..c4aafda4b 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1597,30 +1597,9 @@ void G_UnSnapshotLevel (bool hubLoad) // //========================================================================== -static void writeMapName (FArchive &arc, const char *name) -{ - BYTE size; - if (name[7] != 0) - { - size = 8; - } - else - { - size = (BYTE)strlen (name); - } - arc << size; - arc.Write (name, size); -} - -//========================================================================== -// -// -//========================================================================== - static void writeSnapShot (FArchive &arc, level_info_t *i) { - arc << i->snapshotVer; - writeMapName (arc, i->MapName); + arc << i->snapshotVer << i->MapName; i->snapshot->Serialize (arc); } @@ -1658,14 +1637,14 @@ void G_WriteSnapshots (FILE *file) { arc = new FPNGChunkArchive (file, VIST_ID); } - writeMapName (*arc, wadlevelinfos[i].MapName); + (*arc) << wadlevelinfos[i].MapName; } } if (arc != NULL) { - BYTE zero = 0; - *arc << zero; + FString empty = ""; + (*arc) << empty; delete arc; } @@ -1706,6 +1685,7 @@ void G_ReadSnapshots (PNGHandle *png) DWORD chunkLen; BYTE namelen; char mapname[256]; + FString MapName; level_info_t *i; G_ClearSnapshots (); @@ -1717,10 +1697,15 @@ void G_ReadSnapshots (PNGHandle *png) DWORD snapver; arc << snapver; - arc << namelen; - arc.Read (mapname, namelen); - mapname[namelen] = 0; - i = FindLevelInfo (mapname); + if (SaveVersion < 4508) + { + arc << namelen; + arc.Read(mapname, namelen); + mapname[namelen] = 0; + MapName = mapname; + } + else arc << MapName; + i = FindLevelInfo (MapName); i->snapshotVer = snapver; i->snapshot = new FCompressedMemFile; i->snapshot->Serialize (arc); @@ -1746,14 +1731,25 @@ void G_ReadSnapshots (PNGHandle *png) { FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen); - arc << namelen; - while (namelen != 0) + if (SaveVersion < 4508) { - arc.Read (mapname, namelen); - mapname[namelen] = 0; - i = FindLevelInfo (mapname); - i->flags |= LEVEL_VISITED; arc << namelen; + while (namelen != 0) + { + arc.Read(mapname, namelen); + mapname[namelen] = 0; + i = FindLevelInfo(mapname); + i->flags |= LEVEL_VISITED; + arc << namelen; + } + } + else + { + while (arc << MapName, MapName.Len() > 0) + { + i = FindLevelInfo(MapName); + i->flags |= LEVEL_VISITED; + } } } @@ -1809,8 +1805,7 @@ CCMD(listsnapshots) static void writeDefereds (FArchive &arc, level_info_t *i) { - writeMapName (arc, i->MapName); - arc << i->defered; + arc << i->MapName << i->defered; } //========================================================================== @@ -1837,8 +1832,8 @@ void P_WriteACSDefereds (FILE *file) if (arc != NULL) { // Signal end of defereds - BYTE zero = 0; - *arc << zero; + FString empty = ""; + (*arc) << empty; delete arc; } } @@ -1852,6 +1847,7 @@ void P_ReadACSDefereds (PNGHandle *png) { BYTE namelen; char mapname[256]; + FString MapName; size_t chunklen; P_RemoveDefereds (); @@ -1860,18 +1856,33 @@ void P_ReadACSDefereds (PNGHandle *png) { FPNGChunkArchive arc (png->File->GetFile(), ACSD_ID, chunklen); - arc << namelen; - while (namelen) + if (SaveVersion < 4508) { - arc.Read (mapname, namelen); - mapname[namelen] = 0; - level_info_t *i = FindLevelInfo (mapname); - if (i == NULL) - { - I_Error ("Unknown map '%s' in savegame", mapname); - } - arc << i->defered; arc << namelen; + while (namelen != 0) + { + arc.Read(mapname, namelen); + mapname[namelen] = 0; + level_info_t *i = FindLevelInfo(mapname); + if (i == NULL) + { + I_Error("Unknown map '%s' in savegame", mapname); + } + arc << i->defered; + arc << namelen; + } + } + else + { + while (arc << MapName, MapName.Len() > 0) + { + level_info_t *i = FindLevelInfo(MapName); + if (i == NULL) + { + I_Error("Unknown map '%s' in savegame", MapName.GetChars()); + } + arc << i->defered; + } } } png->File->ResetFilePtr(); diff --git a/src/version.h b/src/version.h index 8e853057a..6c94bf3e6 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4507 +#define SAVEVER 4508 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) From 261bc778467ac07657b35ca92e0d0f69a092a32e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 20 May 2014 10:29:27 +0200 Subject: [PATCH 234/247] - fixed: when bringing up a new weapon the current flash state needs to be removed. Especially when dropping the current weapon it can still be active, this is most easily observed with Strife's crossbow which loops the flash state, but it also can happen with other weapons, right after shooting. --- src/p_pspr.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 85830ac55..49f8bcb84 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -208,6 +208,9 @@ void P_BringUpWeapon (player_t *player) player->psprites[ps_weapon].sy = player->cheats & CF_INSTANTWEAPSWITCH ? WEAPONTOP : WEAPONBOTTOM; P_SetPsprite (player, ps_weapon, newstate); + // make sure that the previous weapon's flash state is terminated. + // When coming here from a weapon drop it may still be active. + P_SetPsprite(player, ps_flash, NULL); } From 9d846395bc0e78a3881ea8530502125191a5a4c9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 24 May 2014 21:05:00 +0200 Subject: [PATCH 235/247] - replaced console buffer with a significantly more efficient new version that also can hold a lot more data. --- src/CMakeLists.txt | 1 + src/c_console.cpp | 402 +++++----------------------------------- src/c_console.h | 3 + src/c_consolebuffer.cpp | 317 +++++++++++++++++++++++++++++++ src/c_consolebuffer.h | 85 +++++++++ src/nodebuild.cpp | 6 - src/v_text.cpp | 4 +- src/v_text.h | 6 +- 8 files changed, 458 insertions(+), 366 deletions(-) create mode 100644 src/c_consolebuffer.cpp create mode 100644 src/c_consolebuffer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5203b294c..517b6bdbe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -789,6 +789,7 @@ add_executable( zdoom WIN32 c_bind.cpp c_cmds.cpp c_console.cpp + c_consolebuffer.cpp c_cvars.cpp c_dispatch.cpp c_expr.cpp diff --git a/src/c_console.cpp b/src/c_console.cpp index 396b2dfce..4dabdb9e1 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -65,22 +65,29 @@ #include "g_level.h" #include "d_event.h" #include "d_player.h" +#include "c_consolebuffer.h" #include "gi.h" -#define CONSOLESIZE 16384 // Number of characters to store in console -#define CONSOLELINES 256 // Max number of lines of console text -#define LINEMASK (CONSOLELINES-1) - #define LEFTMARGIN 8 #define RIGHTMARGIN 8 #define BOTTOMARGIN 12 + +CUSTOM_CVAR(Int, con_buffersize, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + // ensure a minimum size + if (self >= 0 && self < 128) self = 128; +} + +FConsoleBuffer *conbuffer; + static void C_TabComplete (bool goForward); static bool C_TabCompleteList (); static bool TabbedLast; // True if last key pressed was tab static bool TabbedList; // True if tab list was shown -CVAR (Bool, con_notablist, false, CVAR_ARCHIVE) +CVAR(Bool, con_notablist, false, CVAR_ARCHIVE) + static FTextureID conback; static DWORD conshade; @@ -94,18 +101,15 @@ extern FBaseCVar *CVars; extern FConsoleCommand *Commands[FConsoleCommand::HASH_SIZE]; int ConCols, PhysRows; +int ConWidth; bool vidactive = false; bool cursoron = false; int ConBottom, ConScroll, RowAdjust; int CursorTicker; constate_e ConsoleState = c_up; -static char ConsoleBuffer[CONSOLESIZE]; -static char *Lines[CONSOLELINES]; -static bool LineJoins[CONSOLELINES]; static int TopLine, InsertLine; -static char *BufferRover = ConsoleBuffer; static void ClearConsole (); static void C_PasteText(FString clip, BYTE *buffer, int len); @@ -182,7 +186,6 @@ static struct NotifyText static int NotifyTop, NotifyTopGoal; -#define PRINTLEVELS 5 int PrintColors[PRINTLEVELS+2] = { CR_RED, CR_GOLD, CR_GRAY, CR_GREEN, CR_GREEN, CR_GOLD }; static void setmsgcolor (int index, int color); @@ -328,78 +331,11 @@ void C_InitConsole (int width, int height, bool ingame) { cwidth = cheight = 8; } - ConCols = (width - LEFTMARGIN - RIGHTMARGIN) / cwidth; + ConWidth = (width - LEFTMARGIN - RIGHTMARGIN); + ConCols = ConWidth / cwidth; PhysRows = height / cheight; - // If there is some text in the console buffer, reformat it - // for the new resolution. - if (TopLine != InsertLine) - { - // Note: Don't use new here, because we attach a handler to new in - // i_main.cpp that calls I_FatalError if the allocation fails, - // but we can gracefully handle such a condition here by just - // clearing the console buffer. (OTOH, what are the chances that - // any other memory allocations would succeed if we can't get - // these mallocs here?) - - char *fmtBuff = (char *)malloc (CONSOLESIZE); - char **fmtLines = (char **)malloc (CONSOLELINES*sizeof(char*)*4); - int out = 0; - - if (fmtBuff && fmtLines) - { - int in; - char *fmtpos; - bool newline = true; - - fmtpos = fmtBuff; - memset (fmtBuff, 0, CONSOLESIZE); - - for (in = TopLine; in != InsertLine; in = (in + 1) & LINEMASK) - { - size_t len = strlen (Lines[in]); - - if (fmtpos + len + 2 - fmtBuff > CONSOLESIZE) - { - break; - } - if (newline) - { - newline = false; - fmtLines[out++] = fmtpos; - } - strcpy (fmtpos, Lines[in]); - fmtpos += len; - if (!LineJoins[in]) - { - *fmtpos++ = '\n'; - fmtpos++; - if (out == CONSOLELINES*4) - { - break; - } - newline = true; - } - } - } - - ClearConsole (); - - if (fmtBuff && fmtLines) - { - int i; - - for (i = 0; i < out; i++) - { - AddToConsole (-1, fmtLines[i]); - } - } - - if (fmtBuff) - free (fmtBuff); - if (fmtLines) - free (fmtLines); - } + if (conbuffer == NULL) conbuffer = new FConsoleBuffer; } //========================================================================== @@ -507,16 +443,21 @@ void C_DeinitConsole () work = NULL; worklen = 0; } + + if (conbuffer != NULL) + { + delete conbuffer; + conbuffer = NULL; + } } static void ClearConsole () { - RowAdjust = 0; + if (conbuffer != NULL) + { + conbuffer->Clear(); + } TopLine = InsertLine = 0; - BufferRover = ConsoleBuffer; - memset (ConsoleBuffer, 0, CONSOLESIZE); - memset (Lines, 0, sizeof(Lines)); - memset (LineJoins, 0, sizeof(LineJoins)); } static void setmsgcolor (int index, int color) @@ -596,223 +537,9 @@ void C_AddNotifyString (int printlevel, const char *source) NotifyTopGoal = 0; } -static int FlushLines (const char *start, const char *stop) -{ - int i; - - for (i = TopLine; i != InsertLine; i = (i + 1) & LINEMASK) - { - if (Lines[i] < stop && Lines[i] + strlen (Lines[i]) > start) - { - Lines[i] = NULL; - } - else - { - break; - } - } - return i; -} - -static void AddLine (const char *text, bool more, size_t len) -{ - if (BufferRover + len + 1 - ConsoleBuffer > CONSOLESIZE) - { - TopLine = FlushLines (BufferRover, ConsoleBuffer + CONSOLESIZE); - BufferRover = ConsoleBuffer; - } - if (len >= CONSOLESIZE - 1) - { - text = text + len - CONSOLESIZE + 1; - len = CONSOLESIZE - 1; - } - TopLine = FlushLines (BufferRover, BufferRover + len + 1); - memcpy (BufferRover, text, len); - BufferRover[len] = 0; - Lines[InsertLine] = BufferRover; - BufferRover += len + 1; - LineJoins[InsertLine] = more; - InsertLine = (InsertLine + 1) & LINEMASK; - if (InsertLine == TopLine) - { - TopLine = (TopLine + 1) & LINEMASK; - } -} - void AddToConsole (int printlevel, const char *text) { - static enum - { - NEWLINE, - APPENDLINE, - REPLACELINE - } addtype = NEWLINE; - - char *work_p; - char *linestart; - FString cc('A' + char(CR_TAN)); - int size, len; - int x; - int maxwidth; - - if (ConsoleDrawing) - { - EnqueueConsoleText (false, printlevel, text); - return; - } - - len = (int)strlen (text); - size = len + 20; - - if (addtype != NEWLINE) - { - InsertLine = (InsertLine - 1) & LINEMASK; - if (Lines[InsertLine] == NULL) - { - InsertLine = (InsertLine + 1) & LINEMASK; - addtype = NEWLINE; - } - else - { - BufferRover = Lines[InsertLine]; - } - } - if (addtype == APPENDLINE) - { - size += (int)strlen (Lines[InsertLine]); - } - if (size > worklen) - { - work = (char *)M_Realloc (work, size); - worklen = size; - } - if (work == NULL) - { - static char oom[] = TEXTCOLOR_RED "*** OUT OF MEMORY ***"; - work = oom; - worklen = 0; - } - else - { - if (addtype == APPENDLINE) - { - strcpy (work, Lines[InsertLine]); - strcat (work, text); - } - else if (printlevel >= 0) - { - work[0] = TEXTCOLOR_ESCAPE; - work[1] = 'A' + (printlevel == PRINT_HIGH ? CR_TAN : - printlevel == 200 ? CR_GREEN : - printlevel < PRINTLEVELS ? PrintColors[printlevel] : - CR_TAN); - cc = work[1]; - strcpy (work + 2, text); - } - else - { - strcpy (work, text); - } - } - - work_p = linestart = work; - - if (ConFont != NULL && screen != NULL) - { - x = 0; - maxwidth = screen->GetWidth() - LEFTMARGIN - RIGHTMARGIN; - - while (*work_p) - { - if (*work_p == TEXTCOLOR_ESCAPE) - { - work_p++; - if (*work_p == '[') - { - char *start = work_p; - while (*work_p != ']' && *work_p != '\0') - { - work_p++; - } - if (*work_p != '\0') - { - work_p++; - } - cc = FString(start, work_p - start); - } - else if (*work_p != '\0') - { - cc = *work_p++; - } - continue; - } - int w = ConFont->GetCharWidth (*work_p); - if (*work_p == '\n' || x + w > maxwidth) - { - AddLine (linestart, *work_p != '\n', work_p - linestart); - if (*work_p == '\n') - { - x = 0; - work_p++; - } - else - { - x = w; - } - if (*work_p) - { - linestart = work_p - 1 - cc.Len(); - if (linestart < work) - { - // The line start is outside the buffer. - // Make space for the newly inserted stuff. - size_t movesize = work-linestart; - memmove(work + movesize, work, strlen(work)+1); - work_p += movesize; - linestart = work; - } - linestart[0] = TEXTCOLOR_ESCAPE; - strncpy (linestart + 1, cc, cc.Len()); - } - else - { - linestart = work_p; - } - } - else - { - x += w; - work_p++; - } - } - - if (*linestart) - { - AddLine (linestart, true, work_p - linestart); - } - } - else - { - while (*work_p) - { - if (*work_p++ == '\n') - { - AddLine (linestart, false, work_p - linestart - 1); - linestart = work_p; - } - } - if (*linestart) - { - AddLine (linestart, true, work_p - linestart); - } - } - - switch (text[len-1]) - { - case '\r': addtype = REPLACELINE; break; - case '\n': addtype = NEWLINE; break; - default: addtype = APPENDLINE; break; - } + conbuffer->AddText(printlevel, text, Logfile); } /* Adds a string to the console and also to the notify buffer */ @@ -823,34 +550,6 @@ int PrintString (int printlevel, const char *outline) return 0; } - if (Logfile) - { - // Strip out any color escape sequences before writing to the log file - char * copy = new char[strlen(outline)+1]; - const char * srcp = outline; - char * dstp = copy; - - while (*srcp != 0) - { - if (*srcp!=0x1c) - { - *dstp++=*srcp++; - } - else - { - if (srcp[1]!=0) srcp+=2; - else break; - } - } - *dstp=0; - - fputs (copy, Logfile); - delete [] copy; -//#ifdef _DEBUG - fflush (Logfile); -//#endif - } - if (printlevel != PRINT_LOG) { I_PrintStr (outline); @@ -949,6 +648,11 @@ void C_Ticker () if (lasttic == 0) lasttic = gametic - 1; + if (con_buffersize > 0) + { + conbuffer->ResizeBuffer(con_buffersize); + } + if (ConsoleState != c_up) { if (ConsoleState == c_falling) @@ -1236,38 +940,22 @@ void C_DrawConsole (bool hw2d) if (lines > 0) { + // No more enqueuing because adding new text to the console won't touch the actual print data. + conbuffer->FormatText(ConFont, ConWidth); + unsigned int consolelines = conbuffer->GetFormattedLineCount(); + FBrokenLines **blines = conbuffer->GetLines(); + FBrokenLines **printline = blines + consolelines - 1 - RowAdjust; + int bottomline = ConBottom - ConFont->GetHeight()*2 - 4; - int pos = (InsertLine - 1) & LINEMASK; - int i; ConsoleDrawing = true; - for (i = RowAdjust; i; i--) + for(FBrokenLines **p = printline; p >= blines && lines > 0; p--, lines--) { - if (pos == TopLine) - { - RowAdjust = RowAdjust - i; - break; - } - else - { - pos = (pos - 1) & LINEMASK; - } + screen->DrawText(ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), (*p)->Text, TAG_DONE); } - pos++; - do - { - pos = (pos - 1) & LINEMASK; - if (Lines[pos] != NULL) - { - screen->DrawText (ConFont, CR_TAN, LEFTMARGIN, offset + lines * ConFont->GetHeight(), - Lines[pos], TAG_DONE); - } - lines--; - } while (pos != TopLine && lines > 0); ConsoleDrawing = false; - DequeueConsoleText (); if (ConBottom >= 20) { @@ -1293,7 +981,7 @@ void C_DrawConsole (bool hw2d) { // Indicate that the view has been scrolled up (10) // and if we can scroll no further (12) - screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, pos == TopLine ? 12 : 10, TAG_DONE); + screen->DrawChar (ConFont, CR_GREEN, 0, bottomline, RowAdjust == conbuffer->GetFormattedLineCount() ? 12 : 10, TAG_DONE); } } } @@ -1445,7 +1133,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) RowAdjust += (SCREENHEIGHT-4) / ((gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP) ? ConFont->GetHeight() : ConFont->GetHeight()*2) - 3; } - else if (RowAdjust < CONSOLELINES) + else if (RowAdjust < conbuffer->GetFormattedLineCount()) { // Scroll console buffer up if (ev->subtype == EV_GUI_WheelUp) { @@ -1455,6 +1143,10 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) { RowAdjust++; } + if (RowAdjust > conbuffer->GetFormattedLineCount()) + { + RowAdjust = conbuffer->GetFormattedLineCount(); + } } break; @@ -1488,7 +1180,7 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len) case GK_HOME: if (ev->data3 & GKM_CTRL) { // Move to top of console buffer - RowAdjust = CONSOLELINES; + RowAdjust = conbuffer->GetFormattedLineCount(); } else { // Move cursor to start of line diff --git a/src/c_console.h b/src/c_console.h index 8560d6779..2c2e553f9 100644 --- a/src/c_console.h +++ b/src/c_console.h @@ -47,6 +47,9 @@ typedef enum cstate_t } constate_e; +#define PRINTLEVELS 5 +extern int PrintColors[PRINTLEVELS + 2]; + extern constate_e ConsoleState; extern int ConBottom; diff --git a/src/c_consolebuffer.cpp b/src/c_consolebuffer.cpp new file mode 100644 index 000000000..3f64f34e4 --- /dev/null +++ b/src/c_consolebuffer.cpp @@ -0,0 +1,317 @@ +/* +** consolebuffer.cpp +** +** manages the text for the console +** +**--------------------------------------------------------------------------- +** Copyright 2014 Christoph Oelckers +** 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. +**--------------------------------------------------------------------------- +** +*/ + +#include "c_console.h" +#include "c_consolebuffer.h" + + +//========================================================================== +// +// +// +//========================================================================== + +FConsoleBuffer::FConsoleBuffer() +{ + mLogFile = NULL; + mAddType = NEWLINE; + mLastFont = NULL; + mLastDisplayWidth = -1; + mLastLineNeedsUpdate = false; + mTextLines = 0; + mBufferWasCleared = true; + mBrokenStart.Push(0); +} + +//========================================================================== +// +// +// +//========================================================================== + +FConsoleBuffer::~FConsoleBuffer() +{ + FreeBrokenText(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::FreeBrokenText(unsigned start, unsigned end) +{ + if (end > mBrokenConsoleText.Size()) end = mBrokenConsoleText.Size(); + for (unsigned i = start; i < end; i++) + { + if (mBrokenConsoleText[i] != NULL) V_FreeBrokenLines(mBrokenConsoleText[i]); + mBrokenConsoleText[i] = NULL; + } +} + +//========================================================================== +// +// Adds a new line of text to the console +// This is kept as simple as possible. This function does not: +// - remove old text if the buffer gets larger than the specified size +// - format the text for the current screen layout +// +// These tasks will only be be performed once per frame because they are +// relatively expensive. The old console did them each time text was added +// resulting in extremely bad performance with a high output rate. +// +//========================================================================== + +void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile) +{ + FString build = TEXTCOLOR_TAN; + + if (mAddType == REPLACELINE) + { + // Just wondering: Do we actually need this case? If so, it may need some work. + mConsoleText.Pop(); // remove the line to be replaced + mLastLineNeedsUpdate = true; + } + else if (mAddType == APPENDLINE) + { + mConsoleText.Pop(build); + printlevel = -1; + mLastLineNeedsUpdate = true; + } + + if (printlevel >= 0 && printlevel != PRINT_HIGH) + { + if (printlevel == 200) build = TEXTCOLOR_GREEN; + else if (printlevel < PRINTLEVELS) build.Format("%c%c", TEXTCOLOR_ESCAPE, PrintColors[printlevel]); + } + + size_t textsize = strlen(text); + + if (text[textsize-1] == '\r') + { + textsize--; + mAddType = REPLACELINE; + } + else if (text[textsize-1] == '\n') + { + textsize--; + mAddType = NEWLINE; + } + else + { + mAddType = APPENDLINE; + } + + // don't bother about linefeeds etc. inside the text, we'll let the formatter sort this out later. + build.AppendCStrPart(text, textsize); + mConsoleText.Push(build); + if (logfile != NULL) WriteLineToLog(logfile, text); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline) +{ + // Strip out any color escape sequences before writing to the log file + char * copy = new char[strlen(outline)+1]; + const char * srcp = outline; + char * dstp = copy; + + while (*srcp != 0) + { + + if (*srcp != TEXTCOLOR_ESCAPE) + { + switch (*srcp) + { + case '\35': + *dstp++ = '<'; + break; + + case '\36': + *dstp++ = '-'; + break; + + case '\37': + *dstp++ = '>'; + break; + + default: + *dstp++=*srcp; + break; + } + srcp++; + } + else if (srcp[1] == '[') + { + srcp+=2; + while (*srcp != ']' && *srcp != 0) srcp++; + if (*srcp == ']') srcp++; + } + else + { + if (srcp[1]!=0) srcp+=2; + else break; + } + } + *dstp=0; + + fputs (copy, LogFile); + delete [] copy; + fflush (LogFile); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FConsoleBuffer::WriteContentToLog(FILE *LogFile) +{ + if (LogFile != NULL) + { + for (unsigned i = 0; i < mConsoleText.Size(); i++) + { + WriteLineToLog(LogFile, mConsoleText[i]); + } + } +} + +//========================================================================== +// +// ensures that the following text is not appended to the current line. +// +//========================================================================== + +void FConsoleBuffer::Linefeed(FILE *Logfile) +{ + if (mAddType != NEWLINE && Logfile != NULL) fputc('\n', Logfile); + mAddType = NEWLINE; +} + +//========================================================================== +// +// +// +//========================================================================== + +static const char bar1[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_TAN "\n"; +static const char bar2[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_GREEN "\n"; +static const char bar3[] = TEXTCOLOR_RED "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" + "\36\36\36\36\36\36\36\36\36\36\36\36\37" TEXTCOLOR_NORMAL "\n"; +static const char logbar[] = "\n<------------------------------->\n"; + +void FConsoleBuffer::AddMidText(const char *string, bool bold, FILE *Logfile) +{ + Linefeed(Logfile); + AddText (-1, bold? bar2 : bar1, Logfile); + AddText (-1, string, Logfile); + Linefeed(Logfile); + AddText(-1, bar3, Logfile); +} + +//========================================================================== +// +// Format the text for output +// +//========================================================================== + +void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth) +{ + if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared) + { + FreeBrokenText(); + mBrokenConsoleText.Clear(); + mBrokenStart.Clear(); + mBrokenStart.Push(0); + mBrokenLines.Clear(); + mLastFont = formatfont; + mLastDisplayWidth = displaywidth; + mBufferWasCleared = false; + } + unsigned brokensize = mBrokenConsoleText.Size(); + if (brokensize == mConsoleText.Size()) + { + // The last line got text appended. We have to wait until here to format it because + // it is possible that during display new text will be added from the NetUpdate calls in the software version of DrawTextureV. + if (mLastLineNeedsUpdate) + { + brokensize--; + V_FreeBrokenLines(mBrokenConsoleText[brokensize]); + mBrokenConsoleText.Resize(brokensize); + } + } + mBrokenLines.Resize(mBrokenStart[brokensize]); + mBrokenStart.Resize(brokensize); + for (unsigned i = brokensize; i < mConsoleText.Size(); i++) + { + FBrokenLines *bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true); + mBrokenConsoleText.Push(bl); + mBrokenStart.Push(mBrokenLines.Size()); + while (bl->Width != -1) + { + mBrokenLines.Push(bl); + bl++; + } + } + mTextLines = mBrokenLines.Size(); + mBrokenStart.Push(mTextLines); + mLastLineNeedsUpdate = false; +} + +//========================================================================== +// +// Delete old content if number of lines gets too large +// +//========================================================================== + +void FConsoleBuffer::ResizeBuffer(unsigned newsize) +{ + if (mConsoleText.Size() > newsize) + { + unsigned todelete = mConsoleText.Size() - newsize; + mConsoleText.Delete(0, todelete); + mBufferWasCleared = true; + } +} + diff --git a/src/c_consolebuffer.h b/src/c_consolebuffer.h new file mode 100644 index 000000000..710423012 --- /dev/null +++ b/src/c_consolebuffer.h @@ -0,0 +1,85 @@ +/* +** consolebuffer.h +** +** manages the text for the console +** +**--------------------------------------------------------------------------- +** Copyright 2014 Christoph Oelckers +** 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. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include "zstring.h" +#include "tarray.h" +#include "v_text.h" + +enum EAddType +{ + NEWLINE, + APPENDLINE, + REPLACELINE +}; + +class FConsoleBuffer +{ + TArray mConsoleText; + TArray mBrokenConsoleText; // This holds the structures returned by V_BreakLines and is used for memory management. + TArray mBrokenStart; + TArray mBrokenLines; // This holds the single lines, indexed by mBrokenStart and is used for printing. + FILE * mLogFile; + EAddType mAddType; + int mTextLines; + bool mBufferWasCleared; + + FFont *mLastFont; + int mLastDisplayWidth; + bool mLastLineNeedsUpdate; + + void WriteLineToLog(FILE *LogFile, const char *outline); + void FreeBrokenText(unsigned int start = 0, unsigned int end = INT_MAX); + + void Linefeed(FILE *Logfile); + +public: + FConsoleBuffer(); + ~FConsoleBuffer(); + void AddText(int printlevel, const char *string, FILE *logfile = NULL); + void AddMidText(const char *string, bool bold, FILE *logfile); + void FormatText(FFont *formatfont, int displaywidth); + void ResizeBuffer(unsigned newsize); + void WriteContentToLog(FILE *logfile); + void Clear() + { + mBufferWasCleared = true; + mConsoleText.Clear(); + } + int GetFormattedLineCount() { return mTextLines; } + FBrokenLines **GetLines() { return &mBrokenLines[0]; } +}; + diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index f3ceec17d..210f0f3de 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -125,12 +125,10 @@ void FNodeBuilder::BuildTree () { fixed_t bbox[4]; - C_InitTicker ("Building BSP", FRACUNIT); HackSeg = DWORD_MAX; HackMate = DWORD_MAX; CreateNode (0, Segs.Size(), bbox); CreateSubsectorsForReal (); - C_InitTicker (NULL, 0); } int FNodeBuilder::CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]) @@ -199,10 +197,6 @@ int FNodeBuilder::CreateSubsector (DWORD set, fixed_t bbox[4]) } SegsStuffed += count; - if ((SegsStuffed & ~127) != ((SegsStuffed - count) & ~127)) - { - C_SetTicker (MulScale16 (SegsStuffed, (SDWORD)Segs.Size())); - } D(Printf (PRINT_LOG, "bbox (%d,%d)-(%d,%d)\n", bbox[BOXLEFT]>>16, bbox[BOXBOTTOM]>>16, bbox[BOXRIGHT]>>16, bbox[BOXTOP]>>16)); diff --git a/src/v_text.cpp b/src/v_text.cpp index c5208be36..64b95c041 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -336,7 +336,7 @@ static void breakit (FBrokenLines *line, FFont *font, const BYTE *start, const B line->Width = font->StringWidth (line->Text); } -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string) +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool preservecolor) { FBrokenLines lines[128]; // Support up to 128 lines (should be plenty) @@ -397,7 +397,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string) space = string - 1; breakit (&lines[i], font, start, space, linecolor); - if (c == '\n') + if (c == '\n' && !preservecolor) { lastcolor = ""; // Why, oh why, did I do it like this? } diff --git a/src/v_text.h b/src/v_text.h index 29dfa627b..f1426b30a 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -75,9 +75,9 @@ struct FBrokenLines #define TEXTCOLOR_CHAT "\034*" #define TEXTCOLOR_TEAMCHAT "\034!" -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str); +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str, bool preservecolor = false); void V_FreeBrokenLines (FBrokenLines *lines); -inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str) - { return V_BreakLines (font, maxwidth, (const BYTE *)str); } +inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false) + { return V_BreakLines (font, maxwidth, (const BYTE *)str, preservecolor); } #endif //__V_TEXT_H__ From b285cbebe4fb7f3a84240eabeb4276761565567b Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Sun, 25 May 2014 01:12:16 +0200 Subject: [PATCH 236/247] - Fixed compiler errors in latest TEXTURES code. --- src/r_data/sprites.cpp | 4 ++-- src/r_utility.cpp | 2 +- src/textures/animations.cpp | 4 ++-- src/textures/jpegtexture.cpp | 4 ++-- src/textures/multipatchtexture.cpp | 14 +++++++------- src/textures/texturemanager.cpp | 2 +- src/w_wad.h | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 604619403..c1e59c415 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -63,7 +63,7 @@ static bool R_InstallSpriteLump (FTextureID lump, unsigned frame, char rot, bool if (frame >= MAX_SPRITE_FRAMES || rotation > 16) { - Printf (TEXTCOLOR_RED"R_InstallSpriteLump: Bad frame characters in lump %s\n", TexMan[lump]->Name); + Printf (TEXTCOLOR_RED"R_InstallSpriteLump: Bad frame characters in lump %s\n", TexMan[lump]->Name.GetChars()); return false; } @@ -998,4 +998,4 @@ void R_DeinitSpriteData() delete[] skins; skins = NULL; } -} \ No newline at end of file +} diff --git a/src/r_utility.cpp b/src/r_utility.cpp index e11631700..5bf38ad26 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -972,7 +972,7 @@ void FCanvasTextureInfo::Add (AActor *viewpoint, FTextureID picnum, int fov) texture = static_cast(TexMan[picnum]); if (!texture->bHasCanvas) { - Printf ("%s is not a valid target for a camera\n", texture->Name); + Printf ("%s is not a valid target for a camera\n", texture->Name.GetChars()); return; } diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 3601646a0..58ef7a5ca 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -231,8 +231,8 @@ void FTextureManager::InitAnimated (void) if (debuganimated) { Printf("Defining animation '%s' (texture %d, lump %d, file %d) to '%s' (texture %d, lump %d, file %d)\n", - tex1->Name, pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()), - tex2->Name, pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); + tex1->Name.GetChars(), pic1.GetIndex(), tex1->GetSourceLump(), Wads.GetLumpFile(tex1->GetSourceLump()), + tex2->Name.GetChars(), pic2.GetIndex(), tex2->GetSourceLump(), Wads.GetLumpFile(tex2->GetSourceLump())); } if (pic1 == pic2) diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 3a87f70af..849cec645 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -448,7 +448,7 @@ void FJPEGTexture::MakeTexture () } catch (int) { - Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name); + Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name.GetChars()); jpeg_destroy_decompress(&cinfo); } if (buff != NULL) @@ -532,7 +532,7 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC } catch(int) { - Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name); + Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name.GetChars()); } jpeg_destroy_decompress(&cinfo); if (buff != NULL) delete [] buff; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 84e7385db..348ad3a98 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -268,14 +268,14 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl if (unsigned(LittleShort(mpatch.d->patch)) >= unsigned(maxpatchnum)) { I_FatalError ("Bad PNAMES and/or texture directory:\n\nPNAMES has %d entries, but\n%s wants to use entry %d.", - maxpatchnum, Name, LittleShort(mpatch.d->patch)+1); + maxpatchnum, Name.GetChars(), LittleShort(mpatch.d->patch)+1); } Parts[i].OriginX = LittleShort(mpatch.d->originx); Parts[i].OriginY = LittleShort(mpatch.d->originy); Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; if (Parts[i].Texture == NULL) { - Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name, Name); + Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name.GetChars(), Name.GetChars()); NumParts--; i--; } @@ -290,7 +290,7 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } if (NumParts == 0) { - Printf ("Texture %s is left without any patches\n", Name); + Printf ("Texture %s is left without any patches\n", Name.GetChars()); } CheckForHacks (); @@ -1023,7 +1023,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i } if (part.Texture == NULL) { - if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name); + if (!silent) Printf(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name.GetChars()); } sc.MustGetStringName(","); sc.MustGetNumber(); @@ -1244,13 +1244,13 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) { sc.MustGetFloat(); xScale = FLOAT2FIXED(sc.Float); - if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name); + if (xScale == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name.GetChars()); } else if (sc.Compare("YScale")) { sc.MustGetFloat(); yScale = FLOAT2FIXED(sc.Float); - if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name); + if (yScale == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name.GetChars()); } else if (sc.Compare("WorldPanning")) { @@ -1318,7 +1318,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) if (Width <= 0 || Height <= 0) { UseType = FTexture::TEX_Null; - Printf("Texture %s has invalid dimensions (%d, %d)\n", Name, Width, Height); + Printf("Texture %s has invalid dimensions (%d, %d)\n", Name.GetChars(), Width, Height); Width = Height = 1; } CalcBitSize (); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 2a10ce0df..a79769c3d 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -949,7 +949,7 @@ void FTextureManager::SortTexturesByType(int start, int end) { if (newtextures[j] != NULL) { - Printf("Texture %s has unknown type!\n", newtextures[j]->Name); + Printf("Texture %s has unknown type!\n", newtextures[j]->Name.GetChars()); AddTexture(newtextures[j]); } } diff --git a/src/w_wad.h b/src/w_wad.h index 0a95699f6..4dfe3434d 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -196,8 +196,8 @@ public: int GetLumpOffset (int lump); // [RH] Returns offset of lump in the wadfile int GetLumpFlags (int lump); // Return the flags for this lump void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy - void FWadCollection::GetLumpName(FString &to, int lump) const; - const char *GetLumpFullName(int lump) const; // [RH] Returns the lump's full name + void GetLumpName (FString &to, int lump) const; + const char *GetLumpFullName (int lump) const; // [RH] Returns the lump's full name FString GetLumpFullPath (int lump) const; // [RH] Returns wad's name + lump's full name int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to From 75cde0b2219fdd798eaa30e1d41ce33dd696b9f6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 29 May 2014 17:30:01 +0200 Subject: [PATCH 237/247] - allow locks to check for a key's species so that newly defined keys can open previously defined locks without the need to redefine them. --- src/g_shared/a_keys.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index e7f1b286b..67d0ffb10 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -19,12 +19,29 @@ struct OneKey bool check(AActor * owner) { - // P_GetMapColorForKey() checks the key directly - if (owner->IsKindOf (RUNTIME_CLASS(AKey))) + if (owner->IsKindOf(RUNTIME_CLASS(AKey))) + { + // P_GetMapColorForKey() checks the key directly return owner->IsA(key); - // Other calls check an actor that may have a key in its inventory. - else - return !!owner->FindInventory(key); + } + else + { + // Other calls check an actor that may have a key in its inventory. + AInventory *item; + + for (item = owner->Inventory; item != NULL; item = item->Inventory) + { + if (item->IsA(key)) + { + return true; + } + else if (item->GetSpecies() == key->TypeName) + { + return true; + } + } + return false; + } } }; From 8f5683e23d61825e77b2c7b68312a01cf4354d61 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 29 May 2014 17:50:14 +0200 Subject: [PATCH 238/247] - moved secret found message to string table and removed the CVAR crutch that dates from a time when modifying string table content wasn't as easy as it is now. - added 'showsecretsector' CVAR to show the sector number with the secret found message. --- src/g_shared/a_pickups.cpp | 2 +- src/g_shared/a_secrettrigger.cpp | 4 +--- src/p_spec.cpp | 21 +++++++++++++++------ src/p_spec.h | 2 +- wadsrc/static/language.enu | 2 ++ 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index cc559ea94..f14e7f4c7 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1018,7 +1018,7 @@ void AInventory::Touch (AActor *toucher) if (flags5 & MF5_COUNTSECRET) { - P_GiveSecret(toucher, true, true); + P_GiveSecret(toucher, true, true, -1); } //Added by MC: Check if item taken was the roam destination of any bot diff --git a/src/g_shared/a_secrettrigger.cpp b/src/g_shared/a_secrettrigger.cpp index 4484340db..24c6f0db4 100644 --- a/src/g_shared/a_secrettrigger.cpp +++ b/src/g_shared/a_secrettrigger.cpp @@ -42,8 +42,6 @@ #include "v_font.h" #include "p_spec.h" -EXTERN_CVAR(String, secretmessage) - class ASecretTrigger : public AActor { DECLARE_CLASS (ASecretTrigger, AActor) @@ -62,7 +60,7 @@ void ASecretTrigger::PostBeginPlay () void ASecretTrigger::Activate (AActor *activator) { - P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2)); + P_GiveSecret(activator, args[0] <= 1, (args[0] == 0 || args[0] == 2), -1); Destroy (); } diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 63f7c1c89..e66dc2ab4 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -61,6 +61,7 @@ #include "a_sharedglobal.h" #include "farchive.h" #include "a_keys.h" +#include "c_dispatch.h" // State. #include "r_state.h" @@ -73,9 +74,6 @@ static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); void P_SetupPortals(); -// [GrafZahl] Make this message changable by the user! ;) -CVAR(String, secretmessage, "A Secret is revealed!", CVAR_ARCHIVE) - IMPLEMENT_POINTY_CLASS (DScroller) DECLARE_POINTER (m_Interpolations[0]) DECLARE_POINTER (m_Interpolations[1]) @@ -581,7 +579,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) if (sector->special & SECRET_MASK) { sector->special &= ~SECRET_MASK; - P_GiveSecret(player->mo, true, true); + P_GiveSecret(player->mo, true, true, int(sector - sectors)); } } @@ -672,7 +670,9 @@ void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, // //============================================================================ -void P_GiveSecret(AActor *actor, bool printmessage, bool playsound) +CVAR(Bool, showsecretsector, false, 0) + +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum) { if (actor != NULL) { @@ -682,7 +682,16 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound) } if (actor->CheckLocalView (consoleplayer)) { - if (printmessage) C_MidPrint (SmallFont, secretmessage); + if (printmessage) + { + if (!showsecretsector || sectornum < 0) C_MidPrint(SmallFont, GStrings["SECRETMESSAGE"]); + else + { + FString s = GStrings["SECRETMESSAGE"]; + s.AppendFormat(" (Sector %d)", sectornum); + C_MidPrint(SmallFont, s); + } + } if (playsound) S_Sound (CHAN_AUTO | CHAN_UI, "misc/secret", 1, ATTN_NORM); } } diff --git a/src/p_spec.h b/src/p_spec.h index f8dad701b..245c699d7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -172,7 +172,7 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType); void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags); void P_SetSectorFriction (int tag, int amount, bool alterFlag); -void P_GiveSecret(AActor *actor, bool printmessage, bool playsound); +void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum); // // getSide() diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 5695ad502..76ba7c0d7 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2,6 +2,8 @@ [enu default] +SECRETMESSAGE = "A secret is revealed!"; + D_DEVSTR = "Useless mode ON.\n"; D_CDROM = "CD-ROM Version: zdoom.ini from c:\\zdoomdat\n"; PRESSKEY = "press a key."; From 98c25deec19039f61d3ea11e510e4628334c7da5 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sat, 31 May 2014 16:29:28 +0300 Subject: [PATCH 239/247] Fix LZMA compilation on GCC with position-independent code (PIC) generation enabled EBX register is used Global Offset Table in PIC http://www.greyhat.ch/lab/downloads/pic.html --- lzma/C/CpuArch.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lzma/C/CpuArch.c b/lzma/C/CpuArch.c index 4b319fa88..925edbeb8 100644 --- a/lzma/C/CpuArch.c +++ b/lzma/C/CpuArch.c @@ -74,8 +74,24 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) *c = c2; *d = d2; + #elif __PIC__ + + /* GCC or Clang WITH position-independent code generation */ + + __asm__ __volatile__ ( + "xchgl %%ebx, %1\n" + "cpuid\n" + "xchgl %%ebx, %1\n" + : "=a" (*a) , + "=r" (*b) , + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + #else + /* GCC or Clang WITHOUT position-independent code generation */ + __asm__ __volatile__ ( "cpuid" : "=a" (*a) , From e8513a64edf92bb767560b2239c8f91a80ba802e Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 1 Jun 2014 15:29:22 +1200 Subject: [PATCH 240/247] Rebuild nodes for hellfact map04 --- wadsrc/static/compatibility.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index e2516a30d..1c2307ec0 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -332,7 +332,7 @@ F481922F4881F74760F3C0437FD5EDD0 // map03 setactivation 455 16 // SPAC_Push } - +8B2AC8D4DB4A49A5DCCBB067E04434D6 // The Hell Factory Hub One, map04 65A1EB4C87386F290816660A52932FF1 // Master Levels, garrison.wad { rebuildnodes From 3817bed0b3dcbc1dd85f6c1c745e5de9ba0b0759 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 1 Jun 2014 18:11:50 +1200 Subject: [PATCH 241/247] Weap scroll could sometimes miss sameslot weapons In rear cases, when using next/prevweap, defined weapons in the same slot couldn't cycle when looping to another when you only had weapons in 1 slot. --- src/g_shared/a_weapons.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 6caf42b7d..fae232557 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -1143,7 +1143,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player) return weap; } } - while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS); + while ((slot != startslot || index != startindex) && slotschecked <= NUM_WEAPON_SLOTS); } return player->ReadyWeapon; } @@ -1198,7 +1198,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player) return weap; } } - while ((slot != startslot || index != startindex) && slotschecked < NUM_WEAPON_SLOTS); + while ((slot != startslot || index != startindex) && slotschecked <= NUM_WEAPON_SLOTS); } return player->ReadyWeapon; } From 96e4cb90b7e48d40ae07353a34db60318b87b19c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Sun, 1 Jun 2014 15:12:41 +0300 Subject: [PATCH 242/247] Fix crash on attempt to save cached OpenGL nodes on OS X Root permissions are required to be able to create directories inside /Library/Application Support So user's ~/Library/Application Support is used to store cached nodes --- src/m_specialpaths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_specialpaths.cpp b/src/m_specialpaths.cpp index b4fcba3c3..e6f74eda6 100644 --- a/src/m_specialpaths.cpp +++ b/src/m_specialpaths.cpp @@ -335,7 +335,7 @@ FString M_GetCachePath(bool create) char pathstr[PATH_MAX]; FSRef folder; - if (noErr == FSFindFolder(kLocalDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && + if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) { path = pathstr; From 9cd074ddf3cf65fd2192320d34b8e5a05357deb6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 2 Jun 2014 10:51:17 +0200 Subject: [PATCH 243/247] - fixed: plane equation vectors must be normalized when being loaded from UDMF. --- src/p_udmf.cpp | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 19dfdf08c..7588199b4 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1246,6 +1246,7 @@ public: int fadecolor = -1; int desaturation = -1; int fplaneflags = 0, cplaneflags = 0; + double fp[4] = { 0 }, cp[4] = { 0 }; memset(sec, 0, sizeof(*sec)); sec->lightlevel = 160; @@ -1449,44 +1450,42 @@ public: case NAME_floorplane_a: fplaneflags |= 1; - sec->floorplane.a = CheckFixed(key); + fp[0] = CheckFloat(key); break; case NAME_floorplane_b: fplaneflags |= 2; - sec->floorplane.b = CheckFixed(key); + fp[1] = CheckFloat(key); break; case NAME_floorplane_c: fplaneflags |= 4; - sec->floorplane.c = CheckFixed(key); - sec->floorplane.ic = FixedDiv(FRACUNIT, sec->floorplane.c); + fp[2] = CheckFloat(key); break; case NAME_floorplane_d: fplaneflags |= 8; - sec->floorplane.d = CheckFixed(key); + fp[3] = CheckFloat(key); break; case NAME_ceilingplane_a: cplaneflags |= 1; - sec->ceilingplane.a = CheckFixed(key); + cp[0] = CheckFloat(key); break; case NAME_ceilingplane_b: cplaneflags |= 2; - sec->ceilingplane.b = CheckFixed(key); + cp[1] = CheckFloat(key); break; case NAME_ceilingplane_c: cplaneflags |= 4; - sec->ceilingplane.c = CheckFixed(key); - sec->ceilingplane.ic = FixedDiv(FRACUNIT, sec->ceilingplane.c); + cp[2] = CheckFloat(key); break; case NAME_ceilingplane_d: cplaneflags |= 8; - sec->ceilingplane.d = CheckFixed(key); + cp[3] = CheckFloat(key); break; default: @@ -1509,6 +1508,17 @@ public: sec->floorplane.c = FRACUNIT; sec->floorplane.ic = FRACUNIT; } + else + { + double ulen = TVector3(fp[0], fp[1], fp[2]).Length(); + + // normalize the vector, it must have a length of 1 + sec->floorplane.a = FLOAT2FIXED(fp[0] / ulen); + sec->floorplane.b = FLOAT2FIXED(fp[1] / ulen); + sec->floorplane.c = FLOAT2FIXED(fp[2] / ulen); + sec->floorplane.d = FLOAT2FIXED(fp[3] / ulen); + sec->floorplane.ic = FLOAT2FIXED(ulen / fp[2]); + } if (cplaneflags != 15) { sec->ceilingplane.a = sec->ceilingplane.b = 0; @@ -1516,6 +1526,17 @@ public: sec->ceilingplane.c = -FRACUNIT; sec->ceilingplane.ic = -FRACUNIT; } + else + { + double ulen = TVector3(cp[0], cp[1], cp[2]).Length(); + + // normalize the vector, it must have a length of 1 + sec->floorplane.a = FLOAT2FIXED(cp[0] / ulen); + sec->floorplane.b = FLOAT2FIXED(cp[1] / ulen); + sec->floorplane.c = FLOAT2FIXED(cp[2] / ulen); + sec->floorplane.d = FLOAT2FIXED(cp[3] / ulen); + sec->floorplane.ic = FLOAT2FIXED(ulen / cp[2]); + } if (lightcolor == -1 && fadecolor == -1 && desaturation == -1) { From 3e7b0c29165114d543669bb00793920412f37c08 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 2 Jun 2014 10:44:29 +0300 Subject: [PATCH 244/247] Fix crash when GL nodes file cannot be opened for writing Report errors to console if nodes file cannot be opened or written --- src/p_glnodes.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index a8fa04c34..e59f3859a 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1168,8 +1168,21 @@ static void CreateCachedNodes(MapData *map) FString path = CreateCacheName(map, true); FILE *f = fopen(path, "wb"); - fwrite(compressed, 1, outlen+offset, f); - fclose(f); + + if (f != NULL) + { + if (fwrite(compressed, outlen+offset, 1, f) != 1) + { + Printf("Error saving nodes to file %s\n", path.GetChars()); + } + + fclose(f); + } + else + { + Printf("Cannot open nodes file %s for writing\n", path.GetChars()); + } + delete [] compressed; } From 20adcecb1d480724ebccc9448d2bef562c3ba59f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 2 Jun 2014 11:37:40 +0300 Subject: [PATCH 245/247] Remove redundant saving of GL nodes if they were loaded from cache --- src/p_glnodes.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index e59f3859a..899005ffa 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -959,6 +959,7 @@ bool P_LoadGLNodes(MapData * map) bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) { bool ret = false; + bool loaded = false; // If the map loading code has performed a node rebuild we don't need to check for it again. if (!rebuilt && !P_CheckForGLNodes()) @@ -978,7 +979,8 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) numsegs = 0; // Try to load GL nodes (cached or GWA) - if (!P_LoadGLNodes(map)) + loaded = P_LoadGLNodes(map); + if (!loaded) { // none found - we have to build new ones! unsigned int startTime, endTime; @@ -1006,20 +1008,22 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) } } + if (!loaded) + { #ifdef DEBUG - // Building nodes in debug is much slower so let's cache them only if cachetime is 0 - buildtime = 0; + // Building nodes in debug is much slower so let's cache them only if cachetime is 0 + buildtime = 0; #endif - if (gl_cachenodes && buildtime/1000.f >= gl_cachetime) - { - DPrintf("Caching nodes\n"); - CreateCachedNodes(map); + if (gl_cachenodes && buildtime/1000.f >= gl_cachetime) + { + DPrintf("Caching nodes\n"); + CreateCachedNodes(map); + } + else + { + DPrintf("Not caching nodes (time = %f)\n", buildtime/1000.f); + } } - else - { - DPrintf("Not caching nodes (time = %f)\n", buildtime/1000.f); - } - if (!gamenodes) { From 842ef86e73efc3819b61289db0cba5e6c66ff364 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Mon, 9 Jun 2014 19:51:32 +1200 Subject: [PATCH 246/247] Don't reset the inventory of dead players --- src/g_game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 65fa5733d..b84ac890d 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1307,7 +1307,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags) } // Clears the entire inventory and gives back the defaults for starting a game - if (flags & CHANGELEVEL_RESETINVENTORY) + if ((flags & CHANGELEVEL_RESETINVENTORY) && p->playerstate != PST_DEAD) { p->mo->ClearInventory(); p->mo->GiveDefaultInventory(); From 67c6690689b98b36bffecf557dffe9dca875a810 Mon Sep 17 00:00:00 2001 From: WChrisK Date: Wed, 11 Jun 2014 23:30:25 -0400 Subject: [PATCH 247/247] Added a check that doesn't print empty obituary strings, as wad's that hide obituary strings in multiplayer games end up spamming a lot of empty lines. --- src/p_interaction.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 4be8ed627..0eae78632 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -320,6 +320,10 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf message = GStrings("OB_DEFAULT"); } + // [CK] Don't display empty strings + if (message == NULL || strlen(message) <= 0) + return; + SexMessage (message, gendermessage, gender, self->player->userinfo.GetName(), attacker->player->userinfo.GetName()); Printf (PRINT_MEDIUM, "%s\n", gendermessage);