mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
Merge remote-tracking branch 'origin/master' into adlMIDI
This commit is contained in:
commit
0893f0c01e
213 changed files with 4205 additions and 4719 deletions
|
@ -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:
|
||||
|
|
10
.travis.yml
10
.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
|
||||
|
|
|
@ -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} $<TARGET_FILE_DIR:zdoom>/${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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -121,6 +121,8 @@
|
|||
|
||||
EXTERN_CVAR(Bool, hud_althud)
|
||||
void DrawHUD();
|
||||
void D_DoAnonStats();
|
||||
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -1947,7 +1949,6 @@ static FString CheckGameInfo(TArray<FString> & 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<FString> & 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());
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
360
src/d_stats.cpp
Normal file
360
src/d_stats.cpp
Normal file
|
@ -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 <windows.h>
|
||||
#include <winsock2.h>
|
||||
extern int sys_ostype;
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#else // !__APPLE__
|
||||
#include <SDL.h>
|
||||
#endif // __APPLE__
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#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<double, bool> 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
|
108
src/dthinker.cpp
108
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<SortedProfileInfo> sorted;
|
||||
sorted.Grow(Profiles.CountUsed());
|
||||
|
||||
auto it = TMap<FName, ProfileInfo>::Iterator(Profiles);
|
||||
TMap<FName, ProfileInfo>::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();
|
||||
|
|
778
src/files.cpp
778
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<long>(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<long>(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<uint8_t> buf;
|
||||
|
||||
public:
|
||||
MemoryArrayReader(const char *buffer, long length)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
buf.Resize(length);
|
||||
memcpy(&buf[0], buffer, length);
|
||||
}
|
||||
UpdateBuffer();
|
||||
}
|
||||
|
||||
TArray<uint8_t> &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<long>(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<bool(TArray<uint8_t>&)> 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;
|
||||
}
|
||||
|
||||
|
|
531
src/files.h
531
src/files.h
|
@ -37,361 +37,229 @@
|
|||
#define FILES_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
#include "bzlib.h"
|
||||
#include <functional>
|
||||
#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<bool(TArray<uint8_t>&)> 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<uint8_t> &GetArray() { return buf; }
|
||||
|
||||
void UpdateLength() { Length = buf.Size(); }
|
||||
|
||||
protected:
|
||||
TArray<uint8_t> buf;
|
||||
};
|
||||
|
||||
|
||||
class FileWriter
|
||||
|
@ -435,7 +303,4 @@ public:
|
|||
TArray<unsigned char> *GetBuffer() { return &mBuffer; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
604
src/files_decompress.cpp
Normal file
604
src/files_decompress.cpp
Normal file
|
@ -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 <zlib.h>
|
||||
#include <bzlib.h>
|
||||
|
||||
#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<unsigned int>(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<unsigned int>(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;
|
||||
}
|
||||
}
|
|
@ -1930,7 +1930,7 @@ void G_DoLoadGame ()
|
|||
hidecon = gameaction == ga_loadgamehidecon;
|
||||
gameaction = ga_nothing;
|
||||
|
||||
std::unique_ptr<FResourceFile> resfile(FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true));
|
||||
std::unique_ptr<FResourceFile> 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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
void gl_PatchMenu();
|
||||
static TArray<FString> 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<double, bool> 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"));
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<uint32_t>(chunklen,sizeof(chunkbuffer)));
|
||||
stream.avail_in = (uInt)file.Read (chunkbuffer, MIN<uint32_t>(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;
|
||||
}
|
||||
|
|
12
src/m_png.h
12
src/m_png.h
|
@ -36,8 +36,8 @@
|
|||
#include <stdio.h>
|
||||
#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<Chunk> Chunks;
|
||||
TArray<char *> 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);
|
||||
|
||||
|
||||
|
|
78
src/m_swap.h
78
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)
|
||||
{
|
||||
|
|
|
@ -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<long>(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));
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<uint8_t> &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();
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ private:
|
|||
FSaveGameNode NewSaveNode;
|
||||
int LastSaved = -1;
|
||||
int LastAccessed = -1;
|
||||
FileReader *currentSavePic = nullptr;
|
||||
TArray<char> SavePicData;
|
||||
FTexture *SavePic = nullptr;
|
||||
FBrokenLines *SaveComment = nullptr;
|
||||
|
|
|
@ -380,7 +380,7 @@ public:
|
|||
|
||||
BoundsCheckingArray<int32_t *, NUM_MAPVARS> 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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
#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;
|
||||
|
|
|
@ -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() : "-");
|
||||
}
|
||||
}
|
||||
|
|
172
src/p_setup.cpp
172
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
|
||||
|
||||
|
|
|
@ -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 (lumpindex<countof(MapLumps))
|
||||
{
|
||||
file = MapLumps[lumpindex].Reader;
|
||||
file->Seek(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 (lumpindex<countof(MapLumps))
|
||||
{
|
||||
if (size == -1) size = MapLumps[lumpindex].Reader->GetLength();
|
||||
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 (lumpindex<countof(MapLumps) && MapLumps[lumpindex].Reader)
|
||||
if (lumpindex<countof(MapLumps) && MapLumps[lumpindex].Reader.isOpen())
|
||||
{
|
||||
return MapLumps[lumpindex].Reader->GetLength();
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<DrawRectCommand>(*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]))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<std::mutex> 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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
return PvsLineVisible[PvsLineStart[subsectorDepth] + lineIndex];
|
||||
}
|
||||
|
||||
std::vector<subsector_t *> PvsSectors;
|
||||
std::vector<uint32_t> PvsSubsectors;
|
||||
double MaxCeilingHeight = 0.0;
|
||||
double MinFloorHeight = 0.0;
|
||||
|
||||
std::vector<sector_t *> SeenSectors;
|
||||
std::vector<uint32_t> SeenSectors;
|
||||
std::vector<bool> SectorSeen;
|
||||
std::vector<uint32_t> SubsectorDepths;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -386,3 +386,4 @@ TArray<FString> I_GetGogPaths()
|
|||
// GOG's Doom games are Windows only at the moment
|
||||
return TArray<FString>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<FString> I_GetGogPaths()
|
||||
{
|
||||
// GOG's Doom games are Windows only at the moment
|
||||
return TArray<FString>();
|
||||
// GOG's Doom games are Windows only at the moment
|
||||
return TArray<FString>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -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<HuffNode> &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];
|
||||
|
|
|
@ -38,7 +38,7 @@ class FZipExploder
|
|||
int DecodeSFValue(const TArray<HuffNode> ¤tTree);
|
||||
int DecodeSF(TArray<HuffNode> &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);
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize);
|
|
@ -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<int>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<unsigned int>(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<unsigned int>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<uint32_t>(0xffff, FileSize);
|
||||
|
||||
uBackRead = 4;
|
||||
|
@ -149,9 +140,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin)
|
|||
|
||||
uReadSize = MIN<uint32_t>((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<char*>(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<uint16_t, uint16_t> time_to_dos(struct tm *time)
|
||||
{
|
||||
std::pair<uint16_t, uint16_t> 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<uint16_t, uint16_t> &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<uint16_t, uint16_t> &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<FString> &filenames, TArray<FCompress
|
|||
// try to determine local time
|
||||
struct tm *ltime;
|
||||
time_t ttime;
|
||||
uint16_t mydate, mytime;
|
||||
ttime = time(nullptr);
|
||||
ltime = localtime(&ttime);
|
||||
time_to_dos(ltime, &mydate, &mytime);
|
||||
auto dostime = time_to_dos(ltime);
|
||||
|
||||
TArray<int> positions;
|
||||
|
||||
|
@ -634,7 +627,7 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
|
|||
{
|
||||
for (unsigned i = 0; i < filenames.Size(); i++)
|
||||
{
|
||||
int pos = AppendToZip(f, filenames[i], content[i], mydate, mytime);
|
||||
int pos = AppendToZip(f, filenames[i], content[i], dostime);
|
||||
if (pos == -1)
|
||||
{
|
||||
delete f;
|
||||
|
@ -647,7 +640,7 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
|
|||
int dirofs = (int)f->Tell();
|
||||
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<FString> &filenames, TArray<FCompress
|
|||
dirend.Magic = ZIP_ENDOFDIR;
|
||||
dirend.DiskNumber = 0;
|
||||
dirend.FirstDisk = 0;
|
||||
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort(filenames.Size());
|
||||
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)filenames.Size());
|
||||
dirend.DirectoryOffset = LittleLong(dirofs);
|
||||
dirend.DirectorySize = LittleLong(f->Tell() - dirofs);
|
||||
dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs));
|
||||
dirend.ZipCommentLength = 0;
|
||||
if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend))
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#include <zlib.h>
|
||||
#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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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<FString> Songs;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||
#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag
|
||||
|
||||
#include <zlib.h>
|
||||
#include "rapidjson/rapidjson.h"
|
||||
#include "rapidjson/writer.h"
|
||||
#include "rapidjson/prettywriter.h"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#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<uint8_t> &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;
|
||||
|
|
|
@ -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 --------------------
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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<SoundHandle, bool> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -50,7 +50,7 @@ FSoundFontManager sfmanager;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
std::pair<FileReader *, FString> FSoundFontReader::LookupFile(const char *name)
|
||||
std::pair<FileReader, FString> FSoundFontReader::LookupFile(const char *name)
|
||||
{
|
||||
if (!IsAbsPath(name))
|
||||
{
|
||||
|
@ -58,12 +58,12 @@ std::pair<FileReader *, FString> 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);
|
||||
|
|
|
@ -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<FileReader *, FString> 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<FileReader , FString> 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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -33,11 +33,6 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "i_musicinterns.h"
|
||||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -74,28 +74,28 @@ static bool inited = false;
|
|||
|
||||
off_t MPG123Decoder::file_lseek(void *handle, off_t offset, int whence)
|
||||
{
|
||||
FileReader *reader = reinterpret_cast<MPG123Decoder*>(handle)->Reader;
|
||||
auto &reader = reinterpret_cast<MPG123Decoder*>(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<MPG123Decoder*>(handle)->Reader;
|
||||
return (ssize_t)reader->Read(buffer, (long)bytes);
|
||||
auto &reader = reinterpret_cast<MPG123Decoder*>(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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<uint32_t>(loop_end, 0, (uint32_t)decoder->getSampleLength());
|
||||
Reader = reader;
|
||||
Loop_End = sampleLength == 0 ? loop_end : clamp<uint32_t>(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)
|
||||
|
|
|
@ -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<SoftSynthMIDIDevice *>(MIDI));
|
||||
return InitPlayback();
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue