diff --git a/.appveyor.yml b/.appveyor.yml index 486eb2d78..e34cc0af6 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -32,7 +32,7 @@ environment: build_script: - md build - cd build - - cmake -G "%GENERATOR%" -T "%TOOLSET%" .. + - cmake -G "%GENERATOR%" -T "%TOOLSET%" -DPK3_QUIET_ZIPDIR=YES .. - cmake --build . --config "%CONFIGURATION%" -- /verbosity:minimal after_build: diff --git a/.travis.yml b/.travis.yml index f457d5f99..b195f64b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,15 +70,15 @@ matrix: - os: linux compiler: clang env: - - CLANG_VERSION=5.0 + - CLANG_VERSION=6.0 - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=MinSizeRel -DDYN_OPENAL=NO -DDYN_SNDFILE=NO -DDYN_MPG123=NO -DDYN_FLUIDSYNTH=NO" addons: apt: sources: - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 + - llvm-toolchain-trusty-6.0 packages: - - clang-5.0 + - clang-6.0 - libstdc++-5-dev - libsdl2-dev - libgme-dev @@ -98,8 +98,8 @@ script: - echo ${TRAVIS_BUILD_DIR} - mkdir build - cd build - - cmake ${CMAKE_OPTIONS} .. - - make -j2 + - cmake ${CMAKE_OPTIONS} -DPK3_QUIET_ZIPDIR=YES .. + - make -j2 -k notifications: email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 5809118d8..ddbdc70ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,23 +55,24 @@ function( assort_pk3_source_folder FOLDER_NAME PK3_DIR ) endforeach() endfunction() +option( PK3_QUIET_ZIPDIR "Do not list files processed by zipdir" NO ) +if( PK3_QUIET_ZIPDIR ) + set( PK3_ZIPDIR_OPTIONS "-q" ) +endif() + # Simplify pk3 building, add_pk3(filename srcdirectory) function( add_pk3 PK3_NAME PK3_DIR ) - # message(STATUS "Creating build rule for PK3 ${PK3_NAME} ${PK3_DIR}") # Generate target name. Just use "pk3" for main pk3 target. string( REPLACE "." "_" PK3_TARGET ${PK3_NAME} ) - if( ${PK3_TARGET} STREQUAL "zdoom_pk3" ) - set( PK3_TARGET "pk3" ) - endif() if( NOT ZDOOM_OUTPUT_OLDSTYLE ) add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} - COMMAND zipdir -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} + COMMAND zipdir -udf ${PK3_ZIPDIR_OPTIONS} ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} $/${PK3_NAME} DEPENDS zipdir ) else() add_custom_command( OUTPUT ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} - COMMAND zipdir -udf ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} + COMMAND zipdir -udf ${PK3_ZIPDIR_OPTIONS} ${ZDOOM_OUTPUT_DIR}/${PK3_NAME} ${PK3_DIR} DEPENDS zipdir ) endif() # Create a list of source files for this PK3, for use in the IDE diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 15238366c..4e92e262c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -403,6 +403,16 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) endif() endif() +# Check for thread_local keyword, it's optional at the moment + +CHECK_CXX_SOURCE_COMPILES("thread_local int i; int main() { i = 0; }" + HAVE_THREAD_LOCAL) + +if( NOT HAVE_THREAD_LOCAL ) + message( WARNING "C++ compiler doesn't support thread_local storage duration specifier" ) + add_definitions( -Dthread_local= ) +endif() + # Check for functions that may or may not exist. CHECK_FUNCTION_EXISTS( filelength FILELENGTH_EXISTS ) @@ -629,6 +639,12 @@ elseif( FLUIDSYNTH_FOUND ) add_definitions( -DHAVE_FLUIDSYNTH ) endif() +option( SEND_ANON_STATS "Enable sending of anonymous hardware statistics" ON ) + +if( NOT SEND_ANON_STATS ) + add_definitions( -DNO_SEND_STATS ) +endif() + # Project files should be aware of the header files. We can GLOB these since # there's generally a new cpp for every header so this file will get changed if( WIN32 ) @@ -668,6 +684,9 @@ file( GLOB HEADER_FILES scripting/decorate/*.h scripting/zscript/*.h scripting/vm/*.h + sound/midisources/*.h + sound/oplsynth/*.h + sound/oplsynth/dosbox/*.h sound/timidity/*.h sound/timiditypp/*.h sound/wildmidi/*.h @@ -871,6 +890,7 @@ set (PCH_SOURCES d_dehacked.cpp d_iwad.cpp d_main.cpp + d_stats.cpp d_net.cpp d_netinfo.cpp d_protocol.cpp @@ -884,6 +904,7 @@ set (PCH_SOURCES edata.cpp f_wipe.cpp files.cpp + files_decompress.cpp g_doomedmap.cpp g_game.cpp g_hub.cpp @@ -1099,6 +1120,7 @@ set (PCH_SOURCES textures/tgatexture.cpp textures/warptexture.cpp textures/skyboxtexture.cpp + textures/worldtexture.cpp xlat/parse_xlat.cpp fragglescript/t_func.cpp fragglescript/t_load.cpp diff --git a/src/am_map.cpp b/src/am_map.cpp index 452f82b78..2f6c04c6d 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -138,6 +138,7 @@ 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_unexploredsecretcolor, 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); @@ -158,6 +159,7 @@ CVAR (Color, am_ovunseencolor, 0x00226e, CVAR_ARCHIVE); CVAR (Color, am_ovtelecolor, 0xffff00, CVAR_ARCHIVE); CVAR (Color, am_ovinterlevelcolor, 0xffff00, CVAR_ARCHIVE); CVAR (Color, am_ovsecretsectorcolor,0x00ffff, CVAR_ARCHIVE); +CVAR (Color, am_ovunexploredsecretcolor,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); @@ -230,6 +232,7 @@ static const char *ColorNames[] = { "IntraTeleportColor", "InterTeleportColor", "SecretSectorColor", + "UnexploredSecretColor", "PortalColor", "AlmostBackgroundColor", NULL @@ -261,6 +264,7 @@ struct AMColorset IntraTeleportColor, InterTeleportColor, SecretSectorColor, + UnexploredSecretColor, PortalColor, AlmostBackgroundColor, AM_NUM_COLORS @@ -362,6 +366,7 @@ static FColorCVar *cv_standard[] = { &am_intralevelcolor, &am_interlevelcolor, &am_secretsectorcolor, + &am_unexploredsecretcolor, &am_portalcolor }; @@ -388,6 +393,7 @@ static FColorCVar *cv_overlay[] = { &am_ovtelecolor, &am_ovinterlevelcolor, &am_ovsecretsectorcolor, + &am_ovunexploredsecretcolor, &am_ovportalcolor }; @@ -430,6 +436,7 @@ static unsigned char DoomColors[]= { NOT_USED, // intrateleport NOT_USED, // interteleport NOT_USED, // secretsector + NOT_USED, // unexploredsecretsector 0x10,0x10,0x10, // almostbackground 0x40,0x40,0x40 // portal }; @@ -457,6 +464,7 @@ static unsigned char StrifeColors[]= { NOT_USED, // intrateleport NOT_USED, // interteleport NOT_USED, // secretsector + NOT_USED, // unexploredsecretsector 0x10,0x10,0x10, // almostbackground 0x40,0x40,0x40 // portal }; @@ -484,6 +492,7 @@ static unsigned char RavenColors[]= { NOT_USED, // intrateleport NOT_USED, // interteleport NOT_USED, // secretsector + NOT_USED, // unexploredsecretsector 0x10,0x10,0x10, // almostbackground 0x50,0x50,0x50 // portal }; @@ -2209,7 +2218,7 @@ void AM_drawSubsectors() // //============================================================================= -static bool AM_CheckSecret(line_t *line) +static int AM_CheckSecret(line_t *line) { if (AMColors.isValid(AMColors.SecretSectorColor)) { @@ -2217,20 +2226,20 @@ static bool AM_CheckSecret(line_t *line) { if (line->frontsector->wasSecret()) { - if (am_map_secrets!=0 && !line->frontsector->isSecret()) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (am_map_secrets!=0 && !line->frontsector->isSecret()) return 1; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return 2; } } if (line->backsector != NULL) { if (line->backsector->wasSecret()) { - if (am_map_secrets!=0 && !line->backsector->isSecret()) return true; - if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true; + if (am_map_secrets!=0 && !line->backsector->isSecret()) return 1; + if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return 2; } } } - return false; + return 0; } @@ -2584,11 +2593,15 @@ void AM_drawWalls (bool allmap) { AM_drawMline(&l, AMColors.PortalColor); } - else if (AM_CheckSecret(&line)) + else if (AM_CheckSecret(&line) == 1) { // map secret sectors like Boom AM_drawMline(&l, AMColors.SecretSectorColor); } + else if (AM_CheckSecret(&line) == 2) + { + AM_drawMline(&l, AMColors.UnexploredSecretColor); + } else if (line.flags & ML_SECRET) { // secret door if (am_cheat != 0 && line.backsector != NULL) @@ -3075,7 +3088,7 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust, DTA_TranslationIndex, translation, DTA_Alpha, alpha, DTA_FillColor, fillcolor, - DTA_RenderStyle, uint32_t(renderstyle), + DTA_RenderStyle, renderstyle.AsDWORD, TAG_DONE); } diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 842516ba3..f74eae569 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -1224,7 +1224,7 @@ CCMD(secret) int lumpno=Wads.CheckNumForName("SECRETS"); if (lumpno < 0) return; - FWadLump lump = Wads.OpenLumpNum(lumpno); + auto lump = Wads.OpenLumpReader(lumpno); FString maphdr; maphdr.Format("[%s]", mapname); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index ddabdb772..a3e2773af 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -564,6 +564,8 @@ static void stripwhite (char *str) static char *igets (void) { + assert(PatchPt != nullptr); + char *line; if (*PatchPt == '\0' || PatchPt >= PatchFile + PatchSize ) @@ -2494,9 +2496,9 @@ bool D_LoadDehFile(const char *patchfile) { FileReader fr; - if (fr.Open(patchfile)) + if (fr.OpenFile(patchfile)) { - PatchSize = fr.GetLength(); + PatchSize = (int)fr.GetLength(); PatchName = copystring(patchfile); PatchFile = new char[PatchSize + 1]; @@ -2536,7 +2538,7 @@ static bool DoDehPatch() cont = 0; if (0 == strncmp (PatchFile, "Patch File for DeHackEd v", 25)) { - if (PatchFile[25] < '3' && PatchFile[25] != '2' && PatchFile[27] != '3') + if (PatchFile[25] < '3' && (PatchFile[25] < '2' || PatchFile[27] < '3')) { Printf (PRINT_BOLD, "\"%s\" is an old and unsupported DeHackEd patch\n", PatchName); delete[] PatchName; @@ -2550,16 +2552,16 @@ static bool DoDehPatch() } PatchPt = strchr (PatchFile, '\n'); - while ((cont = GetLine()) == 1) + while (PatchPt != nullptr && (cont = GetLine()) == 1) { CHECKKEY ("Doom version", dversion) else CHECKKEY ("Patch format", pversion) } if (!cont || dversion == -1 || pversion == -1) { + Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", PatchName); delete[] PatchName; delete[] PatchFile; - Printf (PRINT_BOLD, "\"%s\" is not a DeHackEd patch file\n", PatchFile); return false; } } diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index fadb9e65b..29c3ea98b 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -243,7 +243,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, FIWadManager::FIWadManager(const char *fn) { - FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); + FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true); if (resfile != NULL) { uint32_t cnt = resfile->LumpCount(); @@ -276,7 +276,7 @@ FIWadManager::FIWadManager(const char *fn) int FIWadManager::ScanIWAD (const char *iwad) { - FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, NULL, true); + FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, true); mLumpsFound.Resize(mIWadInfos.Size()); @@ -332,7 +332,7 @@ int FIWadManager::ScanIWAD (const char *iwad) int FIWadManager::CheckIWADInfo(const char *fn) { - FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); + FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true); if (resfile != NULL) { uint32_t cnt = resfile->LumpCount(); diff --git a/src/d_main.cpp b/src/d_main.cpp index 0b03cf098..007af39d5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -121,6 +121,8 @@ EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); +void D_DoAnonStats(); + // MACROS ------------------------------------------------------------------ @@ -1947,7 +1949,6 @@ static FString CheckGameInfo(TArray & pwads) for(int i=pwads.Size()-1; i>=0; i--) { bool isdir = false; - FileReader *wadinfo; FResourceFile *resfile; const char *filename = pwads[i]; @@ -1960,16 +1961,13 @@ static FString CheckGameInfo(TArray & pwads) if (!isdir) { - try - { - wadinfo = new FileReader(filename); - } - catch (CRecoverableError &) + FileReader fr; + if (!fr.OpenFile(filename)) { // Didn't find file continue; } - resfile = FResourceFile::OpenResourceFile(filename, wadinfo, true); + resfile = FResourceFile::OpenResourceFile(filename, fr, true); } else resfile = FResourceFile::OpenDirectory(filename, true); @@ -2354,6 +2352,9 @@ void D_DoomMain (void) D_DoomInit(); + extern void D_ConfirmSendStats(); + D_ConfirmSendStats(); + // [RH] Make sure zdoom.pk3 is always loaded, // as it contains magic stuff we need. wad = BaseFileSearch (BASEWAD, NULL, true); @@ -2748,6 +2749,8 @@ void D_DoomMain (void) setmodeneeded = false; // This may be set to true here, but isn't needed for a restart } + D_DoAnonStats(); + if (I_FriendlyWindowTitle) I_SetWindowTitle(DoomStartupInfo.Name.GetChars()); diff --git a/src/d_net.cpp b/src/d_net.cpp index 57dbb93b7..7681626d0 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1914,6 +1914,10 @@ void TryRunTics (void) // Check possible stall conditions Net_CheckLastReceived (counts); + // Update time returned by I_GetTime, but only if we are stuck in this loop + if (lowtic < gametic + counts) + I_SetFrameTime(); + // don't stay in here forever -- give the menu a chance to work if (I_GetTime () - entertic >= 1) { diff --git a/src/d_stats.cpp b/src/d_stats.cpp new file mode 100644 index 000000000..e6c0e196b --- /dev/null +++ b/src/d_stats.cpp @@ -0,0 +1,360 @@ + +#ifdef NO_SEND_STATS + +void D_DoAnonStats() +{ +} + +void D_ConfirmSendStats() +{ +} + +#else // !NO_SEND_STATS + +#if defined(_WIN32) +#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN +#include +#include +extern int sys_ostype; +#else +#ifdef __APPLE__ +#include +#else // !__APPLE__ +#include +#endif // __APPLE__ +#include +#include +#include +#include +#include +#endif + +#include +#include "c_cvars.h" +#include "x86.h" +#include "version.h" +#include "v_video.h" + +EXTERN_CVAR(Bool, vid_glswfb) +extern int currentrenderer; +CVAR(Int, sys_statsenabled, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) +CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) +CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) + +// Each machine will only send two reports, one when started with hardware rendering and one when started with software rendering. +#define CHECKVERSION 331 +#define CHECKVERSIONSTR "331" +CVAR(Int, sentstats_swr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) +CVAR(Int, sentstats_hwr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) + +std::pair gl_getInfo(); + + +#ifdef _WIN32 + +bool I_HTTPRequest(const char* request) +{ + if (sys_statshost.GetHumanString() == NULL) + return false; // no host, disable + + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) + { + DPrintf(DMSG_ERROR, "WSAStartup failed.\n"); + return false; + } + SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + struct hostent *host; + host = gethostbyname(sys_statshost.GetHumanString()); + if (host == nullptr) + { + DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); + return false; + } + SOCKADDR_IN SockAddr; + SockAddr.sin_port = htons(sys_statsport); + SockAddr.sin_family = AF_INET; + SockAddr.sin_addr.s_addr = *((uint32_t*)host->h_addr); + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", sys_statshost.GetHumanString()); + if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) + { + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); + return false; + } + send(Socket, request, (int)strlen(request), 0); + char buffer[1024]; + int nDataLength; + while ((nDataLength = recv(Socket, buffer, 1024, 0)) > 0) + { + int i = 0; + while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') + { + i++; + } + } + closesocket(Socket); + WSACleanup(); + DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); + return true; +} +#else +bool I_HTTPRequest(const char* request) +{ + if (sys_statshost.GetHumanString() == NULL || sys_statshost.GetHumanString()[0] == 0) + return false; // no host, disable + + int sockfd, portno, n; + struct sockaddr_in serv_addr; + struct hostent *server; + + portno = sys_statsport; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + { + DPrintf(DMSG_ERROR, "Error opening TCP socket.\n"); + return false; + } + + server = gethostbyname(sys_statshost.GetHumanString()); + if (server == NULL) + { + DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); + return false; + } + bzero((char*) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + + DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", sys_statshost.GetHumanString()); + if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); + return false; + } + + n = write(sockfd, request, strlen(request)); + if (n<0) + { + DPrintf(DMSG_ERROR, "Error writing to socket.\n"); + close(sockfd); + return false; + } + + char buffer[1024] = {}; + n = read(sockfd, buffer, 1023); + close(sockfd); + DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); + return true; +} +#endif + +static int GetOSVersion() +{ +#ifdef _WIN32 + if (sys_ostype == 1) return 1; + if (sizeof(void*) == 4) // 32 bit + { + BOOL res; + if (IsWow64Process(GetCurrentProcess(), &res) && res) + { + return 6; + } + if (sys_ostype == 2) return 2; + else return 4; + } + else + { + if (sys_ostype == 2) return 3; + else return 5; + } + +#elif defined __APPLE__ + + if (sizeof(void*) == 4) // 32 bit + { + return 7; + } + else + { + return 8; + } + +#else + +// fall-through linux stuff here +#ifdef __arm__ + return 10; +#elif __ppc__ + return 9; +#else + if (sizeof(void*) == 4) // 32 bit + { + return 11; + } + else + { + return 12; + } +#endif + + +#endif +} + + +#ifdef _WIN32 + +static int GetCoreInfo() +{ + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; + DWORD returnLength = 0; + int cores = 0; + uint32_t byteOffset = 0; + + auto rc = GetLogicalProcessorInformation(buffer, &returnLength); + + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength); + if (!GetLogicalProcessorInformation(buffer, &returnLength)) return 0; + } + else + { + return 0; + } + + ptr = buffer; + + while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) + { + if (ptr->Relationship == RelationProcessorCore) cores++; + byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + ptr++; + } + free(buffer); + return cores < 2 ? 0 : cores < 4 ? 1 : cores < 6 ? 2 : cores < 8 ? 3 : 4; +} + +#else +static int GetCoreInfo() +{ + int cores = std::thread::hardware_concurrency(); + if (CPU.HyperThreading) cores /= 2; + return cores < 2? 0 : cores < 4? 1 : cores < 6? 2 : cores < 8? 3 : 4; +} +#endif + +static int GetRenderInfo() +{ + if (currentrenderer == 0) + { + if (!screen->Accel2D) return 0; + if (vid_glswfb) return 2; + if (screen->LegacyHardware()) return 6; + return 1; + } + else + { + auto info = gl_getInfo(); + if (info.first < 3.3) return 3; // Legacy OpenGL. Don't care about Intel HD 3000 on Windows being run in 'risky' mode. + if (!info.second) return 4; + return 5; + } +} + +static void D_DoHTTPRequest(const char *request) +{ + if (I_HTTPRequest(request)) + { + if (currentrenderer == 0) + { + cvar_forceset("sentstats_swr_done", CHECKVERSIONSTR); + } + else + { + cvar_forceset("sentstats_hwr_done", CHECKVERSIONSTR); + } + } +} + +void D_DoAnonStats() +{ + if (sys_statsenabled != 1) + { + return; + } + + static bool done = false; // do this only once per session. + if (done) return; + done = true; + + // Do not repeat if already sent. + if (currentrenderer == 0 && sentstats_swr_done >= CHECKVERSION) return; + if (currentrenderer == 1 && sentstats_hwr_done >= CHECKVERSION) return; + + static char requeststring[1024]; + mysnprintf(requeststring, sizeof requeststring, "GET /stats.py?render=%i&cores=%i&os=%i&renderconfig=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", + GetRenderInfo(), GetCoreInfo(), GetOSVersion(), currentrenderer, sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); + DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); + std::thread t1(D_DoHTTPRequest, requeststring); + t1.detach(); +} + +void D_ConfirmSendStats() +{ + if (sys_statsenabled >= 0) + { + return; + } + + // TODO: texts + static const char *const MESSAGE_TEXT = "send stats?"; + static const char *const TITLE_TEXT = GAMENAME; + + UCVarValue enabled = { 0 }; + +#ifdef _WIN32 + extern HWND Window; + enabled.Int = MessageBox(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES; +#elif defined __APPLE__ + const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); + const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); + if (messageString != nullptr && titleString != nullptr) + { + CFOptionFlags response; + const SInt32 result = CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, nullptr, nullptr, nullptr, + titleString, messageString, CFSTR("Yes"), CFSTR("No"), nullptr, &response); + enabled.Int = result == 0 && (response & 3) == kCFUserNotificationDefaultResponse; + CFRelease(titleString); + CFRelease(messageString); + } +#else // !__APPLE__ + const SDL_MessageBoxButtonData buttons[] = + { + { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "Yes" }, + { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "No" }, + }; + const SDL_MessageBoxData messageboxdata = + { + SDL_MESSAGEBOX_INFORMATION, + nullptr, + TITLE_TEXT, + MESSAGE_TEXT, + SDL_arraysize(buttons), + buttons, + nullptr + }; + int buttonid; + enabled.Int = SDL_ShowMessageBox(&messageboxdata, &buttonid) == 0 && buttonid == 0; +#endif // _WIN32 + + sys_statsenabled.ForceSet(enabled, CVAR_Int); +} + +#endif // NO_SEND_STATS diff --git a/src/dthinker.cpp b/src/dthinker.cpp index a415dff03..39de2e9d6 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -41,6 +41,8 @@ #include "serializer.h" #include "d_player.h" #include "vm.h" +#include "c_dispatch.h" +#include "v_text.h" static int ThinkCount; @@ -462,7 +464,57 @@ void DThinker::DestroyThinkersInList (FThinkerList &list) // // //========================================================================== -CVAR(Bool, profilethinkers, false, 0) +static unsigned int profilethinkers, profilelimit; + +CCMD(profilethinkers) +{ + const int argc = argv.argc(); + + if (argc == 2 || argc == 3) + { + const char *str = argv[1]; + bool ascend = true; + + if (*str == '+') + { + ++str; + } + else if (*str == '-') + { + ascend = false; + ++str; + } + + int mode = 0; + + switch (*str) + { + case 't': mode = ascend ? 7 : 8; break; + case 'a': mode = ascend ? 5 : 6; break; + case '#': mode = ascend ? 3 : 4; break; + case 'c': mode = ascend ? 1 : 2; break; + default: mode = atoi(str); break; + } + + profilethinkers = mode; + profilelimit = argc == 3 ? atoi(argv[2]) : 0; + } + else + { + Printf( + "Usage: profilethinkers [+|-][t|a|#|c] [limit]\n" + " profilethinkers [1..8] [limit]\n\n" + "Sorting modes:\n" + TEXTCOLOR_YELLOW "c +c 1 " TEXTCOLOR_NORMAL "actor class, ascending\n" + TEXTCOLOR_YELLOW " -c 2 " TEXTCOLOR_NORMAL "actor class, descending\n" + TEXTCOLOR_YELLOW "# +# 3 " TEXTCOLOR_NORMAL "number of calls, ascending\n" + TEXTCOLOR_YELLOW " -# 4 " TEXTCOLOR_NORMAL "number of calls, descending\n" + TEXTCOLOR_YELLOW "a +a 5 " TEXTCOLOR_NORMAL "average time, ascending\n" + TEXTCOLOR_YELLOW " -a 6 " TEXTCOLOR_NORMAL "average time, descending\n" + TEXTCOLOR_YELLOW "t +t 7 " TEXTCOLOR_NORMAL "total time, ascending\n" + TEXTCOLOR_YELLOW " -t 8 " TEXTCOLOR_NORMAL "total time, descending\n"); + } +} struct ProfileInfo { @@ -526,13 +578,63 @@ void DThinker::RunThinkers () count += ProfileThinkers(&FreshThinkers[i], &Thinkers[i]); } } while (count != 0); + + struct SortedProfileInfo + { + const char* className; + int numcalls; + double time; + }; + + TArray sorted; + sorted.Grow(Profiles.CountUsed()); + auto it = TMap::Iterator(Profiles); TMap::Pair *pair; while (it.NextPair(pair)) { - Printf("%s, %dx, %fms\n", pair->Key.GetChars(), pair->Value.numcalls, pair->Value.timer.TimeMS()); + sorted.Push({ pair->Key.GetChars(), pair->Value.numcalls, pair->Value.timer.TimeMS() }); } - profilethinkers = false; + + std::sort(sorted.begin(), sorted.end(), [](const SortedProfileInfo& left, const SortedProfileInfo& right) + { + switch (profilethinkers) + { + case 1: // by name, from A to Z + return stricmp(left.className, right.className) < 0; + case 2: // by name, from Z to A + return stricmp(right.className, left.className) < 0; + case 3: // number of calls, ascending + return left.numcalls < right.numcalls; + case 4: // number of calls, descending + return right.numcalls < left.numcalls; + case 5: // average time, ascending + return left.time / left.numcalls < right.time / right.numcalls; + case 6: // average time, descending + return right.time / right.numcalls < left.time / left.numcalls; + case 7: // total time, ascending + return left.time < right.time; + default: // total time, descending + return right.time < left.time; + } + }); + + Printf(TEXTCOLOR_YELLOW "Total, ms Averg, ms Calls Actor class\n"); + Printf(TEXTCOLOR_YELLOW "---------- ---------- ------ --------------------\n"); + + const unsigned count = MIN(profilelimit > 0 ? profilelimit : UINT_MAX, sorted.Size()); + + for (unsigned i = 0; i < count; ++i) + { + const SortedProfileInfo& info = sorted[i]; + Printf("%s%10.6f %s%10.6f %s%6d %s%s\n", + profilethinkers >= 7 ? TEXTCOLOR_YELLOW : TEXTCOLOR_WHITE, info.time, + profilethinkers == 5 || profilethinkers == 6 ? TEXTCOLOR_YELLOW : TEXTCOLOR_WHITE, info.time / info.numcalls, + profilethinkers == 3 || profilethinkers == 4 ? TEXTCOLOR_YELLOW : TEXTCOLOR_WHITE, info.numcalls, + profilethinkers == 1 || profilethinkers == 2 ? TEXTCOLOR_YELLOW : TEXTCOLOR_WHITE, info.className); + } + + profilethinkers = 0; } ThinkCycles.Unclock(); diff --git a/src/files.cpp b/src/files.cpp index 1b0e5db1f..93a2f4587 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -33,150 +33,250 @@ ** */ -// This also pulls in windows.h -#include "LzmaDec.h" - #include "files.h" #include "i_system.h" #include "templates.h" #include "m_misc.h" + //========================================================================== // -// FileReader +// StdFileReader // -// reads data from an uncompressed file or part of it +// reads data from an stdio FILE* or part of it. // //========================================================================== -FILE *FileReader::openfd(const char *filename) +class StdFileReader : public FileReaderInterface { - return fopen(filename, "rb"); -} + FILE *File = nullptr; + long StartPos = 0; + long FilePos = 0; -FileReader::FileReader () -: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ -} +public: + StdFileReader() + {} -FileReader::FileReader (const FileReader &other, long length) -: File(other.File), Length(length), CloseOnDestruct(false) -{ - FilePos = StartPos = ftell (other.File); -} - -FileReader::FileReader (const char *filename) -: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ - if (!Open(filename)) + ~StdFileReader() { - I_Error ("Could not open %s", filename); + if (File != nullptr) + { + fclose(File); + } + File = nullptr; } -} -FileReader::FileReader (FILE *file) -: File(file), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ - Length = CalcFileLen(); -} - -FileReader::FileReader (FILE *file, long length) -: File(file), Length(length), CloseOnDestruct(true) -{ - FilePos = StartPos = ftell (file); -} - -FileReader::~FileReader() -{ - Close(); -} - -void FileReader::Close() -{ - if (CloseOnDestruct && File != NULL) + bool Open(const char *filename, long startpos = 0, long len = -1) { - fclose (File); + File = fopen(filename, "rb"); + if (File == nullptr) return false; + FilePos = startpos; + StartPos = startpos; + Length = CalcFileLen(); + if (len >= 0 && len < Length) Length = len; + if (startpos > 0) Seek(0, SEEK_SET); + return true; } - File = NULL; -} -bool FileReader::Open (const char *filename) -{ - File = openfd (filename); - if (File == NULL) return false; - FilePos = 0; - StartPos = 0; - CloseOnDestruct = true; - Length = CalcFileLen(); - return true; -} - - -void FileReader::ResetFilePtr () -{ - FilePos = ftell (File); -} - -long FileReader::Tell () const -{ - return FilePos - StartPos; -} - -long FileReader::Seek (long offset, int origin) -{ - if (origin == SEEK_SET) + long Tell() const override { - offset += StartPos; + return FilePos - StartPos; } - else if (origin == SEEK_CUR) + + long Seek(long offset, int origin) override { + if (origin == SEEK_SET) + { + offset += StartPos; + } + else if (origin == SEEK_CUR) + { + offset += FilePos; + } + else if (origin == SEEK_END) + { + offset += StartPos + Length; + } + if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope + + if (0 == fseek(File, offset, SEEK_SET)) + { + FilePos = offset; + return 0; + } + return -1; + } + + long Read(void *buffer, long len) override + { + assert(len >= 0); + if (len <= 0) return 0; + if (FilePos + len > StartPos + Length) + { + len = Length - FilePos + StartPos; + } + len = (long)fread(buffer, 1, len, File); + FilePos += len; + return len; + } + + char *Gets(char *strbuf, int len) override + { + if (len <= 0 || FilePos >= StartPos + Length) return NULL; + char *p = fgets(strbuf, len, File); + if (p != NULL) + { + int old = FilePos; + FilePos = ftell(File); + if (FilePos - StartPos > Length) + { + strbuf[Length - old + StartPos] = 0; + } + } + return p; + } + +private: + long CalcFileLen() const + { + long endpos; + + fseek(File, 0, SEEK_END); + endpos = ftell(File); + fseek(File, 0, SEEK_SET); + return endpos; + } +}; + +//========================================================================== +// +// FileReaderRedirect +// +// like the above, but uses another File reader as its backing data +// +//========================================================================== + +class FileReaderRedirect : public FileReaderInterface +{ + FileReader *mReader = nullptr; + long StartPos = 0; + long FilePos = 0; + +public: + FileReaderRedirect(FileReader &parent, long start, long length) + { + mReader = &parent; + FilePos = start; + StartPos = start; + Length = length; + Seek(0, SEEK_SET); + } + + virtual long Tell() const override + { + return FilePos - StartPos; + } + + virtual long Seek(long offset, int origin) + { + switch (origin) + { + case SEEK_SET: + offset += StartPos; + break; + + case SEEK_END: + offset += StartPos + Length; + break; + + case SEEK_CUR: + offset += (long)mReader->Tell(); + break; + } + if (offset < StartPos || offset > StartPos + Length) return -1; // out of scope + if (mReader->Seek(offset, FileReader::SeekSet) == 0) + { + FilePos = offset; + return 0; + } + return -1; + } + + virtual long Read(void *buffer, long len) + { + assert(len >= 0); + if (len <= 0) return 0; + if (FilePos + len > StartPos + Length) + { + len = Length - FilePos + StartPos; + } + len = (long)mReader->Read(buffer, len); + FilePos += len; + return len; + } + + virtual char *Gets(char *strbuf, int len) + { + if (len <= 0 || FilePos >= StartPos + Length) return NULL; + char *p = mReader->Gets(strbuf, len); + if (p != NULL) + { + int old = FilePos; + FilePos = (long)mReader->Tell(); + if (FilePos - StartPos > Length) + { + strbuf[Length - old + StartPos] = 0; + } + } + return p; + } + +}; + +//========================================================================== +// +// MemoryReader +// +// reads data from a block of memory +// +//========================================================================== + +long MemoryReader::Tell() const +{ + return FilePos; +} + +long MemoryReader::Seek(long offset, int origin) +{ + switch (origin) + { + case SEEK_CUR: offset += FilePos; + break; + + case SEEK_END: + offset += Length; + break; + } - else if (origin == SEEK_END) - { - offset += StartPos + Length; - } - if (0 == fseek (File, offset, SEEK_SET)) - { - FilePos = offset; - return 0; - } - return -1; + if (offset < 0 || offset >= Length) return -1; + FilePos = clamp(offset, 0, Length); + return 0; } -long FileReader::Read (void *buffer, long len) +long MemoryReader::Read(void *buffer, long len) { - assert(len >= 0); - if (len <= 0) return 0; - if (FilePos + len > StartPos + Length) - { - len = Length - FilePos + StartPos; - } - len = (long)fread (buffer, 1, len, File); + if (len>Length - FilePos) len = Length - FilePos; + if (len<0) len = 0; + memcpy(buffer, bufptr + FilePos, len); FilePos += len; return len; } -char *FileReader::Gets(char *strbuf, int len) +char *MemoryReader::Gets(char *strbuf, int len) { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; - char *p = fgets(strbuf, len, File); - if (p != NULL) - { - int old = FilePos; - FilePos = ftell(File); - if (FilePos - StartPos > Length) - { - strbuf[Length - old + StartPos] = 0; - } - } - return p; -} - -char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) -{ - if (len>Length-FilePos) len=Length-FilePos; + if (len>Length - FilePos) len = Length - FilePos; if (len <= 0) return NULL; char *p = strbuf; @@ -191,7 +291,7 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) { *p++ = bufptr[FilePos]; len--; - if (bufptr[FilePos] == '\n') + if (bufptr[FilePos] == '\n') { FilePos++; break; @@ -199,360 +299,11 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) } FilePos++; } - if (p==strbuf) return NULL; - *p++=0; + if (p == strbuf) return NULL; + *p++ = 0; return strbuf; } -long FileReader::CalcFileLen() const -{ - long endpos; - - fseek (File, 0, SEEK_END); - endpos = ftell (File); - fseek (File, 0, SEEK_SET); - return endpos; -} - -//========================================================================== -// -// FileReaderZ -// -// The zlib wrapper -// reads data from a ZLib compressed stream -// -//========================================================================== - -FileReaderZ::FileReaderZ (FileReader &file, bool zip) -: File(file), SawEOF(false) -{ - int err; - - FillBuffer (); - - Stream.zalloc = Z_NULL; - Stream.zfree = Z_NULL; - - if (!zip) err = inflateInit (&Stream); - else err = inflateInit2 (&Stream, -MAX_WBITS); - - if (err != Z_OK) - { - I_Error ("FileReaderZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); - } -} - -FileReaderZ::~FileReaderZ () -{ - inflateEnd (&Stream); -} - -long FileReaderZ::Read (void *buffer, long len) -{ - int err; - - Stream.next_out = (Bytef *)buffer; - Stream.avail_out = len; - - do - { - err = inflate (&Stream, Z_SYNC_FLUSH); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == Z_OK && Stream.avail_out != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - I_Error ("Corrupt zlib stream"); - } - - if (Stream.avail_out != 0) - { - I_Error ("Ran out of data in zlib stream"); - } - - return len - Stream.avail_out; -} - -void FileReaderZ::FillBuffer () -{ - long numread = File.Read (InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = InBuff; - Stream.avail_in = numread; -} - -//========================================================================== -// -// FileReaderZ -// -// The bzip2 wrapper -// reads data from a libbzip2 compressed stream -// -//========================================================================== - -FileReaderBZ2::FileReaderBZ2 (FileReader &file) -: File(file), SawEOF(false) -{ - int err; - - FillBuffer (); - - Stream.bzalloc = NULL; - Stream.bzfree = NULL; - Stream.opaque = NULL; - - err = BZ2_bzDecompressInit(&Stream, 0, 0); - - if (err != BZ_OK) - { - I_Error ("FileReaderBZ2: bzDecompressInit failed: %d\n", err); - } -} - -FileReaderBZ2::~FileReaderBZ2 () -{ - BZ2_bzDecompressEnd (&Stream); -} - -long FileReaderBZ2::Read (void *buffer, long len) -{ - int err; - - Stream.next_out = (char *)buffer; - Stream.avail_out = len; - - do - { - err = BZ2_bzDecompress(&Stream); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == BZ_OK && Stream.avail_out != 0); - - if (err != BZ_OK && err != BZ_STREAM_END) - { - I_Error ("Corrupt bzip2 stream"); - } - - if (Stream.avail_out != 0) - { - I_Error ("Ran out of data in bzip2 stream"); - } - - return len - Stream.avail_out; -} - -void FileReaderBZ2::FillBuffer () -{ - long numread = File.Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = (char *)InBuff; - Stream.avail_in = numread; -} - -//========================================================================== -// -// bz_internal_error -// -// libbzip2 wants this, since we build it with BZ_NO_STDIO set. -// -//========================================================================== - -extern "C" void bz_internal_error (int errcode) -{ - I_FatalError("libbzip2: internal error number %d\n", errcode); -} - -//========================================================================== -// -// FileReaderLZMA -// -// The lzma wrapper -// reads data from a LZMA compressed stream -// -//========================================================================== - -// This is retarded but necessary to work around the inclusion of windows.h in recent -// LZMA versions, meaning it's no longer possible to include the LZMA headers in files.h. -// As a result we cannot declare the CLzmaDec member in the header so we work around -// it my wrapping it into another struct that can be declared anonymously in the header. -struct FileReaderLZMA::StreamPointer -{ - CLzmaDec Stream; -}; - -static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); } -static void SzFree(ISzAllocPtr, void *address) { free(address); } -ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip) -: File(file), SawEOF(false) -{ - uint8_t header[4 + LZMA_PROPS_SIZE]; - int err; - - assert(zip == true); - - Size = uncompressed_size; - OutProcessed = 0; - - // Read zip LZMA properties header - if (File.Read(header, sizeof(header)) < (long)sizeof(header)) - { - I_Error("FileReaderLZMA: File too shart\n"); - } - if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) - { - I_Error("FileReaderLZMA: LZMA props size is %d (expected %d)\n", - header[2] + header[3] * 256, LZMA_PROPS_SIZE); - } - - FillBuffer(); - - Streamp = new StreamPointer; - LzmaDec_Construct(&Streamp->Stream); - err = LzmaDec_Allocate(&Streamp->Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); - - if (err != SZ_OK) - { - I_Error("FileReaderLZMA: LzmaDec_Allocate failed: %d\n", err); - } - - LzmaDec_Init(&Streamp->Stream); -} - -FileReaderLZMA::~FileReaderLZMA () -{ - LzmaDec_Free(&Streamp->Stream, &g_Alloc); - delete Streamp; -} - -long FileReaderLZMA::Read (void *buffer, long len) -{ - int err; - Byte *next_out = (Byte *)buffer; - - do - { - ELzmaFinishMode finish_mode = LZMA_FINISH_ANY; - ELzmaStatus status; - size_t out_processed = len; - size_t in_processed = InSize; - - err = LzmaDec_DecodeToBuf(&Streamp->Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); - InPos += in_processed; - InSize -= in_processed; - next_out += out_processed; - len = (long)(len - out_processed); - if (err != SZ_OK) - { - I_Error ("Corrupt LZMA stream"); - } - if (in_processed == 0 && out_processed == 0) - { - if (status != LZMA_STATUS_FINISHED_WITH_MARK) - { - I_Error ("Corrupt LZMA stream"); - } - } - if (InSize == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == SZ_OK && len != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - I_Error ("Corrupt LZMA stream"); - } - - if (len != 0) - { - I_Error ("Ran out of data in LZMA stream"); - } - - return (long)(next_out - (Byte *)buffer); -} - -void FileReaderLZMA::FillBuffer () -{ - long numread = File.Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - InPos = 0; - InSize = numread; -} - -//========================================================================== -// -// MemoryReader -// -// reads data from a block of memory -// -//========================================================================== - -MemoryReader::MemoryReader (const char *buffer, long length) -{ - bufptr=buffer; - Length=length; - FilePos=0; -} - -MemoryReader::~MemoryReader () -{ -} - -long MemoryReader::Tell () const -{ - return FilePos; -} - -long MemoryReader::Seek (long offset, int origin) -{ - switch (origin) - { - case SEEK_CUR: - offset+=FilePos; - break; - - case SEEK_END: - offset+=Length; - break; - - } - FilePos=clamp(offset,0,Length); - return 0; -} - -long MemoryReader::Read (void *buffer, long len) -{ - if (len>Length-FilePos) len=Length-FilePos; - if (len<0) len=0; - memcpy(buffer,bufptr+FilePos,len); - FilePos+=len; - return len; -} - -char *MemoryReader::Gets(char *strbuf, int len) -{ - return GetsFromBuffer(bufptr, strbuf, len); -} - //========================================================================== // // MemoryArrayReader @@ -561,53 +312,90 @@ char *MemoryReader::Gets(char *strbuf, int len) // //========================================================================== -MemoryArrayReader::MemoryArrayReader (const char *buffer, long length) +class MemoryArrayReader : public MemoryReader { - buf.Resize(length); - memcpy(&buf[0], buffer, length); - Length=length; - FilePos=0; + TArray buf; + +public: + MemoryArrayReader(const char *buffer, long length) + { + if (length > 0) + { + buf.Resize(length); + memcpy(&buf[0], buffer, length); + } + UpdateBuffer(); + } + + TArray &GetArray() { return buf; } + + void UpdateBuffer() + { + bufptr = (const char*)&buf[0]; + FilePos = 0; + Length = buf.Size(); + } +}; + + + +//========================================================================== +// +// FileReader +// +// this wraps the different reader types in an object with value semantics. +// +//========================================================================== + +bool FileReader::OpenFile(const char *filename, FileReader::Size start, FileReader::Size length) +{ + auto reader = new StdFileReader; + if (!reader->Open(filename, (long)start, (long)length)) return false; + Close(); + mReader = reader; + return true; } -MemoryArrayReader::~MemoryArrayReader () +bool FileReader::OpenFilePart(FileReader &parent, FileReader::Size start, FileReader::Size length) { + auto reader = new FileReaderRedirect(parent, (long)start, (long)length); + Close(); + mReader = reader; + return true; } -long MemoryArrayReader::Tell () const +bool FileReader::OpenMemory(const void *mem, FileReader::Size length) { - return FilePos; + Close(); + mReader = new MemoryReader((const char *)mem, (long)length); + return true; } -long MemoryArrayReader::Seek (long offset, int origin) +bool FileReader::OpenMemoryArray(const void *mem, FileReader::Size length) { - switch (origin) - { - case SEEK_CUR: - offset+=FilePos; - break; - - case SEEK_END: - offset+=Length; - break; - - } - FilePos=clamp(offset,0,Length); - return 0; + Close(); + mReader = new MemoryArrayReader((const char *)mem, (long)length); + return true; } -long MemoryArrayReader::Read (void *buffer, long len) +bool FileReader::OpenMemoryArray(std::function&)> getter) { - if (len>Length-FilePos) len=Length-FilePos; - if (len<0) len=0; - memcpy(buffer,&buf[FilePos],len); - FilePos+=len; - return len; + auto reader = new MemoryArrayReader(nullptr, 0); + if (getter(reader->GetArray())) + { + Close(); + reader->UpdateBuffer(); + mReader = reader; + return true; + } + else + { + // This will keep the old buffer, if one existed + delete reader; + return false; + } } -char *MemoryArrayReader::Gets(char *strbuf, int len) -{ - return GetsFromBuffer((char*)&buf[0], strbuf, len); -} //========================================================================== // @@ -668,7 +456,6 @@ long FileWriter::Seek(long offset, int mode) } } - size_t FileWriter::Printf(const char *fmt, ...) { va_list ap; @@ -686,4 +473,3 @@ size_t BufferWriter::Write(const void *buffer, size_t len) memcpy(&mBuffer[ofs], buffer, len); return len; } - diff --git a/src/files.h b/src/files.h index 808f24d94..89e6a091d 100644 --- a/src/files.h +++ b/src/files.h @@ -37,361 +37,229 @@ #define FILES_H #include -#include -#include "bzlib.h" +#include #include "doomtype.h" #include "m_swap.h" -class FileReaderBase +// Zip compression methods, extended by some internal types to be passed to OpenDecompressor +enum +{ + METHOD_STORED = 0, + METHOD_SHRINK = 1, + METHOD_IMPLODE = 6, + METHOD_DEFLATE = 8, + METHOD_BZIP2 = 12, + METHOD_LZMA = 14, + METHOD_PPMD = 98, + METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression + METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes. +}; + +class FileReaderInterface { public: - virtual ~FileReaderBase() {} + long Length = -1; + virtual ~FileReaderInterface() {} + virtual long Tell () const = 0; + virtual long Seek (long offset, int origin) = 0; virtual long Read (void *buffer, long len) = 0; - - FileReaderBase &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBase &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBase &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBase &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBase &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderBase &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -}; - - -class FileReader : public FileReaderBase -{ -protected: - FILE *openfd(const char *filename); -public: - FileReader (); - FileReader (const char *filename); - FileReader (FILE *file); - FileReader (FILE *file, long length); - bool Open (const char *filename); - void Close(); - virtual ~FileReader (); - - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); + virtual char *Gets(char *strbuf, int len) = 0; + virtual const char *GetBuffer() const { return nullptr; } long GetLength () const { return Length; } +}; - // If you use the underlying FILE without going through this class, - // you must call ResetFilePtr() before using this class again. - void ResetFilePtr (); - - FILE *GetFile () const { return File; } - virtual const char *GetBuffer() const { return NULL; } - - FileReader &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReader &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReader &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReader &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReader &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - +class DecompressorBase : public FileReaderInterface +{ +public: + // These do not work but need to be defined to satisfy the FileReaderInterface. + // They will just error out when called. + long Tell() const override; + long Seek(long offset, int origin) override; + char *Gets(char *strbuf, int len) override; +}; +class MemoryReader : public FileReaderInterface +{ protected: - FileReader (const FileReader &other, long length); + const char * bufptr = nullptr; + long FilePos = 0; - char *GetsFromBuffer(const char * bufptr, char *strbuf, int len); - - FILE *File; - long Length; - long StartPos; - long FilePos; - -private: - long CalcFileLen () const; -protected: - bool CloseOnDestruct; -}; - -// Wraps around a FileReader to decompress a zlib stream -class FileReaderZ : public FileReaderBase -{ -public: - FileReaderZ (FileReader &file, bool zip=false); - ~FileReaderZ (); - - virtual long Read (void *buffer, long len); - - FileReaderZ &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderZ &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderZ &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderZ &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderZ &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderZ &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - z_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderZ &operator= (const FileReaderZ &) { return *this; } -}; - -// Wraps around a FileReader to decompress a bzip2 stream -class FileReaderBZ2 : public FileReaderBase -{ -public: - FileReaderBZ2 (FileReader &file); - ~FileReaderBZ2 (); - - long Read (void *buffer, long len); - - FileReaderBZ2 &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBZ2 &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBZ2 &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBZ2 &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBZ2 &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderBZ2 &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - bz_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderBZ2 &operator= (const FileReaderBZ2 &) { return *this; } -}; - -// Wraps around a FileReader to decompress a lzma stream -class FileReaderLZMA : public FileReaderBase -{ - struct StreamPointer; + MemoryReader() + {} public: - FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip); - ~FileReaderLZMA (); - - long Read (void *buffer, long len); - - FileReaderLZMA &operator>> (uint8_t &v) + MemoryReader(const char *buffer, long length) { - Read (&v, 1); - return *this; + bufptr = buffer; + Length = length; + FilePos = 0; } - FileReaderLZMA &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderLZMA &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderLZMA &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderLZMA &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderLZMA &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - StreamPointer *Streamp; // anonymous pointer to LKZA decoder struct - to avoid including the LZMA headers globally - size_t Size; - size_t InPos, InSize; - size_t OutProcessed; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderLZMA &operator= (const FileReaderLZMA &) { return *this; } + long Tell() const override; + long Seek(long offset, int origin) override; + long Read(void *buffer, long len) override; + char *Gets(char *strbuf, int len) override; + virtual const char *GetBuffer() const override { return bufptr; } }; -class MemoryReader : public FileReader + +struct FResourceLump; + +class FileReader { + friend struct FResourceLump; // needs access to the private constructor. + + FileReaderInterface *mReader = nullptr; + + FileReader(const FileReader &r) = delete; + FileReader &operator=(const FileReader &r) = delete; + + explicit FileReader(FileReaderInterface *r) + { + mReader = r; + } + public: - MemoryReader (const char *buffer, long length); - ~MemoryReader (); + enum ESeek + { + SeekSet = SEEK_SET, + SeekCur = SEEK_CUR, + SeekEnd = SEEK_END + }; - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); - virtual const char *GetBuffer() const { return bufptr; } + typedef ptrdiff_t Size; // let's not use 'long' here. -protected: - const char * bufptr; + FileReader() {} + + FileReader(FileReader &&r) + { + mReader = r.mReader; + r.mReader = nullptr; + } + + FileReader& operator =(FileReader &&r) + { + Close(); + mReader = r.mReader; + r.mReader = nullptr; + return *this; + } + + + ~FileReader() + { + Close(); + } + + bool isOpen() const + { + return mReader != nullptr; + } + + void Close() + { + if (mReader != nullptr) delete mReader; + mReader = nullptr; + } + + bool OpenFile(const char *filename, Size start = 0, Size length = -1); + bool OpenFilePart(FileReader &parent, Size start, Size length); + bool OpenMemory(const void *mem, Size length); // read directly from the buffer + bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer. + bool OpenMemoryArray(std::function&)> getter); // read contents to a buffer and return a reader to it + bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used. + + Size Tell() const + { + return mReader->Tell(); + } + + Size Seek(Size offset, ESeek origin) + { + return mReader->Seek((long)offset, origin); + } + + Size Read(void *buffer, Size len) + { + return mReader->Read(buffer, (long)len); + } + + char *Gets(char *strbuf, Size len) + { + return mReader->Gets(strbuf, (int)len); + } + + const char *GetBuffer() + { + return mReader->GetBuffer(); + } + + Size GetLength() const + { + return mReader->GetLength(); + } + + uint8_t ReadUInt8() + { + uint8_t v = 0; + Read(&v, 1); + return v; + } + + int8_t ReadInt8() + { + int8_t v = 0; + Read(&v, 1); + return v; + } + + uint16_t ReadUInt16() + { + uint16_t v = 0; + Read(&v, 2); + return LittleShort(v); + } + + int16_t ReadInt16() + { + uint16_t v = 0; + Read(&v, 2); + return LittleShort(v); + } + + uint32_t ReadUInt32() + { + uint32_t v = 0; + Read(&v, 4); + return LittleLong(v); + } + + int32_t ReadInt32() + { + uint32_t v = 0; + Read(&v, 4); + return LittleLong(v); + } + + uint32_t ReadUInt32BE() + { + uint32_t v = 0; + Read(&v, 4); + return BigLong(v); + } + + int32_t ReadInt32BE() + { + uint32_t v = 0; + Read(&v, 4); + return BigLong(v); + } + + + friend class FWadCollection; }; -class MemoryArrayReader : public FileReader -{ -public: - MemoryArrayReader (const char *buffer, long length); - ~MemoryArrayReader (); - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); - virtual const char *GetBuffer() const { return (char*)&buf[0]; } - TArray &GetArray() { return buf; } - - void UpdateLength() { Length = buf.Size(); } - -protected: - TArray buf; -}; class FileWriter @@ -435,7 +303,4 @@ public: TArray *GetBuffer() { return &mBuffer; } }; - - - #endif diff --git a/src/files_decompress.cpp b/src/files_decompress.cpp new file mode 100644 index 000000000..b6ba8fbcb --- /dev/null +++ b/src/files_decompress.cpp @@ -0,0 +1,604 @@ +/* +** files.cpp +** Implements classes for reading from files or memory blocks +** +**--------------------------------------------------------------------------- +** Copyright 1998-2008 Randy Heit +** Copyright 2005-2008 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. +**--------------------------------------------------------------------------- +** +*/ + +// This also pulls in windows.h +#include "LzmaDec.h" +#include +#include + +#include "files.h" +#include "i_system.h" +#include "templates.h" +#include "m_misc.h" + + +long DecompressorBase::Tell () const +{ + I_Error("Cannot get position of decompressor stream"); + return 0; +} +long DecompressorBase::Seek (long offset, int origin) +{ + I_Error("Cannot seek in decompressor stream"); + return 0; +} +char *DecompressorBase::Gets(char *strbuf, int len) +{ + I_Error("Cannot use Gets on decompressor stream"); + return nullptr; +} + +//========================================================================== +// +// DecompressorZ +// +// The zlib wrapper +// reads data from a ZLib compressed stream +// +//========================================================================== + +class DecompressorZ : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileReader &File; + bool SawEOF; + z_stream Stream; + uint8_t InBuff[BUFF_SIZE]; + +public: + DecompressorZ (FileReader &file, bool zip) + : File(file), SawEOF(false) + { + int err; + + FillBuffer (); + + Stream.zalloc = Z_NULL; + Stream.zfree = Z_NULL; + + if (!zip) err = inflateInit (&Stream); + else err = inflateInit2 (&Stream, -MAX_WBITS); + + if (err != Z_OK) + { + I_Error ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); + } + } + + ~DecompressorZ () + { + inflateEnd (&Stream); + } + + long Read (void *buffer, long len) override + { + int err; + + Stream.next_out = (Bytef *)buffer; + Stream.avail_out = len; + + do + { + err = inflate (&Stream, Z_SYNC_FLUSH); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == Z_OK && Stream.avail_out != 0); + + if (err != Z_OK && err != Z_STREAM_END) + { + I_Error ("Corrupt zlib stream"); + } + + if (Stream.avail_out != 0) + { + I_Error ("Ran out of data in zlib stream"); + } + + return len - Stream.avail_out; + } + + void FillBuffer () + { + auto numread = File.Read (InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.next_in = InBuff; + Stream.avail_in = (uInt)numread; + } +}; + + +//========================================================================== +// +// DecompressorZ +// +// The bzip2 wrapper +// reads data from a libbzip2 compressed stream +// +//========================================================================== + +class DecompressorBZ2 : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileReader &File; + bool SawEOF; + bz_stream Stream; + uint8_t InBuff[BUFF_SIZE]; + +public: + DecompressorBZ2 (FileReader &file) + : File(file), SawEOF(false) + { + int err; + + FillBuffer (); + + Stream.bzalloc = NULL; + Stream.bzfree = NULL; + Stream.opaque = NULL; + + err = BZ2_bzDecompressInit(&Stream, 0, 0); + + if (err != BZ_OK) + { + I_Error ("DecompressorBZ2: bzDecompressInit failed: %d\n", err); + } + } + + ~DecompressorBZ2 () + { + BZ2_bzDecompressEnd (&Stream); + } + + long Read (void *buffer, long len) override + { + int err; + + Stream.next_out = (char *)buffer; + Stream.avail_out = len; + + do + { + err = BZ2_bzDecompress(&Stream); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == BZ_OK && Stream.avail_out != 0); + + if (err != BZ_OK && err != BZ_STREAM_END) + { + I_Error ("Corrupt bzip2 stream"); + } + + if (Stream.avail_out != 0) + { + I_Error ("Ran out of data in bzip2 stream"); + } + + return len - Stream.avail_out; + } + + void FillBuffer () + { + auto numread = File.Read(InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.next_in = (char *)InBuff; + Stream.avail_in = (unsigned)numread; + } + +}; + +//========================================================================== +// +// bz_internal_error +// +// libbzip2 wants this, since we build it with BZ_NO_STDIO set. +// +//========================================================================== + +extern "C" void bz_internal_error (int errcode) +{ + I_FatalError("libbzip2: internal error number %d\n", errcode); +} + +//========================================================================== +// +// DecompressorLZMA +// +// The lzma wrapper +// reads data from a LZMA compressed stream +// +//========================================================================== + +static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); } +static void SzFree(ISzAllocPtr, void *address) { free(address); } +ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +// Wraps around a Decompressor to decompress a lzma stream +class DecompressorLZMA : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileReader &File; + bool SawEOF; + CLzmaDec Stream; + size_t Size; + size_t InPos, InSize; + size_t OutProcessed; + uint8_t InBuff[BUFF_SIZE]; + +public: + + DecompressorLZMA (FileReader &file, size_t uncompressed_size) + : File(file), SawEOF(false) + { + uint8_t header[4 + LZMA_PROPS_SIZE]; + int err; + + Size = uncompressed_size; + OutProcessed = 0; + + // Read zip LZMA properties header + if (File.Read(header, sizeof(header)) < (long)sizeof(header)) + { + I_Error("DecompressorLZMA: File too short\n"); + } + if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) + { + I_Error("DecompressorLZMA: LZMA props size is %d (expected %d)\n", + header[2] + header[3] * 256, LZMA_PROPS_SIZE); + } + + FillBuffer(); + + LzmaDec_Construct(&Stream); + err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); + + if (err != SZ_OK) + { + I_Error("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err); + } + + LzmaDec_Init(&Stream); + } + + ~DecompressorLZMA () + { + LzmaDec_Free(&Stream, &g_Alloc); + } + + long Read (void *buffer, long len) override + { + int err; + Byte *next_out = (Byte *)buffer; + + do + { + ELzmaFinishMode finish_mode = LZMA_FINISH_ANY; + ELzmaStatus status; + size_t out_processed = len; + size_t in_processed = InSize; + + err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); + InPos += in_processed; + InSize -= in_processed; + next_out += out_processed; + len = (long)(len - out_processed); + if (err != SZ_OK) + { + I_Error ("Corrupt LZMA stream"); + } + if (in_processed == 0 && out_processed == 0) + { + if (status != LZMA_STATUS_FINISHED_WITH_MARK) + { + I_Error ("Corrupt LZMA stream"); + } + } + if (InSize == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == SZ_OK && len != 0); + + if (err != Z_OK && err != Z_STREAM_END) + { + I_Error ("Corrupt LZMA stream"); + } + + if (len != 0) + { + I_Error ("Ran out of data in LZMA stream"); + } + + return (long)(next_out - (Byte *)buffer); + } + + void FillBuffer () + { + auto numread = File.Read(InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + InPos = 0; + InSize = numread; + } + +}; + +//========================================================================== +// +// Console Doom LZSS wrapper. +// +//========================================================================== + +class DecompressorLZSS : public DecompressorBase +{ + enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; + + FileReader &File; + bool SawEOF; + uint8_t InBuff[BUFF_SIZE]; + + enum StreamState + { + STREAM_EMPTY, + STREAM_BITS, + STREAM_FLUSH, + STREAM_FINAL + }; + struct + { + StreamState State; + + uint8_t *In; + unsigned int AvailIn; + unsigned int InternalOut; + + uint8_t CFlags, Bits; + + uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE]; + const uint8_t *WindowData; + uint8_t *InternalBuffer; + } Stream; + + void FillBuffer() + { + if(Stream.AvailIn) + memmove(InBuff, Stream.In, Stream.AvailIn); + + auto numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.In = InBuff; + Stream.AvailIn = (unsigned)numread+Stream.AvailIn; + } + + // Reads a flag byte. + void PrepareBlocks() + { + assert(Stream.InternalBuffer == Stream.WindowData); + Stream.CFlags = *Stream.In++; + --Stream.AvailIn; + Stream.Bits = 0xFF; + Stream.State = STREAM_BITS; + } + + // Reads the next chunk in the block. Returns true if successful and + // returns false if it ran out of input data. + bool UncompressBlock() + { + if(Stream.CFlags & 1) + { + // Check to see if we have enough input + if(Stream.AvailIn < 2) + return false; + Stream.AvailIn -= 2; + + uint16_t pos = BigShort(*(uint16_t*)Stream.In); + uint8_t len = (pos & 0xF)+1; + pos >>= 4; + Stream.In += 2; + if(len == 1) + { + // We've reached the end of the stream. + Stream.State = STREAM_FINAL; + return true; + } + + const uint8_t* copyStart = Stream.InternalBuffer-pos-1; + + // Complete overlap: Single byte repeated + if(pos == 0) + memset(Stream.InternalBuffer, *copyStart, len); + // No overlap: One copy + else if(pos >= len) + memcpy(Stream.InternalBuffer, copyStart, len); + else + { + // Partial overlap: Copy in 2 or 3 chunks. + do + { + unsigned int copy = MIN(len, pos+1); + memcpy(Stream.InternalBuffer, copyStart, copy); + Stream.InternalBuffer += copy; + Stream.InternalOut += copy; + len -= copy; + pos += copy; // Increase our position since we can copy twice as much the next round. + } + while(len); + } + + Stream.InternalOut += len; + Stream.InternalBuffer += len; + } + else + { + // Uncompressed byte. + *Stream.InternalBuffer++ = *Stream.In++; + --Stream.AvailIn; + ++Stream.InternalOut; + } + + Stream.CFlags >>= 1; + Stream.Bits >>= 1; + + // If we're done with this block, flush the output + if(Stream.Bits == 0) + Stream.State = STREAM_FLUSH; + + return true; + } + +public: + DecompressorLZSS(FileReader &file) : File(file), SawEOF(false) + { + Stream.State = STREAM_EMPTY; + Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; + Stream.InternalOut = 0; + Stream.AvailIn = 0; + + FillBuffer(); + } + + ~DecompressorLZSS() + { + } + + long Read(void *buffer, long len) override + { + + uint8_t *Out = (uint8_t*)buffer; + long AvailOut = len; + + do + { + while(Stream.AvailIn) + { + if(Stream.State == STREAM_EMPTY) + PrepareBlocks(); + else if(Stream.State == STREAM_BITS && !UncompressBlock()) + break; + else + break; + } + + unsigned int copy = MIN(Stream.InternalOut, AvailOut); + if(copy > 0) + { + memcpy(Out, Stream.WindowData, copy); + Out += copy; + AvailOut -= copy; + + // Slide our window + memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy); + Stream.InternalBuffer -= copy; + Stream.InternalOut -= copy; + } + + if(Stream.State == STREAM_FINAL) + break; + + if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH) + Stream.State = STREAM_EMPTY; + + if(Stream.AvailIn < 2) + FillBuffer(); + } + while(AvailOut && Stream.State != STREAM_FINAL); + + assert(AvailOut == 0); + return (long)(Out - (uint8_t*)buffer); + } +}; + + +bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable) +{ + DecompressorBase *dec = nullptr; + switch (method) + { + case METHOD_DEFLATE: + case METHOD_ZLIB: + dec = new DecompressorZ(parent, method == METHOD_DEFLATE); + break; + + case METHOD_BZIP2: + dec = new DecompressorBZ2(parent); + break; + + case METHOD_LZMA: + dec = new DecompressorLZMA(parent, length); + break; + + case METHOD_LZSS: + dec = new DecompressorLZSS(parent); + break; + + // todo: METHOD_IMPLODE, METHOD_SHRINK + default: + return false; + } + dec->Length = (long)length; + if (!seekable) + { + Close(); + mReader = dec; + return true; + } + else + { + // todo: create a wrapper. for now this fails + delete dec; + return false; + } +} diff --git a/src/g_game.cpp b/src/g_game.cpp index 2ca349631..b2f58990c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1930,7 +1930,7 @@ void G_DoLoadGame () hidecon = gameaction == ga_loadgamehidecon; gameaction = ga_nothing; - std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true)); + std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), true, true)); if (resfile == nullptr) { Printf ("Could not read savegame '%s'\n", savename.GetChars()); @@ -2372,7 +2372,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio savegame_content[2].Clean(); // Check whether the file is ok by trying to open it. - FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr, true); + FResourceFile *test = FResourceFile::OpenResourceFile(filename, true); if (test != nullptr) { delete test; @@ -2802,7 +2802,7 @@ void G_DoPlayDemo (void) FixPathSeperator (defdemoname); DefaultExtension (defdemoname, ".lmp"); FileReader fr; - if (!fr.Open(defdemoname)) + if (!fr.OpenFile(defdemoname)) { I_Error("Unable to open demo '%s'", defdemoname.GetChars()); } diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index ff98ea421..2ed33954b 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -82,6 +82,7 @@ DEFINE_FIELD(AInventory, MaxAmount) DEFINE_FIELD(AInventory, InterHubAmount) DEFINE_FIELD(AInventory, RespawnTics) DEFINE_FIELD(AInventory, Icon) +DEFINE_FIELD(AInventory, AltHUDIcon) DEFINE_FIELD(AInventory, DropTime) DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, PickupFlash) @@ -147,6 +148,7 @@ void AInventory::Serialize(FSerializer &arc) ("respawntics", RespawnTics, def->RespawnTics) ("itemflags", ItemFlags, def->ItemFlags) ("icon", Icon, def->Icon) + ("althudicon", AltHUDIcon, def->AltHUDIcon) ("pickupsound", PickupSound, def->PickupSound) ("spawnpointclass", SpawnPointClass, def->SpawnPointClass) ("droptime", DropTime, def->DropTime); diff --git a/src/g_pch.h b/src/g_pch.h index cad5a8409..bf2833cf8 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -23,6 +23,7 @@ #include #include #include +#include // These two headers get included nearly everywhere so it doesn't matter if changing them forces a few more recompiles. // The overall savings from PCHing them are more significant. diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 1ac8b33fe..3f0fe4dbf 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -41,6 +41,7 @@ void gl_PatchMenu(); static TArray m_Extensions; RenderContext gl; +static double realglversion; // this is public so the statistics code can access it. EXTERN_CVAR(Bool, gl_legacy_mode) extern int currentrenderer; @@ -59,7 +60,7 @@ static void CollectExtensions() int max = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &max); - if (0 == max) + if (max == 0) { // Try old method to collect extensions const char *supported = (char *)glGetString(GL_EXTENSIONS); @@ -144,6 +145,8 @@ void gl_LoadExtensions() } const char *version = Args->CheckValue("-glversion"); + realglversion = strtod(glversion, NULL); + if (version == NULL) { @@ -152,9 +155,8 @@ void gl_LoadExtensions() else { double v1 = strtod(version, NULL); - double v2 = strtod(glversion, NULL); if (v1 >= 3.0 && v1 < 3.3) v1 = 3.3; // promote '3' to 3.3 to avoid falling back to the legacy path. - if (v2 < v1) version = glversion; + if (realglversion < v1) version = glversion; else Printf("Emulating OpenGL v %s\n", version); } @@ -385,3 +387,9 @@ void gl_PrintStartupLog() } +std::pair gl_getInfo() +{ + // gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL. + // This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support. + return std::make_pair(realglversion, CheckExtension("GL_ARB_bindless_texture")); +} \ No newline at end of file diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index 859706772..98f0559d9 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -31,6 +31,7 @@ #include "r_utility.h" #include "templates.h" #include "sc_man.h" +#include "r_data/renderstyle.h" #include "colormatcher.h" #include "textures/warpbuffer.h" #include "textures/bitmap.h" @@ -297,7 +298,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (hwtex) { // Texture has become invalid - if ((!tex->bHasCanvas && (!tex->bWarped || gl.legacyMode)) && tex->CheckModified()) + if ((!tex->bHasCanvas && (!tex->bWarped || gl.legacyMode)) && tex->CheckModified(DefaultRenderStyle())) { Clean(true); hwtex = CreateHwTexture(); @@ -323,7 +324,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla WarpBuffer((uint32_t*)warpbuffer, (const uint32_t*)buffer, w, h, wt->WidthOffsetMultiplier, wt->HeightOffsetMultiplier, screen->FrameTime, wt->Speed, tex->bWarped); delete[] buffer; buffer = warpbuffer; - wt->GenTime = screen->FrameTime; + wt->GenTime[0] = screen->FrameTime; } tex->ProcessData(buffer, w, h, false); } diff --git a/src/gl/textures/gl_texture.cpp b/src/gl/textures/gl_texture.cpp index 0d3e84e4b..f228d2123 100644 --- a/src/gl/textures/gl_texture.cpp +++ b/src/gl/textures/gl_texture.cpp @@ -238,7 +238,7 @@ void FTexture::CreateDefaultBrightmap() ) { // May have one - let's check when we use this texture - const uint8_t *texbuf = GetPixels(); + const uint8_t *texbuf = GetPixels(DefaultRenderStyle()); const int white = ColorMatcher.Pick(255,255,255); int size = GetWidth() * GetHeight(); @@ -523,24 +523,11 @@ FBrightmapTexture::FBrightmapTexture (FTexture *source) SourceLump = -1; } -FBrightmapTexture::~FBrightmapTexture () -{ -} - -const uint8_t *FBrightmapTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - // not needed - return NULL; -} - -const uint8_t *FBrightmapTexture::GetPixels () -{ - // not needed - return NULL; -} - -void FBrightmapTexture::Unload () +uint8_t *FBrightmapTexture::MakeTexture(FRenderStyle style) { + // This function is only necessary to satisfy the parent class's interface. + // This will never be called. + return nullptr; } int FBrightmapTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) diff --git a/src/gl/textures/gl_texture.h b/src/gl/textures/gl_texture.h index 80eede02f..44016f181 100644 --- a/src/gl/textures/gl_texture.h +++ b/src/gl/textures/gl_texture.h @@ -4,23 +4,17 @@ #include "r_defs.h" #include "textures/textures.h" -class FBrightmapTexture : public FTexture +class FBrightmapTexture : public FWorldTexture { public: FBrightmapTexture (FTexture *source); - ~FBrightmapTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf); - bool UseBasePalette() { return false; } + uint8_t *MakeTexture(FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; + bool UseBasePalette() override { return false; } protected: FTexture *SourcePic; - //uint8_t *Pixels; - //Span **Spans; }; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 481f956b5..ea55a906c 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -122,14 +122,14 @@ void M_FindResponseFile (void) { // READ THE RESPONSE FILE INTO MEMORY FileReader fr; - if (!fr.Open(Args->GetArg(i) + 1)) + if (!fr.OpenFile(Args->GetArg(i) + 1)) { // [RH] Make this a warning, not an error. Printf ("No such response file (%s)!\n", Args->GetArg(i) + 1); } else { Printf ("Found response file %s!\n", Args->GetArg(i) + 1); - size = fr.GetLength(); + size = (int)fr.GetLength(); file = new char[size+1]; fr.Read (file, size); file[size] = 0; diff --git a/src/m_png.cpp b/src/m_png.cpp index a7f82ed8f..ac2035ee6 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -75,22 +75,17 @@ struct IHDR uint8_t Interlace; }; -PNGHandle::PNGHandle (FILE *file) : File(0), bDeleteFilePtr(true), ChunkPt(0) +PNGHandle::PNGHandle (FileReader &file) : bDeleteFilePtr(true), ChunkPt(0) { - File = new FileReader(file); + File = std::move(file); } -PNGHandle::PNGHandle (FileReader *file, bool takereader) : File(file), bDeleteFilePtr(takereader), ChunkPt(0) {} PNGHandle::~PNGHandle () { for (unsigned int i = 0; i < TextChunks.Size(); ++i) { delete[] TextChunks[i]; } - if (bDeleteFilePtr) - { - delete File; - } } // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- @@ -269,7 +264,7 @@ bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text) { crc = AddCRC32 (crc, (uint8_t *)text, len); } - crc = BigLong((unsigned int)crc); + crc = BigLong(crc); return file->Write (&crc, 4) == 4; } return false; @@ -309,7 +304,7 @@ unsigned int M_NextPNGChunk (PNGHandle *png, uint32_t id) { if (png->Chunks[png->ChunkPt].ID == id) { // Found the chunk - png->File->Seek (png->Chunks[png->ChunkPt++].Offset, SEEK_SET); + png->File.Seek (png->Chunks[png->ChunkPt++].Offset, FileReader::SeekSet); return png->Chunks[png->ChunkPt - 1].Size; } } @@ -374,46 +369,43 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf // //========================================================================== -PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) +PNGHandle *M_VerifyPNG (FileReader &filer) { PNGHandle::Chunk chunk; PNGHandle *png; uint32_t data[2]; bool sawIDAT = false; - if (filer->Read(&data, 8) != 8) + if (filer.Read(&data, 8) != 8) { - if (takereader) delete filer; return NULL; } if (data[0] != MAKE_ID(137,'P','N','G') || data[1] != MAKE_ID(13,10,26,10)) { // Does not have PNG signature - if (takereader) delete filer; return NULL; } - if (filer->Read (&data, 8) != 8) + if (filer.Read (&data, 8) != 8) { - if (takereader) delete filer; return NULL; } if (data[1] != MAKE_ID('I','H','D','R')) { // IHDR must be the first chunk - if (takereader) delete filer; return NULL; } // It looks like a PNG so far, so start creating a PNGHandle for it - png = new PNGHandle (filer, takereader); + png = new PNGHandle (filer); + // filer is no longer valid after the above line! chunk.ID = data[1]; chunk.Offset = 16; chunk.Size = BigLong((unsigned int)data[0]); png->Chunks.Push (chunk); - filer->Seek (16, SEEK_SET); + png->File.Seek (16, FileReader::SeekSet); - while (filer->Seek (chunk.Size + 4, SEEK_CUR) == 0) + while (png->File.Seek (chunk.Size + 4, FileReader::SeekCur) == 0) { // If the file ended before an IEND was encountered, it's not a PNG. - if (filer->Read (&data, 8) != 8) + if (png->File.Read (&data, 8) != 8) { break; } @@ -432,7 +424,7 @@ PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) sawIDAT = true; } chunk.ID = data[1]; - chunk.Offset = filer->Tell(); + chunk.Offset = (uint32_t)png->File.Tell(); chunk.Size = BigLong((unsigned int)data[0]); png->Chunks.Push (chunk); @@ -441,7 +433,7 @@ PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) { char *str = new char[chunk.Size + 1]; - if (filer->Read (str, chunk.Size) != (long)chunk.Size) + if (png->File.Read (str, chunk.Size) != chunk.Size) { delete[] str; break; @@ -452,6 +444,7 @@ PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader) } } + filer = std::move(png->File); // need to get the reader back if this function failed. delete png; return NULL; } @@ -477,7 +470,7 @@ void M_FreePNG (PNGHandle *png) // //========================================================================== -bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int pitch, +bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int pitch, uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int chunklen) { // Uninterlaced images are treated as a conceptual eighth pass by these tables. @@ -574,7 +567,7 @@ bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int p if (stream.avail_in == 0 && chunklen > 0) { stream.next_in = chunkbuffer; - stream.avail_in = (uInt)file->Read (chunkbuffer, MIN(chunklen,sizeof(chunkbuffer))); + stream.avail_in = (uInt)file.Read (chunkbuffer, MIN(chunklen,sizeof(chunkbuffer))); chunklen -= stream.avail_in; } @@ -666,7 +659,7 @@ bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int p { uint32_t x[3]; - if (file->Read (x, 12) != 12) + if (file.Read (x, 12) != 12) { lastIDAT = true; } diff --git a/src/m_png.h b/src/m_png.h index 7bc9b474f..10fd4c8e6 100644 --- a/src/m_png.h +++ b/src/m_png.h @@ -36,8 +36,8 @@ #include #include "doomtype.h" #include "v_video.h" +#include "files.h" -class FileReader; class FileWriter; // PNG Writing -------------------------------------------------------------- @@ -64,7 +64,6 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height // PNG Reading -------------------------------------------------------------- -class FileReader; struct PNGHandle { struct Chunk @@ -74,14 +73,13 @@ struct PNGHandle uint32_t Size; }; - FileReader *File; + FileReader File; bool bDeleteFilePtr; TArray Chunks; TArray TextChunks; unsigned int ChunkPt; - PNGHandle(FILE *file); - PNGHandle(FileReader *file, bool takereader = false); + PNGHandle(FileReader &file); ~PNGHandle(); }; @@ -89,7 +87,7 @@ struct PNGHandle // the signature, but also checking for the IEND chunk. CRC checking of // each chunk is not done. If it is valid, you get a PNGHandle to pass to // the following functions. -PNGHandle *M_VerifyPNG (FileReader *file, bool takereader = false); +PNGHandle *M_VerifyPNG (FileReader &file); // Finds a chunk in a PNG file. The file pointer will be positioned at the // beginning of the chunk data, and its length will be returned. A return @@ -108,7 +106,7 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf // The file must be positioned at the start of the first IDAT. It reads // image data into the provided buffer. Returns true on success. -bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int pitch, +bool M_ReadIDAT (FileReader &file, uint8_t *buffer, int width, int height, int pitch, uint8_t bitdepth, uint8_t colortype, uint8_t interlace, unsigned int idatlen); diff --git a/src/m_swap.h b/src/m_swap.h index a68a0837b..a3e03bea2 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -46,16 +46,6 @@ inline unsigned int LittleLong(unsigned int x) return OSSwapLittleToHostInt32(x); } -inline int LittleLong(long x) -{ - return OSSwapLittleToHostInt32((uint32_t)x); -} - -inline unsigned int LittleLong(unsigned long x) -{ - return OSSwapLittleToHostInt32((uint32_t)x); -} - inline short BigShort(short x) { return (short)OSSwapBigToHostInt16((uint16_t)x); @@ -76,8 +66,7 @@ inline unsigned int BigLong(unsigned int x) return OSSwapBigToHostInt32(x); } -#else -#ifdef __BIG_ENDIAN__ +#elif defined __BIG_ENDIAN__ // Swap 16bit, that is, MSB and LSB byte. // No masking with 0xFF should be necessary. @@ -120,42 +109,66 @@ inline int LittleLong (int x) | (((unsigned int)x)<<24)); } -inline unsigned int LittleLong(unsigned long x) +inline short BigShort(short x) { - return LittleLong((unsigned int)x); + return x; } -inline int LittleLong(long x) +inline unsigned short BigShort(unsigned short x) { - return LittleLong((int)x); + return x; } -#define BigShort(x) (x) -#define BigLong(x) (x) +inline unsigned int BigLong(unsigned int &x) +{ + return x; +} + +inline int BigLong(int &x) +{ + return x; +} #else -#define LittleShort(x) (x) -#define LittleLong(x) (x) +inline short LittleShort(short x) +{ + return x; +} -#if defined(_MSC_VER) +inline unsigned short LittleShort(unsigned short x) +{ + return x; +} -inline short BigShort (short x) +inline unsigned int LittleLong(unsigned int x) +{ + return x; +} + +inline int LittleLong(int x) +{ + return x; +} + +#ifdef _MSC_VER + +inline short BigShort(short x) { return (short)_byteswap_ushort((unsigned short)x); } -inline unsigned short BigShort (unsigned short x) +inline unsigned short BigShort(unsigned short x) { return _byteswap_ushort(x); } -inline int BigLong (int x) +inline int BigLong(int x) { return (int)_byteswap_ulong((unsigned long)x); } -inline unsigned int BigLong (unsigned int x) +inline unsigned int BigLong(unsigned int x) { return (unsigned int)_byteswap_ulong((unsigned long)x); } @@ -190,10 +203,16 @@ inline int BigLong (int x) | ((((unsigned int)x)<<8) & 0xff0000) | (((unsigned int)x)<<24)); } + #endif #endif // __BIG_ENDIAN__ -#endif // __APPLE__ + +// These may be destructive so they should create errors +unsigned long BigLong(unsigned long) = delete; +long BigLong(long) = delete; +unsigned long LittleLong(unsigned long) = delete; +long LittleLong(long) = delete; // Data accessors, since some data is highly likely to be unaligned. @@ -206,10 +225,6 @@ inline int GetInt(const unsigned char *foo) { return *(const int *)foo; } -inline int GetBigInt(const unsigned char *foo) -{ - return BigLong(GetInt(foo)); -} #else inline int GetShort(const unsigned char *foo) { @@ -219,11 +234,12 @@ inline int GetInt(const unsigned char *foo) { return int(foo[0] | (foo[1] << 8) | (foo[2] << 16) | (foo[3] << 24)); } +#endif inline int GetBigInt(const unsigned char *foo) { return int((foo[0] << 24) | (foo[1] << 16) | (foo[2] << 8) | foo[3]); } -#endif + #ifdef __BIG_ENDIAN__ inline int GetNativeInt(const unsigned char *foo) { diff --git a/src/md5.cpp b/src/md5.cpp index d345e00d6..1e0f72440 100644 --- a/src/md5.cpp +++ b/src/md5.cpp @@ -95,16 +95,16 @@ void MD5Context::Update(const uint8_t *buf, unsigned len) memcpy(in, buf, len); } -void MD5Context::Update(FileReader *file, unsigned len) +void MD5Context::Update(FileReader &file, unsigned len) { uint8_t readbuf[8192]; long t; - while (len != 0) + while (len > 0) { t = MIN(len, sizeof(readbuf)); len -= t; - t = file->Read(readbuf, t); + t = (long)file.Read(readbuf, t); Update(readbuf, t); } } @@ -270,7 +270,7 @@ CCMD (md5sum) for (int i = 1; i < argv.argc(); ++i) { FileReader fr; - if (!fr.Open(argv[i])) + if (!fr.OpenFile(argv[i])) { Printf("%s: %s\n", argv[i], strerror(errno)); } diff --git a/src/md5.h b/src/md5.h index a645919db..82d4f32dc 100644 --- a/src/md5.h +++ b/src/md5.h @@ -26,7 +26,7 @@ struct MD5Context void Init(); void Update(const uint8_t *buf, unsigned len); - void Update(FileReader *file, unsigned len); + void Update(FileReader &file, unsigned len); void Final(uint8_t digest[16]); private: diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index c9fb7aeba..7d4b1ebf4 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -174,7 +174,7 @@ void FSavegameManager::ReadSaveStrings() // I_FindName only returns the file's name and not its full path FString filepath = G_BuildSaveName(I_FindName(&c_file), -1); - FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, nullptr, true, true); + FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true); if (savegame != nullptr) { bool oldVer = false; @@ -237,7 +237,7 @@ void FSavegameManager::ReadSaveStrings() else // check for old formats. { FileReader file; - if (file.Open(filepath)) + if (file.OpenFile(filepath)) { PNGHandle *png; char sig[16]; @@ -255,7 +255,7 @@ void FSavegameManager::ReadSaveStrings() title[OLDSAVESTRINGSIZE] = 0; - if (nullptr != (png = M_VerifyPNG(&file, false))) + if (nullptr != (png = M_VerifyPNG(file))) { char *ver = M_GetPNGText(png, "ZDoom Save Version"); if (ver != nullptr) @@ -272,7 +272,7 @@ void FSavegameManager::ReadSaveStrings() } else { - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); if (file.Read(sig, 16) == 16) { @@ -469,7 +469,7 @@ unsigned FSavegameManager::ExtractSaveData(int index) (node = SaveGames[index]) && !node->Filename.IsEmpty() && !node->bOldVersion && - (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), nullptr, true)) != nullptr) + (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) { FResourceLump *info = resf->FindLump("info.json"); if (info == nullptr) @@ -496,29 +496,26 @@ unsigned FSavegameManager::ExtractSaveData(int index) FResourceLump *pic = resf->FindLump("savepic.png"); if (pic != nullptr) { - FileReader *reader = pic->NewReader(); - if (reader != nullptr) + FileReader picreader; + + picreader.OpenMemoryArray([=](TArray &array) { - // copy to a memory buffer which gets accessed through a memory reader and PNGHandle. - // We cannot use the actual lump as backing for the texture because that requires keeping the - // savegame file open. - SavePicData.Resize(pic->LumpSize); - reader->Read(&SavePicData[0], pic->LumpSize); - reader = new MemoryReader(&SavePicData[0], SavePicData.Size()); - PNGHandle *png = M_VerifyPNG(reader); - if (png != nullptr) + auto cache = pic->CacheLump(); + array.Resize(pic->LumpSize); + memcpy(&array[0], cache, pic->LumpSize); + pic->ReleaseCache(); + return true; + }); + PNGHandle *png = M_VerifyPNG(picreader); + if (png != nullptr) + { + SavePic = PNGTexture_CreateFromFile(png, node->Filename); + delete png; + if (SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1) { - SavePic = PNGTexture_CreateFromFile(png, node->Filename); - currentSavePic = reader; // must be kept so that the texture can read from it. - delete png; - if (SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1) - { - delete SavePic; - SavePic = nullptr; - delete currentSavePic; - currentSavePic = nullptr; - SavePicData.Clear(); - } + delete SavePic; + SavePic = nullptr; + SavePicData.Clear(); } } } @@ -551,14 +548,9 @@ void FSavegameManager::UnloadSaveData() { V_FreeBrokenLines(SaveComment); } - if (currentSavePic != nullptr) - { - delete currentSavePic; - } SavePic = nullptr; SaveComment = nullptr; - currentSavePic = nullptr; SavePicData.Clear(); } diff --git a/src/menu/menu.h b/src/menu/menu.h index d5211421f..71595903c 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -71,7 +71,6 @@ private: FSaveGameNode NewSaveNode; int LastSaved = -1; int LastAccessed = -1; - FileReader *currentSavePic = nullptr; TArray SavePicData; FTexture *SavePic = nullptr; FBrokenLines *SaveComment = nullptr; diff --git a/src/p_acs.h b/src/p_acs.h index 7b0d18bd8..8ccf62982 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -380,7 +380,7 @@ public: BoundsCheckingArray MapVars; - static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0); + static FBehavior *StaticLoadModule (int lumpnum, FileReader *fr = nullptr, int len=0); static void StaticLoadDefaultModules (); static void StaticUnloadModules (); static bool StaticCheckAllGood (); diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 5d3a872a4..37903021e 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -116,9 +116,9 @@ static int ConversationMenuY; static int ConversationPauseTic; static int StaticLastReply; -static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type); -static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, uint32_t &prevSpeakerType); -static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, uint32_t &prevSpeakerType); +static bool LoadScriptFile(int lumpnum, FileReader &lump, int numnodes, bool include, int type); +static FStrifeDialogueNode *ReadRetailNode (FileReader &lump, uint32_t &prevSpeakerType); +static FStrifeDialogueNode *ReadTeaserNode (FileReader &lump, uint32_t &prevSpeakerType); static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses); static bool DrawConversationMenu (); static void PickConversationReply (int replyindex); @@ -190,8 +190,7 @@ void P_LoadStrifeConversations (MapData *map, const char *mapname) P_FreeStrifeConversations (); if (map->Size(ML_CONVERSATION) > 0) { - map->Seek(ML_CONVERSATION); - LoadScriptFile (map->lumpnum, map->file, map->Size(ML_CONVERSATION), false, 0); + LoadScriptFile (map->lumpnum, map->Reader(ML_CONVERSATION), map->Size(ML_CONVERSATION), false, 0); } else { @@ -228,28 +227,26 @@ void P_LoadStrifeConversations (MapData *map, const char *mapname) bool LoadScriptFile (const char *name, bool include, int type) { int lumpnum = Wads.CheckNumForName (name); - FileReader *lump; if (lumpnum < 0) { return false; } - lump = Wads.ReopenLumpNum (lumpnum); + FileReader lump = Wads.ReopenLumpReader (lumpnum); bool res = LoadScriptFile(lumpnum, lump, Wads.LumpLength(lumpnum), include, type); - delete lump; return res; } -static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type) +static bool LoadScriptFile(int lumpnum, FileReader &lump, int numnodes, bool include, int type) { int i; uint32_t prevSpeakerType; FStrifeDialogueNode *node; char buffer[4]; - lump->Read(buffer, 4); - lump->Seek(-4, SEEK_CUR); + lump.Read(buffer, 4); + lump.Seek(-4, FileReader::SeekCur); // The binary format is so primitive that this check is enough to detect it. bool isbinary = (buffer[0] == 0 || buffer[1] == 0 || buffer[2] == 0 || buffer[3] == 0); @@ -318,7 +315,7 @@ static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool inc // //============================================================================ -static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, uint32_t &prevSpeakerType) +static FStrifeDialogueNode *ReadRetailNode (FileReader &lump, uint32_t &prevSpeakerType) { FStrifeDialogueNode *node; Speech speech; @@ -328,7 +325,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, uint32_t &prevSpea node = new FStrifeDialogueNode; - lump->Read (&speech, sizeof(speech)); + lump.Read (&speech, sizeof(speech)); // Byte swap all the ints in the original data speech.SpeakerType = LittleLong(speech.SpeakerType); @@ -394,7 +391,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, uint32_t &prevSpea // //============================================================================ -static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, uint32_t &prevSpeakerType) +static FStrifeDialogueNode *ReadTeaserNode (FileReader &lump, uint32_t &prevSpeakerType) { FStrifeDialogueNode *node; TeaserSpeech speech; @@ -404,7 +401,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, uint32_t &prevSpea node = new FStrifeDialogueNode; - lump->Read (&speech, sizeof(speech)); + lump.Read (&speech, sizeof(speech)); // Byte swap all the ints in the original data speech.SpeakerType = LittleLong(speech.SpeakerType); diff --git a/src/p_conversation.h b/src/p_conversation.h index 7cabc746c..bc2e56be1 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -78,7 +78,7 @@ void P_ResumeConversation (); void P_ConversationCommand (int netcode, int player, uint8_t **stream); class FileReader; -bool P_ParseUSDF(int lumpnum, FileReader *lump, int lumplen); +bool P_ParseUSDF(int lumpnum, FileReader &lump, int lumplen); #endif diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 60c666e82..7d0e37339 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -45,6 +45,7 @@ #endif +#include #include "templates.h" #include "m_alloc.h" #include "m_argv.h" @@ -215,18 +216,18 @@ bool P_CheckForGLNodes() static int firstglvertex; static bool format5; -static bool LoadGLVertexes(FileReader * lump) +static bool LoadGLVertexes(FileReader &lump) { uint8_t *gldata; int i; firstglvertex = level.vertexes.Size(); - int gllen=lump->GetLength(); + auto gllen=lump.GetLength(); gldata = new uint8_t[gllen]; - lump->Seek(0, SEEK_SET); - lump->Read(gldata, gllen); + lump.Seek(0, FileReader::SeekSet); + lump.Read(gldata, gllen); if (*(int *)gldata == gNd5) { @@ -246,7 +247,7 @@ static bool LoadGLVertexes(FileReader * lump) else format5=false; mapglvertex_t* mgl = (mapglvertex_t *)(gldata + GL_VERT_OFFSET); - unsigned numvertexes = firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t); + unsigned numvertexes = (unsigned)(firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t)); auto oldvertexes = &level.vertexes[0]; level.vertexes.Resize(numvertexes); @@ -293,16 +294,16 @@ static inline int checkGLVertex3(int num) // //========================================================================== -static bool LoadGLSegs(FileReader * lump) +static bool LoadGLSegs(FileReader &lump) { char *data; int i; line_t *ldef=NULL; - int numsegs = lump->GetLength(); + int numsegs = (int)lump.GetLength(); data= new char[numsegs]; - lump->Seek(0, SEEK_SET); - lump->Read(data, numsegs); + lump.Seek(0, FileReader::SeekSet); + lump.Read(data, numsegs); auto &segs = level.segs; #ifdef _MSC_VER @@ -437,15 +438,15 @@ static bool LoadGLSegs(FileReader * lump) // //========================================================================== -static bool LoadGLSubsectors(FileReader * lump) +static bool LoadGLSubsectors(FileReader &lump) { char * datab; int i; - auto numsubsectors = lump->GetLength(); + int numsubsectors = (int)lump.GetLength(); datab = new char[numsubsectors]; - lump->Seek(0, SEEK_SET); - lump->Read(datab, numsubsectors); + lump.Seek(0, FileReader::SeekSet); + lump.Read(datab, numsubsectors); if (numsubsectors == 0) { @@ -521,7 +522,7 @@ static bool LoadGLSubsectors(FileReader * lump) // //========================================================================== -static bool LoadNodes (FileReader * lump) +static bool LoadNodes (FileReader &lump) { const int NF_SUBSECTOR = 0x8000; const int GL5_NF_SUBSECTOR = (1 << 31); @@ -534,15 +535,15 @@ static bool LoadNodes (FileReader * lump) if (!format5) { mapnode_t* mn, * basemn; - unsigned numnodes = unsigned(lump->GetLength() / sizeof(mapnode_t)); + unsigned numnodes = unsigned(lump.GetLength() / sizeof(mapnode_t)); if (numnodes == 0) return false; level.nodes.Alloc(numnodes); - lump->Seek(0, SEEK_SET); + lump.Seek(0, FileReader::SeekSet); basemn = mn = new mapnode_t[numnodes]; - lump->Read(mn, lump->GetLength()); + lump.Read(mn, lump.GetLength()); used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); @@ -594,15 +595,15 @@ static bool LoadNodes (FileReader * lump) else { gl5_mapnode_t* mn, * basemn; - auto numnodes = unsigned(lump->GetLength() / sizeof(gl5_mapnode_t)); + auto numnodes = unsigned(lump.GetLength() / sizeof(gl5_mapnode_t)); if (numnodes == 0) return false; level.nodes.Alloc(numnodes); - lump->Seek(0, SEEK_SET); + lump.Seek(0, FileReader::SeekSet); basemn = mn = new gl5_mapnode_t[numnodes]; - lump->Read(mn, lump->GetLength()); + lump.Read(mn, lump.GetLength()); used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); @@ -660,7 +661,7 @@ static bool LoadNodes (FileReader * lump) // //========================================================================== -static bool DoLoadGLNodes(FileReader ** lumps) +static bool DoLoadGLNodes(FileReader * lumps) { int missing = 0; @@ -803,7 +804,7 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label) if (mustcheck) { char check[16]={0}; - FileReader *fr = f->GetLump(i)->GetReader(); + auto fr = f->GetLump(i)->GetReader(); fr->Read(check, 16); if (MatchHeader(label, check)) return i; } @@ -823,7 +824,7 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label) bool P_LoadGLNodes(MapData * map) { - if (map->MapLumps[ML_GLZNODES].Reader && map->MapLumps[ML_GLZNODES].Reader->GetLength() != 0) + if (map->Size(ML_GLZNODES) != 0) { const int idcheck1a = MAKE_ID('Z','G','L','N'); const int idcheck2a = MAKE_ID('Z','G','L','2'); @@ -833,8 +834,8 @@ bool P_LoadGLNodes(MapData * map) const int idcheck3b = MAKE_ID('X','G','L','3'); int id; - map->Seek(ML_GLZNODES); - map->file->Read (&id, 4); + auto &file = map->Reader(ML_GLZNODES); + file.Read (&id, 4); if (id == idcheck1a || id == idcheck2a || id == idcheck3a || id == idcheck1b || id == idcheck2b || id == idcheck3b) { @@ -843,7 +844,7 @@ bool P_LoadGLNodes(MapData * map) level.subsectors.Clear(); level.segs.Clear(); level.nodes.Clear(); - P_LoadZNodes (*map->file, id); + P_LoadZNodes (file, id); return true; } catch (CRecoverableError &) @@ -857,7 +858,7 @@ bool P_LoadGLNodes(MapData * map) if (!CheckCachedNodes(map)) { - FileReader *gwalumps[4] = { NULL, NULL, NULL, NULL }; + FileReader gwalumps[4]; char path[256]; int li; int lumpfile = Wads.GetLumpFile(map->lumpnum); @@ -875,7 +876,7 @@ bool P_LoadGLNodes(MapData * map) // GL nodes are loaded with a WAD for(int i=0;i<4;i++) { - gwalumps[i]=Wads.ReopenLumpNum(li+i+1); + gwalumps[i]=Wads.ReopenLumpReader(li+i+1); } return DoLoadGLNodes(gwalumps); } @@ -889,7 +890,7 @@ bool P_LoadGLNodes(MapData * map) strcpy(ext, ".gwa"); // Todo: Compare file dates - f_gwa = FResourceFile::OpenResourceFile(path, NULL, true); + f_gwa = FResourceFile::OpenResourceFile(path, true); if (f_gwa==NULL) return false; strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(map->lumpnum), 8); @@ -918,8 +919,6 @@ bool P_LoadGLNodes(MapData * map) if (f_gwa != map->resource) delete f_gwa; - for(unsigned int i = 0;i < 4;++i) - delete gwalumps[i]; return result; } else return true; @@ -1164,7 +1163,7 @@ static bool CheckCachedNodes(MapData *map) FString path = CreateCacheName(map, false); FileReader fr; - if (!fr.Open(path)) return false; + if (!fr.OpenFile(path)) return false; if (fr.Read(magic, 4) != 4) goto errorout; if (memcmp(magic, "CACH", 4)) goto errorout; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 371e3f977..e27ab198c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -8516,5 +8516,7 @@ void PrintMiscActorInfo(AActor *query) query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length()); Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y); Printf("FriendlySeeBlocks: %d\n", query->friendlyseeblocks); + Printf("Target: %s\n", query->target ? query->target->GetClass()->TypeName.GetChars() : "-"); + Printf("Last enemy: %s\n", query->lastenemy ? query->lastenemy->GetClass()->TypeName.GetChars() : "-"); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 4f2a64bde..022eba064 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -240,7 +240,7 @@ static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, MapData *P_OpenMapData(const char * mapname, bool justcheck) { MapData * map = new MapData; - FileReader * wadReader = NULL; + FileReader * wadReader = nullptr; bool externalfile = !strnicmp(mapname, "file:", 5); if (externalfile) @@ -251,7 +251,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) delete map; return NULL; } - map->resource = FResourceFile::OpenResourceFile(mapname, NULL, true); + map->resource = FResourceFile::OpenResourceFile(mapname, true); wadReader = map->resource->GetReader(); } else @@ -281,7 +281,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) { // The following lump is from a different file so whatever this is, // it is not a multi-lump Doom level so let's assume it is a Build map. - map->MapLumps[0].Reader = map->file = Wads.ReopenLumpNum(lump_name); + map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); if (!P_IsBuildMap(map)) { delete map; @@ -292,7 +292,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // This case can only happen if the lump is inside a real WAD file. // As such any special handling for other types of lumps is skipped. - map->MapLumps[0].Reader = map->file = Wads.ReopenLumpNum(lump_name); + map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(lump_name), 8); map->Encrypted = Wads.IsEncryptedFile(lump_name); map->InWad = true; @@ -335,14 +335,14 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // The next lump is not part of this map anymore if (index < 0) break; - map->MapLumps[index].Reader = Wads.ReopenLumpNum(lump_name + i); + map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } else { map->isText = true; - map->MapLumps[1].Reader = Wads.ReopenLumpNum(lump_name + 1); + map->MapLumps[1].Reader = Wads.ReopenLumpReader(lump_name + 1); for(int i = 2;; i++) { const char * lumpname = Wads.GetLumpFullName(lump_name + i); @@ -378,7 +378,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) break; } else continue; - map->MapLumps[index].Reader = Wads.ReopenLumpNum(lump_name + i); + map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } @@ -396,7 +396,8 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) return NULL; } map->lumpnum = lump_wad; - map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), Wads.ReopenLumpNum(lump_wad), true); + auto reader = Wads.ReopenLumpReader(lump_wad); + map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), reader, true); wadReader = map->resource->GetReader(); } } @@ -404,7 +405,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // Although we're using the resource system, we still want to be sure we're // reading from a wad file. - wadReader->Seek(0, SEEK_SET); + wadReader->Seek(0, FileReader::SeekSet); wadReader->Read(&id, sizeof(id)); if (id == IWAD_ID || id == PWAD_ID) @@ -526,29 +527,19 @@ void MapData::GetChecksum(uint8_t cksum[16]) if (isText) { - Seek(ML_TEXTMAP); - if (file != NULL) md5.Update(file, Size(ML_TEXTMAP)); + md5.Update(Reader(ML_TEXTMAP), Size(ML_TEXTMAP)); } else { - if (Size(ML_LABEL) != 0) - { - Seek(ML_LABEL); - if (file != NULL) md5.Update(file, Size(ML_LABEL)); - } - Seek(ML_THINGS); - if (file != NULL) md5.Update(file, Size(ML_THINGS)); - Seek(ML_LINEDEFS); - if (file != NULL) md5.Update(file, Size(ML_LINEDEFS)); - Seek(ML_SIDEDEFS); - if (file != NULL) md5.Update(file, Size(ML_SIDEDEFS)); - Seek(ML_SECTORS); - if (file != NULL) md5.Update(file, Size(ML_SECTORS)); + md5.Update(Reader(ML_LABEL), Size(ML_LABEL)); + md5.Update(Reader(ML_THINGS), Size(ML_THINGS)); + md5.Update(Reader(ML_LINEDEFS), Size(ML_LINEDEFS)); + md5.Update(Reader(ML_SIDEDEFS), Size(ML_SIDEDEFS)); + md5.Update(Reader(ML_SECTORS), Size(ML_SECTORS)); } if (HasBehavior) { - Seek(ML_BEHAVIOR); - if (file != NULL) md5.Update(file, Size(ML_BEHAVIOR)); + md5.Update(Reader(ML_BEHAVIOR), Size(ML_BEHAVIOR)); } md5.Final(cksum); } @@ -847,14 +838,14 @@ void P_LoadVertexes (MapData * map) level.vertexes.Alloc(numvertexes); vertexdatas.Clear(); - map->Seek(ML_VERTEXES); + auto &fr = map->Reader(ML_VERTEXES); // Copy and convert vertex coordinates, internal representation as fixed. for (auto &v : level.vertexes) { - int16_t x, y; + int16_t x = fr.ReadInt16(); + int16_t y = fr.ReadInt16(); - (*map->file) >> x >> y; v.set(double(x), double(y)); } } @@ -865,16 +856,15 @@ void P_LoadVertexes (MapData * map) // //=========================================================================== -void P_LoadZSegs (FileReaderBase &data) +void P_LoadZSegs (FileReader &data) { for (auto &seg : level.segs) { line_t *ldef; - uint32_t v1, v2; - uint16_t line; - uint8_t side; - - data >> v1 >> v2 >> line >> side; + uint32_t v1 = data.ReadUInt32(); + uint32_t v2 = data.ReadUInt32(); + uint16_t line = data.ReadUInt16(); + uint8_t side = data.ReadUInt8(); seg.v1 = &level.vertexes[v1]; seg.v2 = &level.vertexes[v2]; @@ -901,7 +891,7 @@ void P_LoadZSegs (FileReaderBase &data) // //=========================================================================== -void P_LoadGLZSegs (FileReaderBase &data, int type) +void P_LoadGLZSegs (FileReader &data, int type) { for (unsigned i = 0; i < level.subsectors.Size(); ++i) { @@ -909,22 +899,20 @@ void P_LoadGLZSegs (FileReaderBase &data, int type) for (size_t j = 0; j < level.subsectors[i].numlines; ++j) { seg_t *seg; - uint32_t v1, partner; + uint32_t v1 = data.ReadUInt32(); + uint32_t partner = data.ReadUInt32(); uint32_t line; - uint16_t lineword; - uint8_t side; - data >> v1 >> partner; if (type >= 2) { - data >> line; + line = data.ReadUInt32(); } else { - data >> lineword; - line = lineword == 0xFFFF ? 0xFFFFFFFF : lineword; + line = data.ReadUInt16(); + if (line == 0xffff) line = 0xffffffff; } - data >> side; + uint8_t side = data.ReadUInt8(); seg = level.subsectors[i].firstline + j; seg->v1 = &level.vertexes[v1]; @@ -971,13 +959,13 @@ void P_LoadGLZSegs (FileReaderBase &data, int type) // //=========================================================================== -void LoadZNodes(FileReaderBase &data, int glnodes) +void LoadZNodes(FileReader &data, int glnodes) { // Read extra vertices added during node building - uint32_t orgVerts, newVerts; unsigned int i; - data >> orgVerts >> newVerts; + uint32_t orgVerts = data.ReadUInt32(); + uint32_t newVerts = data.ReadUInt32(); if (orgVerts > level.vertexes.Size()) { // These nodes are based on a map with more vertex data than we have. // We can't use them. @@ -990,8 +978,8 @@ void LoadZNodes(FileReaderBase &data, int glnodes) } for (i = 0; i < newVerts; ++i) { - fixed_t x, y; - data >> x >> y; + fixed_t x = data.ReadInt32(); + fixed_t y = data.ReadInt32(); level.vertexes[i + orgVerts].set(x, y); } if (oldvertexes != &level.vertexes[0]) @@ -1004,26 +992,21 @@ void LoadZNodes(FileReaderBase &data, int glnodes) } // Read the subsectors - uint32_t numSubs, currSeg; - - data >> numSubs; + uint32_t currSeg; + uint32_t numSubs = data.ReadUInt32(); level.subsectors.Alloc(numSubs); memset (&level.subsectors[0], 0, level.subsectors.Size()*sizeof(subsector_t)); for (i = currSeg = 0; i < numSubs; ++i) { - uint32_t numsegs; - - data >> numsegs; + uint32_t numsegs = data.ReadUInt32(); level.subsectors[i].firstline = (seg_t *)(size_t)currSeg; // Oh damn. I should have stored the seg count sooner. level.subsectors[i].numlines = numsegs; currSeg += numsegs; } // Read the segs - uint32_t numSegs; - - data >> numSegs; + uint32_t numSegs = data.ReadUInt32(); // The number of segs stored should match the number of // segs used by subsectors. @@ -1050,9 +1033,8 @@ void LoadZNodes(FileReaderBase &data, int glnodes) } // Read nodes - uint32_t numNodes; + uint32_t numNodes = data.ReadUInt32(); - data >> numNodes; auto &nodes = level.nodes; nodes.Alloc(numNodes); memset (&nodes[0], 0, sizeof(node_t)*numNodes); @@ -1061,31 +1043,28 @@ void LoadZNodes(FileReaderBase &data, int glnodes) { if (glnodes < 3) { - int16_t x, y, dx, dy; - - data >> x >> y >> dx >> dy; - nodes[i].x = x << FRACBITS; - nodes[i].y = y << FRACBITS; - nodes[i].dx = dx << FRACBITS; - nodes[i].dy = dy << FRACBITS; + nodes[i].x = data.ReadInt16() * FRACUNIT; + nodes[i].y = data.ReadInt16() * FRACUNIT; + nodes[i].dx = data.ReadInt16() * FRACUNIT; + nodes[i].dy = data.ReadInt16() * FRACUNIT; } else { - data >> nodes[i].x >> nodes[i].y >> nodes[i].dx >> nodes[i].dy; + nodes[i].x = data.ReadInt32(); + nodes[i].y = data.ReadInt32(); + nodes[i].dx = data.ReadInt32(); + nodes[i].dy = data.ReadInt32(); } for (int j = 0; j < 2; ++j) { for (int k = 0; k < 4; ++k) { - int16_t coord; - data >> coord; - nodes[i].bbox[j][k] = coord; + nodes[i].bbox[j][k] = data.ReadInt16(); } } for (int m = 0; m < 2; ++m) { - uint32_t child; - data >> child; + uint32_t child = data.ReadUInt32(); if (child & 0x80000000) { nodes[i].children[m] = (uint8_t *)&level.subsectors[child & 0x7FFFFFFF] + 1; @@ -1157,8 +1136,11 @@ void P_LoadZNodes (FileReader &dalump, uint32_t id) if (compressed) { - FileReaderZ data (dalump); - LoadZNodes(data, type); + FileReader zip; + if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false)) + { + LoadZNodes(zip, type); + } } else { @@ -1398,7 +1380,7 @@ void P_LoadSubsectors (MapData * map) auto &subsectors = level.subsectors; subsectors.Alloc(numsubsectors); - map->Seek(ML_SSECTORS); + auto &fr = map->Reader(ML_SSECTORS); memset (&subsectors[0], 0, numsubsectors*sizeof(subsector_t)); @@ -1406,7 +1388,8 @@ void P_LoadSubsectors (MapData * map) { subsectortype subd; - (*map->file) >> subd.numsegs >> subd.firstseg; + subd.numsegs = sizeof(subd.numsegs) == 2 ? fr.ReadUInt16() : fr.ReadUInt32(); + subd.firstseg = sizeof(subd.firstseg) == 2 ? fr.ReadUInt16() : fr.ReadUInt32(); if (subd.numsegs == 0) { @@ -2500,17 +2483,17 @@ static void P_LoopSidedefs (bool firstloop) int P_DetermineTranslucency (int lumpnum) { - FWadLump tranmap = Wads.OpenLumpNum (lumpnum); + auto tranmap = Wads.OpenLumpReader (lumpnum); uint8_t index; PalEntry newcolor; PalEntry newcolor2; - tranmap.Seek (GPalette.BlackIndex * 256 + GPalette.WhiteIndex, SEEK_SET); + tranmap.Seek (GPalette.BlackIndex * 256 + GPalette.WhiteIndex, FileReader::SeekSet); tranmap.Read (&index, 1); newcolor = GPalette.BaseColors[GPalette.Remap[index]]; - tranmap.Seek (GPalette.WhiteIndex * 256 + GPalette.BlackIndex, SEEK_SET); + tranmap.Seek (GPalette.WhiteIndex * 256 + GPalette.BlackIndex, FileReader::SeekSet); tranmap.Read (&index, 1); newcolor2 = GPalette.BaseColors[GPalette.Remap[index]]; if (newcolor2.r == 255) // if black on white results in white it's either @@ -3311,7 +3294,7 @@ void P_LoadReject (MapData * map, bool junk) const int neededsize = (level.sectors.Size() * level.sectors.Size() + 7) >> 3; int rejectsize; - if (strnicmp (map->MapLumps[ML_REJECT].Name, "REJECT", 8) != 0) + if (!map->CheckName(ML_REJECT, "REJECT")) { rejectsize = 0; } @@ -3335,8 +3318,7 @@ void P_LoadReject (MapData * map, bool junk) rejectsize = MIN (rejectsize, neededsize); level.rejectmatrix.Alloc(rejectsize); - map->Seek(ML_REJECT); - map->file->Read (&level.rejectmatrix[0], rejectsize); + map->Read (ML_REJECT, &level.rejectmatrix[0], rejectsize); int qwords = rejectsize / 8; int i; @@ -3375,8 +3357,7 @@ void P_LoadBehavior(MapData * map) { if (map->Size(ML_BEHAVIOR) > 0) { - map->Seek(ML_BEHAVIOR); - FBehavior::StaticLoadModule(-1, map->file, map->Size(ML_BEHAVIOR)); + FBehavior::StaticLoadModule(-1, &map->Reader(ML_BEHAVIOR), map->Size(ML_BEHAVIOR)); } if (!FBehavior::StaticCheckAllGood()) { @@ -3635,8 +3616,10 @@ void P_FreeExtraLevelData() void P_SetupLevel (const char *lumpname, int position) { cycle_t times[20]; +#if 0 FMapThing *buildthings; int numbuildthings; +#endif int i; bool buildmap; const int *oldvertextable = NULL; @@ -3709,16 +3692,18 @@ void P_SetupLevel (const char *lumpname, int position) // [RH] Support loading Build maps (because I felt like it. :-) buildmap = false; +#if 0 + // deactivated because broken. if (map->Size(0) > 0) { uint8_t *mapdata = new uint8_t[map->Size(0)]; - map->Seek(0); - map->file->Read(mapdata, map->Size(0)); + map->Read(0, mapdata); times[0].Clock(); buildmap = P_LoadBuildMap (mapdata, map->Size(0), &buildthings, &numbuildthings); times[0].Unclock(); delete[] mapdata; } +#endif if (!buildmap) { @@ -3858,19 +3843,19 @@ void P_SetupLevel (const char *lumpname, int position) if (!ForceNodeBuild) { // Check for compressed nodes first, then uncompressed nodes - FWadLump test; + FileReader *fr = nullptr; uint32_t id = MAKE_ID('X','x','X','x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0; if (map->Size(ML_ZNODES) != 0) { // Test normal nodes first - map->Seek(ML_ZNODES); + fr = &map->Reader(ML_ZNODES); idcheck = MAKE_ID('Z','N','O','D'); idcheck2 = MAKE_ID('X','N','O','D'); } else if (map->Size(ML_GLZNODES) != 0) { - map->Seek(ML_GLZNODES); + fr = &map->Reader(ML_GLZNODES); idcheck = MAKE_ID('Z','G','L','N'); idcheck2 = MAKE_ID('Z','G','L','2'); idcheck3 = MAKE_ID('Z','G','L','3'); @@ -3879,12 +3864,12 @@ void P_SetupLevel (const char *lumpname, int position) idcheck6 = MAKE_ID('X','G','L','3'); } - map->file->Read (&id, 4); + if (fr != nullptr && fr->isOpen()) fr->Read (&id, 4); if (id != 0 && (id == idcheck || id == idcheck2 || id == idcheck3 || id == idcheck4 || id == idcheck5 || id == idcheck6)) { try { - P_LoadZNodes (*map->file, id); + P_LoadZNodes (*fr, id); } catch (CRecoverableError &error) { @@ -4067,6 +4052,7 @@ void P_SetupLevel (const char *lumpname, int position) P_TranslateTeleportThings (); // [RH] Assign teleport destination TIDs times[15].Unclock(); } +#if 0 // There is no such thing as a build map. else { for (i = 0; i < numbuildthings; ++i) @@ -4075,6 +4061,7 @@ void P_SetupLevel (const char *lumpname, int position) } delete[] buildthings; } +#endif delete map; if (oldvertextable != NULL) { @@ -4294,3 +4281,4 @@ CCMD (lineloc) lines[linenum].v2->fY()); } #endif + diff --git a/src/p_setup.h b/src/p_setup.h index dae64160b..cd14f17a2 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -34,69 +34,86 @@ struct MapData { +private: struct MapLump { - char Name[8]; - FileReader *Reader; + char Name[8] = { 0 }; + FileReader Reader; } MapLumps[ML_MAX]; - bool HasBehavior; - bool Encrypted; - bool isText; - bool InWad; - int lumpnum; - FileReader * file; - FResourceFile * resource; - - MapData() - { - memset(MapLumps, 0, sizeof(MapLumps)); - file = NULL; - resource = NULL; - lumpnum = -1; - HasBehavior = false; - Encrypted = false; - isText = false; - InWad = false; - } + FileReader nofile; +public: + bool HasBehavior = false; + bool Encrypted = false; + bool isText = false; + bool InWad = false; + int lumpnum = -1; + FResourceFile * resource = nullptr; ~MapData() { - for (unsigned int i = 0;i < ML_MAX;++i) - delete MapLumps[i].Reader; - - delete resource; - resource = NULL; + if (resource != nullptr) delete resource; + resource = nullptr; } + /* void Seek(unsigned int lumpindex) { if (lumpindexSeek(0, SEEK_SET); + file = &MapLumps[lumpindex].Reader; + file->Seek(0, FileReader::SeekSet); } } + */ + + FileReader &Reader(unsigned int lumpindex) + { + if (lumpindex < countof(MapLumps)) + { + auto &file = MapLumps[lumpindex].Reader; + file.Seek(0, FileReader::SeekSet); + return file; + } + return nofile; + } void Read(unsigned int lumpindex, void * buffer, int size = -1) { if (lumpindexGetLength(); - Seek(lumpindex); - file->Read(buffer, size); + if (size == -1) size = Size(lumpindex); + if (size > 0) + { + auto &file = MapLumps[lumpindex].Reader; + file.Seek(0, FileReader::SeekSet); + file.Read(buffer, size); + } } } uint32_t Size(unsigned int lumpindex) { - if (lumpindexGetLength(); + return (uint32_t)MapLumps[lumpindex].Reader.GetLength(); } return 0; } + bool CheckName(unsigned int lumpindex, const char *name) + { + if (lumpindex < countof(MapLumps)) + { + return !strnicmp(MapLumps[lumpindex].Name, name, 8); + } + return false; + } + void GetChecksum(uint8_t cksum[16]); + + friend bool P_LoadGLNodes(MapData * map); + friend MapData *P_OpenMapData(const char * mapname, bool justcheck); + }; MapData * P_OpenMapData(const char * mapname, bool justcheck); diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 015dd9793..816186622 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -474,10 +474,10 @@ class USDFParser : public UDMFParserBase //=========================================================================== public: - bool Parse(int lumpnum, FileReader *lump, int lumplen) + bool Parse(int lumpnum, FileReader &lump, int lumplen) { char *buffer = new char[lumplen]; - lump->Read(buffer, lumplen); + lump.Read(buffer, lumplen); sc.OpenMem(Wads.GetLumpFullName(lumpnum), buffer, lumplen); delete [] buffer; sc.SetCMode(true); @@ -532,7 +532,7 @@ public: -bool P_ParseUSDF(int lumpnum, FileReader *lump, int lumplen) +bool P_ParseUSDF(int lumpnum, FileReader &lump, int lumplen) { USDFParser parse; diff --git a/src/polyrenderer/drawers/poly_draw_args.cpp b/src/polyrenderer/drawers/poly_draw_args.cpp index 466a39f4a..312cb3e32 100644 --- a/src/polyrenderer/drawers/poly_draw_args.cpp +++ b/src/polyrenderer/drawers/poly_draw_args.cpp @@ -46,20 +46,21 @@ void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height) mTranslation = nullptr; } -void PolyDrawArgs::SetTexture(FTexture *texture) +void PolyDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); else - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); mTranslation = nullptr; } -void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool forcePal) +void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style) { - if (translationID != 0xffffffff && translationID != 0) + // Alphatexture overrides translations. + if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) { FRemapTable *table = TranslationToTable(translationID); if (table != nullptr && !table->Inactive) @@ -71,20 +72,20 @@ void PolyDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool fo mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); return; } } - if (forcePal) + if (style.Flags & STYLEF_RedIsAlpha) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); } else { - SetTexture(texture); + SetTexture(texture, style); } } @@ -164,8 +165,7 @@ void PolyDrawArgs::DrawElements(PolyRenderThread *thread, const TriVertex *verti void PolyDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) { - bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); - SetTexture(tex, translationID, forcePal); + SetTexture(tex, translationID, renderstyle); if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { @@ -232,20 +232,20 @@ void RectDrawArgs::SetTexture(const uint8_t *texels, int width, int height) mTranslation = nullptr; } -void RectDrawArgs::SetTexture(FTexture *texture) +void RectDrawArgs::SetTexture(FTexture *texture, FRenderStyle style) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) mTexturePixels = (const uint8_t *)texture->GetPixelsBgra(); else - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); mTranslation = nullptr; } -void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool forcePal) +void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style) { - if (translationID != 0xffffffff && translationID != 0) + if (translationID != 0xffffffff && translationID != 0 && !(style.Flags & STYLEF_RedIsAlpha)) { FRemapTable *table = TranslationToTable(translationID); if (table != nullptr && !table->Inactive) @@ -257,20 +257,20 @@ void RectDrawArgs::SetTexture(FTexture *texture, uint32_t translationID, bool fo mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); return; } } - if (forcePal) + if (style.Flags & STYLEF_RedIsAlpha) { mTextureWidth = texture->GetWidth(); mTextureHeight = texture->GetHeight(); - mTexturePixels = texture->GetPixels(); + mTexturePixels = texture->GetPixels(style); } else { - SetTexture(texture); + SetTexture(texture, style); } } @@ -315,10 +315,9 @@ void RectDrawArgs::Draw(PolyRenderThread *thread, double x0, double x1, double y thread->DrawQueue->Push(*this); } -void RectDrawArgs::SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) +void RectDrawArgs::SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *tex, bool fullbright) { - bool forcePal = (renderstyle == LegacyRenderStyles[STYLE_Shaded] || renderstyle == LegacyRenderStyles[STYLE_AddShaded]); - SetTexture(tex, translationID, forcePal); + SetTexture(tex, translationID, renderstyle); if (renderstyle == LegacyRenderStyles[STYLE_Normal] || (r_drawfuzz == 0 && renderstyle == LegacyRenderStyles[STYLE_OptFuzzy])) { diff --git a/src/polyrenderer/drawers/poly_draw_args.h b/src/polyrenderer/drawers/poly_draw_args.h index eb543bbbf..05ad0862d 100644 --- a/src/polyrenderer/drawers/poly_draw_args.h +++ b/src/polyrenderer/drawers/poly_draw_args.h @@ -67,8 +67,8 @@ class PolyDrawArgs public: void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; } void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture(FTexture *texture); - void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); + void SetTexture(FTexture *texture, FRenderStyle style); + void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed); void SetDepthTest(bool enable) { mDepthTest = enable; } void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; } @@ -186,11 +186,11 @@ class RectDrawArgs { public: void SetTexture(const uint8_t *texels, int width, int height); - void SetTexture(FTexture *texture); - void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false); + void SetTexture(FTexture *texture, FRenderStyle style); + void SetTexture(FTexture *texture, uint32_t translationID, FRenderStyle style); void SetLight(FSWColormap *basecolormap, uint32_t lightlevel); void SetStyle(TriBlendMode blendmode, double srcalpha = 1.0, double destalpha = 1.0) { mBlendMode = blendmode; mSrcAlpha = (uint32_t)(srcalpha * 256.0 + 0.5); mDestAlpha = (uint32_t)(destalpha * 256.0 + 0.5); } - void SetStyle(const FRenderStyle &renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); + void SetStyle(FRenderStyle renderstyle, double alpha, uint32_t fillcolor, uint32_t translationID, FTexture *texture, bool fullbright); void SetColor(uint32_t bgra, uint8_t palindex); void Draw(PolyRenderThread *thread, double x0, double x1, double y0, double y1, double u0, double u1, double v0, double v1); diff --git a/src/polyrenderer/poly_renderthread.cpp b/src/polyrenderer/poly_renderthread.cpp index 9c3b33122..55d1c8469 100644 --- a/src/polyrenderer/poly_renderthread.cpp +++ b/src/polyrenderer/poly_renderthread.cpp @@ -74,7 +74,7 @@ void PolyRenderThread::FlushDrawQueue() } } -void PolyRenderThread::PrepareTexture(FTexture *texture) +void PolyRenderThread::PrepareTexture(FTexture *texture, FRenderStyle style) { if (texture == nullptr) return; @@ -91,9 +91,9 @@ void PolyRenderThread::PrepareTexture(FTexture *texture) std::unique_lock lock(loadmutex); - texture->GetPixels(); + texture->GetPixels(style); const FTexture::Span *spans; - texture->GetColumn(0, &spans); + texture->GetColumn(style, 0, &spans); if (PolyRenderer::Instance()->RenderTarget->IsBgra()) { texture->GetPixelsBgra(); diff --git a/src/polyrenderer/poly_renderthread.h b/src/polyrenderer/poly_renderthread.h index af10fd45c..afed28b19 100644 --- a/src/polyrenderer/poly_renderthread.h +++ b/src/polyrenderer/poly_renderthread.h @@ -47,7 +47,7 @@ public: DrawerCommandQueuePtr DrawQueue; // Make sure texture can accessed safely - void PrepareTexture(FTexture *texture); + void PrepareTexture(FTexture *texture, FRenderStyle style); // Setup poly object in a threadsafe manner void PreparePolyObject(subsector_t *sub); diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index a3361fd62..d53e0e1bf 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -33,26 +33,15 @@ void PolyCull::CullScene(const PolyClipPlane &portalClipPlane) ClearSolidSegments(); MarkViewFrustum(); - if (level.LevelName != lastLevelName) // Is this the best way to detect a level change? - { - lastLevelName = level.LevelName; - SubsectorDepths.clear(); - SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); - SectorSeen.clear(); - SectorSeen.resize(level.sectors.Size()); - } - else - { - for (const auto &sub : PvsSectors) - SubsectorDepths[sub->Index()] = 0xffffffff; - SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); + for (uint32_t sub : PvsSubsectors) + SubsectorDepths[sub] = 0xffffffff; + SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff); - for (const auto §or : SeenSectors) - SectorSeen[sector->Index()] = false; - SectorSeen.resize(level.sectors.Size()); - } + for (uint32_t sector : SeenSectors) + SectorSeen[sector] = false; + SectorSeen.resize(level.sectors.Size()); - PvsSectors.clear(); + PvsSubsectors.clear(); SeenSectors.clear(); NextPvsLineStart = 0; @@ -125,10 +114,10 @@ void PolyCull::CullSubsector(subsector_t *sub) FirstSkyHeight = false; } - uint32_t subsectorDepth = (uint32_t)PvsSectors.size(); + uint32_t subsectorDepth = (uint32_t)PvsSubsectors.size(); // Mark that we need to render this - PvsSectors.push_back(sub); + PvsSubsectors.push_back(sub->Index()); PvsLineStart.push_back(NextPvsLineStart); DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos; @@ -169,7 +158,7 @@ void PolyCull::CullSubsector(subsector_t *sub) if (!SectorSeen[sub->sector->Index()]) { SectorSeen[sub->sector->Index()] = true; - SeenSectors.push_back(sub->sector); + SeenSectors.push_back(sub->sector->Index()); } SubsectorDepths[sub->Index()] = subsectorDepth; diff --git a/src/polyrenderer/scene/poly_cull.h b/src/polyrenderer/scene/poly_cull.h index 474a33bb6..4b851373e 100644 --- a/src/polyrenderer/scene/poly_cull.h +++ b/src/polyrenderer/scene/poly_cull.h @@ -36,11 +36,11 @@ public: return PvsLineVisible[PvsLineStart[subsectorDepth] + lineIndex]; } - std::vector PvsSectors; + std::vector PvsSubsectors; double MaxCeilingHeight = 0.0; double MinFloorHeight = 0.0; - std::vector SeenSectors; + std::vector SeenSectors; std::vector SectorSeen; std::vector SubsectorDepths; diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index c952625c3..b2ce178cc 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -147,7 +147,7 @@ void PolyModelRenderer::DrawArrays(int start, int count) args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); - args.SetTexture(SkinTexture); + args.SetTexture(SkinTexture, DefaultRenderStyle()); args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); @@ -181,7 +181,7 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset) args.SetStencilTestValue(StencilValue); args.SetClipPlane(0, PolyClipPlane()); args.SetStyle(TriBlendMode::TextureOpaque); - args.SetTexture(SkinTexture); + args.SetTexture(SkinTexture, DefaultRenderStyle()); args.SetDepthTest(true); args.SetWriteDepth(true); args.SetWriteStencil(false); diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index f5485d096..874fe2630 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -81,7 +81,7 @@ void RenderPolyPlane::RenderNormal(PolyRenderThread *thread, const TriMatrix &wo args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); args.SetClipPlane(0, clipPlane); - args.SetTexture(tex); + args.SetTexture(tex, DefaultRenderStyle()); args.SetStyle(TriBlendMode::TextureOpaque); args.DrawArray(thread, vertices, fakeflat.Subsector->numlines, PolyDrawMode::TriangleFan); } @@ -572,7 +572,7 @@ void Render3DFloorPlane::Render(PolyRenderThread *thread, const TriMatrix &world args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); args.SetWriteStencil(true, stencilValue + 1); - args.SetTexture(tex); + args.SetTexture(tex, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); args.DrawArray(thread, vertices, sub->numlines, PolyDrawMode::TriangleFan); } diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 02ad1842e..42f6e815b 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -69,8 +69,8 @@ void RenderPolyScene::RenderSectors() { PolyRenderThread *mainthread = PolyRenderer::Instance()->Threads.MainThread(); - int totalcount = (int)Cull.PvsSectors.size(); - auto subsectors = Cull.PvsSectors.data(); + int totalcount = (int)Cull.PvsSubsectors.size(); + uint32_t *subsectors = Cull.PvsSubsectors.data(); TranslucentObjects.resize(PolyRenderer::Instance()->Threads.NumThreads()); @@ -82,7 +82,7 @@ void RenderPolyScene::RenderSectors() int end = thread->End; for (int i = start; i < end; i++) { - RenderSubsector(thread, subsectors[i], i); + RenderSubsector(thread, &level.subsectors[subsectors[i]], i); } }, [&](PolyRenderThread *thread) { @@ -372,8 +372,9 @@ void RenderPolyScene::RenderTranslucent(int portalDepth) } const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; - for (sector_t *sector : Cull.SeenSectors) + for (uint32_t sectorIndex : Cull.SeenSectors) { + sector_t *sector = &level.sectors[sectorIndex]; for (AActor *thing = sector->thinglist; thing != nullptr; thing = thing->snext) { DVector2 left, right; diff --git a/src/polyrenderer/scene/poly_sky.cpp b/src/polyrenderer/scene/poly_sky.cpp index 06cb7a8ec..eafa4c94c 100644 --- a/src/polyrenderer/scene/poly_sky.cpp +++ b/src/polyrenderer/scene/poly_sky.cpp @@ -91,7 +91,7 @@ void PolySkyDome::Render(PolyRenderThread *thread, const TriMatrix &worldToClip) RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, 0, false); RenderCapColorRow(thread, args, mCurrentSetup.frontskytex, rc, true); - args.SetTexture(mCurrentSetup.frontskytex); + args.SetTexture(mCurrentSetup.frontskytex, DefaultRenderStyle()); uint32_t topcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(false); uint32_t bottomcapcolor = mCurrentSetup.frontskytex->GetSkyCapColor(true); diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 20b9a1ade..fb75f7bf4 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -327,7 +327,7 @@ void RenderPolyWall::Render(PolyRenderThread *thread, const TriMatrix &worldToCl args.SetStencilTestValue(StencilValue); args.SetWriteStencil(true, StencilValue + 1); if (Texture && !Polyportal) - args.SetTexture(Texture); + args.SetTexture(Texture, DefaultRenderStyle()); args.SetClipPlane(0, clipPlane); SetDynLights(thread, args); diff --git a/src/polyrenderer/scene/poly_wallsprite.cpp b/src/polyrenderer/scene/poly_wallsprite.cpp index 846524f9d..7da68c5e5 100644 --- a/src/polyrenderer/scene/poly_wallsprite.cpp +++ b/src/polyrenderer/scene/poly_wallsprite.cpp @@ -105,7 +105,7 @@ void RenderPolyWallSprite::Render(PolyRenderThread *thread, const TriMatrix &wor args.SetTransform(&worldToClip); args.SetFaceCullCCW(true); args.SetStencilTestValue(stencilValue); - args.SetTexture(tex); + args.SetTexture(tex, thing->RenderStyle); args.SetClipPlane(0, clipPlane); args.SetDepthTest(true); args.SetWriteDepth(false); diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 3be9a067c..c8f066be5 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -386,3 +386,4 @@ TArray I_GetGogPaths() // GOG's Doom games are Windows only at the moment return TArray(); } + diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index f980e2598..1f41788a0 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -94,7 +94,7 @@ void I_Tactile (int /*on*/, int /*off*/, int /*total*/) ticcmd_t emptycmd; ticcmd_t *I_BaseTiccmd(void) { - return &emptycmd; + return &emptycmd; } void I_BeginRead(void) @@ -129,7 +129,7 @@ void I_Init (void) DumpCPUInfo (&CPU); atterm (I_ShutdownSound); - I_InitSound (); + I_InitSound (); } // @@ -139,9 +139,9 @@ static int has_exited; void I_Quit (void) { - has_exited = 1; /* Prevent infinitely recursive exits -- killough */ + has_exited = 1; /* Prevent infinitely recursive exits -- killough */ - if (demorecording) + if (demorecording) G_CheckDemoStatus(); C_DeinitConsole(); @@ -191,11 +191,11 @@ void Linux_I_FatalError(const char* errortext) void I_FatalError (const char *error, ...) { - static bool alreadyThrown = false; - gameisdead = true; + static bool alreadyThrown = false; + gameisdead = true; - if (!alreadyThrown) // ignore all but the first message -- killough - { + if (!alreadyThrown) // ignore all but the first message -- killough + { alreadyThrown = true; char errortext[MAX_ERRORTEXT]; int index; @@ -221,25 +221,25 @@ void I_FatalError (const char *error, ...) // throw CFatalError (errortext); fprintf (stderr, "%s\n", errortext); exit (-1); - } + } - if (!has_exited) // If it hasn't exited yet, exit now -- killough - { + if (!has_exited) // If it hasn't exited yet, exit now -- killough + { has_exited = 1; // Prevent infinitely recursive exits -- killough exit(-1); - } + } } void I_Error (const char *error, ...) { - va_list argptr; - char errortext[MAX_ERRORTEXT]; + va_list argptr; + char errortext[MAX_ERRORTEXT]; - va_start (argptr, error); - vsprintf (errortext, error, argptr); - va_end (argptr); + va_start (argptr, error); + vsprintf (errortext, error, argptr); + va_end (argptr); - throw CRecoverableError (errortext); + throw CRecoverableError (errortext); } void I_SetIWADInfo () @@ -291,8 +291,8 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) { FString cmd("kdialog --title \"" GAMESIG " "); cmd << GetVersionString() << ": Select an IWAD to use\"" - " --menu \"" GAMENAME " found more than one IWAD\n" - "Select from the list below to determine which one to use:\""; + " --menu \"" GAMENAME " found more than one IWAD\n" + "Select from the list below to determine which one to use:\""; for(i = 0; i < numwads; ++i) { @@ -380,7 +380,7 @@ static int matchfile (struct dirent *ent) static int matchfile (const struct dirent *ent) #endif { - return fnmatch (pattern, ent->d_name, FNM_NOESCAPE) == 0; + return fnmatch (pattern, ent->d_name, FNM_NOESCAPE) == 0; } void *I_FindFirst (const char *filespec, findstate_t *fileinfo) @@ -399,22 +399,22 @@ void *I_FindFirst (const char *filespec, findstate_t *fileinfo) dir = "."; } - fileinfo->current = 0; - fileinfo->count = scandir (dir.GetChars(), &fileinfo->namelist, + fileinfo->current = 0; + fileinfo->count = scandir (dir.GetChars(), &fileinfo->namelist, matchfile, alphasort); - if (fileinfo->count > 0) - { + if (fileinfo->count > 0) + { return fileinfo; - } - return (void*)-1; + } + return (void*)-1; } int I_FindNext (void *handle, findstate_t *fileinfo) { - findstate_t *state = (findstate_t *)handle; - if (state->current < fileinfo->count) - { - return ++state->current < fileinfo->count ? 0 : -1; + findstate_t *state = (findstate_t *)handle; + if (state->current < fileinfo->count) + { + return ++state->current < fileinfo->count ? 0 : -1; } return -1; } @@ -486,6 +486,7 @@ unsigned int I_MakeRNGSeed() TArray I_GetGogPaths() { - // GOG's Doom games are Windows only at the moment - return TArray(); + // GOG's Doom games are Windows only at the moment + return TArray(); } + diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index cce900a80..791101dd3 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -232,7 +232,7 @@ void R_InitColormaps () if (Wads.LumpLength (fakecmaps[j].lump) >= 256) { int k, r, g, b; - FWadLump lump = Wads.OpenLumpNum (fakecmaps[j].lump); + auto lump = Wads.OpenLumpReader (fakecmaps[j].lump); lump.Read(map, 256); r = g = b = 0; diff --git a/src/r_data/models/models_voxel.cpp b/src/r_data/models/models_voxel.cpp index 848f5a54d..9533aca69 100644 --- a/src/r_data/models/models_voxel.cpp +++ b/src/r_data/models/models_voxel.cpp @@ -53,23 +53,17 @@ // //=========================================================================== -class FVoxelTexture : public FTexture +class FVoxelTexture : public FWorldTexture { public: - FVoxelTexture(FVoxel *voxel); - ~FVoxelTexture(); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf); - bool UseBasePalette() { return false; } + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override; + bool UseBasePalette() override { return false; } + uint8_t *MakeTexture(FRenderStyle style) override; protected: FVoxel *SourceVox; - uint8_t *Pixels; - }; //=========================================================================== @@ -86,7 +80,6 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) WidthBits = 4; HeightBits = 4; WidthMask = 15; - Pixels = NULL; gl_info.bNoFilter = true; gl_info.bNoCompress = true; } @@ -97,54 +90,32 @@ FVoxelTexture::FVoxelTexture(FVoxel *vox) // //=========================================================================== -FVoxelTexture::~FVoxelTexture() -{ -} - -const uint8_t *FVoxelTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - // not needed - return NULL; -} - -const uint8_t *FVoxelTexture::GetPixels () +uint8_t *FVoxelTexture::MakeTexture (FRenderStyle style) { // GetPixels gets called when a translated palette is used so we still need to implement it here. - if (Pixels == NULL) + auto Pixels = new uint8_t[256]; + uint8_t *pp = SourceVox->Palette; + + if(pp != NULL) { - Pixels = new uint8_t[256]; - - uint8_t *pp = SourceVox->Palette; - - if(pp != NULL) + for(int i=0;i<256;i++, pp+=3) { - for(int i=0;i<256;i++, pp+=3) - { - PalEntry pe; - pe.r = (pp[0] << 2) | (pp[0] >> 4); - pe.g = (pp[1] << 2) | (pp[1] >> 4); - pe.b = (pp[2] << 2) | (pp[2] >> 4); - Pixels[i] = ColorMatcher.Pick(pe); - } + PalEntry pe; + pe.r = (pp[0] << 2) | (pp[0] >> 4); + pe.g = (pp[1] << 2) | (pp[1] >> 4); + pe.b = (pp[2] << 2) | (pp[2] >> 4); + // Alphatexture handling is just for completeness, but rather unlikely to be used ever. + Pixels[i] = (style.Flags & STYLEF_RedIsAlpha)? pe.r : ColorMatcher.Pick(pe); } - else - { - for(int i=0;i<256;i++, pp+=3) - { - Pixels[i] = (uint8_t)i; - } - } } - return Pixels; -} - -void FVoxelTexture::Unload () -{ - if (Pixels != NULL) + else { - delete[] Pixels; - Pixels = NULL; - } + for(int i=0;i<256;i++, pp+=3) + { + Pixels[i] = (uint8_t)i; + } + } + return Pixels; } //=========================================================================== diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 2313d573d..f122745a0 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -51,6 +51,7 @@ #include "r_data/sprites.h" #include "r_state.h" #include "vm.h" +#include "v_text.h" #include "gi.h" #include "stats.h" @@ -84,7 +85,7 @@ static bool IndexOutOfRange(const int color) if (outOfRange) { - Printf("Palette index %i is out of range [0..255]\n", color); + Printf(TEXTCOLOR_ORANGE "Palette index %i is out of range [0..255]\n", color); } return outOfRange; @@ -370,11 +371,11 @@ FNativePalette *FRemapTable::GetNative() // //---------------------------------------------------------------------------- -void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) +bool FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) { if (IndexOutOfRange(start, end, pal1, pal2)) { - return; + return false; } double palcol, palstep; @@ -391,7 +392,7 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) Remap[start] = pal1; Palette[start] = GPalette.BaseColors[pal1]; Palette[start].a = start == 0 ? 0 : 255; - return; + return true; } palcol = pal1; palstep = (pal2 - palcol) / (end - start); @@ -402,6 +403,7 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) Palette[j] = GPalette.BaseColors[k]; Palette[j].a = j == 0 ? 0 : 255; } + return true; } //---------------------------------------------------------------------------- @@ -410,11 +412,11 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2) // //---------------------------------------------------------------------------- -void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2) +bool FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2) { if (IndexOutOfRange(start, end)) { - return; + return false; } double r1 = _r1; @@ -466,6 +468,7 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in b += bs; } } + return true; } //---------------------------------------------------------------------------- @@ -474,11 +477,11 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in // //---------------------------------------------------------------------------- -void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2) +bool FRemapTable::AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2) { if (IndexOutOfRange(start, end)) { - return; + return false; } r1 = clamp(r1, 0.0, 2.0); @@ -519,6 +522,7 @@ void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, doub Palette[cc] = pe; Palette[cc].a = cc == 0 ? 0:255; } + return true; } //---------------------------------------------------------------------------- @@ -527,11 +531,11 @@ void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, doub // //---------------------------------------------------------------------------- -void FRemapTable::AddColourisation(int start, int end, int r, int g, int b) +bool FRemapTable::AddColourisation(int start, int end, int r, int g, int b) { if (IndexOutOfRange(start, end)) { - return; + return false; } for (int i = start; i < end; ++i) @@ -549,6 +553,7 @@ void FRemapTable::AddColourisation(int start, int end, int r, int g, int b) Palette[j] = PalEntry(j == 0 ? 0 : 255, int(br), int(bg), int(bb)); Remap[j] = ColorMatcher.Pick(Palette[j]); } + return true; } //---------------------------------------------------------------------------- @@ -557,11 +562,11 @@ void FRemapTable::AddColourisation(int start, int end, int r, int g, int b) // //---------------------------------------------------------------------------- -void FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) +bool FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) { if (IndexOutOfRange(start, end)) { - return; + return false; } for (int i = start; i < end; ++i) @@ -579,6 +584,7 @@ void FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) Palette[j] = PalEntry(j == 0 ? 0 : 255, int(br), int(bg), int(bb)); Remap[j] = ColorMatcher.Pick(Palette[j]); } + return true; } //---------------------------------------------------------------------------- @@ -587,7 +593,7 @@ void FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount) // //---------------------------------------------------------------------------- -void FRemapTable::AddToTranslation(const char *range) +bool FRemapTable::AddToTranslation(const char *range) { int start,end; bool desaturated = false; @@ -607,7 +613,7 @@ void FRemapTable::AddToTranslation(const char *range) if (start < 0 || start > 255 || end < 0 || end > 255) { sc.ScriptError("Palette index out of range"); - return; + return false; } sc.MustGetAnyToken(); @@ -643,7 +649,7 @@ void FRemapTable::AddToTranslation(const char *range) b2 = sc.Number; sc.MustGetToken(']'); - AddColorRange(start, end, r1, g1, b1, r2, g2, b2); + return AddColorRange(start, end, r1, g1, b1, r2, g2, b2); } else if (sc.TokenType == '%') { @@ -683,7 +689,7 @@ void FRemapTable::AddToTranslation(const char *range) b2 = sc.Float; sc.MustGetToken(']'); - AddDesaturation(start, end, r1, g1, b1, r2, g2, b2); + return AddDesaturation(start, end, r1, g1, b1, r2, g2, b2); } else if (sc.TokenType == '#') { @@ -700,7 +706,7 @@ void FRemapTable::AddToTranslation(const char *range) b = sc.Number; sc.MustGetToken(']'); - AddColourisation(start, end, r, g, b); + return AddColourisation(start, end, r, g, b); } else if (sc.TokenType == '@') { @@ -720,7 +726,7 @@ void FRemapTable::AddToTranslation(const char *range) b = sc.Number; sc.MustGetToken(']'); - AddTint(start, end, r, g, b, a); + return AddTint(start, end, r, g, b, a); } else { @@ -731,12 +737,13 @@ void FRemapTable::AddToTranslation(const char *range) sc.MustGetToken(':'); sc.MustGetToken(TK_IntConst); pal2 = sc.Number; - AddIndexRange(start, end, pal1, pal2); + return AddIndexRange(start, end, pal1, pal2); } } catch (CRecoverableError &err) { Printf("Error in translation '%s':\n%s\n", range, err.GetMessage()); + return false; } } diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 7c8f821b0..143a8097e 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -39,12 +39,12 @@ struct FRemapTable bool IsIdentity() const; void Serialize(FSerializer &arc); static void StaticSerializeTranslations(FSerializer &arc); - void AddIndexRange(int start, int end, int pal1, int pal2); - void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2); - void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2); - void AddColourisation(int start, int end, int r, int g, int b); - void AddTint(int start, int end, int r, int g, int b, int amount); - void AddToTranslation(const char * range); + bool AddIndexRange(int start, int end, int pal1, int pal2); + bool AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2); + bool AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2); + bool AddColourisation(int start, int end, int r, int g, int b); + bool AddTint(int start, int end, int r, int g, int b, int amount); + bool AddToTranslation(const char * range); int StoreTranslation(int slot); uint8_t *Remap; // For the software renderer diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index b1fd98a5c..afb82d380 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -133,20 +133,28 @@ union FRenderStyle uint32_t AsDWORD; inline FRenderStyle &operator= (ERenderStyle legacy); - operator uint32_t() const { return AsDWORD; } bool operator==(const FRenderStyle &o) const { return AsDWORD == o.AsDWORD; } void CheckFuzz(); bool IsVisible(double alpha) const throw(); private: // Code that compares an actor's render style with a legacy render - // style value should be updated. Making these conversion operators - // private will catch those cases. - operator ERenderStyle() const { return STYLE_Normal; } - operator int() const { return STYLE_Normal; } + // style value should be updated. + operator ERenderStyle() = delete; + operator int() const = delete; }; extern FRenderStyle LegacyRenderStyles[STYLE_Count]; +inline FRenderStyle DefaultRenderStyle() +{ + return LegacyRenderStyles[STYLE_Normal]; +} + +inline FRenderStyle BadRenderStyle() // This is just a marker to find places where work is still needed. +{ + return LegacyRenderStyles[STYLE_Normal]; +} + inline FRenderStyle &FRenderStyle::operator= (ERenderStyle legacy) { if (legacy < STYLE_None || legacy >= STYLE_Count) diff --git a/src/r_data/voxels.cpp b/src/r_data/voxels.cpp index c982f0382..e9a9b89fc 100644 --- a/src/r_data/voxels.cpp +++ b/src/r_data/voxels.cpp @@ -180,6 +180,11 @@ static void RemapVoxelSlabs(kvxslab_t *dest, int size, const uint8_t *remap) // //========================================================================== +#if defined __GNUC__ && !defined __clang__ +#pragma GCC push_options +#pragma GCC optimize ("-fno-tree-loop-vectorize") +#endif // __GNUC__ && !__clang__ + FVoxel *R_LoadKVX(int lumpnum) { const kvxslab_t *slabs[MAXVOXMIPS]; @@ -320,6 +325,10 @@ FVoxel *R_LoadKVX(int lumpnum) return voxel; } +#if defined __GNUC__ && !defined __clang__ +#pragma GCC pop_options +#endif // __GNUC__ && !__clang__ + //========================================================================== // // diff --git a/src/resourcefiles/ancientzip.cpp b/src/resourcefiles/ancientzip.cpp index a56d9adeb..0088d1f00 100644 --- a/src/resourcefiles/ancientzip.cpp +++ b/src/resourcefiles/ancientzip.cpp @@ -70,7 +70,7 @@ if (bs < be) \ c = ReadBuf[bs++]; \ else { \ - be = In->Read(&ReadBuf, sizeof(ReadBuf)); \ + be = (decltype(be))In->Read(&ReadBuf, sizeof(ReadBuf)); \ c = ReadBuf[0]; \ bs = 1; \ } \ @@ -259,7 +259,7 @@ int FZipExploder::DecodeSF(TArray &decoder, int numvals) } int FZipExploder::Explode(unsigned char *out, unsigned int outsize, - FileReader *in, unsigned int insize, + FileReader &in, unsigned int insize, int flags) { int c, i, minMatchLen = 3, len, dist; @@ -268,7 +268,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, Hold = 0; Bits = 0; - In = in; + In = ∈ InLeft = insize; bs = be = 0; @@ -337,9 +337,9 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, #define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */ #define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */ -int ShrinkLoop(unsigned char *out, unsigned int outsize, - FileReader *In, unsigned int InLeft) +int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &_In, unsigned int InLeft) { + FileReader *In = &_In; unsigned char ReadBuf[256]; unsigned short Parent[HSIZE]; unsigned char Value[HSIZE], Stack[HSIZE]; diff --git a/src/resourcefiles/ancientzip.h b/src/resourcefiles/ancientzip.h index d51e89ca5..cffd239ad 100644 --- a/src/resourcefiles/ancientzip.h +++ b/src/resourcefiles/ancientzip.h @@ -38,7 +38,7 @@ class FZipExploder int DecodeSFValue(const TArray ¤tTree); int DecodeSF(TArray &decoder, int numvals); public: - int Explode(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize, int flags); + int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags); }; class CExplosionError : CRecoverableError @@ -47,4 +47,4 @@ public: CExplosionError(const char *message) : CRecoverableError(message) {} }; -int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize); \ No newline at end of file +int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize); \ No newline at end of file diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index aa5018eb3..9e675682c 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -58,19 +58,19 @@ extern ISzAlloc g_Alloc; struct CZDFileInStream { ISeekInStream s; - FileReader *File; + FileReader &File; - CZDFileInStream(FileReader *_file) + CZDFileInStream(FileReader &_file) + : File(_file) { s.Read = Read; s.Seek = Seek; - File = _file; } static SRes Read(const ISeekInStream *pp, void *buf, size_t *size) { CZDFileInStream *p = (CZDFileInStream *)pp; - long numread = p->File->Read(buf, (long)*size); + auto numread = p->File.Read(buf, (long)*size); if (numread < 0) { *size = 0; @@ -83,26 +83,26 @@ struct CZDFileInStream static SRes Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) { CZDFileInStream *p = (CZDFileInStream *)pp; - int move_method; + FileReader::ESeek move_method; int res; if (origin == SZ_SEEK_SET) { - move_method = SEEK_SET; + move_method = FileReader::SeekSet; } else if (origin == SZ_SEEK_CUR) { - move_method = SEEK_CUR; + move_method = FileReader::SeekCur; } else if (origin == SZ_SEEK_END) { - move_method = SEEK_END; + move_method = FileReader::SeekEnd; } else { return 1; } - res = p->File->Seek((long)*pos, move_method); - *pos = p->File->Tell(); + res = (int)p->File.Seek((long)*pos, move_method); + *pos = p->File.Tell(); return res; } }; @@ -117,13 +117,13 @@ struct C7zArchive Byte *OutBuffer; size_t OutBufferSize; - C7zArchive(FileReader *file) : ArchiveStream(file) + C7zArchive(FileReader &file) : ArchiveStream(file) { if (g_CrcTable[1] == 0) { CrcGenerateTable(); } - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); LookToRead2_CreateVTable(&LookStream, false); LookStream.realStream = &ArchiveStream.s; LookToRead2_Init(&LookStream); @@ -192,7 +192,7 @@ class F7ZFile : public FResourceFile C7zArchive *Archive; public: - F7ZFile(const char * filename, FileReader *filer); + F7ZFile(const char * filename, FileReader &filer); bool Open(bool quiet); virtual ~F7ZFile(); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } @@ -206,7 +206,7 @@ public: // //========================================================================== -F7ZFile::F7ZFile(const char * filename, FileReader *filer) +F7ZFile::F7ZFile(const char * filename, FileReader &filer) : FResourceFile(filename, filer) { Lumps = NULL; @@ -295,7 +295,7 @@ bool F7ZFile::Open(bool quiet) lump_p->LumpNameSetup(name); lump_p->LumpSize = static_cast(SzArEx_GetFileSize(archPtr, i)); lump_p->Owner = this; - lump_p->Flags = LUMPF_ZIPFILE; + lump_p->Flags = LUMPF_ZIPFILE|LUMPF_COMPRESSED; lump_p->Position = i; lump_p->CheckEmbedded(); lump_p++; @@ -361,21 +361,21 @@ int F7ZLump::FillCache() // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet) +FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet) { char head[k7zSignatureSize]; - if (file->GetLength() >= k7zSignatureSize) + if (file.GetLength() >= k7zSignatureSize) { - file->Seek(0, SEEK_SET); - file->Read(&head, k7zSignatureSize); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, k7zSignatureSize); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, k7zSignature, k7zSignatureSize)) { FResourceFile *rf = new F7ZFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index 2e5630169..3897e0341 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -55,7 +55,7 @@ struct FDirectoryLump : public FResourceLump { - virtual FileReader *NewReader(); + virtual FileReader NewReader(); virtual int FillCache(); FString mFullPath; @@ -90,7 +90,7 @@ public: //========================================================================== FDirectory::FDirectory(const char * directory) -: FResourceFile(NULL, NULL) +: FResourceFile(NULL) { FString dirname; @@ -287,16 +287,11 @@ void FDirectory::AddEntry(const char *fullpath, int size) // //========================================================================== -FileReader *FDirectoryLump::NewReader() +FileReader FDirectoryLump::NewReader() { - try - { - return new FileReader(mFullPath); - } - catch (CRecoverableError &) - { - return NULL; - } + FileReader fr; + fr.OpenFile(mFullPath); + return fr; } //========================================================================== @@ -307,15 +302,14 @@ FileReader *FDirectoryLump::NewReader() int FDirectoryLump::FillCache() { + FileReader fr; Cache = new char[LumpSize]; - FileReader *reader = NewReader(); - if (reader == NULL) + if (!fr.OpenFile(mFullPath)) { memset(Cache, 0, LumpSize); return 0; } - reader->Read(Cache, LumpSize); - delete reader; + fr.Read(Cache, LumpSize); RefCount = 1; return 1; } @@ -326,7 +320,7 @@ int FDirectoryLump::FillCache() // //========================================================================== -FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckDir(const char *filename, bool quiet) { FResourceFile *rf = new FDirectory(filename); if (rf->Open(quiet)) return rf; diff --git a/src/resourcefiles/file_grp.cpp b/src/resourcefiles/file_grp.cpp index 663aeb16e..4155e3485 100644 --- a/src/resourcefiles/file_grp.cpp +++ b/src/resourcefiles/file_grp.cpp @@ -73,7 +73,7 @@ struct GrpLump class FGrpFile : public FUncompressedFile { public: - FGrpFile(const char * filename, FileReader *file); + FGrpFile(const char * filename, FileReader &file); bool Open(bool quiet); }; @@ -84,7 +84,7 @@ public: // //========================================================================== -FGrpFile::FGrpFile(const char *filename, FileReader *file) +FGrpFile::FGrpFile(const char *filename, FileReader &file) : FUncompressedFile(filename, file) { Lumps = NULL; @@ -100,11 +100,11 @@ bool FGrpFile::Open(bool quiet) { GrpInfo header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); GrpLump *fileinfo = new GrpLump[NumLumps]; - Reader->Read (fileinfo, NumLumps * sizeof(GrpLump)); + Reader.Read (fileinfo, NumLumps * sizeof(GrpLump)); Lumps = new FUncompressedLump[NumLumps]; @@ -134,21 +134,21 @@ bool FGrpFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet) { char head[12]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 12); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 12); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "KenSilverman", 12)) { FResourceFile *rf = new FGrpFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_lump.cpp b/src/resourcefiles/file_lump.cpp index ee8751de3..244ff5c6a 100644 --- a/src/resourcefiles/file_lump.cpp +++ b/src/resourcefiles/file_lump.cpp @@ -46,7 +46,7 @@ class FLumpFile : public FUncompressedFile { public: - FLumpFile(const char * filename, FileReader *file); + FLumpFile(const char * filename, FileReader &file); bool Open(bool quiet); }; @@ -57,7 +57,8 @@ public: // //========================================================================== -FLumpFile::FLumpFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file) +FLumpFile::FLumpFile(const char *filename, FileReader &file) + : FUncompressedFile(filename, file) { } @@ -76,7 +77,7 @@ bool FLumpFile::Open(bool quiet) Lumps->Name[8] = 0; Lumps->Owner = this; Lumps->Position = 0; - Lumps->LumpSize = Reader->GetLength(); + Lumps->LumpSize = (int)Reader.GetLength(); Lumps->Namespace = ns_global; Lumps->Flags = 0; Lumps->FullName = NULL; @@ -94,11 +95,12 @@ bool FLumpFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckLump(const char *filename, FileReader &file, bool quiet) { // always succeeds FResourceFile *rf = new FLumpFile(filename, file); if (rf->Open(quiet)) return rf; + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; return NULL; } diff --git a/src/resourcefiles/file_pak.cpp b/src/resourcefiles/file_pak.cpp index b76a937c8..776138d70 100644 --- a/src/resourcefiles/file_pak.cpp +++ b/src/resourcefiles/file_pak.cpp @@ -66,7 +66,7 @@ struct dpackheader_t class FPakFile : public FUncompressedFile { public: - FPakFile(const char * filename, FileReader *file); + FPakFile(const char * filename, FileReader &file); bool Open(bool quiet); }; @@ -79,7 +79,8 @@ public: // //========================================================================== -FPakFile::FPakFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file) +FPakFile::FPakFile(const char *filename, FileReader &file) + : FUncompressedFile(filename, file) { Lumps = NULL; } @@ -94,13 +95,13 @@ bool FPakFile::Open(bool quiet) { dpackheader_t header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t); header.dirofs = LittleLong(header.dirofs); dpackfile_t *fileinfo = new dpackfile_t[NumLumps]; - Reader->Seek (header.dirofs, SEEK_SET); - Reader->Read (fileinfo, NumLumps * sizeof(dpackfile_t)); + Reader.Seek (header.dirofs, FileReader::SeekSet); + Reader.Read (fileinfo, NumLumps * sizeof(dpackfile_t)); Lumps = new FUncompressedLump[NumLumps]; @@ -126,21 +127,21 @@ bool FPakFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet) { char head[4]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "PACK", 4)) { FResourceFile *rf = new FPakFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_rff.cpp b/src/resourcefiles/file_rff.cpp index ba73dfc8b..6843904c0 100644 --- a/src/resourcefiles/file_rff.cpp +++ b/src/resourcefiles/file_rff.cpp @@ -111,7 +111,7 @@ class FRFFFile : public FResourceFile FRFFLump *Lumps; public: - FRFFFile(const char * filename, FileReader *file); + FRFFFile(const char * filename, FileReader &file); virtual ~FRFFFile(); virtual bool Open(bool quiet); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } @@ -124,7 +124,7 @@ public: // //========================================================================== -FRFFFile::FRFFFile(const char *filename, FileReader *file) +FRFFFile::FRFFFile(const char *filename, FileReader &file) : FResourceFile(filename, file) { Lumps = NULL; @@ -141,13 +141,13 @@ bool FRFFFile::Open(bool quiet) RFFLump *lumps; RFFInfo header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); header.DirOfs = LittleLong(header.DirOfs); lumps = new RFFLump[header.NumLumps]; - Reader->Seek (header.DirOfs, SEEK_SET); - Reader->Read (lumps, header.NumLumps * sizeof(RFFLump)); + Reader.Seek (header.DirOfs, FileReader::SeekSet); + Reader.Read (lumps, header.NumLumps * sizeof(RFFLump)); BloodCrypt (lumps, header.DirOfs, header.NumLumps * sizeof(RFFLump)); Lumps = new FRFFLump[NumLumps]; @@ -247,21 +247,21 @@ int FRFFLump::FillCache() // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet) { char head[4]; - if (file->GetLength() >= 16) + if (file.GetLength() >= 16) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "RFF\x1a", 4)) { FResourceFile *rf = new FRFFFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index 477bda8e1..2e0ebb1dc 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -40,191 +40,7 @@ #include "w_wad.h" #include "gi.h" #include "i_system.h" - -// Console Doom LZSS wrapper. -class FileReaderLZSS : public FileReaderBase -{ -private: - enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; - - FileReader &File; - bool SawEOF; - uint8_t InBuff[BUFF_SIZE]; - - enum StreamState - { - STREAM_EMPTY, - STREAM_BITS, - STREAM_FLUSH, - STREAM_FINAL - }; - struct - { - StreamState State; - - uint8_t *In; - unsigned int AvailIn; - unsigned int InternalOut; - - uint8_t CFlags, Bits; - - uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE]; - const uint8_t *WindowData; - uint8_t *InternalBuffer; - } Stream; - - void FillBuffer() - { - if(Stream.AvailIn) - memmove(InBuff, Stream.In, Stream.AvailIn); - - long numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.In = InBuff; - Stream.AvailIn = numread+Stream.AvailIn; - } - - // Reads a flag byte. - void PrepareBlocks() - { - assert(Stream.InternalBuffer == Stream.WindowData); - Stream.CFlags = *Stream.In++; - --Stream.AvailIn; - Stream.Bits = 0xFF; - Stream.State = STREAM_BITS; - } - - // Reads the next chunk in the block. Returns true if successful and - // returns false if it ran out of input data. - bool UncompressBlock() - { - if(Stream.CFlags & 1) - { - // Check to see if we have enough input - if(Stream.AvailIn < 2) - return false; - Stream.AvailIn -= 2; - - uint16_t pos = BigShort(*(uint16_t*)Stream.In); - uint8_t len = (pos & 0xF)+1; - pos >>= 4; - Stream.In += 2; - if(len == 1) - { - // We've reached the end of the stream. - Stream.State = STREAM_FINAL; - return true; - } - - const uint8_t* copyStart = Stream.InternalBuffer-pos-1; - - // Complete overlap: Single byte repeated - if(pos == 0) - memset(Stream.InternalBuffer, *copyStart, len); - // No overlap: One copy - else if(pos >= len) - memcpy(Stream.InternalBuffer, copyStart, len); - else - { - // Partial overlap: Copy in 2 or 3 chunks. - do - { - unsigned int copy = MIN(len, pos+1); - memcpy(Stream.InternalBuffer, copyStart, copy); - Stream.InternalBuffer += copy; - Stream.InternalOut += copy; - len -= copy; - pos += copy; // Increase our position since we can copy twice as much the next round. - } - while(len); - } - - Stream.InternalOut += len; - Stream.InternalBuffer += len; - } - else - { - // Uncompressed byte. - *Stream.InternalBuffer++ = *Stream.In++; - --Stream.AvailIn; - ++Stream.InternalOut; - } - - Stream.CFlags >>= 1; - Stream.Bits >>= 1; - - // If we're done with this block, flush the output - if(Stream.Bits == 0) - Stream.State = STREAM_FLUSH; - - return true; - } - -public: - FileReaderLZSS(FileReader &file) : File(file), SawEOF(false) - { - Stream.State = STREAM_EMPTY; - Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; - Stream.InternalOut = 0; - Stream.AvailIn = 0; - - FillBuffer(); - } - - ~FileReaderLZSS() - { - } - - long Read(void *buffer, long len) - { - - uint8_t *Out = (uint8_t*)buffer; - long AvailOut = len; - - do - { - while(Stream.AvailIn) - { - if(Stream.State == STREAM_EMPTY) - PrepareBlocks(); - else if(Stream.State == STREAM_BITS && !UncompressBlock()) - break; - else - break; - } - - unsigned int copy = MIN(Stream.InternalOut, AvailOut); - if(copy > 0) - { - memcpy(Out, Stream.WindowData, copy); - Out += copy; - AvailOut -= copy; - - // Slide our window - memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy); - Stream.InternalBuffer -= copy; - Stream.InternalOut -= copy; - } - - if(Stream.State == STREAM_FINAL) - break; - - if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH) - Stream.State = STREAM_EMPTY; - - if(Stream.AvailIn < 2) - FillBuffer(); - } - while(AvailOut && Stream.State != STREAM_FINAL); - - assert(AvailOut == 0); - return (long)(Out - (uint8_t*)buffer); - } -}; +#include "w_zip.h" //========================================================================== // @@ -243,8 +59,8 @@ public: { if(!Compressed) { - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileReader::SeekSet); + return &Owner->Reader; } return NULL; } @@ -252,7 +68,7 @@ public: { if(!Compressed) { - const char * buffer = Owner->Reader->GetBuffer(); + const char * buffer = Owner->Reader.GetBuffer(); if (buffer != NULL) { @@ -263,16 +79,19 @@ public: } } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileReader::SeekSet); Cache = new char[LumpSize]; if(Compressed) { - FileReaderLZSS lzss(*Owner->Reader); - lzss.Read(Cache, LumpSize); + FileReader lzss; + if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false)) + { + lzss.Read(Cache, LumpSize); + } } else - Owner->Reader->Read(Cache, LumpSize); + Owner->Reader.Read(Cache, LumpSize); RefCount = 1; return 1; @@ -294,7 +113,7 @@ class FWadFile : public FResourceFile void SkinHack (); public: - FWadFile(const char * filename, FileReader *file); + FWadFile(const char * filename, FileReader &file); ~FWadFile(); void FindStrifeTeaserVoices (); FResourceLump *GetLump(int lump) { return &Lumps[lump]; } @@ -310,7 +129,8 @@ public: // //========================================================================== -FWadFile::FWadFile(const char *filename, FileReader *file) : FResourceFile(filename, file) +FWadFile::FWadFile(const char *filename, FileReader &file) + : FResourceFile(filename, file) { Lumps = NULL; } @@ -331,9 +151,9 @@ bool FWadFile::Open(bool quiet) wadinfo_t header; uint32_t InfoTableOfs; bool isBigEndian = false; // Little endian is assumed until proven otherwise - const long wadSize = Reader->GetLength(); + auto wadSize = Reader.GetLength(); - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); InfoTableOfs = LittleLong(header.InfoTableOfs); @@ -353,8 +173,8 @@ bool FWadFile::Open(bool quiet) } wadlump_t *fileinfo = new wadlump_t[NumLumps]; - Reader->Seek (InfoTableOfs, SEEK_SET); - Reader->Read (fileinfo, NumLumps * sizeof(wadlump_t)); + Reader.Seek (InfoTableOfs, FileReader::SeekSet); + Reader.Read (fileinfo, NumLumps * sizeof(wadlump_t)); Lumps = new FWadFileLump[NumLumps]; @@ -369,7 +189,7 @@ bool FWadFile::Open(bool quiet) Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); Lumps[i].LumpSize = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); Lumps[i].Namespace = ns_global; - Lumps[i].Flags = 0; + Lumps[i].Flags = Lumps[i].Compressed? LUMPF_COMPRESSED : 0; Lumps[i].FullName = NULL; } @@ -655,21 +475,21 @@ void FWadFile::FindStrifeTeaserVoices () // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet) { char head[4]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { FResourceFile *rf = new FWadFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 3d842131d..b3bfa7a2d 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -51,7 +51,7 @@ // //========================================================================== -static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) +static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) { try { @@ -59,31 +59,23 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L { case METHOD_STORED: { - Reader->Read(Cache, LumpSize); + Reader.Read(Cache, LumpSize); break; } case METHOD_DEFLATE: - { - FileReaderZ frz(*Reader, true); - frz.Read(Cache, LumpSize); - break; - } - case METHOD_BZIP2: - { - FileReaderBZ2 frz(*Reader); - frz.Read(Cache, LumpSize); - break; - } - case METHOD_LZMA: { - FileReaderLZMA frz(*Reader, LumpSize, true); - frz.Read(Cache, LumpSize); + FileReader frz; + if (frz.OpenDecompressor(Reader, LumpSize, Method, false)) + { + frz.Read(Cache, LumpSize); + } break; } + // Fixme: These should also use a stream case METHOD_IMPLODE: { FZipExploder exploder; @@ -112,8 +104,9 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L bool FCompressedBuffer::Decompress(char *destbuffer) { - MemoryReader mr(mBuffer, mCompressedSize); - return UncompressZipLump(destbuffer, &mr, mMethod, mSize, mCompressedSize, mZipFlags); + FileReader mr; + mr.OpenMemory(mBuffer, mCompressedSize); + return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags); } //----------------------------------------------------------------------- @@ -123,7 +116,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer) // //----------------------------------------------------------------------- -static uint32_t Zip_FindCentralDir(FileReader * fin) +static uint32_t Zip_FindCentralDir(FileReader &fin) { unsigned char buf[BUFREADCOMMENT + 4]; uint32_t FileSize; @@ -131,9 +124,7 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) uint32_t uMaxBack; // maximum size of global comment uint32_t uPosFound=0; - fin->Seek(0, SEEK_END); - - FileSize = fin->Tell(); + FileSize = (uint32_t)fin.GetLength(); uMaxBack = MIN(0xffff, FileSize); uBackRead = 4; @@ -149,9 +140,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) uReadSize = MIN((BUFREADCOMMENT + 4), (FileSize - uReadPos)); - if (fin->Seek(uReadPos, SEEK_SET) != 0) break; + if (fin.Seek(uReadPos, FileReader::SeekSet) != 0) break; - if (fin->Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; + if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; for (i = (int)uReadSize - 3; (i--) > 0;) { @@ -174,7 +165,7 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) // //========================================================================== -FZipFile::FZipFile(const char * filename, FileReader *file) +FZipFile::FZipFile(const char * filename, FileReader &file) : FResourceFile(filename, file) { Lumps = NULL; @@ -195,8 +186,8 @@ bool FZipFile::Open(bool quiet) } // Read the central directory info. - Reader->Seek(centraldir, SEEK_SET); - Reader->Read(&info, sizeof(FZipEndOfCentralDirectory)); + Reader.Seek(centraldir, FileReader::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); // No multi-disk zips! if (info.NumEntries != info.NumEntriesOnAllDisks || @@ -212,8 +203,8 @@ bool FZipFile::Open(bool quiet) // Load the entire central directory. Too bad that this contains variable length entries... int dirsize = LittleLong(info.DirectorySize); void *directory = malloc(dirsize); - Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET); - Reader->Read(directory, dirsize); + Reader.Seek(LittleLong(info.DirectoryOffset), FileReader::SeekSet); + Reader.Read(directory, dirsize); char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; @@ -289,6 +280,8 @@ bool FZipFile::Open(bool quiet) } } } + // If it ran through the list without finding anything it should not attempt any path remapping. + if (!foundspeciallump) name0 = ""; dirptr = (char*)directory; lump_p = Lumps; @@ -349,6 +342,7 @@ bool FZipFile::Open(bool quiet) // The start of the Reader will be determined the first time it is accessed. lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Method = uint8_t(zip_fh->Method); + if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED; lump_p->GPFlags = zip_fh->Flags; lump_p->CRC32 = zip_fh->CRC32; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); @@ -394,8 +388,8 @@ FCompressedBuffer FZipLump::GetRawData() { FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] }; if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); - Owner->Reader->Seek(Position, SEEK_SET); - Owner->Reader->Read(cbuf.mBuffer, CompressedSize); + Owner->Reader.Seek(Position, FileReader::SeekSet); + Owner->Reader.Read(cbuf.mBuffer, CompressedSize); return cbuf; } @@ -413,10 +407,8 @@ void FZipLump::SetLumpAddress() FZipLocalFileHeader localHeader; int skiplen; - FileReader *file = Owner->Reader; - - file->Seek(Position, SEEK_SET); - file->Read(&localHeader, sizeof(localHeader)); + Owner->Reader.Seek(Position, FileReader::SeekSet); + Owner->Reader.Read(&localHeader, sizeof(localHeader)); skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength); Position += sizeof(localHeader) + skiplen; Flags &= ~LUMPFZIP_NEEDFILESTART; @@ -435,8 +427,8 @@ FileReader *FZipLump::GetReader() if (Method == METHOD_STORED) { if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileReader::SeekSet); + return &Owner->Reader; } else return NULL; } @@ -452,7 +444,7 @@ int FZipLump::FillCache() if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); const char *buffer; - if (Method == METHOD_STORED && (buffer = Owner->Reader->GetBuffer()) != NULL) + if (Method == METHOD_STORED && (buffer = Owner->Reader.GetBuffer()) != NULL) { // This is an in-memory file so the cache can point directly to the file's data. Cache = const_cast(buffer) + Position; @@ -460,7 +452,7 @@ int FZipLump::FillCache() return -1; } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileReader::SeekSet); Cache = new char[LumpSize]; UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags); RefCount = 1; @@ -486,21 +478,21 @@ int FZipLump::GetFileOffset() // //========================================================================== -FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet) { char head[4]; - if (file->GetLength() >= (long)sizeof(FZipLocalFileHeader)) + if (file.GetLength() >= (long)sizeof(FZipLocalFileHeader)) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "PK\x3\x4", 4)) { FResourceFile *rf = new FZipFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } @@ -517,17 +509,19 @@ FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet) // //========================================================================== -static void time_to_dos(struct tm *time, unsigned short *dosdate, unsigned short *dostime) +static std::pair time_to_dos(struct tm *time) { + std::pair val; if (time == NULL || time->tm_year < 80) { - *dosdate = *dostime = 0; + val.first = val.second = 0; } else { - *dosdate = LittleShort((time->tm_year - 80) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday); - *dostime = LittleShort(time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2); + val.first = (time->tm_year - 80) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday; + val.second= time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2; } + return val; } //========================================================================== @@ -542,7 +536,7 @@ static void time_to_dos(struct tm *time, unsigned short *dosdate, unsigned short // //========================================================================== -int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time) +int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime) { FZipLocalFileHeader local; int position; @@ -550,10 +544,10 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c local.Magic = ZIP_LOCALFILE; local.VersionToExtract[0] = 20; local.VersionToExtract[1] = 0; - local.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort(2) : LittleShort((uint16_t)content.mZipFlags); - local.Method = LittleShort(content.mMethod); - local.ModDate = date; - local.ModTime = time; + local.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); + local.Method = LittleShort((uint16_t)content.mMethod); + local.ModDate = LittleShort(dostime.first); + local.ModTime = LittleShort(dostime.second); local.CRC32 = content.mCRC32; local.UncompressedSize = LittleLong(content.mSize); local.CompressedSize = LittleLong(content.mCompressedSize); @@ -583,7 +577,7 @@ int AppendToZip(FileWriter *zip_file, const char *filename, FCompressedBuffer &c // //========================================================================== -int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, uint16_t date, uint16_t time, int position) +int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompressedBuffer &content, std::pair &dostime, int position) { FZipCentralDirectoryInfo dir; @@ -592,10 +586,10 @@ int AppendCentralDirectory(FileWriter *zip_file, const char *filename, FCompress dir.VersionMadeBy[1] = 0; dir.VersionToExtract[0] = 20; dir.VersionToExtract[1] = 0; - dir.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort(2) : LittleShort((uint16_t)content.mZipFlags); - dir.Method = LittleShort(content.mMethod); - dir.ModTime = time; - dir.ModDate = date; + dir.Flags = content.mMethod == METHOD_DEFLATE ? LittleShort((uint16_t)2) : LittleShort((uint16_t)content.mZipFlags); + dir.Method = LittleShort((uint16_t)content.mMethod); + dir.ModTime = LittleShort(dostime.first); + dir.ModDate = LittleShort(dostime.second); dir.CRC32 = content.mCRC32; dir.CompressedSize = LittleLong(content.mCompressedSize); dir.UncompressedSize = LittleLong(content.mSize); @@ -620,10 +614,9 @@ bool WriteZip(const char *filename, TArray &filenames, TArray positions; @@ -634,7 +627,7 @@ bool WriteZip(const char *filename, TArray &filenames, TArray &filenames, TArrayTell(); for (unsigned i = 0; i < filenames.Size(); i++) { - if (AppendCentralDirectory(f, filenames[i], content[i], mydate, mytime, positions[i]) < 0) + if (AppendCentralDirectory(f, filenames[i], content[i], dostime, positions[i]) < 0) { delete f; remove(filename); @@ -660,9 +653,9 @@ bool WriteZip(const char *filename, TArray &filenames, TArrayTell() - dirofs); + dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs)); dirend.ZipCommentLength = 0; if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) { diff --git a/src/resourcefiles/file_zip.h b/src/resourcefiles/file_zip.h index 1078a0714..466292e40 100644 --- a/src/resourcefiles/file_zip.h +++ b/src/resourcefiles/file_zip.h @@ -43,7 +43,7 @@ class FZipFile : public FResourceFile FZipLump *Lumps; public: - FZipFile(const char * filename, FileReader *file); + FZipFile(const char * filename, FileReader &file); virtual ~FZipFile(); bool Open(bool quiet); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 18a6b6f15..adb484d32 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -34,6 +34,7 @@ ** */ +#include #include "resourcefile.h" #include "cmdlib.h" #include "w_wad.h" @@ -45,7 +46,7 @@ //========================================================================== // -// FileReader that reads from a lump's cache +// File reader that reads from a lump's cache // //========================================================================== @@ -227,9 +228,9 @@ FileReader *FResourceLump::GetReader() // //========================================================================== -FileReader *FResourceLump::NewReader() +FileReader FResourceLump::NewReader() { - return new FLumpReader(this); + return FileReader(new FLumpReader(this)); } //========================================================================== @@ -276,46 +277,45 @@ int FResourceLump::ReleaseCache() // //========================================================================== -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader *file, bool quiet); +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, bool quiet); -FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet); -FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet); +FResourceFile *CheckWad(const char *filename, FileReader &file, bool quiet); +FResourceFile *CheckGRP(const char *filename, FileReader &file, bool quiet); +FResourceFile *CheckRFF(const char *filename, FileReader &file, bool quiet); +FResourceFile *CheckPak(const char *filename, FileReader &file, bool quiet); +FResourceFile *CheckZip(const char *filename, FileReader &file, bool quiet); +FResourceFile *Check7Z(const char *filename, FileReader &file, bool quiet); +FResourceFile *CheckLump(const char *filename,FileReader &file, bool quiet); +FResourceFile *CheckDir(const char *filename, bool quiet); static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckLump }; -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader *file, bool quiet, bool containeronly) +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly) { - bool mustclose = false; - if (file == NULL) - { - try - { - file = new FileReader(filename); - mustclose = true; - } - catch (CRecoverableError &) - { - return NULL; - } - } for(size_t i = 0; i < countof(funcs) - containeronly; i++) { FResourceFile *resfile = funcs[i](filename, file, quiet); if (resfile != NULL) return resfile; } - if (mustclose) delete file; return NULL; } +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly) +{ + return DoOpenResourceFile(filename, file, quiet, containeronly); +} + + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly) +{ + FileReader file; + if (!file.OpenFile(filename)) return nullptr; + return DoOpenResourceFile(filename, file, quiet, containeronly); +} + FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) { - return CheckDir(filename, NULL, quiet); + return CheckDir(filename, quiet); } //========================================================================== @@ -324,18 +324,21 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) // //========================================================================== -FResourceFile::FResourceFile(const char *filename, FileReader *r) +FResourceFile::FResourceFile(const char *filename) { if (filename != NULL) Filename = copystring(filename); else Filename = NULL; - Reader = r; } +FResourceFile::FResourceFile(const char *filename, FileReader &r) + : FResourceFile(filename) +{ + Reader = std::move(r); +} FResourceFile::~FResourceFile() { if (Filename != NULL) delete [] Filename; - delete Reader; } int lumpcmp(const void * a, const void * b) @@ -609,8 +612,8 @@ FResourceLump *FResourceFile::FindLump(const char *name) FileReader *FUncompressedLump::GetReader() { - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileReader::SeekSet); + return &Owner->Reader; } //========================================================================== @@ -621,7 +624,7 @@ FileReader *FUncompressedLump::GetReader() int FUncompressedLump::FillCache() { - const char * buffer = Owner->Reader->GetBuffer(); + const char * buffer = Owner->Reader.GetBuffer(); if (buffer != NULL) { @@ -631,9 +634,9 @@ int FUncompressedLump::FillCache() return -1; } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileReader::SeekSet); Cache = new char[LumpSize]; - Owner->Reader->Read(Cache, LumpSize); + Owner->Reader.Read(Cache, LumpSize); RefCount = 1; return 1; } @@ -644,11 +647,13 @@ int FUncompressedLump::FillCache() // //========================================================================== -FUncompressedFile::FUncompressedFile(const char *filename, FileReader *r) -: FResourceFile(filename, r) -{ - Lumps = NULL; -} +FUncompressedFile::FUncompressedFile(const char *filename) +: FResourceFile(filename) +{} + +FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r) + : FResourceFile(filename, r) +{} FUncompressedFile::~FUncompressedFile() { @@ -671,9 +676,9 @@ FExternalLump::FExternalLump(const char *_filename, int filesize) { FileReader f; - if (f.Open(_filename)) + if (f.OpenFile(_filename)) { - LumpSize = f.GetLength(); + LumpSize = (int)f.GetLength(); } else { @@ -704,7 +709,7 @@ int FExternalLump::FillCache() Cache = new char[LumpSize]; FileReader f; - if (f.Open(filename)) + if (f.OpenFile(filename)) { f.Read(Cache, LumpSize); } @@ -728,7 +733,7 @@ bool FMemoryFile::Open(bool quiet) Lumps->FullName = fname; Lumps->Owner = this; Lumps->Position = 0; - Lumps->LumpSize = Reader->GetLength(); + Lumps->LumpSize = (int)Reader.GetLength(); Lumps->Namespace = ns_global; Lumps->Flags = 0; Lumps->FullName = NULL; diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index f7cc806e2..9b39b0908 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -63,7 +63,7 @@ struct FResourceLump virtual ~FResourceLump(); virtual FileReader *GetReader(); - virtual FileReader *NewReader(); + virtual FileReader NewReader(); virtual int GetFileOffset() { return -1; } virtual int GetIndexNum() const { return 0; } void LumpNameSetup(FString iname); @@ -81,12 +81,13 @@ protected: class FResourceFile { public: - FileReader *Reader; + FileReader Reader; const char *Filename; protected: uint32_t NumLumps; - FResourceFile(const char *filename, FileReader *r); + FResourceFile(const char *filename); + FResourceFile(const char *filename, FileReader &r); // for archives that can contain directories void PostProcessArchive(void *lumps, size_t lumpsize); @@ -98,12 +99,15 @@ private: int FilterLumpsByGameType(int gametype, void *lumps, size_t lumpsize, uint32_t max); bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max); + static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool quiet, bool containeronly); public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false, bool containeronly = false); + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false); + static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false); static FResourceFile *OpenDirectory(const char *filename, bool quiet = false); virtual ~FResourceFile(); - FileReader *GetReader() const { return Reader; } + // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. + FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; } uint32_t LumpCount() const { return NumLumps; } uint32_t GetFirstLump() const { return FirstLump; } void SetFirstLump(uint32_t f) { FirstLump = f; } @@ -129,14 +133,12 @@ struct FUncompressedLump : public FResourceLump class FUncompressedFile : public FResourceFile { protected: - FUncompressedLump * Lumps; + FUncompressedLump * Lumps = nullptr; - - FUncompressedFile(const char *filename, FileReader *r); + FUncompressedFile(const char *filename); + FUncompressedFile(const char *filename, FileReader &r); virtual ~FUncompressedFile(); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } - -public: }; @@ -152,12 +154,10 @@ struct FExternalLump : public FResourceLump struct FMemoryFile : public FUncompressedFile { - MemoryArrayReader mr; - FMemoryFile(const char *_filename, const void *sdata, int length) - : FUncompressedFile(_filename, nullptr), mr((const char *)sdata, length) + : FUncompressedFile(_filename) { - Reader = &mr; + Reader.OpenMemoryArray(sdata, length); } bool Open(bool quiet); diff --git a/src/s_playlist.cpp b/src/s_playlist.cpp index 315a2ac76..979bbb67a 100644 --- a/src/s_playlist.cpp +++ b/src/s_playlist.cpp @@ -62,7 +62,7 @@ bool FPlayList::ChangeList (const char *path) Songs.Clear(); Position = 0; - if (!fr.Open(path)) + if (!fr.OpenFile(path)) { Printf ("Could not open " TEXTCOLOR_BOLD "%s" TEXTCOLOR_NORMAL ": %s\n", path, strerror(errno)); return false; @@ -71,7 +71,7 @@ bool FPlayList::ChangeList (const char *path) first = true; pls = false; playlistdir = ExtractFilePath(path); - while ((song = NextLine(&fr)).IsNotEmpty()) + while ((song = NextLine(fr)).IsNotEmpty()) { if (first) { @@ -133,14 +133,14 @@ bool FPlayList::ChangeList (const char *path) return Songs.Size() != 0; } -FString FPlayList::NextLine (FileReader *file) +FString FPlayList::NextLine (FileReader &file) { char buffer[512]; char *skipper; do { - if (NULL == file->Gets (buffer, countof(buffer))) + if (nullptr == file.Gets (buffer, countof(buffer))) return ""; for (skipper = buffer; *skipper != 0 && *skipper <= ' '; skipper++) diff --git a/src/s_playlist.h b/src/s_playlist.h index 859f0bce4..e1f497879 100644 --- a/src/s_playlist.h +++ b/src/s_playlist.h @@ -53,7 +53,7 @@ public: const char *GetSong (int position) const; private: - static FString NextLine (FileReader *file); + static FString NextLine (FileReader &file); unsigned int Position; TArray Songs; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index f9ee262c1..088f9404d 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1430,7 +1430,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) int size = Wads.LumpLength(sfx->lumpnum); if (size > 0) { - FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum); + auto wlump = Wads.OpenLumpReader(sfx->lumpnum); uint8_t *sfxdata = new uint8_t[size]; wlump.Read(sfxdata, size); int32_t dmxlen = LittleLong(((int32_t *)sfxdata)[1]); @@ -1498,7 +1498,7 @@ static void S_LoadSound3D(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) int size = Wads.LumpLength(sfx->lumpnum); if (size <= 0) return; - FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum); + auto wlump = Wads.OpenLumpReader(sfx->lumpnum); uint8_t *sfxdata = new uint8_t[size]; wlump.Read(sfxdata, size); int32_t dmxlen = LittleLong(((int32_t *)sfxdata)[1]); @@ -2609,7 +2609,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) musicname += 7; } - FileReader *reader = NULL; + FileReader reader; if (!FileExists (musicname)) { if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1) @@ -2623,17 +2623,16 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) { return false; } - reader = Wads.ReopenLumpNumNewFile(lumpnum); - if (reader == NULL) - { - return false; - } + reader = Wads.ReopenLumpReader(lumpnum); } } else { // Load an external file. - reader = new FileReader(musicname); + if (!reader.OpenFile(musicname)) + { + return false; + } } // shutdown old music @@ -2646,7 +2645,6 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) mus_playing.name = musicname; mus_playing.baseorder = order; LastSong = musicname; - delete reader; return true; } @@ -2654,7 +2652,6 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) if (handle != NULL) { mus_playing.handle = handle; - delete reader; } else { diff --git a/src/sc_man.cpp b/src/sc_man.cpp index b78b7a305..216a5527a 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -249,7 +249,7 @@ bool FScanner::OpenFile (const char *name) Close (); FileReader fr; - if (!fr.Open(name)) return false; + if (!fr.OpenFile(name)) return false; auto filesize = fr.GetLength(); auto filebuf = new uint8_t[filesize]; if (fr.Read(filebuf, filesize) != filesize) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 03ad9c1cc..76339417f 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -761,6 +761,7 @@ DEFINE_PROPERTY(translation, L, Actor) else { FRemapTable CurrentTranslation; + bool success = true; CurrentTranslation.MakeIdentity(); for(int i = 1; i < PROP_PARM_COUNT; i++) @@ -774,10 +775,15 @@ DEFINE_PROPERTY(translation, L, Actor) } else { - CurrentTranslation.AddToTranslation(str); + // parse all ranges to get a complete list of errors, if more than one range fails. + success |= CurrentTranslation.AddToTranslation(str); } } defaults->Translation = CurrentTranslation.StoreTranslation (TRANSLATION_Decorate); + if (!success) + { + bag.ScriptPosition.Message(MSG_WARNING, "Failed to parse translation"); + } } } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index e4773f1c6..4d530c8a5 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2494,6 +2494,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool bool hasoptionals = false; if (p != nullptr) { + bool overridemsg = false; do { int elementcount = 1; @@ -2528,6 +2529,22 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { flags |= VARF_Optional; hasoptionals = true; + + if ((varflags & VARF_Override) && !overridemsg) + { + // This is illegal, but in older compilers wasn't checked, so there it has to be demoted to a warning. + // Virtual calls always need to get their defaults from the base virtual method. + if (mVersion >= MakeVersion(3, 3)) + { + Error(p, "Default values for parameter of virtual override not allowed"); + } + else + { + Warn(p, "Default values for parameter of virtual override will be ignored!"); + } + overridemsg = true; + } + FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); FCompileContext ctx(OutNamespace, c->Type(), false); @@ -2721,6 +2738,13 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool clstype->Virtuals[vindex] = sym->Variants[0].Implementation; sym->Variants[0].Implementation->VirtualIndex = vindex; sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; + + // Defaults must be identical to parent class + if (parentfunc->Variants[0].Implementation->DefaultArgs.Size() > 0) + { + sym->Variants[0].Implementation->DefaultArgs = parentfunc->Variants[0].Implementation->DefaultArgs; + sym->Variants[0].ArgFlags = parentfunc->Variants[0].ArgFlags; + } } } else diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 02d78021b..6902753da 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -484,7 +484,7 @@ static void DoParse(int lumpnum) else if (FScriptPosition::WarnCounter > 0) { // If we got warnings, but no errors, print the information but continue. - Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); + Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars()); } } diff --git a/src/serializer.cpp b/src/serializer.cpp index c41fec1f3..75f96d581 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -37,6 +37,7 @@ #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag +#include #include "rapidjson/rapidjson.h" #include "rapidjson/writer.h" #include "rapidjson/prettywriter.h" diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index cbea4ee2c..273ddb115 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "i_musicinterns.h" #include "doomtype.h" @@ -398,7 +399,7 @@ static EMIDIType IdentifyMIDIType(uint32_t *id, int size) // //========================================================================== -MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) +MusInfo *I_RegisterSong (FileReader &reader, MidiDeviceSetting *device) { MusInfo *info = nullptr; const char *fmt; @@ -406,14 +407,12 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) if (nomusic) { - delete reader; - return 0; + return nullptr; } - if(reader->Read(id, 32) != 32 || reader->Seek(-32, SEEK_CUR) != 0) + if(reader.Read(id, 32) != 32 || reader.Seek(-32, FileReader::SeekCur) != 0) { - delete reader; - return 0; + return nullptr; } // Check for gzip compression. Some formats are expected to have players @@ -421,44 +420,38 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) // gzippable. if ((id[0] & MAKE_ID(255, 255, 255, 0)) == GZIP_ID) { - int len = reader->GetLength(); - uint8_t *gzipped = new uint8_t[len]; - if (reader->Read(gzipped, len) != len) + + if (!reader.OpenMemoryArray([&reader](TArray &array) { + bool res = false; + auto len = reader.GetLength(); + uint8_t *gzipped = new uint8_t[len]; + if (reader.Read(gzipped, len) == len) + { + res = ungzip(gzipped, (int)len, array); + } delete[] gzipped; - delete reader; + return res; + })) + { return nullptr; } - delete reader; - MemoryArrayReader *memreader = new MemoryArrayReader(nullptr, 0); - if (!ungzip(gzipped, len, memreader->GetArray())) + if (reader.Read(id, 32) != 32 || reader.Seek(-32, FileReader::SeekCur) != 0) { - delete[] gzipped; - delete memreader; - return 0; + return nullptr; } - delete[] gzipped; - memreader->UpdateLength(); - - if (memreader->Read(id, 32) != 32 || memreader->Seek(-32, SEEK_CUR) != 0) - { - delete memreader; - return 0; - } - reader = memreader; } EMIDIType miditype = IdentifyMIDIType(id, sizeof(id)); if (miditype != MIDI_NOTMIDI) { - auto source = CreateMIDISource(*reader, miditype); - if (source == nullptr) return 0; + auto source = CreateMIDISource(reader, miditype); + if (source == nullptr) return nullptr; if (!source->isValid()) { - delete reader; delete source; - return 0; + return nullptr; } EMidiDevice devtype = device == nullptr? MDEV_DEFAULT : (EMidiDevice)device->device; @@ -471,9 +464,8 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) MIDIStreamer *streamer = CreateMIDIStreamer(devtype, device != nullptr? device->args.GetChars() : ""); if (streamer == nullptr) { - delete reader; delete source; - return 0; + return nullptr; } streamer->SetMIDISource(source); info = streamer; @@ -485,22 +477,21 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) (id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL (id[0] == MAKE_ID('A','D','L','I') && *((uint8_t *)id + 4) == 'B')) // Martin Fernandez's modified IMF { - info = new OPLMUSSong (*reader, device != nullptr? device->args.GetChars() : ""); + info = new OPLMUSSong (reader, device != nullptr? device->args.GetChars() : ""); } // Check for game music else if ((fmt = GME_CheckFormat(id[0])) != nullptr && fmt[0] != '\0') { - info = GME_OpenSong(*reader, fmt); + info = GME_OpenSong(reader, fmt); } // Check for module formats else { - info = MOD_OpenSong(*reader); + info = MOD_OpenSong(reader); } if (info == nullptr) { - info = SndFile_OpenSong(*reader); - if (info != nullptr) reader = nullptr; + info = SndFile_OpenSong(reader); } if (info == nullptr) @@ -510,24 +501,21 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device) { uint32_t subid; - reader->Seek(8, SEEK_CUR); - if (reader->Read (&subid, 4) != 4) + reader.Seek(8, FileReader::SeekCur); + if (reader.Read (&subid, 4) != 4) { - delete reader; - return 0; + return nullptr; } - reader->Seek(-12, SEEK_CUR); + reader.Seek(-12, FileReader::SeekCur); if (subid == (('C')|(('D')<<8)|(('D')<<16)|(('A')<<24))) { // This is a CDDA file - info = new CDDAFile (*reader); + info = new CDDAFile (reader); } } } - if (reader != nullptr) delete reader; - if (info && !info->IsValid ()) { delete info; @@ -719,10 +707,10 @@ static MIDISource *GetMIDISource(const char *fn) return nullptr; } - FWadLump wlump = Wads.OpenLumpNum(lump); + auto wlump = Wads.OpenLumpReader(lump); uint32_t id[32 / 4]; - if (wlump.Read(id, 32) != 32 || wlump.Seek(-32, SEEK_CUR) != 0) + if (wlump.Read(id, 32) != 32 || wlump.Seek(-32, FileReader::SeekCur) != 0) { Printf("Unable to read lump %s\n", src.GetChars()); return nullptr; diff --git a/src/sound/i_music.h b/src/sound/i_music.h index 9a7b0836b..7976c1d48 100644 --- a/src/sound/i_music.h +++ b/src/sound/i_music.h @@ -55,7 +55,7 @@ void I_SetMusicVolume (float volume); // Registers a song handle to song data. class MusInfo; struct MidiDeviceSetting; -MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device); +MusInfo *I_RegisterSong (FileReader &reader, MidiDeviceSetting *device); MusInfo *I_RegisterCDSong (int track, int cdid = 0); // The base music class. Everything is derived from this -------------------- diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 3dc5b8384..9e5887043 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -198,7 +198,7 @@ protected: class MIDIWaveWriter : public SoftSynthMIDIDevice { public: - MIDIWaveWriter(const char *filename, MIDIDevice *devtouse); + MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *devtouse); ~MIDIWaveWriter(); int Resume(); int Open(MidiCallback cb, void *userdata) @@ -428,7 +428,7 @@ protected: class StreamSong : public MusInfo { public: - StreamSong (FileReader *reader); + StreamSong (FileReader &reader); ~StreamSong (); void Play (bool looping, int subsong); void Pause (); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 562945d19..ac05783c5 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -159,9 +159,8 @@ public: { return NULL; } - SoundStream *OpenStream (FileReader *reader, int flags) + SoundStream *OpenStream (FileReader &reader, int flags) { - delete reader; return NULL; } @@ -371,13 +370,15 @@ FString SoundRenderer::GatherStats () short *SoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType ctype) { - MemoryReader reader((const char*)coded, sizebytes); + FileReader reader; short *samples = (short*)calloc(1, outlen); ChannelConfig chans; SampleType type; int srate; - SoundDecoder *decoder = CreateDecoder(&reader); + reader.OpenMemory(coded, sizebytes); + + SoundDecoder *decoder = CreateDecoder(reader); if(!decoder) return samples; decoder->getInfo(&srate, &chans, &type); @@ -577,16 +578,16 @@ std::pair SoundRenderer::LoadSoundBuffered(FSoundLoadBuffer * return std::make_pair(retval, true); } -SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader) +SoundDecoder *SoundRenderer::CreateDecoder(FileReader &reader) { SoundDecoder *decoder = NULL; - int pos = reader->Tell(); + auto pos = reader.Tell(); #ifdef HAVE_SNDFILE decoder = new SndFileDecoder; if (decoder->open(reader)) return decoder; - reader->Seek(pos, SEEK_SET); + reader.Seek(pos, FileReader::SeekSet); delete decoder; decoder = NULL; @@ -595,7 +596,7 @@ SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader) decoder = new MPG123Decoder; if (decoder->open(reader)) return decoder; - reader->Seek(pos, SEEK_SET); + reader.Seek(pos, FileReader::SeekSet); delete decoder; decoder = NULL; diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 333eda229..ce02f7356 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -118,7 +118,7 @@ public: // Streaming sounds. virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; - virtual SoundStream *OpenStream (FileReader *reader, int flags) = 0; + virtual SoundStream *OpenStream (FileReader &reader, int flags) = 0; // Starts a sound. virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0; @@ -168,7 +168,7 @@ public: virtual void DrawWaveDebug(int mode); - static SoundDecoder *CreateDecoder(FileReader *reader); + static SoundDecoder *CreateDecoder(FileReader &reader); }; extern SoundRenderer *GSnd; diff --git a/src/sound/i_soundfont.cpp b/src/sound/i_soundfont.cpp index 4a073bc5e..3e30af741 100644 --- a/src/sound/i_soundfont.cpp +++ b/src/sound/i_soundfont.cpp @@ -50,7 +50,7 @@ FSoundFontManager sfmanager; // //========================================================================== -std::pair FSoundFontReader::LookupFile(const char *name) +std::pair FSoundFontReader::LookupFile(const char *name) { if (!IsAbsPath(name)) { @@ -58,12 +58,12 @@ std::pair FSoundFontReader::LookupFile(const char *name) { FString fullname = mPaths[i] + name; auto fr = OpenFile(fullname); - if (fr != nullptr) return std::make_pair(fr, fullname); + if (fr.isOpen()) return std::make_pair(std::move(fr), fullname); } } auto fr = OpenFile(name); - if (fr != nullptr) return std::make_pair(fr, name); - return std::make_pair(nullptr, FString()); + if (!fr.isOpen()) name = ""; + return std::make_pair(std::move(fr), name); } //========================================================================== @@ -117,24 +117,24 @@ FSF2Reader::FSF2Reader(const char *fn) // //========================================================================== -FileReader *FSF2Reader::OpenMainConfigFile() +FileReader FSF2Reader::OpenMainConfigFile() { + FileReader fr; if (mMainConfigForSF2.IsNotEmpty()) { - return new MemoryReader(mMainConfigForSF2.GetChars(), (long)mMainConfigForSF2.Len()); + fr.OpenMemory(mMainConfigForSF2.GetChars(), mMainConfigForSF2.Len()); } - return nullptr; + return fr; } -FileReader *FSF2Reader::OpenFile(const char *name) +FileReader FSF2Reader::OpenFile(const char *name) { + FileReader fr; if (mFilename.CompareNoCase(name) == 0) { - auto fr = new FileReader; - if (fr->Open(name)) return fr; - delete fr; + fr.OpenFile(name); } - return nullptr; + return fr; } //========================================================================== @@ -145,7 +145,7 @@ FileReader *FSF2Reader::OpenFile(const char *name) FZipPatReader::FZipPatReader(const char *filename) { - resf = FResourceFile::OpenResourceFile(filename, nullptr, true); + resf = FResourceFile::OpenResourceFile(filename, true); } FZipPatReader::~FZipPatReader() @@ -153,13 +153,14 @@ FZipPatReader::~FZipPatReader() if (resf != nullptr) delete resf; } -FileReader *FZipPatReader::OpenMainConfigFile() +FileReader FZipPatReader::OpenMainConfigFile() { return OpenFile("timidity.cfg"); } -FileReader *FZipPatReader::OpenFile(const char *name) +FileReader FZipPatReader::OpenFile(const char *name) { + FileReader fr; if (resf != nullptr) { auto lump = resf->FindLump(name); @@ -168,7 +169,7 @@ FileReader *FZipPatReader::OpenFile(const char *name) return lump->NewReader(); } } - return nullptr; + return fr; } //========================================================================== @@ -194,8 +195,8 @@ FPatchSetReader::FPatchSetReader(const char *filename) }; #endif mAllowAbsolutePaths = true; - FileReader *fr = new FileReader; - if (fr->Open(filename)) + FileReader fr; + if (fr.OpenFile(filename)) { mFullPathToConfig = filename; } @@ -204,7 +205,7 @@ FPatchSetReader::FPatchSetReader(const char *filename) for(auto c : paths) { FStringf fullname("%s/%s", c, filename); - if (fr->Open(fullname)) + if (fr.OpenFile(fullname)) { mFullPathToConfig = fullname; } @@ -224,23 +225,21 @@ FPatchSetReader::FPatchSetReader() mAllowAbsolutePaths = true; } -FileReader *FPatchSetReader::OpenMainConfigFile() +FileReader FPatchSetReader::OpenMainConfigFile() { - auto fr = new FileReader; - if (fr->Open(mFullPathToConfig)) return fr; - delete fr; - return nullptr; + FileReader fr; + fr.OpenFile(mFullPathToConfig); + return fr; } -FileReader *FPatchSetReader::OpenFile(const char *name) +FileReader FPatchSetReader::OpenFile(const char *name) { FString path; if (IsAbsPath(name)) path = name; else path = mBasePath + name; - auto fr = new FileReader; - if (fr->Open(path)) return fr; - delete fr; - return nullptr; + FileReader fr; + fr.OpenFile(path); + return fr; } //========================================================================== @@ -252,7 +251,6 @@ FileReader *FPatchSetReader::OpenFile(const char *name) FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) { mLumpIndex = Wads.CheckNumForFullName(filename); - FileReader *fr = new FileReader; mBasePath = filename; FixPathSeperator(mBasePath); @@ -260,19 +258,19 @@ FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/'; } -FileReader *FLumpPatchSetReader::OpenMainConfigFile() +FileReader FLumpPatchSetReader::OpenMainConfigFile() { - return Wads.ReopenLumpNum(mLumpIndex); + return Wads.ReopenLumpReader(mLumpIndex); } -FileReader *FLumpPatchSetReader::OpenFile(const char *name) +FileReader FLumpPatchSetReader::OpenFile(const char *name) { FString path; - if (IsAbsPath(name)) return nullptr; // no absolute paths in the lump directory. + if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory. path = mBasePath + name; auto index = Wads.CheckNumForFullName(path); - if (index < 0) return nullptr; - return Wads.ReopenLumpNum(index); + if (index < 0) return FileReader(); + return Wads.ReopenLumpReader(index); } //========================================================================== @@ -296,7 +294,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) } FileReader fr; - if (fr.Open(fn)) + if (fr.OpenFile(fn)) { // Try to identify. We only accept .sf2 and .zip by content. All other archives are intentionally ignored. char head[16] = { 0}; @@ -308,7 +306,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) } else if (!memcmp(head, "PK", 2)) { - auto zip = FResourceFile::OpenResourceFile(fn, nullptr, true); + auto zip = FResourceFile::OpenResourceFile(fn, true); if (zip != nullptr) { if (zip->LumpCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code @@ -438,7 +436,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed if (allowed & SF_SF2) { FileReader fr; - if (fr.Open(name)) + if (fr.OpenFile(name)) { char head[16] = { 0}; fr.Read(head, 16); @@ -452,7 +450,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed if (allowed & SF_GUS) { FileReader fr; - if (fr.Open(name)) + if (fr.OpenFile(name)) { char head[16] = { 0 }; fr.Read(head, 2); diff --git a/src/sound/i_soundfont.h b/src/sound/i_soundfont.h index 9208351e4..5ef60102c 100644 --- a/src/sound/i_soundfont.h +++ b/src/sound/i_soundfont.h @@ -41,9 +41,9 @@ protected: public: virtual ~FSoundFontReader() {} - virtual FileReader *OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets - virtual FileReader *OpenFile(const char *name) = 0; - std::pair LookupFile(const char *name); + virtual FileReader OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets + virtual FileReader OpenFile(const char *name) = 0; + std::pair LookupFile(const char *name); void AddPath(const char *str); virtual FString basePath() const { @@ -63,8 +63,8 @@ class FSF2Reader : public FSoundFontReader FString mFilename; public: FSF2Reader(const char *filename); - virtual FileReader *OpenMainConfigFile() override; - virtual FileReader *OpenFile(const char *name) override; + virtual FileReader OpenMainConfigFile() override; + virtual FileReader OpenFile(const char *name) override; }; //========================================================================== @@ -79,8 +79,8 @@ class FZipPatReader : public FSoundFontReader public: FZipPatReader(const char *filename); ~FZipPatReader(); - virtual FileReader *OpenMainConfigFile() override; - virtual FileReader *OpenFile(const char *name) override; + virtual FileReader OpenMainConfigFile() override; + virtual FileReader OpenFile(const char *name) override; bool isOk() { return resf != nullptr; } }; @@ -97,8 +97,8 @@ class FLumpPatchSetReader : public FSoundFontReader public: FLumpPatchSetReader(const char *filename); - virtual FileReader *OpenMainConfigFile() override; - virtual FileReader *OpenFile(const char *name) override; + virtual FileReader OpenMainConfigFile() override; + virtual FileReader OpenFile(const char *name) override; virtual FString basePath() const override { return mBasePath; @@ -120,8 +120,8 @@ class FPatchSetReader : public FSoundFontReader public: FPatchSetReader(); FPatchSetReader(const char *filename); - virtual FileReader *OpenMainConfigFile() override; - virtual FileReader *OpenFile(const char *name) override; + virtual FileReader OpenMainConfigFile() override; + virtual FileReader OpenFile(const char *name) override; virtual FString basePath() const override { return mBasePath; diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index 5bdc023bc..a6104166d 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -112,7 +112,7 @@ struct FISoundChannel }; -void FindLoopTags(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass); +void FindLoopTags(FileReader &fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass); enum SampleType @@ -143,7 +143,7 @@ struct SoundDecoder virtual ~SoundDecoder() { } protected: - virtual bool open(FileReader *reader) = 0; + virtual bool open(FileReader &reader) = 0; friend class SoundRenderer; private: diff --git a/src/sound/mididevices/music_opl_mididevice.cpp b/src/sound/mididevices/music_opl_mididevice.cpp index a37358520..48aa8104f 100644 --- a/src/sound/mididevices/music_opl_mididevice.cpp +++ b/src/sound/mididevices/music_opl_mididevice.cpp @@ -83,7 +83,9 @@ OPLMIDIDevice::OPLMIDIDevice(const char *args) { OPL_SetCore(args); FullPan = opl_fullpan; - FWadLump data = Wads.OpenLumpName("GENMIDI"); + auto lump = Wads.CheckNumForName("GENMIDI", ns_global); + if (lump < 0) I_Error("No GENMIDI lump found"); + auto data = Wads.OpenLumpReader(lump); uint8_t filehdr[8]; data.Read(filehdr, 8); diff --git a/src/sound/mididevices/music_wavewriter_mididevice.cpp b/src/sound/mididevices/music_wavewriter_mididevice.cpp index 1f109aea2..6bf585636 100644 --- a/src/sound/mididevices/music_wavewriter_mididevice.cpp +++ b/src/sound/mididevices/music_wavewriter_mididevice.cpp @@ -87,11 +87,11 @@ struct FmtChunk // //========================================================================== -MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice) - : SoftSynthMIDIDevice(playDevice->GetSampleRate()) +MIDIWaveWriter::MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *playdevice) + : SoftSynthMIDIDevice(playdevice->GetSampleRate()) { File = FileWriter::Open(filename); - playDevice = (SoftSynthMIDIDevice*) playdevice; + playDevice = playdevice; if (File != nullptr) { // Write wave header uint32_t work[3]; @@ -106,18 +106,18 @@ MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice) playDevice->CalcTickRate(); fmt.ChunkID = MAKE_ID('f','m','t',' '); fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8)); - fmt.FormatTag = LittleShort(0xFFFE); // WAVE_FORMAT_EXTENSIBLE - fmt.Channels = LittleShort(2); + fmt.FormatTag = LittleShort((uint16_t)0xFFFE); // WAVE_FORMAT_EXTENSIBLE + fmt.Channels = LittleShort((uint16_t)2); fmt.SamplesPerSec = LittleLong(SampleRate); fmt.AvgBytesPerSec = LittleLong(SampleRate * 8); - fmt.BlockAlign = LittleShort(8); - fmt.BitsPerSample = LittleShort(32); - fmt.ExtensionSize = LittleShort(2 + 4 + 16); - fmt.ValidBitsPerSample = LittleShort(32); + fmt.BlockAlign = LittleShort((uint16_t)8); + fmt.BitsPerSample = LittleShort((uint16_t)32); + fmt.ExtensionSize = LittleShort((uint16_t)(2 + 4 + 16)); + fmt.ValidBitsPerSample = LittleShort((uint16_t)32); fmt.ChannelMask = LittleLong(3); fmt.SubFormatA = LittleLong(0x00000003); // Set subformat to KSDATAFORMAT_SUBTYPE_IEEE_FLOAT - fmt.SubFormatB = LittleShort(0x0000); - fmt.SubFormatC = LittleShort(0x0010); + fmt.SubFormatB = 0x0000; + fmt.SubFormatC = LittleShort((uint16_t)0x0010); fmt.SubFormatD[0] = 0x80; fmt.SubFormatD[1] = 0x00; fmt.SubFormatD[2] = 0x00; diff --git a/src/sound/midisources/midisource_hmi.cpp b/src/sound/midisources/midisource_hmi.cpp index c2ce9b1fc..7b9276f1f 100644 --- a/src/sound/midisources/midisource_hmi.cpp +++ b/src/sound/midisources/midisource_hmi.cpp @@ -128,7 +128,7 @@ struct HMISong::TrackInfo HMISong::HMISong (FileReader &reader) { - int len = reader.GetLength(); + int len = (int)reader.GetLength(); if (len < 0x100) { // Way too small to be HMI. return; diff --git a/src/sound/midisources/midisource_mus.cpp b/src/sound/midisources/midisource_mus.cpp index feddfe67c..f978b888f 100644 --- a/src/sound/midisources/midisource_mus.cpp +++ b/src/sound/midisources/midisource_mus.cpp @@ -33,11 +33,6 @@ // HEADER FILES ------------------------------------------------------------ -#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__OpenBSD__) -#include -#else -#include -#endif #include "i_musicinterns.h" #include "templates.h" #include "doomdef.h" diff --git a/src/sound/midisources/midisource_smf.cpp b/src/sound/midisources/midisource_smf.cpp index 6385bf997..5330d74d4 100644 --- a/src/sound/midisources/midisource_smf.cpp +++ b/src/sound/midisources/midisource_smf.cpp @@ -105,7 +105,7 @@ MIDISong2::MIDISong2 (FileReader &reader) int p; int i; - SongLen = reader.GetLength(); + SongLen = (int)reader.GetLength(); MusHeader = new uint8_t[SongLen]; if (reader.Read(MusHeader, SongLen) != SongLen) return; diff --git a/src/sound/midisources/midisource_xmi.cpp b/src/sound/midisources/midisource_xmi.cpp index b59308176..3fbfdeb5d 100644 --- a/src/sound/midisources/midisource_xmi.cpp +++ b/src/sound/midisources/midisource_xmi.cpp @@ -108,7 +108,7 @@ struct XMISong::TrackInfo XMISong::XMISong (FileReader &reader) : MusHeader(0), Songs(0) { - SongLen = reader.GetLength(); + SongLen = (int)reader.GetLength(); MusHeader = new uint8_t[SongLen]; if (reader.Read(MusHeader, SongLen) != SongLen) return; diff --git a/src/sound/mpg123_decoder.cpp b/src/sound/mpg123_decoder.cpp index f8d946429..716553c52 100644 --- a/src/sound/mpg123_decoder.cpp +++ b/src/sound/mpg123_decoder.cpp @@ -74,28 +74,28 @@ static bool inited = false; off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence) { - FileReader *reader = reinterpret_cast(handle)->Reader; + auto &reader = reinterpret_cast(handle)->Reader; if(whence == SEEK_CUR) { - if(offset < 0 && reader->Tell()+offset < 0) + if(offset < 0 && reader.Tell()+offset < 0) return -1; } else if(whence == SEEK_END) { - if(offset < 0 && reader->GetLength()+offset < 0) + if(offset < 0 && reader.GetLength()+offset < 0) return -1; } - if(reader->Seek(offset, whence) != 0) + if(reader.Seek(offset, (FileReader::ESeek)whence) != 0) return -1; - return reader->Tell(); + return (off_t)reader.Tell(); } ssize_t MPG123Decoder::file_read(void *handle, void *buffer, size_t bytes) { - FileReader *reader = reinterpret_cast(handle)->Reader; - return (ssize_t)reader->Read(buffer, (long)bytes); + auto &reader = reinterpret_cast(handle)->Reader; + return (ssize_t)reader.Read(buffer, (long)bytes); } @@ -109,7 +109,7 @@ MPG123Decoder::~MPG123Decoder() } } -bool MPG123Decoder::open(FileReader *reader) +bool MPG123Decoder::open(FileReader &reader) { if(!inited) { @@ -118,7 +118,7 @@ bool MPG123Decoder::open(FileReader *reader) inited = true; } - Reader = reader; + Reader = std::move(reader); { MPG123 = mpg123_new(NULL, NULL); @@ -145,7 +145,8 @@ bool MPG123Decoder::open(FileReader *reader) MPG123 = 0; } - return false; + reader = std::move(Reader); // need to give it back. + return false; } void MPG123Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) @@ -214,8 +215,10 @@ bool MPG123Decoder::seek(size_t ms_offset, bool ms, bool mayrestart) mpg123_delete(MPG123); MPG123 = 0; } - Reader->Seek(0, SEEK_SET); - return open(Reader); + Reader.Seek(0, FileReader::SeekSet); + // Do not call open with our own reader variable, that would be catastrophic. + auto reader = std::move(Reader); + return open(reader); } } size_t MPG123Decoder::getSampleOffset() diff --git a/src/sound/mpg123_decoder.h b/src/sound/mpg123_decoder.h index 02af11a16..dad0f11fe 100644 --- a/src/sound/mpg123_decoder.h +++ b/src/sound/mpg123_decoder.h @@ -2,6 +2,7 @@ #define MPG123_DECODER_H #include "i_soundinternal.h" +#include "files.h" #ifdef HAVE_MPG123 @@ -29,13 +30,13 @@ struct MPG123Decoder : public SoundDecoder virtual ~MPG123Decoder(); protected: - virtual bool open(FileReader *reader); + virtual bool open(FileReader &reader); private: mpg123_handle *MPG123; bool Done; - FileReader *Reader; + FileReader Reader; static off_t file_lseek(void *handle, off_t offset, int whence); static ssize_t file_read(void *handle, void *buffer, size_t bytes); diff --git a/src/sound/musicformats/music_cd.cpp b/src/sound/musicformats/music_cd.cpp index 7d5a8e4a3..52de04a57 100644 --- a/src/sound/musicformats/music_cd.cpp +++ b/src/sound/musicformats/music_cd.cpp @@ -118,11 +118,11 @@ CDDAFile::CDDAFile (FileReader &reader) uint32_t chunk; uint16_t track; uint32_t discid; - long endpos = reader.Tell() + reader.GetLength() - 8; + auto endpos = reader.Tell() + reader.GetLength() - 8; // I_RegisterSong already identified this as a CDDA file, so we // just need to check the contents we're interested in. - reader.Seek(12, SEEK_CUR); + reader.Seek(12, FileReader::SeekCur); while (reader.Tell() < endpos) { @@ -130,11 +130,11 @@ CDDAFile::CDDAFile (FileReader &reader) if (chunk != (('f')|(('m')<<8)|(('t')<<16)|((' ')<<24))) { reader.Read(&chunk, 4); - reader.Seek(chunk, SEEK_CUR); + reader.Seek(chunk, FileReader::SeekCur); } else { - reader.Seek(6, SEEK_CUR); + reader.Seek(6, FileReader::SeekCur); reader.Read(&track, 2); reader.Read(&discid, 4); diff --git a/src/sound/musicformats/music_dumb.cpp b/src/sound/musicformats/music_dumb.cpp index 7706ff947..19f76cb02 100644 --- a/src/sound/musicformats/music_dumb.cpp +++ b/src/sound/musicformats/music_dumb.cpp @@ -776,7 +776,6 @@ MusInfo *MOD_OpenSong(FileReader &reader) }; dumbfile_mem_status filestate; DUMBFILE *f = NULL; - long fpos = 0; input_mod *state = NULL; bool is_it = false; @@ -784,8 +783,8 @@ MusInfo *MOD_OpenSong(FileReader &reader) atterm(dumb_exit); - int size = reader.GetLength(); - fpos = reader.Tell(); + int size = (int)reader.GetLength(); + auto fpos = reader.Tell(); filestate.ptr = start; filestate.offset = 0; @@ -903,7 +902,7 @@ MusInfo *MOD_OpenSong(FileReader &reader) { if (!(f = dumb_read_allfile(&filestate, start, reader, headsize, size))) { - reader.Seek(fpos, SEEK_SET); + reader.Seek(fpos, FileReader::SeekSet); return NULL; } } @@ -944,7 +943,7 @@ MusInfo *MOD_OpenSong(FileReader &reader) else { // Reposition file pointer for other codecs to do their checks. - reader.Seek(fpos, SEEK_SET); + reader.Seek(fpos, FileReader::SeekSet); } if (filestate.ptr != (uint8_t *)start) { diff --git a/src/sound/musicformats/music_gme.cpp b/src/sound/musicformats/music_gme.cpp index 88aeabcab..b0dff3da1 100644 --- a/src/sound/musicformats/music_gme.cpp +++ b/src/sound/musicformats/music_gme.cpp @@ -128,31 +128,31 @@ MusInfo *GME_OpenSong(FileReader &reader, const char *fmt) } sample_rate = (int)GSnd->GetOutputRate(); emu = gme_new_emu(type, sample_rate); - if (emu == NULL) + if (emu == nullptr) { - return NULL; + return nullptr; } - int fpos = reader.Tell(); - int len = reader.GetLength(); + auto fpos = reader.Tell(); + auto len = reader.GetLength(); song = new uint8_t[len]; if (reader.Read(song, len) != len) { delete[] song; gme_delete(emu); - reader.Seek(fpos, SEEK_SET); - return NULL; + reader.Seek(fpos, FileReader::SeekSet); + return nullptr; } - err = gme_load_data(emu, song, len); + err = gme_load_data(emu, song, (long)len); delete[] song; - if (err != NULL) + if (err != nullptr) { Printf("Failed loading song: %s\n", err); gme_delete(emu); - reader.Seek(fpos, SEEK_SET); - return NULL; + reader.Seek(fpos, FileReader::SeekSet); + return nullptr; } gme_set_stereo_depth(emu, clamp(*gme_stereodepth, 0.f, 1.f)); return new GMESong(emu, sample_rate); diff --git a/src/sound/musicformats/music_libsndfile.cpp b/src/sound/musicformats/music_libsndfile.cpp index af53ac37f..61be6b56c 100644 --- a/src/sound/musicformats/music_libsndfile.cpp +++ b/src/sound/musicformats/music_libsndfile.cpp @@ -48,7 +48,7 @@ class SndFileSong : public StreamSong { public: - SndFileSong(FileReader *reader, SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass); + SndFileSong(FileReader &reader, SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass); ~SndFileSong(); bool SetSubsong(int subsong); void Play(bool looping, int subsong); @@ -56,7 +56,7 @@ public: protected: FCriticalSection CritSec; - FileReader *Reader; + FileReader Reader; SoundDecoder *Decoder; int Channels; int SampleRate; @@ -105,23 +105,23 @@ CUSTOM_CVAR(Int, snd_streambuffersize, 64, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // //========================================================================== -static void ParseVorbisComments(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass) +static void ParseVorbisComments(FileReader &fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass) { uint8_t vc_data[4]; // The VC block starts with a 32LE integer for the vendor string length, // followed by the vendor string - if(fr->Read(vc_data, 4) != 4) + if(fr.Read(vc_data, 4) != 4) return; uint32_t vndr_len = vc_data[0] | (vc_data[1]<<8) | (vc_data[2]<<16) | (vc_data[3]<<24); // Skip vendor string - if(fr->Seek(vndr_len, SEEK_CUR) == -1) + if(fr.Seek(vndr_len, FileReader::SeekCur) == -1) return; // Following the vendor string is a 32LE integer for the number of // comments, followed by each comment. - if(fr->Read(vc_data, 4) != 4) + if(fr.Read(vc_data, 4) != 4) return; size_t count = vc_data[0] | (vc_data[1]<<8) | (vc_data[2]<<16) | (vc_data[3]<<24); @@ -129,20 +129,20 @@ static void ParseVorbisComments(FileReader *fr, uint32_t *start, bool *startass, { // Each comment is a 32LE integer for the comment length, followed by // the comment text (not null terminated!) - if(fr->Read(vc_data, 4) != 4) + if(fr.Read(vc_data, 4) != 4) return; uint32_t length = vc_data[0] | (vc_data[1]<<8) | (vc_data[2]<<16) | (vc_data[3]<<24); if(length >= 128) { // If the comment is "big", skip it - if(fr->Seek(length, SEEK_CUR) == -1) + if(fr.Seek(length, FileReader::SeekCur) == -1) return; continue; } char strdat[128]; - if(fr->Read(strdat, length) != (long)length) + if(fr.Read(strdat, length) != (long)length) return; strdat[length] = 0; @@ -153,13 +153,13 @@ static void ParseVorbisComments(FileReader *fr, uint32_t *start, bool *startass, } } -static void FindFlacComments(FileReader *fr, uint32_t *loop_start, bool *startass, uint32_t *loop_end, bool *endass) +static void FindFlacComments(FileReader &fr, uint32_t *loop_start, bool *startass, uint32_t *loop_end, bool *endass) { // Already verified the fLaC marker, so we're 4 bytes into the file bool lastblock = false; uint8_t header[4]; - while(!lastblock && fr->Read(header, 4) == 4) + while(!lastblock && fr.Read(header, 4) == 4) { // The first byte of the block header contains the type and a flag // indicating the last metadata block @@ -175,18 +175,18 @@ static void FindFlacComments(FileReader *fr, uint32_t *loop_start, bool *startas return; } - if(fr->Seek(blocksize, SEEK_CUR) == -1) + if(fr.Seek(blocksize, FileReader::SeekCur) == -1) break; } } -static void FindOggComments(FileReader *fr, uint32_t *loop_start, bool *startass, uint32_t *loop_end, bool *endass) +static void FindOggComments(FileReader &fr, uint32_t *loop_start, bool *startass, uint32_t *loop_end, bool *endass) { uint8_t ogghead[27]; // We already read and verified the OggS marker, so skip the first 4 bytes // of the Ogg page header. - while(fr->Read(ogghead+4, 23) == 23) + while(fr.Read(ogghead+4, 23) == 23) { // The 19th byte of the Ogg header is a 32LE integer for the page // number, and the 27th is a uint8 for the number of segments in the @@ -199,7 +199,7 @@ static void FindOggComments(FileReader *fr, uint32_t *loop_start, bool *startass // each segment in the page. The page segment data follows contiguously // after. uint8_t segsizes[256]; - if(fr->Read(segsizes, ogg_segments) != ogg_segments) + if(fr.Read(segsizes, ogg_segments) != ogg_segments) break; // Find the segment with the Vorbis Comment packet (type 3) @@ -210,7 +210,7 @@ static void FindOggComments(FileReader *fr, uint32_t *loop_start, bool *startass if(segsize > 16) { uint8_t vorbhead[7]; - if(fr->Read(vorbhead, 7) != 7) + if(fr.Read(vorbhead, 7) != 7) return; if(vorbhead[0] == 3 && memcmp(vorbhead+1, "vorbis", 6) == 0) @@ -237,7 +237,7 @@ static void FindOggComments(FileReader *fr, uint32_t *loop_start, bool *startass segsize -= 7; } - if(fr->Seek(segsize, SEEK_CUR) == -1) + if(fr.Seek(segsize, FileReader::SeekCur) == -1) return; } @@ -245,16 +245,16 @@ static void FindOggComments(FileReader *fr, uint32_t *loop_start, bool *startass if(ogg_pagenum >= 2) break; - if(fr->Read(ogghead, 4) != 4 || memcmp(ogghead, "OggS", 4) != 0) + if(fr.Read(ogghead, 4) != 4 || memcmp(ogghead, "OggS", 4) != 0) break; } } -void FindLoopTags(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass) +void FindLoopTags(FileReader &fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass) { uint8_t signature[4]; - fr->Read(signature, 4); + fr.Read(signature, 4); if(memcmp(signature, "fLaC", 4) == 0) FindFlacComments(fr, start, startass, end, endass); else if(memcmp(signature, "OggS", 4) == 0) @@ -270,16 +270,16 @@ void FindLoopTags(FileReader *fr, uint32_t *start, bool *startass, uint32_t *end MusInfo *SndFile_OpenSong(FileReader &fr) { - fr.Seek(0, SEEK_SET); + fr.Seek(0, FileReader::SeekSet); uint32_t loop_start = 0, loop_end = ~0u; bool startass = false, endass = false; - FindLoopTags(&fr, &loop_start, &startass, &loop_end, &endass); + FindLoopTags(fr, &loop_start, &startass, &loop_end, &endass); - fr.Seek(0, SEEK_SET); - auto decoder = SoundRenderer::CreateDecoder(&fr); + fr.Seek(0, FileReader::SeekSet); + auto decoder = SoundRenderer::CreateDecoder(fr); if (decoder == nullptr) return nullptr; - return new SndFileSong(&fr, decoder, loop_start, loop_end, startass, endass); + return new SndFileSong(fr, decoder, loop_start, loop_end, startass, endass); } //========================================================================== @@ -288,7 +288,7 @@ MusInfo *SndFile_OpenSong(FileReader &fr) // //========================================================================== -SndFileSong::SndFileSong(FileReader *reader, SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass) +SndFileSong::SndFileSong(FileReader &reader, SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass) { ChannelConfig iChannels; SampleType Type; @@ -298,9 +298,10 @@ SndFileSong::SndFileSong(FileReader *reader, SoundDecoder *decoder, uint32_t loo if (!startass) loop_start = Scale(loop_start, SampleRate, 1000); if (!endass) loop_end = Scale(loop_end, SampleRate, 1000); + const uint32_t sampleLength = (uint32_t)decoder->getSampleLength(); Loop_Start = loop_start; - Loop_End = clamp(loop_end, 0, (uint32_t)decoder->getSampleLength()); - Reader = reader; + Loop_End = sampleLength == 0 ? loop_end : clamp(loop_end, 0, sampleLength); + Reader = std::move(reader); Decoder = decoder; Channels = iChannels == ChannelConfig_Stereo? 2:1; m_Stream = GSnd->CreateStream(Read, snd_streambuffersize * 1024, iChannels == ChannelConfig_Stereo? 0 : SoundStream::Mono, SampleRate, this); @@ -324,10 +325,6 @@ SndFileSong::~SndFileSong() { delete Decoder; } - if (Reader != nullptr) - { - delete Reader; - } } @@ -423,12 +420,17 @@ bool SndFileSong::Read(SoundStream *stream, void *vbuff, int ilen, void *userdat // This looks a bit more complicated than necessary because libmpg123 will not read the full requested length for the last block in the file. if (currentpos + framestoread > song->Loop_End) { - size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; - size_t endlen = song->Decoder->read(buff, endblock); + // Loop can be very short, make sure the current position doesn't exceed it + if (currentpos < song->Loop_End) + { + size_t endblock = (song->Loop_End - currentpos) * song->Channels * 2; + size_t endlen = song->Decoder->read(buff, endblock); + + // Even if zero bytes was read give it a chance to start from the beginning + buff += endlen; + len -= endlen; + } - // Even if zero bytes was read give it a chance to start from the beginning - buff = buff + endlen; - len -= endlen; song->Decoder->seek(song->Loop_Start, false, true); } while (len > 0) diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index 3a5697ac4..85fc91545 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -325,8 +325,13 @@ bool MIDIStreamer::DumpWave(const char *filename, int subsong, int samplerate) assert(MIDI == NULL); auto devtype = SelectMIDIDevice(DeviceType); + if (devtype == MDEV_MMAPI) + { + Printf("MMAPI device is not supported"); + return false; + } MIDI = CreateMIDIDevice(devtype, samplerate); - MIDI = new MIDIWaveWriter(filename, MIDI); + MIDI = new MIDIWaveWriter(filename, reinterpret_cast(MIDI)); return InitPlayback(); } diff --git a/src/sound/musicformats/music_opl.cpp b/src/sound/musicformats/music_opl.cpp index 64596c2fb..fe29bb145 100644 --- a/src/sound/musicformats/music_opl.cpp +++ b/src/sound/musicformats/music_opl.cpp @@ -74,7 +74,7 @@ OPLMUSSong::OPLMUSSong (FileReader &reader, const char *args) int samples = int(OPL_SAMPLE_RATE / 14); OPL_SetCore(args); - Music = new OPLmusicFile (&reader); + Music = new OPLmusicFile (reader); m_Stream = GSnd->CreateStream (FillStream, samples*4, (current_opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this); diff --git a/src/sound/musicformats/music_stream.cpp b/src/sound/musicformats/music_stream.cpp index dbb5a85f2..01f75fb4b 100644 --- a/src/sound/musicformats/music_stream.cpp +++ b/src/sound/musicformats/music_stream.cpp @@ -85,7 +85,7 @@ StreamSong::~StreamSong () } } -StreamSong::StreamSong (FileReader *reader) +StreamSong::StreamSong (FileReader &reader) { m_Stream = GSnd->OpenStream (reader, SoundStream::Loop); } diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index d234b0b05..033f40b89 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -228,7 +228,7 @@ class OpenALSoundStream : public SoundStream ALfloat Volume; - FileReader *Reader; + FileReader Reader; SoundDecoder *Decoder; static bool DecoderCallback(SoundStream *_sstream, void *ptr, int length, void *user) { @@ -290,7 +290,7 @@ class OpenALSoundStream : public SoundStream public: OpenALSoundStream(OpenALSoundRenderer *renderer) - : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Reader(NULL), Decoder(NULL) + : Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f), Decoder(NULL) { memset(Buffers, 0, sizeof(Buffers)); Renderer->AddStream(this); @@ -317,7 +317,6 @@ public: getALError(); delete Decoder; - delete Reader; } @@ -604,17 +603,15 @@ public: return true; } - bool Init(FileReader *reader, bool loop) + bool Init(FileReader &reader, bool loop) { if(!SetupSource()) { - delete reader; return false; } if(Decoder) delete Decoder; - if(Reader) delete Reader; - Reader = reader; + Reader = std::move(reader); Decoder = Renderer->CreateDecoder(Reader); if(!Decoder) return false; @@ -1279,7 +1276,7 @@ std::pair OpenALSoundRenderer::LoadSoundRaw(uint8_t *sfxdata, std::pair OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int length, bool monoize, FSoundLoadBuffer *pBuffer) { SoundHandle retval = { NULL }; - MemoryReader reader((const char*)sfxdata, length); + FileReader reader; ALenum format = AL_NONE; ChannelConfig chans; SampleType type; @@ -1290,10 +1287,12 @@ std::pair OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int /* Only downmix to mono if we can't spatialize multi-channel sounds. */ monoize = monoize && !AL.SOFT_source_spatialize; - FindLoopTags(&reader, &loop_start, &startass, &loop_end, &endass); + reader.OpenMemory(sfxdata, length); - reader.Seek(0, SEEK_SET); - std::unique_ptr decoder(CreateDecoder(&reader)); + FindLoopTags(reader, &loop_start, &startass, &loop_end, &endass); + + reader.Seek(0, FileReader::SeekSet); + std::unique_ptr decoder(CreateDecoder(reader)); if (!decoder) return std::make_pair(retval, true); decoder->getInfo(&srate, &chans, &type); @@ -1530,7 +1529,7 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int return stream; } -SoundStream *OpenALSoundRenderer::OpenStream(FileReader *reader, int flags) +SoundStream *OpenALSoundRenderer::OpenStream(FileReader &reader, int flags) { if(StreamThread.get_id() == std::thread::id()) StreamThread = std::thread(std::mem_fn(&OpenALSoundRenderer::BackgroundProc), this); diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 92d2235aa..a2a7869ce 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -136,7 +136,7 @@ public: // Streaming sounds. virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata); - virtual SoundStream *OpenStream(FileReader *reader, int flags); + virtual SoundStream *OpenStream(FileReader &reader, int flags); // Starts a sound. virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan); diff --git a/src/sound/oplsynth/opl_mus_player.cpp b/src/sound/oplsynth/opl_mus_player.cpp index 6b70be34f..6cb33348e 100644 --- a/src/sound/oplsynth/opl_mus_player.cpp +++ b/src/sound/oplsynth/opl_mus_player.cpp @@ -84,8 +84,8 @@ void OPLmusicBlock::Restart() LastOffset = 0; } -OPLmusicFile::OPLmusicFile (FileReader *reader) - : ScoreLen (reader->GetLength()) +OPLmusicFile::OPLmusicFile (FileReader &reader) + : ScoreLen ((int)reader.GetLength()) { if (io == NULL) { @@ -94,7 +94,7 @@ OPLmusicFile::OPLmusicFile (FileReader *reader) scoredata = new uint8_t[ScoreLen]; - if (reader->Read(scoredata, ScoreLen) != ScoreLen) + if (reader.Read(scoredata, ScoreLen) != ScoreLen) { fail: delete[] scoredata; scoredata = NULL; diff --git a/src/sound/oplsynth/opl_mus_player.h b/src/sound/oplsynth/opl_mus_player.h index 52ef4be76..17f5521e2 100644 --- a/src/sound/oplsynth/opl_mus_player.h +++ b/src/sound/oplsynth/opl_mus_player.h @@ -34,7 +34,7 @@ protected: class OPLmusicFile : public OPLmusicBlock { public: - OPLmusicFile(FileReader *reader); + OPLmusicFile(FileReader &reader); OPLmusicFile(const OPLmusicFile *source, const char *filename); virtual ~OPLmusicFile(); diff --git a/src/sound/sndfile_decoder.cpp b/src/sound/sndfile_decoder.cpp index 6fa5c5c07..f23ac2337 100644 --- a/src/sound/sndfile_decoder.cpp +++ b/src/sound/sndfile_decoder.cpp @@ -72,23 +72,23 @@ bool IsSndFilePresent() sf_count_t SndFileDecoder::file_get_filelen(void *user_data) { - FileReader *reader = reinterpret_cast(user_data)->Reader; - return reader->GetLength(); + auto &reader = reinterpret_cast(user_data)->Reader; + return reader.GetLength(); } sf_count_t SndFileDecoder::file_seek(sf_count_t offset, int whence, void *user_data) { - FileReader *reader = reinterpret_cast(user_data)->Reader; + auto &reader = reinterpret_cast(user_data)->Reader; - if(reader->Seek((long)offset, whence) != 0) + if(reader.Seek((long)offset, (FileReader::ESeek)whence) != 0) return -1; - return reader->Tell(); + return reader.Tell(); } sf_count_t SndFileDecoder::file_read(void *ptr, sf_count_t count, void *user_data) { - FileReader *reader = reinterpret_cast(user_data)->Reader; - return reader->Read(ptr, (long)count); + auto &reader = reinterpret_cast(user_data)->Reader; + return reader.Read(ptr, (long)count); } sf_count_t SndFileDecoder::file_write(const void *ptr, sf_count_t count, void *user_data) @@ -98,8 +98,8 @@ sf_count_t SndFileDecoder::file_write(const void *ptr, sf_count_t count, void *u sf_count_t SndFileDecoder::file_tell(void *user_data) { - FileReader *reader = reinterpret_cast(user_data)->Reader; - return reader->Tell(); + auto &reader = reinterpret_cast(user_data)->Reader; + return reader.Tell(); } @@ -110,13 +110,13 @@ SndFileDecoder::~SndFileDecoder() SndFile = 0; } -bool SndFileDecoder::open(FileReader *reader) +bool SndFileDecoder::open(FileReader &reader) { if (!IsSndFilePresent()) return false; SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; - Reader = reader; + Reader = std::move(reader); SndInfo.format = 0; SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this); if (SndFile) @@ -127,7 +127,8 @@ bool SndFileDecoder::open(FileReader *reader) sf_close(SndFile); SndFile = 0; } - return false; + reader = std::move(Reader); // need to give it back. + return false; } void SndFileDecoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) diff --git a/src/sound/sndfile_decoder.h b/src/sound/sndfile_decoder.h index 0d5c83a41..cbbcf8714 100644 --- a/src/sound/sndfile_decoder.h +++ b/src/sound/sndfile_decoder.h @@ -2,6 +2,7 @@ #define SNDFILE_DECODER_H #include "i_soundinternal.h" +#include "files.h" #ifdef HAVE_SNDFILE @@ -25,13 +26,13 @@ struct SndFileDecoder : public SoundDecoder virtual ~SndFileDecoder(); protected: - virtual bool open(FileReader *reader); + virtual bool open(FileReader &reader); private: SNDFILE *SndFile; SF_INFO SndInfo; - FileReader *Reader; + FileReader Reader; static sf_count_t file_get_filelen(void *user_data); static sf_count_t file_seek(sf_count_t offset, int whence, void *user_data); static sf_count_t file_read(void *ptr, sf_count_t count, void *user_data); diff --git a/src/sound/timidity/instrum.cpp b/src/sound/timidity/instrum.cpp index d92f7eb81..32ccd121f 100644 --- a/src/sound/timidity/instrum.cpp +++ b/src/sound/timidity/instrum.cpp @@ -153,7 +153,6 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss { Instrument *ip; Sample *sp; - FileReader *fp; GF1PatchHeader header; GF1InstrumentData idata; GF1LayerData layer_data; @@ -164,19 +163,19 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss if (!name || gus_sfreader == nullptr) return nullptr; /* Open patch file */ - fp = gus_sfreader->LookupFile(name).first; - if (fp == NULL) + auto fp = gus_sfreader->LookupFile(name).first; + if (!fp.isOpen()) { /* Try with various extensions */ FString tmp = name; tmp += ".pat"; fp = gus_sfreader->LookupFile(tmp).first; - if (fp == NULL) + if (!fp.isOpen()) { #ifdef __unix__ // Windows isn't case-sensitive. tmp.ToUpper(); fp = gus_sfreader->LookupFile(tmp).first; - if (fp == NULL) + if (!fp.isOpen()) #endif { noluck = true; @@ -194,26 +193,23 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss /* Read some headers and do cursory sanity checks. */ - if (sizeof(header) != fp->Read(&header, sizeof(header))) + if (sizeof(header) != fp.Read(&header, sizeof(header))) { failread: cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Error reading instrument.\n", name); - delete fp; return 0; } if (strncmp(header.Header, GF1_HEADER_TEXT, HEADER_SIZE - 4) != 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not an instrument.\n", name); - delete fp; return 0; } if (strcmp(header.Header + 8, "110") < 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Is an old and unsupported patch version.\n", name); - delete fp; return 0; } - if (sizeof(idata) != fp->Read(&idata, sizeof(idata))) + if (sizeof(idata) != fp.Read(&idata, sizeof(idata))) { goto failread; } @@ -226,18 +222,16 @@ failread: if (header.Instruments != 1 && header.Instruments != 0) /* instruments. To some patch makers, 0 means 1 */ { cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments.\n", header.Instruments); - delete fp; return 0; } if (idata.Layers != 1 && idata.Layers != 0) /* layers. What's a layer? */ { cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers.\n", idata.Layers); - delete fp; return 0; } - if (sizeof(layer_data) != fp->Read(&layer_data, sizeof(layer_data))) + if (sizeof(layer_data) != fp.Read(&layer_data, sizeof(layer_data))) { goto failread; } @@ -245,7 +239,6 @@ failread: if (layer_data.Samples == 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument has 0 samples.\n"); - delete fp; return 0; } @@ -255,12 +248,11 @@ failread: memset(ip->sample, 0, sizeof(Sample) * layer_data.Samples); for (i = 0; i < layer_data.Samples; ++i) { - if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data))) + if (sizeof(patch_data) != fp.Read(&patch_data, sizeof(patch_data))) { fail: cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d.\n", i); delete ip; - delete fp; return 0; } @@ -422,7 +414,7 @@ fail: } sp->data = (sample_t *)safe_malloc(sp->data_length); - if (sp->data_length != fp->Read(sp->data, sp->data_length)) + if (sp->data_length != fp.Read(sp->data, sp->data_length)) goto fail; convert_sample_data(sp, sp->data); @@ -469,7 +461,6 @@ fail: sp->data_length = sp->loop_end; } } - delete fp; return ip; } diff --git a/src/sound/timidity/instrum_font.cpp b/src/sound/timidity/instrum_font.cpp index 41709809c..22fd5d50d 100644 --- a/src/sound/timidity/instrum_font.cpp +++ b/src/sound/timidity/instrum_font.cpp @@ -17,7 +17,7 @@ namespace Timidity FontFile *Fonts; extern std::unique_ptr gus_sfreader; -FontFile *ReadDLS(const char *filename, FileReader *f) +FontFile *ReadDLS(const char *filename, FileReader &f) { return NULL; } @@ -57,15 +57,14 @@ void font_add(const char *filename, int load_order) } else { - FileReader *fp = gus_sfreader->LookupFile(filename).first; + FileReader fp = gus_sfreader->LookupFile(filename).first; - if (fp != NULL) + if (fp.isOpen()) { if ((font = ReadSF2(filename, fp)) || (font = ReadDLS(filename, fp))) { font->SetAllOrders(load_order); } - delete fp; } } } diff --git a/src/sound/timidity/instrum_sf2.cpp b/src/sound/timidity/instrum_sf2.cpp index dccbf53ac..dd7f8dd61 100644 --- a/src/sound/timidity/instrum_sf2.cpp +++ b/src/sound/timidity/instrum_sf2.cpp @@ -28,7 +28,7 @@ class CBadVer {}; struct ListHandler { uint32_t ID; - void (*Parser)(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); + void (*Parser)(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); }; enum @@ -162,15 +162,15 @@ static const SFGenComposite DefaultGenerators = -1 // overridingRootKey }; -static void ParseIfil(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseSmpl(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseSm24(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParsePhdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseBag(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseMod(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseGen(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseInst(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); -static void ParseShdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen); +static void ParseIfil(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseSmpl(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseSm24(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParsePhdr(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseBag(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseMod(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseGen(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseInst(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); +static void ParseShdr(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen); ListHandler INFOHandlers[] = { @@ -225,87 +225,87 @@ static int32_t calc_rate(Renderer *song, int diff, double sec) } -static inline uint32_t read_id(FileReader *f) +static inline uint32_t read_id(FileReader &f) { uint32_t id; - if (f->Read(&id, 4) != 4) + if (f.Read(&id, 4) != 4) { throw CIOErr(); } return id; } -static inline int read_byte(FileReader *f) +static inline int read_byte(FileReader &f) { uint8_t x; - if (f->Read(&x, 1) != 1) + if (f.Read(&x, 1) != 1) { throw CIOErr(); } return x; } -static inline int read_char(FileReader *f) +static inline int read_char(FileReader &f) { int8_t x; - if (f->Read(&x, 1) != 1) + if (f.Read(&x, 1) != 1) { throw CIOErr(); } return x; } -static inline int read_uword(FileReader *f) +static inline int read_uword(FileReader &f) { uint16_t x; - if (f->Read(&x, 2) != 2) + if (f.Read(&x, 2) != 2) { throw CIOErr(); } return LittleShort(x); } -static inline int read_sword(FileReader *f) +static inline int read_sword(FileReader &f) { int16_t x; - if (f->Read(&x, 2) != 2) + if (f.Read(&x, 2) != 2) { throw CIOErr(); } return LittleShort(x); } -static inline uint32_t read_dword(FileReader *f) +static inline uint32_t read_dword(FileReader &f) { uint32_t x; - if (f->Read(&x, 4) != 4) + if (f.Read(&x, 4) != 4) { throw CIOErr(); } return LittleLong(x); } -static inline void read_name(FileReader *f, char name[21]) +static inline void read_name(FileReader &f, char name[21]) { - if (f->Read(name, 20) != 20) + if (f.Read(name, 20) != 20) { throw CIOErr(); } name[20] = 0; } -static inline void skip_chunk(FileReader *f, uint32_t len) +static inline void skip_chunk(FileReader &f, uint32_t len) { // RIFF, like IFF, adds an extra pad byte to the end of // odd-sized chunks so that new chunks are always on even // byte boundaries. - if (f->Seek(len + (len & 1), SEEK_CUR) != 0) + if (f.Seek(len + (len & 1), FileReader::SeekCur) != 0) { throw CIOErr(); } } -static void check_list(FileReader *f, uint32_t id, uint32_t filelen, uint32_t &chunklen) +static void check_list(FileReader &f, uint32_t id, uint32_t filelen, uint32_t &chunklen) { if (read_id(f) != ID_LIST) { @@ -322,7 +322,7 @@ static void check_list(FileReader *f, uint32_t id, uint32_t filelen, uint32_t &c } } -static void ParseIfil(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseIfil(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { uint16_t major, minor; @@ -341,7 +341,7 @@ static void ParseIfil(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu sf2->MinorVersion = minor; } -static void ParseLIST(SFFile *sf2, FileReader *f, uint32_t chunklen, ListHandler *handlers) +static void ParseLIST(SFFile *sf2, FileReader &f, uint32_t chunklen, ListHandler *handlers) { ListHandler *handler; uint32_t id; @@ -375,7 +375,7 @@ static void ParseLIST(SFFile *sf2, FileReader *f, uint32_t chunklen, ListHandler } } -static void ParseINFO(SFFile *sf2, FileReader *f, uint32_t chunklen) +static void ParseINFO(SFFile *sf2, FileReader &f, uint32_t chunklen) { sf2->MinorVersion = -1; @@ -387,7 +387,7 @@ static void ParseINFO(SFFile *sf2, FileReader *f, uint32_t chunklen) } } -static void ParseSdta(SFFile *sf2, FileReader *f, uint32_t chunklen) +static void ParseSdta(SFFile *sf2, FileReader &f, uint32_t chunklen) { ParseLIST(sf2, f, chunklen, SdtaHandlers); if (sf2->SampleDataOffset == 0) @@ -404,7 +404,7 @@ static void ParseSdta(SFFile *sf2, FileReader *f, uint32_t chunklen) } } -static void ParseSmpl(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseSmpl(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { // Only use the first smpl chunk. (Or should we reject files with more than one?) if (sf2->SampleDataOffset == 0) @@ -413,13 +413,13 @@ static void ParseSmpl(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu { // Chunk must be an even number of bytes. throw CBadForm(); } - sf2->SampleDataOffset = f->Tell(); + sf2->SampleDataOffset = (uint32_t)f.Tell(); sf2->SizeSampleData = chunklen >> 1; } skip_chunk(f, chunklen); } -static void ParseSm24(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseSm24(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { // The sm24 chunk is ignored if the file version is < 2.04 if (sf2->MinorVersion >= 4) @@ -427,19 +427,19 @@ static void ParseSm24(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu // Only use the first sm24 chunk. (Or should we reject files with more than one?) if (sf2->SampleDataLSBOffset == 0) { - sf2->SampleDataLSBOffset = f->Tell(); + sf2->SampleDataLSBOffset = (uint32_t)f.Tell(); sf2->SizeSampleDataLSB = chunklen; } } skip_chunk(f, chunklen); } -static void ParsePdta(SFFile *sf2, FileReader *f, uint32_t chunklen) +static void ParsePdta(SFFile *sf2, FileReader &f, uint32_t chunklen) { ParseLIST(sf2, f, chunklen, PdtaHandlers); } -static void ParsePhdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParsePhdr(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { SFPreset *preset; @@ -477,7 +477,7 @@ static void ParsePhdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu } } -static void ParseBag(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseBag(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { SFBag *bags, *bag; uint16_t prev_mod = 0; @@ -539,7 +539,7 @@ static void ParseBag(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chun } } -static void ParseMod(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseMod(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { // Section 7.4, page 23: // It [the PMOD sub-chunk] is always a multiple of ten bytes in length, @@ -552,7 +552,7 @@ static void ParseMod(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chun skip_chunk(f, chunklen); } -static void ParseGen(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseGen(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { SFGenList *gens, *gen; int numgens; @@ -604,7 +604,7 @@ static void ParseGen(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chun } } -static void ParseInst(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseInst(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { int i; SFInst *inst; @@ -639,7 +639,7 @@ static void ParseInst(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu } } -static void ParseShdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chunklen) +static void ParseShdr(SFFile *sf2, FileReader &f, uint32_t chunkid, uint32_t chunklen) { int i; SFSample *sample; @@ -698,7 +698,7 @@ static void ParseShdr(SFFile *sf2, FileReader *f, uint32_t chunkid, uint32_t chu } -SFFile *ReadSF2(const char *filename, FileReader *f) +SFFile *ReadSF2(const char *filename, FileReader &f) { SFFile *sf2 = NULL; uint32_t filelen; @@ -1508,33 +1508,30 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend void SFFile::LoadSample(SFSample *sample) { - FileReader *fp = gus_sfreader->LookupFile(Filename).first; + FileReader fp = gus_sfreader->LookupFile(Filename).first; uint32_t i; - if (fp == NULL) + if (!fp.isOpen()) { return; } sample->InMemoryData = new float[sample->End - sample->Start + 1]; - fp->Seek(SampleDataOffset + sample->Start * 2, SEEK_SET); + fp.Seek(SampleDataOffset + sample->Start * 2, FileReader::SeekSet); // Load 16-bit sample data. for (i = 0; i < sample->End - sample->Start; ++i) { - int16_t samp; - *fp >> samp; + int16_t samp = fp.ReadInt16(); sample->InMemoryData[i] = samp / 32768.f; } if (SampleDataLSBOffset != 0) { // Load lower 8 bits of 24-bit sample data. - fp->Seek(SampleDataLSBOffset + sample->Start, SEEK_SET); + fp.Seek(SampleDataLSBOffset + sample->Start, FileReader::SeekSet); for (i = 0; i < sample->End - sample->Start; ++i) { - uint8_t samp; - *fp >> samp; + uint8_t samp = fp.ReadUInt8(); sample->InMemoryData[i] = ((((int32_t(sample->InMemoryData[i] * 32768) << 8) | samp) << 8) >> 8) / 8388608.f; } } // Final 0 byte is for interpolation. sample->InMemoryData[i] = 0; - delete fp; } diff --git a/src/sound/timidity/sf2.h b/src/sound/timidity/sf2.h index 26d413ab5..c68cd24ad 100644 --- a/src/sound/timidity/sf2.h +++ b/src/sound/timidity/sf2.h @@ -315,4 +315,4 @@ struct SFFile : public Timidity::FontFile int NumSamples; }; -SFFile *ReadSF2(const char *filename, FileReader *f); +SFFile *ReadSF2(const char *filename, FileReader &f); diff --git a/src/sound/timidity/timidity.cpp b/src/sound/timidity/timidity.cpp index 455ed1713..104407e2a 100644 --- a/src/sound/timidity/timidity.cpp +++ b/src/sound/timidity/timidity.cpp @@ -82,7 +82,7 @@ static bool InitReader(const char *config_file) static int read_config_file(const char *name, bool ismain) { - FileReader *fp; + FileReader fp; char tmp[1024], *cp; ToneBank *bank = NULL; int i, j, k, line = 0, words; @@ -103,12 +103,12 @@ static int read_config_file(const char *name, bool ismain) { fp = gus_sfreader->LookupFile(name).first; } - if (fp == nullptr) + if (!fp .isOpen()) { return -1; } - while (fp->Gets(tmp, sizeof(tmp))) + while (fp.Gets(tmp, sizeof(tmp))) { line++; FCommandLine w(tmp, true); @@ -207,7 +207,6 @@ static int read_config_file(const char *name, bool ismain) if (words < 2) { Printf("%s: line %d: No soundfont given\n", name, line); - delete fp; return -2; } if (words > 2 && !strcmp(w[2], "remove")) @@ -223,7 +222,6 @@ static int read_config_file(const char *name, bool ismain) if (!(cp = strchr(w[i], '='))) { Printf("%s: line %d: bad soundfont option %s\n", name, line, w[i]); - delete fp; return -2; } } @@ -241,7 +239,6 @@ static int read_config_file(const char *name, bool ismain) if (words < 3) { Printf("%s: line %d: syntax error\n", name, line); - delete fp; return -2; } @@ -258,7 +255,6 @@ static int read_config_file(const char *name, bool ismain) else { Printf("%s: line %d: font subcommand must be 'order' or 'exclude'\n", name, line); - delete fp; return -2; } if (i < words) @@ -312,7 +308,6 @@ static int read_config_file(const char *name, bool ismain) if (words < 2) { Printf("%s: line %d: No directory given\n", name, line); - delete fp; return -2; } for (i = 1; i < words; i++) @@ -340,7 +335,6 @@ static int read_config_file(const char *name, bool ismain) if (words != 2) { Printf("%s: line %d: Must specify exactly one patch name\n", name, line); - delete fp; return -2; } def_instr_name = w[1]; @@ -350,14 +344,12 @@ static int read_config_file(const char *name, bool ismain) if (words < 2) { Printf("%s: line %d: No drum set number given\n", name, line); - delete fp; return -2; } i = atoi(w[1]); if (i < 0 || i > 127) { Printf("%s: line %d: Drum set must be between 0 and 127\n", name, line); - delete fp; return -2; } if (drumset[i] == NULL) @@ -371,14 +363,12 @@ static int read_config_file(const char *name, bool ismain) if (words < 2) { Printf("%s: line %d: No bank number given\n", name, line); - delete fp; return -2; } i = atoi(w[1]); if (i < 0 || i > 127) { Printf("%s: line %d: Tone bank must be between 0 and 127\n", name, line); - delete fp; return -2; } if (tonebank[i] == NULL) @@ -392,20 +382,17 @@ static int read_config_file(const char *name, bool ismain) if ((words < 2) || (*w[0] < '0' || *w[0] > '9')) { Printf("%s: line %d: syntax error\n", name, line); - delete fp; return -2; } i = atoi(w[0]); if (i < 0 || i > 127) { Printf("%s: line %d: Program must be between 0 and 127\n", name, line); - delete fp; return -2; } if (bank == NULL) { Printf("%s: line %d: Must specify tone bank or drum set before assignment\n", name, line); - delete fp; return -2; } bank->tone[i].note = bank->tone[i].pan = @@ -440,7 +427,6 @@ static int read_config_file(const char *name, bool ismain) if (!(cp=strchr(w[j], '='))) { Printf("%s: line %d: bad patch option %s\n", name, line, w[j]); - delete fp; return -2; } *cp++ = 0; @@ -454,7 +440,6 @@ static int read_config_file(const char *name, bool ismain) if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9')) { Printf("%s: line %d: note must be between 0 and 127\n", name, line); - delete fp; return -2; } bank->tone[i].note = k; @@ -474,7 +459,6 @@ static int read_config_file(const char *name, bool ismain) { Printf("%s: line %d: panning must be left, right, " "center, or between -100 and 100\n", name, line); - delete fp; return -2; } bank->tone[i].pan = k; @@ -488,7 +472,6 @@ static int read_config_file(const char *name, bool ismain) else { Printf("%s: line %d: keep must be env or loop\n", name, line); - delete fp; return -2; } } @@ -503,28 +486,17 @@ static int read_config_file(const char *name, bool ismain) else { Printf("%s: line %d: strip must be env, loop, or tail\n", name, line); - delete fp; return -2; } } else { Printf("%s: line %d: bad patch option %s\n", name, line, w[j]); - delete fp; return -2; } } } } - /* - if (ferror(fp)) - { - Printf("Can't read %s: %s\n", name, strerror(errno)); - close_file(fp); - return -2; - } - */ - delete fp; return 0; } @@ -590,7 +562,7 @@ int LoadDMXGUS() if (lump == -1) lump = Wads.CheckNumForName("DMXGUSC"); if (lump == -1) return LoadConfig(midi_config); - FWadLump data = Wads.OpenLumpNum(lump); + auto data = Wads.OpenLumpReader(lump); if (data.GetLength() == 0) return LoadConfig(midi_config); // Check if we got some GUS data before using it. @@ -613,7 +585,7 @@ int LoadDMXGUS() gus_sfreader.reset(psreader); char readbuffer[1024]; - long size = data.GetLength(); + auto size = data.GetLength(); long read = 0; uint8_t remap[256]; @@ -624,7 +596,7 @@ int LoadDMXGUS() int status = -1; int gusbank = (gus_memsize >= 1 && gus_memsize <= 4) ? gus_memsize : -1; - data.Seek(0, SEEK_SET); + data.Seek(0, FileReader::SeekSet); while (data.Gets(readbuffer, 1024) && read < size) { diff --git a/src/sound/timidity/timidity.h b/src/sound/timidity/timidity.h index 2f923b697..f297f35bb 100644 --- a/src/sound/timidity/timidity.h +++ b/src/sound/timidity/timidity.h @@ -21,8 +21,7 @@ #define TIMIDITY_H #include "doomtype.h" - -class FileReader; +#include "files.h" namespace Timidity { @@ -362,7 +361,7 @@ void font_order(int order, int bank, int preset, int keynote); Instrument *load_instrument_font(struct Renderer *song, const char *font, int drum, int bank, int instrument); Instrument *load_instrument_font_order(struct Renderer *song, int order, int drum, int bank, int instrument); -FontFile *ReadDLS(const char *filename, FileReader *f); +FontFile *ReadDLS(const char *filename, FileReader &f); /* mix.h diff --git a/src/sound/timiditypp/common.cpp b/src/sound/timiditypp/common.cpp index b323a85d7..77df91798 100644 --- a/src/sound/timiditypp/common.cpp +++ b/src/sound/timiditypp/common.cpp @@ -130,7 +130,7 @@ double flt_rand() struct timidity_file *open_file(const char *name, FSoundFontReader *sfreader) { - FileReader *fr; + FileReader fr; FString filename; if (name == nullptr) { @@ -140,60 +140,56 @@ struct timidity_file *open_file(const char *name, FSoundFontReader *sfreader) else { auto res = sfreader->LookupFile(name); - fr = res.first; + fr = std::move(res.first); filename = res.second; } - if (fr == nullptr) return nullptr; + if (!fr.isOpen()) return nullptr; auto tf = new timidity_file; - tf->url = fr; + tf->url = std::move(fr); tf->filename = filename.GetChars(); return tf; } /* This closes files opened with open_file */ -void close_file(struct timidity_file *tf) +void tf_close(struct timidity_file *tf) { - if (tf->url != NULL) - { - tf->url->Close(); - delete tf->url; - } + tf->url.Close(); delete tf; } /* This is meant for skipping a few bytes. */ void skip(struct timidity_file *tf, size_t len) { - tf->url->Seek((long)len, SEEK_CUR); + tf->url.Seek((long)len, FileReader::SeekCur); } char *tf_gets(char *buff, int n, struct timidity_file *tf) { - return tf->url->Gets(buff, n); + return tf->url.Gets(buff, n); } int tf_getc(struct timidity_file *tf) { unsigned char c; - auto read = tf->url->Read(&c, 1); + auto read = tf->url.Read(&c, 1); return read == 0 ? EOF : c; } long tf_read(void *buff, int32_t size, int32_t nitems, struct timidity_file *tf) { - return tf->url->Read(buff, size * nitems) / size; + return (long)tf->url.Read(buff, size * nitems) / size; } long tf_seek(struct timidity_file *tf, long offset, int whence) { - return tf->url->Seek(offset, whence); + return (long)tf->url.Seek(offset, (FileReader::ESeek)whence); } long tf_tell(struct timidity_file *tf) { - return tf->url->Tell(); + return (long)tf->url.Tell(); } } diff --git a/src/sound/timiditypp/common.h b/src/sound/timiditypp/common.h index d288a1f0f..74c7070df 100644 --- a/src/sound/timiditypp/common.h +++ b/src/sound/timiditypp/common.h @@ -35,12 +35,12 @@ namespace TimidityPlus struct timidity_file { - FileReader *url; + FileReader url; std::string filename; }; extern struct timidity_file *open_file(const char *name, FSoundFontReader *); -extern void close_file(struct timidity_file *tf); +extern void tf_close(struct timidity_file *tf); extern void skip(struct timidity_file *tf, size_t len); extern char *tf_gets(char *buff, int n, struct timidity_file *tf); int tf_getc(struct timidity_file *tf); diff --git a/src/sound/timiditypp/configfile.cpp b/src/sound/timiditypp/configfile.cpp index 80b4f54f5..1344a9cd6 100644 --- a/src/sound/timiditypp/configfile.cpp +++ b/src/sound/timiditypp/configfile.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include +#include #include @@ -43,7 +44,7 @@ namespace TimidityPlus ctl_cmsg(CMSG_ERROR, VERB_NORMAL, \ "Too many errors... Give up read %s", name); \ reuse_mblock(&varbuf); \ - close_file(tf); return 1; } + tf_close(tf); return 1; } typedef struct { @@ -1427,7 +1428,7 @@ int Instruments::read_config_file(const char *name, int self, int allow_missing_ continue; case READ_CONFIG_RECURSION: reuse_mblock(&varbuf); - close_file(tf); + tf_close(tf); return READ_CONFIG_RECURSION; case READ_CONFIG_FILE_NOT_FOUND: break; @@ -1610,7 +1611,7 @@ int Instruments::read_config_file(const char *name, int self, int allow_missing_ } } reuse_mblock(&varbuf); - close_file(tf); + tf_close(tf); return (errcnt == 0) ? READ_CONFIG_SUCCESS : READ_CONFIG_ERROR; } diff --git a/src/sound/timiditypp/instrum.cpp b/src/sound/timiditypp/instrum.cpp index 988da8730..ddd0d8fab 100644 --- a/src/sound/timiditypp/instrum.cpp +++ b/src/sound/timiditypp/instrum.cpp @@ -75,6 +75,8 @@ Instruments::~Instruments() free_tone_bank(); free_instrument_map(); + + if (sfreader != nullptr) delete sfreader; } void Instruments::free_instrument(Instrument *ip) @@ -667,20 +669,20 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr, && memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) { /* don't know what the differences are */ ctl_cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name); - close_file(tf); + tf_close(tf); return 0; } /* instruments. To some patch makers, 0 means 1 */ if (tmp[82] != 1 && tmp[82] != 0) { ctl_cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments", tmp[82]); - close_file(tf); + tf_close(tf); return 0; } if (tmp[151] != 1 && tmp[151] != 0) { /* layers. What's a layer? */ ctl_cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers", tmp[151]); - close_file(tf); + tf_close(tf); return 0; } ip = (Instrument *)safe_malloc(sizeof(Instrument)); @@ -697,7 +699,7 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr, free(ip->sample[j].data); free(ip->sample); free(ip); - close_file(tf); + tf_close(tf); return 0; } sp = &(ip->sample[i]); @@ -964,7 +966,7 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr, ctl_cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail"); } } - close_file(tf); + tf_close(tf); store_instrument_cache(ip, name, panning, amp, note_to_use, strip_loop, strip_envelope, strip_tail); return ip; diff --git a/src/sound/timiditypp/reverb.cpp b/src/sound/timiditypp/reverb.cpp index c0446c8c6..c83e1f568 100644 --- a/src/sound/timiditypp/reverb.cpp +++ b/src/sound/timiditypp/reverb.cpp @@ -29,6 +29,7 @@ */ #include +#include #include "timidity.h" #include "tables.h" #include "common.h" diff --git a/src/sound/timiditypp/sfitem.cpp b/src/sound/timiditypp/sfitem.cpp index 1e2173c1d..fc7d55e69 100644 --- a/src/sound/timiditypp/sfitem.cpp +++ b/src/sound/timiditypp/sfitem.cpp @@ -24,6 +24,7 @@ *================================================================*/ #include +#include #include "timidity.h" #include "common.h" #include "sflayer.h" @@ -95,4 +96,4 @@ const LayerItem static_layer_items[SF_EOF] = { {L_OVWRT, T_NOCONV, 0, 127, -1}, /* rootKey */ }; -} \ No newline at end of file +} diff --git a/src/sound/timiditypp/smplfile.cpp b/src/sound/timiditypp/smplfile.cpp index e34703004..b482796db 100644 --- a/src/sound/timiditypp/smplfile.cpp +++ b/src/sound/timiditypp/smplfile.cpp @@ -283,10 +283,10 @@ int Instruments::import_wave_discriminant(char *sample_file) if (tf_read(buf, 12, 1, tf) != 1 || memcmp(&buf[0], "RIFF", 4) != 0 || memcmp(&buf[8], "WAVE", 4) != 0) { - close_file(tf); + tf_close(tf); return 1; } - close_file(tf); + tf_close(tf); return 0; } @@ -314,7 +314,7 @@ int Instruments::import_wave_load(char *sample_file, Instrument *inst) if (tf_read(buf, 12, 1, tf) != 1 || memcmp(&buf[0], "RIFF", 4) != 0 || memcmp(&buf[8], "WAVE", 4) != 0) { - close_file(tf); + tf_close(tf); return 1; } //ctl_cmsg(CMSG_INFO,VERB_NOISY,"Loading WAV: %s", sample_file); @@ -378,7 +378,7 @@ int Instruments::import_wave_load(char *sample_file, Instrument *inst) type_index = 4 - (chunk_size & 1); type_size = 8 + (chunk_size & 1); } - close_file(tf); + tf_close(tf); if (chunk_flags & WAVE_CHUNKFLAG_SAMPLER) { uint8_t modes; @@ -557,10 +557,10 @@ int Instruments::import_aiff_discriminant(char *sample_file) || memcmp(&buf[0], "FORM", 4) != 0 || memcmp(&buf[8], "AIF", 3) != 0 || (buf[8 + 3] != 'F' && buf[8 + 3] != 'C')) { - close_file(tf); + tf_close(tf); return 1; } - close_file(tf); + tf_close(tf); return 0; } @@ -597,7 +597,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst) || memcmp(&buf[0], "FORM", 4) != 0 || memcmp(&buf[8], "AIF", 3) != 0 || (buf[8 + 3] != 'F' && buf[8 + 3] != 'C')) { - close_file(tf); + tf_close(tf); return 1; } compressed = buf[8 + 3] == 'C'; @@ -684,7 +684,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst) { if (marker_data != NULL) free(marker_data); - close_file(tf); + tf_close(tf); return -1; } if (!(chunk_flags & AIFF_CHUNKFLAG_SOUNDREAD)) @@ -693,7 +693,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst) { if (marker_data != NULL) free(marker_data); - close_file(tf); + tf_close(tf); return 1; } } @@ -729,7 +729,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst) } if (marker_data != NULL) free(marker_data); - close_file(tf); + tf_close(tf); return 0; } diff --git a/src/sound/timiditypp/sndfont.cpp b/src/sound/timiditypp/sndfont.cpp index 9e0e51d18..b7bf00511 100644 --- a/src/sound/timiditypp/sndfont.cpp +++ b/src/sound/timiditypp/sndfont.cpp @@ -223,10 +223,8 @@ void Instruments::free_soundfonts() SFInsts *sf, *next; for (sf = sfrecs; sf != NULL; sf = next) { - if ((sf->tf != NULL) && (sf->tf->url != NULL)) - free(sf->tf->url); - if (sf->tf != NULL) - free(sf->tf); + if (sf->tf != nullptr) tf_close(sf->tf); + sf->tf = nullptr; reuse_mblock(&sf->pool); next = sf->next; free(sf); @@ -308,7 +306,7 @@ void Instruments::init_sf(SFInsts *rec) free_soundfont(&sfinfo); if (opt_sf_close_each_file) { - close_file(rec->tf); + tf_close(rec->tf); rec->tf = NULL; } } @@ -324,7 +322,7 @@ void Instruments::init_load_soundfont(void) void Instruments::end_soundfont(SFInsts *rec) { if (rec->tf) { - close_file(rec->tf); + tf_close(rec->tf); rec->tf = NULL; } @@ -383,7 +381,7 @@ Instrument *Instruments::try_load_soundfont(SFInsts *rec, int order, int bank,in inst = load_from_file(rec, ip); if (opt_sf_close_each_file) { - close_file(rec->tf); + tf_close(rec->tf); rec->tf = NULL; } diff --git a/src/sound/timiditypp/timidity.h b/src/sound/timiditypp/timidity.h index cc6b8a22f..5fe3667f6 100644 --- a/src/sound/timiditypp/timidity.h +++ b/src/sound/timiditypp/timidity.h @@ -28,9 +28,9 @@ #ifndef TIMIDITY_H_INCLUDED #define TIMIDITY_H_INCLUDED 1 -#include "c_cvars.h" #include "controls.h" #include "mblock.h" +#include #ifdef _MSC_VER #pragma warning(disable:4244) // double->float truncation occurs so often in here that it's pointless to fix it all. diff --git a/src/sound/wildmidi/file_io.cpp b/src/sound/wildmidi/file_io.cpp index fa7910a2c..b1d3d2dd5 100644 --- a/src/sound/wildmidi/file_io.cpp +++ b/src/sound/wildmidi/file_io.cpp @@ -60,7 +60,7 @@ bool _WM_InitReader(const char *config_file) unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) { - FileReader *fp; + FileReader fp; if (filename == nullptr) { @@ -72,13 +72,13 @@ unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) fp = wm_sfreader->OpenFile(filename); } - if (fp == NULL) + if (!fp.isOpen()) { _WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno); return NULL; } - long fsize = fp->GetLength(); + auto fsize = fp.GetLength(); if (fsize > WM_MAXFILESIZE) { @@ -95,9 +95,8 @@ unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size) return NULL; } - fp->Read(data, fsize); - delete fp; + fp.Read(data, fsize); data[fsize] = 0; - *size = fsize; + *size = (long)fsize; return data; } diff --git a/src/sound/wildmidi/wildmidi_lib.cpp b/src/sound/wildmidi/wildmidi_lib.cpp index 87afc16de..f4b4a254c 100644 --- a/src/sound/wildmidi/wildmidi_lib.cpp +++ b/src/sound/wildmidi/wildmidi_lib.cpp @@ -676,7 +676,7 @@ static int WM_LoadConfig(const char *config_file, bool main) { int token_count = 0; auto config_parm = config_file; - FileReader *fr = nullptr; + FileReader fr; if (main) { if (!_WM_InitReader(config_file)) return -1; // unable to open this as a config file. diff --git a/src/swrenderer/line/r_farclip_line.cpp b/src/swrenderer/line/r_farclip_line.cpp index f000744c2..5b55e654f 100644 --- a/src/swrenderer/line/r_farclip_line.cpp +++ b/src/swrenderer/line/r_farclip_line.cpp @@ -65,13 +65,14 @@ namespace swrenderer Thread = thread; } - void FarClipLine::Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane) + void FarClipLine::Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, Fake3DOpaque opaque3dfloor) { mSubsector = subsector; mFrontSector = mSubsector->sector; mLineSegment = line; mFloorPlane = linefloorplane; mCeilingPlane = lineceilingplane; + m3DFloor = opaque3dfloor; DVector2 pt1 = line->v1->fPos() - Thread->Viewport->viewpoint.Pos; DVector2 pt2 = line->v2->fPos() - Thread->Viewport->viewpoint.Pos; @@ -153,7 +154,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { - short top = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKECEILING) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; + short top = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeCeiling) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; short bottom = MIN(walltop.ScreenY[x], floorclip[x]); if (top < bottom) { @@ -177,7 +178,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]); - short bottom = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKEFLOOR) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; + short bottom = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeFloor) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; if (top < bottom) { assert(bottom <= viewheight); diff --git a/src/swrenderer/line/r_farclip_line.h b/src/swrenderer/line/r_farclip_line.h index c450a6383..05cba472d 100644 --- a/src/swrenderer/line/r_farclip_line.h +++ b/src/swrenderer/line/r_farclip_line.h @@ -28,7 +28,7 @@ namespace swrenderer { public: FarClipLine(RenderThread *thread); - void Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane); + void Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, Fake3DOpaque opaque3dfloor); RenderThread *Thread = nullptr; @@ -44,6 +44,7 @@ namespace swrenderer seg_t *mLineSegment; VisiblePlane *mFloorPlane; VisiblePlane *mCeilingPlane; + Fake3DOpaque m3DFloor; double mFrontCeilingZ1; double mFrontCeilingZ2; diff --git a/src/swrenderer/line/r_fogboundary.cpp b/src/swrenderer/line/r_fogboundary.cpp index bd6ba50aa..1b8f1c99d 100644 --- a/src/swrenderer/line/r_fogboundary.cpp +++ b/src/swrenderer/line/r_fogboundary.cpp @@ -54,7 +54,7 @@ namespace swrenderer { - void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, short *uclip, short *dclip, int wallshade, float lightleft, float lightstep, FDynamicColormap *basecolormap) + void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, int wallshade, float lightleft, float lightstep, FDynamicColormap *basecolormap) { // This is essentially the same as R_MapVisPlane but with an extra step // to create new horizontal spans whenever the light changes enough that diff --git a/src/swrenderer/line/r_fogboundary.h b/src/swrenderer/line/r_fogboundary.h index 39005c039..b506ec7f8 100644 --- a/src/swrenderer/line/r_fogboundary.h +++ b/src/swrenderer/line/r_fogboundary.h @@ -31,7 +31,7 @@ namespace swrenderer class RenderFogBoundary { public: - void Render(RenderThread *thread, int x1, int x2, short *uclip, short *dclip, int wallshade, float lightleft, float lightstep, FDynamicColormap *basecolormap); + void Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, int wallshade, float lightleft, float lightstep, FDynamicColormap *basecolormap); private: void RenderSection(RenderThread *thread, int y, int y2, int x1); diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 3f663defd..b2c1fee72 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -71,7 +71,7 @@ namespace swrenderer Thread = thread; } - void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, bool infog, FDynamicColormap *colormap) + void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, bool infog, FDynamicColormap *colormap, Fake3DOpaque opaque3dfloor) { mSubsector = subsector; mFrontSector = sector; @@ -81,6 +81,7 @@ namespace swrenderer foggy = infog; basecolormap = colormap; mLineSegment = line; + m3DFloor = opaque3dfloor; DVector2 pt1 = line->v1->fPos() - Thread->Viewport->viewpoint.Pos; DVector2 pt2 = line->v2->fPos() - Thread->Viewport->viewpoint.Pos; @@ -133,7 +134,7 @@ namespace swrenderer Clip3DFloors *clip3d = Thread->Clip3D.get(); - if (!(clip3d->fake3D & FAKE3D_FAKEBACK)) + if (m3DFloor.type != Fake3DOpaque::FakeBack) { mBackSector = line->backsector; } @@ -141,7 +142,7 @@ namespace swrenderer if (mBackSector) { // kg3D - its fake, no transfer_heights - if (!(clip3d->fake3D & FAKE3D_FAKEBACK)) + if (m3DFloor.type != Fake3DOpaque::FakeBack) { // killough 3/8/98, 4/4/98: hack for invisible ceilings / deep water mBackSector = Thread->OpaquePass->FakeFlat(mBackSector, &tempsec, nullptr, nullptr, mLineSegment, WallC.sx1, WallC.sx2, mFrontCeilingZ1, mFrontCeilingZ2); } @@ -151,15 +152,15 @@ namespace swrenderer mBackCeilingZ2 = mBackSector->ceilingplane.ZatPoint(line->v2); mBackFloorZ2 = mBackSector->floorplane.ZatPoint(line->v2); - if (clip3d->fake3D & FAKE3D_FAKEBACK) + if (m3DFloor.type == Fake3DOpaque::FakeBack) { if (mFrontFloorZ1 >= mBackFloorZ1 && mFrontFloorZ2 >= mBackFloorZ2) { - clip3d->fake3D |= FAKE3D_CLIPBOTFRONT; + m3DFloor.clipBotFront = true; } if (mFrontCeilingZ1 <= mBackCeilingZ1 && mFrontCeilingZ2 <= mBackCeilingZ2) { - clip3d->fake3D |= FAKE3D_CLIPTOPFRONT; + m3DFloor.clipTopFront = true; } } } @@ -325,7 +326,7 @@ namespace swrenderer // 3D floors code abuses the line render code to update plane clipping // lists but doesn't actually draw anything. - bool onlyUpdatePlaneClip = (clip3d->fake3D & FAKE3D_FAKEMASK) ? true : false; + bool onlyUpdatePlaneClip = (m3DFloor.type != Fake3DOpaque::Normal); if (!onlyUpdatePlaneClip) Thread->DrawSegments->Push(draw_segment); @@ -516,9 +517,9 @@ namespace swrenderer MarkFloorPlane(start, stop); Mark3DFloors(start, stop); - if (clip3d->fake3D & FAKE3D_FAKEMASK) + if (m3DFloor.type != Fake3DOpaque::Normal) { - return (clip3d->fake3D & FAKE3D_FAKEMASK) == 0; + return false; } MarkOpaquePassClip(start, stop); @@ -557,7 +558,7 @@ namespace swrenderer Thread->Portal->AddLinePortal(mLineSegment->linedef, draw_segment->x1, draw_segment->x2, draw_segment->sprtopclip, draw_segment->sprbottomclip); } - return (clip3d->fake3D & FAKE3D_FAKEMASK) == 0; + return m3DFloor.type == Fake3DOpaque::Normal; } bool SWRenderLine::ShouldMarkFloor() const @@ -1015,7 +1016,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { - short top = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKECEILING) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; + short top = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeCeiling) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; short bottom = MIN(walltop.ScreenY[x], floorclip[x]); if (top < bottom) { @@ -1039,7 +1040,7 @@ namespace swrenderer for (int x = x1; x < x2; ++x) { short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]); - short bottom = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKEFLOOR) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; + short bottom = (clip3d->fakeFloor && m3DFloor.type == Fake3DOpaque::FakeFloor) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; if (top < bottom) { assert(bottom <= viewheight); @@ -1055,12 +1056,12 @@ namespace swrenderer Clip3DFloors *clip3d = Thread->Clip3D.get(); // kg3D - fake planes clipping - if (clip3d->fake3D & FAKE3D_REFRESHCLIP) + if (m3DFloor.type == Fake3DOpaque::FakeBack) { auto ceilingclip = Thread->OpaquePass->ceilingclip; auto floorclip = Thread->OpaquePass->floorclip; - if (clip3d->fake3D & FAKE3D_CLIPBOTFRONT) + if (m3DFloor.clipBotFront) { memcpy(clip3d->fakeFloor->floorclip + x1, wallbottom.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -1072,7 +1073,7 @@ namespace swrenderer } memcpy(clip3d->fakeFloor->floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); } - if (clip3d->fake3D & FAKE3D_CLIPTOPFRONT) + if (m3DFloor.clipTopFront) { memcpy(clip3d->fakeFloor->ceilingclip + x1, walltop.ScreenY + x1, (x2 - x1) * sizeof(short)); } diff --git a/src/swrenderer/line/r_line.h b/src/swrenderer/line/r_line.h index 1462410e5..a76f4dc7c 100644 --- a/src/swrenderer/line/r_line.h +++ b/src/swrenderer/line/r_line.h @@ -25,6 +25,7 @@ #include "vectors.h" #include "r_wallsetup.h" #include "swrenderer/segments/r_clipsegment.h" +#include "swrenderer/scene/r_3dfloors.h" struct seg_t; struct subsector_t; @@ -71,7 +72,7 @@ namespace swrenderer { public: SWRenderLine(RenderThread *thread); - void Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap); + void Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque fake3DOpaque); RenderThread *Thread = nullptr; @@ -109,6 +110,7 @@ namespace swrenderer VisiblePlane *mFloorPlane; VisiblePlane *mCeilingPlane; seg_t *mLineSegment; + Fake3DOpaque m3DFloor; double mBackCeilingZ1; double mBackCeilingZ2; diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index 89c73455c..f46fbc133 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -63,11 +63,12 @@ namespace swrenderer Thread = thread; } - void RenderDrawSegment::Render(DrawSegment *ds, int x1, int x2) + void RenderDrawSegment::Render(DrawSegment *ds, int x1, int x2, Fake3DTranslucent clip3DFloor) { auto viewport = Thread->Viewport.get(); curline = ds->curline; + m3DFloor = clip3DFloor; float alpha = (float)MIN(curline->linedef->alpha, 1.); bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; @@ -102,17 +103,13 @@ namespace swrenderer Clip3DFloors *clip3d = Thread->Clip3D.get(); - if (!(clip3d->fake3D & FAKE3D_CLIPTOP)) - { - clip3d->sclipTop = sec->ceilingplane.ZatPoint(Thread->Viewport->viewpoint.Pos); - } - CameraLight *cameraLight = CameraLight::Instance(); if (cameraLight->FixedLightLevel() < 0) { + double clipTop = m3DFloor.clipTop ? m3DFloor.sclipTop : sec->ceilingplane.ZatPoint(Thread->Viewport->viewpoint.Pos); for (int i = frontsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) { - if (clip3d->sclipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0()) + if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0()) { lightlist_t *lit = &frontsector->e->XFloor.lightlist[i]; basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); @@ -123,15 +120,13 @@ namespace swrenderer } } - bool wrap = (curline->linedef->flags & ML_WRAP_MIDTEX) || (curline->sidedef->Flags & WALLF_WRAP_MIDTEX); - // [RH] Draw fog partition bool renderwall = true; bool notrelevant = false; if (ds->bFogBoundary) { - short *mfloorclip = ds->sprbottomclip - ds->x1; - short *mceilingclip = ds->sprtopclip - ds->x1; + const short *mfloorclip = ds->sprbottomclip - ds->x1; + const short *mceilingclip = ds->sprtopclip - ds->x1; RenderFogBoundary renderfog; renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, wallshade, rw_light, rw_lightstep, basecolormap); @@ -145,7 +140,7 @@ namespace swrenderer } if (renderwall) - notrelevant = RenderWall(ds, x1, x2, walldrawerargs, columndrawerargs, visible, basecolormap, wallshade, wrap); + notrelevant = RenderWall(ds, x1, x2, walldrawerargs, columndrawerargs, visible, basecolormap, wallshade); if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls()) { @@ -153,23 +148,14 @@ namespace swrenderer } if (!notrelevant) { - if (clip3d->fake3D & FAKE3D_REFRESHCLIP) - { - if (!wrap) - { - assert(ds->bkup != nullptr); - memcpy(ds->sprtopclip, ds->bkup, (ds->x2 - ds->x1) * 2); - } - } - else - { - fillshort(ds->sprtopclip - ds->x1 + x1, x2 - x1, viewheight); - } + ds->sprclipped = true; + fillshort(ds->sprtopclip - ds->x1 + x1, x2 - x1, viewheight); } } - bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int wallshade, bool wrap) + bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int wallshade) { + auto renderstyle = DefaultRenderStyle(); auto viewport = Thread->Viewport.get(); Clip3DFloors *clip3d = Thread->Clip3D.get(); @@ -179,8 +165,8 @@ namespace swrenderer tex = tex->GetRawTexture(); } - short *mfloorclip = ds->sprbottomclip - ds->x1; - short *mceilingclip = ds->sprtopclip - ds->x1; + const short *mfloorclip = ds->sprbottomclip - ds->x1; + const short *mceilingclip = ds->sprtopclip - ds->x1; float *MaskedSWall = ds->swall - ds->x1; float MaskedScaleY = ds->yscale; @@ -220,6 +206,7 @@ namespace swrenderer double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); + bool wrap = (curline->linedef->flags & ML_WRAP_MIDTEX) || (curline->sidedef->Flags & WALLF_WRAP_MIDTEX); if (!wrap) { // Texture does not wrap vertically. double textop; @@ -263,11 +250,11 @@ namespace swrenderer return false; } - if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && textop < clip3d->sclipBottom - Thread->Viewport->viewpoint.Pos.Z) + if (m3DFloor.clipBottom && textop < m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z) { return true; } - if ((clip3d->fake3D & FAKE3D_CLIPTOP) && textop - texheight > clip3d->sclipTop - Thread->Viewport->viewpoint.Pos.Z) + if (m3DFloor.clipTop && textop - texheight > m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z) { return true; } @@ -277,21 +264,26 @@ namespace swrenderer WallC.sx1 = ds->sx1; WallC.sx2 = ds->sx2; - if (clip3d->fake3D & FAKE3D_CLIPTOP) + double top, bot; + GetMaskedWallTopBottom(ds, top, bot); + top -= Thread->Viewport->viewpoint.Pos.Z; + bot -= Thread->Viewport->viewpoint.Pos.Z; + + if (m3DFloor.clipTop) { - wallupper.Project(Thread->Viewport.get(), textop < clip3d->sclipTop - Thread->Viewport->viewpoint.Pos.Z ? textop : clip3d->sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); + wallupper.Project(Thread->Viewport.get(), textop < m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z ? textop : m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); } else { - wallupper.Project(Thread->Viewport.get(), textop, &WallC); + wallupper.Project(Thread->Viewport.get(), MIN(textop, top), &WallC); } - if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) + if (m3DFloor.clipBottom) { - walllower.Project(Thread->Viewport.get(), textop - texheight > clip3d->sclipBottom - Thread->Viewport->viewpoint.Pos.Z ? textop - texheight : clip3d->sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); + walllower.Project(Thread->Viewport.get(), textop - texheight > m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z ? textop - texheight : m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); } else { - walllower.Project(Thread->Viewport.get(), textop - texheight, &WallC); + walllower.Project(Thread->Viewport.get(), MAX(textop - texheight, bot), &WallC); } for (int i = x1; i < x2; i++) @@ -323,7 +315,7 @@ namespace swrenderer // draw the columns one at a time if (visible) { - Thread->PrepareTexture(tex); + Thread->PrepareTexture(tex, renderstyle); for (int x = x1; x < x2; ++x) { if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0) @@ -338,7 +330,7 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle); rw_light += rw_lightstep; spryscale += rw_scalestep; @@ -377,9 +369,9 @@ namespace swrenderer } } - if (clip3d->fake3D & FAKE3D_CLIPTOP) + if (m3DFloor.clipTop) { - wallupper.Project(Thread->Viewport.get(), clip3d->sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); + wallupper.Project(Thread->Viewport.get(), m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); for (int i = x1; i < x2; i++) { if (wallupper.ScreenY[i] < mceilingclip[i]) @@ -387,9 +379,9 @@ namespace swrenderer } mceilingclip = wallupper.ScreenY; } - if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) + if (m3DFloor.clipBottom) { - walllower.Project(Thread->Viewport.get(), clip3d->sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); + walllower.Project(Thread->Viewport.get(), m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); for (int i = x1; i < x2; i++) { if (walllower.ScreenY[i] > mfloorclip[i]) @@ -412,7 +404,7 @@ namespace swrenderer } // kg3D - render one fake wall - void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap) + void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap, double clipTop, double clipBottom) { int i; double xscale; @@ -428,8 +420,8 @@ namespace swrenderer rw_lightstep = ds->lightstep; rw_light = ds->light + (x1 - ds->x1) * rw_lightstep; - short *mfloorclip = ds->sprbottomclip - ds->x1; - short *mceilingclip = ds->sprtopclip - ds->x1; + const short *mfloorclip = ds->sprbottomclip - ds->x1; + const short *mceilingclip = ds->sprtopclip - ds->x1; //double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1); float *MaskedSWall = ds->swall - ds->x1; @@ -495,8 +487,8 @@ namespace swrenderer WallT = ds->tmapvals; Clip3DFloors *clip3d = Thread->Clip3D.get(); - wallupper.Project(Thread->Viewport.get(), clip3d->sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); - walllower.Project(Thread->Viewport.get(), clip3d->sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); + wallupper.Project(Thread->Viewport.get(), clipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC); + walllower.Project(Thread->Viewport.get(), clipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC); for (i = x1; i < x2; i++) { @@ -552,15 +544,14 @@ namespace swrenderer Clip3DFloors *clip3d = Thread->Clip3D.get(); - // maybe fix clipheights - if (!(clip3d->fake3D & FAKE3D_CLIPBOTTOM)) clip3d->sclipBottom = floorHeight; - if (!(clip3d->fake3D & FAKE3D_CLIPTOP)) clip3d->sclipTop = ceilingHeight; + double clipTop = m3DFloor.clipTop ? m3DFloor.sclipTop : ceilingHeight; + double clipBottom = m3DFloor.clipBottom ? m3DFloor.sclipBottom : floorHeight; // maybe not visible - if (clip3d->sclipBottom >= frontsector->CenterCeiling()) return; - if (clip3d->sclipTop <= frontsector->CenterFloor()) return; + if (clipBottom >= frontsector->CenterCeiling()) return; + if (clipTop <= frontsector->CenterFloor()) return; - if (clip3d->fake3D & FAKE3D_DOWN2UP) + if (m3DFloor.down2Up) { // bottom to viewz last = 0; for (i = backsector->e->XFloor.ffloors.Size() - 1; i >= 0; i--) @@ -571,7 +562,7 @@ namespace swrenderer // visible? passed = 0; if (!(rover->flags & FF_RENDERSIDES) || rover->top.plane->isSlope() || rover->bottom.plane->isSlope() || - rover->top.plane->Zat0() <= clip3d->sclipBottom || + rover->top.plane->Zat0() <= clipBottom || rover->bottom.plane->Zat0() >= ceilingHeight || rover->top.plane->Zat0() <= floorHeight) { @@ -586,7 +577,7 @@ namespace swrenderer } rw_pic = nullptr; - if (rover->bottom.plane->Zat0() >= clip3d->sclipTop || passed) + if (rover->bottom.plane->Zat0() >= clipTop || passed) { if (last) { @@ -608,8 +599,8 @@ namespace swrenderer if (fover->top.plane->isSlope() || fover->bottom.plane->isSlope()) continue; // visible? - if (fover->top.plane->Zat0() <= clip3d->sclipBottom) continue; // no - if (fover->bottom.plane->Zat0() >= clip3d->sclipTop) + if (fover->top.plane->Zat0() <= clipBottom) continue; // no + if (fover->bottom.plane->Zat0() >= clipTop) { // no, last possible fover = nullptr; break; @@ -661,8 +652,8 @@ namespace swrenderer if (fover->top.plane->isSlope() || fover->bottom.plane->isSlope()) continue; // visible? - if (fover->top.plane->Zat0() <= clip3d->sclipBottom) continue; // no - if (fover->bottom.plane->Zat0() >= clip3d->sclipTop) + if (fover->top.plane->Zat0() <= clipBottom) continue; // no + if (fover->bottom.plane->Zat0() >= clipTop) { // visible, last possible fover = nullptr; break; @@ -713,7 +704,7 @@ namespace swrenderer { for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) { - if (clip3d->sclipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) + if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) { lightlist_t *lit = &backsector->e->XFloor.lightlist[j]; basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); @@ -727,7 +718,7 @@ namespace swrenderer { for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) { - if (clip3d->sclipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) + if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) { lightlist_t *lit = &frontsector->e->XFloor.lightlist[j]; basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); @@ -742,7 +733,7 @@ namespace swrenderer if (rw_pic != DONT_DRAW) { - RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); + RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap, clipTop, clipBottom); } else rw_pic = nullptr; break; @@ -759,7 +750,7 @@ namespace swrenderer passed = 0; if (!(rover->flags & FF_RENDERSIDES) || rover->top.plane->isSlope() || rover->bottom.plane->isSlope() || - rover->bottom.plane->Zat0() >= clip3d->sclipTop || + rover->bottom.plane->Zat0() >= clipTop || rover->top.plane->Zat0() <= floorHeight || rover->bottom.plane->Zat0() >= ceilingHeight) { @@ -773,7 +764,7 @@ namespace swrenderer } } rw_pic = nullptr; - if (rover->top.plane->Zat0() <= clip3d->sclipBottom || passed) + if (rover->top.plane->Zat0() <= clipBottom || passed) { // maybe wall from inside rendering? fover = nullptr; for (j = 0; j < (int)frontsector->e->XFloor.ffloors.Size(); j++) @@ -790,8 +781,8 @@ namespace swrenderer if (fover->top.plane->isSlope() || fover->bottom.plane->isSlope()) continue; // visible? - if (fover->bottom.plane->Zat0() >= clip3d->sclipTop) continue; // no - if (fover->top.plane->Zat0() <= clip3d->sclipBottom) + if (fover->bottom.plane->Zat0() >= clipTop) continue; // no + if (fover->top.plane->Zat0() <= clipBottom) { // no, last possible fover = nullptr; break; @@ -842,8 +833,8 @@ namespace swrenderer if (fover->top.plane->isSlope() || fover->bottom.plane->isSlope()) continue; // visible? - if (fover->bottom.plane->Zat0() >= clip3d->sclipTop) continue; // no - if (fover->top.plane->Zat0() <= clip3d->sclipBottom) + if (fover->bottom.plane->Zat0() >= clipTop) continue; // no + if (fover->top.plane->Zat0() <= clipBottom) { // visible, last possible fover = nullptr; break; @@ -892,7 +883,7 @@ namespace swrenderer { for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) { - if (clip3d->sclipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) + if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) { lightlist_t *lit = &backsector->e->XFloor.lightlist[j]; basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); @@ -906,7 +897,7 @@ namespace swrenderer { for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) { - if (clip3d->sclipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) + if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) { lightlist_t *lit = &frontsector->e->XFloor.lightlist[j]; basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]); @@ -921,7 +912,7 @@ namespace swrenderer if (rw_pic != DONT_DRAW) { - RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap); + RenderFakeWall(ds, x1, x2, fover ? fover : rover, wallshade, basecolormap, clipTop, clipBottom); } else { @@ -962,14 +953,13 @@ namespace swrenderer top = MAX(frontcz1, frontcz2); bot = MIN(frontfz1, frontfz2); - Clip3DFloors *clip3d = Thread->Clip3D.get(); - if (clip3d->fake3D & FAKE3D_CLIPTOP) + if (m3DFloor.clipTop) { - top = MIN(top, clip3d->sclipTop); + top = MIN(top, m3DFloor.sclipTop); } - if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) + if (m3DFloor.clipBottom) { - bot = MAX(bot, clip3d->sclipBottom); + bot = MAX(bot, m3DFloor.sclipBottom); } } } diff --git a/src/swrenderer/line/r_renderdrawsegment.h b/src/swrenderer/line/r_renderdrawsegment.h index 42a5ac5bc..82186f317 100644 --- a/src/swrenderer/line/r_renderdrawsegment.h +++ b/src/swrenderer/line/r_renderdrawsegment.h @@ -32,14 +32,14 @@ namespace swrenderer { public: RenderDrawSegment(RenderThread *thread); - void Render(DrawSegment *ds, int x1, int x2); + void Render(DrawSegment *ds, int x1, int x2, Fake3DTranslucent clip3DFloor); RenderThread *Thread = nullptr; private: - bool RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int wallshade, bool wrap); + bool RenderWall(DrawSegment *ds, int x1, int x2, WallDrawerArgs &walldrawerargs, SpriteDrawerArgs &columndrawerargs, bool visible, FDynamicColormap *basecolormap, int wallshade); void ClipMidtex(int x1, int x2); - void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap); + void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int wallshade, FDynamicColormap *basecolormap, double clipTop, double clipBottom); void RenderFakeWallRange(DrawSegment *ds, int x1, int x2, int wallshade); void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot); @@ -47,6 +47,7 @@ namespace swrenderer sector_t *backsector = nullptr; seg_t *curline = nullptr; + Fake3DTranslucent m3DFloor; FWallCoords WallC; FWallTmapVals WallT; diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 5b7518440..0b9c9131d 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -97,7 +97,7 @@ namespace swrenderer col = width + (col % width); } - source = texture->GetColumn(col, nullptr); + source = texture->GetColumn(DefaultRenderStyle(), col, nullptr); source2 = nullptr; texturefracx = 0; } @@ -330,7 +330,6 @@ namespace swrenderer if (rw_pic->UseType == FTexture::TEX_Null) return; - rw_pic->GetHeight(); // To ensure that rw_pic->HeightBits has been set int fracbits = 32 - rw_pic->HeightBits; if (fracbits == 32) { // Hack for one pixel tall textures @@ -531,7 +530,7 @@ namespace swrenderer this->rw_pic = pic; this->mask = mask; - Thread->PrepareTexture(pic); + Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here. if (rw_pic->GetHeight() != 1 << rw_pic->HeightBits) { diff --git a/src/swrenderer/plane/r_skyplane.cpp b/src/swrenderer/plane/r_skyplane.cpp index ef7a6b898..e95abbd46 100644 --- a/src/swrenderer/plane/r_skyplane.cpp +++ b/src/swrenderer/plane/r_skyplane.cpp @@ -172,8 +172,8 @@ namespace swrenderer drawerargs.SetLight(&NormalLight, 0, 0); } - Thread->PrepareTexture(frontskytex); - Thread->PrepareTexture(backskytex); + Thread->PrepareTexture(frontskytex, DefaultRenderStyle()); + Thread->PrepareTexture(backskytex, DefaultRenderStyle()); DrawSky(pl); } diff --git a/src/swrenderer/plane/r_visibleplanelist.cpp b/src/swrenderer/plane/r_visibleplanelist.cpp index 7a4f5a57c..561930cc2 100644 --- a/src/swrenderer/plane/r_visibleplanelist.cpp +++ b/src/swrenderer/plane/r_visibleplanelist.cpp @@ -99,7 +99,7 @@ namespace swrenderer } } - VisiblePlane *VisiblePlaneList::FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal, FDynamicColormap *basecolormap) + VisiblePlane *VisiblePlaneList::FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal, FDynamicColormap *basecolormap, Fake3DOpaque::Type fakeFloorType, fixed_t fakeAlpha) { secplane_t plane; VisiblePlane *check; @@ -140,8 +140,7 @@ namespace swrenderer // kg3D - hack, store alpha in sky // i know there is ->alpha, but this also allows to identify fake plane // and ->alpha is for stacked sectors - Clip3DFloors *clip3d = Thread->Clip3D.get(); - if (clip3d->fake3D & (FAKE3D_FAKEFLOOR | FAKE3D_FAKECEILING)) sky = 0x80000000 | clip3d->fakeAlpha; + if (fakeFloorType == Fake3DOpaque::FakeFloor || fakeFloorType == Fake3DOpaque::FakeCeiling) sky = 0x80000000 | fakeAlpha; else sky = 0; // not skyflatnum so it can't be a sky portal = nullptr; alpha = OPAQUE; diff --git a/src/swrenderer/plane/r_visibleplanelist.h b/src/swrenderer/plane/r_visibleplanelist.h index c44c860eb..a49479e6c 100644 --- a/src/swrenderer/plane/r_visibleplanelist.h +++ b/src/swrenderer/plane/r_visibleplanelist.h @@ -40,7 +40,7 @@ namespace swrenderer void Clear(); void ClearKeepFakePlanes(); - VisiblePlane *FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal, FDynamicColormap *basecolormap); + VisiblePlane *FindPlane(const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive, const FTransform &xxform, int sky, FSectorPortal *portal, FDynamicColormap *basecolormap, Fake3DOpaque::Type fakeFloorType, fixed_t fakeAlpha); VisiblePlane *GetRange(VisiblePlane *pl, int start, int stop); bool HasPortalPlanes() const; diff --git a/src/swrenderer/r_renderthread.cpp b/src/swrenderer/r_renderthread.cpp index bb2816a94..986879618 100644 --- a/src/swrenderer/r_renderthread.cpp +++ b/src/swrenderer/r_renderthread.cpp @@ -89,7 +89,7 @@ namespace swrenderer return pal_drawers.get(); } - void RenderThread::PrepareTexture(FTexture *texture) + void RenderThread::PrepareTexture(FTexture *texture, FRenderStyle style) { if (texture == nullptr) return; @@ -106,9 +106,9 @@ namespace swrenderer std::unique_lock lock(loadmutex); - texture->GetPixels(); + texture->GetPixels(style); const FTexture::Span *spans; - texture->GetColumn(0, &spans); + texture->GetColumn(style, 0, &spans); if (Viewport->RenderTarget->IsBgra()) { texture->GetPixelsBgra(); diff --git a/src/swrenderer/r_renderthread.h b/src/swrenderer/r_renderthread.h index 3e559155b..34beab6ae 100644 --- a/src/swrenderer/r_renderthread.h +++ b/src/swrenderer/r_renderthread.h @@ -84,7 +84,7 @@ namespace swrenderer SWPixelFormatDrawers *Drawers(RenderViewport *viewport); // Make sure texture can accessed safely - void PrepareTexture(FTexture *texture); + void PrepareTexture(FTexture *texture, FRenderStyle style); // Setup poly object in a threadsafe manner void PreparePolyObject(subsector_t *sub); diff --git a/src/swrenderer/r_swcanvas.cpp b/src/swrenderer/r_swcanvas.cpp index 0330d4d6e..5522d89dc 100644 --- a/src/swrenderer/r_swcanvas.cpp +++ b/src/swrenderer/r_swcanvas.cpp @@ -196,7 +196,7 @@ void SWCanvas::DrawTexture(DCanvas *canvas, FTexture *img, DrawParms &parms) while (x < x2_i) { - drawerargs.DrawMaskedColumn(&thread, x, iscale, img, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, !parms.masked); + drawerargs.DrawMaskedColumn(&thread, x, iscale, img, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, parms.style, !parms.masked); x++; frac += xiscale_i; } diff --git a/src/swrenderer/r_swcolormaps.cpp b/src/swrenderer/r_swcolormaps.cpp index 318ccead2..13c66706b 100644 --- a/src/swrenderer/r_swcolormaps.cpp +++ b/src/swrenderer/r_swcolormaps.cpp @@ -366,7 +366,7 @@ void SetDefaultColormap (const char *name) } else { - FWadLump lumpr = Wads.OpenLumpNum (lump); + auto lumpr = Wads.OpenLumpReader (lump); // [RH] The colormap may not have been designed for the specific // palette we are using, so remap it to match the current palette. @@ -427,7 +427,7 @@ static void InitBoomColormaps () if (Wads.LumpLength (fakecmaps[j].lump) >= (NUMCOLORMAPS+1)*256) { int k, r; - FWadLump lump = Wads.OpenLumpNum (fakecmaps[j].lump); + auto lump = Wads.OpenLumpReader (fakecmaps[j].lump); uint8_t *const map = realcolormaps.Maps + NUMCOLORMAPS*256*j; for (k = 0; k < NUMCOLORMAPS; ++k) diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 3c18e6218..c31908a17 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -105,14 +105,14 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache) if (isbgra) tex->GetColumnBgra(0, &spanp); else - tex->GetColumn(0, &spanp); + tex->GetColumn(DefaultRenderStyle(), 0, &spanp); } else if (cache != 0) { if (isbgra) tex->GetPixelsBgra(); else - tex->GetPixels (); + tex->GetPixels (DefaultRenderStyle()); } else { @@ -282,7 +282,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin cameraViewpoint = r_viewpoint; cameraViewwindow = r_viewwindow; - uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(); + uint8_t *Pixels = renderTarget->IsBgra() ? (uint8_t*)tex->GetPixelsBgra() : (uint8_t*)tex->GetPixels(DefaultRenderStyle()); DSimpleCanvas *Canvas = renderTarget->IsBgra() ? tex->GetCanvasBgra() : tex->GetCanvas(); // curse Doom's overuse of global variables in the renderer. @@ -328,7 +328,7 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin // We need to make sure that both pixel buffers contain data: int width = tex->GetWidth(); int height = tex->GetHeight(); - uint8_t *palbuffer = (uint8_t *)tex->GetPixels(); + uint8_t *palbuffer = (uint8_t *)tex->GetPixels(DefaultRenderStyle()); uint32_t *bgrabuffer = (uint32_t*)tex->GetPixelsBgra(); for (int x = 0; x < width; x++) { diff --git a/src/swrenderer/scene/r_3dfloors.cpp b/src/swrenderer/scene/r_3dfloors.cpp index 111cbf504..d468c9611 100644 --- a/src/swrenderer/scene/r_3dfloors.cpp +++ b/src/swrenderer/scene/r_3dfloors.cpp @@ -67,7 +67,6 @@ namespace swrenderer FakeFloors.clear(); fakeActive = false; - fake3D = 0; while (CurrentSkybox) { DeleteHeights(); diff --git a/src/swrenderer/scene/r_3dfloors.h b/src/swrenderer/scene/r_3dfloors.h index d697755b2..0237ca95e 100644 --- a/src/swrenderer/scene/r_3dfloors.h +++ b/src/swrenderer/scene/r_3dfloors.h @@ -33,24 +33,33 @@ namespace swrenderer ClipStack *next; }; - enum Fake3DOpaque + // BSP stage + struct Fake3DOpaque { - // BSP stage: - FAKE3D_FAKEFLOOR = 1, // fake floor, mark seg as FAKE - FAKE3D_FAKECEILING = 2, // fake ceiling, mark seg as FAKE - FAKE3D_FAKEBACK = 4, // RenderLine with fake backsector, mark seg as FAKE - FAKE3D_FAKEMASK = 7, - FAKE3D_CLIPBOTFRONT = 8, // use front sector clipping info (bottom) - FAKE3D_CLIPTOPFRONT = 16, // use front sector clipping info (top) + enum Type + { + Normal, // Not a 3D floor + FakeFloor, // fake floor, mark seg as FAKE + FakeCeiling, // fake ceiling, mark seg as FAKE + FakeBack // RenderLine with fake backsector, mark seg as FAKE + }; + Type type = Normal; + + bool clipBotFront = false; // use front sector clipping info (bottom) + bool clipTopFront = false; // use front sector clipping info (top) + + Fake3DOpaque() { } + Fake3DOpaque(Type type) : type(type) { } }; - enum Fake3DTranslucent + // Drawing stage + struct Fake3DTranslucent { - // sorting stage: - FAKE3D_CLIPBOTTOM = 1, // clip bottom - FAKE3D_CLIPTOP = 2, // clip top - FAKE3D_REFRESHCLIP = 4, // refresh clip info - FAKE3D_DOWN2UP = 8, // rendering from down to up (floors) + bool clipBottom = false; + bool clipTop = false; + bool down2Up = false; // rendering from down to up (floors) + double sclipBottom = 0; + double sclipTop = 0; }; class FakeFloorClip @@ -82,13 +91,8 @@ namespace swrenderer RenderThread *Thread = nullptr; - int fake3D = 0; - FakeFloorClip *fakeFloor = nullptr; - fixed_t fakeAlpha = 0; bool fakeActive = false; - double sclipBottom = 0; - double sclipTop = 0; HeightLevel *height_top = nullptr; HeightLevel *height_cur = nullptr; int CurrentSkybox = 0; diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index f18cdc2ec..4b0c6f1fa 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -450,7 +450,7 @@ namespace swrenderer } // kg3D - add fake segs, never rendered - void RenderOpaquePass::FakeDrawLoop(subsector_t *sub, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap) + void RenderOpaquePass::FakeDrawLoop(subsector_t *sub, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque opaque3dfloor) { int count; seg_t* line; @@ -462,7 +462,7 @@ namespace swrenderer { if ((line->sidedef) && !(line->sidedef->Flags & WALLF_POLYOBJ)) { - renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap); + renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap, opaque3dfloor); } line++; } @@ -565,7 +565,9 @@ namespace swrenderer frontsector->planes[sector_t::ceiling].xform, frontsector->sky, portal, - basecolormap + basecolormap, + Fake3DOpaque::Normal, + 0 ) : nullptr; if (ceilingplane) @@ -606,7 +608,9 @@ namespace swrenderer frontsector->planes[sector_t::floor].xform, frontsector->sky, portal, - basecolormap + basecolormap, + Fake3DOpaque::Normal, + 0 ) : nullptr; if (floorplane) @@ -634,7 +638,7 @@ namespace swrenderer if (!(clip3d->fakeFloor->fakeFloor->flags & FF_RENDERPLANES)) continue; if (clip3d->fakeFloor->fakeFloor->alpha == 0) continue; if (clip3d->fakeFloor->fakeFloor->flags & FF_THISINSIDE && clip3d->fakeFloor->fakeFloor->flags & FF_INVERTSECTOR) continue; - clip3d->fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); + fixed_t fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (clip3d->fakeFloor->validcount != validcount) { clip3d->fakeFloor->validcount = validcount; @@ -644,7 +648,6 @@ namespace swrenderer if (fakeHeight < Thread->Viewport->viewpoint.Pos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot)) { - clip3d->fake3D = FAKE3D_FAKEFLOOR; tempsec = *clip3d->fakeFloor->fakeFloor->model; tempsec.floorplane = *clip3d->fakeFloor->fakeFloor->top.plane; tempsec.ceilingplane = *clip3d->fakeFloor->fakeFloor->bottom.plane; @@ -672,13 +675,14 @@ namespace swrenderer frontsector->planes[position].xform, frontsector->sky, nullptr, - basecolormap); + basecolormap, + Fake3DOpaque::FakeFloor, + fakeAlpha); if (floorplane) floorplane->AddLights(Thread, frontsector->lighthead); - FakeDrawLoop(sub, floorplane, ceilingplane, foggy, basecolormap); - clip3d->fake3D = 0; + FakeDrawLoop(sub, floorplane, ceilingplane, foggy, basecolormap, Fake3DOpaque::FakeFloor); frontsector = sub->sector; } } @@ -696,7 +700,7 @@ namespace swrenderer if (!(clip3d->fakeFloor->fakeFloor->flags & FF_RENDERPLANES)) continue; if (clip3d->fakeFloor->fakeFloor->alpha == 0) continue; if (!(clip3d->fakeFloor->fakeFloor->flags & FF_THISINSIDE) && (clip3d->fakeFloor->fakeFloor->flags & (FF_SWIMMABLE | FF_INVERTSECTOR)) == (FF_SWIMMABLE | FF_INVERTSECTOR)) continue; - clip3d->fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); + fixed_t fakeAlpha = MIN(Scale(clip3d->fakeFloor->fakeFloor->alpha, OPAQUE, 255), OPAQUE); if (clip3d->fakeFloor->validcount != validcount) { @@ -707,7 +711,6 @@ namespace swrenderer if (fakeHeight > Thread->Viewport->viewpoint.Pos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot)) { - clip3d->fake3D = FAKE3D_FAKECEILING; tempsec = *clip3d->fakeFloor->fakeFloor->model; tempsec.floorplane = *clip3d->fakeFloor->fakeFloor->top.plane; tempsec.ceilingplane = *clip3d->fakeFloor->fakeFloor->bottom.plane; @@ -738,13 +741,14 @@ namespace swrenderer frontsector->planes[position].xform, frontsector->sky, nullptr, - basecolormap); + basecolormap, + Fake3DOpaque::FakeCeiling, + fakeAlpha); if (ceilingplane) ceilingplane->AddLights(Thread, frontsector->lighthead); - FakeDrawLoop(sub, floorplane, ceilingplane, foggy, basecolormap); - clip3d->fake3D = 0; + FakeDrawLoop(sub, floorplane, ceilingplane, foggy, basecolormap, Fake3DOpaque::FakeCeiling); frontsector = sub->sector; } } @@ -787,7 +791,7 @@ namespace swrenderer if (dist1 > line_distance_cull && dist2 > line_distance_cull) { FarClipLine farclip(Thread); - farclip.Render(line, InSubsector, floorplane, ceilingplane); + farclip.Render(line, InSubsector, floorplane, ceilingplane, Fake3DOpaque::Normal); } else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ)) { @@ -805,7 +809,7 @@ namespace swrenderer if (!(clip3d->fakeFloor->fakeFloor->flags & FF_EXISTS)) continue; if (!(clip3d->fakeFloor->fakeFloor->flags & FF_RENDERPLANES)) continue; if (!clip3d->fakeFloor->fakeFloor->model) continue; - clip3d->fake3D = FAKE3D_FAKEBACK; + Fake3DOpaque opaque3dfloor = Fake3DOpaque::FakeBack; tempsec = *clip3d->fakeFloor->fakeFloor->model; tempsec.floorplane = *clip3d->fakeFloor->fakeFloor->top.plane; tempsec.ceilingplane = *clip3d->fakeFloor->fakeFloor->bottom.plane; @@ -814,14 +818,13 @@ namespace swrenderer clip3d->fakeFloor->validcount = validcount; clip3d->NewClip(); } - renderline.Render(line, InSubsector, frontsector, &tempsec, floorplane, ceilingplane, foggy, basecolormap); // fake + renderline.Render(line, InSubsector, frontsector, &tempsec, floorplane, ceilingplane, foggy, basecolormap, opaque3dfloor); // fake } clip3d->fakeFloor = nullptr; - clip3d->fake3D = 0; floorplane = backupfp; ceilingplane = backupcp; } - renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap); // now real + renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap, Fake3DOpaque::Normal); // now real } line++; } diff --git a/src/swrenderer/scene/r_opaque_pass.h b/src/swrenderer/scene/r_opaque_pass.h index c71dd3985..e17a6109a 100644 --- a/src/swrenderer/scene/r_opaque_pass.h +++ b/src/swrenderer/scene/r_opaque_pass.h @@ -82,7 +82,7 @@ namespace swrenderer bool CheckBBox(float *bspcoord); void AddPolyobjs(subsector_t *sub); - void FakeDrawLoop(subsector_t *sub, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap); + void FakeDrawLoop(subsector_t *sub, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque opaque3dfloor); void AddSprites(sector_t *sec, int lightlevel, WaterFakeSide fakeside, bool foggy, FDynamicColormap *basecolormap); diff --git a/src/swrenderer/scene/r_translucent_pass.cpp b/src/swrenderer/scene/r_translucent_pass.cpp index e08486ef9..244bb4392 100644 --- a/src/swrenderer/scene/r_translucent_pass.cpp +++ b/src/swrenderer/scene/r_translucent_pass.cpp @@ -131,7 +131,7 @@ namespace swrenderer return false; } - void RenderTranslucentPass::DrawMaskedSingle(bool renew) + void RenderTranslucentPass::DrawMaskedSingle(bool renew, Fake3DTranslucent clip3DFloor) { RenderPortal *renderportal = Thread->Portal.get(); DrawSegmentList *drawseglist = Thread->DrawSegments.get(); @@ -143,17 +143,12 @@ namespace swrenderer if (sprite->IsCurrentPortalUniq(renderportal->CurrentPortalUniq)) { - sprite->Render(Thread); + sprite->Render(Thread, clip3DFloor); } } // render any remaining masked mid textures - if (renew) - { - Thread->Clip3D->fake3D |= FAKE3D_REFRESHCLIP; - } - for (unsigned int index = 0; index != drawseglist->SegmentsCount(); index++) { DrawSegment *ds = drawseglist->Segment(index); @@ -161,12 +156,18 @@ namespace swrenderer // [ZZ] the same as above if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) continue; - if (ds->maskedtexturecol != nullptr || ds->bFogBoundary) + if (ds->maskedtexturecol || ds->bFogBoundary) { RenderDrawSegment renderer(Thread); - renderer.Render(ds, ds->x1, ds->x2); + renderer.Render(ds, ds->x1, ds->x2, clip3DFloor); if (renew && ds->bFogBoundary) // don't draw fogboundary again ds->bFogBoundary = false; + + if (renew && ds->sprclipped) + { + memcpy(ds->sprtopclip, ds->bkup, (ds->x2 - ds->x1) * sizeof(short)); + ds->sprclipped = false; + } } } } @@ -183,48 +184,49 @@ namespace swrenderer Clip3DFloors *clip3d = Thread->Clip3D.get(); if (clip3d->height_top == nullptr) { // kg3D - no visible 3D floors, normal rendering - DrawMaskedSingle(false); + Fake3DTranslucent clip3DFloor; + DrawMaskedSingle(false, clip3DFloor); } else { // kg3D - correct sorting // ceilings for (HeightLevel *hl = clip3d->height_cur; hl != nullptr && hl->height >= Thread->Viewport->viewpoint.Pos.Z; hl = hl->prev) { + Fake3DTranslucent clip3DFloor; if (hl->next) { - clip3d->fake3D = FAKE3D_CLIPBOTTOM | FAKE3D_CLIPTOP; - clip3d->sclipTop = hl->next->height; + clip3DFloor.clipTop = true; + clip3DFloor.sclipTop = hl->next->height; } - else - { - clip3d->fake3D = FAKE3D_CLIPBOTTOM; - } - clip3d->sclipBottom = hl->height; - DrawMaskedSingle(true); + clip3DFloor.clipBottom = true; + clip3DFloor.sclipBottom = hl->height; + DrawMaskedSingle(true, clip3DFloor); Thread->PlaneList->RenderHeight(hl->height); } // floors - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP; - clip3d->sclipTop = clip3d->height_top->height; - DrawMaskedSingle(true); + { + Fake3DTranslucent clip3DFloor; + clip3DFloor.clipTop = true; + clip3DFloor.sclipTop = clip3d->height_top->height; + clip3DFloor.down2Up = true; + DrawMaskedSingle(true, clip3DFloor); + } for (HeightLevel *hl = clip3d->height_top; hl != nullptr && hl->height < Thread->Viewport->viewpoint.Pos.Z; hl = hl->next) { Thread->PlaneList->RenderHeight(hl->height); + Fake3DTranslucent clip3DFloor; if (hl->next) { - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPTOP | FAKE3D_CLIPBOTTOM; - clip3d->sclipTop = hl->next->height; + clip3DFloor.clipTop = true; + clip3DFloor.sclipTop = hl->next->height; } - else - { - clip3d->fake3D = FAKE3D_DOWN2UP | FAKE3D_CLIPBOTTOM; - } - clip3d->sclipBottom = hl->height; - DrawMaskedSingle(true); + clip3DFloor.clipBottom = true; + clip3DFloor.sclipBottom = hl->height; + clip3DFloor.down2Up = true; + DrawMaskedSingle(true, clip3DFloor); } clip3d->DeleteHeights(); - clip3d->fake3D = 0; } if (Thread->MainThread) diff --git a/src/swrenderer/scene/r_translucent_pass.h b/src/swrenderer/scene/r_translucent_pass.h index 47da285b5..5c28749a7 100644 --- a/src/swrenderer/scene/r_translucent_pass.h +++ b/src/swrenderer/scene/r_translucent_pass.h @@ -49,7 +49,7 @@ namespace swrenderer private: void CollectPortals(); - void DrawMaskedSingle(bool renew); + void DrawMaskedSingle(bool renew, Fake3DTranslucent clip3DFloor); TArray portaldrawsegs; }; diff --git a/src/swrenderer/segments/r_drawsegment.h b/src/swrenderer/segments/r_drawsegment.h index c29b3a67a..4e2943ab0 100644 --- a/src/swrenderer/segments/r_drawsegment.h +++ b/src/swrenderer/segments/r_drawsegment.h @@ -47,6 +47,7 @@ namespace swrenderer fixed_t *maskedtexturecol = nullptr; float *swall = nullptr; short *bkup = nullptr; // sprtopclip backup, for mid and fake textures + bool sprclipped = false; // True if draw segment was used for clipping sprites FWallTmapVals tmapvals; diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index b1711d9e3..8361a8061 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -312,14 +312,14 @@ namespace swrenderer if (visible) { - thread->PrepareTexture(WallSpriteTile); + thread->PrepareTexture(WallSpriteTile, decal->RenderStyle); while (x < x2) { if (calclighting) { // calculate lighting drawerargs.SetLight(usecolormap, light, wallshade); } - DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle); light += lightstep; x++; } @@ -333,7 +333,7 @@ namespace swrenderer } while (needrepeat--); } - void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) + void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style) { auto viewport = thread->Viewport.get(); @@ -345,6 +345,6 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style); } } diff --git a/src/swrenderer/things/r_decal.h b/src/swrenderer/things/r_decal.h index 712e82900..e617b04a6 100644 --- a/src/swrenderer/things/r_decal.h +++ b/src/swrenderer/things/r_decal.h @@ -16,6 +16,6 @@ namespace swrenderer private: static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int wallshade, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass); - static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); + static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style); }; } diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index f86a7e384..b6f5fe0c7 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -64,7 +64,7 @@ namespace swrenderer this->idepth = idepth; } - void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) + void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { SWModelRenderer renderer(thread); renderer.RenderModel(x, y, z, smf, actor); @@ -199,7 +199,7 @@ namespace swrenderer if (Thread->Viewport->RenderTarget->IsBgra()) args.SetTexture((const uint8_t *)SkinTexture->GetPixelsBgra(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); else - args.SetTexture(SkinTexture->GetPixels(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); + args.SetTexture(SkinTexture->GetPixels(DefaultRenderStyle()), SkinTexture->GetWidth(), SkinTexture->GetHeight()); args.SetDepthTest(true); args.SetWriteDepth(true); @@ -237,7 +237,7 @@ namespace swrenderer if (Thread->Viewport->RenderTarget->IsBgra()) args.SetTexture((const uint8_t *)SkinTexture->GetPixelsBgra(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); else - args.SetTexture(SkinTexture->GetPixels(), SkinTexture->GetWidth(), SkinTexture->GetHeight()); + args.SetTexture(SkinTexture->GetPixels(DefaultRenderStyle()), SkinTexture->GetWidth(), SkinTexture->GetHeight()); args.SetDepthTest(true); args.SetWriteDepth(true); diff --git a/src/swrenderer/things/r_model.h b/src/swrenderer/things/r_model.h index 94ca1d909..3f6fd0e90 100644 --- a/src/swrenderer/things/r_model.h +++ b/src/swrenderer/things/r_model.h @@ -40,7 +40,7 @@ namespace swrenderer static void Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); protected: - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; bool IsModel() const override { return true; } private: diff --git a/src/swrenderer/things/r_particle.cpp b/src/swrenderer/things/r_particle.cpp index ee791b56b..0e167f7c4 100644 --- a/src/swrenderer/things/r_particle.cpp +++ b/src/swrenderer/things/r_particle.cpp @@ -225,7 +225,7 @@ namespace swrenderer thread->SpriteList->Push(vis); } - void RenderParticle::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) + void RenderParticle::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { auto vis = this; @@ -239,7 +239,7 @@ namespace swrenderer if (ycount <= 0 || countbase <= 0) return; - DrawMaskedSegsBehindParticle(thread); + DrawMaskedSegsBehindParticle(thread, clip3DFloor); uint32_t fg = LightBgra::shade_pal_index_simple(color, LightBgra::calc_light_multiplier(LIGHTSCALE(0, vis->Light.ColormapNum << FRACBITS))); @@ -278,7 +278,7 @@ namespace swrenderer } } - void RenderParticle::DrawMaskedSegsBehindParticle(RenderThread *thread) + void RenderParticle::DrawMaskedSegsBehindParticle(RenderThread *thread, const Fake3DTranslucent &clip3DFloor) { // Draw any masked textures behind this particle so that when the // particle is drawn, it will be in front of them. @@ -297,7 +297,7 @@ namespace swrenderer if (ds->CurrentPortalUniq == CurrentPortalUniq) { RenderDrawSegment renderer(thread); - renderer.Render(ds, MAX(ds->x1, x1), MIN(ds->x2, x2)); + renderer.Render(ds, MAX(ds->x1, x1), MIN(ds->x2, x2), clip3DFloor); } } } diff --git a/src/swrenderer/things/r_particle.h b/src/swrenderer/things/r_particle.h index 84bd10aae..79d10b7c5 100644 --- a/src/swrenderer/things/r_particle.h +++ b/src/swrenderer/things/r_particle.h @@ -14,10 +14,10 @@ namespace swrenderer protected: bool IsParticle() const override { return true; } - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; private: - void DrawMaskedSegsBehindParticle(RenderThread *thread); + void DrawMaskedSegsBehindParticle(RenderThread *thread, const Fake3DTranslucent &clip3DFloor); fixed_t xscale = 0; fixed_t startfrac = 0; // horizontal position of x1 diff --git a/src/swrenderer/things/r_playersprite.cpp b/src/swrenderer/things/r_playersprite.cpp index 41ec47239..924c7a7d8 100644 --- a/src/swrenderer/things/r_playersprite.cpp +++ b/src/swrenderer/things/r_playersprite.cpp @@ -545,10 +545,10 @@ namespace swrenderer short *mceilingclip = zeroarray; fixed_t frac = startfrac; - thread->PrepareTexture(pic); + thread->PrepareTexture(pic, RenderStyle); for (int x = x1; x < x2; x++) { - drawerargs.DrawMaskedColumn(thread, x, iscale, pic, frac + xiscale / 2, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); + drawerargs.DrawMaskedColumn(thread, x, iscale, pic, frac + xiscale / 2, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, RenderStyle, false); frac += xiscale; } diff --git a/src/swrenderer/things/r_sprite.cpp b/src/swrenderer/things/r_sprite.cpp index b9ed668bc..be26ad7c2 100644 --- a/src/swrenderer/things/r_sprite.cpp +++ b/src/swrenderer/things/r_sprite.cpp @@ -303,7 +303,7 @@ namespace swrenderer thread->SpriteList->Push(vis); } - void RenderSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int) + void RenderSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int, Fake3DTranslucent) { auto vis = this; @@ -361,11 +361,11 @@ namespace swrenderer { RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - thread->PrepareTexture(tex); + thread->PrepareTexture(tex, vis->RenderStyle); while (x < x2) { if (!translucentPass->ClipSpriteColumnWithPortals(x, vis)) - drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, false); + drawerargs.DrawMaskedColumn(thread, x, iscale, tex, frac, spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, vis->RenderStyle, false); x++; frac += xiscale; } diff --git a/src/swrenderer/things/r_sprite.h b/src/swrenderer/things/r_sprite.h index 55d504fc9..8fe53080e 100644 --- a/src/swrenderer/things/r_sprite.h +++ b/src/swrenderer/things/r_sprite.h @@ -10,7 +10,7 @@ namespace swrenderer static void Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap); protected: - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; private: fixed_t xscale = 0; diff --git a/src/swrenderer/things/r_visiblesprite.cpp b/src/swrenderer/things/r_visiblesprite.cpp index 2a1d36eeb..458e83dbb 100644 --- a/src/swrenderer/things/r_visiblesprite.cpp +++ b/src/swrenderer/things/r_visiblesprite.cpp @@ -49,11 +49,11 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { - void VisibleSprite::Render(RenderThread *thread) + void VisibleSprite::Render(RenderThread *thread, Fake3DTranslucent clip3DFloor) { if (IsModel()) { - Render(thread, nullptr, nullptr, 0, 0); + Render(thread, nullptr, nullptr, 0, 0, clip3DFloor); return; } @@ -62,10 +62,8 @@ namespace swrenderer VisibleSprite *spr = this; - int i; int x1, x2; short topclip, botclip; - short *clip1, *clip2; FSWColormap *colormap = spr->Light.BaseColormap; int colormapnum = spr->Light.ColormapNum; F3DFloor *rover; @@ -76,10 +74,10 @@ namespace swrenderer if (spr->IsParticle()) { // kg3D - reject invisible parts - if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return; - if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return; + if (clip3DFloor.clipBottom && spr->gpos.Z <= clip3DFloor.sclipBottom) return; + if (clip3DFloor.clipTop && spr->gpos.Z >= clip3DFloor.sclipTop) return; - spr->Render(thread, nullptr, nullptr, 0, 0); + spr->Render(thread, nullptr, nullptr, 0, 0, clip3DFloor); return; } @@ -95,27 +93,29 @@ namespace swrenderer return; // kg3D - reject invisible parts - if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gzt <= clip3d->sclipBottom) return; - if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gzb >= clip3d->sclipTop) return; + if (clip3DFloor.clipBottom && spr->gzt <= clip3DFloor.sclipBottom) return; + if (clip3DFloor.clipTop && spr->gzb >= clip3DFloor.sclipTop) return; // kg3D - correct colors now CameraLight *cameraLight = CameraLight::Instance(); if (!cameraLight->FixedColormap() && cameraLight->FixedLightLevel() < 0 && spr->sector->e && spr->sector->e->XFloor.lightlist.Size()) { - if (!(clip3d->fake3D & FAKE3D_CLIPTOP)) - { - clip3d->sclipTop = spr->sector->ceilingplane.ZatPoint(thread->Viewport->viewpoint.Pos); - } + double clipTop; + if (clip3DFloor.clipTop) + clipTop = clip3DFloor.clipTop; + else + clipTop = spr->sector->ceilingplane.ZatPoint(thread->Viewport->viewpoint.Pos); + sector_t *sec = nullptr; FDynamicColormap *mybasecolormap = nullptr; - for (i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) + for (int i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) { - if (clip3d->sclipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0()) + if (clipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0()) { rover = spr->sector->e->XFloor.lightlist[i].caster; if (rover) { - if (rover->flags & FF_DOUBLESHADOW && clip3d->sclipTop <= rover->bottom.plane->Zat0()) + if (rover->flags & FF_DOUBLESHADOW && clipTop <= rover->bottom.plane->Zat0()) { break; } @@ -231,15 +231,15 @@ namespace swrenderer } } - if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) + if (clip3DFloor.clipBottom) { if (!spr->IsVoxel()) { - double hz = clip3d->sclipBottom; + double hz = clip3DFloor.sclipBottom; if (spr->fakefloor) { double floorz = spr->fakefloor->top.plane->Zat0(); - if (viewport->viewpoint.Pos.Z > floorz && floorz == clip3d->sclipBottom) + if (viewport->viewpoint.Pos.Z > floorz && floorz == clip3DFloor.sclipBottom) { hz = spr->fakefloor->bottom.plane->Zat0(); } @@ -250,17 +250,17 @@ namespace swrenderer botclip = MAX(0, h); } } - hzb = MAX(hzb, clip3d->sclipBottom); + hzb = MAX(hzb, clip3DFloor.sclipBottom); } - if (clip3d->fake3D & FAKE3D_CLIPTOP) + if (clip3DFloor.clipTop) { if (!spr->IsVoxel()) { - double hz = clip3d->sclipTop; + double hz = clip3DFloor.sclipTop; if (spr->fakeceiling != nullptr) { double ceilingZ = spr->fakeceiling->bottom.plane->Zat0(); - if (viewport->viewpoint.Pos.Z < ceilingZ && ceilingZ == clip3d->sclipTop) + if (viewport->viewpoint.Pos.Z < ceilingZ && ceilingZ == clip3DFloor.sclipTop) { hz = spr->fakeceiling->top.plane->Zat0(); } @@ -271,7 +271,7 @@ namespace swrenderer topclip = short(MIN(h, viewheight)); } } - hzt = MIN(hzt, clip3d->sclipTop); + hzt = MIN(hzt, clip3DFloor.sclipTop); } if (topclip >= botclip) @@ -281,14 +281,16 @@ namespace swrenderer return; } - i = x2 - x1; - clip1 = clipbot + x1; - clip2 = cliptop + x1; - do { - *clip1++ = botclip; - *clip2++ = topclip; - } while (--i); + int i = x2 - x1; + short *clip1 = clipbot + x1; + short *clip2 = cliptop + x1; + do + { + *clip1++ = botclip; + *clip2++ = topclip; + } while (--i); + } // Scan drawsegs from end to start for obscuring segs. // The first drawseg that is closer than the sprite is the clip seg. @@ -320,7 +322,7 @@ namespace swrenderer int r2 = MIN(ds->x2, x2); RenderDrawSegment renderer(thread); - renderer.Render(ds, r1, r2); + renderer.Render(ds, r1, r2, clip3DFloor); } } } @@ -338,9 +340,9 @@ namespace swrenderer int r2 = MIN(group.x2, x2); // Clip bottom - clip1 = clipbot + r1; - clip2 = group.sprbottomclip + r1 - group.x1; - i = r2 - r1; + short *clip1 = clipbot + r1; + const short *clip2 = group.sprbottomclip + r1 - group.x1; + int i = r2 - r1; do { if (*clip1 > *clip2) @@ -398,9 +400,9 @@ namespace swrenderer if (ds->silhouette & SIL_BOTTOM) //bottom sil { - clip1 = clipbot + r1; - clip2 = ds->sprbottomclip + r1 - ds->x1; - i = r2 - r1; + short *clip1 = clipbot + r1; + const short *clip2 = ds->sprbottomclip + r1 - ds->x1; + int i = r2 - r1; do { if (*clip1 > *clip2) @@ -412,9 +414,9 @@ namespace swrenderer if (ds->silhouette & SIL_TOP) // top sil { - clip1 = cliptop + r1; - clip2 = ds->sprtopclip + r1 - ds->x1; - i = r2 - r1; + short *clip1 = cliptop + r1; + const short *clip2 = ds->sprtopclip + r1 - ds->x1; + int i = r2 - r1; do { if (*clip1 < *clip2) @@ -431,13 +433,14 @@ namespace swrenderer if (!spr->IsVoxel()) { - spr->Render(thread, clipbot, cliptop, 0, 0); + spr->Render(thread, clipbot, cliptop, 0, 0, clip3DFloor); } else { // If it is completely clipped away, don't bother drawing it. if (cliptop[x2] >= clipbot[x2]) { + int i; for (i = x1; i < x2; ++i) { if (cliptop[i] < clipbot[i]) @@ -464,7 +467,7 @@ namespace swrenderer } int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale); int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale); - spr->Render(thread, cliptop, clipbot, minvoxely, maxvoxely); + spr->Render(thread, cliptop, clipbot, minvoxely, maxvoxely, clip3DFloor); } spr->Light.BaseColormap = colormap; spr->Light.ColormapNum = colormapnum; diff --git a/src/swrenderer/things/r_visiblesprite.h b/src/swrenderer/things/r_visiblesprite.h index c9fff3327..782196486 100644 --- a/src/swrenderer/things/r_visiblesprite.h +++ b/src/swrenderer/things/r_visiblesprite.h @@ -38,7 +38,7 @@ namespace swrenderer VisibleSprite() { RenderStyle = STYLE_Normal; } virtual ~VisibleSprite() { } - void Render(RenderThread *thread); + void Render(RenderThread *thread, Fake3DTranslucent clip3DFloor); bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; } const FVector3 &WorldPos() const { return gpos; } @@ -54,7 +54,7 @@ namespace swrenderer virtual bool IsWallSprite() const { return false; } virtual bool IsModel() const { return false; } - virtual void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) = 0; + virtual void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) = 0; FTexture *pic = nullptr; diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index 75b0a2c07..a3c12a865 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -205,7 +205,7 @@ namespace swrenderer thread->SpriteList->Push(vis); } - void RenderVoxel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) + void RenderVoxel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) { auto spr = this; auto viewport = thread->Viewport.get(); diff --git a/src/swrenderer/things/r_voxel.h b/src/swrenderer/things/r_voxel.h index bef22d480..7121d3498 100644 --- a/src/swrenderer/things/r_voxel.h +++ b/src/swrenderer/things/r_voxel.h @@ -64,7 +64,7 @@ namespace swrenderer protected: bool IsVoxel() const override { return true; } - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; private: struct posang diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 1555e7124..f44d88e2a 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -145,7 +145,7 @@ namespace swrenderer thread->SpriteList->Push(vis); } - void RenderWallSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int) + void RenderWallSprite::Render(RenderThread *thread, short *mfloorclip, short *mceilingclip, int, int, Fake3DTranslucent) { auto spr = this; @@ -239,7 +239,7 @@ namespace swrenderer { RenderTranslucentPass *translucentPass = thread->TranslucentPass.get(); - thread->PrepareTexture(WallSpriteTile); + thread->PrepareTexture(WallSpriteTile, spr->RenderStyle); while (x < x2) { if (calclighting) @@ -247,14 +247,14 @@ namespace swrenderer drawerargs.SetLight(usecolormap, light, shade); } if (!translucentPass->ClipSpriteColumnWithPortals(x, spr)) - DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip); + DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle); light += lightstep; x++; } } } - void RenderWallSprite::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) + void RenderWallSprite::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style) { auto viewport = thread->Viewport.get(); @@ -266,6 +266,6 @@ namespace swrenderer else sprtopscreen = viewport->CenterY - texturemid * spryscale; - drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style); } } diff --git a/src/swrenderer/things/r_wallsprite.h b/src/swrenderer/things/r_wallsprite.h index 2c2ca269c..fa127ccf4 100644 --- a/src/swrenderer/things/r_wallsprite.h +++ b/src/swrenderer/things/r_wallsprite.h @@ -14,10 +14,10 @@ namespace swrenderer protected: bool IsWallSprite() const override { return true; } - void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ) override; + void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; private: - static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip); + static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style); FWallCoords wallc; uint32_t Translation = 0; diff --git a/src/swrenderer/viewport/r_skydrawer.cpp b/src/swrenderer/viewport/r_skydrawer.cpp index 16e2d2ab3..c134a46e2 100644 --- a/src/swrenderer/viewport/r_skydrawer.cpp +++ b/src/swrenderer/viewport/r_skydrawer.cpp @@ -56,7 +56,7 @@ namespace swrenderer } else { - dc_source = texture->GetColumn(column, nullptr); + dc_source = texture->GetColumn(DefaultRenderStyle(), column, nullptr); dc_sourceheight = texture->GetHeight(); } } @@ -75,7 +75,7 @@ namespace swrenderer } else { - dc_source2 = texture->GetColumn(column, nullptr); + dc_source2 = texture->GetColumn(DefaultRenderStyle(), column, nullptr); dc_sourceheight2 = texture->GetHeight(); } } diff --git a/src/swrenderer/viewport/r_spandrawer.cpp b/src/swrenderer/viewport/r_spandrawer.cpp index ffc4dfc5f..e5adf5409 100644 --- a/src/swrenderer/viewport/r_spandrawer.cpp +++ b/src/swrenderer/viewport/r_spandrawer.cpp @@ -32,7 +32,7 @@ namespace swrenderer void SpanDrawerArgs::SetTexture(RenderThread *thread, FTexture *tex) { - thread->PrepareTexture(tex); + thread->PrepareTexture(tex, DefaultRenderStyle()); ds_texwidth = tex->GetWidth(); ds_texheight = tex->GetHeight(); @@ -47,7 +47,7 @@ namespace swrenderer ds_ybits--; } - ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(); + ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels(DefaultRenderStyle()); // Get correct render style? Shaded won't get here. ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1; } diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index 0dbb38716..20abfca51 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -43,7 +43,7 @@ namespace swrenderer colfunc = &SWPixelFormatDrawers::DrawColumn; } - void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked) + void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked) { if (x < thread->X1 || x >= thread->X2) return; @@ -67,7 +67,7 @@ namespace swrenderer if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) column = (const uint8_t *)tex->GetColumnBgra(col >> FRACBITS, &span); else - column = tex->GetColumn(col >> FRACBITS, &span); + column = tex->GetColumn(style, col >> FRACBITS, &span); FTexture::Span unmaskedSpan[2]; if (unmasked) diff --git a/src/swrenderer/viewport/r_spritedrawer.h b/src/swrenderer/viewport/r_spritedrawer.h index e1df5e926..f6a3aae79 100644 --- a/src/swrenderer/viewport/r_spritedrawer.h +++ b/src/swrenderer/viewport/r_spritedrawer.h @@ -33,7 +33,7 @@ namespace swrenderer void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; } void SetDynamicLight(uint32_t color) { dynlightcolor = color; } - void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, bool unmasked = false); + void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked = false); void FillColumn(RenderThread *thread); void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount); diff --git a/src/textures/automaptexture.cpp b/src/textures/automaptexture.cpp index 3bd16f5bc..c07eded6e 100644 --- a/src/textures/automaptexture.cpp +++ b/src/textures/automaptexture.cpp @@ -38,6 +38,7 @@ #include "doomtype.h" #include "files.h" #include "w_wad.h" +#include "v_palette.h" #include "textures/textures.h" //========================================================================== @@ -46,21 +47,11 @@ // //========================================================================== -class FAutomapTexture : public FTexture +class FAutomapTexture : public FWorldTexture { public: - ~FAutomapTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - void MakeTexture (); - - FAutomapTexture (int lumpnum); - -private: - uint8_t *Pixels; - Span DummySpan[2]; + FAutomapTexture(int lumpnum); + uint8_t *MakeTexture (FRenderStyle style); }; @@ -86,16 +77,11 @@ FTexture *AutomapTexture_TryCreate(FileReader &data, int lumpnum) //========================================================================== FAutomapTexture::FAutomapTexture (int lumpnum) -: FTexture(NULL, lumpnum), Pixels(NULL) +: FWorldTexture(NULL, lumpnum) { Width = 320; Height = uint16_t(Wads.LumpLength(lumpnum) / 320); CalcBitSize (); - - DummySpan[0].TopOffset = 0; - DummySpan[0].Length = Height; - DummySpan[1].TopOffset = 0; - DummySpan[1].Length = 0; } //========================================================================== @@ -104,84 +90,22 @@ FAutomapTexture::FAutomapTexture (int lumpnum) // //========================================================================== -FAutomapTexture::~FAutomapTexture () -{ - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FAutomapTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FAutomapTexture::MakeTexture () +uint8_t *FAutomapTexture::MakeTexture (FRenderStyle style) { int x, y; FMemLump data = Wads.ReadLump (SourceLump); const uint8_t *indata = (const uint8_t *)data.GetMem(); - Pixels = new uint8_t[Width * Height]; + auto Pixels = new uint8_t[Width * Height]; for (x = 0; x < Width; ++x) { for (y = 0; y < Height; ++y) { - Pixels[x*Height+y] = indata[x+320*y]; + auto p = indata[x + 320 * y]; + Pixels[x*Height + y] = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; } } -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FAutomapTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } return Pixels; } -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FAutomapTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - column %= Width; - } - if (spans_out != NULL) - { - *spans_out = DummySpan; - } - return Pixels + column*Height; -} diff --git a/src/textures/backdroptexture.cpp b/src/textures/backdroptexture.cpp index aec95cc2e..9d9049fae 100644 --- a/src/textures/backdroptexture.cpp +++ b/src/textures/backdroptexture.cpp @@ -56,7 +56,7 @@ // //============================================================================= -struct FBackdropTexture : public FTexture +class FBackdropTexture : public FWorldTexture { enum { @@ -77,15 +77,12 @@ struct FBackdropTexture : public FTexture public: FBackdropTexture(); - const uint8_t *GetColumn(unsigned int column, const Span **spans_out); - const uint8_t *GetPixels(); - void Unload(); - bool CheckModified(); + bool CheckModified(FRenderStyle style) override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: uint32_t costab[COS_SIZE]; - uint8_t *Pixels; - static const Span DummySpan[2]; + uint8_t Pixels[160*144]; int LastRenderTic; uint32_t time1, time2, time3, time4; @@ -170,8 +167,6 @@ static uint8_t pattern2[1024] = 7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5, }; -const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } }; - //============================================================================= // // @@ -180,7 +175,7 @@ const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } }; FBackdropTexture::FBackdropTexture() { - Pixels = nullptr; + PixelsAreStatic = 3; Width = 144; Height = 160; WidthBits = 8; @@ -209,44 +204,19 @@ FBackdropTexture::FBackdropTexture() // //============================================================================= -bool FBackdropTexture::CheckModified() +bool FBackdropTexture::CheckModified(FRenderStyle) { return LastRenderTic != gametic; } -void FBackdropTexture::Unload() -{ - if (Pixels != nullptr) delete[] Pixels; - Pixels = nullptr; -} - //============================================================================= // -// +// There's no point making this work as a regular texture as it is made to +// work with special translations. As an alpha texture it should be fine. // //============================================================================= -const uint8_t *FBackdropTexture::GetColumn(unsigned int column, const Span **spans_out) -{ - if (LastRenderTic != gametic) - { - Render(); - } - column = clamp(column, 0u, 143u); - if (spans_out != nullptr) - { - *spans_out = DummySpan; - } - return Pixels + column*160; -} - -//============================================================================= -// -// -// -//============================================================================= - -const uint8_t *FBackdropTexture::GetPixels() +uint8_t *FBackdropTexture::MakeTexture(FRenderStyle style) { if (LastRenderTic != gametic) { @@ -266,7 +236,6 @@ void FBackdropTexture::Render() uint8_t *from; int width, height, pitch; - if (Pixels == nullptr) Pixels = new uint8_t[160 * 144]; width = 160; height = 144; pitch = width; diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index cdeb645e3..33cfe2141 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -193,13 +193,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step, iCopyColors, \ iCopyColors, \ iCopyColors, \ + iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors \ } -static const CopyFunc copyfuncs[][10]={ +static const CopyFunc copyfuncs[][11]={ COPY_FUNCS(bCopy), COPY_FUNCS(bBlend), COPY_FUNCS(bAdd), diff --git a/src/textures/bitmap.h b/src/textures/bitmap.h index 0811eaa70..51d857ac4 100644 --- a/src/textures/bitmap.h +++ b/src/textures/bitmap.h @@ -235,6 +235,15 @@ struct cCMYK static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; } }; +struct cYCbCr +{ + static __forceinline unsigned char R(const unsigned char * p) { return clamp((int)(p[0] + 1.40200 * (int(p[2]) - 0x80)), 0, 255); } + static __forceinline unsigned char G(const unsigned char * p) { return clamp((int)(p[0] - 0.34414 * (int(p[1] - 0x80)) - 0.71414 * (int(p[2]) - 0x80)), 0, 255); } + static __forceinline unsigned char B(const unsigned char * p) { return clamp((int)(p[0] + 1.77200 * (int(p[1]) - 0x80)), 0, 255); } + static __forceinline unsigned char A(const unsigned char * p, uint8_t x, uint8_t y, uint8_t z) { return 255; } + static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; } +}; + struct cBGR { static __forceinline unsigned char R(const unsigned char * p) { return p[2]; } @@ -310,6 +319,7 @@ enum ColorType CF_RGBA, CF_IA, CF_CMYK, + CF_YCbCr, CF_BGR, CF_BGRA, CF_I16, diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index d23e5e6f2..96e24af21 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -1,9 +1,10 @@ /* ** buildtexture.cpp -** Handling Build textures +** Handling Build textures (now as a usable editing feature!) ** **--------------------------------------------------------------------------- ** Copyright 2004-2006 Randy Heit +** Copyright 2018 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -39,8 +40,13 @@ #include "templates.h" #include "cmdlib.h" #include "st_start.h" +#include "colormatcher.h" +#include "bitmap.h" #include "textures/textures.h" #include "r_data/sprites.h" +#include "r_data/r_translate.h" +#include "resourcefiles/resourcefile.h" + //========================================================================== // @@ -48,18 +54,18 @@ // //========================================================================== -class FBuildTexture : public FTexture +class FBuildTexture : public FWorldTexture { public: - FBuildTexture (int tilenum, const uint8_t *pixels, int width, int height, int left, int top); - ~FBuildTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + FBuildTexture (const FString &pathprefix, int tilenum, const uint8_t *pixels, int translation, int width, int height, int left, int top); + uint8_t *MakeTexture(FRenderStyle style) override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override { return false; } + FTextureFormat GetFormat() override { return TEX_RGB; } protected: - const uint8_t *Pixels; - Span **Spans; + const uint8_t *RawPixels; + int Translation; }; @@ -69,72 +75,37 @@ protected: // //========================================================================== -FBuildTexture::FBuildTexture (int tilenum, const uint8_t *pixels, int width, int height, int left, int top) -: Pixels (pixels), Spans (NULL) +FBuildTexture::FBuildTexture(const FString &pathprefix, int tilenum, const uint8_t *pixels, int translation, int width, int height, int left, int top) +: RawPixels (pixels), Translation(translation) { + PixelsAreStatic = 3; Width = width; Height = height; LeftOffset = left; TopOffset = top; CalcBitSize (); - Name.Format("BTIL%04d", tilenum); - UseType = TEX_Build; + Name.Format("%sBTIL%04d", pathprefix.GetChars(), tilenum); + UseType = TEX_Override; } -//========================================================================== -// -// -// -//========================================================================== - -FBuildTexture::~FBuildTexture () +uint8_t *FBuildTexture::MakeTexture(FRenderStyle style) { - if (Spans != NULL) + auto Pixels = new uint8_t[Width * Height]; + FRemapTable *Remap = translationtables[TRANSLATION_Standard][Translation]; + for (int i = 0; i < Width*Height; i++) { - FreeSpans (Spans); - Spans = NULL; + auto c = RawPixels[i]; + Pixels[i] = (style.Flags & STYLEF_RedIsAlpha) ? Remap->Palette[c].r : Remap->Remap[c]; } + return (uint8_t*)RawPixels; } -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FBuildTexture::GetPixels () +int FBuildTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { - return Pixels; -} + PalEntry *Remap = translationtables[TRANSLATION_Standard][Translation]->Palette; + bmp->CopyPixelData(x, y, RawPixels, Width, Height, Height, 1, rotate, Remap, inf); + return 0; -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FBuildTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (column >= 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; } //=========================================================================== @@ -145,15 +116,16 @@ const uint8_t *FBuildTexture::GetColumn (unsigned int column, const Span **spans // //=========================================================================== -void FTextureManager::AddTiles (void *tiles) +void FTextureManager::AddTiles (const FString &pathprefix, const void *tiles, int translation) { + // int numtiles = LittleLong(((uint32_t *)tiles)[1]); // This value is not reliable int tilestart = LittleLong(((uint32_t *)tiles)[2]); int tileend = LittleLong(((uint32_t *)tiles)[3]); const uint16_t *tilesizx = &((const uint16_t *)tiles)[8]; const uint16_t *tilesizy = &tilesizx[tileend - tilestart + 1]; const uint32_t *picanm = (const uint32_t *)&tilesizy[tileend - tilestart + 1]; - uint8_t *tiledata = (uint8_t *)&picanm[tileend - tilestart + 1]; + const uint8_t *tiledata = (const uint8_t *)&picanm[tileend - tilestart + 1]; for (int i = tilestart; i <= tileend; ++i) { @@ -169,15 +141,12 @@ void FTextureManager::AddTiles (void *tiles) if (width <= 0 || height <= 0) continue; - tex = new FBuildTexture (i, tiledata, width, height, xoffs, yoffs); + tex = new FBuildTexture (pathprefix, i, tiledata, translation, width, height, xoffs, yoffs); texnum = AddTexture (tex); - while (size > 0) - { - *tiledata = 255 - *tiledata; - tiledata++; - size--; - } - StartScreen->Progress(); + tiledata += size; + + // reactivate only if the texture counter works here. + //StartScreen->Progress(); if ((picanm[pic] & 63) && (picanm[pic] & 192)) { @@ -251,7 +220,7 @@ void FTextureManager::AddTiles (void *tiles) // //=========================================================================== -int FTextureManager::CountTiles (void *tiles) +static int CountTiles (const void *tiles) { int version = LittleLong(*(uint32_t *)tiles); if (version != 1) @@ -265,6 +234,60 @@ int FTextureManager::CountTiles (void *tiles) return tileend >= tilestart ? tileend - tilestart + 1 : 0; } +//=========================================================================== +// +// Create palette data and remap table for the tile set's palette +// +//=========================================================================== + +static int BuildPaletteTranslation(int lump) +{ + if (Wads.LumpLength(lump) < 768) + { + return false; + } + + FMemLump data = Wads.ReadLump(lump); + const uint8_t *ipal = (const uint8_t *)data.GetMem(); + FRemapTable opal; + + bool blood = false; + for (int c = 0; c < 765; c++) // Build used VGA palettes (color values 0..63), Blood used full palettes (0..255) Let's hope this doesn't screw up... + { + if (ipal[c] >= 64) + { + blood = true; + break; + } + } + + for (int c = 0; c < 255; c++) + { + int r, g, b; + if (!blood) + { + r = (ipal[3*c ] << 2) | (ipal[3 * c ] >> 4); + g = (ipal[3*c + 1] << 2) | (ipal[3 * c + 1] >> 4); + b = (ipal[3*c + 2] << 2) | (ipal[3 * c + 2] >> 4); + } + else + { + r = ipal[3 * c] << 2; + g = ipal[3 * c + 1] << 2; + b = ipal[3 * c + 2] << 2; + } + opal.Palette[c] = PalEntry(255, r, g, b); + opal.Remap[c] = ColorMatcher.Pick(r, g, b); + } + // The last entry is transparent. + opal.Palette[255] = 0; + opal.Remap[255] = 0; + // Store the remap table in the translation manager so that we do not need to keep track of it ourselves. + // Slot 0 for internal translations is a convenient location because normally it only contains a small number of translations. + return GetTranslationIndex(opal.StoreTranslation(TRANSLATION_Standard)); +} + + //=========================================================================== // // R_CountBuildTiles @@ -274,98 +297,59 @@ int FTextureManager::CountTiles (void *tiles) // //=========================================================================== -int FTextureManager::CountBuildTiles () +void FTextureManager::InitBuildTiles() { - int numartfiles = 0; - char artfile[] = "tilesXXX.art"; int lumpnum; int numtiles; int totaltiles = 0; - lumpnum = Wads.CheckNumForFullName ("blood.pal"); - if (lumpnum >= 0) + // The search rules are as follows: + // - scan the entire lump directory for palette.dat files. + // - if one is found, process the directory for .ART files and add textures for them. + // - once all have been found, process all directories that may contain Build data. + // - the root is not excluded which allows to read this from .GRP files as well. + // - Blood support has been removed because it is not useful for modding to have loose .ART files. + // + // Unfortunately neither the palettes nor the .ART files contain any usable identifying marker + // so this can only go by the file names. + + int numlumps = Wads.GetNumLumps(); + for (int i = 0; i < numlumps; i++) { - // Blood's tiles are external resources. (Why did they do it like that?) - FString rffpath = Wads.GetWadFullName (Wads.GetLumpFile (lumpnum)); - int slashat = rffpath.LastIndexOf ('/'); - if (slashat >= 0) + const char *name = Wads.GetLumpFullName(i); + if (Wads.CheckNumForFullName(name) != i) continue; // This palette is hidden by a later one. Do not process + FString base = ExtractFileBase(name, true); + base.ToLower(); + if (base.Compare("palette.dat") == 0 && Wads.LumpLength(i) >= 768) // must be a valid palette, i.e. at least 256 colors. { - rffpath.Truncate (slashat + 1); - } - else - { - rffpath += '/'; - } + FString path = ExtractFilePath(name); + if (path.IsNotEmpty() && path.Back() != '/') path += '/'; - for (; numartfiles < 1000; numartfiles++) - { - artfile[5] = numartfiles / 100 + '0'; - artfile[6] = numartfiles / 10 % 10 + '0'; - artfile[7] = numartfiles % 10 + '0'; - - FString artpath = rffpath; - artpath += artfile; - - FileReader fr; - - if (!fr.Open(artpath)) + int translation = BuildPaletteTranslation(i); + for (int numartfiles = 0; numartfiles < 1000; numartfiles++) { - break; - } + FStringf artpath("%stiles%03d.art", path.GetChars(), numartfiles); + // only read from the same source as the palette. + // The entire format here is just too volatile to allow liberal mixing. + // An .ART set must be treated as one unit. + lumpnum = Wads.CheckNumForFullName(artpath, Wads.GetLumpFile(i)); + if (lumpnum < 0) + { + break; + } - long len = fr.GetLength(); - uint8_t *art = new uint8_t[len]; - if (fr.Read (art, len) != len || (numtiles = CountTiles(art)) == 0) - { - delete[] art; - } - else - { - BuildTileFiles.Push (art); - totaltiles += numtiles; + BuildTileData.Reserve(1); + auto &artdata = BuildTileData.Last(); + artdata.Resize(Wads.LumpLength(lumpnum)); + Wads.ReadLump(lumpnum, &artdata[0]); + + if ((numtiles = CountTiles(&artdata[0])) > 0) + { + AddTiles(path, &artdata[0], translation); + totaltiles += numtiles; + } } } } - - for (; numartfiles < 1000; numartfiles++) - { - artfile[5] = numartfiles / 100 + '0'; - artfile[6] = numartfiles / 10 % 10 + '0'; - artfile[7] = numartfiles % 10 + '0'; - lumpnum = Wads.CheckNumForFullName (artfile); - if (lumpnum < 0) - { - break; - } - - uint8_t *art = new uint8_t[Wads.LumpLength (lumpnum)]; - Wads.ReadLump (lumpnum, art); - - if ((numtiles = CountTiles(art)) == 0) - { - delete[] art; - } - else - { - BuildTileFiles.Push (art); - totaltiles += numtiles; - } - } - return totaltiles; } -//=========================================================================== -// -// R_InitBuildTiles -// -// [RH] Support Build tiles! -// -//=========================================================================== - -void FTextureManager::InitBuildTiles () -{ - for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) - { - AddTiles (BuildTileFiles[i]); - } -} diff --git a/src/textures/canvastexture.cpp b/src/textures/canvastexture.cpp index d2530017b..e13dd6d3d 100644 --- a/src/textures/canvastexture.cpp +++ b/src/textures/canvastexture.cpp @@ -65,12 +65,12 @@ FCanvasTexture::~FCanvasTexture () Unload (); } -const uint8_t *FCanvasTexture::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FCanvasTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { bNeedsUpdate = true; if (Canvas == NULL) { - MakeTexture (); + MakeTexture (style); } if ((unsigned)column >= (unsigned)Width) { @@ -90,12 +90,12 @@ const uint8_t *FCanvasTexture::GetColumn (unsigned int column, const Span **span return Pixels + column*Height; } -const uint8_t *FCanvasTexture::GetPixels () +const uint8_t *FCanvasTexture::GetPixels (FRenderStyle style) { bNeedsUpdate = true; if (Canvas == NULL) { - MakeTexture (); + MakeTexture (style); } return Pixels; } @@ -110,7 +110,7 @@ const uint32_t *FCanvasTexture::GetPixelsBgra() return PixelsBgra; } -void FCanvasTexture::MakeTexture () +void FCanvasTexture::MakeTexture (FRenderStyle) // This ignores the render style because making it work as alpha texture is impractical. { Canvas = new DSimpleCanvas (Width, Height, false); Canvas->Lock (); @@ -183,7 +183,7 @@ void FCanvasTexture::Unload () FTexture::Unload(); } -bool FCanvasTexture::CheckModified () +bool FCanvasTexture::CheckModified (FRenderStyle) { if (bDidUpdate) { diff --git a/src/textures/ddstexture.cpp b/src/textures/ddstexture.cpp index e340d4e81..313682f14 100644 --- a/src/textures/ddstexture.cpp +++ b/src/textures/ddstexture.cpp @@ -153,22 +153,21 @@ struct DDSFileHeader // //========================================================================== -class FDDSTexture : public FTexture +class FDDSTexture : public FWorldTexture { + enum + { + PIX_Palette = 0, + PIX_Alphatex = 1, + PIX_ARGB = 2 + }; public: FDDSTexture (FileReader &lump, int lumpnum, void *surfdesc); - ~FDDSTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); + FTextureFormat GetFormat () override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: - - uint8_t *Pixels; - Span **Spans; - uint32_t Format; uint32_t RMask, GMask, BMask, AMask; @@ -180,11 +179,10 @@ protected: static void CalcBitShift (uint32_t mask, uint8_t *lshift, uint8_t *rshift); - void MakeTexture (); - void ReadRGB (FWadLump &lump, uint8_t *tcbuf = NULL); - void DecompressDXT1 (FWadLump &lump, uint8_t *tcbuf = NULL); - void DecompressDXT3 (FWadLump &lump, bool premultiplied, uint8_t *tcbuf = NULL); - void DecompressDXT5 (FWadLump &lump, bool premultiplied, uint8_t *tcbuf = NULL); + void ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode); + void DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmode); + void DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); + void DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); bool UseBasePalette(); @@ -203,7 +201,7 @@ static bool CheckDDS (FileReader &file) { DDSFileHeader Header; - file.Seek (0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); if (file.Read (&Header, sizeof(Header)) != sizeof(Header)) { return false; @@ -232,7 +230,7 @@ FTexture *DDSTexture_TryCreate (FileReader &data, int lumpnum) if (!CheckDDS(data)) return NULL; - data.Seek (4, SEEK_SET); + data.Seek(4, FileReader::SeekSet); data.Read (&surfdesc, sizeof(surfdesc)); #ifdef __BIG_ENDIAN__ @@ -287,7 +285,7 @@ FTexture *DDSTexture_TryCreate (FileReader &data, int lumpnum) //========================================================================== FDDSTexture::FDDSTexture (FileReader &lump, int lumpnum, void *vsurfdesc) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0) +: FWorldTexture(NULL, lumpnum) { DDSURFACEDESC2 *surf = (DDSURFACEDESC2 *)vsurfdesc; @@ -381,38 +379,6 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift // //========================================================================== -FDDSTexture::~FDDSTexture () -{ - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDDSTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - FTextureFormat FDDSTexture::GetFormat() { #if 0 @@ -437,88 +403,41 @@ FTextureFormat FDDSTexture::GetFormat() // //========================================================================== -const uint8_t *FDDSTexture::GetColumn (unsigned int column, const Span **spans_out) +uint8_t *FDDSTexture::MakeTexture (FRenderStyle style) { - 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; -} + auto lump = Wads.OpenLumpReader (SourceLump); -//========================================================================== -// -// -// -//========================================================================== + auto Pixels = new uint8_t[Width*Height]; -const uint8_t *FDDSTexture::GetPixels () -{ - if (Pixels == NULL) + lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet); + + int pmode = (style.Flags & STYLEF_RedIsAlpha) ? PIX_Alphatex : PIX_Palette; + if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel { - MakeTexture (); + ReadRGB (lump, Pixels, pmode); + } + else if (Format == ID_DXT1) + { + DecompressDXT1 (lump, Pixels, pmode); + } + else if (Format == ID_DXT3 || Format == ID_DXT2) + { + DecompressDXT3 (lump, Format == ID_DXT2, Pixels, pmode); + } + else if (Format == ID_DXT5 || Format == ID_DXT4) + { + DecompressDXT5 (lump, Format == ID_DXT4, Pixels, pmode); } return Pixels; } //========================================================================== // -// +// Note that pixel size == 8 is column-major, but 32 is row-major! // //========================================================================== -void FDDSTexture::MakeTexture () -{ - FWadLump lump = Wads.OpenLumpNum (SourceLump); - - Pixels = new uint8_t[Width*Height]; - - lump.Seek (sizeof(DDSURFACEDESC2) + 4, SEEK_SET); - - if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel - { - ReadRGB (lump); - } - else if (Format == ID_DXT1) - { - DecompressDXT1 (lump); - } - else if (Format == ID_DXT3 || Format == ID_DXT2) - { - DecompressDXT3 (lump, Format == ID_DXT2); - } - else if (Format == ID_DXT5 || Format == ID_DXT4) - { - DecompressDXT5 (lump, Format == ID_DXT4); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FDDSTexture::ReadRGB (FWadLump &lump, uint8_t *tcbuf) +void FDDSTexture::ReadRGB (FileReader &lump, uint8_t *buffer, int pixelmode) { uint32_t x, y; uint32_t amask = AMask == 0 ? 0 : 0x80000000 >> AShiftL; @@ -527,7 +446,7 @@ void FDDSTexture::ReadRGB (FWadLump &lump, uint8_t *tcbuf) for (y = Height; y > 0; --y) { uint8_t *buffp = linebuff; - uint8_t *pixelp = tcbuf? tcbuf + 4*y*Height : Pixels + y; + uint8_t *pixelp = pixelmode == PIX_ARGB? buffer + 4*y*Height : buffer + y; lump.Read (linebuff, Pitch); for (x = Width; x > 0; --x) { @@ -548,14 +467,21 @@ void FDDSTexture::ReadRGB (FWadLump &lump, uint8_t *tcbuf) { c = *buffp++; } - if (!tcbuf) + if (pixelmode != PIX_ARGB) { if (amask == 0 || (c & amask)) { uint32_t r = (c & RMask) << RShiftL; r |= r >> RShiftR; - uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR; - uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR; - *pixelp = RGB256k.RGB[r >> 26][g >> 26][b >> 26]; + if (pixelmode == PIX_Palette) + { + uint32_t g = (c & GMask) << GShiftL; g |= g >> GShiftR; + uint32_t b = (c & BMask) << BShiftL; b |= b >> BShiftR; + *pixelp = RGB256k.RGB[r >> 26][g >> 26][b >> 26]; + } + else + { + *pixelp = uint8_t(r >> 24); + } } else { @@ -587,13 +513,13 @@ void FDDSTexture::ReadRGB (FWadLump &lump, uint8_t *tcbuf) // //========================================================================== -void FDDSTexture::DecompressDXT1 (FWadLump &lump, uint8_t *tcbuf) +void FDDSTexture::DecompressDXT1 (FileReader &lump, uint8_t *buffer, int pixelmode) { const long blocklinelen = ((Width + 3) >> 2) << 3; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; - uint8_t palcol[4]; + uint8_t palcol[4] = { 0,0,0,0 }; // shut up compiler warnings. int ox, oy, x, y, i; color[0].a = 255; @@ -639,9 +565,12 @@ void FDDSTexture::DecompressDXT1 (FWadLump &lump, uint8_t *tcbuf) bMasked = true; } // Pick colors from the palette for each of the four colors. - /*if (!tcbuf)*/ for (i = 3; i >= 0; --i) + if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; + if (pixelmode == PIX_Palette) + palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; + else + palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. } // Now decode this 4x4 block to the pixel buffer. for (y = 0; y < 4; ++y) @@ -658,13 +587,13 @@ void FDDSTexture::DecompressDXT1 (FWadLump &lump, uint8_t *tcbuf) break; } int ci = (yslice >> (x + x)) & 3; - if (!tcbuf) + if (pixelmode != PIX_ARGB) { - Pixels[oy + y + (ox + x) * Height] = palcol[ci]; + buffer[oy + y + (ox + x) * Height] = palcol[ci]; } else { - uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; + uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4]; tcp[0] = color[ci].r; tcp[1] = color[ci].g; tcp[2] = color[ci].b; @@ -685,13 +614,13 @@ void FDDSTexture::DecompressDXT1 (FWadLump &lump, uint8_t *tcbuf) // //========================================================================== -void FDDSTexture::DecompressDXT3 (FWadLump &lump, bool premultiplied, uint8_t *tcbuf) +void FDDSTexture::DecompressDXT3 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode) { const long blocklinelen = ((Width + 3) >> 2) << 4; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; - uint8_t palcol[4]; + uint8_t palcol[4] = { 0,0,0,0 }; int ox, oy, x, y, i; for (oy = 0; oy < Height; oy += 4) @@ -719,10 +648,14 @@ void FDDSTexture::DecompressDXT3 (FWadLump &lump, bool premultiplied, uint8_t *t color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3; // Pick colors from the palette for each of the four colors. - if (!tcbuf) for (i = 3; i >= 0; --i) + if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - palcol[i] = RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2]; + if (pixelmode == PIX_Palette) + palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; + else + palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. } + // Now decode this 4x4 block to the pixel buffer. for (y = 0; y < 4; ++y) { @@ -738,14 +671,14 @@ void FDDSTexture::DecompressDXT3 (FWadLump &lump, bool premultiplied, uint8_t *t { break; } - if (!tcbuf) + if (pixelmode != PIX_ARGB) { - Pixels[oy + y + (ox + x) * Height] = ((yalphaslice >> (x*4)) & 15) < 8 ? + buffer[oy + y + (ox + x) * Height] = ((yalphaslice >> (x*4)) & 15) < 8 ? (bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3]; } else { - uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; + uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4]; int c = (yslice >> (x + x)) & 3; tcp[0] = color[c].r; tcp[1] = color[c].g; @@ -767,13 +700,13 @@ void FDDSTexture::DecompressDXT3 (FWadLump &lump, bool premultiplied, uint8_t *t // //========================================================================== -void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, uint8_t *tcbuf) +void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t *buffer, int pixelmode) { const long blocklinelen = ((Width + 3) >> 2) << 4; uint8_t *blockbuff = new uint8_t[blocklinelen]; uint8_t *block; PalEntry color[4]; - uint8_t palcol[4]; + uint8_t palcol[4] = { 0,0,0,0 }; uint32_t yalphaslice = 0; int ox, oy, x, y, i; @@ -824,9 +757,12 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, uint8_t *t color[3].b = (color[0].b + color[1].b + color[1].b + 1) / 3; // Pick colors from the palette for each of the four colors. - if (!tcbuf) for (i = 3; i >= 0; --i) + if (pixelmode != PIX_ARGB) for (i = 3; i >= 0; --i) { - palcol[i] = RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2]; + if (pixelmode == PIX_Palette) + palcol[i] = color[i].a ? RGB256k.RGB[color[i].r >> 2][color[i].g >> 2][color[i].b >> 2] : 0; + else + palcol[i] = (color[i].a * color[i].r) / 255; // use the same logic as the hardware renderer. } // Now decode this 4x4 block to the pixel buffer. for (y = 0; y < 4; ++y) @@ -851,14 +787,14 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, uint8_t *t { break; } - if (!tcbuf) + if (pixelmode == 8) { - Pixels[oy + y + (ox + x) * Height] = alpha[((yalphaslice >> (x*3)) & 7)] < 128 ? + buffer[oy + y + (ox + x) * Height] = alpha[((yalphaslice >> (x*3)) & 7)] < 128 ? (bMasked = true, 0) : palcol[(yslice >> (x + x)) & 3]; } else { - uint8_t * tcp = &tcbuf[(ox + x)*4 + (oy + y) * Width*4]; + uint8_t * tcp = &buffer[(ox + x)*4 + (oy + y) * Width*4]; int c = (yslice >> (x + x)) & 3; tcp[0] = color[c].r; tcp[1] = color[c].g; @@ -881,27 +817,27 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, uint8_t *t int FDDSTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) { - FWadLump lump = Wads.OpenLumpNum (SourceLump); + auto lump = Wads.OpenLumpReader (SourceLump); uint8_t *TexBuffer = new uint8_t[4*Width*Height]; - lump.Seek (sizeof(DDSURFACEDESC2) + 4, SEEK_SET); + lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet); if (Format >= 1 && Format <= 4) // RGB: Format is # of bytes per pixel { - ReadRGB (lump, TexBuffer); + ReadRGB (lump, TexBuffer, PIX_ARGB); } else if (Format == ID_DXT1) { - DecompressDXT1 (lump, TexBuffer); + DecompressDXT1 (lump, TexBuffer, PIX_ARGB); } else if (Format == ID_DXT3 || Format == ID_DXT2) { - DecompressDXT3 (lump, Format == ID_DXT2, TexBuffer); + DecompressDXT3 (lump, Format == ID_DXT2, TexBuffer, PIX_ARGB); } else if (Format == ID_DXT5 || Format == ID_DXT4) { - DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer); + DecompressDXT5 (lump, Format == ID_DXT4, TexBuffer, PIX_ARGB); } // All formats decompress to RGBA. diff --git a/src/textures/emptytexture.cpp b/src/textures/emptytexture.cpp index 701380993..19698551f 100644 --- a/src/textures/emptytexture.cpp +++ b/src/textures/emptytexture.cpp @@ -1,7 +1,8 @@ /* -** flattexture.cpp +** emptytexture.cpp ** Texture class for empty placeholder textures ** (essentially patches with dimensions and offsets of (0,0) ) +** These need special treatment because a texture size of 0 is illegal ** **--------------------------------------------------------------------------- ** Copyright 2009 Christoph Oelckers @@ -41,30 +42,21 @@ //========================================================================== // -// A texture defined between F_START and F_END markers +// // //========================================================================== -class FEmptyTexture : public FTexture +class FEmptyTexture : public FWorldTexture { + uint8_t Pixel = 0; public: FEmptyTexture (int lumpnum); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload() {} - -protected: - uint8_t Pixels[1]; - Span DummySpans[1]; + uint8_t *MakeTexture(FRenderStyle style) override; }; - - //========================================================================== // -// Since there is no way to detect the validity of a flat -// they can't be used anywhere else but between F_START and F_END +// // //========================================================================== @@ -72,7 +64,7 @@ FTexture *EmptyTexture_TryCreate(FileReader & file, int lumpnum) { char check[8]; if (file.GetLength() != 8) return NULL; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); if (file.Read(check, 8) != 8) return NULL; if (memcmp(check, "\0\0\0\0\0\0\0\0", 8)) return NULL; @@ -86,15 +78,13 @@ FTexture *EmptyTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FEmptyTexture::FEmptyTexture (int lumpnum) -: FTexture(NULL, lumpnum) +: FWorldTexture(NULL, lumpnum) { bMasked = true; WidthBits = HeightBits = 1; Width = Height = 1; WidthMask = 0; - DummySpans[0].TopOffset = 0; - DummySpans[0].Length = 0; - Pixels[0] = 0; + PixelsAreStatic = 3; } //========================================================================== @@ -103,23 +93,8 @@ FEmptyTexture::FEmptyTexture (int lumpnum) // //========================================================================== -const uint8_t *FEmptyTexture::GetColumn (unsigned int column, const Span **spans_out) +uint8_t *FEmptyTexture::MakeTexture(FRenderStyle style) { - if (spans_out != NULL) - { - *spans_out = DummySpans; - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FEmptyTexture::GetPixels () -{ - return Pixels; + return &Pixel; } diff --git a/src/textures/flattexture.cpp b/src/textures/flattexture.cpp index 6e584f694..7581b3a6e 100644 --- a/src/textures/flattexture.cpp +++ b/src/textures/flattexture.cpp @@ -45,24 +45,11 @@ // //========================================================================== -class FFlatTexture : public FTexture +class FFlatTexture : public FWorldTexture { public: FFlatTexture (int lumpnum); - ~FFlatTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - -protected: - uint8_t *Pixels; - Span DummySpans[2]; - - - void MakeTexture (); - - friend class FTexture; + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -86,7 +73,7 @@ FTexture *FlatTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FFlatTexture::FFlatTexture (int lumpnum) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { int area; int bits; @@ -108,10 +95,6 @@ FFlatTexture::FFlatTexture (int lumpnum) WidthBits = HeightBits = bits; Width = Height = 1 << bits; WidthMask = (1 << bits) - 1; - DummySpans[0].TopOffset = 0; - DummySpans[0].Length = Height; - DummySpans[1].TopOffset = 0; - DummySpans[1].Length = 0; } //========================================================================== @@ -120,87 +103,17 @@ FFlatTexture::FFlatTexture (int lumpnum) // //========================================================================== -FFlatTexture::~FFlatTexture () +uint8_t *FFlatTexture::MakeTexture (FRenderStyle style) { - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FFlatTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FFlatTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - *spans_out = DummySpans; - } - return Pixels + column*Height; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FFlatTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FFlatTexture::MakeTexture () -{ - FWadLump lump = Wads.OpenLumpNum (SourceLump); - Pixels = new uint8_t[Width*Height]; - long numread = lump.Read (Pixels, Width*Height); + auto lump = Wads.OpenLumpReader (SourceLump); + auto Pixels = new uint8_t[Width*Height]; + auto numread = lump.Read (Pixels, Width*Height); if (numread < Width*Height) { memset (Pixels + numread, 0xBB, Width*Height - numread); } - FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap); + if (!(style.Flags & STYLEF_RedIsAlpha)) FTexture::FlipSquareBlockRemap (Pixels, Width, Height, GPalette.Remap); + else FTexture::FlipSquareBlock(Pixels, Width, Height); + return Pixels; } diff --git a/src/textures/imgztexture.cpp b/src/textures/imgztexture.cpp index 1689289d0..e21074055 100644 --- a/src/textures/imgztexture.cpp +++ b/src/textures/imgztexture.cpp @@ -36,6 +36,7 @@ #include "doomtype.h" #include "files.h" #include "w_wad.h" +#include "v_palette.h" #include "textures/textures.h" @@ -47,7 +48,7 @@ // //========================================================================== -class FIMGZTexture : public FTexture +class FIMGZTexture : public FWorldTexture { struct ImageHeader { @@ -62,18 +63,7 @@ class FIMGZTexture : public FTexture public: FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t); - ~FIMGZTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - -protected: - - uint8_t *Pixels; - Span **Spans; - - void MakeTexture (); + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -89,10 +79,13 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum) uint16_t w, h; int16_t l, t; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); if (file.Read(&magic, 4) != 4) return NULL; if (magic != MAKE_ID('I','M','G','Z')) return NULL; - file >> w >> h >> l >> t; + w = file.ReadUInt16(); + h = file.ReadUInt16(); + l = file.ReadInt16(); + t = file.ReadInt16(); return new FIMGZTexture(lumpnum, w, h, l, t); } @@ -103,7 +96,7 @@ FTexture *IMGZTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int16_t t) - : FTexture(NULL, lumpnum), Pixels(0), Spans(0) + : FWorldTexture(NULL, lumpnum) { Wads.GetLumpName (Name, lumpnum); Width = w; @@ -119,88 +112,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 // //========================================================================== -FIMGZTexture::~FIMGZTexture () -{ - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FIMGZTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FIMGZTexture::GetColumn (unsigned int column, const Span **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; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FIMGZTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FIMGZTexture::MakeTexture () +uint8_t *FIMGZTexture::MakeTexture (FRenderStyle style) { FMemLump lump = Wads.ReadLump (SourceLump); const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); @@ -219,7 +131,7 @@ void FIMGZTexture::MakeTexture () int dest_rew = Width * Height - 1; CalcBitSize (); - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; // Convert the source image from row-major to column-major format @@ -229,7 +141,8 @@ void FIMGZTexture::MakeTexture () { for (int x = Width; x != 0; --x) { - *dest_p = *data; + auto p = *data; + *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; dest_p += dest_adv; data++; } @@ -248,8 +161,8 @@ void FIMGZTexture::MakeTexture () { if (runlen != 0) { - uint8_t color = *data; - *dest_p = color; + auto p = *data; + *dest_p = (style.Flags & STYLEF_RedIsAlpha) ? p : GPalette.Remap[p]; dest_p += dest_adv; data++; x--; @@ -279,5 +192,6 @@ void FIMGZTexture::MakeTexture () dest_p -= dest_rew; } } + return Pixels; } diff --git a/src/textures/jpegtexture.cpp b/src/textures/jpegtexture.cpp index 02bb82829..33ecaf148 100644 --- a/src/textures/jpegtexture.cpp +++ b/src/textures/jpegtexture.cpp @@ -82,7 +82,7 @@ void FLumpSourceMgr::InitSource (j_decompress_ptr cinfo) boolean FLumpSourceMgr::FillInputBuffer (j_decompress_ptr cinfo) { FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); - long nbytes = me->Lump->Read (me->Buffer, sizeof(me->Buffer)); + auto nbytes = me->Lump->Read (me->Buffer, sizeof(me->Buffer)); if (nbytes <= 0) { @@ -113,7 +113,7 @@ void FLumpSourceMgr::SkipInputData (j_decompress_ptr cinfo, long num_bytes) else { num_bytes -= (long)me->bytes_in_buffer; - me->Lump->Seek (num_bytes, SEEK_CUR); + me->Lump->Seek (num_bytes, FileReader::SeekCur); FillInputBuffer (cinfo); } } @@ -179,27 +179,15 @@ void JPEG_OutputMessage (j_common_ptr cinfo) // //========================================================================== -class FJPEGTexture : public FTexture +class FJPEGTexture : public FWorldTexture { public: FJPEGTexture (int lumpnum, int width, int height); - ~FJPEGTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); - -protected: - - uint8_t *Pixels; - Span DummySpans[2]; - - void MakeTexture (); - - friend class FTexture; + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -217,7 +205,7 @@ FTexture *JPEGTexture_TryCreate(FileReader & data, int lumpnum) uint8_t b[4]; } first4bytes; - data.Seek(0, SEEK_SET); + data.Seek(0, FileReader::SeekSet); if (data.Read(&first4bytes, 4) < 4) return NULL; if (first4bytes.b[0] != 0xFF || first4bytes.b[1] != 0xD8 || first4bytes.b[2] != 0xFF) @@ -231,7 +219,7 @@ FTexture *JPEGTexture_TryCreate(FileReader & data, int lumpnum) { return NULL; } - data.Seek (BigShort(first4bytes.w[0]) - 2, SEEK_CUR); + data.Seek (BigShort(first4bytes.w[0]) - 2, FileReader::SeekCur); if (data.Read (first4bytes.b + 2, 2) != 2 || first4bytes.b[2] != 0xFF) { return NULL; @@ -259,7 +247,7 @@ FTexture *JPEGTexture_TryCreate(FileReader & data, int lumpnum) //========================================================================== FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { UseType = TEX_MiscPatch; LeftOffset = 0; @@ -269,35 +257,6 @@ FJPEGTexture::FJPEGTexture (int lumpnum, int width, int height) Width = width; Height = height; CalcBitSize (); - - DummySpans[0].TopOffset = 0; - DummySpans[0].Length = Height; - DummySpans[1].TopOffset = 0; - DummySpans[1].Length = 0; -} - -//========================================================================== -// -// -// -//========================================================================== - -FJPEGTexture::~FJPEGTexture () -{ - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FJPEGTexture::Unload () -{ - delete[] Pixels; - Pixels = NULL; - FTexture::Unload(); } //========================================================================== @@ -317,142 +276,123 @@ FTextureFormat FJPEGTexture::GetFormat() // //========================================================================== -const uint8_t *FJPEGTexture::GetColumn (unsigned int column, const Span **spans_out) +uint8_t *FJPEGTexture::MakeTexture (FRenderStyle style) { - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - *spans_out = DummySpans; - } - return Pixels + column*Height; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FJPEGTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FJPEGTexture::MakeTexture () -{ - FWadLump lump = Wads.OpenLumpNum (SourceLump); + auto lump = Wads.OpenLumpReader (SourceLump); JSAMPLE *buff = NULL; + bool doalpha = !!(style.Flags & STYLEF_RedIsAlpha); jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; - Pixels = new uint8_t[Width * Height]; + auto Pixels = new uint8_t[Width * Height]; memset (Pixels, 0xBA, Width * Height); cinfo.err = jpeg_std_error(&jerr); cinfo.err->output_message = JPEG_OutputMessage; cinfo.err->error_exit = JPEG_ErrorExit; jpeg_create_decompress(&cinfo); + + FLumpSourceMgr sourcemgr(&lump, &cinfo); try { - FLumpSourceMgr sourcemgr(&lump, &cinfo); jpeg_read_header(&cinfo, TRUE); if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) + (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || + (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) { - Printf (TEXTCOLOR_ORANGE "Unsupported color format\n"); - throw -1; + Printf(TEXTCOLOR_ORANGE "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } - - jpeg_start_decompress(&cinfo); - - int y = 0; - buff = new uint8_t[cinfo.output_width * cinfo.output_components]; - - while (cinfo.output_scanline < cinfo.output_height) + else { - int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); - uint8_t *in = buff; - uint8_t *out = Pixels + y; - switch (cinfo.out_color_space) + jpeg_start_decompress(&cinfo); + + int y = 0; + buff = new uint8_t[cinfo.output_width * cinfo.output_components]; + + while (cinfo.output_scanline < cinfo.output_height) { - case JCS_RGB: - for (int x = Width; x > 0; --x) + int num_scanlines = jpeg_read_scanlines(&cinfo, &buff, 1); + uint8_t *in = buff; + uint8_t *out = Pixels + y; + switch (cinfo.out_color_space) { - *out = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; - out += Height; - in += 3; - } - break; + case JCS_RGB: + for (int x = Width; x > 0; --x) + { + *out = !doalpha? RGB256k.RGB[in[0] >> 2][in[1] >> 2][in[2] >> 2] : in[0]; + out += Height; + in += 3; + } + break; - case JCS_GRAYSCALE: - for (int x = Width; x > 0; --x) - { - *out = GrayMap[in[0]]; - out += Height; - in += 1; - } - break; + case JCS_GRAYSCALE: + for (int x = Width; x > 0; --x) + { + *out = !doalpha ? FTexture::GrayMap[in[0]] : in[0]; + out += Height; + in += 1; + } + break; - case JCS_CMYK: - // What are you doing using a CMYK image? :) - for (int x = Width; x > 0; --x) - { - // To be precise, these calculations should use 255, but - // 256 is much faster and virtually indistinguishable. - int r = in[3] - (((256-in[0])*in[3]) >> 8); - int g = in[3] - (((256-in[1])*in[3]) >> 8); - int b = in[3] - (((256-in[2])*in[3]) >> 8); - *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; - out += Height; - in += 4; - } - break; + case JCS_CMYK: + // What are you doing using a CMYK image? :) + for (int x = Width; x > 0; --x) + { + // To be precise, these calculations should use 255, but + // 256 is much faster and virtually indistinguishable. + int r = in[3] - (((256 - in[0])*in[3]) >> 8); + if (!doalpha) + { + int g = in[3] - (((256 - in[1])*in[3]) >> 8); + int b = in[3] - (((256 - in[2])*in[3]) >> 8); + *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; + } + else *out = (uint8_t)r; + out += Height; + in += 4; + } + break; - default: - // The other colorspaces were considered above and discarded, - // but GCC will complain without a default for them here. - break; + case JCS_YCbCr: + // Probably useless but since I had the formula available... + for (int x = Width; x > 0; --x) + { + double Y = in[0], Cb = in[1], Cr = in[2]; + int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255); + if (!doalpha) + { + int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); + int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); + *out = RGB256k.RGB[r >> 2][g >> 2][b >> 2]; + } + else *out = (uint8_t)r; + out += Height; + in += 4; + } + break; + + default: + // The other colorspaces were considered above and discarded, + // but GCC will complain without a default for them here. + break; + } + y++; } - y++; + jpeg_finish_decompress(&cinfo); } - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); } catch (int) { - Printf (TEXTCOLOR_ORANGE " in texture %s\n", Name.GetChars()); - jpeg_destroy_decompress(&cinfo); + Printf(TEXTCOLOR_ORANGE "JPEG error in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } + jpeg_destroy_decompress(&cinfo); if (buff != NULL) { delete[] buff; } + return Pixels; } @@ -468,7 +408,7 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC { PalEntry pe[256]; - FWadLump lump = Wads.OpenLumpNum (SourceLump); + auto lump = Wads.OpenLumpReader (SourceLump); JSAMPLE *buff = NULL; jpeg_decompress_struct cinfo; @@ -479,58 +419,66 @@ int FJPEGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FC cinfo.err->error_exit = JPEG_ErrorExit; jpeg_create_decompress(&cinfo); + FLumpSourceMgr sourcemgr(&lump, &cinfo); try { - FLumpSourceMgr sourcemgr(&lump, &cinfo); jpeg_read_header(&cinfo, TRUE); if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || - (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || - (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) + (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || + (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) { - Printf (TEXTCOLOR_ORANGE "Unsupported color format\n"); - throw -1; + Printf(TEXTCOLOR_ORANGE "Unsupported color format in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } - jpeg_start_decompress(&cinfo); - - int yc = 0; - buff = new uint8_t[cinfo.output_height * cinfo.output_width * cinfo.output_components]; - - - while (cinfo.output_scanline < cinfo.output_height) + else { - uint8_t * ptr = buff + cinfo.output_width * cinfo.output_components * yc; - jpeg_read_scanlines(&cinfo, &ptr, 1); - yc++; + jpeg_start_decompress(&cinfo); + + int yc = 0; + buff = new uint8_t[cinfo.output_height * cinfo.output_width * cinfo.output_components]; + + + while (cinfo.output_scanline < cinfo.output_height) + { + uint8_t * ptr = buff + cinfo.output_width * cinfo.output_components * yc; + jpeg_read_scanlines(&cinfo, &ptr, 1); + yc++; + } + + switch (cinfo.out_color_space) + { + case JCS_RGB: + bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, + 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf); + break; + + case JCS_GRAYSCALE: + for (int i = 0; i < 256; i++) pe[i] = PalEntry(255, i, i, i); // default to a gray map + bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height, + 1, cinfo.output_width, rotate, pe, inf); + break; + + case JCS_CMYK: + bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, + 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf); + break; + + case JCS_YCbCr: + bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, + 4, cinfo.output_width * cinfo.output_components, rotate, CF_YCbCr, inf); + break; + + default: + assert(0); + break; + } + jpeg_finish_decompress(&cinfo); } - - switch (cinfo.out_color_space) - { - case JCS_RGB: - bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, - 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB, inf); - break; - - case JCS_GRAYSCALE: - for(int i=0;i<256;i++) pe[i]=PalEntry(255,i,i,i); // default to a gray map - bmp->CopyPixelData(x, y, buff, cinfo.output_width, cinfo.output_height, - 1, cinfo.output_width, rotate, pe, inf); - break; - - case JCS_CMYK: - bmp->CopyPixelDataRGB(x, y, buff, cinfo.output_width, cinfo.output_height, - 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK, inf); - break; - - default: - assert(0); - break; - } - jpeg_finish_decompress(&cinfo); } - catch(int) + catch (int) { - Printf (TEXTCOLOR_ORANGE " in JPEG texture %s\n", Name.GetChars()); + Printf(TEXTCOLOR_ORANGE "JPEG error in %s\n", Wads.GetLumpFullPath(SourceLump).GetChars()); } jpeg_destroy_decompress(&cinfo); if (buff != NULL) delete [] buff; diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 46b652e29..8571f820b 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -148,24 +148,21 @@ struct FPatchLookup // //========================================================================== -class FMultiPatchTexture : public FTexture +class FMultiPatchTexture : public FWorldTexture { public: FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); FMultiPatchTexture (FScanner &sc, int usetype); ~FMultiPatchTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - FTextureFormat GetFormat(); - bool UseBasePalette() ; - void Unload (); - virtual void SetFrontSkyLayer (); + FTextureFormat GetFormat() override; + bool UseBasePalette() override; + virtual void SetFrontSkyLayer () override; - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - int GetSourceLump() { return DefinitionLump; } - FTexture *GetRedirect(bool wantwarped); - FTexture *GetRawTexture(); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + int GetSourceLump() override { return DefinitionLump; } + FTexture *GetRedirect(bool wantwarped) override; + FTexture *GetRawTexture() override; void ResolvePatches(); protected: @@ -198,10 +195,16 @@ protected: int NumParts; TexPart *Parts; TexInit *Inits; - bool bRedirect:1; - bool bTranslucentPatches:1; + bool bRedirect; + bool bTranslucentPatches; + + uint8_t *MakeTexture (FRenderStyle style); + + // The getters must optionally redirect if it's a simple one-patch texture. + const uint8_t *GetPixels(FRenderStyle style) override { return bRedirect ? Parts->Texture->GetPixels(style) : FWorldTexture::GetPixels(style); } + const uint8_t *GetColumn(FRenderStyle style, unsigned int col, const Span **out) override + { return bRedirect ? Parts->Texture->GetColumn(style, col, out) : FWorldTexture::GetColumn(style, col, out); } - void MakeTexture (); private: void CheckForHacks (); @@ -323,11 +326,6 @@ FMultiPatchTexture::~FMultiPatchTexture () delete[] Inits; Inits = nullptr; } - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } } //========================================================================== @@ -345,80 +343,6 @@ void FMultiPatchTexture::SetFrontSkyLayer () bNoRemap0 = true; } -//========================================================================== -// -// FMultiPatchTexture :: Unload -// -//========================================================================== - -void FMultiPatchTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// FMultiPatchTexture :: GetPixels -// -//========================================================================== - -const uint8_t *FMultiPatchTexture::GetPixels () -{ - if (bRedirect) - { - return Parts->Texture->GetPixels (); - } - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// FMultiPatchTexture :: GetColumn -// -//========================================================================== - -const uint8_t *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 @@ -427,7 +351,6 @@ const uint8_t *FMultiPatchTexture::GetColumn (unsigned int column, const Span ** uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork) { - switch (blend.a==0 ? int(blend) : -1) { case BLEND_ICEMAP: @@ -480,39 +403,54 @@ uint8_t *GetBlendMap(PalEntry blend, uint8_t *blendwork) // //========================================================================== -void FMultiPatchTexture::MakeTexture () +uint8_t *FMultiPatchTexture::MakeTexture (FRenderStyle style) { // 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; uint8_t blendwork[256]; - bool hasTranslucent = false; + bool buildrgb = bComplex; - Pixels = new uint8_t[numpix]; + auto Pixels = new uint8_t[numpix]; memset (Pixels, 0, numpix); - for (int i = 0; i < NumParts; ++i) + if (style.Flags & STYLEF_RedIsAlpha) { - if (Parts[i].op != OP_COPY) + // The rules here are as follows: + // A texture uses its palette index as alpha only if it reports to use the base palette. + // In summary this means: + // If a texture is marked 'complex', it will use the red channel. + // If a texture uses non-base-palette patches, it will use the red channel for all pixels, even those coming from a base palette patch. + // If a texture only uses base-palette patches and no compositing effects it will use the palette index. + // + buildrgb = !UseBasePalette(); + } + else + { + // For regular textures we can use paletted compositing if all patches are just being copied because they all can create a paletted buffer. + if (!buildrgb) for (int i = 0; i < NumParts; ++i) { - hasTranslucent = true; + if (Parts[i].op != OP_COPY) + { + buildrgb = true; + } } } - if (!hasTranslucent) - { + if (!buildrgb) + { for (int i = 0; i < NumParts; ++i) { if (Parts[i].Texture->bHasCanvas) continue; // cannot use camera textures as patch. - uint8_t *trans = Parts[i].Translation ? Parts[i].Translation->Remap : NULL; + uint8_t *trans = Parts[i].Translation? Parts[i].Translation->Remap : nullptr; { 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); + Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans, style); } } } @@ -531,7 +469,7 @@ void FMultiPatchTexture::MakeTexture () { if (*out == 0 && in[3] != 0) { - *out = RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2]; + *out = (style.Flags & STYLEF_RedIsAlpha)? in[2]*in[3] : RGB256k.RGB[in[2]>>2][in[1]>>2][in[0]>>2]; } out += Height; in += 4; @@ -539,6 +477,7 @@ void FMultiPatchTexture::MakeTexture () } delete [] buffer; } + return Pixels; } //=========================================================================== @@ -755,14 +694,6 @@ void FMultiPatchTexture::CheckForHacks () break; } } - - if (i == NumParts) - { - for (i = 0; i < NumParts; ++i) - { - Parts[i].Texture->HackHack(256); - } - } } } @@ -814,9 +745,8 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d } { - FWadLump pnames = Wads.OpenLumpNum (patcheslump); - - pnames >> numpatches; + auto pnames = Wads.OpenLumpReader(patcheslump); + numpatches = pnames.ReadUInt32(); // Check whether the amount of names reported is correct. if ((signed)numpatches < 0) diff --git a/src/textures/patchtexture.cpp b/src/textures/patchtexture.cpp index 2393357bd..b4a8e3909 100644 --- a/src/textures/patchtexture.cpp +++ b/src/textures/patchtexture.cpp @@ -39,6 +39,7 @@ #include "templates.h" #include "v_palette.h" #include "textures/textures.h" +#include "r_data/r_translate.h" // posts are runs of non masked source pixels @@ -55,24 +56,13 @@ struct column_t // //========================================================================== -class FPatchTexture : public FTexture +class FPatchTexture : public FWorldTexture { + bool badflag = false; public: FPatchTexture (int lumpnum, patch_t *header); - ~FPatchTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - -protected: - uint8_t *Pixels; - Span **Spans; - bool hackflag; - - - virtual void MakeTexture (); - void HackHack (int newheight); + uint8_t *MakeTexture (FRenderStyle style) override; + void DetectBadPatches(); }; //========================================================================== @@ -86,7 +76,7 @@ static bool CheckIfPatch(FileReader & file) if (file.GetLength() < 13) return false; // minimum length of a valid Doom patch uint8_t *data = new uint8_t[file.GetLength()]; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); file.Read(data, file.GetLength()); const patch_t *foo = (const patch_t *)data; @@ -134,8 +124,11 @@ FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum) patch_t header; if (!CheckIfPatch(file)) return NULL; - file.Seek(0, SEEK_SET); - file >> header.width >> header.height >> header.leftoffset >> header.topoffset; + file.Seek(0, FileReader::SeekSet); + header.width = file.ReadUInt16(); + header.height = file.ReadUInt16(); + header.leftoffset = file.ReadInt16(); + header.topoffset = file.ReadInt16(); return new FPatchTexture(lumpnum, &header); } @@ -146,12 +139,13 @@ FTexture *PatchTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0), hackflag(false) +: FWorldTexture(NULL, lumpnum) { Width = header->width; Height = header->height; LeftOffset = header->leftoffset; TopOffset = header->topoffset; + DetectBadPatches(); CalcBitSize (); } @@ -161,89 +155,7 @@ FPatchTexture::FPatchTexture (int lumpnum, patch_t * header) // //========================================================================== -FPatchTexture::~FPatchTexture () -{ - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FPatchTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FPatchTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FPatchTexture::GetColumn (unsigned int column, const Span **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; -} - - -//========================================================================== -// -// -// -//========================================================================== - -void FPatchTexture::MakeTexture () +uint8_t *FPatchTexture::MakeTexture (FRenderStyle style) { uint8_t *remap, remaptable[256]; int numspans; @@ -255,23 +167,11 @@ void FPatchTexture::MakeTexture () maxcol = (const column_t *)((const uint8_t *)patch + Wads.LumpLength (SourceLump) - 3); - // Check for badly-sized patches -#if 0 // Such textures won't be created so there's no need to check here - if (LittleShort(patch->width) <= 0 || LittleShort(patch->height) <= 0) + if (style.Flags & STYLEF_RedIsAlpha) { - lump = Wads.ReadLump ("-BADPATC"); - patch = (const patch_t *)lump.GetMem(); - Printf (PRINT_BOLD, "Patch %s has a non-positive size.\n", Name); + remap = translationtables[TRANSLATION_Standard][8]->Remap; } - else if (LittleShort(patch->width) > 2048 || LittleShort(patch->height) > 2048) - { - lump = Wads.ReadLump ("-BADPATC"); - patch = (const patch_t *)lump.GetMem(); - Printf (PRINT_BOLD, "Patch %s is too big.\n", Name); - } -#endif - - if (bNoRemap0) + else if (bNoRemap0) { memcpy (remaptable, GPalette.Remap, 256); remaptable[0] = 0; @@ -283,9 +183,9 @@ void FPatchTexture::MakeTexture () } - if (hackflag) + if (badflag) { - Pixels = new uint8_t[Width * Height]; + auto Pixels = new uint8_t[Width * Height]; uint8_t *out; // Draw the image to the buffer @@ -299,7 +199,7 @@ void FPatchTexture::MakeTexture () out++, in++; } } - return; + return Pixels; } // Add a little extra space at the end if the texture's height is not @@ -308,7 +208,7 @@ void FPatchTexture::MakeTexture () numspans = Width; - Pixels = new uint8_t[numpix]; + auto Pixels = new uint8_t[numpix]; memset (Pixels, 0, numpix); // Draw the image to the buffer @@ -352,6 +252,7 @@ void FPatchTexture::MakeTexture () column = (const column_t *)((const uint8_t *)column + column->length + 4); } } + return Pixels; } @@ -361,8 +262,11 @@ void FPatchTexture::MakeTexture () // //========================================================================== -void FPatchTexture::HackHack (int newheight) +void FPatchTexture::DetectBadPatches () { + // The patch must look like it is large enough for the rules to apply to avoid using this on truly empty patches. + if (Wads.LumpLength(SourceLump) < Width * Height / 2) return; + // Check if this patch is likely to be a problem. // It must be 256 pixels tall, and all its columns must have exactly // one post, where each post has a supposed length of 0. @@ -378,29 +282,17 @@ void FPatchTexture::HackHack (int newheight) const column_t *col = (column_t*)((uint8_t*)realpatch+LittleLong(cofs[x])); if (col->topdelta != 0 || col->length != 0) { - break; // It's not bad! + return; // It's not bad! } col = (column_t *)((uint8_t *)col + 256 + 4); if (col->topdelta != 0xFF) { - break; // More than one post in a column! + return; // More than one post in a column! } } - if (x == x2) - { - // If all the columns were checked, it needs fixing. - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - } - - Height = newheight; - LeftOffset = 0; - TopOffset = 0; - - hackflag = true; - bMasked = false; // Hacked textures don't have transparent parts. - } + LeftOffset = 0; + TopOffset = 0; + badflag = true; + bMasked = false; // Hacked textures don't have transparent parts. } } diff --git a/src/textures/pcxtexture.cpp b/src/textures/pcxtexture.cpp index 757877b03..f5635c7a3 100644 --- a/src/textures/pcxtexture.cpp +++ b/src/textures/pcxtexture.cpp @@ -81,32 +81,23 @@ struct PCXHeader // //========================================================================== -class FPCXTexture : public FTexture +class FPCXTexture : public FWorldTexture { public: FPCXTexture (int lumpnum, PCXHeader &); - ~FPCXTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); + FTextureFormat GetFormat () override; - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; protected: - uint8_t *Pixels; - Span DummySpans[2]; - void ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX4bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX8bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr); void ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr, int planes); - virtual void MakeTexture (); - - friend class FTexture; + uint8_t *MakeTexture (FRenderStyle style) override; }; @@ -120,7 +111,7 @@ FTexture * PCXTexture_TryCreate(FileReader & file, int lumpnum) { PCXHeader hdr; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); if (file.Read(&hdr, sizeof(hdr)) != sizeof(hdr)) { return NULL; @@ -141,7 +132,7 @@ FTexture * PCXTexture_TryCreate(FileReader & file, int lumpnum) if (hdr.padding[i] != 0) return NULL; } - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); return new FPCXTexture(lumpnum, hdr); @@ -154,44 +145,12 @@ FTexture * PCXTexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FPCXTexture::FPCXTexture(int lumpnum, PCXHeader & hdr) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { bMasked = false; Width = LittleShort(hdr.xmax) - LittleShort(hdr.xmin) + 1; Height = LittleShort(hdr.ymax) - LittleShort(hdr.ymin) + 1; CalcBitSize(); - - DummySpans[0].TopOffset = 0; - DummySpans[0].Length = Height; - DummySpans[1].TopOffset = 0; - DummySpans[1].Length = 0; -} - -//========================================================================== -// -// -// -//========================================================================== - -FPCXTexture::~FPCXTexture () -{ - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FPCXTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); } //========================================================================== @@ -211,51 +170,6 @@ FTextureFormat FPCXTexture::GetFormat() // //========================================================================== -const uint8_t *FPCXTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - if (WidthMask + 1 == Width) - { - column &= WidthMask; - } - else - { - column %= Width; - } - } - if (spans_out != NULL) - { - *spans_out = DummySpans; - } - return Pixels + column*Height; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FPCXTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - void FPCXTexture::ReadPCX1bit (uint8_t *dst, FileReader & lump, PCXHeader *hdr) { int y, i, bytes; @@ -457,18 +371,19 @@ void FPCXTexture::ReadPCX24bits (uint8_t *dst, FileReader & lump, PCXHeader *hdr // //========================================================================== -void FPCXTexture::MakeTexture() +uint8_t *FPCXTexture::MakeTexture(FRenderStyle style) { uint8_t PaletteMap[256]; PCXHeader header; int bitcount; + bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha); - FWadLump lump = Wads.OpenLumpNum(SourceLump); + auto lump = Wads.OpenLumpReader(SourceLump); lump.Read(&header, sizeof(header)); bitcount = header.bitsPerPixel * header.numColorPlanes; - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; if (bitcount < 24) { @@ -476,7 +391,8 @@ void FPCXTexture::MakeTexture() { for (int i=0;i<16;i++) { - PaletteMap[i] = ColorMatcher.Pick(header.palette[i*3],header.palette[i*3+1],header.palette[i*3+2]); + if (!alphatex) PaletteMap[i] = ColorMatcher.Pick(header.palette[i * 3], header.palette[i * 3 + 1], header.palette[i * 3 + 2]); + else PaletteMap[i] = header.palette[i * 3]; } switch (bitcount) @@ -493,18 +409,18 @@ void FPCXTexture::MakeTexture() } else if (bitcount == 8) { - uint8_t c; - lump.Seek(-769, SEEK_END); - lump >> c; + lump.Seek(-769, FileReader::SeekEnd); + uint8_t c = lump.ReadUInt8(); //if (c !=0x0c) memcpy(PaletteMap, GrayMap, 256); // Fallback for files without palette //else for(int i=0;i<256;i++) { - uint8_t r,g,b; - lump >> r >> g >> b; - PaletteMap[i] = ColorMatcher.Pick(r,g,b); + uint8_t r = lump.ReadUInt8(); + uint8_t g = lump.ReadUInt8(); + uint8_t b = lump.ReadUInt8(); + PaletteMap[i] = !alphatex? ColorMatcher.Pick(r,g,b) : r; } - lump.Seek(sizeof(header), SEEK_SET); + lump.Seek(sizeof(header), FileReader::SeekSet); ReadPCX8bits (Pixels, lump, &header); } if (Width == Height) @@ -529,12 +445,13 @@ void FPCXTexture::MakeTexture() { for(int x=0; x < Width; x++) { - Pixels[y+Height*x] = RGB256k.RGB[row[0]>>2][row[1]>>2][row[2]>>2]; + Pixels[y + Height * x] = !alphatex? RGB256k.RGB[row[0] >> 2][row[1] >> 2][row[2] >> 2] : row[0]; row+=3; } } delete [] buffer; } + return Pixels; } //=========================================================================== @@ -552,7 +469,7 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo int bitcount; uint8_t * Pixels; - FWadLump lump = Wads.OpenLumpNum(SourceLump); + auto lump = Wads.OpenLumpReader(SourceLump); lump.Read(&header, sizeof(header)); @@ -582,9 +499,8 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo } else if (bitcount == 8) { - uint8_t c; - lump.Seek(-769, SEEK_END); - lump >> c; + lump.Seek(-769, FileReader::SeekEnd); + uint8_t c = lump.ReadUInt8(); c=0x0c; // Apparently there's many non-compliant PCXs out there... if (c !=0x0c) { @@ -592,11 +508,12 @@ int FPCXTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo } else for(int i=0;i<256;i++) { - uint8_t r,g,b; - lump >> r >> g >> b; + uint8_t r = lump.ReadUInt8(); + uint8_t g = lump.ReadUInt8(); + uint8_t b = lump.ReadUInt8(); pe[i] = PalEntry(255, r,g,b); } - lump.Seek(sizeof(header), SEEK_SET); + lump.Seek(sizeof(header), FileReader::SeekSet); ReadPCX8bits (Pixels, lump, &header); } bmp->CopyPixelData(x, y, Pixels, Width, Height, 1, Width, rotate, pe, inf); diff --git a/src/textures/pngtexture.cpp b/src/textures/pngtexture.cpp index 63948bcea..00a7ba701 100644 --- a/src/textures/pngtexture.cpp +++ b/src/textures/pngtexture.cpp @@ -48,25 +48,22 @@ // //========================================================================== -class FPNGTexture : public FTexture +class FPNGTexture : public FWorldTexture { public: FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, uint8_t bitdepth, uint8_t colortype, uint8_t interlace); - ~FPNGTexture (); + ~FPNGTexture(); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; + uint8_t *MakeTexture(FRenderStyle style) override; protected: + void ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap); FString SourceFile; - uint8_t *Pixels; - Span **Spans; - FileReader *fr; + FileReader fr; uint8_t BitDepth; uint8_t ColorType; @@ -74,13 +71,10 @@ protected: bool HaveTrans; uint16_t NonPaletteTrans[3]; - uint8_t *PaletteMap; - int PaletteSize; - uint32_t StartOfIDAT; - - void MakeTexture (); - - friend class FTexture; + uint8_t *PaletteMap = nullptr; + int PaletteSize = 0; + uint32_t StartOfIDAT = 0; + uint32_t StartOfPalette = 0; }; @@ -99,14 +93,12 @@ FTexture *PNGTexture_TryCreate(FileReader & data, int lumpnum) uint8_t b[4]; } first4bytes; - uint32_t width, height; - uint8_t bitdepth, colortype, compression, filter, interlace; // This is most likely a PNG, but make sure. (Note that if the // first 4 bytes match, but later bytes don't, we assume it's // a corrupt PNG.) - data.Seek(0, SEEK_SET); + data.Seek(0, FileReader::SeekSet); if (data.Read (first4bytes.b, 4) != 4) return NULL; if (first4bytes.dw != MAKE_ID(137,'P','N','G')) return NULL; if (data.Read (first4bytes.b, 4) != 4) return NULL; @@ -118,9 +110,13 @@ FTexture *PNGTexture_TryCreate(FileReader & data, int lumpnum) // The PNG looks valid so far. Check the IHDR to make sure it's a // type of PNG we support. - data.Read(&width, 4); - data.Read(&height, 4); - data >> bitdepth >> colortype >> compression >> filter >> interlace; + int width = data.ReadInt32BE(); + int height = data.ReadInt32BE(); + uint8_t bitdepth = data.ReadUInt8(); + uint8_t colortype = data.ReadUInt8(); + uint8_t compression = data.ReadUInt8(); + uint8_t filter = data.ReadUInt8(); + uint8_t interlace = data.ReadUInt8(); if (compression != 0 || filter != 0 || interlace > 1) { @@ -136,7 +132,7 @@ FTexture *PNGTexture_TryCreate(FileReader & data, int lumpnum) } // Just for completeness, make sure the PNG has something more than an IHDR. - data.Seek (4, SEEK_CUR); + data.Seek (4, FileReader::SeekSet); data.Read (first4bytes.b, 4); if (first4bytes.dw == 0) { @@ -147,8 +143,7 @@ FTexture *PNGTexture_TryCreate(FileReader & data, int lumpnum) } } - return new FPNGTexture (data, lumpnum, FString(), BigLong((int)width), BigLong((int)height), - bitdepth, colortype, interlace); + return new FPNGTexture (data, lumpnum, FString(), width, height, bitdepth, colortype, interlace); } //========================================================================== @@ -159,8 +154,6 @@ FTexture *PNGTexture_TryCreate(FileReader & data, int lumpnum) FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) { - uint32_t width, height; - uint8_t bitdepth, colortype, compression, filter, interlace; if (M_FindPNGChunk(png, MAKE_ID('I','H','D','R')) == 0) { @@ -168,9 +161,14 @@ FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) } // Check the IHDR to make sure it's a type of PNG we support. - png->File->Read(&width, 4); - png->File->Read(&height, 4); - (*png->File) >> bitdepth >> colortype >> compression >> filter >> interlace; + auto &data = png->File; + int width = data.ReadInt32BE(); + int height = data.ReadInt32BE(); + uint8_t bitdepth = data.ReadUInt8(); + uint8_t colortype = data.ReadUInt8(); + uint8_t compression = data.ReadUInt8(); + uint8_t filter = data.ReadUInt8(); + uint8_t interlace = data.ReadUInt8(); if (compression != 0 || filter != 0 || interlace > 1) { @@ -185,8 +183,7 @@ FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) return NULL; } - return new FPNGTexture (*png->File, -1, filename, BigLong((int)width), BigLong((int)height), - bitdepth, colortype, interlace); + return new FPNGTexture (png->File, -1, filename, width, height, bitdepth, colortype, interlace); } //========================================================================== @@ -197,9 +194,8 @@ FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename) FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename, int width, int height, uint8_t depth, uint8_t colortype, uint8_t interlace) -: FTexture(NULL, lumpnum), SourceFile(filename), Pixels(0), Spans(0), - BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false), - PaletteMap(0), PaletteSize(0), StartOfIDAT(0) +: FWorldTexture(NULL, lumpnum), SourceFile(filename), + BitDepth(depth), ColorType(colortype), Interlace(interlace), HaveTrans(false) { union { @@ -210,9 +206,6 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename uint32_t len, id; int i; - if (lumpnum == -1) fr = &lump; - else fr = nullptr; - UseType = TEX_MiscPatch; LeftOffset = 0; TopOffset = 0; @@ -225,7 +218,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename memset(trans, 255, 256); // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? - lump.Seek(33, SEEK_SET); + lump.Seek(33, FileReader::SeekSet); lump.Read(&len, 4); lump.Read(&id, 4); @@ -235,7 +228,7 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename switch (id) { default: - lump.Seek (len, SEEK_CUR); + lump.Seek (len, FileReader::SeekCur); break; case MAKE_ID('g','r','A','b'): @@ -265,10 +258,11 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename case MAKE_ID('P','L','T','E'): PaletteSize = MIN (len / 3, 256); + StartOfPalette = (uint32_t)lump.Tell(); lump.Read (p.pngpal, PaletteSize * 3); if (PaletteSize * 3 != (int)len) { - lump.Seek (len - PaletteSize * 3, SEEK_CUR); + lump.Seek (len - PaletteSize * 3, FileReader::SeekCur); } for (i = PaletteSize - 1; i >= 0; --i) { @@ -284,18 +278,13 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename NonPaletteTrans[1] = uint16_t(trans[2] * 256 + trans[3]); NonPaletteTrans[2] = uint16_t(trans[4] * 256 + trans[5]); break; - - case MAKE_ID('a','l','P','h'): - bAlphaTexture = true; - bMasked = true; - break; } - lump.Seek(4, SEEK_CUR); // Skip CRC + lump.Seek(4, FileReader::SeekCur); // Skip CRC lump.Read(&len, 4); id = MAKE_ID('I','E','N','D'); lump.Read(&id, 4); } - StartOfIDAT = lump.Tell() - 8; + StartOfIDAT = (uint32_t)lump.Tell() - 8; switch (colortype) { @@ -304,20 +293,17 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename // intentional fall-through case 0: // Grayscale - if (!bAlphaTexture) + if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) { - if (colortype == 0 && HaveTrans && NonPaletteTrans[0] < 256) - { - bMasked = true; - PaletteSize = 256; - PaletteMap = new uint8_t[256]; - memcpy (PaletteMap, GrayMap, 256); - PaletteMap[NonPaletteTrans[0]] = 0; - } - else - { - PaletteMap = GrayMap; - } + bMasked = true; + PaletteSize = 256; + PaletteMap = new uint8_t[256]; + memcpy (PaletteMap, GrayMap, 256); + PaletteMap[NonPaletteTrans[0]] = 0; + } + else + { + PaletteMap = GrayMap; } break; @@ -342,6 +328,8 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename bMasked = HaveTrans; break; } + // If this is a savegame we must keep the reader. + if (lumpnum == -1) fr = std::move(lump); } //========================================================================== @@ -352,16 +340,10 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, const FString &filename FPNGTexture::~FPNGTexture () { - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } - if (PaletteMap != NULL && PaletteMap != GrayMap) + if (PaletteMap != nullptr && PaletteMap != FTexture::GrayMap) { delete[] PaletteMap; - PaletteMap = NULL; + PaletteMap = nullptr; } } @@ -371,19 +353,6 @@ FPNGTexture::~FPNGTexture () // //========================================================================== -void FPNGTexture::Unload () -{ - delete[] Pixels; - Pixels = NULL; - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - FTextureFormat FPNGTexture::GetFormat() { #if 0 @@ -405,32 +374,18 @@ FTextureFormat FPNGTexture::GetFormat() // //========================================================================== -const uint8_t *FPNGTexture::GetColumn (unsigned int column, const Span **spans_out) +void FPNGTexture::ReadAlphaRemap(FileReader *lump, uint8_t *alpharemap) { - if (Pixels == NULL) + auto p = lump->Tell(); + lump->Seek(StartOfPalette, FileReader::SeekSet); + for (int i = 0; i < PaletteSize; i++) { - MakeTexture (); + uint8_t r = lump->ReadUInt8(); + lump->ReadUInt8(); // Skip g and b. + lump->ReadUInt8(); + alpharemap[i] = PaletteMap[i] == 0? 0 : r; } - 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; + lump->Seek(p, FileReader::SeekSet); } //========================================================================== @@ -439,36 +394,23 @@ const uint8_t *FPNGTexture::GetColumn (unsigned int column, const Span **spans_o // //========================================================================== -const uint8_t *FPNGTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - - -//========================================================================== -// -// -// -//========================================================================== - -void FPNGTexture::MakeTexture () +uint8_t *FPNGTexture::MakeTexture (FRenderStyle style) { FileReader *lump; + FileReader lfr; + bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha); if (SourceLump >= 0) { - lump = new FWadLump(Wads.OpenLumpNum(SourceLump)); + lfr = Wads.OpenLumpReader(SourceLump); + lump = 𝔩 } else { - lump = fr;// new FileReader(SourceFile.GetChars()); + lump = &fr; } - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; if (StartOfIDAT == 0) { memset (Pixels, 0x99, Width*Height); @@ -476,35 +418,47 @@ void FPNGTexture::MakeTexture () else { uint32_t len, id; - lump->Seek (StartOfIDAT, SEEK_SET); + lump->Seek (StartOfIDAT, FileReader::SeekSet); lump->Read(&len, 4); lump->Read(&id, 4); if (ColorType == 0 || ColorType == 3) /* Grayscale and paletted */ { - M_ReadIDAT (lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); + M_ReadIDAT (*lump, Pixels, Width, Height, Width, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); if (Width == Height) { - if (PaletteMap != NULL) + if (!alphatex) { - FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap); + FTexture::FlipSquareBlockRemap (Pixels, Width, Height, PaletteMap); + } + else if (ColorType == 0) + { + FTexture::FlipSquareBlock (Pixels, Width, Height); } else { - FlipSquareBlock (Pixels, Width, Height); + uint8_t alpharemap[256]; + ReadAlphaRemap(lump, alpharemap); + FTexture::FlipSquareBlockRemap(Pixels, Width, Height, alpharemap); } } else { uint8_t *newpix = new uint8_t[Width*Height]; - if (PaletteMap != NULL) + if (!alphatex) { - FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, Width, PaletteMap); + FTexture::FlipNonSquareBlockRemap (newpix, Pixels, Width, Height, Width, PaletteMap); + } + else if (ColorType == 0) + { + FTexture::FlipNonSquareBlock (newpix, Pixels, Width, Height, Width); } else { - FlipNonSquareBlock (newpix, Pixels, Width, Height, Width); + uint8_t alpharemap[256]; + ReadAlphaRemap(lump, alpharemap); + FTexture::FlipNonSquareBlockRemap(newpix, Pixels, Width, Height, Width, alpharemap); } uint8_t *oldpix = Pixels; Pixels = newpix; @@ -518,7 +472,7 @@ void FPNGTexture::MakeTexture () uint8_t *in, *out; int x, y, pitch, backstep; - M_ReadIDAT (lump, tempix, Width, Height, Width*bytesPerPixel, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); + M_ReadIDAT (*lump, tempix, Width, Height, Width*bytesPerPixel, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); in = tempix; out = Pixels; @@ -533,22 +487,13 @@ void FPNGTexture::MakeTexture () { for (y = Height; y > 0; --y) { - if (!HaveTrans) + if (HaveTrans && in[0] == NonPaletteTrans[0] && in[1] == NonPaletteTrans[1] && in[2] == NonPaletteTrans[2]) { - *out++ = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; + *out++ = 0; } else { - if (in[0] == NonPaletteTrans[0] && - in[1] == NonPaletteTrans[1] && - in[2] == NonPaletteTrans[2]) - { - *out++ = 0; - } - else - { - *out++ = RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; - } + *out++ = alphatex? in[0] : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; } in += pitch; } @@ -559,29 +504,14 @@ void FPNGTexture::MakeTexture () case 4: // Grayscale + Alpha pitch = Width * 2; backstep = Height * pitch - 2; - if (PaletteMap != NULL) + for (x = Width; x > 0; --x) { - for (x = Width; x > 0; --x) + for (y = Height; y > 0; --y) { - for (y = Height; y > 0; --y) - { - *out++ = in[1] < 128 ? 0 : PaletteMap[in[0]]; - in += pitch; - } - in -= backstep; - } - } - else - { - for (x = Width; x > 0; --x) - { - for (y = Height; y > 0; --y) - { - *out++ = in[1] < 128 ? 0 : in[0]; - in += pitch; - } - in -= backstep; + *out++ = alphatex? ((in[0] * in[1]) >> 8) : in[1] < 128 ? 0 : PaletteMap[in[0]]; + in += pitch; } + in -= backstep; } break; @@ -592,7 +522,7 @@ void FPNGTexture::MakeTexture () { for (y = Height; y > 0; --y) { - *out++ = in[3] < 128 ? 0 : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; + *out++ = alphatex? ((in[0] * in[3]) >> 8) : in[3] < 128 ? 0 : RGB256k.RGB[in[0]>>2][in[1]>>2][in[2]>>2]; in += pitch; } in -= backstep; @@ -602,7 +532,7 @@ void FPNGTexture::MakeTexture () delete[] tempix; } } - if (lump != fr) delete lump; + return Pixels; } //=========================================================================== @@ -616,21 +546,24 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo // Parse pre-IDAT chunks. I skip the CRCs. Is that bad? PalEntry pe[256]; uint32_t len, id; - FileReader *lump; static char bpp[] = {1, 0, 3, 1, 2, 0, 4}; int pixwidth = Width * bpp[ColorType]; int transpal = false; + FileReader *lump; + FileReader lfr; + if (SourceLump >= 0) { - lump = new FWadLump(Wads.OpenLumpNum(SourceLump)); + lfr = Wads.OpenLumpReader(SourceLump); + lump = 𝔩 } else { - lump = fr;// new FileReader(SourceFile.GetChars()); + lump = &fr; } - lump->Seek(33, SEEK_SET); + lump->Seek(33, FileReader::SeekSet); for(int i = 0; i < 256; i++) // default to a gray map pe[i] = PalEntry(255,i,i,i); @@ -642,13 +575,15 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo switch (id) { default: - lump->Seek (len, SEEK_CUR); + lump->Seek (len, FileReader::SeekCur); break; case MAKE_ID('P','L','T','E'): for(int i = 0; i < PaletteSize; i++) { - (*lump) >> pe[i].r >> pe[i].g >> pe[i].b; + pe[i].r = lump->ReadUInt8(); + pe[i].g = lump->ReadUInt8(); + pe[i].b = lump->ReadUInt8(); } break; @@ -657,18 +592,18 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo { for(uint32_t i = 0; i < len; i++) { - (*lump) >> pe[i].a; + pe[i].a = lump->ReadUInt8(); if (pe[i].a != 0 && pe[i].a != 255) transpal = true; } } else { - lump->Seek(len, SEEK_CUR); + lump->Seek(len, FileReader::SeekCur); } break; } - lump->Seek(4, SEEK_CUR); // Skip CRC + lump->Seek(4, FileReader::SeekCur); // Skip CRC lump->Read(&len, 4); id = MAKE_ID('I','E','N','D'); lump->Read(&id, 4); @@ -682,11 +617,10 @@ int FPNGTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCo uint8_t * Pixels = new uint8_t[pixwidth * Height]; - lump->Seek (StartOfIDAT, SEEK_SET); + lump->Seek (StartOfIDAT, FileReader::SeekSet); lump->Read(&len, 4); lump->Read(&id, 4); - M_ReadIDAT (lump, Pixels, Width, Height, pixwidth, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); - if (lump != fr) delete lump; + M_ReadIDAT (*lump, Pixels, Width, Height, pixwidth, BitDepth, ColorType, Interlace, BigLong((unsigned int)len)); switch (ColorType) { diff --git a/src/textures/rawpagetexture.cpp b/src/textures/rawpagetexture.cpp index bdcebbbaf..adf8abfff 100644 --- a/src/textures/rawpagetexture.cpp +++ b/src/textures/rawpagetexture.cpp @@ -46,21 +46,11 @@ // //========================================================================== -class FRawPageTexture : public FTexture +class FRawPageTexture : public FWorldTexture { public: FRawPageTexture (int lumpnum); - ~FRawPageTexture (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - -protected: - uint8_t *Pixels; - static const Span DummySpans[2]; - - void MakeTexture (); + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -80,7 +70,7 @@ static bool CheckIfRaw(FileReader & data) int width; foo = (patch_t *)M_Malloc (data.GetLength()); - data.Seek (0, SEEK_SET); + data.Seek (0, FileReader::SeekSet); data.Read (foo, data.GetLength()); height = LittleShort(foo->height); @@ -155,17 +145,6 @@ FTexture *RawPageTexture_TryCreate(FileReader & file, int lumpnum) } -//========================================================================== -// -// -// -//========================================================================== - -const FTexture::Span FRawPageTexture::DummySpans[2] = -{ - { 0, 200 }, { 0, 0 } -}; - //========================================================================== // // @@ -173,7 +152,7 @@ const FTexture::Span FRawPageTexture::DummySpans[2] = //========================================================================== FRawPageTexture::FRawPageTexture (int lumpnum) -: FTexture(NULL, lumpnum), Pixels(0) +: FWorldTexture(NULL, lumpnum) { Width = 320; Height = 200; @@ -188,79 +167,14 @@ FRawPageTexture::FRawPageTexture (int lumpnum) // //========================================================================== -FRawPageTexture::~FRawPageTexture () -{ - Unload (); -} - -//========================================================================== -// -// -// -//========================================================================== - -void FRawPageTexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FRawPageTexture::GetColumn (unsigned int column, const Span **spans_out) -{ - if (Pixels == NULL) - { - MakeTexture (); - } - if ((unsigned)column >= (unsigned)Width) - { - column %= 320; - } - if (spans_out != NULL) - { - *spans_out = DummySpans; - } - return Pixels + column*Height; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FRawPageTexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FRawPageTexture::MakeTexture () +uint8_t *FRawPageTexture::MakeTexture (FRenderStyle style) { FMemLump lump = Wads.ReadLump (SourceLump); const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *source_p = source; uint8_t *dest_p; - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; dest_p = Pixels; // Convert the source image from row-major to column-major format @@ -268,11 +182,12 @@ void FRawPageTexture::MakeTexture () { for (int x = 320; x != 0; --x) { - *dest_p = GPalette.Remap[*source_p]; + *dest_p = (style.Flags & STYLEF_RedIsAlpha)? *source_p : GPalette.Remap[*source_p]; dest_p += 200; source_p++; } dest_p -= 200*320-1; } + return Pixels; } diff --git a/src/textures/shadertexture.cpp b/src/textures/shadertexture.cpp index 93e423470..67d4db683 100644 --- a/src/textures/shadertexture.cpp +++ b/src/textures/shadertexture.cpp @@ -49,9 +49,11 @@ #include "r_defs.h" #include "r_state.h" #include "r_data/r_translate.h" +#include "r_data/renderstyle.h" +#include "bitmap.h" -class FBarShader : public FTexture +class FBarShader : public FWorldTexture { public: FBarShader(bool vertical, bool reverse) @@ -62,6 +64,7 @@ public: Width = vertical ? 2 : 256; Height = vertical ? 256 : 2; CalcBitSize(); + PixelsAreStatic = 2; // The alpha buffer is static, but if this gets used as a regular texture, a separate buffer needs to be made. // Fill the column/row with shading values. // Vertical shaders have have minimum alpha at the top @@ -106,24 +109,42 @@ public: } } } - DummySpan[0].TopOffset = 0; - DummySpan[0].Length = vertical ? 256 : 2; - DummySpan[1].TopOffset = 0; - DummySpan[1].Length = 0; } - const uint8_t *GetColumn(unsigned int column, const Span **spans_out) + + uint8_t *MakeTexture(FRenderStyle style) override { - if (spans_out != NULL) + if (style.Flags & STYLEF_RedIsAlpha) { - *spans_out = DummySpan; + return Pixels; + } + else + { + // Since this presents itself to the game as a regular named texture + // it can easily be used on walls and flats and should work as such, + // even if it makes little sense. + auto Pix = new uint8_t[512]; + for (int i = 0; i < 512; i++) + { + Pix[i] = GrayMap[Pixels[i]]; + } + return Pix; } - return Pixels + ((column & WidthMask) << HeightBits); } - const uint8_t *GetPixels() { return Pixels; } - void Unload() {} + + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override + { + bmp->CopyPixelData(x, y, Pixels, Width, Height, Height, 1, rotate, translationtables[TRANSLATION_Standard][8]->Palette, inf); + return 0; + } + + bool UseBasePalette() override + { + return false; + } + + private: uint8_t Pixels[512]; - Span DummySpan[2]; }; diff --git a/src/textures/skyboxtexture.cpp b/src/textures/skyboxtexture.cpp index 9c3b21b67..5270af937 100644 --- a/src/textures/skyboxtexture.cpp +++ b/src/textures/skyboxtexture.cpp @@ -59,9 +59,9 @@ FSkyBox::~FSkyBox() // //----------------------------------------------------------------------------- -const uint8_t *FSkyBox::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FSkyBox::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { - if (faces[0]) return faces[0]->GetColumn(column, spans_out); + if (faces[0]) return faces[0]->GetColumn(style, column, spans_out); return NULL; } @@ -71,9 +71,9 @@ const uint8_t *FSkyBox::GetColumn (unsigned int column, const Span **spans_out) // //----------------------------------------------------------------------------- -const uint8_t *FSkyBox::GetPixels () +const uint8_t *FSkyBox::GetPixels (FRenderStyle style) { - if (faces[0]) return faces[0]->GetPixels(); + if (faces[0]) return faces[0]->GetPixels(style); return NULL; } diff --git a/src/textures/skyboxtexture.h b/src/textures/skyboxtexture.h index 3a4edd042..a6048ce58 100644 --- a/src/textures/skyboxtexture.h +++ b/src/textures/skyboxtexture.h @@ -17,8 +17,8 @@ public: FSkyBox(); ~FSkyBox(); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf); bool UseBasePalette(); void Unload (); diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index b446c43c6..2b6ec321c 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -47,7 +47,6 @@ #include "textures/textures.h" #include "v_palette.h" -typedef bool (*CheckFunc)(FileReader & file); typedef FTexture * (*CreateFunc)(FileReader & file, int lumpnum); struct TexCreateInfo @@ -99,7 +98,7 @@ FTexture * FTexture::CreateTexture (int lumpnum, int usetype) if (lumpnum == -1) return NULL; - FWadLump data = Wads.OpenLumpNum (lumpnum); + auto data = Wads.OpenLumpReader (lumpnum); for(size_t i = 0; i < countof(CreateInfo); i++) { @@ -184,19 +183,20 @@ void FTexture::Unload() const uint32_t *FTexture::GetColumnBgra(unsigned int column, const Span **spans_out) { const uint32_t *pixels = GetPixelsBgra(); + if (pixels == nullptr) return nullptr; column %= Width; if (spans_out != nullptr) - GetColumn(column, spans_out); + GetColumn(DefaultRenderStyle(), column, spans_out); // This isn't the right way to create the spans. return pixels + column * Height; } const uint32_t *FTexture::GetPixelsBgra() { - if (PixelsBgra.empty() || CheckModified()) + if (PixelsBgra.empty() || CheckModified(DefaultRenderStyle())) { - if (!GetColumn(0, nullptr)) + if (!GetColumn(DefaultRenderStyle(), 0, nullptr)) return nullptr; FBitmap bitmap; @@ -207,7 +207,7 @@ const uint32_t *FTexture::GetPixelsBgra() return PixelsBgra.data(); } -bool FTexture::CheckModified () +bool FTexture::CheckModified (FRenderStyle) { return false; } @@ -249,10 +249,6 @@ void FTexture::CalcBitSize () HeightBits = i; } -void FTexture::HackHack (int newheight) -{ -} - FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const { Span **spans, *span; @@ -287,6 +283,7 @@ FTexture::Span **FTexture::CreateSpans (const uint8_t *pixels) const newspan = true; for (y = numrows; y > 0; --y) { + if (*data_p++ == 0) { if (!newspan) @@ -555,14 +552,15 @@ void FTexture::GenerateBgraMipmapsFast() } } -void FTexture::CopyToBlock (uint8_t *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const uint8_t *translation) +void FTexture::CopyToBlock (uint8_t *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const uint8_t *translation, FRenderStyle style) { - const uint8_t *pixels = GetPixels(); + const uint8_t *pixels = GetPixels(style); int srcwidth = Width; int srcheight = Height; int step_x = Height; int step_y = 1; FClipRect cr = {0, 0, dwidth, dheight}; + if (style.Flags & STYLEF_RedIsAlpha) translation = nullptr; // do not apply translations to alpha textures. if (ClipCopyPixelRect(&cr, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate)) { @@ -724,7 +722,7 @@ FNativeTexture *FTexture::GetNative(bool wrapping) } else { - if (CheckModified()) + if (CheckModified(DefaultRenderStyle())) { Native->Update(); } @@ -744,12 +742,6 @@ void FTexture::KillNative() } } -// For this generic implementation, we just call GetPixels and copy that data -// to the buffer. Texture formats that can do better than paletted images -// should provide their own implementation that may preserve the original -// color data. Note that the buffer expects row-major data, since that's -// generally more convenient for any non-Doom image formats, and it doesn't -// need to be used by any of Doom's column drawing routines. void FTexture::FillBuffer(uint8_t *buff, int pitch, int height, FTextureFormat fmt) { const uint8_t *pix; @@ -762,7 +754,7 @@ void FTexture::FillBuffer(uint8_t *buff, int pitch, int height, FTextureFormat f { case TEX_Pal: case TEX_Gray: - pix = GetPixels(); + pix = GetPixels(DefaultRenderStyle()); stride = pitch - w; for (y = 0; y < h; ++y) { @@ -806,14 +798,14 @@ int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyI { PalEntry *palette = screen->GetPalette(); for(int i=1;i<256;i++) palette[i].a = 255; // set proper alpha values - bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette, inf); + bmp->CopyPixelData(x, y, GetPixels(DefaultRenderStyle()), Width, Height, Height, 1, rotate, palette, inf); for(int i=1;i<256;i++) palette[i].a = 0; return 0; } int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, PalEntry *remap, FCopyInfo *inf) { - bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, remap, inf); + bmp->CopyPixelData(x, y, GetPixels(DefaultRenderStyle()), Width, Height, Height, 1, rotate, remap, inf); return 0; } @@ -924,7 +916,7 @@ int FTexture::CheckRealHeight() for (int i = 0; i < GetWidth(); ++i) { - GetColumn(i, &span); + GetColumn(DefaultRenderStyle(), i, &span); while (span->Length != 0) { if (span->TopOffset < miny) @@ -964,16 +956,15 @@ void FDummyTexture::SetSize (int width, int height) CalcBitSize (); } -// This must never be called -const uint8_t *FDummyTexture::GetColumn (unsigned int column, const Span **spans_out) +// These only get called from the texture precacher which discards the result. +const uint8_t *FDummyTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) { - return NULL; + return nullptr; } -// And this also must never be called -const uint8_t *FDummyTexture::GetPixels () +const uint8_t *FDummyTexture::GetPixels(FRenderStyle style) { - return NULL; + return nullptr; } //========================================================================== @@ -1000,7 +991,7 @@ CCMD (printspans) { const FTexture::Span *spans; Printf ("%4d:", x); - tex->GetColumn (x, &spans); + tex->GetColumn(DefaultRenderStyle(), x, &spans); while (spans->Length != 0) { Printf (" (%4d,%4d)", spans->TopOffset, spans->TopOffset+spans->Length-1); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 613aa3be9..b16b5bd5e 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -137,12 +137,7 @@ void FTextureManager::DeleteAll() } } mAnimatedDoors.Clear(); - - for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) - { - delete[] BuildTileFiles[i]; - } - BuildTileFiles.Clear(); + BuildTileData.Clear(); } //========================================================================== @@ -764,16 +759,16 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) void FTextureManager::AddPatches (int lumpnum) { - FWadLump *file = Wads.ReopenLumpNum (lumpnum); + auto file = Wads.ReopenLumpReader (lumpnum, true); uint32_t numpatches, i; char name[9]; - *file >> numpatches; + numpatches = file.ReadUInt32(); name[8] = '\0'; for (i = 0; i < numpatches; ++i) { - file->Read (name, 8); + file.Read (name, 8); if (CheckForTexture (name, FTexture::TEX_WallPatch, 0) == -1) { @@ -781,8 +776,6 @@ void FTextureManager::AddPatches (int lumpnum) } StartScreen->Progress(); } - - delete file; } @@ -984,8 +977,7 @@ void FTextureManager::Init() { DeleteAll(); SpriteFrames.Clear(); - // Init Build Tile data if it hasn't been done already - if (BuildTileFiles.Size() == 0) CountBuildTiles (); + //if (BuildTileFiles.Size() == 0) CountBuildTiles (); FTexture::InitGrayMap(); // Texture 0 is a dummy texture used to indicate "no texture" @@ -1133,7 +1125,7 @@ int FTextureManager::GuesstimateNumTextures () } } - numtex += CountBuildTiles (); + //numtex += CountBuildTiles (); // this cannot be done with a lot of overhead so just leave it out. numtex += CountTexturesX (); return numtex; } @@ -1187,10 +1179,9 @@ int FTextureManager::CountLumpTextures (int lumpnum) { if (lumpnum >= 0) { - FWadLump file = Wads.OpenLumpNum (lumpnum); - uint32_t numtex; + auto file = Wads.OpenLumpReader (lumpnum); + uint32_t numtex = file.ReadUInt32();; - file >> numtex; return int(numtex) >= 0 ? numtex : 0; } return 0; diff --git a/src/textures/textures.h b/src/textures/textures.h index c80abf87b..52fd089c8 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -37,6 +37,7 @@ #include "doomtype.h" #include "vectors.h" +#include "r_data/renderstyle.h" #include struct FloatRect @@ -147,8 +148,6 @@ struct patch_t // the [0] is &columnofs[width] }; -class FileReader; - // All FTextures present their data to the world in 8-bit format, but if // the source data is something else, this is it. enum FTextureFormat @@ -208,7 +207,6 @@ public: TEX_Flat, TEX_Sprite, TEX_WallPatch, - TEX_Build, TEX_SkinSprite, TEX_Decal, TEX_MiscPatch, @@ -227,13 +225,13 @@ public: }; // Returns a single column of the texture - virtual const uint8_t *GetColumn (unsigned int column, const Span **spans_out) = 0; + virtual const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) = 0; // Returns a single column of the texture, in BGRA8 format virtual const uint32_t *GetColumnBgra(unsigned int column, const Span **spans_out); // Returns the whole texture, stored in column-major order - virtual const uint8_t *GetPixels () = 0; + virtual const uint8_t *GetPixels(FRenderStyle style) = 0; // Returns the whole texture, stored in column-major order, in BGRA8 format virtual const uint32_t *GetPixelsBgra(); @@ -279,17 +277,12 @@ public: virtual void SetFrontSkyLayer(); - void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, const uint8_t *translation=NULL) - { - CopyToBlock(dest, dwidth, dheight, x, y, 0, translation); - } - - void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, int rotate, const uint8_t *translation=NULL); + void CopyToBlock (uint8_t *dest, int dwidth, int dheight, int x, int y, int rotate, const uint8_t *translation, FRenderStyle style); // Returns true if the next call to GetPixels() will return an image different from the // last call to GetPixels(). This should be considered valid only if a call to CheckModified() // is immediately followed by a call to GetPixels(). - virtual bool CheckModified (); + virtual bool CheckModified (FRenderStyle style); static void InitGrayMap(); @@ -309,8 +302,6 @@ public: PalEntry GetSkyCapColor(bool bottom); static PalEntry averageColor(const uint32_t *data, int size, int maxout); - virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. - protected: uint16_t Width, Height, WidthMask; static uint8_t GrayMap[256]; @@ -530,9 +521,8 @@ private: int CountLumpTextures (int lumpnum); // Build tiles - void AddTiles (void *tiles); - int CountTiles (void *tiles); - int CountBuildTiles (); + void AddTiles (const FString &pathprefix, const void *, int translation); + //int CountBuildTiles (); void InitBuildTiles (); // Animation stuff @@ -574,11 +564,12 @@ private: FTextureID DefaultTexture; TArray FirstTextureForFile; TMap PalettedVersions; // maps from normal -> paletted version + TArray > BuildTileData; TArray mAnimations; TArray mSwitchDefs; TArray mAnimatedDoors; - TArray BuildTileFiles; + public: short sintable[2048]; // for texture warping enum @@ -587,45 +578,60 @@ public: }; }; +// base class for everything that can be used as a world texture. +// This intermediate class encapsulates the buffers for the software renderer. +class FWorldTexture : public FTexture +{ +protected: + uint8_t *Pixeldata[2] = { nullptr, nullptr }; + Span **Spandata[2] = { nullptr, nullptr }; + uint8_t PixelsAreStatic = 0; // can be set by subclasses which provide static pixel buffers. + + FWorldTexture(const char *name = nullptr, int lumpnum = -1); + ~FWorldTexture(); + + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle style) override; + void Unload() override; + virtual uint8_t *MakeTexture(FRenderStyle style) = 0; + void FreeAllSpans(); +}; + // A texture that doesn't really exist class FDummyTexture : public FTexture { public: FDummyTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle style) override; void SetSize (int width, int height); }; // A texture that returns a wiggly version of another texture. -class FWarpTexture : public FTexture +class FWarpTexture : public FWorldTexture { public: FWarpTexture (FTexture *source, int warptype); ~FWarpTexture (); + void Unload() override; - virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL) override; const uint32_t *GetPixelsBgra() override; - void Unload (); - bool CheckModified (); + bool CheckModified (FRenderStyle) override; float GetSpeed() const { return Speed; } int GetSourceLump() { return SourcePic->GetSourceLump(); } void SetSpeed(float fac) { Speed = fac; } FTexture *GetRedirect(bool wantwarped); - uint64_t GenTime; - uint64_t GenTimeBgra; - float Speed; + uint64_t GenTime[2] = { 0, 0 }; + uint64_t GenTimeBgra = 0; + float Speed = 1.f; int WidthOffsetMultiplier, HeightOffsetMultiplier; // [mxd] protected: FTexture *SourcePic; - uint8_t *Pixels; - Span **Spans; - virtual void MakeTexture (uint64_t time); + uint8_t *MakeTexture (FRenderStyle style) override; int NextPo2 (int v); // [mxd] void SetupMultipliers (int width, int height); // [mxd] }; @@ -640,17 +646,17 @@ public: FCanvasTexture (const char *name, int width, int height); ~FCanvasTexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); const uint32_t *GetPixelsBgra() override; void Unload (); - bool CheckModified (); + bool CheckModified (FRenderStyle) override; void NeedUpdate() { bNeedsUpdate=true; } void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; } DSimpleCanvas *GetCanvas() { return Canvas; } DSimpleCanvas *GetCanvasBgra() { return CanvasBgra; } bool Mipmapped() override { return false; } - void MakeTexture (); + void MakeTexture (FRenderStyle style); void MakeTextureBgra (); protected: diff --git a/src/textures/tgatexture.cpp b/src/textures/tgatexture.cpp index 702da82b1..4b6430837 100644 --- a/src/textures/tgatexture.cpp +++ b/src/textures/tgatexture.cpp @@ -76,29 +76,18 @@ struct TGAHeader // //========================================================================== -class FTGATexture : public FTexture +class FTGATexture : public FWorldTexture { public: FTGATexture (int lumpnum, TGAHeader *); - ~FTGATexture (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - void Unload (); - FTextureFormat GetFormat (); - - int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL); - bool UseBasePalette(); + FTextureFormat GetFormat () override; + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL) override; + bool UseBasePalette() override; protected: - uint8_t *Pixels; - Span **Spans; - void ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel); - - virtual void MakeTexture (); - - friend class FTexture; + uint8_t *MakeTexture (FRenderStyle style) override; }; //========================================================================== @@ -113,7 +102,7 @@ FTexture *TGATexture_TryCreate(FileReader & file, int lumpnum) if (file.GetLength() < (long)sizeof(hdr)) return NULL; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); @@ -127,7 +116,7 @@ FTexture *TGATexture_TryCreate(FileReader & file, int lumpnum) if (hdr.img_type >=4 && hdr.img_type <= 8) return NULL; if ((hdr.img_desc & 16) != 0) return NULL; - file.Seek(0, SEEK_SET); + file.Seek(0, FileReader::SeekSet); file.Read(&hdr, sizeof(hdr)); hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); @@ -142,7 +131,7 @@ FTexture *TGATexture_TryCreate(FileReader & file, int lumpnum) //========================================================================== FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) -: FTexture(NULL, lumpnum), Pixels(0), Spans(0) +: FWorldTexture(NULL, lumpnum) { Wads.GetLumpName (Name, lumpnum); Width = hdr->width; @@ -158,38 +147,6 @@ FTGATexture::FTGATexture (int lumpnum, TGAHeader * hdr) // //========================================================================== -FTGATexture::~FTGATexture () -{ - Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FTGATexture::Unload () -{ - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - FTexture::Unload(); -} - -//========================================================================== -// -// -// -//========================================================================== - FTextureFormat FTGATexture::GetFormat() { return TEX_RGB; @@ -201,64 +158,14 @@ FTextureFormat FTGATexture::GetFormat() // //========================================================================== -const uint8_t *FTGATexture::GetColumn (unsigned int column, const Span **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; -} - -//========================================================================== -// -// -// -//========================================================================== - -const uint8_t *FTGATexture::GetPixels () -{ - if (Pixels == NULL) - { - MakeTexture (); - } - return Pixels; -} - -//========================================================================== -// -// -// -//========================================================================== - void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytesperpixel) { - uint8_t b; uint8_t data[4]; int Size = Width * Height; while (Size > 0) { - lump >> b; + uint8_t b = lump.ReadUInt8(); if (b & 128) { b&=~128; @@ -287,18 +194,19 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe // //========================================================================== -void FTGATexture::MakeTexture () +uint8_t *FTGATexture::MakeTexture (FRenderStyle style) { uint8_t PaletteMap[256]; - FWadLump lump = Wads.OpenLumpNum (SourceLump); + auto lump = Wads.OpenLumpReader (SourceLump); TGAHeader hdr; uint16_t w; uint8_t r,g,b,a; uint8_t * buffer; + bool alphatex = !!(style.Flags & STYLEF_RedIsAlpha); - Pixels = new uint8_t[Width*Height]; + auto Pixels = new uint8_t[Width*Height]; lump.Read(&hdr, sizeof(hdr)); - lump.Seek(hdr.id_len, SEEK_CUR); + lump.Seek(hdr.id_len, FileReader::SeekCur); hdr.width = LittleShort(hdr.width); hdr.height = LittleShort(hdr.height); @@ -314,7 +222,7 @@ void FTGATexture::MakeTexture () { case 15: case 16: - lump >> w; + w = lump.ReadUInt16(); r = (w & 0x001F) << 3; g = (w & 0x03E0) >> 2; b = (w & 0x7C00) >> 7; @@ -322,12 +230,17 @@ void FTGATexture::MakeTexture () break; case 24: - lump >> b >> g >> r; + b = lump.ReadUInt8(); + g = lump.ReadUInt8(); + r = lump.ReadUInt8(); a=255; break; case 32: - lump >> b >> g >> r >> a; + b = lump.ReadUInt8(); + g = lump.ReadUInt8(); + r = lump.ReadUInt8(); + a = lump.ReadUInt8(); if ((hdr.img_desc&15)!=8) a=255; break; @@ -335,7 +248,7 @@ void FTGATexture::MakeTexture () r=g=b=a=0; break; } - PaletteMap[i] = a>=128? ColorMatcher.Pick(r, g, b) : 0; + PaletteMap[i] = !alphatex? (a>=128? ColorMatcher.Pick(r, g, b) : 0) : (r * a) >> 8; } } @@ -393,8 +306,8 @@ void FTGATexture::MakeTexture () uint16_t * p = (uint16_t*)(ptr + y * Pitch); for(int x=0;x>10) & 0x1f)*2][((v>>5) & 0x1f)*2][(v & 0x1f)*2]; + int v = LittleShort(*p); + Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[((v >> 10) & 0x1f) * 2][((v >> 5) & 0x1f) * 2][(v & 0x1f) * 2] : ((v >> 10) & 0x1f) * 8; p+=step_x; } } @@ -406,7 +319,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x>2][p[1]>>2][p[0]>>2]; + Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : p[2]; p+=step_x; } } @@ -420,7 +333,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x>2][p[1]>>2][p[0]>>2]; + Pixels[x*Height + y] = !alphatex ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : p[2]; p+=step_x; } } @@ -432,7 +345,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x= 128? RGB256k.RGB[p[2]>>2][p[1]>>2][p[0]>>2] : 0; + Pixels[x*Height + y] = !alphatex ? (p[3] >= 128 ? RGB256k.RGB[p[2] >> 2][p[1] >> 2][p[0] >> 2] : 0) : (p[2] * p[3]) >> 8; p+=step_x; } } @@ -453,7 +366,7 @@ void FTGATexture::MakeTexture () uint8_t * p = ptr + y * Pitch; for(int x=0;x> w; + w = lump.ReadUInt16(); r = (w & 0x001F) << 3; g = (w & 0x03E0) >> 2; b = (w & 0x7C00) >> 7; a = 255; break; - + case 24: - lump >> b >> g >> r; - a=255; + b = lump.ReadUInt8(); + g = lump.ReadUInt8(); + r = lump.ReadUInt8(); + a = 255; break; - + case 32: - lump >> b >> g >> r >> a; - if ((hdr.img_desc&15)!=8) a=255; - else if (a!=0 && a!=255) transval = true; + b = lump.ReadUInt8(); + g = lump.ReadUInt8(); + r = lump.ReadUInt8(); + a = lump.ReadUInt8(); + if ((hdr.img_desc & 15) != 8) a = 255; + else if (a != 0 && a != 255) transval = true; break; - + default: // should never happen r=g=b=a=0; break; diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 2e073c186..d78bc5249 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -44,7 +44,7 @@ FWarpTexture::FWarpTexture (FTexture *source, int warptype) -: GenTime (0), GenTimeBgra(0), Speed (1.f), SourcePic (source), Pixels (0), Spans (0) + : SourcePic (source) { CopyInfo(source); if (warptype == 2) SetupMultipliers(256, 128); @@ -55,53 +55,25 @@ FWarpTexture::FWarpTexture (FTexture *source, int warptype) FWarpTexture::~FWarpTexture () { Unload (); - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } delete SourcePic; } void FWarpTexture::Unload () { - if (Pixels != NULL) - { - delete[] Pixels; - Pixels = NULL; - } - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } SourcePic->Unload (); - FTexture::Unload(); + FWorldTexture::Unload(); + FreeAllSpans(); } -bool FWarpTexture::CheckModified () +bool FWarpTexture::CheckModified (FRenderStyle style) { - return screen->FrameTime != GenTime; -} - -const uint8_t *FWarpTexture::GetPixels () -{ - uint64_t time = screen->FrameTime; - - if (Pixels == NULL || time != GenTime) - { - MakeTexture (time); - } - return Pixels; + return screen->FrameTime != GenTime[!!(style.Flags & STYLEF_RedIsAlpha)]; } const uint32_t *FWarpTexture::GetPixelsBgra() { - uint64_t time = screen->FrameTime; - if (Pixels == NULL || time != GenTime) - MakeTexture(time); - - if (PixelsBgra.empty() || time != GenTimeBgra) + auto Pixels = GetPixels(DefaultRenderStyle()); + if (PixelsBgra.empty() || GenTime[0] != GenTimeBgra) { CreatePixelsBgraWithMipmaps(); for (int i = 0; i < Width * Height; i++) @@ -112,58 +84,21 @@ const uint32_t *FWarpTexture::GetPixelsBgra() PixelsBgra[i] = 0; } GenerateBgraMipmapsFast(); - GenTimeBgra = time; + GenTimeBgra = GenTime[0]; } return PixelsBgra.data(); } -const uint8_t *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out) + +uint8_t *FWarpTexture::MakeTexture(FRenderStyle style) { - uint64_t time =screen->FrameTime; - - if (Pixels == NULL || time != GenTime) - { - MakeTexture (time); - } - 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; -} - - -void FWarpTexture::MakeTexture(uint64_t time) -{ - const uint8_t *otherpix = SourcePic->GetPixels(); - - if (Pixels == NULL) - { - Pixels = new uint8_t[Width * Height]; - } - if (Spans != NULL) - { - FreeSpans(Spans); - Spans = NULL; - } - - GenTime = time; + uint64_t time = screen->FrameTime; + const uint8_t *otherpix = SourcePic->GetPixels(style); + auto Pixels = new uint8_t[Width * Height]; WarpBuffer(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed, bWarped); + FreeAllSpans(); + GenTime[!!(style.Flags & STYLEF_RedIsAlpha)] = time; + return Pixels; } // [mxd] Non power of 2 textures need different offset multipliers, otherwise warp animation won't sync across texture diff --git a/src/textures/worldtexture.cpp b/src/textures/worldtexture.cpp new file mode 100644 index 000000000..db50c7fb4 --- /dev/null +++ b/src/textures/worldtexture.cpp @@ -0,0 +1,150 @@ +/* +** worldtexture.cpp +** Intermediate class for some common code for several classes +** +**--------------------------------------------------------------------------- +** Copyright 2018 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 "textures.h" + + +//========================================================================== +// +// +// +//========================================================================== + +FWorldTexture::FWorldTexture(const char *name, int lumpnum) + : FTexture(name, lumpnum) +{ +} + +//========================================================================== +// +// +// +//========================================================================== + +FWorldTexture::~FWorldTexture() +{ + Unload(); + FreeAllSpans(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FWorldTexture::FreeAllSpans() +{ + for(int i = 0; i < 2; i++) + { + if (Spandata[i] != nullptr) + { + FreeSpans (Spandata[i]); + Spandata[i] = nullptr; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FWorldTexture::Unload () +{ + for(int i = 0; i < 2; i++) + { + if (!(PixelsAreStatic & (1 << i))) + { + delete[] Pixeldata[i]; + } + Pixeldata[i] = nullptr; + } + FTexture::Unload(); +} + +//========================================================================== +// +// +// +//========================================================================== + +const uint8_t *FWorldTexture::GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out) +{ + int index = !!(style.Flags & STYLEF_RedIsAlpha); + GetPixels(style); + if ((unsigned)column >= (unsigned)Width) + { + if (WidthMask + 1 == Width) + { + column &= WidthMask; + } + else + { + column %= Width; + } + } + if (spans_out != nullptr) + { + if (Spandata[index] == nullptr) + { + Spandata[index] = CreateSpans (Pixeldata[index]); + } + *spans_out = Spandata[index][column]; + } + return Pixeldata[index] + column*Height; +} + +//========================================================================== +// +// +// +//========================================================================== + +const uint8_t *FWorldTexture::GetPixels (FRenderStyle style) +{ + if (CheckModified(style)) + { + Unload(); + } + int index = !!(style.Flags & STYLEF_RedIsAlpha); + if (Pixeldata[index] == nullptr) + { + Pixeldata[index] = MakeTexture (style); + } + return Pixeldata[index]; +} + diff --git a/src/v_font.cpp b/src/v_font.cpp index 9716f2744..e38ecfbde 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -177,8 +177,8 @@ class FFontChar1 : public FTexture { public: FFontChar1 (FTexture *sourcelump); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); void SetSourceRemap(const uint8_t *sourceremap); void Unload (); ~FFontChar1 (); @@ -198,8 +198,8 @@ public: FFontChar2 (int sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); ~FFontChar2 (); - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); + const uint8_t *GetColumn(FRenderStyle style, unsigned int column, const Span **spans_out); + const uint8_t *GetPixels (FRenderStyle style); void SetSourceRemap(const uint8_t *sourceremap); void Unload (); @@ -321,7 +321,7 @@ FFont *V_GetFont(const char *name) { uint32_t head; { - FWadLump lumpy = Wads.OpenLumpNum (lump); + auto lumpy = Wads.OpenLumpReader (lump); lumpy.Read (&head, 4); } if ((head & MAKE_ID(255,255,255,0)) == MAKE_ID('F','O','N',0) || @@ -559,7 +559,7 @@ void RecordTextureColors (FTexture *pic, uint8_t *usedcolors) for (x = pic->GetWidth() - 1; x >= 0; x--) { const FTexture::Span *spans; - const uint8_t *column = pic->GetColumn (x, &spans); + const uint8_t *column = pic->GetColumn(DefaultRenderStyle(), x, &spans); // This shouldn't use the spans... while (spans->Length != 0) { @@ -1649,9 +1649,11 @@ FFontChar1::FFontChar1 (FTexture *sourcelump) // // FFontChar1 :: GetPixels // +// Render style is not relevant for fonts. This must not use it! +// //========================================================================== -const uint8_t *FFontChar1::GetPixels () +const uint8_t *FFontChar1::GetPixels (FRenderStyle) { if (Pixels == NULL) { @@ -1666,12 +1668,12 @@ const uint8_t *FFontChar1::GetPixels () // //========================================================================== -void FFontChar1::MakeTexture () +void FFontChar1::MakeTexture () { // Make the texture as normal, then remap it so that all the colors // are at the low end of the palette Pixels = new uint8_t[Width*Height]; - const uint8_t *pix = BaseTexture->GetPixels(); + const uint8_t *pix = BaseTexture->GetPixels(DefaultRenderStyle()); if (!SourceRemap) { @@ -1692,14 +1694,14 @@ void FFontChar1::MakeTexture () // //========================================================================== -const uint8_t *FFontChar1::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FFontChar1::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (Pixels == NULL) { MakeTexture (); } - BaseTexture->GetColumn(column, spans_out); + BaseTexture->GetColumn(DefaultRenderStyle(), column, spans_out); return Pixels + column*Height; } @@ -1797,9 +1799,11 @@ void FFontChar2::Unload () // // FFontChar2 :: GetPixels // +// Like for FontChar1, the render style has no relevance here as well. +// //========================================================================== -const uint8_t *FFontChar2::GetPixels () +const uint8_t *FFontChar2::GetPixels (FRenderStyle) { if (Pixels == NULL) { @@ -1814,7 +1818,7 @@ const uint8_t *FFontChar2::GetPixels () // //========================================================================== -const uint8_t *FFontChar2::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FFontChar2::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (Pixels == NULL) { @@ -1855,7 +1859,7 @@ void FFontChar2::SetSourceRemap(const uint8_t *sourceremap) void FFontChar2::MakeTexture () { - FWadLump lump = Wads.OpenLumpNum (SourceLump); + auto lump = Wads.OpenLumpReader (SourceLump); int destSize = Width * Height; uint8_t max = 255; bool rle = true; @@ -1868,18 +1872,18 @@ void FFontChar2::MakeTexture () { lump.Read (buff, 7); max = buff[6]; - lump.Seek (SourcePos - 11, SEEK_CUR); + lump.Seek (SourcePos - 11, FileReader::SeekCur); } else if (buff[3] == 0x1A) { lump.Read(buff, 13); max = buff[12] - 1; - lump.Seek (SourcePos - 17, SEEK_CUR); + lump.Seek (SourcePos - 17, FileReader::SeekCur); rle = false; } else { - lump.Seek (SourcePos - 4, SEEK_CUR); + lump.Seek (SourcePos - 4, FileReader::SeekCur); } } @@ -1899,9 +1903,7 @@ void FFontChar2::MakeTexture () { if (runlen != 0) { - uint8_t color; - - lump >> color; + uint8_t color = lump.ReadUInt8(); color = MIN (color, max); if (SourceRemap != NULL) { @@ -1921,18 +1923,14 @@ void FFontChar2::MakeTexture () } else { - int8_t code; - - lump >> code; + int8_t code = lump.ReadInt8(); if (code >= 0) { runlen = code + 1; } else if (code != -128) { - uint8_t color; - - lump >> color; + uint8_t color = lump.ReadUInt8(); setlen = (-code) + 1; setval = MIN (color, max); if (SourceRemap != NULL) @@ -1951,8 +1949,7 @@ void FFontChar2::MakeTexture () { for (int x = Width; x != 0; --x) { - uint8_t color; - lump >> color; + uint8_t color = lump.ReadUInt8(); if (color > max) { color = max; diff --git a/src/v_palette.cpp b/src/v_palette.cpp index 11e3f6945..654526a20 100644 --- a/src/v_palette.cpp +++ b/src/v_palette.cpp @@ -340,69 +340,20 @@ void ReadPalette(int lumpnum, uint8_t *buffer) } } -static bool FixBuildPalette (uint8_t *opal, int lump, bool blood) -{ - if (Wads.LumpLength (lump) < 768) - { - return false; - } - - FMemLump data = Wads.ReadLump (lump); - const uint8_t *ipal = (const uint8_t *)data.GetMem(); - - // Reverse the palette because BUILD used entry 255 as - // transparent, but we use 0 as transparent. - - for (int c = 0; c < 768; c += 3) - { - if (!blood) - { - opal[c] = (ipal[765-c] << 2) | (ipal[765-c] >> 4); - opal[c+1] = (ipal[766-c] << 2) | (ipal[766-c] >> 4); - opal[c+2] = (ipal[767-c] << 2) | (ipal[767-c] >> 4); - } - else - { - opal[c] = ipal[765-c]; - opal[c+1] = ipal[766-c]; - opal[c+2] = ipal[767-c]; - } - } - return true; -} - void InitPalette () { uint8_t pal[768]; - bool usingBuild = false; - int lump; - - if ((lump = Wads.CheckNumForFullName ("palette.dat")) >= 0 && Wads.LumpLength (lump) >= 768) - { - usingBuild = FixBuildPalette (pal, lump, false); - } - else if ((lump = Wads.CheckNumForFullName ("blood.pal")) >= 0 && Wads.LumpLength (lump) >= 768) - { - usingBuild = FixBuildPalette (pal, lump, true); - } - - if (!usingBuild) - { - ReadPalette(Wads.CheckNumForName("PLAYPAL"), pal); - } + + ReadPalette(Wads.CheckNumForName("PLAYPAL"), pal); GPalette.SetPalette (pal); GPalette.MakeGoodRemap (); ColorMatcher.SetPalette ((uint32_t *)GPalette.BaseColors); - // The BUILD engine already has a transparent color, so it doesn't need any remapping. - if (!usingBuild) - { - if (GPalette.Remap[0] == 0) - { // No duplicates, so settle for something close to color 0 - GPalette.Remap[0] = BestColor ((uint32_t *)GPalette.BaseColors, - GPalette.BaseColors[0].r, GPalette.BaseColors[0].g, GPalette.BaseColors[0].b, 1, 255); - } + if (GPalette.Remap[0] == 0) + { // No duplicates, so settle for something close to color 0 + GPalette.Remap[0] = BestColor ((uint32_t *)GPalette.BaseColors, + GPalette.BaseColors[0].r, GPalette.BaseColors[0].g, GPalette.BaseColors[0].b, 1, 255); } // Colormaps have to be initialized before actors are loaded, diff --git a/src/v_video.cpp b/src/v_video.cpp index ca2e8b62a..5e86b915b 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -135,9 +135,9 @@ class FPaletteTester : public FTexture public: FPaletteTester (); - const uint8_t *GetColumn(unsigned int column, const Span **spans_out); - const uint8_t *GetPixels(); - bool CheckModified(); + const uint8_t *GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) override; + const uint8_t *GetPixels(FRenderStyle); + bool CheckModified(FRenderStyle); void SetTranslation(int num); protected: @@ -983,7 +983,7 @@ FPaletteTester::FPaletteTester() // //========================================================================== -bool FPaletteTester::CheckModified() +bool FPaletteTester::CheckModified(FRenderStyle) { return CurTranslation != WantTranslation; } @@ -1008,7 +1008,7 @@ void FPaletteTester::SetTranslation(int num) // //========================================================================== -const uint8_t *FPaletteTester::GetColumn (unsigned int column, const Span **spans_out) +const uint8_t *FPaletteTester::GetColumn(FRenderStyle, unsigned int column, const Span **spans_out) { if (CurTranslation != WantTranslation) { @@ -1028,7 +1028,7 @@ const uint8_t *FPaletteTester::GetColumn (unsigned int column, const Span **span // //========================================================================== -const uint8_t *FPaletteTester::GetPixels () +const uint8_t *FPaletteTester::GetPixels (FRenderStyle) { if (CurTranslation != WantTranslation) { diff --git a/src/v_video.h b/src/v_video.h index 1d7abd581..4d30cb0ef 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -405,6 +405,7 @@ public: virtual void SetBlendingRect (int x1, int y1, int x2, int y2); bool Accel2D; // If true, 2D drawing can be accelerated. + virtual bool LegacyHardware() const { return false; } // only for reporting SM1.4 support to the stat collector // Begin 2D drawing operations. This is like Update, but it doesn't end // the scene, and it doesn't present the image yet. If you are going to diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 21c35e669..31e65cd9b 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -225,12 +225,13 @@ int FWadCollection::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) +void FWadCollection::AddFile (const char *filename, FileReader *wadr) { int startlump; bool isdir = false; + FileReader wadreader; - if (wadinfo == NULL) + if (wadr == nullptr) { // Does this exist? If so, is it a directory? if (!DirEntryExists(filename, &isdir)) @@ -242,18 +243,15 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) if (!isdir) { - try - { - wadinfo = new FileReader(filename); - } - catch (CRecoverableError &err) + if (!wadreader.OpenFile(filename)) { // Didn't find file - Printf (TEXTCOLOR_RED "%s\n", err.GetMessage()); + Printf (TEXTCOLOR_RED "%s: File not found\n", filename); PrintLastError (); return; } } } + else wadreader = std::move(*wadr); if (!batchrun) Printf (" adding %s", filename); startlump = NumLumps; @@ -261,7 +259,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) FResourceFile *resfile; if (!isdir) - resfile = FResourceFile::OpenResourceFile(filename, wadinfo); + resfile = FResourceFile::OpenResourceFile(filename, wadreader); else resfile = FResourceFile::OpenDirectory(filename); @@ -292,8 +290,8 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) { FString path; path.Format("%s:%s", filename, lump->FullName.GetChars()); - FileReader *embedded = lump->NewReader(); - AddFile(path, embedded); + auto embedded = lump->NewReader(); + AddFile(path, &embedded); } } @@ -303,13 +301,11 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) char cksumout[33]; memset(cksumout, 0, sizeof(cksumout)); - FileReader *reader = wadinfo; - - if (reader != NULL) + if (wadreader.isOpen()) { MD5Context md5; - reader->Seek(0, SEEK_SET); - md5.Update(reader, reader->GetLength()); + wadreader.Seek(0, FileReader::SeekSet); + md5.Update(wadreader, (unsigned)wadreader.GetLength()); md5.Final(cksum); for (size_t j = 0; j < sizeof(cksum); ++j) @@ -317,7 +313,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) sprintf(cksumout + (j * 2), "%02X", cksum[j]); } - fprintf(hashfile, "file: %s, hash: %s, size: %ld\n", filename, cksumout, reader->GetLength()); + fprintf(hashfile, "file: %s, hash: %s, size: %d\n", filename, cksumout, (int)wadreader.GetLength()); } else @@ -329,9 +325,8 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) if (!(lump->Flags & LUMPF_EMBEDDED)) { - reader = lump->NewReader(); - MD5Context md5; + auto reader = lump->NewReader(); md5.Update(reader, lump->LumpSize); md5.Final(cksum); @@ -343,8 +338,6 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %d\n", filename, lump->FullName.IsNotEmpty() ? lump->FullName.GetChars() : lump->Name, cksumout, lump->LumpSize); - - delete reader; } } } @@ -929,7 +922,7 @@ void FWadCollection::RenameNerve () int w = GetIwadNum(); while (++w < GetNumWads()) { - FileReader *fr = GetFileReader(w); + auto fr = GetFileReader(w); if (fr == NULL) { continue; @@ -940,9 +933,9 @@ void FWadCollection::RenameNerve () // cheaper way to know this is not the file continue; } - fr->Seek(0, SEEK_SET); + fr->Seek(0, FileReader::SeekSet); MD5Context md5; - md5.Update(fr, fr->GetLength()); + md5.Update(*fr, (unsigned)fr->GetLength()); md5.Final(cksum); if (memcmp(nerve, cksum, 16) == 0) { @@ -990,8 +983,8 @@ void FWadCollection::FixMacHexen() return; } - FileReader* const reader = GetFileReader(GetIwadNum()); - const long iwadSize = reader->GetLength(); + FileReader *reader = GetFileReader(GetIwadNum()); + auto iwadSize = reader->GetLength(); static const long DEMO_SIZE = 13596228; static const long BETA_SIZE = 13749984; @@ -1004,11 +997,12 @@ void FWadCollection::FixMacHexen() return; } - reader->Seek(0, SEEK_SET); + reader->Seek(0, FileReader::SeekSet); uint8_t checksum[16]; MD5Context md5; - md5.Update(reader, iwadSize); + + md5.Update(*reader, (unsigned)iwadSize); md5.Final(checksum); static const uint8_t HEXEN_DEMO_MD5[16] = @@ -1261,6 +1255,19 @@ int FWadCollection::GetLumpFile (int lump) const return LumpInfo[lump].wadnum; } +//========================================================================== +// +// W_GetLumpFile +// +//========================================================================== + +FResourceLump *FWadCollection::GetLumpRecord(int lump) const +{ + if ((size_t)lump >= LumpInfo.Size()) + return nullptr; + return LumpInfo[lump].lump; +} + //========================================================================== // // W_ReadLump @@ -1271,9 +1278,9 @@ int FWadCollection::GetLumpFile (int lump) const void FWadCollection::ReadLump (int lump, void *dest) { - FWadLump lumpr = OpenLumpNum (lump); - long size = lumpr.GetLength (); - long numread = lumpr.Read (dest, size); + auto lumpr = OpenLumpReader (lump); + auto size = lumpr.GetLength (); + auto numread = lumpr.Read (dest, size); if (numread != size) { @@ -1305,59 +1312,60 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) //========================================================================== // -// OpenLumpNum +// OpenLumpReader // -// Returns a copy of the file object for a lump's wad and positions its -// file pointer at the beginning of the lump. +// uses a more abstract interface to allow for easier low level optimization later // //========================================================================== -FWadLump FWadCollection::OpenLumpNum (int lump) + +FileReader FWadCollection::OpenLumpReader(int lump) { if ((unsigned)lump >= (unsigned)LumpInfo.Size()) { - I_Error ("W_OpenLumpNum: %u >= NumLumps", lump); + I_Error("W_OpenLumpNum: %u >= NumLumps", lump); } - return FWadLump(LumpInfo[lump].lump); + auto rl = LumpInfo[lump].lump; + auto rd = rl->GetReader(); + + if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & (LUMPF_BLOODCRYPT | LUMPF_COMPRESSED))) + { + FileReader rdr; + rdr.OpenFilePart(*rd, rl->GetFileOffset(), rl->LumpSize); + return rdr; + } + return rl->NewReader(); // This always gets a reader to the cache } -//========================================================================== -// -// ReopenLumpNum -// -// Similar to OpenLumpNum, except a new, independant file object is created -// for the lump's wad. Use this when you won't read the lump's data all at -// once (e.g. for streaming an Ogg Vorbis stream from a wad as music). -// -//========================================================================== - -FWadLump *FWadCollection::ReopenLumpNum (int lump) +FileReader FWadCollection::ReopenLumpReader(int lump, bool alwayscache) { if ((unsigned)lump >= (unsigned)LumpInfo.Size()) { - I_Error ("W_ReopenLumpNum: %u >= NumLumps", lump); + I_Error("ReopenLumpReader: %u >= NumLumps", lump); } - return new FWadLump(LumpInfo[lump].lump, true); -} + auto rl = LumpInfo[lump].lump; + auto rd = rl->GetReader(); -FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump) -{ - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) + if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & (LUMPF_BLOODCRYPT|LUMPF_COMPRESSED))) { - return NULL; + int fileno = Wads.GetLumpFile(lump); + const char *filename = Wads.GetWadFullName(fileno); + FileReader fr; + if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize)) + { + return fr; + } } - - return new FWadLump(lump, LumpInfo[lump].lump); + return rl->NewReader(); // This always gets a reader to the cache } - //========================================================================== // // GetFileReader // -// Retrieves the FileReader object to access the given WAD +// Retrieves the File reader object to access the given WAD // Careful: This is only useful for real WAD files! // //========================================================================== @@ -1368,6 +1376,7 @@ FileReader *FWadCollection::GetFileReader(int wadnum) { return NULL; } + return Files[wadnum]->GetReader(); } @@ -1458,31 +1467,6 @@ const char *FWadCollection::GetWadFullName (int wadnum) const } -//========================================================================== -// -// IsUncompressedFile -// -// Returns true when the lump is available as an uncompressed portion of -// a file. The music player can play such lumps by streaming but anything -// else has to be loaded into memory first. -// -//========================================================================== - -bool FWadCollection::IsUncompressedFile(int lump) const -{ - if ((unsigned)lump >= (unsigned)NumLumps) - { - I_Error ("IsUncompressedFile: %u >= NumLumps",lump); - } - - FResourceLump *l = LumpInfo[lump].lump; - FileReader *f = l->GetReader(); - - // We can access the file only if we get the FILE pointer from the FileReader here. - // Any other case means it won't work. - return (f != NULL && f->GetFile() != NULL); -} - //========================================================================== // // IsEncryptedFile @@ -1501,157 +1485,6 @@ bool FWadCollection::IsEncryptedFile(int lump) const } -// FWadLump ----------------------------------------------------------------- - -FWadLump::FWadLump () -: FileReader(), Lump(NULL) -{ -} - -FWadLump::FWadLump (const FWadLump ©) -: FileReader() -{ - // This must be defined isn't called. - File = copy.File; - Length = copy.Length; - FilePos = copy.FilePos; - StartPos = copy.StartPos; - CloseOnDestruct = false; - if ((Lump = copy.Lump)) Lump->CacheLump(); -} - -#ifdef _DEBUG -FWadLump & FWadLump::operator= (const FWadLump ©) -{ - // Only the debug build actually calls this! - File = copy.File; - Length = copy.Length; - FilePos = copy.FilePos; - StartPos = copy.StartPos; - CloseOnDestruct = false; - if ((Lump = copy.Lump)) Lump->CacheLump(); - return *this; -} -#endif - - -FWadLump::FWadLump(FResourceLump *lump, bool alwayscache) -: FileReader() -{ - FileReader *f = lump->GetReader(); - - if (f != NULL && f->GetFile() != NULL && !alwayscache) - { - // Uncompressed lump in a file - File = f->GetFile(); - Length = lump->LumpSize; - StartPos = FilePos = lump->GetFileOffset(); - Lump = NULL; - } - else - { - File = NULL; - Length = lump->LumpSize; - StartPos = FilePos = 0; - Lump = lump; - Lump->CacheLump(); - } -} - -FWadLump::FWadLump(int lumpnum, FResourceLump *lump) -: FileReader() -{ - FileReader *f = lump->GetReader(); - - if (f != NULL && f->GetFile() != NULL) - { - // Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming - int fileno = Wads.GetLumpFile(lumpnum); - const char *filename = Wads.GetWadFullName(fileno); - File = openfd(filename); - if (File != NULL) - { - Length = lump->LumpSize; - StartPos = FilePos = lump->GetFileOffset(); - Lump = NULL; - CloseOnDestruct = true; - Seek(0, SEEK_SET); - return; - } - } - File = NULL; - Length = lump->LumpSize; - StartPos = FilePos = 0; - Lump = lump; - Lump->CacheLump(); -} - -FWadLump::~FWadLump() -{ - if (Lump != NULL) - { - Lump->ReleaseCache(); - } -} - -long FWadLump::Seek (long offset, int origin) -{ - if (Lump != NULL) - { - switch (origin) - { - case SEEK_CUR: - offset += FilePos; - break; - - case SEEK_END: - offset += Length; - break; - - default: - break; - } - FilePos = clamp (offset, 0, Length); - return 0; - } - return FileReader::Seek(offset, origin); -} - -long FWadLump::Read (void *buffer, long len) -{ - long numread; - long startread = FilePos; - - if (Lump != NULL) - { - if (FilePos + len > Length) - { - len = Length - FilePos; - } - memcpy(buffer, Lump->Cache + FilePos, len); - FilePos += len; - numread = len; - } - else - { - numread = FileReader::Read(buffer, len); - } - return numread; -} - -char *FWadLump::Gets(char *strbuf, int len) -{ - if (Lump != NULL) - { - return GetsFromBuffer(Lump->Cache, strbuf, len); - } - else - { - return FileReader::Gets(strbuf, len); - } - return strbuf; -} - // FMemLump ----------------------------------------------------------------- FMemLump::FMemLump () @@ -1680,10 +1513,10 @@ FMemLump::~FMemLump () FString::FString (ELumpNum lumpnum) { - FWadLump lumpr = Wads.OpenLumpNum ((int)lumpnum); - long size = lumpr.GetLength (); + auto lumpr = Wads.OpenLumpReader ((int)lumpnum); + auto size = lumpr.GetLength (); AllocBuffer (1 + size); - long numread = lumpr.Read (&Chars[0], size); + auto numread = lumpr.Read (&Chars[0], size); Chars[size] = '\0'; if (numread != size) diff --git a/src/w_wad.h b/src/w_wad.h index 11e4a954d..9f33ac2c1 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -68,44 +68,18 @@ typedef enum { enum ELumpFlags { - LUMPF_MAYBEFLAT=1, - LUMPF_ZIPFILE=2, - LUMPF_EMBEDDED=4, - LUMPF_BLOODCRYPT = 8, + LUMPF_MAYBEFLAT=1, // might be a flat outside F_START/END + LUMPF_ZIPFILE=2, // contains a full path + LUMPF_EMBEDDED=4, // from an embedded WAD + LUMPF_BLOODCRYPT = 8, // encrypted + LUMPF_COMPRESSED = 16, // compressed + LUMPF_SEQUENTIAL = 32, // compressed but a sequential reader can be retrieved. }; // [RH] Copy an 8-char string and uppercase it. void uppercopy (char *to, const char *from); -// A very loose reference to a lump on disk. This is really just a wrapper -// around the main wad's FILE object with a different length recorded. Since -// two lumps from the same wad share the same FILE, you cannot read from -// both of them independantly. -class FWadLump : public FileReader -{ -public: - FWadLump (); - FWadLump (const FWadLump ©); -#ifdef _DEBUG - FWadLump & operator= (const FWadLump ©); -#endif - ~FWadLump(); - - long Seek (long offset, int origin); - long Read (void *buffer, long len); - char *Gets(char *strbuf, int len); - -private: - FWadLump (FResourceLump *Lump, bool alwayscache = false); - FWadLump(int lumpnum, FResourceLump *lump); - - FResourceLump *Lump; - - friend class FWadCollection; -}; - - // A lump in memory. class FMemLump { @@ -177,12 +151,8 @@ public: FMemLump ReadLump (int lump); FMemLump ReadLump (const char *name) { return ReadLump (GetNumForName (name)); } - FWadLump OpenLumpNum (int lump); - FWadLump OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); } - FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE - FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE - - FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD + FileReader OpenLumpReader(int lump); // opens a reader that redirects to the containing file's one. + FileReader ReopenLumpReader(int lump, bool alwayscache = false); // opens an independent reader. int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names @@ -200,9 +170,9 @@ public: 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 int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump + FResourceLump *GetLumpRecord(int lump) const; // Returns the FResourceLump, in case the caller wants to have direct access to the lump cache. bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match - bool IsUncompressedFile(int lump) const; bool IsEncryptedFile(int lump) const; int GetNumLumps () const; @@ -237,6 +207,7 @@ private: void RenameNerve(); void FixMacHexen(); void DeleteAll(); + FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD }; extern FWadCollection Wads; diff --git a/src/w_zip.h b/src/w_zip.h index 6120e629b..0a2ce6d4e 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -62,14 +62,6 @@ struct FZipLocalFileHeader #define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) #define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) -#define METHOD_STORED 0 -#define METHOD_SHRINK 1 -#define METHOD_IMPLODE 6 -#define METHOD_DEFLATE 8 -#define METHOD_BZIP2 12 -#define METHOD_LZMA 14 -#define METHOD_PPMD 98 - // File header flags. #define ZF_ENCRYPTED 0x1 diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index 58a611d3e..a8ecfccae 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -509,4 +509,3 @@ CCMD (vid_currentmode) { Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); } - diff --git a/src/win32/i_crash.cpp b/src/win32/i_crash.cpp index 2e904cc0f..4caa954e1 100644 --- a/src/win32/i_crash.cpp +++ b/src/win32/i_crash.cpp @@ -166,49 +166,49 @@ namespace zip #pragma pack(push,1) struct LocalFileHeader { - DWORD Magic; // 0 + uint32_t Magic; // 0 uint8_t VersionToExtract[2]; // 4 uint16_t Flags; // 6 uint16_t Method; // 8 uint16_t ModTime; // 10 uint16_t ModDate; // 12 - DWORD CRC32; // 14 - DWORD CompressedSize; // 18 - DWORD UncompressedSize; // 22 + uint32_t CRC32; // 14 + uint32_t CompressedSize; // 18 + uint32_t UncompressedSize; // 22 uint16_t NameLength; // 26 uint16_t ExtraLength; // 28 }; struct CentralDirectoryEntry { - DWORD Magic; - uint8_t VersionMadeBy[2]; - uint8_t VersionToExtract[2]; + uint32_t Magic; + uint8_t VersionMadeBy[2]; + uint8_t VersionToExtract[2]; uint16_t Flags; uint16_t Method; uint16_t ModTime; uint16_t ModDate; - DWORD CRC32; - DWORD CompressedSize; - DWORD UncompressedSize; + uint32_t CRC32; + uint32_t CompressedSize; + uint32_t UncompressedSize; uint16_t NameLength; uint16_t ExtraLength; uint16_t CommentLength; uint16_t StartingDiskNumber; uint16_t InternalAttributes; - DWORD ExternalAttributes; - DWORD LocalHeaderOffset; + uint32_t ExternalAttributes; + uint32_t LocalHeaderOffset; }; struct EndOfCentralDirectory { - DWORD Magic; + uint32_t Magic; uint16_t DiskNumber; uint16_t FirstDisk; uint16_t NumEntries; uint16_t NumEntriesOnAllDisks; - DWORD DirectorySize; - DWORD DirectoryOffset; + uint32_t DirectorySize; + uint32_t DirectoryOffset; uint16_t ZipCommentLength; }; #pragma pack(pop) @@ -219,9 +219,9 @@ struct TarFile HANDLE File; const char *Filename; int ZipOffset; - DWORD UncompressedSize; - DWORD CompressedSize; - DWORD CRC32; + uint32_t UncompressedSize; + uint32_t CompressedSize; + uint32_t CRC32; bool Deflated; }; @@ -1513,7 +1513,8 @@ static HANDLE MakeZip () struct tm *nowtm; int i, numfiles; HANDLE file; - DWORD len, dirsize; + DWORD len; + uint32_t dirsize; size_t namelen; if (NumFiles == 0) @@ -1553,7 +1554,7 @@ static HANDLE MakeZip () central.ModTime = dostime; central.ModDate = dosdate; - dirend.DirectoryOffset = LittleLong(SetFilePointer (file, 0, NULL, FILE_CURRENT)); + dirend.DirectoryOffset = LittleLong((uint32_t)SetFilePointer (file, 0, NULL, FILE_CURRENT)); for (i = 0, numfiles = 0, dirsize = 0; i < NumFiles; ++i) { @@ -1565,8 +1566,8 @@ static HANDLE MakeZip () numfiles++; if (TarFiles[i].Deflated) { - central.Flags = LittleShort(2); - central.Method = LittleShort(8); + central.Flags = LittleShort((uint16_t)2); + central.Method = LittleShort((uint16_t)8); } else { @@ -1577,7 +1578,7 @@ static HANDLE MakeZip () central.InternalAttributes = 0; if (namelen > 4 && stricmp(TarFiles[i].Filename - 4, ".txt") == 0) { // Bit 0 set indicates this is probably a text file. But do any tools use it? - central.InternalAttributes = LittleShort(1); + central.InternalAttributes = LittleShort((uint16_t)1); } central.CRC32 = LittleLong(TarFiles[i].CRC32); central.CompressedSize = LittleLong(TarFiles[i].CompressedSize); @@ -1590,7 +1591,7 @@ static HANDLE MakeZip () } // Write the directory terminator - dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort(numfiles); + dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)numfiles); dirend.DirectorySize = LittleLong(dirsize); WriteFile (file, &dirend, sizeof(dirend), &len, NULL); @@ -1635,7 +1636,7 @@ static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, sho if (gzip) { - local.Method = LittleShort(8); + local.Method = LittleShort((uint16_t)8); whichfile->Deflated = true; stream.next_out = outbuf; stream.avail_out = sizeof(outbuf); @@ -1643,7 +1644,7 @@ static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, sho // Write out the header and filename. local.VersionToExtract[0] = 20; - local.Flags = gzip ? LittleShort(2) : 0; + local.Flags = gzip ? LittleShort((uint16_t)2) : 0; local.ModTime = dostime; local.ModDate = dosdate; local.UncompressedSize = LittleLong(whichfile->UncompressedSize); diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index a537329e4..50bc7d8d0 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -154,6 +154,7 @@ uint32_t LanguageIDs[4]; UINT TimerPeriod; bool gameisdead; +int sys_ostype = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -229,10 +230,12 @@ void I_DetectOS(void) if (info.dwMinorVersion == 1) { osname = "XP"; + sys_ostype = 1; // legacy OS } else if (info.dwMinorVersion == 2) { osname = "Server 2003"; + sys_ostype = 1; // legacy OS } } else if (info.dwMajorVersion == 6) @@ -240,10 +243,12 @@ void I_DetectOS(void) if (info.dwMinorVersion == 0) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "Vista" : "Server 2008"; + sys_ostype = 2; // legacy OS } else if (info.dwMinorVersion == 1) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "7" : "Server 2008 R2"; + sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 2) { @@ -251,16 +256,23 @@ void I_DetectOS(void) // the highest version of Windows you support, which will also be the // highest version of Windows this function returns. osname = (info.wProductType == VER_NT_WORKSTATION) ? "8" : "Server 2012"; + sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 3) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "8.1" : "Server 2012 R2"; + sys_ostype = 2; // supported OS } else if (info.dwMinorVersion == 4) { - osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 10 (or higher)"; + osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (beta)" : "Server 10 (beta)"; } } + else if (info.dwMajorVersion == 10) + { + osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 10 (or higher)"; + sys_ostype = 3; // modern OS + } break; default: diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 5ba3848c7..98034f002 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -966,8 +966,8 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, HRESULT &hr) // Fill bitmap with the startup image. memset (ST_Util_BitsForBitmap(StartupBitmap), 0xF0, 64000); - FWadLump lumpr = Wads.OpenLumpNum (startup_lump); - lumpr.Seek (57 * 320, SEEK_SET); + auto lumpr = Wads.OpenLumpReader (startup_lump); + lumpr.Seek (57 * 320, FileReader::SeekSet); lumpr.Read (ST_Util_BitsForBitmap(StartupBitmap) + 41 * 320, 95 * 320); // Load the animated overlays. @@ -978,7 +978,7 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, HRESULT &hr) if (lumpnum >= 0 && (lumplen = Wads.LumpLength (lumpnum)) == StrifeStartupPicSizes[i]) { - FWadLump lumpr = Wads.OpenLumpNum (lumpnum); + auto lumpr = Wads.OpenLumpReader (lumpnum); StartupPics[i] = new uint8_t[lumplen]; lumpr.Read (StartupPics[i], lumplen); } diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index d2cea2024..d3523e17b 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -147,6 +147,7 @@ public: HRESULT GetHR (); bool Is8BitMode() { return false; } virtual int GetTrueHeight() { return TrueHeight; } + virtual bool LegacyHardware() const { return SM14; } private: friend class D3DTex; diff --git a/src/x86.cpp b/src/x86.cpp index b8c2d01d0..877bd726d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -143,6 +143,8 @@ haveid: cpu->FeatureFlags[1] = foo[2]; // Store extended feature flags cpu->FeatureFlags[2] = foo[3]; // Store feature flags + cpu->HyperThreading = (foo[3] & (1 << 28)) > 0; + // If CLFLUSH instruction is supported, get the real cache line size. if (foo[3] & (1 << 19)) { @@ -251,6 +253,7 @@ void DumpCPUInfo(const CPUInfo *cpu) if (cpu->bSSE42) Printf(" SSE4.2"); if (cpu->b3DNow) Printf(" 3DNow!"); if (cpu->b3DNowPlus) Printf(" 3DNow!+"); + if (cpu->HyperThreading) Printf(" HyperThreading"); Printf ("\n"); } } diff --git a/src/x86.h b/src/x86.h index 1839e2c35..9c0f0f170 100644 --- a/src/x86.h +++ b/src/x86.h @@ -20,6 +20,7 @@ struct CPUInfo // 92 bytes uint8_t Model; uint8_t Family; uint8_t Type; + uint8_t HyperThreading; union { diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index eabe3b2f5..155ce839d 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1979,6 +1979,7 @@ MAPCOLORMNU_LOCKEDCOLOR = "Locked doors"; MAPCOLORMNU_INTRALEVELCOLOR = "Teleporter to the same map"; MAPCOLORMNU_INTERLEVELCOLOR = "Teleporter to a different map"; MAPCOLORMNU_SECRETSECTORCOLOR = "Secret sector"; +MAPCOLORMNU_UNEXPLOREDSECRETCOLOR = "Unexplored secret"; MAPCOLORMNU_SPECIALWALLCOLOR = "Special trigger lines"; MAPCOLORMNU_CHEATMODE = "Cheat Mode"; MAPCOLORMNU_TSWALLCOLOR = "Invisible 2-sided walls"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 09604328c..744e4d4c7 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1157,6 +1157,7 @@ OptionMenu MapColorMenu protected ColorPicker "$MAPCOLORMNU_INTRALEVELCOLOR", "am_intralevelcolor" ColorPicker "$MAPCOLORMNU_INTERLEVELCOLOR", "am_interlevelcolor" ColorPicker "$MAPCOLORMNU_SECRETSECTORCOLOR", "am_secretsectorcolor" + ColorPicker "$MAPCOLORMNU_UNEXPLOREDSECRETCOLOR", "am_unexploredsecretcolor" ColorPicker "$MAPCOLORMNU_SPECIALWALLCOLOR", "am_specialwallcolor" ColorPicker "$MAPCOLORMNU_PORTAL", "am_portalcolor" StaticText " " diff --git a/wadsrc/static/shaders/glsl/material_normal.fp b/wadsrc/static/shaders/glsl/material_normal.fp index 610a239d2..b048f4559 100644 --- a/wadsrc/static/shaders/glsl/material_normal.fp +++ b/wadsrc/static/shaders/glsl/material_normal.fp @@ -34,13 +34,12 @@ vec3 lightContribution(int i, vec3 normal) vec3 ProcessMaterial(vec3 material, vec3 color) { + vec4 dynlight = uDynLightColor; + vec3 normal = ApplyNormalMap(); + if (uLightIndex >= 0) { - vec4 dynlight = uDynLightColor; - vec3 normal = ApplyNormalMap(); - ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); - if (lightRange.z > lightRange.x) { // modulated lights @@ -55,9 +54,13 @@ vec3 ProcessMaterial(vec3 material, vec3 color) dynlight.rgb -= lightContribution(i, normal); } } + } - vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); + vec3 frag = material * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); + if (uLightIndex >= 0) + { + ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); if (lightRange.w > lightRange.z) { vec4 addlight = vec4(0.0,0.0,0.0,0.0); @@ -70,11 +73,7 @@ vec3 ProcessMaterial(vec3 material, vec3 color) frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0); } + } - return frag; - } - else - { - return material * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4); - } + return frag; } diff --git a/wadsrc/static/shaders/glsl/material_specular.fp b/wadsrc/static/shaders/glsl/material_specular.fp index ab61d6cf9..dff634737 100644 --- a/wadsrc/static/shaders/glsl/material_specular.fp +++ b/wadsrc/static/shaders/glsl/material_specular.fp @@ -36,16 +36,15 @@ vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA) vec3 ProcessMaterial(vec3 material, vec3 color) { + vec4 dynlight = uDynLightColor; + vec4 specular = vec4(0.0, 0.0, 0.0, 1.0); + + vec3 normal = ApplyNormalMap(); + vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz); + if (uLightIndex >= 0) { - vec4 dynlight = uDynLightColor; - vec4 specular = vec4(0.0, 0.0, 0.0, 1.0); - - vec3 normal = ApplyNormalMap(); - vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz); - ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); - if (lightRange.z > lightRange.x) { // modulated lights @@ -66,17 +65,21 @@ vec3 ProcessMaterial(vec3 material, vec3 color) specular.rgb -= lightcolor.rgb * attenuation.y; } } + } - dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); - specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4); + dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4); + specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4); - vec4 materialSpec = texture(speculartexture, vTexCoord.st); - vec3 frag = material * dynlight.rgb + materialSpec.rgb * specular.rgb; + vec4 materialSpec = texture(speculartexture, vTexCoord.st); + vec3 frag = material * dynlight.rgb + materialSpec.rgb * specular.rgb; + if (uLightIndex >= 0) + { + ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); if (lightRange.w > lightRange.z) { vec4 addlight = vec4(0.0,0.0,0.0,0.0); - + // additive lights for(int i=lightRange.z; i SpawnPointClass; // For respawning like Heretic's mace native Class PickupFlash; // actor to spawn as pickup flash diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index 691a89e33..8d490444e 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -6,6 +6,7 @@ class HereticStatusBar : BaseStatusBar HUDFont mBigFont; InventoryBarState diparms; InventoryBarState diparms_sbar; + private int wiggle; override void Init() @@ -40,6 +41,12 @@ class HereticStatusBar : BaseStatusBar { Super.Tick(); mHealthInterpolator.Update(CPlayer.health); + + // wiggle the chain if it moves + if (level.time & 1) + { + wiggle = (mHealthInterpolator.GetValue() != CPlayer.health) && Random[ChainWiggle](0, 1); + } } override void Draw (int state, double TicFrac) @@ -73,7 +80,6 @@ class HereticStatusBar : BaseStatusBar DrawImage("CHAINCAC", (0, 190), DI_ITEM_OFFSETS); // wiggle the chain if it moves int inthealth = mHealthInterpolator.GetValue(); - int wiggle = (inthealth != CPlayer.health) && Random[ChainWiggle](0, 1); DrawGem("CHAIN", "LIFEGEM2",inthealth, CPlayer.mo.GetMaxHealth(true), (2, 191 + wiggle), 15, 25, 16, (multiplayer? DI_TRANSLATABLE : 0) | DI_ITEM_LEFT_TOP); DrawImage("LTFACE", (0, 190), DI_ITEM_OFFSETS); DrawImage("RTFACE", (276, 190), DI_ITEM_OFFSETS);