diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index bd6ea5b79..cbd589980 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -101,7 +101,6 @@ set(libdevilutionx_SRCS engine/direction.cpp engine/dx.cpp engine/load_cel.cpp - engine/load_pcx_as_cel.cpp engine/load_pcx.cpp engine/palette.cpp engine/path.cpp @@ -161,7 +160,6 @@ set(libdevilutionx_SRCS utils/logged_fstream.cpp utils/paths.cpp utils/pcx.cpp - utils/pcx_to_cel.cpp utils/sdl_bilinear_scale.cpp utils/sdl_thread.cpp utils/utf8.cpp) diff --git a/Source/engine/load_pcx_as_cel.cpp b/Source/engine/load_pcx_as_cel.cpp deleted file mode 100644 index 9670fb971..000000000 --- a/Source/engine/load_pcx_as_cel.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "engine/load_pcx_as_cel.hpp" - -#include - -#include "engine/assets.hpp" -#include "utils/log.hpp" -#include "utils/pcx_to_cel.hpp" - -namespace devilution { - -std::optional LoadPcxAssetAsCel(const char *filename, unsigned numFrames, bool generateFrameHeaders, uint8_t transparentColorIndex) -{ - SDL_RWops *handle = OpenAsset(filename); - if (handle == nullptr) { - LogError("Missing file: {}", filename); - return std::nullopt; - } - return LoadPcxAsCel(handle, numFrames, generateFrameHeaders, transparentColorIndex); -} - -} // namespace devilution diff --git a/Source/engine/load_pcx_as_cel.hpp b/Source/engine/load_pcx_as_cel.hpp deleted file mode 100644 index a3ae221b6..000000000 --- a/Source/engine/load_pcx_as_cel.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -#include "engine/cel_sprite.hpp" -#include "utils/stdcompat/optional.hpp" - -namespace devilution { - -std::optional LoadPcxAssetAsCel(const char *filename, unsigned numFrames, bool generateFrameHeaders = false, uint8_t transparentColorIndex = 1); - -} // namespace devilution diff --git a/Source/utils/pcx_to_cel.cpp b/Source/utils/pcx_to_cel.cpp deleted file mode 100644 index 503982c99..000000000 --- a/Source/utils/pcx_to_cel.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "utils/pcx_to_cel.hpp" - -#include -#include -#include -#include -#include - -#include "appfat.h" -#include "utils/pcx.hpp" -#include "utils/stdcompat/cstddef.hpp" - -#ifdef USE_SDL1 -#include "utils/sdl2_to_1_2_backports.h" -#endif - -namespace devilution { - -namespace { - -void WriteLE32(uint8_t *out, uint32_t val) -{ - const uint32_t littleEndian = SDL_SwapLE32(val); - memcpy(out, &littleEndian, 4); -} - -void WriteLE16(uint8_t *out, uint16_t val) -{ - const uint16_t littleEndian = SDL_SwapLE16(val); - memcpy(out, &littleEndian, 2); -} - -void AppendCelTransparentRun(unsigned width, std::vector &out) -{ - while (width >= 128) { - out.push_back(0x80); - width -= 128; - } - if (width == 0) - return; - out.push_back(0xFF - (width - 1)); -} - -void AppendCelSolidRun(const uint8_t *src, unsigned width, std::vector &out) -{ - while (width >= 127) { - out.push_back(127); - for (size_t i = 0; i < 127; ++i) - out.push_back(src[i]); - width -= 127; - src += 127; - } - if (width == 0) - return; - out.push_back(width); - for (size_t i = 0; i < width; ++i) - out.push_back(src[i]); -} - -void AppendCelLine(const uint8_t *src, unsigned width, uint8_t transparentColorIndex, std::vector &out) -{ - unsigned runBegin = 0; - bool transparentRun = false; - for (unsigned i = 0; i < width; ++i) { - const uint8_t pixel = src[i]; - if (pixel == transparentColorIndex) { - if (transparentRun) - continue; - if (runBegin != i) - AppendCelSolidRun(src + runBegin, i - runBegin, out); - transparentRun = true; - runBegin = i; - } else if (transparentRun) { - AppendCelTransparentRun(i - runBegin, out); - transparentRun = false; - runBegin = i; - } - } - if (transparentRun) { - AppendCelTransparentRun(width - runBegin, out); - } else { - AppendCelSolidRun(src + runBegin, width - runBegin, out); - } -} - -} // namespace - -std::optional LoadPcxAsCel(SDL_RWops *handle, unsigned numFrames, bool generateFrameHeaders, uint8_t transparentColorIndex) -{ - int width; - int height; - uint8_t bpp; - if (!LoadPcxMeta(handle, width, height, bpp)) { - SDL_RWclose(handle); - return std::nullopt; - } - assert(bpp == 8); - - ptrdiff_t pixelDataSize = SDL_RWsize(handle); - if (pixelDataSize < 0) { - SDL_RWclose(handle); - return std::nullopt; - } - - pixelDataSize -= PcxHeaderSize; - - std::unique_ptr fileBuffer { new uint8_t[pixelDataSize] }; - if (SDL_RWread(handle, fileBuffer.get(), pixelDataSize, 1) == 0) { - SDL_RWclose(handle); - return std::nullopt; - } - - // CEL header: frame count, frame offset for each frame, file size - std::vector celData(4 * (2 + static_cast(numFrames))); - WriteLE32(&celData[0], numFrames); - - // We process the PCX a whole frame at a time because the lines are reversed in CEL. - const unsigned frameHeight = height / numFrames; - auto frameBuffer = std::unique_ptr(new uint8_t[static_cast(frameHeight) * width]); - - const unsigned srcSkip = width % 2; - uint8_t *dataPtr = fileBuffer.get(); - for (unsigned frame = 1; frame <= numFrames; ++frame) { - WriteLE32(&celData[4 * static_cast(frame)], static_cast(celData.size())); - - // Frame header: 5 16-bit offsets to 32-pixel height blocks. - const size_t frameHeaderPos = celData.size(); - if (generateFrameHeaders) { - constexpr size_t FrameHeaderSize = 10; - celData.resize(celData.size() + FrameHeaderSize); - WriteLE16(&celData[frameHeaderPos], FrameHeaderSize); - } - - for (unsigned j = 0; j < frameHeight; ++j) { - uint8_t *buffer = &frameBuffer[static_cast(j) * width]; - for (unsigned x = 0; x < static_cast(width);) { - constexpr uint8_t PcxMaxSinglePixel = 0xBF; - const uint8_t byte = *dataPtr++; - if (byte <= PcxMaxSinglePixel) { - *buffer++ = byte; - ++x; - continue; - } - constexpr uint8_t PcxRunLengthMask = 0x3F; - const uint8_t runLength = (byte & PcxRunLengthMask); - std::memset(buffer, *dataPtr++, runLength); - buffer += runLength; - x += runLength; - } - dataPtr += srcSkip; - } - - size_t line = frameHeight; - while (line-- != 0) { - AppendCelLine(&frameBuffer[line * width], width, transparentColorIndex, celData); - if (generateFrameHeaders) { - switch (line) { - case 32: - WriteLE16(&celData[frameHeaderPos + 2], static_cast(celData.size() - frameHeaderPos)); - break; - case 64: - WriteLE16(&celData[frameHeaderPos + 4], static_cast(celData.size() - frameHeaderPos)); - break; - case 96: - WriteLE16(&celData[frameHeaderPos + 6], static_cast(celData.size() - frameHeaderPos)); - break; - case 128: - WriteLE16(&celData[frameHeaderPos + 8], static_cast(celData.size() - frameHeaderPos)); - break; - } - } - } - } - WriteLE32(&celData[4 * (1 + static_cast(numFrames))], static_cast(celData.size())); - - SDL_RWclose(handle); - - auto out = std::unique_ptr(new byte[celData.size()]); - memcpy(&out[0], celData.data(), celData.size()); - return OwnedCelSpriteWithFrameHeight { - OwnedCelSprite { std::move(out), static_cast(width) }, - frameHeight - }; -} - -} // namespace devilution diff --git a/Source/utils/pcx_to_cel.hpp b/Source/utils/pcx_to_cel.hpp deleted file mode 100644 index a3528a4a3..000000000 --- a/Source/utils/pcx_to_cel.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include - -#include "engine/cel_sprite.hpp" -#include "utils/stdcompat/optional.hpp" - -namespace devilution { - -/** @brief Loads a PCX file as CEL. - * - * Assumes that the PCX file does not have a palette. - * - * @param handle A non-null SDL_RWops handle. Closed by this function. - * @param numFrames The number of vertically stacked frames in the PCX file. - * @param generateFrameHeaders Whether to generate frame headers in the CEL sprite. - * @param transparentColorIndex The PCX palette index of the transparent color. - */ -std::optional LoadPcxAsCel(SDL_RWops *handle, unsigned numFrames, bool generateFrameHeaders, - uint8_t transparentColorIndex = 1); - -} // namespace devilution