Merge remote-tracking branch 'gzdoom/master'
This commit is contained in:
commit
805bce1166
214 changed files with 10327 additions and 6393 deletions
|
|
@ -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" )
|
||||
|
|
|
|||
89
auto-setup-windows-arm.cmd
Normal file
89
auto-setup-windows-arm.cmd
Normal 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!
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public:
|
|||
|
||||
void Activate();
|
||||
|
||||
std::function<void(int)> OnChanged;
|
||||
std::function<void()> OnActivated;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ void ListView::SetSelectedItem(int index)
|
|||
if (selectedItem != index && index >= 0 && index < items.size())
|
||||
{
|
||||
selectedItem = index;
|
||||
if (OnChanged) OnChanged(selectedItem);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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{@]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "alc.h"
|
||||
#endif
|
||||
|
||||
#include "alext.h"
|
||||
#include "thirdparty/alext.h"
|
||||
|
||||
|
||||
class OpenALSoundStream;
|
||||
|
|
|
|||
287
src/common/audio/sound/thirdparty/alext.h
vendored
287
src/common/audio/sound/thirdparty/alext.h
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
63
src/common/filesystem/include/fs_decompress.h
Normal file
63
src/common/filesystem/include/fs_decompress.h
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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> ¤tTree);
|
||||
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> ¤tTree);
|
||||
int DecodeSF(std::vector<HuffNode> &decoder, int numvals);
|
||||
public:
|
||||
int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags);
|
||||
};
|
||||
|
|
|
|||
150
src/common/filesystem/source/critsec.cpp
Normal file
150
src/common/filesystem/source/critsec.cpp
Normal 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
|
||||
|
||||
}
|
||||
39
src/common/filesystem/source/critsec.h
Normal file
39
src/common/filesystem/source/critsec.h
Normal 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;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
109
src/common/filesystem/source/file_hog.cpp
Normal file
109
src/common/filesystem/source/file_hog.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
98
src/common/filesystem/source/file_mvl.cpp
Normal file
98
src/common/filesystem/source/file_mvl.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
1833
src/common/filesystem/source/wildcards.hpp
Normal file
1833
src/common/filesystem/source/wildcards.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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! ;)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1441,7 +1441,7 @@ public:
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxGlobalVariaböe
|
||||
// FxGlobalVariable
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -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 --------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue