Merge remote-tracking branch 'gzdoom/master'

This commit is contained in:
Magnus Norddahl 2024-01-10 04:03:35 +01:00
commit 805bce1166
214 changed files with 10327 additions and 6393 deletions

View file

@ -256,7 +256,7 @@ if( MSVC )
# String pooling
# Function-level linking
# Disable run-time type information
set( ALL_C_FLAGS "/GF /Gy /permissive-" )
set( ALL_C_FLAGS "/GF /Gy /permissive- /utf-8" )
if ( HAVE_VULKAN )
set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_VULKAN" )

View file

@ -0,0 +1,89 @@
@echo off
goto aftercopyright
**
** auto-setup-windows-arm.cmd
** Automatic (easy) setup and build script for Windows ARM (cross compiling on x64) - please have a
** build of x64 in your build folder ready before executing this script!
**
** Note that this script assumes you have both 'git' and 'cmake' installed properly and in your PATH!
** This script also assumes you have installed a build system that cmake can automatically detect.
** Such as Visual Studio Community. Requires appropriate SDK installed too!
** Without these items, this script will FAIL! So make sure you have your build environment properly
** set up in order for this script to succeed.
**
** The purpose of this script is to get someone easily going with a full working compile of GZDoom.
** This allows anyone to make simple changes or tweaks to the engine as they see fit and easily
** compile their own copy without having to follow complex instructions to get it working.
** Every build environment is different, and every computer system is different - this should work
** in most typical systems under Windows but it may fail under certain types of systems or conditions.
** Not guaranteed to work and your mileage will vary.
**
**---------------------------------------------------------------------------
** Copyright 2024 Rachael Alexanderson and the GZDoom team
** 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.
**---------------------------------------------------------------------------
**
:aftercopyright
setlocal
rem -- Always operate within the build-arm folder
if not exist "%~dp0\build-arm" mkdir "%~dp0\build-arm"
pushd "%~dp0\build-arm"
if exist ..\build\vcpkg if exist ..\build\vcpkg\* git -C ../build/vcpkg pull
if not exist ..\build\vcpkg goto :nobuild
if exist zmusic if exist zmusic\* git -C ./zmusic pull
if not exist zmusic git clone https://github.com/zdoom/zmusic
mkdir "%~dp0\build-arm\zmusic\build"
mkdir "%~dp0\build-arm\vcpkg_installed"
cmake -A ARM64 -S ./zmusic -B ./zmusic/build ^
-DCMAKE_TOOLCHAIN_FILE=../../build/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DVCPKG_LIBSNDFILE=1 ^
-DVCPKG_INSTALLLED_DIR=../vcpkg_installed/ ^
-DCMAKE_CROSSCOMPILING=TRUE
cmake --build ./zmusic/build --config Release -- -maxcpucount -verbosity:minimal
cmake -A ARM64 -S .. -B . ^
-DCMAKE_TOOLCHAIN_FILE=../build/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DZMUSIC_INCLUDE_DIR=./zmusic/include ^
-DZMUSIC_LIBRARIES=./zmusic/build/source/Release/zmusic.lib ^
-DVCPKG_INSTALLLED_DIR=./vcpkg_installed/ ^
-DFORCE_CROSSCOMPILE=TRUE ^
-DIMPORT_EXECUTABLES=../build/ImportExecutables.cmake
cmake --build . --config RelWithDebInfo -- -maxcpucount -verbosity:minimal
rem -- If successful, show the build
if exist RelWithDebInfo\gzdoom.exe explorer.exe RelWithDebInfo
goto :eof
:nobuild
echo Please use auto-setup-windows.cmd to create an x64 build first!

View file

@ -49,8 +49,8 @@ goto aftercopyright
:aftercopyright
setlocal enableextensions
setlocal
rem -- Always operate within the build folder
if not exist "%~dp0\build" mkdir "%~dp0\build"
pushd "%~dp0\build"
@ -61,8 +61,8 @@ if not exist vcpkg git clone https://github.com/microsoft/vcpkg
if exist zmusic if exist vcpkg\* git -C ./zmusic pull
if not exist zmusic git clone https://github.com/zdoom/zmusic
mkdir "%~dp0\build\zmusic\build"
mkdir "%~dp0\build\vcpkg_installed"
if not exist "%~dp0\build\zmusic\build" mkdir "%~dp0\build\zmusic\build"
if not exist "%~dp0\build\vcpkg_installed" mkdir "%~dp0\build\vcpkg_installed"
cmake -A x64 -S ./zmusic -B ./zmusic/build ^
-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ^
@ -78,5 +78,5 @@ cmake -A x64 -S .. -B . ^
cmake --build . --config RelWithDebInfo -- -maxcpucount -verbosity:minimal
rem -- If successful, show the build
if exist RelWithDebInfo\gzdoom.exe explorer.exe RelWithDebInfo
if not errorlevel 1 if exist RelWithDebInfo\gzdoom.exe explorer.exe RelWithDebInfo

View file

@ -4,5 +4,11 @@
#include <cstdint>
#include <string>
std::vector<uint8_t> LoadWidgetFontData(const std::string& name);
std::vector<uint8_t> LoadWidgetImageData(const std::string& name);
struct SingleFontData
{
std::vector<uint8_t> fontdata;
std::string language;
};
std::vector<SingleFontData> LoadWidgetFontData(const std::string& name);
std::vector<uint8_t> LoadWidgetData(const std::string& name);

View file

@ -16,6 +16,8 @@ public:
void Toggle();
double GetPreferredHeight() const;
std::function<void(bool)> FuncChanged;
void SetRadioStyle(bool on) { radiostyle = on; }
protected:
void OnPaint(Canvas* canvas) override;
@ -27,5 +29,6 @@ protected:
private:
std::string text;
bool checked = false;
bool radiostyle = false;
bool mouseDownActive = false;
};

View file

@ -19,6 +19,7 @@ public:
void Activate();
std::function<void(int)> OnChanged;
std::function<void()> OnActivated;
protected:

View file

@ -149,7 +149,7 @@ private:
bool select_all_on_focus_gain = false;
std::shared_ptr<Font> font = Font::Create("Segoe UI", 12.0);
std::shared_ptr<Font> font = Font::Create("NotoSans", 12.0);
template<typename T>
static T clamp(T val, T minval, T maxval) { return std::max<T>(std::min<T>(val, maxval), minval); }

View file

@ -41,9 +41,10 @@ public:
class CanvasFont
{
public:
CanvasFont(const std::string& fontname, double height) : fontname(fontname), height(height)
CanvasFont(const std::string& fontname, double height, std::vector<uint8_t> data) : fontname(fontname), height(height)
{
ttf = std::make_unique<TrueTypeFont>(std::make_shared<TrueTypeFontFileData>(LoadWidgetFontData(fontname)));
auto tdata = std::make_shared<TrueTypeFontFileData>(std::move(data));
ttf = std::make_unique<TrueTypeFont>(tdata);
textmetrics = ttf->GetTextMetrics(height);
}
@ -54,6 +55,7 @@ public:
CanvasGlyph* getGlyph(uint32_t utfchar)
{
uint32_t glyphIndex = ttf->GetGlyphIndex(utfchar);
if (glyphIndex == 0) return nullptr;
auto& glyph = glyphs[glyphIndex];
if (glyph)
@ -120,6 +122,52 @@ public:
std::unordered_map<uint32_t, std::unique_ptr<CanvasGlyph>> glyphs;
};
class CanvasFontGroup
{
public:
struct SingleFont
{
std::unique_ptr<CanvasFont> font;
std::string language;
};
CanvasFontGroup(const std::string& fontname, double height) : height(height)
{
auto fontdata = LoadWidgetFontData(fontname);
fonts.resize(fontdata.size());
for (size_t i = 0; i < fonts.size(); i++)
{
fonts[i].font = std::make_unique<CanvasFont>(fontname, height, fontdata[i].fontdata);
fonts[i].language = fontdata[i].language;
}
}
CanvasGlyph* getGlyph(uint32_t utfchar, const char* lang = nullptr)
{
for (int i = 0; i < 2; i++)
{
for (auto& fd : fonts)
{
if (i == 1 || lang == nullptr || *lang == 0 || fd.language.empty() || fd.language == lang)
{
auto g = fd.font->getGlyph(utfchar);
if (g) return g;
}
}
}
return nullptr;
}
TrueTypeTextMetrics& GetTextMetrics()
{
return fonts[0].font->textmetrics;
}
double height;
std::vector<SingleFont> fonts;
};
class BitmapCanvas : public Canvas
{
public:
@ -172,6 +220,8 @@ public:
int getClipMaxX() const;
int getClipMaxY() const;
void setLanguage(const char* lang) { language = lang; }
std::unique_ptr<CanvasTexture> createTexture(int width, int height, const void* pixels, ImageFormat format = ImageFormat::B8G8R8A8);
template<typename T>
@ -179,7 +229,7 @@ public:
DisplayWindow* window = nullptr;
std::unique_ptr<CanvasFont> font;
std::unique_ptr<CanvasFontGroup> font;
std::unique_ptr<CanvasTexture> whiteTexture;
Point origin;
@ -191,6 +241,7 @@ public:
std::vector<uint32_t> pixels;
std::unordered_map<std::shared_ptr<Image>, std::unique_ptr<CanvasTexture>> imageTextures;
std::string language;
};
BitmapCanvas::BitmapCanvas(DisplayWindow* window) : window(window)
@ -198,7 +249,7 @@ BitmapCanvas::BitmapCanvas(DisplayWindow* window) : window(window)
uiscale = window->GetDpiScale();
uint32_t white = 0xffffffff;
whiteTexture = createTexture(1, 1, &white);
font = std::make_unique<CanvasFont>("Segoe UI", 13.0*uiscale);
font = std::make_unique<CanvasFontGroup>("NotoSans", 13.0 * uiscale);
}
BitmapCanvas::~BitmapCanvas()
@ -358,8 +409,8 @@ void BitmapCanvas::drawText(const Point& pos, const Colorf& color, const std::st
UTF8Reader reader(text.data(), text.size());
while (!reader.is_end())
{
CanvasGlyph* glyph = font->getGlyph(reader.character());
if (!glyph->texture)
CanvasGlyph* glyph = font->getGlyph(reader.character(), language.c_str());
if (!glyph || !glyph->texture)
{
glyph = font->getGlyph(32);
}
@ -379,13 +430,13 @@ void BitmapCanvas::drawText(const Point& pos, const Colorf& color, const std::st
Rect BitmapCanvas::measureText(const std::string& text)
{
double x = 0.0;
double y = font->textmetrics.ascender - font->textmetrics.descender;
double y = font->GetTextMetrics().ascender - font->GetTextMetrics().descender;
UTF8Reader reader(text.data(), text.size());
while (!reader.is_end())
{
CanvasGlyph* glyph = font->getGlyph(reader.character());
if (!glyph->texture)
CanvasGlyph* glyph = font->getGlyph(reader.character(), language.c_str());
if (!glyph || !glyph->texture)
{
glyph = font->getGlyph(32);
}
@ -401,8 +452,9 @@ VerticalTextPosition BitmapCanvas::verticalTextAlign()
{
VerticalTextPosition align;
align.top = 0.0f;
align.baseline = font->textmetrics.ascender / uiscale;
align.bottom = (font->textmetrics.ascender - font->textmetrics.descender) / uiscale;
auto tm = font->GetTextMetrics();
align.baseline = tm.ascender / uiscale;
align.bottom = (tm.ascender - tm.descender) / uiscale;
return align;
}

View file

@ -62,7 +62,7 @@ std::shared_ptr<Image> Image::LoadResource(const std::string& resourcename, doub
if (extension == "png")
{
auto filedata = LoadWidgetImageData(resourcename);
auto filedata = LoadWidgetData(resourcename);
std::vector<unsigned char> pixels;
unsigned long width = 0, height = 0;
@ -74,7 +74,7 @@ std::shared_ptr<Image> Image::LoadResource(const std::string& resourcename, doub
}
else if (extension == "svg")
{
auto filedata = LoadWidgetImageData(resourcename);
auto filedata = LoadWidgetData(resourcename);
filedata.push_back(0);
NSVGimage* svgimage = nsvgParse((char*)filedata.data(), "px", (float)(96.0 * dpiscale));

View file

@ -192,6 +192,11 @@ void nsvgDelete(NSVGimage* image);
#include <stdio.h>
#include <math.h>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4244)
#endif
#define NSVG_PI (3.14159265358979323846264338327f)
#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs.
@ -3093,6 +3098,10 @@ void nsvgDelete(NSVGimage* image)
free(image);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif // NANOSVG_IMPLEMENTATION
#endif // NANOSVG_H

View file

@ -42,14 +42,14 @@ void CheckboxLabel::OnPaint(Canvas* canvas)
{
if (checked)
{
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 5.0, 10.0, 10.0), Colorf::fromRgba8(100, 100, 100));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 4.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
canvas->fillRect(Rect::xywh(2.0, GetHeight() * 0.5 - 3.0, 6.0, 6.0), Colorf::fromRgba8(226, 223, 219));
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), Colorf::fromRgba8(100, 100, 100));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
canvas->fillRect(Rect::xywh(2.0, GetHeight() * 0.5 - 4.0, 6.0, 6.0), Colorf::fromRgba8(226, 223, 219));
}
else
{
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 5.0, 10.0, 10.0), Colorf::fromRgba8(68, 68, 68));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 4.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
canvas->fillRect(Rect::xywh(0.0, GetHeight() * 0.5 - 6.0, 10.0, 10.0), Colorf::fromRgba8(99, 99, 99));
canvas->fillRect(Rect::xywh(1.0, GetHeight() * 0.5 - 5.0, 8.0, 8.0), Colorf::fromRgba8(51, 51, 51));
}
canvas->drawText(Point(14.0, GetHeight() - 5.0), Colorf::fromRgba8(255, 255, 255), text);
@ -83,6 +83,8 @@ void CheckboxLabel::OnKeyUp(EInputKey key)
void CheckboxLabel::Toggle()
{
checked = !checked;
bool oldchecked = checked;
checked = radiostyle? true : !checked;
Update();
if (checked != oldchecked && FuncChanged) FuncChanged(checked);
}

View file

@ -27,6 +27,7 @@ void ListView::SetSelectedItem(int index)
if (selectedItem != index && index >= 0 && index < items.size())
{
selectedItem = index;
if (OnChanged) OnChanged(selectedItem);
Update();
}
}

View file

@ -819,11 +819,7 @@
// [@CC_FALLTHROUGH{@]
// \def ASMJIT_FALLTHROUGH
// The code falls through annotation (switch / case).
#if ASMJIT_CC_CLANG && __cplusplus >= 201103L
# define ASMJIT_FALLTHROUGH [[clang::fallthrough]]
#else
# define ASMJIT_FALLTHROUGH (void)0
#endif
# define ASMJIT_FALLTHROUGH [[fallthrough]]
// [@CC_FALLTHROUGH}@]
// [@CC_UNUSED{@]

View file

@ -617,6 +617,7 @@ file( GLOB HEADER_FILES
common/scripting/frontend/*.h
utility/*.h
launcher/*.h
scripting/*.h
scripting/backend/*.h
scripting/decorate/*.h
@ -958,6 +959,8 @@ set (PCH_SOURCES
rendering/swrenderer/textures/warptexture.cpp
rendering/swrenderer/textures/swcanvastexture.cpp
events.cpp
launcher/launcherwindow.cpp
common/audio/sound/i_sound.cpp
common/audio/sound/oalsound.cpp
common/audio/sound/s_environment.cpp
@ -972,6 +975,7 @@ set (PCH_SOURCES
common/2d/v_drawtext.cpp
common/2d/v_draw.cpp
common/2d/wipe.cpp
common/thirdparty/animlib.cpp
common/thirdparty/gain_analysis.cpp
common/thirdparty/sfmt/SFMT.cpp
common/startscreen/startscreen.cpp
@ -980,7 +984,6 @@ set (PCH_SOURCES
common/startscreen/startscreen_strife.cpp
common/startscreen/startscreen_generic.cpp
common/startscreen/endoom.cpp
common/widgets/launcherwindow.cpp
common/widgets/errorwindow.cpp
common/widgets/netstartwindow.cpp
common/widgets/widgetresourcedata.cpp
@ -1006,7 +1009,6 @@ set (PCH_SOURCES
common/textures/skyboxtexture.cpp
common/textures/animtexture.cpp
common/textures/v_collection.cpp
common/textures/animlib.cpp
common/textures/formats/automaptexture.cpp
common/textures/formats/brightmaptexture.cpp
common/textures/formats/buildtexture.cpp
@ -1068,6 +1070,7 @@ set (PCH_SOURCES
common/utility/name.cpp
common/utility/r_memory.cpp
common/utility/bounds.cpp
common/utility/writezip.cpp
common/thirdparty/base64.cpp
common/thirdparty/md5.cpp
common/thirdparty/superfasthash.cpp
@ -1199,6 +1202,8 @@ set( GAME_SOURCES
common/filesystem/source/file_pak.cpp
common/filesystem/source/file_whres.cpp
common/filesystem/source/file_ssi.cpp
common/filesystem/source/file_hog.cpp
common/filesystem/source/file_mvl.cpp
common/filesystem/source/file_directory.cpp
common/filesystem/source/resourcefile.cpp
common/filesystem/source/files.cpp
@ -1206,6 +1211,7 @@ set( GAME_SOURCES
common/filesystem/source/fs_findfile.cpp
common/filesystem/source/fs_stringpool.cpp
common/filesystem/source/unicode.cpp
common/filesystem/source/critsec.cpp
)
@ -1292,6 +1298,7 @@ include_directories(
scripting
scripting/zscript
rendering
launcher
../libraries/ZVulkan/include
../libraries/ZWidget/include
../libraries/dp_rect_pack
@ -1500,6 +1507,7 @@ source_group("Utility\\Smackerdec" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_D
source_group("Utility\\Smackerdec\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/include/.+")
source_group("Utility\\Smackerdec\\Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/src/.+")
source_group("Statusbar" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_statusbar/.+")
source_group("Launcher" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/launcher/.+")
source_group("Versioning" FILES version.h win32/zdoom.rc)
source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h)
source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h common/engine/sc_man_scanner.re)

View file

@ -194,7 +194,7 @@ public:
TArray<TwoDVertex> mVertices;
TArray<RenderCommand> mData;
int Width, Height;
bool isIn2D;
bool isIn2D = false;
bool locked = false; // prevents clearing of the data so it can be reused multiple times (useful for screen fades)
float screenFade = 1.f;
DVector2 offset;
@ -319,7 +319,7 @@ public:
RefCountedPtr<DShape2DBufferInfo> bufferInfo;
DrawParms* lastParms;
DrawParms* lastParms = nullptr;
void OnDestroy() override;
};

View file

@ -182,8 +182,8 @@ static void SetupGenMidi()
}
auto genmidi = fileSystem.ReadFile(lump);
if (genmidi.GetSize() < 8 + 175 * 36 || memcmp(genmidi.GetMem(), "#OPL_II#", 8)) return;
ZMusic_SetGenMidi(genmidi.GetBytes() + 8);
if (genmidi.size() < 8 + 175 * 36 || memcmp(genmidi.data(), "#OPL_II#", 8)) return;
ZMusic_SetGenMidi(genmidi.bytes() + 8);
}
static void SetupWgOpn()
@ -194,7 +194,7 @@ static void SetupWgOpn()
return;
}
auto data = fileSystem.ReadFile(lump);
ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize());
ZMusic_SetWgOpn(data.data(), (uint32_t)data.size());
}
static void SetupDMXGUS()
@ -206,7 +206,7 @@ static void SetupDMXGUS()
return;
}
auto data = fileSystem.ReadFile(lump);
ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize());
ZMusic_SetDmxGus(data.data(), (uint32_t)data.size());
}
#endif

View file

@ -218,7 +218,7 @@ FileReader FZipPatReader::OpenFile(const char *name)
auto lump = resf->FindEntry(name);
if (lump >= 0)
{
return resf->GetEntryReader(lump);
return resf->GetEntryReader(lump, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE);
}
}
fr.OpenFile(name);
@ -465,19 +465,16 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all
//
//==========================================================================
FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed)
FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *const name, int allowed)
{
if (name == nullptr) return nullptr;
// First check if the given name is inside the loaded resources.
// To avoid clashes this will only be done if the name has the '.cfg' extension.
// Sound fonts cannot be loaded this way.
if (name != nullptr)
const char *p = name + strlen(name) - 4;
if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0)
{
const char *p = name + strlen(name) - 4;
if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0)
{
return new FLumpPatchSetReader(name);
}
return new FLumpPatchSetReader(name);
}
// Next check if the file is a .sf file

View file

@ -57,6 +57,7 @@
#include "c_cvars.h"
#include "md5.h"
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern int nomusic;
@ -74,14 +75,12 @@ float saved_relative_volume = 1.0f; // this could be used to implement an ACS Fa
MusicVolumeMap MusicVolumes;
MidiDeviceMap MidiDevices;
static FileReader DefaultOpenMusic(const char* fn)
static int DefaultFindMusic(const char* fn)
{
// This is the minimum needed to make the music system functional.
FileReader fr;
fr.OpenFile(fn);
return fr;
return -1;
}
static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic };
MusicCallbacks mus_cb = { nullptr, DefaultFindMusic };
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -94,18 +93,47 @@ EXTERN_CVAR(Float, fluid_gain)
CVAR(Bool, mus_calcgain, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song.
CVAR(Bool, mus_usereplaygain, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // changing this will only take effect for the next song.
CUSTOM_CVAR(Float, mus_gainoffset, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // for customizing the base volume
{
if (self > 10.f) self = 10.f;
mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset);
}
// CODE --------------------------------------------------------------------
//==========================================================================
//
// OpenMusic
//
// opens a FileReader for the music - used as a callback to keep
// implementation details out of the core player.
//
//==========================================================================
static FileReader OpenMusic(const char* musicname)
{
FileReader reader;
if (!FileExists(musicname))
{
int lumpnum;
lumpnum = mus_cb.FindMusic(musicname);
if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music);
if (lumpnum == -1)
{
Printf("Music \"%s\" not found\n", musicname);
}
else if (fileSystem.FileLength(lumpnum) != 0)
{
reader = fileSystem.ReopenFileReader(lumpnum);
}
}
else
{
// Load an external file.
reader.OpenFile(musicname);
}
return reader;
}
void S_SetMusicCallbacks(MusicCallbacks* cb)
{
mus_cb = *cb;
if (mus_cb.OpenMusic == nullptr) mus_cb.OpenMusic = DefaultOpenMusic; // without this we are dead in the water.
if (mus_cb.FindMusic == nullptr) mus_cb.FindMusic = DefaultFindMusic; // without this we are dead in the water.
}
int MusicEnabled() // int return is for scripting
@ -167,12 +195,12 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
if (mus_playing.isfloat)
{
written = ZMusic_FillStream(mus_playing.handle, buff, len);
if (mus_playing.replayGainFactor != 1.f)
if (mus_playing.musicVolume != 1.f)
{
float* fbuf = (float*)buff;
for (int i = 0; i < len / 4; i++)
{
fbuf[i] *= mus_playing.replayGainFactor;
fbuf[i] *= mus_playing.musicVolume;
}
}
}
@ -184,7 +212,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
float* fbuf = (float*)buff;
for (int i = 0; i < len / 4; i++)
{
fbuf[i] = convert[i] * mus_playing.replayGainFactor * (1.f/32768.f);
fbuf[i] = convert[i] * mus_playing.musicVolume * (1.f/32768.f);
}
}
@ -404,14 +432,14 @@ static FString ReplayGainHash(ZMusicCustomReader* reader, int flength, int playe
{
std::string playparam = _playparam;
uint8_t buffer[50000]; // for performance reasons only hash the start of the file. If we wanted to do this to large waveform songs it'd cause noticable lag.
TArray<uint8_t> buffer(50000, true); // for performance reasons only hash the start of the file. If we wanted to do this to large waveform songs it'd cause noticable lag.
uint8_t digest[16];
char digestout[33];
auto length = reader->read(reader, buffer, 50000);
auto length = reader->read(reader, buffer.data(), 50000);
reader->seek(reader, 0, SEEK_SET);
MD5Context md5;
md5.Init();
md5.Update(buffer, (int)length);
md5.Update(buffer.data(), (int)length);
md5.Final(digest);
for (size_t j = 0; j < sizeof(digest); ++j)
@ -420,7 +448,7 @@ static FString ReplayGainHash(ZMusicCustomReader* reader, int flength, int playe
}
digestout[32] = 0;
auto type = ZMusic_IdentifyMIDIType((uint32_t*)buffer, 32);
auto type = ZMusic_IdentifyMIDIType((uint32_t*)buffer.data(), 32);
if (type == MIDI_NOTMIDI) return FStringf("%d:%s", flength, digestout);
// get the default for MIDI synth
@ -508,26 +536,24 @@ CCMD(setreplaygain)
if (argv.argc() < 2)
{
Printf("Usage: setreplaygain {dB}\n");
Printf("Current replay gain is %f dB\n", mus_playing.replayGain);
Printf("Current replay gain is %f dB\n", AmplitudeTodB(mus_playing.musicVolume));
return;
}
float dB = (float)strtod(argv[1], nullptr);
if (dB > 10) dB = 10; // don't blast the speakers. Values above 2 or 3 are very rare.
gainMap.Insert(mus_playing.hash, dB);
SaveGains();
mus_playing.replayGain = dB;
mus_playing.replayGainFactor = (float)dBToAmplitude(mus_playing.replayGain + mus_gainoffset);
mus_playing.musicVolume = (float)dBToAmplitude(dB);
}
static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const char *playparam)
{
mus_playing.replayGain = 0.f;
mus_playing.replayGainFactor = dBToAmplitude(mus_gainoffset);
mus_playing.musicVolume = 1;
fluid_gain->Callback();
mod_dumb_mastervolume->Callback();
if (!mus_usereplaygain) return;
FileReader reader = mus_cb.OpenMusic(musicname);
FileReader reader = OpenMusic(musicname);
if (!reader.isOpen()) return;
int flength = (int)reader.GetLength();
auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper.
@ -539,8 +565,7 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const
auto entry = gainMap.CheckKey(hash);
if (entry)
{
mus_playing.replayGain = *entry;
mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset);
mus_playing.musicVolume = dBToAmplitude(*entry);
return;
}
if (!mus_calcgain) return;
@ -624,19 +649,18 @@ static void CheckReplayGain(const char *musicname, EMidiDevice playertype, const
}
ZMusic_Close(handle);
GainAnalyzer analyzer;
int result = analyzer.InitGainAnalysis(fmt.mSampleRate);
auto analyzer = std::make_unique<GainAnalyzer>();
int result = analyzer->InitGainAnalysis(fmt.mSampleRate);
if (result == GAIN_ANALYSIS_OK)
{
result = analyzer.AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2);
result = analyzer->AnalyzeSamples(lbuffer.Data(), rbuffer.Size() == 0 ? nullptr : rbuffer.Data(), lbuffer.Size(), rbuffer.Size() == 0 ? 1 : 2);
if (result == GAIN_ANALYSIS_OK)
{
auto gain = analyzer.GetTitleGain();
Printf("Calculated replay gain for %s at %f dB\n", hash.GetChars(), gain);
auto gain = analyzer->GetTitleGain();
Printf("Calculated replay gain for %s (%s) at %f dB\n", musicname, hash.GetChars(), gain);
gainMap.Insert(hash, gain);
mus_playing.replayGain = gain;
mus_playing.replayGainFactor = dBToAmplitude(mus_playing.replayGain + mus_gainoffset);
mus_playing.musicVolume = dBToAmplitude(gain);
SaveGains();
}
}
@ -692,7 +716,6 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
}
ZMusic_MusicStream handle = nullptr;
MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname);
// Strip off any leading file:// component.
if (strncmp(musicname, "file://", 7) == 0)
@ -701,8 +724,10 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
}
// opening the music must be done by the game because it's different depending on the game's file system use.
FileReader reader = mus_cb.OpenMusic(musicname);
FileReader reader = OpenMusic(musicname);
if (!reader.isOpen()) return false;
auto m = reader.Read();
reader.Seek(0, FileReader::SeekSet);
// shutdown old music
S_StopMusic(true);
@ -724,8 +749,19 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
}
else
{
int lumpnum = mus_cb.FindMusic(musicname);
MidiDeviceSetting* devp = MidiDevices.CheckKey(lumpnum);
CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : "");
auto volp = MusicVolumes.CheckKey(lumpnum);
if (volp)
{
mus_playing.musicVolume = *volp;
}
else
{
CheckReplayGain(musicname, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : "");
}
auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper.
mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : "");
if (mus_playing.handle == nullptr)
@ -741,13 +777,12 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
if (mus_playing.handle != 0)
{ // play it
auto volp = MusicVolumes.CheckKey(musicname);
float vol = volp ? *volp : 1.f;
if (!S_StartMusicPlaying(mus_playing.handle, looping, vol, order))
if (!S_StartMusicPlaying(mus_playing.handle, looping, 1.f, order))
{
Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
return false;
}
S_CreateStream();
mus_playing.baseorder = order;
return true;

View file

@ -24,7 +24,7 @@ void S_PauseAllCustomStreams(bool on);
struct MusicCallbacks
{
FString(*LookupFileName)(const char* fn, int &order);
FileReader(*OpenMusic)(const char* fn);
int(*FindMusic)(const char* fn);
};
void S_SetMusicCallbacks(MusicCallbacks* cb);
@ -68,19 +68,20 @@ struct MidiDeviceSetting
FString args;
};
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
typedef TMap<FName, float> MusicVolumeMap;
typedef TMap<int, MidiDeviceSetting> MidiDeviceMap;
typedef TMap<int, float> MusicVolumeMap;
extern MidiDeviceMap MidiDevices;
extern MusicVolumeMap MusicVolumes;
extern MusicCallbacks mus_cb;
struct MusPlayingInfo
{
FString name;
ZMusic_MusicStream handle;
int lumpnum;
int baseorder;
float replayGain;
float replayGainFactor;
float musicVolume;
bool loop;
bool isfloat;
FString LastSong; // last music that was played

View file

@ -1,643 +0,0 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 2008 by authors.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#ifndef AL_ALEXT_H
#define AL_ALEXT_H
#include <stddef.h>
/* Define int64 and uint64 types */
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
(defined(__cplusplus) && __cplusplus >= 201103L)
#include <stdint.h>
typedef int64_t _alsoft_int64_t;
typedef uint64_t _alsoft_uint64_t;
#elif defined(_WIN32)
typedef __int64 _alsoft_int64_t;
typedef unsigned __int64 _alsoft_uint64_t;
#else
/* Fallback if nothing above works */
#include <stdint.h>
typedef int64_t _alsoft_int64_t;
typedef uint64_t _alsoft_uint64_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef AL_LOKI_IMA_ADPCM_format
#define AL_LOKI_IMA_ADPCM_format 1
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
#endif
#ifndef AL_LOKI_WAVE_format
#define AL_LOKI_WAVE_format 1
#define AL_FORMAT_WAVE_EXT 0x10002
#endif
#ifndef AL_EXT_vorbis
#define AL_EXT_vorbis 1
#define AL_FORMAT_VORBIS_EXT 0x10003
#endif
#ifndef AL_LOKI_quadriphonic
#define AL_LOKI_quadriphonic 1
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
#endif
#ifndef AL_EXT_float32
#define AL_EXT_float32 1
#define AL_FORMAT_MONO_FLOAT32 0x10010
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_EXT_double
#define AL_EXT_double 1
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
#endif
#ifndef AL_EXT_MULAW
#define AL_EXT_MULAW 1
#define AL_FORMAT_MONO_MULAW_EXT 0x10014
#define AL_FORMAT_STEREO_MULAW_EXT 0x10015
#endif
#ifndef AL_EXT_ALAW
#define AL_EXT_ALAW 1
#define AL_FORMAT_MONO_ALAW_EXT 0x10016
#define AL_FORMAT_STEREO_ALAW_EXT 0x10017
#endif
#ifndef ALC_LOKI_audio_channel
#define ALC_LOKI_audio_channel 1
#define ALC_CHAN_MAIN_LOKI 0x500001
#define ALC_CHAN_PCM_LOKI 0x500002
#define ALC_CHAN_CD_LOKI 0x500003
#endif
#ifndef AL_EXT_MCFORMATS
#define AL_EXT_MCFORMATS 1
/* Provides support for surround sound buffer formats with 8, 16, and 32-bit
* samples.
*
* QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left,
* Rear Right).
* QUAD16: Signed 16-bit, Quadraphonic.
* QUAD32: 32-bit float, Quadraphonic.
* REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right).
* REAR16: Signed 16-bit, Rear Stereo.
* REAR32: 32-bit float, Rear Stereo.
* 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center,
* LFE, Side Left, Side Right). Note that some audio systems may label
* 5.1's Side channels as Rear or Surround; they are equivalent for the
* purposes of this extension.
* 51CHN16: Signed 16-bit, 5.1 Surround.
* 51CHN32: 32-bit float, 5.1 Surround.
* 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center,
* LFE, Rear Center, Side Left, Side Right).
* 61CHN16: Signed 16-bit, 6.1 Surround.
* 61CHN32: 32-bit float, 6.1 Surround.
* 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center,
* LFE, Rear Left, Rear Right, Side Left, Side Right).
* 71CHN16: Signed 16-bit, 7.1 Surround.
* 71CHN32: 32-bit float, 7.1 Surround.
*/
#define AL_FORMAT_QUAD8 0x1204
#define AL_FORMAT_QUAD16 0x1205
#define AL_FORMAT_QUAD32 0x1206
#define AL_FORMAT_REAR8 0x1207
#define AL_FORMAT_REAR16 0x1208
#define AL_FORMAT_REAR32 0x1209
#define AL_FORMAT_51CHN8 0x120A
#define AL_FORMAT_51CHN16 0x120B
#define AL_FORMAT_51CHN32 0x120C
#define AL_FORMAT_61CHN8 0x120D
#define AL_FORMAT_61CHN16 0x120E
#define AL_FORMAT_61CHN32 0x120F
#define AL_FORMAT_71CHN8 0x1210
#define AL_FORMAT_71CHN16 0x1211
#define AL_FORMAT_71CHN32 0x1212
#endif
#ifndef AL_EXT_MULAW_MCFORMATS
#define AL_EXT_MULAW_MCFORMATS 1
#define AL_FORMAT_MONO_MULAW 0x10014
#define AL_FORMAT_STEREO_MULAW 0x10015
#define AL_FORMAT_QUAD_MULAW 0x10021
#define AL_FORMAT_REAR_MULAW 0x10022
#define AL_FORMAT_51CHN_MULAW 0x10023
#define AL_FORMAT_61CHN_MULAW 0x10024
#define AL_FORMAT_71CHN_MULAW 0x10025
#endif
#ifndef AL_EXT_IMA4
#define AL_EXT_IMA4 1
#define AL_FORMAT_MONO_IMA4 0x1300
#define AL_FORMAT_STEREO_IMA4 0x1301
#endif
#ifndef AL_EXT_STATIC_BUFFER
#define AL_EXT_STATIC_BUFFER 1
typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
#endif
#endif
#ifndef ALC_EXT_EFX
#define ALC_EXT_EFX 1
#include "efx.h"
#endif
#ifndef ALC_EXT_disconnect
#define ALC_EXT_disconnect 1
#define ALC_CONNECTED 0x313
#endif
#ifndef ALC_EXT_thread_local_context
#define ALC_EXT_thread_local_context 1
typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);
typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context);
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
#endif
#endif
#ifndef AL_EXT_source_distance_model
#define AL_EXT_source_distance_model 1
#define AL_SOURCE_DISTANCE_MODEL 0x200
#endif
#ifndef AL_SOFT_buffer_sub_data
#define AL_SOFT_buffer_sub_data 1
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
#endif
#endif
#ifndef AL_SOFT_loop_points
#define AL_SOFT_loop_points 1
#define AL_LOOP_POINTS_SOFT 0x2015
#endif
#ifndef AL_EXT_FOLDBACK
#define AL_EXT_FOLDBACK 1
#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK"
#define AL_FOLDBACK_EVENT_BLOCK 0x4112
#define AL_FOLDBACK_EVENT_START 0x4111
#define AL_FOLDBACK_EVENT_STOP 0x4113
#define AL_FOLDBACK_MODE_MONO 0x4101
#define AL_FOLDBACK_MODE_STEREO 0x4102
typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei);
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK);
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback);
AL_API void AL_APIENTRY alRequestFoldbackStop(void);
#endif
#endif
#ifndef ALC_EXT_DEDICATED
#define ALC_EXT_DEDICATED 1
#define AL_DEDICATED_GAIN 0x0001
#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001
#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
#endif
#ifndef AL_SOFT_buffer_samples
#define AL_SOFT_buffer_samples 1
/* Channel configurations */
#define AL_MONO_SOFT 0x1500
#define AL_STEREO_SOFT 0x1501
#define AL_REAR_SOFT 0x1502
#define AL_QUAD_SOFT 0x1503
#define AL_5POINT1_SOFT 0x1504
#define AL_6POINT1_SOFT 0x1505
#define AL_7POINT1_SOFT 0x1506
/* Sample types */
#define AL_BYTE_SOFT 0x1400
#define AL_UNSIGNED_BYTE_SOFT 0x1401
#define AL_SHORT_SOFT 0x1402
#define AL_UNSIGNED_SHORT_SOFT 0x1403
#define AL_INT_SOFT 0x1404
#define AL_UNSIGNED_INT_SOFT 0x1405
#define AL_FLOAT_SOFT 0x1406
#define AL_DOUBLE_SOFT 0x1407
#define AL_BYTE3_SOFT 0x1408
#define AL_UNSIGNED_BYTE3_SOFT 0x1409
/* Storage formats */
#define AL_MONO8_SOFT 0x1100
#define AL_MONO16_SOFT 0x1101
#define AL_MONO32F_SOFT 0x10010
#define AL_STEREO8_SOFT 0x1102
#define AL_STEREO16_SOFT 0x1103
#define AL_STEREO32F_SOFT 0x10011
#define AL_QUAD8_SOFT 0x1204
#define AL_QUAD16_SOFT 0x1205
#define AL_QUAD32F_SOFT 0x1206
#define AL_REAR8_SOFT 0x1207
#define AL_REAR16_SOFT 0x1208
#define AL_REAR32F_SOFT 0x1209
#define AL_5POINT1_8_SOFT 0x120A
#define AL_5POINT1_16_SOFT 0x120B
#define AL_5POINT1_32F_SOFT 0x120C
#define AL_6POINT1_8_SOFT 0x120D
#define AL_6POINT1_16_SOFT 0x120E
#define AL_6POINT1_32F_SOFT 0x120F
#define AL_7POINT1_8_SOFT 0x1210
#define AL_7POINT1_16_SOFT 0x1211
#define AL_7POINT1_32F_SOFT 0x1212
/* Buffer attributes */
#define AL_INTERNAL_FORMAT_SOFT 0x2008
#define AL_BYTE_LENGTH_SOFT 0x2009
#define AL_SAMPLE_LENGTH_SOFT 0x200A
#define AL_SEC_LENGTH_SOFT 0x200B
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
#endif
#endif
#ifndef AL_SOFT_direct_channels
#define AL_SOFT_direct_channels 1
#define AL_DIRECT_CHANNELS_SOFT 0x1033
#endif
#ifndef ALC_SOFT_loopback
#define ALC_SOFT_loopback 1
#define ALC_FORMAT_CHANNELS_SOFT 0x1990
#define ALC_FORMAT_TYPE_SOFT 0x1991
/* Sample types */
#define ALC_BYTE_SOFT 0x1400
#define ALC_UNSIGNED_BYTE_SOFT 0x1401
#define ALC_SHORT_SOFT 0x1402
#define ALC_UNSIGNED_SHORT_SOFT 0x1403
#define ALC_INT_SOFT 0x1404
#define ALC_UNSIGNED_INT_SOFT 0x1405
#define ALC_FLOAT_SOFT 0x1406
/* Channel configurations */
#define ALC_MONO_SOFT 0x1500
#define ALC_STEREO_SOFT 0x1501
#define ALC_QUAD_SOFT 0x1503
#define ALC_5POINT1_SOFT 0x1504
#define ALC_6POINT1_SOFT 0x1505
#define ALC_7POINT1_SOFT 0x1506
typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*);
typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum);
typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName);
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
#endif
#endif
#ifndef AL_EXT_STEREO_ANGLES
#define AL_EXT_STEREO_ANGLES 1
#define AL_STEREO_ANGLES 0x1030
#endif
#ifndef AL_EXT_SOURCE_RADIUS
#define AL_EXT_SOURCE_RADIUS 1
#define AL_SOURCE_RADIUS 0x1031
#endif
#ifndef AL_SOFT_source_latency
#define AL_SOFT_source_latency 1
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
typedef _alsoft_int64_t ALint64SOFT;
typedef _alsoft_uint64_t ALuint64SOFT;
typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*);
typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT);
typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT);
typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value);
AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3);
AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values);
AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value);
AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3);
AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values);
AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value);
AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3);
AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values);
AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value);
AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3);
AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values);
#endif
#endif
#ifndef ALC_EXT_DEFAULT_FILTER_ORDER
#define ALC_EXT_DEFAULT_FILTER_ORDER 1
#define ALC_DEFAULT_FILTER_ORDER 0x1100
#endif
#ifndef AL_SOFT_deferred_updates
#define AL_SOFT_deferred_updates 1
#define AL_DEFERRED_UPDATES_SOFT 0xC002
typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alDeferUpdatesSOFT(void);
AL_API void AL_APIENTRY alProcessUpdatesSOFT(void);
#endif
#endif
#ifndef AL_SOFT_block_alignment
#define AL_SOFT_block_alignment 1
#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C
#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D
#endif
#ifndef AL_SOFT_MSADPCM
#define AL_SOFT_MSADPCM 1
#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302
#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303
#endif
#ifndef AL_SOFT_source_length
#define AL_SOFT_source_length 1
/*#define AL_BYTE_LENGTH_SOFT 0x2009*/
/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/
/*#define AL_SEC_LENGTH_SOFT 0x200B*/
#endif
#ifndef ALC_SOFT_pause_device
#define ALC_SOFT_pause_device 1
typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device);
typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device);
ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);
#endif
#endif
#ifndef AL_EXT_BFORMAT
#define AL_EXT_BFORMAT 1
/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling
* and layout).
*
* BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY).
* BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY).
* BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY).
* BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ).
* BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ).
* BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ).
*/
#define AL_FORMAT_BFORMAT2D_8 0x20021
#define AL_FORMAT_BFORMAT2D_16 0x20022
#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023
#define AL_FORMAT_BFORMAT3D_8 0x20031
#define AL_FORMAT_BFORMAT3D_16 0x20032
#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033
#endif
#ifndef AL_EXT_MULAW_BFORMAT
#define AL_EXT_MULAW_BFORMAT 1
#define AL_FORMAT_BFORMAT2D_MULAW 0x10031
#define AL_FORMAT_BFORMAT3D_MULAW 0x10032
#endif
#ifndef ALC_SOFT_HRTF
#define ALC_SOFT_HRTF 1
#define ALC_HRTF_SOFT 0x1992
#define ALC_DONT_CARE_SOFT 0x0002
#define ALC_HRTF_STATUS_SOFT 0x1993
#define ALC_HRTF_DISABLED_SOFT 0x0000
#define ALC_HRTF_ENABLED_SOFT 0x0001
#define ALC_HRTF_DENIED_SOFT 0x0002
#define ALC_HRTF_REQUIRED_SOFT 0x0003
#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004
#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005
#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994
#define ALC_HRTF_SPECIFIER_SOFT 0x1995
#define ALC_HRTF_ID_SOFT 0x1996
typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index);
typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index);
ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs);
#endif
#endif
#ifndef AL_SOFT_gain_clamp_ex
#define AL_SOFT_gain_clamp_ex 1
#define AL_GAIN_LIMIT_SOFT 0x200E
#endif
#ifndef AL_SOFT_source_resampler
#define AL_SOFT_source_resampler
#define AL_NUM_RESAMPLERS_SOFT 0x1210
#define AL_DEFAULT_RESAMPLER_SOFT 0x1211
#define AL_SOURCE_RESAMPLER_SOFT 0x1212
#define AL_RESAMPLER_NAME_SOFT 0x1213
typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index);
#ifdef AL_ALEXT_PROTOTYPES
AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index);
#endif
#endif
#ifndef AL_SOFT_source_spatialize
#define AL_SOFT_source_spatialize
#define AL_SOURCE_SPATIALIZE_SOFT 0x1214
#define AL_AUTO_SOFT 0x0002
#endif
#ifndef ALC_SOFT_output_limiter
#define ALC_SOFT_output_limiter
#define ALC_OUTPUT_LIMITER_SOFT 0x199A
#endif
#ifndef ALC_SOFT_device_clock
#define ALC_SOFT_device_clock 1
typedef _alsoft_int64_t ALCint64SOFT;
typedef _alsoft_uint64_t ALCuint64SOFT;
#define ALC_DEVICE_CLOCK_SOFT 0x1600
#define ALC_DEVICE_LATENCY_SOFT 0x1601
#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602
#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202
#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203
typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
#endif
#endif
#ifndef AL_SOFT_direct_channels_remix
#define AL_SOFT_direct_channels_remix 1
#define AL_DROP_UNMATCHED_SOFT 0x0001
#define AL_REMIX_UNMATCHED_SOFT 0x0002
#endif
#ifndef AL_SOFT_bformat_ex
#define AL_SOFT_bformat_ex 1
#define AL_AMBISONIC_LAYOUT_SOFT 0x1997
#define AL_AMBISONIC_SCALING_SOFT 0x1998
/* Ambisonic layouts */
#define AL_FUMA_SOFT 0x0000
#define AL_ACN_SOFT 0x0001
/* Ambisonic scalings (normalization) */
/*#define AL_FUMA_SOFT*/
#define AL_SN3D_SOFT 0x0001
#define AL_N3D_SOFT 0x0002
#endif
#ifndef ALC_SOFT_loopback_bformat
#define ALC_SOFT_loopback_bformat 1
#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997
#define ALC_AMBISONIC_SCALING_SOFT 0x1998
#define ALC_AMBISONIC_ORDER_SOFT 0x1999
#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B
#define ALC_BFORMAT3D_SOFT 0x1507
/* Ambisonic layouts */
#define ALC_FUMA_SOFT 0x0000
#define ALC_ACN_SOFT 0x0001
/* Ambisonic scalings (normalization) */
/*#define ALC_FUMA_SOFT*/
#define ALC_SN3D_SOFT 0x0001
#define ALC_N3D_SOFT 0x0002
#endif
#ifndef AL_SOFT_effect_target
#define AL_SOFT_effect_target
#define AL_EFFECTSLOT_TARGET_SOFT 0x199C
#endif
#ifndef AL_SOFT_events
#define AL_SOFT_events 1
#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2
#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3
#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4
#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5
#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6
typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param,
ALsizei length, const ALchar *message,
void *userParam);
typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable);
typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam);
typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname);
typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable);
AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam);
AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname);
AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);
#endif
#endif
#ifndef ALC_SOFT_reopen_device
#define ALC_SOFT_reopen_device
typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device,
const ALCchar *deviceName, const ALCint *attribs);
#ifdef AL_ALEXT_PROTOTYPES
ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName,
const ALCint *attribs);
#endif
#endif
#ifndef AL_SOFT_callback_buffer
#define AL_SOFT_callback_buffer
#define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0
#define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1
typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes);
typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr);
typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value);
typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3);
typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr);
AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr);
AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2);
AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr);
#endif
#endif
#ifndef AL_SOFT_UHJ
#define AL_SOFT_UHJ
#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2
#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3
#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4
#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5
#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6
#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7
#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8
#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9
#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA
#define AL_STEREO_MODE_SOFT 0x19B0
#define AL_NORMAL_SOFT 0x0000
#define AL_SUPER_STEREO_SOFT 0x0001
#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1
#endif
#ifndef ALC_SOFT_output_mode
#define ALC_SOFT_output_mode
#define ALC_OUTPUT_MODE_SOFT 0x19AC
#define ALC_ANY_SOFT 0x19AD
/*#define ALC_MONO_SOFT 0x1500*/
/*#define ALC_STEREO_SOFT 0x1501*/
#define ALC_STEREO_BASIC_SOFT 0x19AE
#define ALC_STEREO_UHJ_SOFT 0x19AF
#define ALC_STEREO_HRTF_SOFT 0x19B2
/*#define ALC_QUAD_SOFT 0x1503*/
#define ALC_SURROUND_5_1_SOFT 0x1504
#define ALC_SURROUND_6_1_SOFT 0x1505
#define ALC_SURROUND_7_1_SOFT 0x1506
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -21,7 +21,7 @@
#include "alc.h"
#endif
#include "alext.h"
#include "thirdparty/alext.h"
class OpenALSoundStream;

View file

@ -13,8 +13,8 @@
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
@ -22,22 +22,22 @@
#define AL_ALEXT_H
#include <stddef.h>
/* Define int64_t and uint64_t types */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#include <inttypes.h>
#elif defined(_WIN32) && defined(__GNUC__)
/* Define int64 and uint64 types */
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
(defined(__cplusplus) && __cplusplus >= 201103L)
#include <stdint.h>
typedef int64_t _alsoft_int64_t;
typedef uint64_t _alsoft_uint64_t;
#elif defined(_WIN32)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef __int64 _alsoft_int64_t;
typedef unsigned __int64 _alsoft_uint64_t;
#else
/* Fallback if nothing above works */
#include <inttypes.h>
#include <stdint.h>
typedef int64_t _alsoft_int64_t;
typedef uint64_t _alsoft_uint64_t;
#endif
#include "alc.h"
#include "al.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -97,6 +97,31 @@ extern "C" {
#ifndef AL_EXT_MCFORMATS
#define AL_EXT_MCFORMATS 1
/* Provides support for surround sound buffer formats with 8, 16, and 32-bit
* samples.
*
* QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left,
* Rear Right).
* QUAD16: Signed 16-bit, Quadraphonic.
* QUAD32: 32-bit float, Quadraphonic.
* REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right).
* REAR16: Signed 16-bit, Rear Stereo.
* REAR32: 32-bit float, Rear Stereo.
* 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center,
* LFE, Side Left, Side Right). Note that some audio systems may label
* 5.1's Side channels as Rear or Surround; they are equivalent for the
* purposes of this extension.
* 51CHN16: Signed 16-bit, 5.1 Surround.
* 51CHN32: 32-bit float, 5.1 Surround.
* 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center,
* LFE, Rear Center, Side Left, Side Right).
* 61CHN16: Signed 16-bit, 6.1 Surround.
* 61CHN32: 32-bit float, 6.1 Surround.
* 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center,
* LFE, Rear Left, Rear Right, Side Left, Side Right).
* 71CHN16: Signed 16-bit, 7.1 Surround.
* 71CHN32: 32-bit float, 7.1 Surround.
*/
#define AL_FORMAT_QUAD8 0x1204
#define AL_FORMAT_QUAD16 0x1205
#define AL_FORMAT_QUAD32 0x1206
@ -133,9 +158,9 @@ extern "C" {
#ifndef AL_EXT_STATIC_BUFFER
#define AL_EXT_STATIC_BUFFER 1
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
AL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
#endif
#endif
@ -168,9 +193,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
#define AL_SOFT_buffer_sub_data 1
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
#endif
#endif
@ -318,8 +343,8 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe
#define AL_SOFT_source_latency 1
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
typedef int64_t ALint64SOFT;
typedef uint64_t ALuint64SOFT;
typedef _alsoft_int64_t ALint64SOFT;
typedef _alsoft_uint64_t ALuint64SOFT;
typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);
@ -356,11 +381,11 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64
#ifndef AL_SOFT_deferred_updates
#define AL_SOFT_deferred_updates 1
#define AL_DEFERRED_UPDATES_SOFT 0xC002
typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void);
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void);
AL_API void AL_APIENTRY alDeferUpdatesSOFT(void);
AL_API void AL_APIENTRY alProcessUpdatesSOFT(void);
#endif
#endif
@ -393,6 +418,224 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);
#endif
#endif
#ifndef AL_EXT_BFORMAT
#define AL_EXT_BFORMAT 1
/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling
* and layout).
*
* BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY).
* BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY).
* BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY).
* BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ).
* BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ).
* BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ).
*/
#define AL_FORMAT_BFORMAT2D_8 0x20021
#define AL_FORMAT_BFORMAT2D_16 0x20022
#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023
#define AL_FORMAT_BFORMAT3D_8 0x20031
#define AL_FORMAT_BFORMAT3D_16 0x20032
#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033
#endif
#ifndef AL_EXT_MULAW_BFORMAT
#define AL_EXT_MULAW_BFORMAT 1
#define AL_FORMAT_BFORMAT2D_MULAW 0x10031
#define AL_FORMAT_BFORMAT3D_MULAW 0x10032
#endif
#ifndef ALC_SOFT_HRTF
#define ALC_SOFT_HRTF 1
#define ALC_HRTF_SOFT 0x1992
#define ALC_DONT_CARE_SOFT 0x0002
#define ALC_HRTF_STATUS_SOFT 0x1993
#define ALC_HRTF_DISABLED_SOFT 0x0000
#define ALC_HRTF_ENABLED_SOFT 0x0001
#define ALC_HRTF_DENIED_SOFT 0x0002
#define ALC_HRTF_REQUIRED_SOFT 0x0003
#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004
#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005
#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994
#define ALC_HRTF_SPECIFIER_SOFT 0x1995
#define ALC_HRTF_ID_SOFT 0x1996
typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index);
typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index);
ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs);
#endif
#endif
#ifndef AL_SOFT_gain_clamp_ex
#define AL_SOFT_gain_clamp_ex 1
#define AL_GAIN_LIMIT_SOFT 0x200E
#endif
#ifndef AL_SOFT_source_resampler
#define AL_SOFT_source_resampler
#define AL_NUM_RESAMPLERS_SOFT 0x1210
#define AL_DEFAULT_RESAMPLER_SOFT 0x1211
#define AL_SOURCE_RESAMPLER_SOFT 0x1212
#define AL_RESAMPLER_NAME_SOFT 0x1213
typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index);
#ifdef AL_ALEXT_PROTOTYPES
AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index);
#endif
#endif
#ifndef AL_SOFT_source_spatialize
#define AL_SOFT_source_spatialize
#define AL_SOURCE_SPATIALIZE_SOFT 0x1214
#define AL_AUTO_SOFT 0x0002
#endif
#ifndef ALC_SOFT_output_limiter
#define ALC_SOFT_output_limiter
#define ALC_OUTPUT_LIMITER_SOFT 0x199A
#endif
#ifndef ALC_SOFT_device_clock
#define ALC_SOFT_device_clock 1
typedef _alsoft_int64_t ALCint64SOFT;
typedef _alsoft_uint64_t ALCuint64SOFT;
#define ALC_DEVICE_CLOCK_SOFT 0x1600
#define ALC_DEVICE_LATENCY_SOFT 0x1601
#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602
#define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202
#define AL_SEC_OFFSET_CLOCK_SOFT 0x1203
typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
#endif
#endif
#ifndef AL_SOFT_direct_channels_remix
#define AL_SOFT_direct_channels_remix 1
#define AL_DROP_UNMATCHED_SOFT 0x0001
#define AL_REMIX_UNMATCHED_SOFT 0x0002
#endif
#ifndef AL_SOFT_bformat_ex
#define AL_SOFT_bformat_ex 1
#define AL_AMBISONIC_LAYOUT_SOFT 0x1997
#define AL_AMBISONIC_SCALING_SOFT 0x1998
/* Ambisonic layouts */
#define AL_FUMA_SOFT 0x0000
#define AL_ACN_SOFT 0x0001
/* Ambisonic scalings (normalization) */
/*#define AL_FUMA_SOFT*/
#define AL_SN3D_SOFT 0x0001
#define AL_N3D_SOFT 0x0002
#endif
#ifndef ALC_SOFT_loopback_bformat
#define ALC_SOFT_loopback_bformat 1
#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997
#define ALC_AMBISONIC_SCALING_SOFT 0x1998
#define ALC_AMBISONIC_ORDER_SOFT 0x1999
#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B
#define ALC_BFORMAT3D_SOFT 0x1507
/* Ambisonic layouts */
#define ALC_FUMA_SOFT 0x0000
#define ALC_ACN_SOFT 0x0001
/* Ambisonic scalings (normalization) */
/*#define ALC_FUMA_SOFT*/
#define ALC_SN3D_SOFT 0x0001
#define ALC_N3D_SOFT 0x0002
#endif
#ifndef AL_SOFT_effect_target
#define AL_SOFT_effect_target
#define AL_EFFECTSLOT_TARGET_SOFT 0x199C
#endif
#ifndef AL_SOFT_events
#define AL_SOFT_events 1
#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2
#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3
#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4
#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5
#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6
typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param,
ALsizei length, const ALchar *message,
void *userParam);
typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable);
typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam);
typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname);
typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable);
AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam);
AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname);
AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);
#endif
#endif
#ifndef ALC_SOFT_reopen_device
#define ALC_SOFT_reopen_device
typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device,
const ALCchar *deviceName, const ALCint *attribs);
#ifdef AL_ALEXT_PROTOTYPES
ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName,
const ALCint *attribs);
#endif
#endif
#ifndef AL_SOFT_callback_buffer
#define AL_SOFT_callback_buffer
#define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0
#define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1
typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes);
typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr);
typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value);
typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3);
typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr);
AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr);
AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2);
AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr);
#endif
#endif
#ifndef AL_SOFT_UHJ
#define AL_SOFT_UHJ
#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2
#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3
#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4
#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5
#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6
#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7
#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8
#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9
#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA
#define AL_STEREO_MODE_SOFT 0x19B0
#define AL_NORMAL_SOFT 0x0000
#define AL_SUPER_STEREO_SOFT 0x0001
#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1
#endif
#ifndef ALC_SOFT_output_mode
#define ALC_SOFT_output_mode
#define ALC_OUTPUT_MODE_SOFT 0x19AC
#define ALC_ANY_SOFT 0x19AD
/*#define ALC_MONO_SOFT 0x1500*/
/*#define ALC_STEREO_SOFT 0x1501*/
#define ALC_STEREO_BASIC_SOFT 0x19AE
#define ALC_STEREO_UHJ_SOFT 0x19AF
#define ALC_STEREO_HRTF_SOFT 0x19B2
/*#define ALC_QUAD_SOFT 0x1503*/
#define ALC_SURROUND_5_1_SOFT 0x1504
#define ALC_SURROUND_6_1_SOFT 0x1505
#define ALC_SURROUND_7_1_SOFT 0x1506
#endif
#ifdef __cplusplus
}
#endif

View file

@ -244,7 +244,7 @@ CCMD (wdir)
{
if (wadnum == -1 || fileSystem.GetFileContainer(i) == wadnum)
{
Printf ("%10d %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i));
Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i));
}
}
}

View file

@ -153,7 +153,7 @@ class AnmPlayer : public MoviePlayer
{
// This doesn't need its own class type
anim_t anim;
FileSys::ResourceData buffer;
FileSys::FileData buffer;
int numframes = 0;
int curframe = 1;
int frametime = 0;
@ -515,7 +515,7 @@ public:
}
else if (soundtrack >= 0)
{
FileReader reader = fileSystem.OpenFileReader(soundtrack);
FileReader reader = fileSystem.ReopenFileReader(soundtrack);
if (reader.isOpen())
{
MusicStream = ZMusic_OpenSong(GetMusicReader(reader), MDEV_DEFAULT, nullptr);
@ -794,7 +794,7 @@ public:
if (sound == INVALID_SOUND)
soundEngine->StopAllChannels();
else
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI : CHANF_NONE, sound, 1.f, ATTN_NONE);
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI | CHANF_FORCE : CHANF_FORCE, sound, 1.f, ATTN_NONE);
}
}
}
@ -838,10 +838,10 @@ MoviePlayer* OpenMovie(const char* filename, TArray<int>& ans, const int* framet
{
auto fn = StripExtension(filename);
DefaultExtension(fn, ".ivf");
fr = fileSystem.OpenFileReader(fn.GetChars());
fr = fileSystem.ReopenFileReader(fn.GetChars());
}
if (!fr.isOpen()) fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen()) fr = fileSystem.ReopenFileReader(filename);
if (!fr.isOpen())
{
size_t nLen = strlen(filename);
@ -849,7 +849,7 @@ MoviePlayer* OpenMovie(const char* filename, TArray<int>& ans, const int* framet
if (nLen >= 3 && isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
{
filename += 3;
fr = fileSystem.OpenFileReader(filename);
fr = fileSystem.ReopenFileReader(filename);
}
if (!fr.isOpen())
{

View file

@ -55,7 +55,7 @@ enum ETexMode
};
// Legacy render styles
enum ERenderStyle
enum ERenderStyle : int
{
STYLE_None, // Do not draw
STYLE_Normal, // Normal; just copy the image to the screen

View file

@ -200,10 +200,10 @@ void FScanner :: OpenLumpNum (int lump)
{
Close ();
{
auto mem = fileSystem.OpenFileReader(lump);
auto buff = ScriptBuffer.LockNewBuffer(mem.GetLength());
mem.Read(buff, mem.GetLength());
buff[mem.GetLength()] = 0;
auto len = fileSystem.FileLength(lump);
auto buff = ScriptBuffer.LockNewBuffer(len);
fileSystem.ReadFile(lump, buff);
buff[len] = 0;
ScriptBuffer.UnlockBuffer();
}
ScriptName = fileSystem.GetFileFullPath(lump).c_str();
@ -260,6 +260,7 @@ void FScanner::PrepareScript ()
StateOptions = false;
StringBuffer[0] = '\0';
BigStringBuffer = "";
ParseError = false;
}
//==========================================================================
@ -1089,13 +1090,14 @@ void FScanner::ScriptError (const char *message, ...)
va_end (arglist);
}
ParseError = true;
if (NoFatalErrors)
{
Printf(TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
Printf(TEXTCOLOR_RED "%sScript error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", PrependMessage.GetChars(), ScriptName.GetChars(),
AlreadyGot ? AlreadyGotLine : Line, composed.GetChars());
return;
}
I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
I_Error ("%sScript error, \"%s\" line %d:\n%s\n", PrependMessage.GetChars(), ScriptName.GetChars(),
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
}
@ -1121,7 +1123,8 @@ void FScanner::ScriptMessage (const char *message, ...)
va_end (arglist);
}
Printf (TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
ParseError = true;
Printf (TEXTCOLOR_RED "%sScript error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", PrependMessage.GetChars(), ScriptName.GetChars(),
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
}
@ -1383,4 +1386,3 @@ int ParseHex(const char* hex, FScriptPosition* sc)
return num;
}

View file

@ -192,6 +192,7 @@ public:
void ScriptError(const char *message, ...) GCCPRINTF(2,3);
void ScriptMessage(const char *message, ...) GCCPRINTF(2,3);
void SetPrependMessage(const FString& message) { PrependMessage = message; }
bool isText();
@ -238,6 +239,7 @@ protected:
bool StateOptions;
bool Escape;
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
FString PrependMessage = "";
bool ScanValue(bool allowfloat, bool evaluate);

View file

@ -753,7 +753,6 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
EndObject();
buff.filename = nullptr;
buff.mSize = (unsigned)w->mOutString.GetSize();
buff.mZipFlags = 0;
buff.mCRC32 = crc32(0, (const Bytef*)w->mOutString.GetString(), buff.mSize);
uint8_t *compressbuf = new uint8_t[buff.mSize+1];
@ -762,9 +761,9 @@ FCompressedBuffer FSerializer::GetCompressedOutput()
int err;
stream.next_in = (Bytef *)w->mOutString.GetString();
stream.avail_in = buff.mSize;
stream.avail_in = (unsigned)buff.mSize;
stream.next_out = (Bytef*)compressbuf;
stream.avail_out = buff.mSize;
stream.avail_out = (unsigned)buff.mSize;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;

View file

@ -47,27 +47,29 @@
//
//==========================================================================
void FStringTable::LoadStrings (const char *language)
void FStringTable::LoadStrings (FileSys::FileSystem& fileSystem_, const char *language)
{
int lastlump, lump;
fileSystem = &fileSystem_;
allStrings.Clear();
lastlump = 0;
while ((lump = fileSystem.FindLump("LMACROS", &lastlump)) != -1)
while ((lump = fileSystem->FindLump("LMACROS", &lastlump)) != -1)
{
readMacros(lump);
}
lastlump = 0;
while ((lump = fileSystem.FindLump ("LANGUAGE", &lastlump)) != -1)
while ((lump = fileSystem->FindLump ("LANGUAGE", &lastlump)) != -1)
{
auto lumpdata = fileSystem.ReadFile(lump);
auto lumpdata = fileSystem->ReadFile(lump);
if (!ParseLanguageCSV(lump, lumpdata.GetString(), lumpdata.GetSize()))
LoadLanguage (lump, lumpdata.GetString(), lumpdata.GetSize());
if (!ParseLanguageCSV(lump, lumpdata.string(), lumpdata.size()))
LoadLanguage (lump, lumpdata.string(), lumpdata.size());
}
UpdateLanguage(language);
allMacros.Clear();
fileSystem = nullptr;
}
@ -159,9 +161,10 @@ TArray<TArray<FString>> FStringTable::parseCSV(const char* buffer, size_t size)
bool FStringTable::readMacros(int lumpnum)
{
auto lumpdata = fileSystem.ReadFile(lumpnum);
auto data = parseCSV(lumpdata.GetString(), lumpdata.GetSize());
auto lumpdata = fileSystem->ReadFile(lumpnum);
auto data = parseCSV(lumpdata.string(), lumpdata.size());
allMacros.Clear();
for (unsigned i = 1; i < data.Size(); i++)
{
auto macroname = data[i][0];
@ -321,7 +324,7 @@ void FStringTable::LoadLanguage (int lumpnum, const char* buffer, size_t size)
}
else
{
sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %lu characters long.",
sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %zu characters long.",
sc.String, len);
}
}
@ -410,7 +413,7 @@ void FStringTable::DeleteForLabel(int lumpnum, FName label)
{
decltype(allStrings)::Iterator it(allStrings);
decltype(allStrings)::Pair *pair;
auto filenum = fileSystem.GetFileContainer(lumpnum);
auto filenum = fileSystem->GetFileContainer(lumpnum);
while (it.NextPair(pair))
{
@ -432,7 +435,7 @@ void FStringTable::DeleteForLabel(int lumpnum, FName label)
void FStringTable::InsertString(int lumpnum, int langid, FName label, const FString &string)
{
const char *strlangid = (const char *)&langid;
TableElement te = { fileSystem.GetFileContainer(lumpnum), { string, string, string, string } };
TableElement te = { fileSystem->GetFileContainer(lumpnum), { string, string, string, string } };
ptrdiff_t index;
while ((index = te.strings[0].IndexOf("@[")) >= 0)
{

View file

@ -84,7 +84,7 @@ public:
using LangMap = TMap<uint32_t, StringMap>;
using StringMacroMap = TMap<FName, StringMacro>;
void LoadStrings(const char *language);
void LoadStrings(FileSys::FileSystem& fileSystem, const char *language);
void UpdateLanguage(const char* language);
StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison
void SetOverrideStrings(StringMap & map)
@ -108,6 +108,7 @@ public:
private:
FileSys::FileSystem* fileSystem;
FString activeLanguage;
StringMacroMap allMacros;
LangMap allStrings;

View file

@ -0,0 +1,63 @@
#pragma once
#include "fs_files.h"
namespace FileSys {
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
enum ECompressionMethod
{
METHOD_STORED = 0,
METHOD_SHRINK = 1,
METHOD_IMPLODE = 6,
METHOD_DEFLATE = 8,
METHOD_BZIP2 = 12,
METHOD_LZMA = 14,
METHOD_XZ = 95,
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.
METHOD_RFFCRYPT = 1339, // not actual compression but can be put in here to make handling easier.
METHOD_IMPLODE_MIN = 1000, // having discrete types for these avoids keeping around the GPFlags word in Zips.
METHOD_IMPLODE_0 = 1000,
METHOD_IMPLODE_2 = 1002,
METHOD_IMPLODE_4 = 1004,
METHOD_IMPLODE_6 = 1006,
METHOD_IMPLODE_MAX = 1006,
METHOD_INVALID = 0x7fff,
METHOD_TRANSFEROWNER = 0x8000,
};
enum EDecompressFlags
{
DCF_TRANSFEROWNER = 1,
DCF_SEEKABLE = 2,
DCF_EXCEPTIONS = 4,
DCF_CACHED = 8,
};
bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags = 0); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
// This holds a compresed Zip entry with all needed info to decompress it.
struct FCompressedBuffer
{
size_t mSize;
size_t mCompressedSize;
int mMethod;
unsigned mCRC32;
char* mBuffer;
const char* filename;
bool Decompress(char* destbuffer);
void Clean()
{
mSize = mCompressedSize = 0;
if (mBuffer != nullptr)
{
delete[] mBuffer;
mBuffer = nullptr;
}
}
};
}

View file

@ -40,12 +40,11 @@
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <functional>
#include <vector>
#include "fs_swap.h"
#include "tarray.h"
namespace FileSys {
class FileSystemException : public std::exception
@ -72,26 +71,10 @@ public:
}
};
// 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_XZ = 95,
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.
METHOD_TRANSFEROWNER = 0x8000,
};
class FileReader;
// an opaque memory buffer to the file's content. Can either own the memory or just point to an external buffer.
class ResourceData
class FileData
{
void* memory;
size_t length;
@ -99,13 +82,30 @@ class ResourceData
public:
using value_type = uint8_t;
ResourceData() { memory = nullptr; length = 0; owned = true; }
FileData() { memory = nullptr; length = 0; owned = true; }
FileData(const void* memory_, size_t len, bool own = true)
{
length = len;
if (own)
{
length = len;
memory = malloc(len);
owned = true;
if (memory_) memcpy(memory, memory_, len);
}
else
{
memory = (void*)memory_;
owned = false;
}
}
uint8_t* writable() const { return owned? (uint8_t*)memory : nullptr; }
const void* data() const { return memory; }
size_t size() const { return length; }
const char* string() const { return (const char*)memory; }
const uint8_t* bytes() const { return (const uint8_t*)memory; }
ResourceData& operator = (const ResourceData& copy)
FileData& operator = (const FileData& copy)
{
if (owned && memory) free(memory);
length = copy.length;
@ -119,7 +119,7 @@ public:
return *this;
}
ResourceData& operator = (ResourceData&& copy) noexcept
FileData& operator = (FileData&& copy) noexcept
{
if (owned && memory) free(memory);
length = copy.length;
@ -131,13 +131,13 @@ public:
return *this;
}
ResourceData(const ResourceData& copy)
FileData(const FileData& copy)
{
memory = nullptr;
*this = copy;
}
~ResourceData()
~FileData()
{
if (owned && memory) free(memory);
}
@ -168,6 +168,7 @@ public:
};
class FileReaderInterface
{
public:
@ -181,12 +182,8 @@ public:
ptrdiff_t GetLength () const { return Length; }
};
struct FResourceLump;
class FileReader
{
friend struct FResourceLump; // needs access to the private constructor.
FileReaderInterface *mReader = nullptr;
FileReader(const FileReader &r) = delete;
@ -210,13 +207,13 @@ public:
FileReader() {}
FileReader(FileReader &&r)
FileReader(FileReader &&r) noexcept
{
mReader = r.mReader;
r.mReader = nullptr;
}
FileReader& operator =(FileReader &&r)
FileReader& operator =(FileReader &&r) noexcept
{
Close();
mReader = r.mReader;
@ -252,11 +249,7 @@ public:
bool OpenFile(const char *filename, Size start = 0, Size length = -1, bool buffered = false);
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::vector<uint8_t>& data); // take the given array
bool OpenMemoryArray(ResourceData& data); // take the given array
bool OpenMemoryArray(std::function<bool(std::vector<uint8_t>&)> getter); // read contents to a buffer and return a reader to it
bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, bool exceptions = false); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
bool OpenMemoryArray(FileData& data); // take the given array
Size Tell() const
{
@ -273,36 +266,14 @@ public:
return mReader->Read(buffer, len);
}
ResourceData Read(size_t len)
{
ResourceData buffer;
if (len > 0)
{
Size length = mReader->Read(buffer.allocate(len), len);
if ((size_t)length < len) buffer.allocate(length);
}
return buffer;
}
FileData Read(size_t len);
FileData ReadPadded(size_t padding);
ResourceData Read()
FileData Read()
{
return Read(GetLength());
}
ResourceData ReadPadded(size_t padding)
{
auto len = GetLength();
ResourceData buffer;
if (len > 0)
{
auto p = (char*)buffer.allocate(len + padding);
Size length = mReader->Read(p, len);
if (length < len) buffer.clear();
else memset(p + len, 0, padding);
}
return buffer;
}
char *Gets(char *strbuf, Size len)
{

View file

@ -22,42 +22,6 @@ union LumpShortName
};
// A lump in memory.
class FileData
{
public:
FileData() { lump = nullptr; }
const void *GetMem () { return lump->Cache; }
size_t GetSize () { return lump->LumpSize; }
const char* GetString () const { return (const char*)lump->Cache; }
const uint8_t* GetBytes() const { return (const uint8_t*)lump->Cache; }
FileData& operator = (const FileData& copy) = delete;
FileData(const FileData& copy)
{
lump = copy.lump;
lump->Lock();
}
~FileData()
{
if (lump) lump->Unlock();
}
private:
FileData(FResourceLump* nlump)
{
lump = nlump;
if (lump) lump->Lock();
}
FResourceLump* lump;
friend class FileSystem;
};
struct FolderEntry
{
const char *name;
@ -129,9 +93,19 @@ public:
FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); }
FileData ReadFileFullName(const char* name) { return ReadFile(GetNumForFullName(name)); }
FileReader OpenFileReader(int lump); // opens a reader that redirects to the containing file's one.
FileReader ReopenFileReader(int lump, bool alwayscache = false); // opens an independent reader.
FileReader OpenFileReader(int lump, int readertype, int readerflags); // opens a reader that redirects to the containing file's one.
FileReader OpenFileReader(const char* name);
FileReader ReopenFileReader(const char* name, bool alwayscache = false);
FileReader OpenFileReader(int lump)
{
return OpenFileReader(lump, READER_SHARED, READERFLAG_SEEKABLE);
}
FileReader ReopenFileReader(int lump, bool alwayscache = false)
{
return OpenFileReader(lump, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE);
}
int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication
int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names
@ -145,8 +119,7 @@ public:
static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name
int FileLength (int lump) const;
int GetFileOffset (int lump); // [RH] Returns offset of lump in the wadfile
ptrdiff_t FileLength (int lump) const;
int GetFileFlags (int lump); // Return the flags for this lump
const char* GetFileShortName(int lump) const;
const char *GetFileFullName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name
@ -169,9 +142,7 @@ public:
return (int)Files.size();
}
void AddLump(FResourceLump* lump);
int AddExternalFile(const char *filename);
int AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags);
int AddFromBuffer(const char* name, char* data, int size, int id, int flags);
FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
void InitHashChains();
@ -183,20 +154,20 @@ protected:
std::vector<LumpRecord> FileInfo;
std::vector<uint32_t> Hashes; // one allocation for all hash lists.
uint32_t *FirstLumpIndex; // [RH] Hashing stuff moved out of lumpinfo structure
uint32_t *NextLumpIndex;
uint32_t *FirstLumpIndex = nullptr; // [RH] Hashing stuff moved out of lumpinfo structure
uint32_t *NextLumpIndex = nullptr;
uint32_t *FirstLumpIndex_FullName; // The same information for fully qualified paths from .zips
uint32_t *NextLumpIndex_FullName;
uint32_t *FirstLumpIndex_FullName = nullptr; // The same information for fully qualified paths from .zips
uint32_t *NextLumpIndex_FullName = nullptr;
uint32_t *FirstLumpIndex_NoExt; // The same information for fully qualified paths from .zips
uint32_t *NextLumpIndex_NoExt;
uint32_t *FirstLumpIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips
uint32_t *NextLumpIndex_NoExt = nullptr;
uint32_t* FirstLumpIndex_ResId; // The same information for fully qualified paths from .zips
uint32_t* NextLumpIndex_ResId;
uint32_t* FirstLumpIndex_ResId = nullptr; // The same information for fully qualified paths from .zips
uint32_t* NextLumpIndex_ResId = nullptr;
uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size()
uint32_t NumWads;
uint32_t NumWads = 0;
int IwadIndex = -1;
int MaxIwadIndex = -1;

View file

@ -23,7 +23,6 @@ using FileList = std::vector<FileListEntry>;
struct FCompressedBuffer;
bool ScanDirectory(std::vector<FileListEntry>& list, const char* dirpath, const char* match, bool nosubdir = false, bool readhidden = false);
bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t contentcount);
bool FS_DirEntryExists(const char* pathname, bool* isdir);
inline void FixPathSeparator(char* path)

View file

@ -7,6 +7,7 @@
#include <vector>
#include <string>
#include "fs_files.h"
#include "fs_decompress.h"
namespace FileSys {
@ -18,7 +19,6 @@ void strReplace(std::string& str, const char* from, const char* to);
struct LumpFilterInfo
{
std::vector<std::string> gameTypeFilter; // this can contain multiple entries
std::string dotFilter;
// The following are for checking if the root directory of a zip can be removed.
std::vector<std::string> reservedFolders;
@ -78,125 +78,69 @@ typedef enum {
enum ELumpFlags
{
LUMPF_MAYBEFLAT = 1, // might be a flat outside F_START/END
LUMPF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names.
LUMPF_EMBEDDED = 4, // marks an embedded resource file for later processing.
LUMPF_SHORTNAME = 8, // the stored name is a short extension-less name
LUMPF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader.
RESFF_MAYBEFLAT = 1, // might be a flat inside a WAD outside F_START/END
RESFF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names.
RESFF_EMBEDDED = 4, // marks an embedded resource file for later processing.
RESFF_SHORTNAME = 8, // the stored name is a short extension-less name
RESFF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader.
RESFF_NEEDFILESTART = 32, // The real position is not known yet and needs to be calculated on access
};
// This holds a compresed Zip entry with all needed info to decompress it.
struct FCompressedBuffer
enum EReaderType
{
size_t mSize;
size_t mCompressedSize;
int mMethod;
int mZipFlags;
unsigned mCRC32;
char *mBuffer;
const char* filename;
bool Decompress(char *destbuffer);
void Clean()
{
mSize = mCompressedSize = 0;
if (mBuffer != nullptr)
{
delete[] mBuffer;
mBuffer = nullptr;
}
}
READER_SHARED = 0, // returns a view into the parent's reader.
READER_NEW = 1, // opens a new file handle
READER_CACHED = 2, // returns a MemoryArrayReader
READERFLAG_SEEKABLE = 1 // ensure the reader is seekable.
};
struct FResourceLump
struct FResourceEntry
{
protected:
friend class FResourceFile;
friend class FWadFile; // this still needs direct access.
friend class FileData;
friend class FileSystem;
friend class FLumpFile;
friend class FLumpReader;
friend class FGrpFile;
friend class F7ZFile;
friend class FSSIFile;
friend class FWHResFile;
friend class FZipFile;
friend class FPakFile;
friend class FRFFFile;
friend class FDirectory;
friend int lumpcmp(const void* a, const void* b);
int LumpSize;
int RefCount;
//protected:
const char* FullName;
//public:
uint8_t Flags;
char * Cache;
FResourceFile * Owner;
public:
FResourceLump()
{
Cache = NULL;
Owner = NULL;
Flags = 0;
RefCount = 0;
FullName = "";
LumpSize = 0;
}
virtual ~FResourceLump();
protected:
virtual FileReader *GetReader();
virtual FileReader NewReader();
virtual int GetFileOffset() { return -1; }
virtual int GetIndexNum() const { return -1; }
virtual int GetNamespace() const { return 0; }
void LumpNameSetup(const char* iname, StringPool* allocator);
void CheckEmbedded(LumpFilterInfo* lfi);
virtual FCompressedBuffer GetRawData();
void *Lock(); // validates the cache and increases the refcount.
int Unlock(); // decreases the refcount and frees the buffer
unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; }
const char* getName() { return FullName; }
void clearName() { FullName = ""; }
protected:
virtual int FillCache() { return -1; }
size_t Length;
size_t CompressedSize;
const char* FileName;
size_t Position;
int ResourceID;
uint32_t CRC32;
uint16_t Flags;
uint16_t Method;
int16_t Namespace;
};
void SetMainThread();
class FResourceFile
{
public:
FResourceFile(const char* filename, StringPool* sp);
FResourceFile(const char* filename, FileReader& r, StringPool* sp);
const char* NormalizeFileName(const char* fn, int fallbackcp = 0);
FResourceEntry* AllocateEntries(int count);
void GenerateHash();
void PostProcessArchive(LumpFilterInfo* filter);
protected:
FileReader Reader;
const char* FileName;
FResourceEntry* Entries = nullptr;
uint32_t NumLumps;
char Hash[48];
StringPool* stringpool;
FResourceFile(const char *filename, StringPool* sp);
FResourceFile(const char *filename, FileReader &r, StringPool* sp);
// for archives that can contain directories
void GenerateHash();
void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter);
virtual void SetEntryAddress(uint32_t entry)
{
Entries[entry].Flags &= ~RESFF_NEEDFILESTART;
}
bool IsFileInFolder(const char* const resPath);
void CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi);
private:
uint32_t FirstLump;
int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max);
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(const char* 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);
int FilterLumps(const std::string& filtername, uint32_t max);
bool FindPrefixRange(const char* filter, uint32_t max, uint32_t &start, uint32_t &end);
void JunkLeftoverFilters(uint32_t max);
void FindCommonFolder(LumpFilterInfo* filter);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
public:
@ -211,47 +155,45 @@ public:
void SetFirstLump(uint32_t f) { FirstLump = f; }
const char* GetHash() const { return Hash; }
virtual FResourceLump *GetLump(int no) = 0;
int EntryCount() const { return NumLumps; }
int FindEntry(const char* name);
size_t Length(int entry)
size_t Length(uint32_t entry)
{
auto l = GetLump(entry);
return l ? l->LumpSize : -1;
return (entry < NumLumps) ? Entries[entry].Length : 0;
}
size_t Offset(uint32_t entry)
{
return (entry < NumLumps) ? Entries[entry].Position : 0;
}
FileReader GetEntryReader(int entry, bool newreader = true)
// default is the safest reader type.
virtual FileReader GetEntryReader(uint32_t entry, int readertype = READER_NEW, int flags = READERFLAG_SEEKABLE);
int GetEntryFlags(uint32_t entry)
{
auto l = GetLump(entry);
return l ? l->NewReader() : FileReader();
return (entry < NumLumps) ? Entries[entry].Flags : 0;
}
int GetEntryFlags(int entry)
int GetEntryNamespace(uint32_t entry)
{
auto l = GetLump(entry);
return l ? l->Flags : 0;
return (entry < NumLumps) ? Entries[entry].Namespace : (int)ns_hidden;
}
ResourceData Read(int entry)
int GetEntryResourceID(uint32_t entry)
{
auto fr = GetEntryReader(entry, false);
return fr.Read();
return (entry < NumLumps) ? Entries[entry].ResourceID : -1;
}
const char* getName(int entry)
const char* getName(uint32_t entry)
{
auto l = GetLump(entry);
return l ? l->FullName : nullptr;
}
FCompressedBuffer GetRawData(int entry)
{
auto l = GetLump(entry);
if (!l) return {};
return l->GetRawData();
return (entry < NumLumps) ? Entries[entry].FileName : nullptr;
}
virtual FileData Read(uint32_t entry);
virtual FCompressedBuffer GetRawData(uint32_t entry);
FileReader Destroy()
{
auto fr = std::move(Reader);

View file

@ -7,7 +7,8 @@
#define FORCE_PACKED
#endif
namespace FileSys {
#include <stdint.h>
#pragma pack(1)
// FZipCentralInfo
@ -107,5 +108,4 @@ struct FZipLocalFileHeader
// File header flags.
#define ZF_ENCRYPTED 0x1
}
#endif

View file

@ -44,6 +44,8 @@
#include <stdlib.h>
#include <assert.h>
#include <memory>
#include "ancientzip.h"
namespace FileSys {
@ -125,7 +127,7 @@ static const unsigned char BitReverse4[] = {
#define FIRST_BIT_LEN 8
#define REST_BIT_LEN 4
void FZipExploder::InsertCode(TArray<HuffNode> &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value)
void FZipExploder::InsertCode(std::vector<HuffNode> &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value)
{
assert(len > 0);
unsigned int node = pos + (code & ((1 << bits) - 1));
@ -161,12 +163,12 @@ void FZipExploder::InsertCode(TArray<HuffNode> &decoder, unsigned int pos, int b
}
}
unsigned int FZipExploder::InitTable(TArray<HuffNode> &decoder, int numspots)
unsigned int FZipExploder::InitTable(std::vector<HuffNode> &decoder, int numspots)
{
unsigned int start = decoder.Size();
decoder.Reserve(numspots);
size_t start = decoder.size();
decoder.resize(decoder.size() + numspots);
memset(&decoder[start], 0, sizeof(HuffNode)*numspots);
return start;
return (unsigned)start;
}
int FZipExploder::buildercmp(const void *a, const void *b)
@ -180,7 +182,7 @@ int FZipExploder::buildercmp(const void *a, const void *b)
return d;
}
int FZipExploder::BuildDecoder(TArray<HuffNode> &decoder, TableBuilder *values, int numvals)
int FZipExploder::BuildDecoder(std::vector<HuffNode> &decoder, TableBuilder *values, int numvals)
{
int i;
@ -218,7 +220,7 @@ int FZipExploder::BuildDecoder(TArray<HuffNode> &decoder, TableBuilder *values,
}
int FZipExploder::DecodeSFValue(const TArray<HuffNode> &decoder)
int FZipExploder::DecodeSFValue(const std::vector<HuffNode> &decoder)
{
unsigned int bits = FIRST_BIT_LEN, table = 0, code;
const HuffNode *pos;
@ -236,7 +238,7 @@ int FZipExploder::DecodeSFValue(const TArray<HuffNode> &decoder)
}
int FZipExploder::DecodeSF(TArray<HuffNode> &decoder, int numvals)
int FZipExploder::DecodeSF(std::vector<HuffNode> &decoder, int numvals)
{
TableBuilder builder[256];
unsigned char a, c;
@ -341,10 +343,19 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &_In, unsigned int InLeft)
{
// don't allocate this on the stack, it's a bit on the large side.
struct work
{
unsigned char ReadBuf[256];
unsigned short Parent[HSIZE];
unsigned char Value[HSIZE], Stack[HSIZE];
};
auto s = std::make_unique<work>();
unsigned char* ReadBuf = s->ReadBuf;
unsigned short* Parent = s->Parent;
unsigned char* Value = s->Value, * Stack = s->Stack;
FileReader *In = &_In;
unsigned char ReadBuf[256];
unsigned short Parent[HSIZE];
unsigned char Value[HSIZE], Stack[HSIZE];
unsigned char *newstr;
int len;
int KwKwK, codesize = 9; /* start at 9 bits/code */

View file

@ -27,18 +27,18 @@ class FZipExploder
unsigned short Code;
};
TArray<HuffNode> LiteralDecoder;
TArray<HuffNode> DistanceDecoder;
TArray<HuffNode> LengthDecoder;
std::vector<HuffNode> LiteralDecoder;
std::vector<HuffNode> DistanceDecoder;
std::vector<HuffNode> LengthDecoder;
unsigned char ReadBuf[256];
unsigned int bs, be;
static int buildercmp(const void *a, const void *b);
void InsertCode(TArray<HuffNode> &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value);
unsigned int InitTable(TArray<HuffNode> &decoder, int numspots);
int BuildDecoder(TArray<HuffNode> &decoder, TableBuilder *values, int numvals);
int DecodeSFValue(const TArray<HuffNode> &currentTree);
int DecodeSF(TArray<HuffNode> &decoder, int numvals);
void InsertCode(std::vector<HuffNode> &decoder, unsigned int pos, int bits, unsigned short code, int len, unsigned char value);
unsigned int InitTable(std::vector<HuffNode> &decoder, int numspots);
int BuildDecoder(std::vector<HuffNode> &decoder, TableBuilder *values, int numvals);
int DecodeSFValue(const std::vector<HuffNode> &currentTree);
int DecodeSF(std::vector<HuffNode> &decoder, int numvals);
public:
int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags);
};

View file

@ -0,0 +1,150 @@
/*
**
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
namespace FileSys {
#ifdef _WIN32
#ifndef _WINNT_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
class FInternalCriticalSection
{
public:
void Enter()
{
AcquireSRWLockExclusive(&CritSec);
}
void Leave()
{
ReleaseSRWLockExclusive(&CritSec);
}
private:
SRWLOCK CritSec = SRWLOCK_INIT;
};
FInternalCriticalSection *CreateCriticalSection()
{
return new FInternalCriticalSection();
}
void DeleteCriticalSection(FInternalCriticalSection *c)
{
delete c;
}
void EnterCriticalSection(FInternalCriticalSection *c)
{
c->Enter();
}
void LeaveCriticalSection(FInternalCriticalSection *c)
{
c->Leave();
}
#else
#include "critsec.h"
#include <pthread.h>
class FInternalCriticalSection
{
public:
FInternalCriticalSection();
~FInternalCriticalSection();
void Enter();
void Leave();
private:
pthread_mutex_t m_mutex;
};
// TODO: add error handling
FInternalCriticalSection::FInternalCriticalSection()
{
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attributes);
pthread_mutexattr_destroy(&attributes);
}
FInternalCriticalSection::~FInternalCriticalSection()
{
pthread_mutex_destroy(&m_mutex);
}
void FInternalCriticalSection::Enter()
{
pthread_mutex_lock(&m_mutex);
}
void FInternalCriticalSection::Leave()
{
pthread_mutex_unlock(&m_mutex);
}
FInternalCriticalSection *CreateCriticalSection()
{
return new FInternalCriticalSection();
}
void DeleteCriticalSection(FInternalCriticalSection *c)
{
delete c;
}
void EnterCriticalSection(FInternalCriticalSection *c)
{
c->Enter();
}
void LeaveCriticalSection(FInternalCriticalSection *c)
{
c->Leave();
}
#endif
}

View file

@ -0,0 +1,39 @@
#pragma once
namespace FileSys {
// System independent critical sections without polluting the namespace with the operating system headers.
class FInternalCriticalSection;
FInternalCriticalSection *CreateCriticalSection();
void DeleteCriticalSection(FInternalCriticalSection *c);
void EnterCriticalSection(FInternalCriticalSection *c);
void LeaveCriticalSection(FInternalCriticalSection *c);
// This is just a convenience wrapper around the function interface adjusted to use std::lock_guard
class FCriticalSection
{
public:
FCriticalSection()
{
c = CreateCriticalSection();
}
~FCriticalSection()
{
DeleteCriticalSection(c);
}
void lock()
{
EnterCriticalSection(c);
}
void unlock()
{
LeaveCriticalSection(c);
}
private:
FInternalCriticalSection *c;
};
}

View file

@ -38,6 +38,9 @@
#include "7zCrc.h"
#include "resourcefile.h"
#include "fs_findfile.h"
#include "unicode.h"
#include "critsec.h"
#include <mutex>
namespace FileSys {
@ -158,20 +161,6 @@ struct C7zArchive
return res;
}
};
//==========================================================================
//
// Zip Lump
//
//==========================================================================
struct F7ZLump : public FResourceLump
{
int Position;
virtual int FillCache() override;
};
//==========================================================================
//
@ -183,14 +172,15 @@ class F7ZFile : public FResourceFile
{
friend struct F7ZLump;
F7ZLump *Lumps;
C7zArchive *Archive;
FCriticalSection critsec;
public:
F7ZFile(const char * filename, FileReader &filer, StringPool* sp);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual ~F7ZFile();
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
FileData Read(uint32_t entry) override;
FileReader GetEntryReader(uint32_t entry, int, int) override;
};
@ -204,8 +194,7 @@ public:
F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp)
: FResourceFile(filename, filer, sp)
{
Lumps = NULL;
Archive = NULL;
Archive = nullptr;
}
@ -247,19 +236,18 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
CSzArEx* const archPtr = &Archive->DB;
AllocateEntries(archPtr->NumFiles);
NumLumps = archPtr->NumFiles;
Lumps = new F7ZLump[NumLumps];
F7ZLump *lump_p = Lumps;
std::u16string nameUTF16;
std::string nameASCII;
std::vector<char> nameASCII;
uint32_t j = 0;
for (uint32_t i = 0; i < NumLumps; ++i)
{
// skip Directories
if (SzArEx_IsDir(archPtr, i))
{
skipped++;
continue;
}
@ -267,39 +255,34 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
if (0 == nameLength)
{
++skipped;
continue;
}
nameUTF16.resize((unsigned)nameLength);
nameASCII.resize((unsigned)nameLength);
// note that the file system is not equipped to handle non-ASCII, so don't bother with proper Unicode conversion here.
SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data());
for (size_t c = 0; c < nameLength; ++c)
{
nameASCII[c] = tolower(static_cast<char>(nameUTF16[c]));
}
FixPathSeparator(&nameASCII.front());
lump_p->LumpNameSetup(nameASCII.c_str(), stringpool);
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
lump_p->Owner = this;
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
lump_p->Position = i;
lump_p->CheckEmbedded(filter);
lump_p++;
SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data());
utf16_to_utf8((uint16_t*)nameUTF16.data(), nameASCII);
Entries[j].FileName = NormalizeFileName(nameASCII.data());
Entries[j].Length = SzArEx_GetFileSize(archPtr, i);
Entries[j].Flags = RESFF_FULLPATH|RESFF_COMPRESSED;
Entries[j].ResourceID = -1;
Entries[j].Namespace = ns_global;
Entries[j].Method = METHOD_INVALID;
Entries[j].Position = i;
j++;
}
// Resize the lump record array to its actual size
NumLumps -= skipped;
NumLumps = j;
if (NumLumps > 0)
{
// Quick check for unsupported compression method
TArray<char> temp;
temp.Resize(Lumps[0].LumpSize);
FileData temp(nullptr, Entries[0].Length);
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
if (SZ_OK != Archive->Extract((UInt32)Entries[0].Position, (char*)temp.writable()))
{
Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName);
return false;
@ -307,7 +290,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
}
GenerateHash();
PostProcessArchive(&Lumps[0], sizeof(F7ZLump), filter);
PostProcessArchive(filter);
return true;
}
@ -319,11 +302,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
F7ZFile::~F7ZFile()
{
if (Lumps != NULL)
{
delete[] Lumps;
}
if (Archive != NULL)
if (Archive != nullptr)
{
delete Archive;
}
@ -331,22 +310,41 @@ F7ZFile::~F7ZFile()
//==========================================================================
//
// Fills the lump cache and performs decompression
// Reads data for one entry into a buffer
//
//==========================================================================
int F7ZLump::FillCache()
FileData F7ZFile::Read(uint32_t entry)
{
Cache = new char[LumpSize];
SRes code = static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
if (code != SZ_OK)
FileData buffer;
if (entry < NumLumps && Entries[entry].Length > 0)
{
throw FileSystemException("Error %d reading from 7z archive", code);
auto p = buffer.allocate(Entries[entry].Length);
// There is no realistic way to keep multiple references to a 7z file open without massive overhead so to make this thread-safe a mutex is the only option.
std::lock_guard<FCriticalSection> lock(critsec);
SRes code = Archive->Extract((UInt32)Entries[entry].Position, (char*)p);
if (code != SZ_OK) buffer.clear();
}
RefCount = 1;
return 1;
return buffer;
}
//==========================================================================
//
// This can only return a FileReader to a memory buffer.
//
//==========================================================================
FileReader F7ZFile::GetEntryReader(uint32_t entry, int, int)
{
FileReader fr;
if (entry < 0 || entry >= NumLumps) return fr;
auto buffer = Read(entry);
if (buffer.size() > 0)
fr.OpenMemoryArray(buffer);
return fr;
}
//==========================================================================
//
// File open

View file

@ -44,25 +44,6 @@ namespace FileSys {
std::string FS_FullPath(const char* directory);
#ifdef _WIN32
std::wstring toWide(const char* str);
#endif
//==========================================================================
//
// Zip Lump
//
//==========================================================================
struct FDirectoryLump : public FResourceLump
{
FileReader NewReader() override;
int FillCache() override;
const char* mFullPath;
};
//==========================================================================
//
// Zip file
@ -71,16 +52,17 @@ struct FDirectoryLump : public FResourceLump
class FDirectory : public FResourceFile
{
TArray<FDirectoryLump> Lumps;
const bool nosubdir;
const char* mBasePath;
const char** SystemFilePath;
int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
void AddEntry(const char *fullpath, const char* relpath, int size);
public:
FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
FileReader GetEntryReader(uint32_t entry, int, int) override;
};
@ -116,8 +98,18 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
}
else
{
mBasePath = nullptr;
AllocateEntries((int)list.size());
SystemFilePath = (const char**)stringpool->Alloc(list.size() * sizeof(const char*));
for(auto& entry : list)
{
if (mBasePath == nullptr)
{
// extract the base path from the first entry to cover changes made in ScanDirectory.
auto full = entry.FilePath.find(entry.FilePathRel);
std::string path(entry.FilePath, 0, full);
mBasePath = stringpool->Strdup(path.c_str());
}
if (!entry.isDirectory)
{
auto fi = entry.FileName;
@ -128,14 +120,23 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
continue;
}
if (filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str()))
if (filter == nullptr || filter->filenamecheck == nullptr || filter->filenamecheck(fi.c_str(), entry.FilePath.c_str()))
{
if (entry.Length > 0x7fffffff)
{
Printf(FSMessageLevel::Warning, "%s is larger than 2GB and will be ignored\n", entry.FilePath.c_str());
continue;
}
AddEntry(entry.FilePath.c_str(), entry.FilePathRel.c_str(), (int)entry.Length);
// for internal access we use the normalized form of the relative path.
Entries[count].FileName = NormalizeFileName(entry.FilePathRel.c_str());
SystemFilePath[count] = Entries[count].FileName;
Entries[count].CompressedSize = Entries[count].Length = entry.Length;
Entries[count].Flags = RESFF_FULLPATH;
Entries[count].ResourceID = -1;
Entries[count].Method = METHOD_STORED;
Entries[count].Namespace = ns_global;
Entries[count].Position = count;
count++;
}
}
@ -153,7 +154,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy
bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{
NumLumps = AddDirectory(FileName, filter, Printf);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter);
PostProcessArchive(filter);
return true;
}
@ -163,62 +164,23 @@ bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
//
//==========================================================================
void FDirectory::AddEntry(const char *fullpath, const char* relpath, int size)
{
FDirectoryLump *lump_p = &Lumps[Lumps.Reserve(1)];
// Store the full path here so that we can access the file later, even if it is from a filter directory.
lump_p->mFullPath = stringpool->Strdup(fullpath);
// [mxd] Convert name to lowercase
std::string name = relpath;
for (auto& c : name) c = tolower(c);
// The lump's name is only the part relative to the main directory
lump_p->LumpNameSetup(name.c_str(), stringpool);
lump_p->LumpSize = size;
lump_p->Owner = this;
lump_p->Flags = 0;
lump_p->CheckEmbedded(nullptr);
}
//==========================================================================
//
//
//
//==========================================================================
FileReader FDirectoryLump::NewReader()
FileReader FDirectory::GetEntryReader(uint32_t entry, int readertype, int)
{
FileReader fr;
fr.OpenFile(mFullPath);
if (entry < NumLumps)
{
std::string fn = mBasePath;
fn += SystemFilePath[Entries[entry].Position];
fr.OpenFile(fn.c_str());
if (readertype == READER_CACHED)
{
auto data = fr.Read();
fr.OpenMemoryArray(data);
}
}
return fr;
}
//==========================================================================
//
//
//
//==========================================================================
int FDirectoryLump::FillCache()
{
FileReader fr;
Cache = new char[LumpSize];
if (!fr.OpenFile(mFullPath))
{
throw FileSystemException("unable to open file");
}
auto read = fr.Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
RefCount = 1;
return 1;
}
//==========================================================================
//
// File open

View file

@ -33,7 +33,7 @@
**
*/
#include "resourcefile_internal.h"
#include "resourcefile.h"
#include "fs_swap.h"
namespace FileSys {
@ -65,62 +65,39 @@ struct GrpLump
};
//==========================================================================
//
// Build GRP file
//
//==========================================================================
class FGrpFile : public FUncompressedFile
{
public:
FGrpFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter);
};
//==========================================================================
//
// Initializes a Build GRP file
//
//==========================================================================
FGrpFile::FGrpFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file, sp)
{
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FGrpFile::Open(LumpFilterInfo* filter)
static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter)
{
GrpHeader header;
Reader.Read(&header, sizeof(header));
NumLumps = LittleLong(header.NumLumps);
auto Reader = file->GetContainerReader();
Reader->Read(&header, sizeof(header));
uint32_t NumLumps = LittleLong(header.NumLumps);
auto Entries = file->AllocateEntries(NumLumps);
GrpLump *fileinfo = new GrpLump[NumLumps];
Reader.Read (fileinfo, NumLumps * sizeof(GrpLump));
Lumps.Resize(NumLumps);
Reader->Read (fileinfo, NumLumps * sizeof(GrpLump));
int Position = sizeof(GrpHeader) + NumLumps * sizeof(GrpLump);
for(uint32_t i = 0; i < NumLumps; i++)
{
Lumps[i].Owner = this;
Lumps[i].Position = Position;
Lumps[i].LumpSize = LittleLong(fileinfo[i].Size);
Entries[i].Position = Position;
Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].Size);
Position += fileinfo[i].Size;
Lumps[i].Flags = 0;
Entries[i].Flags = 0;
Entries[i].Namespace = ns_global;
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero, stringpool);
Entries[i].ResourceID = -1;
Entries[i].Method = METHOD_STORED;
Entries[i].FileName = file->NormalizeFileName(fileinfo[i].Name);
}
GenerateHash();
file->GenerateHash();
delete[] fileinfo;
return true;
}
@ -143,12 +120,12 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "KenSilverman", 12))
{
auto rf = new FGrpFile(filename, file, sp);
if (rf->Open(filter)) return rf;
auto rf = new FResourceFile(filename, file, sp);
if (OpenGrp(rf, filter)) return rf;
file = rf->Destroy();
}
}
return NULL;
return nullptr;
}
}

View file

@ -0,0 +1,109 @@
/*
** file_hog.cpp
**
** reads Descent .hog files
**
**---------------------------------------------------------------------------
** Copyright 2023 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "fs_swap.h"
namespace FileSys {
using namespace byteswap;
static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter)
{
auto Reader = rf->GetContainerReader();
FileReader::Size length = Reader->GetLength();
std::vector<FResourceEntry> entries;
// Hogs store their data as a list of file records, each containing a name, length and the actual data.
// To read the directory the entire file must be scanned.
while (Reader->Tell() <= length)
{
char name[13];
auto r = Reader->Read(&name, 13);
if (r < 13) break;
name[12] = 0;
uint32_t elength = Reader->ReadUInt32();
FResourceEntry Entry;
Entry.Position = Reader->Tell();
Entry.CompressedSize = Entry.Length = elength;
Entry.Flags = 0;
Entry.CRC32 = 0;
Entry.Namespace = ns_global;
Entry.ResourceID = -1;
Entry.Method = METHOD_STORED;
Entry.FileName = rf->NormalizeFileName(name);
entries.push_back(Entry);
Reader->Seek(elength, FileReader::SeekCur);
}
auto Entries = rf->AllocateEntries((int)entries.size());
memcpy(Entries, entries.data(), entries.size() * sizeof(Entries[0]));
rf->GenerateHash();
return true;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{
char head[3];
if (file.GetLength() >= 20)
{
file.Seek(0, FileReader::SeekSet);
file.Read(&head, 3);
if (!memcmp(head, "DHF", 3))
{
auto rf = new FResourceFile(filename, file, sp);
if (OpenHog(rf, filter)) return rf;
file = rf->Destroy();
}
file.Seek(0, FileReader::SeekSet);
}
return nullptr;
}
}

View file

@ -32,49 +32,25 @@
**
*/
#include "resourcefile_internal.h"
#include "resourcefile.h"
namespace FileSys {
//==========================================================================
//
// Single lump
//
//==========================================================================
class FLumpFile : public FUncompressedFile
{
public:
FLumpFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter);
};
//==========================================================================
//
// FLumpFile::FLumpFile
//
//==========================================================================
FLumpFile::FLumpFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file, sp)
{
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FLumpFile::Open(LumpFilterInfo*)
static bool OpenLump(FResourceFile* file, LumpFilterInfo*)
{
Lumps.Resize(1);
Lumps[0].LumpNameSetup(ExtractBaseName(FileName, true).c_str(), stringpool);
Lumps[0].Owner = this;
Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength();
Lumps[0].Flags = 0;
NumLumps = 1;
auto Entries = file->AllocateEntries(1);
Entries[0].FileName = file->NormalizeFileName(ExtractBaseName(file->GetFileName(), true).c_str());
Entries[0].Namespace = ns_global;
Entries[0].ResourceID = -1;
Entries[0].Position = 0;
Entries[0].CompressedSize = Entries[0].Length = file->GetContainerReader()->GetLength();
Entries[0].Method = METHOD_STORED;
Entries[0].Flags = 0;
return true;
}
@ -87,8 +63,8 @@ bool FLumpFile::Open(LumpFilterInfo*)
FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{
// always succeeds
auto rf = new FLumpFile(filename, file, sp);
if (rf->Open(filter)) return rf;
auto rf = new FResourceFile(filename, file, sp);
if (OpenLump(rf, filter)) return rf;
file = rf->Destroy();
return NULL;
}

View file

@ -0,0 +1,98 @@
/*
** file_mvl.cpp
**
** reads Descent2 .mvl files
**
**---------------------------------------------------------------------------
** Copyright 2023 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "resourcefile.h"
#include "fs_swap.h"
namespace FileSys {
using namespace byteswap;
static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter)
{
auto Reader = rf->GetContainerReader();
auto count = Reader->ReadUInt32();
auto Entries = rf->AllocateEntries(count);
size_t pos = 8 + (17 * count); // files start after the directory
for (uint32_t i = 0; i < count; i++)
{
char name[13];
Reader->Read(&name, 13);
name[12] = 0;
uint32_t elength = Reader->ReadUInt32();
Entries[i].Position = pos;
Entries[i].CompressedSize = Entries[i].Length = elength;
Entries[i].ResourceID = -1;
Entries[i].FileName = rf->NormalizeFileName(name);
pos += elength;
}
return true;
}
//==========================================================================
//
// File open
//
//==========================================================================
FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp)
{
char head[4];
if (file.GetLength() >= 20)
{
file.Seek(0, FileReader::SeekSet);
file.Read(&head, 4);
if (!memcmp(head, "DMVL", 4))
{
auto rf = new FResourceFile(filename, file, sp);
if (OpenMvl(rf, filter)) return rf;
file = rf->Destroy();
}
file.Seek(0, FileReader::SeekSet);
}
return nullptr;
}
}

View file

@ -32,7 +32,7 @@
**
*/
#include "resourcefile_internal.h"
#include "resourcefile.h"
namespace FileSys {
@ -57,64 +57,38 @@ struct dpackheader_t
} ;
//==========================================================================
//
// Wad file
//
//==========================================================================
class FPakFile : public FUncompressedFile
{
public:
FPakFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter);
};
//==========================================================================
//
// FWadFile::FWadFile
//
// Initializes a WAD file
//
//==========================================================================
FPakFile::FPakFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file, sp)
{
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FPakFile::Open(LumpFilterInfo* filter)
static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter)
{
dpackheader_t header;
Reader.Read(&header, sizeof(header));
NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t);
auto Reader = file->GetContainerReader();
Reader->Read(&header, sizeof(header));
uint32_t NumLumps = header.dirlen / sizeof(dpackfile_t);
auto Entries = file->AllocateEntries(NumLumps);
header.dirofs = LittleLong(header.dirofs);
TArray<dpackfile_t> fileinfo(NumLumps, true);
Reader.Seek (header.dirofs, FileReader::SeekSet);
Reader.Read (fileinfo.Data(), NumLumps * sizeof(dpackfile_t));
Lumps.Resize(NumLumps);
Reader->Seek (header.dirofs, FileReader::SeekSet);
auto fd = Reader->Read (NumLumps * sizeof(dpackfile_t));
auto fileinfo = (const dpackfile_t*)fd.data();
for(uint32_t i = 0; i < NumLumps; i++)
{
Lumps[i].LumpNameSetup(fileinfo[i].name, stringpool);
Lumps[i].Flags = LUMPF_FULLPATH;
Lumps[i].Owner = this;
Lumps[i].Position = LittleLong(fileinfo[i].filepos);
Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen);
Lumps[i].CheckEmbedded(filter);
Entries[i].Position = LittleLong(fileinfo[i].filepos);
Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].filelen);
Entries[i].Flags = RESFF_FULLPATH;
Entries[i].Namespace = ns_global;
Entries[i].ResourceID = -1;
Entries[i].Method = METHOD_STORED;
Entries[i].FileName = file->NormalizeFileName(fileinfo[i].name);
}
GenerateHash();
PostProcessArchive(&Lumps[0], sizeof(Lumps[0]), filter);
file->GenerateHash();
file->PostProcessArchive(filter);
return true;
}
@ -136,8 +110,8 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "PACK", 4))
{
auto rf = new FPakFile(filename, file, sp);
if (rf->Open(filter)) return rf;
auto rf = new FResourceFile(filename, file, sp);
if (OpenPak(rf, filter)) return rf;
file = rf->Destroy();
}
}

View file

@ -33,7 +33,8 @@
**
*/
#include "resourcefile_internal.h"
#include <assert.h>
#include "resourcefile.h"
#include "fs_swap.h"
namespace FileSys {
@ -67,22 +68,6 @@ struct RFFLump
uint32_t IndexNum; // Used by .sfx, possibly others
};
//==========================================================================
//
// Blood RFF lump (uncompressed lump with encryption)
//
//==========================================================================
struct FRFFLump : public FUncompressedLump
{
virtual FileReader *GetReader();
virtual int FillCache() override;
uint32_t IndexNum;
int GetIndexNum() const { return IndexNum; }
};
//==========================================================================
//
// BloodCrypt
@ -100,68 +85,47 @@ void BloodCrypt (void *data, int key, int len)
}
//==========================================================================
//
// Blood RFF file
//
//==========================================================================
class FRFFFile : public FResourceFile
{
FRFFLump *Lumps;
public:
FRFFFile(const char * filename, FileReader &file, StringPool* sp);
virtual ~FRFFFile();
virtual bool Open(LumpFilterInfo* filter);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
//==========================================================================
//
// Initializes a Blood RFF file
//
//==========================================================================
FRFFFile::FRFFFile(const char *filename, FileReader &file, StringPool* sp)
: FResourceFile(filename, file, sp)
{
Lumps = NULL;
}
//==========================================================================
//
// Initializes a Blood RFF file
//
//==========================================================================
bool FRFFFile::Open(LumpFilterInfo*)
static bool OpenRFF(FResourceFile* file, LumpFilterInfo*)
{
RFFLump *lumps;
RFFInfo header;
Reader.Read(&header, sizeof(header));
auto Reader = file->GetContainerReader();
Reader->Read(&header, sizeof(header));
NumLumps = LittleLong(header.NumLumps);
uint32_t NumLumps = LittleLong(header.NumLumps);
auto Entries = file->AllocateEntries(NumLumps);
header.DirOfs = LittleLong(header.DirOfs);
lumps = new RFFLump[header.NumLumps];
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];
Reader->Seek (LittleLong(header.DirOfs), FileReader::SeekSet);
Reader->Read (lumps, NumLumps * sizeof(RFFLump));
BloodCrypt (lumps, LittleLong(header.DirOfs), NumLumps * sizeof(RFFLump));
for (uint32_t i = 0; i < NumLumps; ++i)
{
Lumps[i].Position = LittleLong(lumps[i].FilePos);
Lumps[i].LumpSize = LittleLong(lumps[i].Size);
Lumps[i].Owner = this;
Entries[i].Position = LittleLong(lumps[i].FilePos);
Entries[i].CompressedSize = Entries[i].Length = LittleLong(lumps[i].Size);
Entries[i].Flags = 0;
Entries[i].Method = METHOD_STORED;
if (lumps[i].Flags & 0x10)
{
Lumps[i].Flags |= LUMPF_COMPRESSED; // flags the lump as not directly usable
Entries[i].Flags = RESFF_COMPRESSED; // for purposes of decoding, compression and encryption are equivalent.
Entries[i].Method = METHOD_RFFCRYPT;
}
Lumps[i].IndexNum = LittleLong(lumps[i].IndexNum);
else
{
Entries[i].Flags = 0;
Entries[i].Method = METHOD_STORED;
}
Entries[i].Namespace = ns_global;
Entries[i].ResourceID = LittleLong(lumps[i].IndexNum);
// Rearrange the name and extension to construct the fullname.
char name[13];
strncpy(name, lumps[i].Name, 8);
@ -173,66 +137,13 @@ bool FRFFFile::Open(LumpFilterInfo*)
name[len+2] = lumps[i].Extension[1];
name[len+3] = lumps[i].Extension[2];
name[len+4] = 0;
Lumps[i].LumpNameSetup(name, stringpool);
Entries[i].FileName = file->NormalizeFileName(name);
}
delete[] lumps;
GenerateHash();
file->GenerateHash();
return true;
}
FRFFFile::~FRFFFile()
{
if (Lumps != NULL)
{
delete[] Lumps;
}
}
//==========================================================================
//
// Get reader (only returns non-NULL if not encrypted)
//
//==========================================================================
FileReader *FRFFLump::GetReader()
{
// Don't return the reader if this lump is encrypted
// In that case always force caching of the lump
if (!(Flags & LUMPF_COMPRESSED))
{
return FUncompressedLump::GetReader();
}
else
{
return NULL;
}
}
//==========================================================================
//
// Fills the lump cache and performs decryption
//
//==========================================================================
int FRFFLump::FillCache()
{
int res = FUncompressedLump::FillCache();
if (Flags & LUMPF_COMPRESSED)
{
int cryptlen = std::min<int> (LumpSize, 256);
uint8_t *data = (uint8_t *)Cache;
for (int i = 0; i < cryptlen; ++i)
{
data[i] ^= i >> 1;
}
}
return res;
}
//==========================================================================
//
// File open
@ -250,8 +161,8 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo*
file.Seek(0, FileReader::SeekSet);
if (!memcmp(head, "RFF\x1a", 4))
{
auto rf = new FRFFFile(filename, file, sp);
if (rf->Open(filter)) return rf;
auto rf = new FResourceFile(filename, file, sp);
if (OpenRFF(rf, filter)) return rf;
file = rf->Destroy();
}
}

View file

@ -33,33 +33,9 @@
**
*/
#include "resourcefile_internal.h"
#include "resourcefile.h"
namespace FileSys {
//==========================================================================
//
// Build GRP file
//
//==========================================================================
class FSSIFile : public FUncompressedFile
{
public:
FSSIFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(int version, int EntryCount, LumpFilterInfo* filter);
};
//==========================================================================
//
// Initializes a Build GRP file
//
//==========================================================================
FSSIFile::FSSIFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file, sp)
{
}
//==========================================================================
//
@ -68,42 +44,50 @@ FSSIFile::FSSIFile(const char *filename, FileReader &file, StringPool* sp)
//
//==========================================================================
bool FSSIFile::Open(int version, int EntryCount, LumpFilterInfo*)
static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilterInfo*)
{
NumLumps = EntryCount*2;
Lumps.Resize(EntryCount*2);
uint32_t NumLumps = EntryCount * 2;
auto Entries = file->AllocateEntries(NumLumps);
auto Reader = file->GetContainerReader();
int32_t j = (version == 2 ? 267 : 254) + (EntryCount * 121);
for (uint32_t i = 0; i < NumLumps; i+=2)
{
char fn[13];
int strlength = Reader.ReadUInt8();
int strlength = Reader->ReadUInt8();
if (strlength > 12) strlength = 12;
Reader.Read(fn, 12);
Reader->Read(fn, 12);
fn[strlength] = 0;
int flength = Reader.ReadInt32();
int flength = Reader->ReadInt32();
Lumps[i].LumpNameSetup(fn, stringpool);
Lumps[i].Position = j;
Lumps[i].LumpSize = flength;
Lumps[i].Owner = this;
if (strstr(fn, ".GRP")) Lumps[i].Flags |= LUMPF_EMBEDDED;
Entries[i].Position = j;
Entries[i].CompressedSize = Entries[i].Length = flength;
Entries[i].Flags = 0;
Entries[i].Namespace = ns_global;
Entries[i].Method = METHOD_STORED;
Entries[i].ResourceID = -1;
Entries[i].FileName = file->NormalizeFileName(fn);
if (strstr(fn, ".GRP")) Entries[i].Flags |= RESFF_EMBEDDED;
// SSI files can swap the order of the extension's characters - but there's no reliable detection for this and it can be mixed inside the same container,
// so we have no choice but to create another file record for the altered name.
std::swap(fn[strlength - 1], fn[strlength - 3]);
Lumps[i+1].LumpNameSetup(fn, stringpool);
Lumps[i+1].Position = j;
Lumps[i+1].LumpSize = flength;
Lumps[i+1].Owner = this;
if (strstr(fn, ".GRP")) Lumps[i+1].Flags |= LUMPF_EMBEDDED;
Entries[i + 1].Position = j;
Entries[i + 1].CompressedSize = Entries[i + 1].Length = flength;
Entries[i + 1].Flags = 0;
Entries[i + 1].Namespace = ns_global;
Entries[i + 1].ResourceID = -1;
Entries[i + 1].FileName = file->NormalizeFileName(fn);
Entries[i + 1].Method = METHOD_STORED;
if (strstr(fn, ".GRP")) Entries[i + 1].Flags |= RESFF_EMBEDDED;
j += flength;
Reader.Seek(104, FileReader::SeekCur);
Reader->Seek(104, FileReader::SeekCur);
file->GenerateHash();
}
return true;
}
@ -145,8 +129,8 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo*
{
if (!skipstring(70)) return nullptr;
}
auto ssi = new FSSIFile(filename, file, sp);
if (ssi->Open(version, numfiles, filter)) return ssi;
auto ssi = new FResourceFile(filename, file, sp);
if (OpenSSI(ssi, version, numfiles, filter)) return ssi;
file = ssi->Destroy();
}
}

View file

@ -37,6 +37,8 @@
#include "resourcefile.h"
#include "fs_filesystem.h"
#include "fs_swap.h"
#include "fs_stringpool.h"
#include "resourcefile.h"
namespace FileSys {
using namespace byteswap;
@ -56,71 +58,6 @@ struct wadlump_t
char Name[8];
};
//==========================================================================
//
// Wad Lump (with console doom LZSS support)
//
//==========================================================================
class FWadFileLump : public FResourceLump
{
public:
bool Compressed;
int Position;
int Namespace;
int GetNamespace() const override { return Namespace; }
int GetFileOffset() override { return Position; }
FileReader *GetReader() override
{
if(!Compressed)
{
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
return Owner->GetContainerReader();
}
return NULL;
}
int FillCache() override
{
if(!Compressed)
{
const char * buffer = Owner->GetContainerReader()->GetBuffer();
if (buffer != NULL)
{
// This is an in-memory file so the cache can point directly to the file's data.
Cache = const_cast<char*>(buffer) + Position;
RefCount = -1;
return -1;
}
}
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
Cache = new char[LumpSize];
if(Compressed)
{
FileReader lzss;
if (lzss.OpenDecompressor(*Owner->GetContainerReader(), LumpSize, METHOD_LZSS, false, true))
{
lzss.Read(Cache, LumpSize);
}
}
else
{
auto read = Owner->GetContainerReader()->Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
}
RefCount = 1;
return 1;
}
};
//==========================================================================
//
// Wad file
@ -129,15 +66,12 @@ public:
class FWadFile : public FResourceFile
{
TArray<FWadFileLump> Lumps;
bool IsMarker(int lump, const char *marker);
void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false);
void SkinHack (FileSystemMessageFunc Printf);
public:
FWadFile(const char * filename, FileReader &file, StringPool* sp);
FResourceLump *GetLump(int lump) { return &Lumps[lump]; }
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
};
@ -188,56 +122,62 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
}
}
TArray<wadlump_t> fileinfo(NumLumps, true);
Reader.Seek (InfoTableOfs, FileReader::SeekSet);
Reader.Read (fileinfo.Data(), NumLumps * sizeof(wadlump_t));
Reader.Seek(InfoTableOfs, FileReader::SeekSet);
auto fd = Reader.Read(NumLumps * sizeof(wadlump_t));
auto fileinfo = (const wadlump_t*)fd.data();
Lumps.Resize(NumLumps);
AllocateEntries(NumLumps);
for(uint32_t i = 0; i < NumLumps; i++)
{
// WAD only supports ASCII. It is also the only format which can use valid backslashes in its names.
char n[9];
for(int j = 0; j < 8; j++) n[j] = toupper(fileinfo[i].Name[j]);
n[8] = 0;
// This needs to be done differently. We cannot simply assume that all lumps where the first character's high bit is set are compressed without verification.
// This requires explicit toggling for precisely the files that need it.
#if 0
Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80;
n[0] &= ~0x80;
#else
Lumps[i].Compressed = false;
#endif
Lumps[i].LumpNameSetup(n, stringpool);
Lumps[i].Owner = this;
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 = Lumps[i].Compressed ? LUMPF_COMPRESSED | LUMPF_SHORTNAME : LUMPF_SHORTNAME;
// Check if the lump is within the WAD file and print a warning if not.
if (Lumps[i].Position + Lumps[i].LumpSize > wadSize || Lumps[i].Position < 0 || Lumps[i].LumpSize < 0)
int ishigh = 0;
for (int j = 0; j < 8; j++)
{
if (Lumps[i].LumpSize != 0)
{
Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName, Lumps[i].getName());
Lumps[i].clearName();
}
Lumps[i].LumpSize = Lumps[i].Position = 0;
if (fileinfo[i].Name[j] & 0x80) ishigh |= 1 << j;
n[j] = tolower(fileinfo[i].Name[j]);
}
n[8] = 0;
if (ishigh == 1) n[0] &= 0x7f;
else if (ishigh > 1)
{
// This may not end up printing something proper because we do not know what encoding might have been used.
Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", FileName, fileinfo[i].Name);
}
Entries[i].FileName = nullptr;
Entries[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos);
Entries[i].CompressedSize = Entries[i].Length = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size);
Entries[i].Namespace = ns_global;
Entries[i].Flags = ishigh? RESFF_SHORTNAME | RESFF_COMPRESSED : RESFF_SHORTNAME;
Entries[i].Method = ishigh == 1? METHOD_LZSS : METHOD_STORED;
Entries[i].FileName = stringpool->Strdup(n);
// This doesn't set up the namespace yet.
}
for (uint32_t i = 0; i < NumLumps; i++)
{
if (Entries[i].Method == METHOD_LZSS)
{
// compressed size is implicit.
Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader.GetLength() : Entries[i + 1].Position) - Entries[i].Position;
}
}
GenerateHash(); // Do this before the lump processing below.
SetNamespace("S_START", "S_END", ns_sprites, Printf);
SetNamespace("F_START", "F_END", ns_flats, Printf, true);
SetNamespace("C_START", "C_END", ns_colormaps, Printf);
SetNamespace("A_START", "A_END", ns_acslibrary, Printf);
SetNamespace("TX_START", "TX_END", ns_newtextures, Printf);
SetNamespace("V_START", "V_END", ns_strifevoices, Printf);
SetNamespace("HI_START", "HI_END", ns_hires, Printf);
SetNamespace("VX_START", "VX_END", ns_voxels, Printf);
SetNamespace("s_start", "s_end", ns_sprites, Printf);
SetNamespace("f_start", "f_end", ns_flats, Printf, true);
SetNamespace("c_start", "c_end", ns_colormaps, Printf);
SetNamespace("a_start", "a_end", ns_acslibrary, Printf);
SetNamespace("tx_start", "tx_end", ns_newtextures, Printf);
SetNamespace("v_start", "v_end", ns_strifevoices, Printf);
SetNamespace("hi_start", "hi_end", ns_hires, Printf);
SetNamespace("vx_start", "vx_end", ns_voxels, Printf);
SkinHack(Printf);
return true;
}
@ -251,10 +191,10 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
inline bool FWadFile::IsMarker(int lump, const char *marker)
{
if (Lumps[lump].getName()[0] == marker[0])
if (Entries[lump].FileName[0] == marker[0])
{
return (!strcmp(Lumps[lump].getName(), marker) ||
(marker[1] == '_' && !strcmp(Lumps[lump].getName() +1, marker)));
return (!strcmp(Entries[lump].FileName, marker) ||
(marker[1] == '_' && !strcmp(Entries[lump].FileName +1, marker)));
}
else return false;
}
@ -283,20 +223,20 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
bool warned = false;
int numstartmarkers = 0, numendmarkers = 0;
unsigned int i;
TArray<Marker> markers;
std::vector<Marker> markers;
for(i = 0; i < NumLumps; i++)
{
if (IsMarker(i, startmarker))
{
Marker m = { 0, i };
markers.Push(m);
markers.push_back(m);
numstartmarkers++;
}
else if (IsMarker(i, endmarker))
{
Marker m = { 1, i };
markers.Push(m);
markers.push_back(m);
numendmarkers++;
}
}
@ -312,15 +252,15 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{
// We have found no F_START but one or more F_END markers.
// mark all lumps before the last F_END marker as potential flats.
unsigned int end = markers[markers.Size()-1].index;
unsigned int end = markers[markers.size()-1].index;
for(unsigned int ii = 0; ii < end; ii++)
{
if (Lumps[ii].LumpSize == 4096)
if (Entries[ii].Length == 4096)
{
// We can't add this to the flats namespace but
// it needs to be flagged for the texture manager.
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Lumps[ii].getName());
Lumps[ii].Flags |= LUMPF_MAYBEFLAT;
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Entries[ii].FileName);
Entries[ii].Flags |= RESFF_MAYBEFLAT;
}
}
}
@ -328,7 +268,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
}
i = 0;
while (i < markers.Size())
while (i < markers.size())
{
int start, end;
if (markers[i].markertype != 0)
@ -340,21 +280,21 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
start = i++;
// skip over subsequent x_START markers
while (i < markers.Size() && markers[i].markertype == 0)
while (i < markers.size() && markers[i].markertype == 0)
{
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker);
i++;
continue;
}
// same for x_END markers
while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
while (i < markers.size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
{
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker);
i++;
continue;
}
// We found a starting marker but no end marker. Ignore this block.
if (i >= markers.Size())
if (i >= markers.size())
{
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker);
end = NumLumps;
@ -368,7 +308,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end);
for(int j = markers[start].index + 1; j < end; j++)
{
if (Lumps[j].Namespace != ns_global)
if (Entries[j].Namespace != ns_global)
{
if (!warned)
{
@ -376,17 +316,17 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
}
warned = true;
}
else if (space == ns_sprites && Lumps[j].LumpSize < 8)
else if (space == ns_sprites && Entries[j].Length < 8)
{
// sf 26/10/99:
// ignore sprite lumps smaller than 8 bytes (the smallest possible)
// in size -- this was used by some dmadds wads
// as an 'empty' graphics resource
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Lumps[j].getName(), j);
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Entries[j].FileName, j);
}
else
{
Lumps[j].Namespace = space;
Entries[j].Namespace = space;
}
}
}
@ -416,11 +356,11 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
for (i = 0; i < NumLumps; i++)
{
FResourceLump *lump = &Lumps[i];
auto lump = &Entries[i];
if (!strnicmp(lump->getName(), "S_SKIN", 6))
if (!strnicmp(lump->FileName, "S_SKIN", 6))
{ // Wad has at least one skin.
lump->LumpNameSetup("S_SKIN", nullptr);
lump->FileName = "S_SKIN";
if (!skinned)
{
skinned = true;
@ -428,24 +368,24 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
for (j = 0; j < NumLumps; j++)
{
Lumps[j].Namespace = namespc;
Entries[j].Namespace = namespc;
}
namespc++;
}
}
// needless to say, this check is entirely useless these days as map names can be more diverse..
if ((lump->getName()[0] == 'M' &&
lump->getName()[1] == 'A' &&
lump->getName()[2] == 'P' &&
lump->getName()[3] >= '0' && lump->getName()[3] <= '9' &&
lump->getName()[4] >= '0' && lump->getName()[4] <= '9' &&
lump->getName()[5] == '\0')
if ((lump->FileName[0] == 'M' &&
lump->FileName[1] == 'A' &&
lump->FileName[2] == 'P' &&
lump->FileName[3] >= '0' && lump->FileName[3] <= '9' &&
lump->FileName[4] >= '0' && lump->FileName[4] <= '9' &&
lump->FileName[5] == '\0')
||
(lump->getName()[0] == 'E' &&
lump->getName()[1] >= '0' && lump->getName()[1] <= '9' &&
lump->getName()[2] == 'M' &&
lump->getName()[3] >= '0' && lump->getName()[3] <= '9' &&
lump->getName()[4] == '\0'))
(lump->FileName[0] == 'E' &&
lump->FileName[1] >= '0' && lump->FileName[1] <= '9' &&
lump->FileName[2] == 'M' &&
lump->FileName[3] >= '0' && lump->FileName[3] <= '9' &&
lump->FileName[4] == '\0'))
{
hasmap = true;
}

View file

@ -34,76 +34,61 @@
**
*/
#include "resourcefile_internal.h"
#include "resourcefile.h"
#include "fs_stringpool.h"
#include "fs_swap.h"
namespace FileSys {
using namespace byteswap;
//==========================================================================
//
// WH resource file
//
//==========================================================================
class FWHResFile : public FUncompressedFile
{
const char* BaseName;
public:
FWHResFile(const char * filename, FileReader &file, StringPool* sp);
bool Open(LumpFilterInfo* filter);
};
//==========================================================================
//
//
//
//==========================================================================
FWHResFile::FWHResFile(const char *filename, FileReader &file, StringPool* sp)
: FUncompressedFile(filename, file, sp)
{
BaseName = stringpool->Strdup(ExtractBaseName(filename, false).c_str());
}
//==========================================================================
//
// Open it
//
//==========================================================================
bool FWHResFile::Open(LumpFilterInfo*)
bool OpenWHRes(FResourceFile* file, LumpFilterInfo*)
{
uint32_t directory[1024];
Reader.Seek(-4096, FileReader::SeekEnd);
Reader.Read(directory, 4096);
auto BaseName = ExtractBaseName(file->GetFileName());
auto Reader = file->GetContainerReader();
Reader->Seek(-4096, FileReader::SeekEnd);
Reader->Read(directory, 4096);
int nl =1024/3;
Lumps.Resize(nl);
int k;
for (k = 0; k < nl; k++)
{
uint32_t offset = LittleLong(directory[k * 3]) * 4096;
uint32_t length = LittleLong(directory[k * 3 + 1]);
if (length == 0)
{
break;
}
}
auto Entries = file->AllocateEntries(k);
auto NumLumps = k;
int i = 0;
for(int k = 0; k < nl; k++)
for(k = 0; k < NumLumps; k++)
{
uint32_t offset = LittleLong(directory[k*3]) * 4096;
uint32_t length = LittleLong(directory[k*3+1]);
if (length == 0) break;
char num[6];
snprintf(num, 6, "/%04d", k);
std::string synthname = BaseName;
synthname += num;
Lumps[i].LumpNameSetup(synthname.c_str(), stringpool);
Lumps[i].Owner = this;
Lumps[i].Position = offset;
Lumps[i].LumpSize = length;
std::string synthname = BaseName + num;
Entries[i].Position = offset;
Entries[i].CompressedSize = Entries[i].Length = length;
Entries[i].Flags = RESFF_FULLPATH;
Entries[i].Namespace = ns_global;
Entries[i].ResourceID = -1;
Entries[i].Method = METHOD_STORED;
Entries[i].FileName = file->NormalizeFileName(synthname.c_str());
i++;
}
NumLumps = i;
Lumps.Clamp(NumLumps);
Lumps.ShrinkToFit();
return true;
}
@ -134,8 +119,8 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo
if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr;
checkpos += (length+4095) / 4096;
}
auto rf = new FWHResFile(filename, file, sp);
if (rf->Open(filter)) return rf;
auto rf = new FResourceFile(filename, file, sp);
if (OpenWHRes(rf, filter)) return rf;
file = rf->Destroy();
}
return NULL;

View file

@ -3,7 +3,7 @@
**
**---------------------------------------------------------------------------
** Copyright 1998-2009 Randy Heit
** Copyright 2005-2009 Christoph Oelckers
** Copyright 2005-2023 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -35,78 +35,18 @@
#include <time.h>
#include <stdexcept>
#include "file_zip.h"
#include "w_zip.h"
#include "ancientzip.h"
#include "resourcefile.h"
#include "fs_findfile.h"
#include "fs_swap.h"
#include "fs_stringpool.h"
namespace FileSys {
using namespace byteswap;
#define BUFREADCOMMENT (0x400)
//==========================================================================
//
// Decompression subroutine
//
//==========================================================================
static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, ptrdiff_t LumpSize, ptrdiff_t CompressedSize, int GPFlags, bool exceptions)
{
switch (Method)
{
case METHOD_STORED:
{
Reader.Read(Cache, LumpSize);
break;
}
case METHOD_DEFLATE:
case METHOD_BZIP2:
case METHOD_LZMA:
case METHOD_XZ:
{
FileReader frz;
if (frz.OpenDecompressor(Reader, LumpSize, Method, false, exceptions))
{
frz.Read(Cache, LumpSize);
}
break;
}
// Fixme: These should also use a stream
case METHOD_IMPLODE:
{
FZipExploder exploder;
if (exploder.Explode((unsigned char*)Cache, (unsigned)LumpSize, Reader, (unsigned)CompressedSize, GPFlags) == -1)
{
// decompression failed so zero the cache.
memset(Cache, 0, LumpSize);
}
break;
}
case METHOD_SHRINK:
{
ShrinkLoop((unsigned char *)Cache, (unsigned)LumpSize, Reader, (unsigned)CompressedSize);
break;
}
default:
assert(0);
return false;
}
return true;
}
bool FCompressedBuffer::Decompress(char *destbuffer)
{
FileReader mr;
mr.OpenMemory(mBuffer, mCompressedSize);
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags, false);
}
//-----------------------------------------------------------------------
//
// Finds the central directory end record in the end of the file.
@ -166,10 +106,25 @@ static uint32_t Zip_FindCentralDir(FileReader &fin, bool* zip64)
//
//==========================================================================
class FZipFile : public FResourceFile
{
void SetEntryAddress(uint32_t entry) override;
public:
FZipFile(const char* filename, FileReader& file, StringPool* sp);
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
FCompressedBuffer GetRawData(uint32_t entry) override;
};
//==========================================================================
//
// Zip file
//
//==========================================================================
FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp)
: FResourceFile(filename, file, sp)
{
Lumps = NULL;
}
bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
@ -178,8 +133,6 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64);
int skipped = 0;
Lumps = NULL;
if (centraldir == 0)
{
Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName);
@ -225,15 +178,12 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
dirsize = info.DirectorySize;
DirectoryOffset = info.DirectoryOffset;
}
Lumps = new FZipLump[NumLumps];
// Load the entire central directory. Too bad that this contains variable length entries...
void *directory = malloc(dirsize);
Reader.Seek(DirectoryOffset, FileReader::SeekSet);
Reader.Read(directory, dirsize);
char *dirptr = (char*)directory;
FZipLump *lump_p = Lumps;
std::string name0, name1;
bool foundspeciallump = false;
@ -259,58 +209,11 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName);
return false;
}
for (auto& c : name) c = tolower(c);
auto vv = name.find("__macosx");
if (name.find("filter/") == 0)
continue; // 'filter' is a reserved name of the file system.
if (name.find("__macosx") == 0)
continue; // skip Apple garbage. At this stage only the root folder matters.
if (name.find(".bat") != std::string::npos || name.find(".exe") != std::string::npos)
continue; // also ignore executables for this.
if (!foundprefix)
{
// check for special names, if one of these gets found this must be treated as a normal zip.
bool isspecial = name.find("/") == std::string::npos ||
(filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end());
if (isspecial) break;
name0 = std::string(name, 0, name.rfind("/")+1);
name1 = std::string(name, 0, name.find("/") + 1);
foundprefix = true;
}
if (name.find(name0) != 0)
{
if (!name1.empty())
{
name0 = name1;
if (name.find(name0) != 0)
{
name0 = "";
}
}
if (name0.empty())
break;
}
if (!foundspeciallump && filter)
{
// at least one of the more common definition lumps must be present.
for (auto &p : filter->requiredPrefixes)
{
if (name.find(name0 + p) == 0 || name.rfind(p) == size_t(name.length() - p.length()))
{
foundspeciallump = true;
break;
}
}
}
}
// 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;
AllocateEntries(NumLumps);
auto Entry = Entries;
for (uint32_t i = 0; i < NumLumps; i++)
{
FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr;
@ -329,13 +232,6 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
return false;
}
if (name.find("__macosx") == 0 || name.find("__MACOSX") == 0)
{
skipped++;
continue; // Weed out Apple's resource fork garbage right here because it interferes with safe operation.
}
if (!name0.empty()) name = std::string(name, name0.length());
// skip Directories
if (name.empty() || (name.back() == '/' && LittleLong(zip_fh->UncompressedSize32) == 0))
{
@ -366,9 +262,6 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
continue;
}
FixPathSeparator(&name.front());
for (auto& c : name) c = tolower(c);
uint32_t UncompressedSize =LittleLong(zip_fh->UncompressedSize32);
uint32_t CompressedSize = LittleLong(zip_fh->CompressedSize32);
uint64_t LocalHeaderOffset = LittleLong(zip_fh->LocalHeaderOffset32);
@ -399,54 +292,59 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
}
}
lump_p->LumpNameSetup(name.c_str(), stringpool);
lump_p->LumpSize = UncompressedSize;
lump_p->Owner = this;
Entry->FileName = NormalizeFileName(name.c_str());
Entry->Length = UncompressedSize;
// The start of the Reader will be determined the first time it is accessed.
lump_p->Flags = LUMPF_FULLPATH;
lump_p->NeedFileStart = true;
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 = CompressedSize;
lump_p->Position = LocalHeaderOffset;
lump_p->CheckEmbedded(filter);
Entry->Flags = RESFF_FULLPATH | RESFF_NEEDFILESTART;
Entry->Method = uint8_t(zip_fh->Method);
if (Entry->Method != METHOD_STORED) Entry->Flags |= RESFF_COMPRESSED;
if (Entry->Method == METHOD_IMPLODE)
{
// for Implode merge the flags into the compression method to make handling in the file system easier and save one variable.
if ((zip_fh->Flags & 6) == 2) Entry->Method = METHOD_IMPLODE_2;
else if ((zip_fh->Flags & 6) == 4) Entry->Method = METHOD_IMPLODE_4;
else if ((zip_fh->Flags & 6) == 6) Entry->Method = METHOD_IMPLODE_6;
else Entry->Method = METHOD_IMPLODE_0;
}
Entry->CRC32 = zip_fh->CRC32;
Entry->CompressedSize = CompressedSize;
Entry->Position = LocalHeaderOffset;
Entry++;
lump_p++;
}
// Resize the lump record array to its actual size
NumLumps -= skipped;
free(directory);
GenerateHash();
PostProcessArchive(&Lumps[0], sizeof(FZipLump), filter);
PostProcessArchive(filter);
return true;
}
//==========================================================================
//
// Zip file
//
//
//==========================================================================
FZipFile::~FZipFile()
FCompressedBuffer FZipFile::GetRawData(uint32_t entry)
{
if (Lumps != NULL) delete [] Lumps;
}
FCompressedBuffer cbuf;
//==========================================================================
//
//
//
//==========================================================================
FCompressedBuffer FZipLump::GetRawData()
{
FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] };
if (NeedFileStart) SetLumpAddress();
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
Owner->GetContainerReader()->Read(cbuf.mBuffer, CompressedSize);
if (entry >= NumLumps || Entries[entry].Length == 0)
{
cbuf = { 0, 0, METHOD_STORED, 0, 0, nullptr };
}
else
{
auto& e = Entries[entry];
cbuf = { e.Length, e.CompressedSize, e.Method, e.CRC32, new char[e.CompressedSize] };
if (e.Flags & RESFF_NEEDFILESTART) SetEntryAddress(entry);
Reader.Seek(e.Position, FileReader::SeekSet);
Reader.Read(cbuf.mBuffer, e.CompressedSize);
}
return cbuf;
}
@ -456,7 +354,7 @@ FCompressedBuffer FZipLump::GetRawData()
//
//==========================================================================
void FZipLump::SetLumpAddress()
void FZipFile::SetEntryAddress(uint32_t entry)
{
// This file is inside a zip and has not been opened before.
// Position points to the start of the local file header, which we must
@ -464,69 +362,11 @@ void FZipLump::SetLumpAddress()
FZipLocalFileHeader localHeader;
int skiplen;
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
Owner->GetContainerReader()->Read(&localHeader, sizeof(localHeader));
Reader.Seek(Entries[entry].Position, FileReader::SeekSet);
Reader.Read(&localHeader, sizeof(localHeader));
skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength);
Position += sizeof(localHeader) + skiplen;
NeedFileStart = false;
}
//==========================================================================
//
// Get reader (only returns non-NULL if not encrypted)
//
//==========================================================================
FileReader *FZipLump::GetReader()
{
// Don't return the reader if this lump is encrypted
// In that case always force caching of the lump
if (Method == METHOD_STORED)
{
if (NeedFileStart) SetLumpAddress();
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
return Owner->GetContainerReader();
}
else return NULL;
}
//==========================================================================
//
// Fills the lump cache and performs decompression
//
//==========================================================================
int FZipLump::FillCache()
{
if (NeedFileStart) SetLumpAddress();
const char *buffer;
if (Method == METHOD_STORED && (buffer = Owner->GetContainerReader()->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;
RefCount = -1;
return -1;
}
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
Cache = new char[LumpSize];
UncompressZipLump(Cache, *Owner->GetContainerReader(), Method, LumpSize, CompressedSize, GPFlags, true);
RefCount = 1;
return 1;
}
//==========================================================================
//
//
//
//==========================================================================
int FZipLump::GetFileOffset()
{
if (Method != METHOD_STORED) return -1;
if (NeedFileStart) SetLumpAddress();
return (int)Position;
Entries[entry].Position += sizeof(localHeader) + skiplen;
Entries[entry].Flags &= ~RESFF_NEEDFILESTART;
}
//==========================================================================
@ -555,171 +395,4 @@ FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo*
}
//==========================================================================
//
// time_to_dos
//
// Converts time from struct tm to the DOS format used by zip files.
//
//==========================================================================
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)
{
val.first = val.second = 0;
}
else
{
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;
}
//==========================================================================
//
// append_to_zip
//
// Write a given file to the zipFile.
//
// zipfile: zip object to be written to
//
// returns: position = success, -1 = error
//
//==========================================================================
static int AppendToZip(FileWriter *zip_file, const FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime)
{
FZipLocalFileHeader local;
int position;
local.Magic = ZIP_LOCALFILE;
local.VersionToExtract[0] = 20;
local.VersionToExtract[1] = 0;
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((unsigned)content.mSize);
local.CompressedSize = LittleLong((unsigned)content.mCompressedSize);
local.NameLength = LittleShort((unsigned short)strlen(content.filename));
local.ExtraLength = 0;
// Fill in local directory header.
position = (int)zip_file->Tell();
// Write out the header, file name, and file data.
if (zip_file->Write(&local, sizeof(local)) != sizeof(local) ||
zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename) ||
zip_file->Write(content.mBuffer, content.mCompressedSize) != content.mCompressedSize)
{
return -1;
}
return position;
}
//==========================================================================
//
// write_central_dir
//
// Writes the central directory entry for a file.
//
//==========================================================================
int AppendCentralDirectory(FileWriter *zip_file, const FCompressedBuffer &content, std::pair<uint16_t, uint16_t> &dostime, int position)
{
FZipCentralDirectoryInfo dir;
dir.Magic = ZIP_CENTRALFILE;
dir.VersionMadeBy[0] = 20;
dir.VersionMadeBy[1] = 0;
dir.VersionToExtract[0] = 20;
dir.VersionToExtract[1] = 0;
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.CompressedSize32 = LittleLong((unsigned)content.mCompressedSize);
dir.UncompressedSize32 = LittleLong((unsigned)content.mSize);
dir.NameLength = LittleShort((unsigned short)strlen(content.filename));
dir.ExtraLength = 0;
dir.CommentLength = 0;
dir.StartingDiskNumber = 0;
dir.InternalAttributes = 0;
dir.ExternalAttributes = 0;
dir.LocalHeaderOffset32 = LittleLong((unsigned)position);
if (zip_file->Write(&dir, sizeof(dir)) != sizeof(dir) ||
zip_file->Write(content.filename, strlen(content.filename)) != strlen(content.filename))
{
return -1;
}
return 0;
}
bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t contentcount)
{
// try to determine local time
struct tm *ltime;
time_t ttime;
ttime = time(nullptr);
ltime = localtime(&ttime);
auto dostime = time_to_dos(ltime);
TArray<int> positions;
auto f = FileWriter::Open(filename);
if (f != nullptr)
{
for (size_t i = 0; i < contentcount; i++)
{
int pos = AppendToZip(f, content[i], dostime);
if (pos == -1)
{
delete f;
remove(filename);
return false;
}
positions.Push(pos);
}
int dirofs = (int)f->Tell();
for (size_t i = 0; i < contentcount; i++)
{
if (AppendCentralDirectory(f, content[i], dostime, positions[i]) < 0)
{
delete f;
remove(filename);
return false;
}
}
// Write the directory terminator.
FZipEndOfCentralDirectory dirend;
dirend.Magic = ZIP_ENDOFDIR;
dirend.DiskNumber = 0;
dirend.FirstDisk = 0;
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort((uint16_t)contentcount);
dirend.DirectoryOffset = LittleLong((unsigned)dirofs);
dirend.DirectorySize = LittleLong((uint32_t)(f->Tell() - dirofs));
dirend.ZipCommentLength = 0;
if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend))
{
delete f;
remove(filename);
return false;
}
delete f;
return true;
}
return false;
}
}

View file

@ -1,51 +0,0 @@
#ifndef __FILE_ZIP_H
#define __FILE_ZIP_H
#include "resourcefile.h"
namespace FileSys {
//==========================================================================
//
// Zip Lump
//
//==========================================================================
struct FZipLump : public FResourceLump
{
uint16_t GPFlags;
uint8_t Method;
bool NeedFileStart;
int CompressedSize;
int64_t Position;
unsigned CRC32;
virtual FileReader *GetReader();
virtual int FillCache() override;
private:
void SetLumpAddress();
virtual int GetFileOffset();
FCompressedBuffer GetRawData();
};
//==========================================================================
//
// Zip file
//
//==========================================================================
class FZipFile : public FResourceFile
{
FZipLump *Lumps;
public:
FZipFile(const char * filename, FileReader &file, StringPool* sp);
virtual ~FZipFile();
bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
}
#endif

View file

@ -35,6 +35,9 @@
#include <string>
#include <memory>
#include <algorithm>
#include <assert.h>
#include <string.h>
#include "files_internal.h"
namespace FileSys {
@ -326,15 +329,15 @@ char *MemoryReader::Gets(char *strbuf, ptrdiff_t len)
int BufferingReader::FillBuffer(ptrdiff_t newpos)
{
if (newpos > Length) newpos = Length;
if (newpos < bufferpos) return 0;
auto read = baseReader->Read(&buf[bufferpos], newpos - bufferpos);
if (newpos <= bufferpos) return 0;
auto read = baseReader->Read(&buf.writable()[bufferpos], newpos - bufferpos);
bufferpos += read;
if (bufferpos == Length)
{
// we have read the entire file, so delete our data provider.
baseReader.reset();
}
return read == newpos - bufferpos ? 0 : -1;
return newpos == bufferpos ? 0 : -1;
}
ptrdiff_t BufferingReader::Seek(ptrdiff_t offset, int origin)
@ -392,45 +395,40 @@ bool FileReader::OpenMemory(const void *mem, FileReader::Size length)
return true;
}
bool FileReader::OpenMemoryArray(const void *mem, FileReader::Size length)
bool FileReader::OpenMemoryArray(FileData& data)
{
Close();
mReader = new MemoryArrayReader<std::vector<uint8_t>>((const char *)mem, length);
if (data.size() > 0) mReader = new MemoryArrayReader(data);
return true;
}
bool FileReader::OpenMemoryArray(std::vector<uint8_t>& data)
FileData FileReader::Read(size_t len)
{
Close();
if (data.size() > 0) mReader = new MemoryArrayReader<std::vector<uint8_t>>(data);
return true;
}
bool FileReader::OpenMemoryArray(ResourceData& data)
{
Close();
if (data.size() > 0) mReader = new MemoryArrayReader<ResourceData>(data);
return true;
}
bool FileReader::OpenMemoryArray(std::function<bool(std::vector<uint8_t>&)> getter)
{
auto reader = new MemoryArrayReader<std::vector<uint8_t>>(nullptr, 0);
if (getter(reader->GetArray()))
FileData buffer;
if (len > 0)
{
Close();
reader->UpdateBuffer();
mReader = reader;
return true;
}
else
{
// This will keep the old buffer, if one existed
delete reader;
return false;
Size length = mReader->Read(buffer.allocate(len), len);
if ((size_t)length < len) buffer.allocate(length);
}
return buffer;
}
FileData FileReader::ReadPadded(size_t padding)
{
auto len = GetLength();
FileData buffer;
if (len > 0)
{
auto p = (char*)buffer.allocate(len + padding);
Size length = mReader->Read(p, len);
if (length < len) buffer.clear();
else memset(p + len, 0, padding);
}
return buffer;
}
//==========================================================================
//

View file

@ -45,6 +45,9 @@
#include <stdexcept>
#include "fs_files.h"
#include "files_internal.h"
#include "ancientzip.h"
#include "fs_decompress.h"
namespace FileSys {
using namespace byteswap;
@ -53,6 +56,7 @@ namespace FileSys {
class DecompressorBase : public FileReaderInterface
{
bool exceptions = false;
public:
// These do not work but need to be defined to satisfy the FileReaderInterface.
// They will just error out when called.
@ -64,6 +68,10 @@ public:
void EnableExceptions(bool on) { exceptions = on; }
protected:
DecompressorBase()
{
//seekable = false;
}
FileReader* File = nullptr;
FileReader OwnedFile;
};
@ -174,7 +182,7 @@ public:
inflateEnd (&Stream);
}
ptrdiff_t Read (void *buffer, ptrdiff_t len) override
ptrdiff_t Read (void *buffer, ptrdiff_t olen) override
{
int err = 0;
@ -183,6 +191,7 @@ public:
DecompressionError("File not open");
return 0;
}
auto len = olen;
if (len == 0) return 0;
while (len > 0)
@ -215,7 +224,7 @@ public:
return 0;
}
return len - Stream.avail_out;
return olen - Stream.avail_out;
}
void FillBuffer ()
@ -841,19 +850,22 @@ public:
};
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, bool exceptions)
bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size length, int method, int flags)
{
FileReaderInterface* fr = nullptr;
DecompressorBase* dec = nullptr;
try
{
FileReader* p = &parent;
switch (method & ~METHOD_TRANSFEROWNER)
bool exceptions = !!(flags & DCF_EXCEPTIONS);
switch (method)
{
case METHOD_DEFLATE:
case METHOD_ZLIB:
{
auto idec = new DecompressorZ;
dec = idec;
fr = dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p, method == METHOD_DEFLATE))
{
@ -865,7 +877,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
case METHOD_BZIP2:
{
auto idec = new DecompressorBZ2;
dec = idec;
fr = dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p))
{
@ -877,7 +889,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
case METHOD_LZMA:
{
auto idec = new DecompressorLZMA;
dec = idec;
fr = dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p, length))
{
@ -889,7 +901,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
case METHOD_XZ:
{
auto idec = new DecompressorXZ;
dec = idec;
fr = dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p, length))
{
@ -901,7 +913,7 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
case METHOD_LZSS:
{
auto idec = new DecompressorLZSS;
dec = idec;
fr = dec = idec;
idec->EnableExceptions(exceptions);
if (!idec->Open(p))
{
@ -911,34 +923,103 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
break;
}
// todo: METHOD_IMPLODE, METHOD_SHRINK
// The decoders for these legacy formats can only handle the full data in one go so we have to perform the entire decompression here.
case METHOD_IMPLODE_0:
case METHOD_IMPLODE_2:
case METHOD_IMPLODE_4:
case METHOD_IMPLODE_6:
{
FileData buffer(nullptr, length);
FZipExploder exploder;
if (exploder.Explode(buffer.writable(), (unsigned)length, *p, (unsigned)p->GetLength(), method - METHOD_IMPLODE_MIN) == -1)
{
if (exceptions)
{
throw FileSystemException("DecompressImplode failed");
}
return false;
}
fr = new MemoryArrayReader(buffer);
flags &= ~(DCF_SEEKABLE | DCF_CACHED);
break;
}
case METHOD_SHRINK:
{
FileData buffer(nullptr, length);
ShrinkLoop(buffer.writable(), (unsigned)length, *p, (unsigned)p->GetLength()); // this never fails.
fr = new MemoryArrayReader(buffer);
flags &= ~(DCF_SEEKABLE | DCF_CACHED);
break;
}
// While this could be made a buffering reader it isn't worth the effort because only stock RFFs are encrypted and they do not contain large files.
case METHOD_RFFCRYPT:
{
FileData buffer = p->Read(length);
auto bufr = buffer.writable();
FileReader::Size cryptlen = std::min<FileReader::Size>(length, 256);
for (FileReader::Size i = 0; i < cryptlen; ++i)
{
bufr[i] ^= i >> 1;
}
fr = new MemoryArrayReader(buffer);
flags &= ~(DCF_SEEKABLE | DCF_CACHED);
break;
}
default:
return false;
}
if (method & METHOD_TRANSFEROWNER)
if (dec)
{
dec->SetOwnsReader();
if (flags & DCF_TRANSFEROWNER)
{
dec->SetOwnsReader();
}
dec->Length = length;
}
dec->Length = length;
if (!seekable)
if ((flags & DCF_CACHED))
{
Close();
mReader = dec;
return true;
// read everything into a MemoryArrayReader.
FileData data(nullptr, length);
fr->Read(data.writable(), length);
fr = new MemoryArrayReader(data);
}
else
else if ((flags & DCF_SEEKABLE))
{
// todo: create a wrapper. for now this fails
delete dec;
return false;
// create a wrapper that can buffer the content so that seeking is possible
fr = new BufferingReader(fr);
}
}
self = FileReader(fr);
return true;
}
catch (...)
{
if (dec) delete dec;
if (fr) delete fr;
throw;
}
}
bool FCompressedBuffer::Decompress(char* destbuffer)
{
if (mMethod == METHOD_STORED)
{
memcpy(destbuffer, mBuffer, mSize);
return true;
}
else
{
FileReader mr;
mr.OpenMemory(mBuffer, mCompressedSize);
FileReader frz;
if (OpenDecompressor(frz, mr, mSize, mMethod))
{
return frz.Read(destbuffer, mSize) != mSize;
}
}
return false;
}
}

View file

@ -31,7 +31,7 @@ public:
class BufferingReader : public MemoryReader
{
std::vector<uint8_t> buf;
FileData buf;
std::unique_ptr<FileReaderInterface> baseReader;
ptrdiff_t bufferpos = 0;
@ -40,6 +40,9 @@ public:
BufferingReader(FileReaderInterface* base)
: baseReader(base)
{
Length = base->Length;
buf.allocate(Length);
bufptr = (const char*)buf.data();
}
ptrdiff_t Seek(ptrdiff_t offset, int origin) override;
@ -55,10 +58,9 @@ public:
//
//==========================================================================
template<class T>
class MemoryArrayReader : public MemoryReader
{
T buf;
FileData buf;
public:
MemoryArrayReader()
@ -67,24 +69,18 @@ public:
Length = 0;
}
MemoryArrayReader(const char* buffer, ptrdiff_t length)
MemoryArrayReader(size_t len)
{
if (length > 0)
{
buf.resize(length);
memcpy(&buf[0], buffer, length);
}
buf.allocate(len);
UpdateBuffer();
}
MemoryArrayReader(T& buffer)
MemoryArrayReader(FileData& buffer)
{
buf = std::move(buffer);
UpdateBuffer();
}
std::vector<uint8_t>& GetArray() { return buf; }
void UpdateBuffer()
{
bufptr = (const char*)buf.data();
@ -93,7 +89,4 @@ public:
}
};
bool OpenMemoryArray(std::vector<uint8_t>& data); // take the given array
}

View file

@ -40,8 +40,9 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <inttypes.h>
#include "resourcefile_internal.h"
#include "resourcefile.h"
#include "fs_filesystem.h"
#include "fs_findfile.h"
#include "md5.hpp"
@ -90,29 +91,33 @@ static void md5Hash(FileReader& reader, uint8_t* digest)
struct FileSystem::LumpRecord
{
FResourceLump *lump;
FResourceFile *resfile;
LumpShortName shortName;
const char* LongName;
int rfnum;
int Namespace;
int resindex;
int16_t rfnum; // this is not necessarily the same as resfile's index!
int16_t Namespace;
int resourceId;
int flags;
void SetFromLump(int filenum, FResourceLump* lmp, StringPool* sp)
void SetFromLump(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr)
{
lump = lmp;
resfile = file;
resindex = fileindex;
rfnum = filenum;
flags = 0;
if (lump->Flags & LUMPF_SHORTNAME)
auto lflags = file->GetEntryFlags(fileindex);
if (!name) name = file->getName(fileindex);
if (lflags & RESFF_SHORTNAME)
{
UpperCopy(shortName.String, lump->getName());
UpperCopy(shortName.String, name);
shortName.String[8] = 0;
LongName = "";
Namespace = lump->GetNamespace();
Namespace = file->GetEntryNamespace(fileindex);
resourceId = -1;
}
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
else if ((lflags & RESFF_EMBEDDED) || !name || !*name)
{
shortName.qword = 0;
LongName = "";
@ -121,8 +126,8 @@ struct FileSystem::LumpRecord
}
else
{
LongName = lump->getName();
resourceId = lump->GetIndexNum();
LongName = name;
resourceId = file->GetEntryResourceID(fileindex);
// Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS.
@ -206,11 +211,6 @@ void FileSystem::DeleteAll ()
Hashes.clear();
NumEntries = 0;
// explicitly delete all manually added lumps.
for (auto &frec : FileInfo)
{
if (frec.rfnum == -1) delete frec.lump;
}
FileInfo.clear();
for (int i = (int)Files.size() - 1; i >= 0; --i)
{
@ -242,6 +242,8 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
{
int numfiles;
// the first call here will designate a main thread which may use shared file readers. All other thewads have to open new file handles.
SetMainThread();
// open all the files, load headers, and count lumps
DeleteAll();
numfiles = 0;
@ -287,35 +289,6 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
return true;
}
//==========================================================================
//
// AddLump
//
// Adds a given lump to the directory. Does not perform rehashing
//
//==========================================================================
void FileSystem::AddLump(FResourceLump *lump)
{
FileInfo.resize(FileInfo.size() + 1);
FileInfo.back().SetFromLump(-1, lump, stringpool);
}
//-----------------------------------------------------------------------
//
// Adds an external file to the lump list but not to the hash chains
// It's just a simple means to assign a lump number to some file so that
// the texture manager can read from it.
//
//-----------------------------------------------------------------------
int FileSystem::AddExternalFile(const char *filename)
{
FResourceLump *lump = new FExternalLump(filename, -1, stringpool);
AddLump(lump);
return (int)FileInfo.size() - 1; // later
}
//==========================================================================
//
// AddFromBuffer
@ -324,27 +297,24 @@ int FileSystem::AddExternalFile(const char *filename)
//
//==========================================================================
struct FMemoryLump : public FResourceLump
int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, int flags)
{
FMemoryLump(const void* data, int length)
{
RefCount = -1;
LumpSize = length;
Cache = new char[length];
memcpy(Cache, data, length);
}
};
FileReader fr;
FileData blob(data, size);
fr.OpenMemoryArray(blob);
int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags)
{
std::string fullname = name;
fullname += '.';
fullname += type;
auto newlump = new FMemoryLump(data, size);
newlump->LumpNameSetup(fullname.c_str(), stringpool);
AddLump(newlump);
FileInfo.back().resourceId = id;
return (int)FileInfo.size()-1;
// wrap this into a single lump resource file (should be done a little better later.)
auto rf = new FResourceFile(name, fr, stringpool);
auto Entries = rf->AllocateEntries(1);
Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str());
Entries[0].ResourceID = -1;
Entries[0].Length = size;
Files.push_back(rf);
FileInfo.resize(FileInfo.size() + 1);
FileSystem::LumpRecord* lump_p = &FileInfo.back();
lump_p->SetFromLump(rf, 0, (int)Files.size() - 1, stringpool);
return (int)FileInfo.size() - 1;
}
//==========================================================================
@ -409,25 +379,23 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
uint32_t lumpstart = (uint32_t)FileInfo.size();
resfile->SetFirstLump(lumpstart);
Files.push_back(resfile);
for (int i = 0; i < resfile->EntryCount(); i++)
{
FResourceLump* lump = resfile->GetLump(i);
FileInfo.resize(FileInfo.size() + 1);
FileSystem::LumpRecord* lump_p = &FileInfo.back();
lump_p->SetFromLump((int)Files.size(), lump, stringpool);
lump_p->SetFromLump(resfile, i, (int)Files.size() - 1, stringpool);
}
Files.push_back(resfile);
for (int i = 0; i < resfile->EntryCount(); i++)
{
int flags = resfile->GetEntryFlags(i);
if (flags & LUMPF_EMBEDDED)
if (flags & RESFF_EMBEDDED)
{
std::string path = filename;
path += ':';
path += resfile->getName(i);
auto embedded = resfile->GetEntryReader(i, true);
auto embedded = resfile->GetEntryReader(i, READER_NEW, READERFLAG_SEEKABLE);
AddFile(path.c_str(), &embedded, filter, Printf, hashfile);
}
}
@ -448,7 +416,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]);
}
fprintf(hashfile, "file: %s, hash: %s, size: %d\n", filename, cksumout, (int)filereader.GetLength());
fprintf(hashfile, "file: %s, hash: %s, size: %td\n", filename, cksumout, filereader.GetLength());
}
else
@ -457,9 +425,9 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
for (int i = 0; i < resfile->EntryCount(); i++)
{
int flags = resfile->GetEntryFlags(i);
if (!(flags & LUMPF_EMBEDDED))
if (!(flags & RESFF_EMBEDDED))
{
auto reader = resfile->GetEntryReader(i, true);
auto reader = resfile->GetEntryReader(i, READER_SHARED, 0);
md5Hash(filereader, cksum);
for (size_t j = 0; j < sizeof(cksum); ++j)
@ -467,7 +435,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]);
}
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %llu\n", filename, resfile->getName(i), cksumout, (uint64_t)resfile->Length(i));
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %zu\n", filename, resfile->getName(i), cksumout, (uint64_t)resfile->Length(i));
}
}
}
@ -561,8 +529,9 @@ int FileSystem::CheckNumForName (const char *name, int space) const
// If we find a lump with this name in the global namespace that does not come
// from a Zip return that. WADs don't know these namespaces and single lumps must
// work as well.
auto lflags = lump.resfile->GetEntryFlags(lump.resindex);
if (space > ns_specialzipdirectory && lump.Namespace == ns_global &&
!((lump.lump->Flags ^lump.flags) & LUMPF_FULLPATH)) break;
!((lflags ^lump.flags) & RESFF_FULLPATH)) break;
}
i = NextLumpIndex[i];
}
@ -802,31 +771,14 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const
//
//==========================================================================
int FileSystem::FileLength (int lump) const
ptrdiff_t FileSystem::FileLength (int lump) const
{
if ((size_t)lump >= NumEntries)
{
return -1;
}
return FileInfo[lump].lump->LumpSize;
}
//==========================================================================
//
// GetFileOffset
//
// Returns the offset from the beginning of the file to the lump.
// Returns -1 if the lump is compressed or can't be read directly
//
//==========================================================================
int FileSystem::GetFileOffset (int lump)
{
if ((size_t)lump >= NumEntries)
{
return -1;
}
return FileInfo[lump].lump->GetFileOffset();
const auto &lump_p = FileInfo[lump];
return (int)lump_p.resfile->Length(lump_p.resindex);
}
//==========================================================================
@ -842,7 +794,8 @@ int FileSystem::GetFileFlags (int lump)
return 0;
}
return FileInfo[lump].lump->Flags ^ FileInfo[lump].flags;
const auto& lump_p = FileInfo[lump];
return lump_p.resfile->GetEntryFlags(lump_p.resindex) ^ lump_p.flags;
}
//==========================================================================
@ -938,8 +891,6 @@ void FileSystem::RenameFile(int num, const char* newfn)
//
//==========================================================================
static FResourceLump placeholderLump;
void FileSystem::MoveLumpsInFolder(const char *path)
{
if (FileInfo.size() == 0)
@ -957,11 +908,12 @@ void FileSystem::MoveLumpsInFolder(const char *path)
if (li.rfnum >= GetIwadNum()) break;
if (strnicmp(li.LongName, path, len) == 0)
{
FileInfo.push_back(li);
li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list.
auto lic = li; // make a copy before pushing.
FileInfo.push_back(lic);
li.LongName = ""; //nuke the name of the old record.
li.shortName.qword = 0;
auto &ln = FileInfo.back();
ln.lump->LumpNameSetup(ln.LongName + len, stringpool); // may be able to avoid the string allocation!
ln.SetFromLump(rfnum, ln.lump, stringpool);
ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len);
}
}
}
@ -1321,7 +1273,7 @@ void FileSystem::ReadFile (int lump, void *dest)
if (numread != size)
{
throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n",
throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n",
numread, size, FileInfo[lump].LongName);
}
}
@ -1341,9 +1293,7 @@ FileData FileSystem::ReadFile (int lump)
{
throw FileSystemException("ReadFile: %u >= NumEntries", lump);
}
auto lumpp = FileInfo[lump].lump;
return FileData(lumpp);
return FileInfo[lump].resfile->Read(FileInfo[lump].resindex);
}
//==========================================================================
@ -1355,53 +1305,31 @@ FileData FileSystem::ReadFile (int lump)
//==========================================================================
FileReader FileSystem::OpenFileReader(int lump)
FileReader FileSystem::OpenFileReader(int lump, int readertype, int readerflags)
{
if ((unsigned)lump >= (unsigned)FileInfo.size())
{
throw FileSystemException("OpenFileReader: %u >= NumEntries", lump);
}
auto rl = FileInfo[lump].lump;
auto rd = rl->GetReader();
if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & LUMPF_COMPRESSED))
{
FileReader rdr;
rdr.OpenFilePart(*rd, rl->GetFileOffset(), rl->LumpSize);
return rdr;
}
return rl->NewReader(); // This always gets a reader to the cache
}
FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache)
{
if ((unsigned)lump >= (unsigned)FileInfo.size())
{
throw FileSystemException("ReopenFileReader: %u >= NumEntries", lump);
}
auto rl = FileInfo[lump].lump;
auto rd = rl->GetReader();
if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & LUMPF_COMPRESSED))
{
int fileno = GetFileContainer(lump);
const char *filename = GetResourceFileFullName(fileno);
FileReader fr;
if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize))
{
return fr;
}
}
return rl->NewReader(); // This always gets a reader to the cache
auto file = FileInfo[lump].resfile;
return file->GetEntryReader(FileInfo[lump].resindex, readertype, readerflags);
}
FileReader FileSystem::OpenFileReader(const char* name)
{
FileReader fr;
auto lump = CheckNumForFullName(name);
if (lump < 0) return FileReader();
else return OpenFileReader(lump);
if (lump >= 0) fr = OpenFileReader(lump);
return fr;
}
FileReader FileSystem::ReopenFileReader(const char* name, bool alwayscache)
{
FileReader fr;
auto lump = CheckNumForFullName(name);
if (lump >= 0) fr = ReopenFileReader(lump, alwayscache);
return fr;
}
//==========================================================================
@ -1530,7 +1458,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
if (slash == nullptr)
{
FileInfo[lump].flags = LUMPF_FULLPATH;
FileInfo[lump].flags = RESFF_FULLPATH;
return true; // already is pathless.
}
@ -1538,7 +1466,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
// just create a new reference to the original data with a different name.
oldlump.LongName = slash + 1;
oldlump.resourceId = id;
oldlump.flags = LUMPF_FULLPATH;
oldlump.flags = RESFF_FULLPATH;
FileInfo.push_back(oldlump);
return true;
}

View file

@ -104,10 +104,11 @@ StringPool::Block *StringPool::AddBlock(size_t size)
return mem;
}
void *StringPool::iAlloc(size_t size)
void *StringPool::Alloc(size_t size)
{
Block *block;
size = (size + 7) & ~7;
for (block = TopBlock; block != nullptr; block = block->NextBlock)
{
void *res = block->Alloc(size);
@ -122,7 +123,7 @@ void *StringPool::iAlloc(size_t size)
const char* StringPool::Strdup(const char* str)
{
char* p = (char*)iAlloc((strlen(str) + 8) & ~7 );
char* p = (char*)Alloc(strlen(str) + 1);
strcpy(p, str);
return p;
}

View file

@ -8,19 +8,18 @@ class StringPool
friend class FileSystem;
friend class FResourceFile;
private:
StringPool(bool _shared, size_t blocksize = 10*1024) : TopBlock(nullptr), FreeBlocks(nullptr), BlockSize(blocksize), shared(_shared) {}
StringPool(bool _shared, size_t blocksize = 10*1024) : TopBlock(nullptr), BlockSize(blocksize), shared(_shared) {}
public:
~StringPool();
const char* Strdup(const char*);
void* Alloc(size_t size);
protected:
struct Block;
Block *AddBlock(size_t size);
void *iAlloc(size_t size);
Block *TopBlock;
Block *FreeBlocks;
size_t BlockSize;
public:
bool shared;

View file

@ -35,13 +35,29 @@
*/
#include <miniz.h>
#include "resourcefile_internal.h"
#include "resourcefile.h"
#include "md5.hpp"
#include "fs_stringpool.h"
#include "files_internal.h"
#include "unicode.h"
#include "fs_findfile.h"
#include "fs_decompress.h"
#include "wildcards.hpp"
namespace FileSys {
// this is for restricting shared file readers to the main thread.
thread_local bool mainThread;
void SetMainThread()
{
// only set the global flag on the first thread calling this.
static bool done = false;
if (!done)
{
mainThread = done = true;
}
}
std::string ExtractBaseName(const char* path, bool include_extension)
{
const char* src, * dot;
@ -78,195 +94,43 @@ void strReplace(std::string& str, const char *from, const char* to)
}
}
//==========================================================================
//
// File reader that reads from a lump's cache
//
//==========================================================================
class FLumpReader : public MemoryReader
{
FResourceLump *source;
public:
FLumpReader(FResourceLump *src)
: MemoryReader(NULL, src->LumpSize), source(src)
{
src->Lock();
bufptr = src->Cache;
}
~FLumpReader()
{
source->Unlock();
}
};
//==========================================================================
//
// Base class for resource lumps
//
//==========================================================================
FResourceLump::~FResourceLump()
{
if (Cache != NULL && RefCount >= 0)
{
delete [] Cache;
Cache = NULL;
}
Owner = NULL;
}
//==========================================================================
//
// Sets up the lump name information for anything not coming from a WAD file.
//
//==========================================================================
void FResourceLump::LumpNameSetup(const char *iname, StringPool* allocator)
{
// this causes interference with real Dehacked lumps.
if (!stricmp(iname, "dehacked.exe"))
{
iname = "";
}
else if (allocator)
{
iname = allocator->Strdup(iname);
}
FullName = iname;
}
//==========================================================================
//
// Checks for embedded resource files
//
//==========================================================================
static bool IsWadInFolder(const FResourceFile* const archive, const char* const resPath)
bool FResourceFile::IsFileInFolder(const char* const resPath)
{
// Checks a special case when <somefile.wad> was put in
// <myproject> directory inside <myproject.zip>
if (NULL == archive)
{
return false;
}
const auto dirName = ExtractBaseName(archive->GetFileName());
const auto dirName = ExtractBaseName(FileName);
const auto fileName = ExtractBaseName(resPath, true);
const std::string filePath = dirName + '/' + fileName;
return 0 == stricmp(filePath.c_str(), resPath);
}
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi)
{
// Checks for embedded archives
const char *c = strstr(FullName, ".wad");
if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName)))
auto FullName = Entries[entry].FileName;
const char *c = strstr(FullName, ".wad"); // fixme: Use lfi for this.
if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsFileInFolder(FullName)))
{
Flags |= LUMPF_EMBEDDED;
Entries[entry].Flags |= RESFF_EMBEDDED;
}
else if (lfi) for (auto& fstr : lfi->embeddings)
{
if (!stricmp(FullName, fstr.c_str()))
{
Flags |= LUMPF_EMBEDDED;
Entries[entry].Flags |= RESFF_EMBEDDED;
}
}
}
//==========================================================================
//
// this is just for completeness. For non-Zips only an uncompressed lump can
// be returned.
//
//==========================================================================
FCompressedBuffer FResourceLump::GetRawData()
{
FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)LumpSize, METHOD_STORED, 0, 0, new char[LumpSize] };
memcpy(cbuf.mBuffer, Lock(), LumpSize);
Unlock();
cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize);
return cbuf;
}
//==========================================================================
//
// Returns the owner's FileReader if it can be used to access this lump
//
//==========================================================================
FileReader *FResourceLump::GetReader()
{
return NULL;
}
//==========================================================================
//
// Returns a file reader to the lump's cache
//
//==========================================================================
FileReader FResourceLump::NewReader()
{
return FileReader(new FLumpReader(this));
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
//
//==========================================================================
void *FResourceLump::Lock()
{
if (Cache != NULL)
{
if (RefCount > 0) RefCount++;
}
else if (LumpSize > 0)
{
try
{
FillCache();
}
catch (const FileSystemException& err)
{
// enrich the message with info about this lump.
throw FileSystemException("%s, file '%s': %s", getName(), Owner->GetFileName(), err.what());
}
}
return Cache;
}
//==========================================================================
//
// Decrements reference counter and frees lump if counter reaches 0
//
//==========================================================================
int FResourceLump::Unlock()
{
if (LumpSize > 0 && RefCount > 0)
{
if (--RefCount == 0)
{
delete [] Cache;
Cache = NULL;
}
}
return RefCount;
}
//==========================================================================
//
// Opens a resource file
@ -282,11 +146,13 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo*
FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp);
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckWHRes, CheckLump };
static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckHog, CheckMvl, CheckWHRes, CheckLump };
static int nulPrintf(FSMessageLevel msg, const char* fmt, ...)
{
@ -347,11 +213,95 @@ FResourceFile::~FResourceFile()
if (!stringpool->shared) delete stringpool;
}
int lumpcmp(const void * a, const void * b)
//==========================================================================
//
// this is just for completeness. For non-Zips only an uncompressed lump can
// be returned.
//
//==========================================================================
FCompressedBuffer FResourceFile::GetRawData(uint32_t entry)
{
FResourceLump * rec1 = (FResourceLump *)a;
FResourceLump * rec2 = (FResourceLump *)b;
return stricmp(rec1->getName(), rec2->getName());
size_t LumpSize = entry << NumLumps ? Entries[entry].Length : 0;
FCompressedBuffer cbuf = { LumpSize, LumpSize, METHOD_STORED, 0, 0, LumpSize == 0? nullptr : new char[LumpSize] };
if (LumpSize > 0)
{
auto fr = GetEntryReader(entry, READER_SHARED, 0);
size_t read = fr.Read(cbuf.mBuffer, LumpSize);
if (read < LumpSize)
{
delete cbuf.mBuffer;
cbuf.mBuffer = nullptr;
LumpSize = cbuf.mCompressedSize = cbuf.mSize = 0;
}
}
if (LumpSize > 0)
cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize);
return cbuf;
}
//==========================================================================
//
// normalize the visible file name in the system
// to lowercase canonical precomposed Unicode.
//
//==========================================================================
const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp)
{
if (!fn || !*fn) return "";
auto norm = tolower_normalize(fn);
if (!norm)
{
if (fallbackcp == 437)
{
std::vector<char> buffer;
ibm437_to_utf8(fn, buffer);
norm = tolower_normalize(buffer.data());
}
// maybe handle other codepages
else
{
// if the filename is not valid UTF-8, nuke all bytes larger than 0x80 so that we still got something semi-usable
std::string ffn = fn;
for (auto& c : ffn)
{
if (c & 0x80) c = '@';
}
norm = tolower_normalize(&ffn.front());
}
}
FixPathSeparator(norm);
auto pooled = stringpool->Strdup(norm);
free(norm);
return pooled;
}
//==========================================================================
//
// allocate the Entries array
// this also uses the string pool to reduce maintenance
//
//==========================================================================
FResourceEntry* FResourceFile::AllocateEntries(int count)
{
NumLumps = count;
Entries = (FResourceEntry*)stringpool->Alloc(count * sizeof(FResourceEntry));
memset(Entries, 0, count * sizeof(FResourceEntry));
return Entries;
}
//---------------------------------------------------
int entrycmp(const void* a, const void* b)
{
FResourceEntry* rec1 = (FResourceEntry*)a;
FResourceEntry* rec2 = (FResourceEntry*)b;
// we are comparing lowercase UTF-8 here
return strcmp(rec1->FileName, rec2->FileName);
}
//==========================================================================
@ -379,6 +329,8 @@ void FResourceFile::GenerateHash()
{
auto name = getName(i);
auto size = Length(i);
if (name == nullptr)
continue;
md5_append(&state, (const uint8_t*)name, (unsigned)strlen(name) + 1);
md5_append(&state, (const uint8_t*)&size, sizeof(size));
}
@ -400,30 +352,132 @@ void FResourceFile::GenerateHash()
//
//==========================================================================
void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter)
void FResourceFile::PostProcessArchive(LumpFilterInfo *filter)
{
// Entries in archives are sorted alphabetically
qsort(lumps, NumLumps, lumpsize, lumpcmp);
// only do this for archive types which contain full file names. All others are assumed to be pre-sorted.
if (NumLumps == 0 || !(Entries[0].Flags & RESFF_FULLPATH)) return;
// First eliminate all unwanted files
if (filter)
{
for (uint32_t i = 0; i < NumLumps; i++)
{
std::string name = Entries[i].FileName;
for (auto& pattern : filter->blockednames)
{
if (wildcards::match(name, pattern))
{
Entries[i].FileName = "";
continue;
}
}
}
}
// Entries in archives are sorted alphabetically.
qsort(Entries, NumLumps, sizeof(Entries[0]), entrycmp);
if (!filter) return;
FindCommonFolder(filter);
// Filter out lumps using the same names as the Autoload.* sections
// in the ini file use. We reduce the maximum lump concidered after
// in the ini file. We reduce the maximum lump concidered after
// each one so that we don't risk refiltering already filtered lumps.
uint32_t max = NumLumps;
max -= FilterLumpsByGameType(filter, lumps, lumpsize, max);
ptrdiff_t len;
ptrdiff_t lastpos = -1;
std::string file;
std::string& LumpFilter = filter->dotFilter;
while (size_t(len = LumpFilter.find_first_of('.', lastpos+1)) != LumpFilter.npos)
for (auto& LumpFilter : filter->gameTypeFilter)
{
max -= FilterLumps(std::string(LumpFilter, 0, len), lumps, lumpsize, max);
lastpos = len;
ptrdiff_t len;
ptrdiff_t lastpos = -1;
std::string file;
while (size_t(len = LumpFilter.find_first_of('.', lastpos + 1)) != LumpFilter.npos)
{
max -= FilterLumps(std::string(LumpFilter, 0, len), max);
lastpos = len;
}
max -= FilterLumps(LumpFilter, max);
}
max -= FilterLumps(LumpFilter, lumps, lumpsize, max);
JunkLeftoverFilters(lumps, lumpsize, max);
JunkLeftoverFilters(max);
for (uint32_t i = 0; i < NumLumps; i++)
{
CheckEmbedded(i, filter);
}
}
//==========================================================================
//
// FResourceFile :: FindCommonFolder
//
// Checks if all content is in a common folder that can be stripped out.
//
//==========================================================================
void FResourceFile::FindCommonFolder(LumpFilterInfo* filter)
{
std::string name0, name1;
bool foundspeciallump = false;
bool foundprefix = false;
// try to find a path prefix.
for (uint32_t i = 0; i < NumLumps; i++)
{
if (*Entries[i].FileName == 0) continue;
std::string name = Entries[i].FileName;
// first eliminate files we do not want to have.
// Some, like MacOS resource forks and executables are eliminated unconditionally, but the calling code can alsp pass a list of invalid content.
if (name.find("filter/") == 0)
return; // 'filter' is a reserved name of the file system. If this appears in the root we got no common folder, and 'filter' cannot be it.
if (!foundprefix)
{
// check for special names, if one of these gets found this must be treated as a normal zip.
bool isspecial = name.find("/") == std::string::npos ||
(filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name) != filter->reservedFolders.end());
if (isspecial) break;
name0 = std::string(name, 0, name.rfind("/") + 1);
name1 = std::string(name, 0, name.find("/") + 1);
foundprefix = true;
}
if (name.find(name0) != 0)
{
if (!name1.empty())
{
name0 = name1;
if (name.find(name0) != 0)
{
name0 = "";
}
}
if (name0.empty())
break;
}
if (!foundspeciallump && filter)
{
// at least one of the more common definition lumps must be present.
for (auto& p : filter->requiredPrefixes)
{
if (name.find(name0 + p) == 0 || name.rfind(p) == size_t(name.length() - p.length()))
{
foundspeciallump = true;
break;
}
}
}
}
// If it ran through the list without finding anything it should not attempt any path remapping.
if (!foundspeciallump || name0.empty()) return;
size_t pathlen = name0.length();
for (uint32_t i = 0; i < NumLumps; i++)
{
if (Entries[i].FileName[0] == 0) continue;
Entries[i].FileName += pathlen;
}
}
//==========================================================================
@ -436,7 +490,7 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI
//
//==========================================================================
int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max)
int FResourceFile::FilterLumps(const std::string& filtername, uint32_t max)
{
uint32_t start, end;
@ -446,44 +500,35 @@ int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_
}
std::string filter = "filter/" + filtername + '/';
bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
// Workaround for old Doom filter names (todo: move out of here.)
if (!found && filtername.find("doom.id.doom") == 0)
{
strReplace(filter, "doom.id.doom", "doom.doom");
found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
}
bool found = FindPrefixRange(filter.c_str(), max, start, end);
if (found)
{
void *from = (uint8_t *)lumps + start * lumpsize;
// Remove filter prefix from every name
void *lump_p = from;
for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize)
for (uint32_t i = start; i < end; ++i)
{
FResourceLump *lump = (FResourceLump *)lump_p;
assert(strnicmp(lump->FullName, filter.c_str(), filter.length()) == 0);
lump->LumpNameSetup(lump->FullName + filter.length(), nullptr);
assert(strnicmp(Entries[i].FileName, filter.c_str(), filter.length()) == 0);
Entries[i].FileName += filter.length();
}
// Move filtered lumps to the end of the lump list.
size_t count = (end - start) * lumpsize;
void *to = (uint8_t *)lumps + NumLumps * lumpsize - count;
size_t count = (end - start);
auto from = Entries + start;
auto to = Entries + NumLumps - count;
assert (to >= from);
if (from != to)
{
// Copy filtered lumps to a temporary buffer.
uint8_t *filteredlumps = new uint8_t[count];
memcpy(filteredlumps, from, count);
auto filteredlumps = new FResourceEntry[count];
memcpy(filteredlumps, from, count * sizeof(*Entries));
// Shift lumps left to make room for the filtered ones at the end.
memmove(from, (uint8_t *)from + count, (NumLumps - end) * lumpsize);
memmove(from, from + count, (NumLumps - end) * sizeof(*Entries));
// Copy temporary buffer to newly freed space.
memcpy(to, filteredlumps, count);
memcpy(to, filteredlumps, count * sizeof(*Entries));
delete[] filteredlumps;
}
@ -491,29 +536,6 @@ int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_
return end - start;
}
//==========================================================================
//
// FResourceFile :: FilterLumpsByGameType
//
// Matches any lumps that match "filter/game-<gametype>/*". Includes
// inclusive gametypes like Raven.
//
//==========================================================================
int FResourceFile::FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max)
{
if (filter == nullptr)
{
return 0;
}
int count = 0;
for (auto &fstring : filter->gameTypeFilter)
{
count += FilterLumps(fstring, lumps, lumpsize, max);
}
return count;
}
//==========================================================================
//
// FResourceFile :: JunkLeftoverFilters
@ -522,19 +544,17 @@ int FResourceFile::FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, si
//
//==========================================================================
void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max)
void FResourceFile::JunkLeftoverFilters(uint32_t max)
{
uint32_t start, end;
if (FindPrefixRange("filter/", lumps, lumpsize, max, start, end))
if (FindPrefixRange("filter/", max, start, end))
{
// Since the resource lumps may contain non-POD data besides the
// full name, we "delete" them by erasing their names so they
// can't be found.
void *stop = (uint8_t *)lumps + end * lumpsize;
for (void *p = (uint8_t *)lumps + start * lumpsize; p < stop; p = (uint8_t *)p + lumpsize)
for (uint32_t i = start; i < end; i++)
{
FResourceLump *lump = (FResourceLump *)p;
lump->clearName();
Entries[i].FileName = "";
}
}
}
@ -549,25 +569,24 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m
//
//==========================================================================
bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end)
bool FResourceFile::FindPrefixRange(const char* filter, uint32_t maxlump, uint32_t &start, uint32_t &end)
{
uint32_t min, max, mid, inside;
FResourceLump *lump;
int cmp = 0;
end = start = 0;
// Pretend that our range starts at 1 instead of 0 so that we can avoid
// unsigned overflow if the range starts at the first lump.
lumps = (uint8_t *)lumps - lumpsize;
auto lumps = &Entries[-1];
// Binary search to find any match at all.
mid = min = 1, max = maxlump;
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
auto lump = &lumps[mid];
cmp = strnicmp(lump->FileName, filter, strlen(filter));
if (cmp == 0)
break;
else if (cmp < 0)
@ -586,8 +605,8 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
auto lump = &lumps[mid];
cmp = strnicmp(lump->FileName, filter, strlen(filter));
// Go left on matches and right on misses.
if (cmp == 0)
max = mid - 1;
@ -601,8 +620,8 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
while (min <= max)
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = strnicmp(lump->FullName, filter, (int)strlen(filter));
auto lump = &lumps[mid];
cmp = strnicmp(lump->FileName, filter, strlen(filter));
// Go right on matches and left on misses.
if (cmp == 0)
min = mid + 1;
@ -621,27 +640,19 @@ bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lump
int FResourceFile::FindEntry(const char *name)
{
auto norm_fn = tolower_normalize(name);
for (unsigned i = 0; i < NumLumps; i++)
{
if (!stricmp(name, getName(i)))
if (!strcmp(norm_fn, getName(i)))
{
free(norm_fn);
return i;
}
}
free(norm_fn);
return -1;
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
//
//==========================================================================
FileReader *FUncompressedLump::GetReader()
{
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
return Owner->GetContainerReader();
}
//==========================================================================
//
@ -649,103 +660,73 @@ FileReader *FUncompressedLump::GetReader()
//
//==========================================================================
int FUncompressedLump::FillCache()
FileReader FResourceFile::GetEntryReader(uint32_t entry, int readertype, int readerflags)
{
const char * buffer = Owner->GetContainerReader()->GetBuffer();
if (buffer != NULL)
FileReader fr;
if (entry < NumLumps)
{
// This is an in-memory file so the cache can point directly to the file's data.
Cache = const_cast<char*>(buffer) + Position;
RefCount = -1;
return -1;
}
Owner->GetContainerReader()->Seek(Position, FileReader::SeekSet);
Cache = new char[LumpSize];
auto read = Owner->GetContainerReader()->Read(Cache, LumpSize);
if (read != LumpSize)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
}
RefCount = 1;
return 1;
}
//==========================================================================
//
// Base class for uncompressed resource files
//
//==========================================================================
FUncompressedFile::FUncompressedFile(const char *filename, StringPool* sp)
: FResourceFile(filename, sp)
{}
FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r, StringPool* sp)
: FResourceFile(filename, r, sp)
{}
//==========================================================================
//
// external lump
//
//==========================================================================
FExternalLump::FExternalLump(const char *_filename, int filesize, StringPool* stringpool)
{
FileName = stringpool->Strdup(_filename);
if (filesize == -1)
{
FileReader f;
if (f.OpenFile(_filename))
if (Entries[entry].Flags & RESFF_NEEDFILESTART)
{
LumpSize = (int)f.GetLength();
SetEntryAddress(entry);
}
if (!(Entries[entry].Flags & RESFF_COMPRESSED))
{
auto buf = Reader.GetBuffer();
// if this is backed by a memory buffer, create a new reader directly referencing it.
if (buf != nullptr)
{
fr.OpenMemory(buf + Entries[entry].Position, Entries[entry].Length);
}
else
{
if (readertype == READER_SHARED && !mainThread)
readertype = READER_NEW;
if (readertype == READER_SHARED)
{
fr.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].Length);
}
else if (readertype == READER_NEW)
{
fr.OpenFile(FileName, Entries[entry].Position, Entries[entry].Length);
}
else if (readertype == READER_CACHED)
{
Reader.Seek(Entries[entry].Position, FileReader::SeekSet);
auto data = Reader.Read(Entries[entry].Length);
fr.OpenMemoryArray(data);
}
}
}
else
{
LumpSize = 0;
FileReader fri;
if (readertype == READER_NEW || !mainThread) fri.OpenFile(FileName, Entries[entry].Position, Entries[entry].CompressedSize);
else fri.OpenFilePart(Reader, Entries[entry].Position, Entries[entry].CompressedSize);
int flags = DCF_TRANSFEROWNER | DCF_EXCEPTIONS;
if (readertype == READER_CACHED) flags |= DCF_CACHED;
else if (readerflags & READERFLAG_SEEKABLE) flags |= DCF_SEEKABLE;
OpenDecompressor(fr, fri, Entries[entry].Length, Entries[entry].Method, flags);
}
}
else
{
LumpSize = filesize;
}
return fr;
}
//==========================================================================
//
// Caches a lump's content and increases the reference counter
// For external lumps this reopens the file each time it is accessed
//
//==========================================================================
int FExternalLump::FillCache()
FileData FResourceFile::Read(uint32_t entry)
{
Cache = new char[LumpSize];
FileReader f;
if (f.OpenFile(FileName))
if (!(Entries[entry].Flags & RESFF_COMPRESSED) && Reader.isOpen())
{
auto read = f.Read(Cache, LumpSize);
if (read != LumpSize)
auto buf = Reader.GetBuffer();
// if this is backed by a memory buffer, we can just return a reference to the backing store.
if (buf != nullptr)
{
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
return FileData(buf + Entries[entry].Position, Entries[entry].Length, false);
}
}
else
{
throw FileSystemException("unable to open file");
}
RefCount = 1;
return 1;
auto fr = GetEntryReader(entry, READER_SHARED, 0);
return fr.Read(entry < NumLumps ? Entries[entry].Length : 0);
}
}

View file

@ -1,38 +0,0 @@
#pragma once
#include "resourcefile.h"
namespace FileSys {
struct FUncompressedLump : public FResourceLump
{
int Position;
virtual FileReader *GetReader();
virtual int FillCache() override;
virtual int GetFileOffset() { return Position; }
};
// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps)
class FUncompressedFile : public FResourceFile
{
protected:
TArray<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename, StringPool* sp);
FUncompressedFile(const char *filename, FileReader &r, StringPool* sp);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
// should only be used internally.
struct FExternalLump : public FResourceLump
{
const char* FileName;
FExternalLump(const char *_filename, int filesize, StringPool* sp);
virtual int FillCache() override;
};
}

View file

@ -151,7 +151,7 @@ bool unicode_validate(const char* str)
while (*str != 0)
{
int cp;
int result = utf8proc_iterate((const uint8_t*)str, -1, &cp);
auto result = utf8proc_iterate((const uint8_t*)str, -1, &cp);
if (result < 0) return false;
}
return true;

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,7 @@ struct HexDataSource
FScanner sc;
auto data = resf->Read(index);
sc.OpenMem("newconsolefont.hex", data.string(), data.size());
sc.OpenMem("newconsolefont.hex", data.string(), (int)data.size());
sc.SetCMode(true);
glyphdata.Push(0); // ensure that index 0 can be used as 'not present'.
while (sc.GetString())

View file

@ -125,7 +125,7 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump)
FontName = name;
auto data1 = fileSystem.ReadFile (lump);
auto data = data1.GetBytes();
auto data = data1.bytes();
if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A)
{
@ -475,7 +475,7 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
void FSingleLumpFont::CheckFON1Chars()
{
auto memLump = fileSystem.ReadFile(Lump);
auto data = memLump.GetBytes();
auto data = memLump.bytes();
const uint8_t* data_p;
data_p = data + 8;

View file

@ -57,7 +57,7 @@ public:
sft.xScale = height;
sft.yScale = height;
sft.flags = SFT_DOWNWARD_Y;
sft.font = sft_loadmem(lumpdata.GetBytes(), lumpdata.GetSize());
sft.font = sft_loadmem(lumpdata.data(), lumpdata.size());
if (!sft.font)
I_FatalError("Could not load truetype font file");

View file

@ -316,15 +316,7 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index)
auto pic = resf->FindEntry("savepic.png");
if (pic >= 0)
{
FileReader picreader;
picreader.OpenMemoryArray([=](std::vector<uint8_t>& array)
{
auto rd = resf->GetEntryReader(pic, false);
array.resize(resf->Length(pic));
rd.Read(array.data(), array.size());
return true;
});
FileReader picreader = resf->GetEntryReader(pic, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE);
PNGHandle *png = M_VerifyPNG(picreader);
if (png != nullptr)
{

View file

@ -163,9 +163,15 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent)
if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
}
int len = fileSystem.FileLength(lump);
auto len = fileSystem.FileLength(lump);
if (len >= 0x80000000ll)
{
Printf(PRINT_HIGH, "LoadModel: File to large: '%s'\n", fullname.GetChars());
return -1;
}
auto lumpd = fileSystem.ReadFile(lump);
const char * buffer = lumpd.GetString();
const char * buffer = lumpd.string();
if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 )
{
@ -208,7 +214,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent)
if (model != nullptr)
{
if (!model->Load(path, lump, buffer, len))
if (!model->Load(path, lump, buffer, (int)len))
{
delete model;
return -1;

View file

@ -137,7 +137,7 @@ bool IQMModel::Load(const char* path, int lumpnum, const char* buffer, int lengt
}
reader.SeekTo(ofs_anims);
for(int i = 0; i < Anims.Size(); i++)
for(unsigned i = 0; i < Anims.Size(); i++)
{
IQMAnim& anim = Anims[i];
anim.Name = reader.ReadName(text);
@ -274,7 +274,7 @@ void IQMModel::LoadGeometry()
try
{
auto lumpdata = fileSystem.ReadFile(mLumpNum);
IQMFileReader reader(lumpdata.GetMem(), (int)lumpdata.GetSize());
IQMFileReader reader(lumpdata.data(), (int)lumpdata.size());
Vertices.Resize(NumVertices);
for (IQMVertexArray& vertexArray : VertexArrays)

View file

@ -178,7 +178,7 @@ void FDMDModel::LoadGeometry()
{
static int axis[3] = { VX, VY, VZ };
auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString();
auto buffer = lumpdata.string();
texCoords = new FTexCoord[info.numTexCoords];
memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord));
@ -502,7 +502,7 @@ void FMD2Model::LoadGeometry()
static int axis[3] = { VX, VY, VZ };
uint8_t *md2_frames;
auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString();
auto buffer = lumpdata.string();
texCoords = new FTexCoord[info.numTexCoords];
memcpy(texCoords, (uint8_t*)buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord));

View file

@ -190,7 +190,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le
void FMD3Model::LoadGeometry()
{
auto lumpdata = fileSystem.ReadFile(mLumpNum);
auto buffer = lumpdata.GetString();
auto buffer = lumpdata.string();
md3_header_t * hdr = (md3_header_t *)buffer;
md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces));

View file

@ -71,9 +71,9 @@ void FUE1Model::LoadGeometry()
{
const char *buffer, *buffer2;
auto lump = fileSystem.ReadFile(mDataLump);
buffer = lump.GetString();
buffer = lump.string();
auto lump2 = fileSystem.ReadFile(mAnivLump);
buffer2 = lump2.GetString();
buffer2 = lump2.string();
// map structures
dhead = (const d3dhead*)(buffer);
dpolys = (const d3dpoly*)(buffer+sizeof(d3dhead));

View file

@ -162,8 +162,8 @@ FVoxel *R_LoadKVX(int lumpnum)
int i, j, n;
auto lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end.
auto rawvoxel = lump.GetBytes();
int voxelsize = (int)(lump.GetSize());
auto rawvoxel = lump.bytes();
int voxelsize = (int)(lump.size());
// Oh, KVX, why couldn't you have a proper header? We'll just go through
// and collect each MIP level, doing lots of range checking, and if the

View file

@ -65,11 +65,10 @@
#include "palutil.h"
#include "st_start.h"
#include "printf.h"
#include "common/widgets/launcherwindow.h"
#include "launcherwindow.h"
#ifndef NO_GTK
bool I_GtkAvailable ();
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags);
void I_ShowFatalError_Gtk(const char* errortext);
#elif defined(__APPLE__)
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad);

View file

@ -484,106 +484,6 @@ public:
}
};
static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags)
{
char caption[100];
mysnprintf(caption, countof(caption), GAMENAME " %s: Select an IWAD to use", GetVersionString());
ZUIWindow window(caption);
ZUIVBox vbox;
ZUILabel label(GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:");
ZUIListView listview(wads, numwads, defaultiwad);
ZUIScrolledWindow scroll((ZUIWidget*)&listview);
ZUIHBox hboxOptions;
ZUIVBox vboxVideo;
ZUILabel videoSettings("Video settings");
ZUIRadioButton vulkan("Vulkan");
ZUICheckButton fullscreen("Full screen");
ZUIVBox vboxMisc;
ZUICheckButton noautoload("Disable autoload");
ZUICheckButton dontAskAgain("Don't ask me this again");
ZUIVBox vboxExtra;
ZUILabel extraGraphics("Extra graphics");
ZUICheckButton lights("Lights");
ZUICheckButton brightmaps("Brightmaps");
ZUICheckButton widescreen("Widescreen");
ZUIHBox hboxButtons;
ZUIButtonBox bbox;
ZUIButton playButton("Play Game!", true);
ZUIButton exitButton("Exit", false);
window.AddWidget(&vbox);
vbox.PackStart(&label, false, false, 0);
vbox.PackStart(&scroll, true, true, 0);
vbox.PackEnd(&hboxButtons, false, false, 0);
vbox.PackEnd(&hboxOptions, false, false, 0);
hboxOptions.PackStart(&vboxVideo, false, false, 15);
hboxOptions.PackStart(&vboxMisc, true, false, 15);
hboxOptions.PackStart(&vboxExtra, false, false, 15);
vboxVideo.PackStart(&videoSettings, false, false, 0);
vboxVideo.PackStart(&vulkan, false, false, 0);
vboxVideo.PackStart(&fullscreen, false, false, 15);
vboxMisc.PackStart(&noautoload, false, false, 0);
vboxMisc.PackStart(&dontAskAgain, false, false, 0);
vboxExtra.PackStart(&extraGraphics, false, false, 0);
vboxExtra.PackStart(&lights, false, false, 0);
vboxExtra.PackStart(&brightmaps, false, false, 0);
vboxExtra.PackStart(&widescreen, false, false, 0);
hboxButtons.PackStart(&bbox, true, true, 0);
bbox.PackStart(&playButton, false, false, 0);
bbox.PackEnd(&exitButton, false, false, 0);
dontAskAgain.SetChecked(!showwin);
vulkan.SetChecked(true);
if (vid_fullscreen) fullscreen.SetChecked(true);
if (autoloadflags & 1) noautoload.SetChecked(true);
if (autoloadflags & 2) lights.SetChecked(true);
if (autoloadflags & 4) brightmaps.SetChecked(true);
if (autoloadflags & 8) widescreen.SetChecked(true);
int close_style = 0;
listview.ConnectButtonPress(&close_style);
listview.ConnectKeyPress(&window);
playButton.ConnectClickedOK(&close_style);
exitButton.ConnectClickedExit(&window);
playButton.GrabDefault();
window.RunModal();
if (close_style == 1)
{
int i = listview.GetSelectedIndex();
// Set state of queryiwad based on the checkbox.
queryiwad = !dontAskAgain.GetChecked();
vid_fullscreen = fullscreen.GetChecked();
autoloadflags = 0;
if (noautoload.GetChecked()) autoloadflags |= 1;
if (lights.GetChecked()) autoloadflags |= 2;
if (brightmaps.GetChecked()) autoloadflags |= 4;
if (widescreen.GetChecked()) autoloadflags |= 8;
return i;
}
else
{
return -1;
}
}
static void ShowError(const char* errortext)
{
@ -606,11 +506,6 @@ static void ShowError(const char* errortext)
} // namespace Gtk
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags)
{
return Gtk::PickIWad (wads, numwads, showwin, defaultiwad, autoloadflags);
}
void I_ShowFatalError_Gtk(const char* errortext) {
Gtk::ShowError(errortext);
}

View file

@ -381,12 +381,14 @@ static HANDLE WriteMyMiniDump (void)
{
MiniDumpThreadData dumpdata = { file, pMiniDumpWriteDump, &exceptor };
DWORD id;
HANDLE thread = CreateThread (NULL, 0, WriteMiniDumpInAnotherThread,
&dumpdata, 0, &id);
WaitForSingleObject (thread, INFINITE);
if (GetExitCodeThread (thread, &id))
HANDLE thread = CreateThread (NULL, 0, WriteMiniDumpInAnotherThread, &dumpdata, 0, &id);
if (thread != nullptr)
{
good = id;
WaitForSingleObject(thread, INFINITE);
if (GetExitCodeThread(thread, &id))
{
good = id;
}
}
}
}

View file

@ -421,7 +421,8 @@ void FDInputJoystick::ProcessInput()
return;
}
state = (uint8_t *)alloca(DataFormat.dwDataSize);
TArray<uint8_t> statearr(DataFormat.dwDataSize, true);
state = statearr.data();
hr = Device->GetDeviceState(DataFormat.dwDataSize, state);
if (FAILED(hr))
return;

View file

@ -334,7 +334,8 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (!GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) &&
size != 0)
{
uint8_t *buffer = (uint8_t *)alloca(size);
TArray<uint8_t> array(size, true);
uint8_t *buffer = array.data();
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)) == size)
{
int code = GET_RAWINPUT_CODE_WPARAM(wParam);
@ -691,12 +692,15 @@ void I_PutInClipboard (const char *str)
auto wstr = WideString(str);
HGLOBAL cliphandle = GlobalAlloc (GMEM_DDESHARE, wstr.length() * 2 + 2);
if (cliphandle != NULL)
if (cliphandle != nullptr)
{
wchar_t *ptr = (wchar_t *)GlobalLock (cliphandle);
wcscpy (ptr, wstr.c_str());
GlobalUnlock (cliphandle);
SetClipboardData (CF_UNICODETEXT, cliphandle);
if (ptr)
{
wcscpy(ptr, wstr.c_str());
GlobalUnlock(cliphandle);
SetClipboardData(CF_UNICODETEXT, cliphandle);
}
}
CloseClipboard ();
}

View file

@ -284,12 +284,12 @@ int DoMain (HINSTANCE hInstance)
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
ShowWindow(mainwindow.GetHandle(), SW_HIDE);
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
if (StdOut != nullptr) WriteFile(StdOut, "Press any key to exit...", 24, &bytes, nullptr);
FlushConsoleInputBuffer(stdinput);
SetConsoleMode(stdinput, 0);
ReadConsole(stdinput, &bytes, 1, &bytes, NULL);
}
else if (StdOut == NULL)
else if (StdOut == nullptr)
{
mainwindow.ShowErrorPane(nullptr);
}

View file

@ -52,7 +52,7 @@ void MainWindow::Create(const FString& caption, int x, int y, int width, int hei
WS_EX_APPWINDOW,
WinClassName,
wcaption.c_str(),
WS_OVERLAPPEDWINDOW/* | WS_VISIBLE*/ | WS_CLIPCHILDREN,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
x, y, width, height,
(HWND)NULL,
(HMENU)NULL,

View file

@ -87,7 +87,7 @@
#include "i_interface.h"
#include "i_mainwindow.h"
#include "common/widgets/launcherwindow.h"
#include "launcherwindow.h"
// MACROS ------------------------------------------------------------------
@ -343,107 +343,6 @@ static void SetQueryIWad(HWND dialog)
queryiwad = query;
}
//==========================================================================
//
// IWADBoxCallback
//
// Dialog proc for the IWAD selector.
//
//==========================================================================
static int* pAutoloadflags;
BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
int& flags = *pAutoloadflags;;
HWND ctrl;
int i;
switch (message)
{
case WM_INITDIALOG:
// Add our program name to the window title
{
WCHAR label[256];
FString newlabel;
GetWindowTextW(hDlg, label, countof(label));
FString alabel(label);
newlabel.Format(GAMENAME " %s: %s", GetVersionString(), alabel.GetChars());
auto wlabel = newlabel.WideString();
SetWindowTextW(hDlg, wlabel.c_str());
}
// [SP] Upstreamed from Zandronum
char szString[256];
// Check the current video settings.
SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_SETCHECK, vid_fullscreen ? BST_CHECKED : BST_UNCHECKED, 0 );
SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN2, BM_SETCHECK, BST_CHECKED, 0 );
// [SP] This is our's
SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, (flags & 1) ? BST_CHECKED : BST_UNCHECKED, 0);
SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, (flags & 2) ? BST_CHECKED : BST_UNCHECKED, 0 );
SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, (flags & 4) ? BST_CHECKED : BST_UNCHECKED, 0 );
SendDlgItemMessage( hDlg, IDC_WELCOME_WIDESCREEN, BM_SETCHECK, (flags & 8) ? BST_CHECKED : BST_UNCHECKED, 0 );
// Set up our version string.
snprintf(szString, sizeof(szString), "Version %s.", GetVersionString());
SetDlgItemTextA (hDlg, IDC_WELCOME_VERSION, szString);
// Populate the list with all the IWADs found
ctrl = GetDlgItem(hDlg, IDC_IWADLIST);
for (i = 0; i < NumWads; i++)
{
const char *filepart = strrchr(WadList[i].Path.GetChars(), '/');
if (filepart == NULL)
filepart = WadList[i].Path.GetChars();
else
filepart++;
FString work;
if (*filepart) work.Format("%s (%s)", WadList[i].Name.GetChars(), filepart);
else work = WadList[i].Name.GetChars();
std::wstring wide = work.WideString();
SendMessage(ctrl, LB_ADDSTRING, 0, (LPARAM)wide.c_str());
SendMessage(ctrl, LB_SETITEMDATA, i, (LPARAM)i);
}
SendMessage(ctrl, LB_SETCURSEL, DefaultWad, 0);
SetFocus(ctrl);
// Set the state of the "Don't ask me again" checkbox
ctrl = GetDlgItem(hDlg, IDC_DONTASKIWAD);
SendMessage(ctrl, BM_SETCHECK, queryiwad ? BST_UNCHECKED : BST_CHECKED, 0);
// Make sure the dialog is in front. If SHIFT was pressed to force it visible,
// then the other window will normally be on top.
SetForegroundWindow(hDlg);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDCANCEL)
{
EndDialog (hDlg, -1);
}
else if (LOWORD(wParam) == IDOK ||
(LOWORD(wParam) == IDC_IWADLIST && HIWORD(wParam) == LBN_DBLCLK))
{
SetQueryIWad(hDlg);
// [SP] Upstreamed from Zandronum
vid_fullscreen = SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED;
// [SP] This is our's.
flags = 0;
if (SendDlgItemMessage(hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 1;
if (SendDlgItemMessage(hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 2;
if (SendDlgItemMessage(hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 4;
if (SendDlgItemMessage(hDlg, IDC_WELCOME_WIDESCREEN, BM_GETCHECK, 0, 0) == BST_CHECKED) flags |= 8;
ctrl = GetDlgItem (hDlg, IDC_IWADLIST);
EndDialog(hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0));
}
break;
}
return FALSE;
}
//==========================================================================
//
// I_PickIWad
@ -455,7 +354,6 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags)
{
int vkey;
pAutoloadflags = &autoloadflags;
if (stricmp(queryiwad_key, "shift") == 0)
{
vkey = VK_SHIFT;
@ -470,14 +368,6 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int&
}
if (showwin || (vkey != 0 && GetAsyncKeyState(vkey)))
{
/*
WadList = wads;
NumWads = numwads;
DefaultWad = defaultiwad;
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
(HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback);
*/
return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags);
}
return defaultiwad;

View file

@ -326,8 +326,7 @@ bool Win32GLVideo::SetupPixelFormat(int multisample)
if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats))
{
Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n");
goto oldmethod;
I_FatalError("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n");
}
if (vid_hdr && numFormats == 0) // This card/driver doesn't support the rgb16f pixel format. Fall back to 8bpc
@ -343,8 +342,7 @@ bool Win32GLVideo::SetupPixelFormat(int multisample)
if (!myWglChoosePixelFormatARB(m_hDC, attributes.data(), attribsFloat, 1, &pixelFormat, &numFormats))
{
Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n");
goto oldmethod;
I_FatalError("R_OPENGL: Couldn't choose pixel format.");
}
}
else if (vid_hdr)
@ -360,41 +358,12 @@ bool Win32GLVideo::SetupPixelFormat(int multisample)
vr_enable_quadbuffered = false;
goto again;
}
Printf("R_OPENGL: No valid pixel formats found. Retrying in compatibility mode\n");
goto oldmethod;
I_FatalError("R_OPENGL: No valid pixel formats found.");
}
}
else
{
oldmethod:
// If wglChoosePixelFormatARB is not found we have to do it the old fashioned way.
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32, // color depth
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32, // z depth
8, // stencil buffer
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
pixelFormat = ChoosePixelFormat(m_hDC, &pfd);
DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd);
if (pfd.dwFlags & PFD_GENERIC_FORMAT)
{
I_Error("R_OPENGL: OpenGL driver not accelerated!");
return false;
}
I_FatalError("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n");
}
if (!::SetPixelFormat(m_hDC, pixelFormat, NULL))
@ -452,8 +421,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample)
m_hRC = zd_wglCreateContext(m_hDC);
if (m_hRC == NULL)
{
I_Error("R_OPENGL: Unable to create an OpenGL render context.\n");
return false;
I_FatalError("R_OPENGL: Unable to create an OpenGL render context.\n");
}
}
@ -464,7 +432,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample)
}
}
// We get here if the driver doesn't support the modern context creation API which always means an old driver.
I_Error("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n");
I_FatalError("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n");
return false;
}

View file

@ -66,7 +66,7 @@
//-----------------------------------------------------------------------------
//
// Shamelessly lifted from Doomsday (written by Jaakko Keränen)
// Shamelessly lifted from Doomsday (written by Jaakko Keränen)
// also shamelessly lifted from ZDoomGL! ;)
//
//-----------------------------------------------------------------------------

View file

@ -112,7 +112,6 @@ FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defin
{
int lump = fileSystem.CheckNumForFullName(lumpName.GetChars());
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
auto sp = fileSystem.ReadFile(lump);
FString code = GetStringFromLump(lump);
FString patchedCode;

View file

@ -11674,7 +11674,7 @@ FxExpression *FxThreeArgForEachLoop::Resolve(FCompileContext &ctx)
if(HasGameSpecificThreeArgForEachLoopTypeNames())
{
ScriptPosition.Message(MSG_ERROR, "foreach( a, b, c : it ) - 'it' must be % but is a %s", GetGameSpecificThreeArgForEachLoopTypeNames(), BlockIteratorExpr->ValueType->DescriptiveName());
ScriptPosition.Message(MSG_ERROR, "foreach( a, b, c : it ) - 'it' must be %s but is a %s", GetGameSpecificThreeArgForEachLoopTypeNames(), BlockIteratorExpr->ValueType->DescriptiveName());
delete this;
return nullptr;
}
@ -11727,7 +11727,7 @@ FxExpression *FxTypedForEachLoop::Resolve(FCompileContext &ctx)
if(HasGameSpecificTypedForEachLoopTypeNames())
{
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be % but is a %s",GetGameSpecificTypedForEachLoopTypeNames(), Expr->ValueType->DescriptiveName());
ScriptPosition.Message(MSG_ERROR, "foreach(Type var : it ) - 'it' must be %s but is a %s",GetGameSpecificTypedForEachLoopTypeNames(), Expr->ValueType->DescriptiveName());
delete this;
return nullptr;
}

View file

@ -1441,7 +1441,7 @@ public:
//==========================================================================
//
// FxGlobalVariaböe
// FxGlobalVariable
//
//==========================================================================

View file

@ -54,7 +54,7 @@ class PSymbolType : public PSymbol
{
DECLARE_CLASS(PSymbolType, PSymbol);
public:
PType *Type;
PType *Type = nullptr;
PSymbolType(FName name, class PType *ty) : PSymbol(name), Type(ty) {}
PSymbolType() : PSymbol(NAME_None) {}
@ -66,7 +66,7 @@ class PSymbolTreeNode : public PSymbol
{
DECLARE_CLASS(PSymbolTreeNode, PSymbol);
public:
struct ZCC_TreeNode *Node;
struct ZCC_TreeNode *Node = nullptr;
PSymbolTreeNode(FName name, struct ZCC_TreeNode *node) : PSymbol(name), Node(node) {}
PSymbolTreeNode() : PSymbol(NAME_None) {}
@ -147,11 +147,11 @@ public:
void *Pad;
};
PSymbolConstNumeric(FName name, PType *type=NULL) : PSymbolConst(name, type) {}
PSymbolConstNumeric(FName name, PType *type=nullptr) : PSymbolConst(name, type), Float(0) {}
PSymbolConstNumeric(FName name, PType *type, int val) : PSymbolConst(name, type), Value(val) {}
PSymbolConstNumeric(FName name, PType *type, unsigned int val) : PSymbolConst(name, type), Value((int)val) {}
PSymbolConstNumeric(FName name, PType *type, double val) : PSymbolConst(name, type), Float(val) {}
PSymbolConstNumeric() {}
PSymbolConstNumeric() : Float(0) {}
};
// A constant string value --------------------------------------------------

View file

@ -116,7 +116,7 @@ void DumpTypeTable()
}
Printf("\n");
}
Printf("Used buckets: %d/%lu (%.2f%%) for %d entries\n", used, countof(TypeTable.TypeHash), double(used)/countof(TypeTable.TypeHash)*100, all);
Printf("Used buckets: %d/%zu (%.2f%%) for %d entries\n", used, countof(TypeTable.TypeHash), double(used)/countof(TypeTable.TypeHash)*100, all);
Printf("Min bucket size: %d\n", min);
Printf("Max bucket size: %d\n", max);
Printf("Avg bucket size: %.2f\n", double(all) / used);
@ -2568,7 +2568,7 @@ static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m)
{ // invalid
m->ValueType->WriteValue(ar,"invalid",static_cast<const void *>(&p->Value));
}
else if(p->Key == 0 || p->Key >= TexMan.NumTextures())
else if(p->Key == 0 || p->Key >= (unsigned)TexMan.NumTextures())
{ // null
m->ValueType->WriteValue(ar,"null",static_cast<const void *>(&p->Value));
}
@ -2693,7 +2693,7 @@ static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m)
ar.EndObject();
return false;
}
int v = s.ToULong();
int v = (int)s.ToULong();
if (sysCallbacks.RemapTranslation) v = sysCallbacks.RemapTranslation(FTranslationID::fromInt(v)).index();

View file

@ -852,7 +852,7 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpLength)
{
PARAM_PROLOGUE;
PARAM_INT(lump);
ACTION_RETURN_INT(fileSystem.FileLength(lump));
ACTION_RETURN_INT((int)fileSystem.FileLength(lump));
}
//==========================================================================
@ -1407,3 +1407,361 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Translation, MakeID, MakeTransID)
ACTION_RETURN_INT(MakeTransID(g, t));
}
// DObject-based wrapper around FScanner, for ZScript.
class DScriptScanner : public DObject
{
DECLARE_CLASS(DScriptScanner, DObject)
public:
FScanner wrapped;
};
IMPLEMENT_CLASS(DScriptScanner, false, false);
static void OpenLumpNum(DScriptScanner* self, int lump) { return self->wrapped.OpenLumpNum(lump); }
static void OpenString(DScriptScanner* self, const FString* name, FString* script) { return self->wrapped.OpenString(name->GetChars(), *script); }
static void SavePos(DScriptScanner* self, FScanner::SavedPos *pos) { *pos = self->wrapped.SavePos(); }
static void RestorePos(DScriptScanner* self, const FScanner::SavedPos* pos) { return self->wrapped.RestorePos(*pos); }
static void GetStringContents(DScriptScanner* self, FString* str) { *str = self->wrapped.String; }
static void UnGet(DScriptScanner* self) { return self->wrapped.UnGet(); }
static int isText(DScriptScanner* self) { return self->wrapped.isText(); }
static int GetMessageLine(DScriptScanner* self) { return self->wrapped.GetMessageLine(); }
static void Close(DScriptScanner* self) { return self->wrapped.Close(); }
static void SetCMode(DScriptScanner* self, int cmode) { return self->wrapped.SetCMode(cmode); }
static void SetNoOctals(DScriptScanner* self, int cmode) { return self->wrapped.SetNoOctals(cmode); }
static void SetEscape(DScriptScanner* self, int esc) { return self->wrapped.SetNoOctals(esc); }
static void SetNoFatalErrors(DScriptScanner* self, int cmode) { return self->wrapped.SetNoFatalErrors(cmode); }
static void AddSymbolUint(DScriptScanner* self, const FString* name, uint32_t value) { return self->wrapped.AddSymbol(name->GetChars(), value); }
static void AddSymbolInt(DScriptScanner* self, const FString* name, int32_t value) { return self->wrapped.AddSymbol(name->GetChars(), value); }
static void AddSymbolDouble(DScriptScanner* self, const FString* name, double value) { return self->wrapped.AddSymbol(name->GetChars(), value); }
static int GetString(DScriptScanner* self) { return self->wrapped.GetString(); }
static int GetNumber(DScriptScanner* self, int evaluate) { return self->wrapped.GetNumber(evaluate); }
static int GetFloat(DScriptScanner* self, int evaluate) { return self->wrapped.GetFloat(evaluate); }
static int CheckValue(DScriptScanner* self, int allowfloat, int evaluate) { return self->wrapped.CheckValue(allowfloat, evaluate); }
static int CheckNumber(DScriptScanner* self, int evaluate) { return self->wrapped.CheckNumber(evaluate); }
static int CheckBoolToken(DScriptScanner* self) { return self->wrapped.CheckBoolToken(); }
static int CheckString(DScriptScanner* self, const FString* name) { return self->wrapped.CheckString(name->GetChars()); }
static int CheckFloat(DScriptScanner* self, int evaluate) { return self->wrapped.CheckFloat(evaluate); }
static void SetPrependMessage(DScriptScanner* self, const FString* message) { return self->wrapped.SetPrependMessage(*message); }
static void SkipToEndOfBlock(DScriptScanner* self) { return self->wrapped.SkipToEndOfBlock(); }
static int StartBraces(DScriptScanner* self, FScanner::SavedPos* braceend) { return self->wrapped.StartBraces(braceend); }
static int FoundEndBrace(DScriptScanner* self, FScanner::SavedPos* braceend) { return self->wrapped.FoundEndBrace(*braceend); }
static void MustGetValue(DScriptScanner* self, int allowfloat, int evaluate) { return self->wrapped.MustGetValue(allowfloat, evaluate); }
static void MustGetFloat(DScriptScanner* self, int evaluate) { return self->wrapped.MustGetFloat(evaluate); }
static void MustGetNumber(DScriptScanner* self, int evaluate) { return self->wrapped.MustGetNumber(evaluate); }
static void MustGetString(DScriptScanner* self) { return self->wrapped.MustGetString(); }
static void MustGetStringName(DScriptScanner* self, const FString* name) { return self->wrapped.MustGetStringName(name->GetChars()); }
static void MustGetBoolToken(DScriptScanner* self) { return self->wrapped.MustGetBoolToken(); }
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, OpenLumpNum, OpenLumpNum)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_INT(lump);
OpenLumpNum(self, lump);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, OpenString, OpenString)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
PARAM_STRING_VAL(script);
OpenString(self, &name, &script);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SavePos, SavePos)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_POINTER(pos, FScanner::SavedPos);
SavePos(self, pos);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, RestorePos, RestorePos)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_POINTER(pos, FScanner::SavedPos);
RestorePos(self, pos);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetStringContents, GetStringContents)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
ACTION_RETURN_STRING(self->wrapped.String);
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, UnGet, UnGet)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
UnGet(self);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, isText, isText)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
ACTION_RETURN_BOOL(isText(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetMessageLine, GetMessageLine)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
ACTION_RETURN_INT(GetMessageLine(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbol, AddSymbolInt)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
PARAM_INT(value);
AddSymbolInt(self, &name, value);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbolUnsigned, AddSymbolUint)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
PARAM_UINT(value);
AddSymbolUint(self, &name, value);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, AddSymbolFloat, AddSymbolDouble)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
PARAM_FLOAT(value);
AddSymbolDouble(self, &name, value);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetString, GetString)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
ACTION_RETURN_BOOL(GetString(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetNumber, GetNumber)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
ACTION_RETURN_BOOL(GetNumber(self, evaluate));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, GetFloat, GetFloat)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
ACTION_RETURN_BOOL(GetFloat(self, evaluate));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckValue, CheckValue)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(allowfloat);
PARAM_BOOL(evaluate);
ACTION_RETURN_BOOL(CheckValue(self, allowfloat, evaluate));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckBoolToken, CheckBoolToken)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
ACTION_RETURN_BOOL(CheckBoolToken(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckNumber, CheckNumber)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
ACTION_RETURN_BOOL(CheckNumber(self, evaluate));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckString, CheckString)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
ACTION_RETURN_BOOL(CheckString(self, &name));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, CheckFloat, CheckFloat)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
ACTION_RETURN_BOOL(CheckFloat(self, evaluate));
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetPrependMessage, SetPrependMessage)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(message);
SetPrependMessage(self, &message);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetCMode, SetCMode)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(cmode);
SetCMode(self, cmode);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetNoOctals, SetNoOctals)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(cmode);
SetNoOctals(self, cmode);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetEscape, SetEscape)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(esc);
SetEscape(self, esc);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SkipToEndOfBlock, SkipToEndOfBlock)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
SkipToEndOfBlock(self);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, StartBraces, StartBraces)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_POINTER(braceend, FScanner::SavedPos);
StartBraces(self, braceend); // the return value of this is useless.
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, FoundEndBrace, FoundEndBrace)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_POINTER(braceend, FScanner::SavedPos);
ACTION_RETURN_BOOL(FoundEndBrace(self, braceend));
}
DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptError)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
FString s = FStringFormat(VM_ARGS_NAMES);
self->wrapped.ScriptError("%s", s.GetChars());
return 0;
}
DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptMessage)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
FString s = FStringFormat(VM_ARGS_NAMES);
self->wrapped.ScriptMessage("%s", s.GetChars());
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetValue, MustGetValue)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(allowfloat);
PARAM_BOOL(evaluate);
MustGetValue(self, allowfloat, evaluate);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetNumber, MustGetNumber)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
MustGetNumber(self, evaluate);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetFloat, MustGetFloat)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(evaluate);
MustGetFloat(self, evaluate);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetString, MustGetString)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
MustGetString(self);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetStringName, MustGetStringName)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_STRING(name);
MustGetStringName(self, &name);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, MustGetBoolToken, MustGetBoolToken)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
MustGetBoolToken(self);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, Close, Close)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
Close(self);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(DScriptScanner, SetNoFatalErrors, SetNoFatalErrors)
{
PARAM_SELF_PROLOGUE(DScriptScanner);
PARAM_BOOL(cmode);
SetNoFatalErrors(self, cmode);
return 0;
}
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Line, Line);
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Float, Float);
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Number, Number);
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.End, End);
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Crossed, Crossed);
DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.ParseError, ParseError);

View file

@ -257,21 +257,21 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy,
step_y = pstep_y;
break;
case 1: // rotate 90° right
case 1: // rotate 90° right
pixxoffset = 0;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
step_y = pstep_x;
break;
case 2: // rotate 180°
case 2: // rotate 180°
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_x;
step_y = -pstep_y;
break;
case 3: // rotate 90° left
case 3: // rotate 90° left
pixxoffset = srcwidth - 1;
pixyoffset = 0;
step_x = pstep_y;
@ -285,7 +285,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy,
step_y = pstep_y;
break;
case 5: // flip horizontally and rotate 90° right
case 5: // flip horizontally and rotate 90° right
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
@ -299,7 +299,7 @@ bool ClipCopyPixelRect(const FClipRect *cr, int &originx, int &originy,
step_y = -pstep_y;
break;
case 7: // flip horizontally and rotate 90° left
case 7: // flip horizontally and rotate 90° left
pixxoffset = 0;
pixyoffset = 0;
step_x = pstep_y;

View file

@ -108,7 +108,7 @@ public:
FBitmap(const FBitmap &other) = delete; // disallow because in nearly all cases this creates an unwanted copy.
FBitmap(FBitmap &&other)
FBitmap(FBitmap &&other) noexcept
{
data = other.data;
Pitch = other.Pitch;
@ -122,7 +122,7 @@ public:
FBitmap &operator=(const FBitmap &other) = delete; // disallow because in nearly all cases this creates an unwanted copy. Use Copy instead.
FBitmap &operator=(FBitmap &&other)
FBitmap &operator=(FBitmap &&other) noexcept
{
if (data != nullptr && FreeBuffer) delete[] data;
data = other.data;

View file

@ -106,10 +106,10 @@ FAnmTexture::FAnmTexture (int lumpnum, int w, int h)
void FAnmTexture::ReadFrame(uint8_t *pixels, uint8_t *palette)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
std::unique_ptr<anim_t> anim = std::make_unique<anim_t>(); // note that this struct is very large and should not go onto the stack!
if (ANIM_LoadAnim(anim.get(), source, (int)lump.GetSize()) >= 0)
if (ANIM_LoadAnim(anim.get(), source, (int)lump.size()) >= 0)
{
int numframes = ANIM_NumFrames(anim.get());
if (numframes >= 1)

View file

@ -93,7 +93,7 @@ PalettedPixels FAutomapTexture::CreatePalettedPixels(int conversion, int frame)
{
int x, y;
auto data = fileSystem.ReadFile (SourceLump);
auto indata = data.GetBytes();
auto indata = data.bytes();
PalettedPixels Pixels(Width * Height);

View file

@ -74,10 +74,9 @@ FImageSource *FlatImage_TryCreate(FileReader & file, int lumpnum)
FFlatTexture::FFlatTexture (int lumpnum)
: FImageSource(lumpnum)
{
int area;
int bits;
area = fileSystem.FileLength (lumpnum);
auto area = fileSystem.FileLength (lumpnum);
switch (area)
{

View file

@ -121,7 +121,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1
PalettedPixels FIMGZTexture::CreatePalettedPixels(int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto imgz = (const ImageHeader *)lump.GetMem();
auto imgz = (const ImageHeader *)lump.data();
const uint8_t *data = (const uint8_t *)&imgz[1];
uint8_t *dest_p;

View file

@ -186,7 +186,7 @@ PalettedPixels FPatchTexture::CreatePalettedPixels(int conversion, int frame)
int x;
auto lump = fileSystem.ReadFile (SourceLump);
const patch_t *patch = (const patch_t *)lump.GetMem();
const patch_t *patch = (const patch_t *)lump.data();
maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.FileLength (SourceLump) - 3);
@ -296,7 +296,7 @@ void FPatchTexture::DetectBadPatches ()
// It must be 256 pixels tall, and all its columns must have exactly
// one post, where each post has a supposed length of 0.
auto lump = fileSystem.ReadFile (SourceLump);
const patch_t *realpatch = (patch_t *)lump.GetMem();
const patch_t *realpatch = (patch_t *)lump.data();
const uint32_t *cofs = realpatch->columnofs;
int x, x2 = LittleShort(realpatch->width);

View file

@ -141,14 +141,14 @@ int FQOITexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
constexpr auto QOI_COLOR_HASH = [](PalEntry C) { return (C.r * 3 + C.g * 5 + C.b * 7 + C.a * 11); };
auto lump = fileSystem.ReadFile(SourceLump);
if (lump.GetSize() < 22) return 0; // error
if (lump.size() < 22) return 0; // error
PalEntry index[64] = {};
PalEntry pe = 0xff000000;
size_t p = 14, run = 0;
size_t chunks_len = lump.GetSize() - 8;
auto bytes = lump.GetBytes();
size_t chunks_len = lump.size() - 8;
auto bytes = lump.bytes();
for (int h = 0; h < Height; h++)
{

View file

@ -183,7 +183,7 @@ FRawPageTexture::FRawPageTexture (int lumpnum)
PalettedPixels FRawPageTexture::CreatePalettedPixels(int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
const uint8_t *source_p = source;
uint8_t *dest_p;
@ -216,8 +216,8 @@ int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{
auto lump = fileSystem.ReadFile(SourceLump);
auto plump = fileSystem.ReadFile(mPaletteLump);
auto source = lump.GetBytes();
auto psource = plump.GetBytes();
auto source = lump.bytes();
auto psource = plump.bytes();
PalEntry paldata[256];
for (auto & pe : paldata)
{

View file

@ -165,7 +165,7 @@ FStartupTexture::FStartupTexture (int lumpnum)
bUseGamePalette = false;
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
// Initialize the bitmap palette.
// the palette is static so that the notches can share it.
@ -234,7 +234,7 @@ void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int
PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
@ -254,7 +254,7 @@ PalettedPixels FStartupTexture::CreatePalettedPixels(int conversion, int frame)
int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height);
return 0;
}
@ -282,7 +282,7 @@ FNotchTexture::FNotchTexture (int lumpnum, int width, int height)
PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
TArray<uint8_t> Work(Width*Height, true);
@ -305,7 +305,7 @@ PalettedPixels FNotchTexture::CreatePalettedPixels(int conversion, int frame)
int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
auto Work = (uint32_t*)bmp->GetPixels();
for(int i = 0; i < Width * Height / 2; i++)
@ -339,7 +339,7 @@ FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h)
PalettedPixels FStrifeStartupTexture::CreatePalettedPixels(int conversion, int frame)
{
auto lump = fileSystem.ReadFile (SourceLump);
auto source = lump.GetBytes();
auto source = lump.bytes();
PalettedPixels Pixels(Width*Height);
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source, Width, Height, Width, remap);

View file

@ -142,7 +142,7 @@ int FWebPTexture::CopyPixels(FBitmap *bmp, int conversion, int frame)
config.output.u.RGBA.stride = bmp->GetPitch();
config.output.is_external_memory = 1;
(void)WebPDecode(bytes.GetBytes(), bytes.GetSize(), &config);
(void)WebPDecode(bytes.bytes(), bytes.size(), &config);
return 0;
}

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