From 8a9618aea271cc1e4f3696486757311c4545339d Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 23 Jun 2021 01:13:30 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Clean=20up=20`cel=5Fheader?= =?UTF-8?q?.hpp`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Rename `CelGetFrameStart` to `CelGetFrame`, in line with the other 2 functions with the same name and load the `uint32_t` safely. 2. Remove redundant `FrameHeader`, simply use `LoadLE16`. 3. Document all the functions. --- Source/engine/cel_header.hpp | 58 +++++++++++++++++++----------------- Source/missiles.cpp | 2 +- Source/monster.cpp | 4 +-- Source/player.cpp | 2 +- Source/towners.cpp | 2 +- Source/utils/endian.hpp | 8 +++++ 6 files changed, 43 insertions(+), 33 deletions(-) diff --git a/Source/engine/cel_header.hpp b/Source/engine/cel_header.hpp index 9701655b4..9e8c0f899 100644 --- a/Source/engine/cel_header.hpp +++ b/Source/engine/cel_header.hpp @@ -10,46 +10,48 @@ namespace devilution { -inline byte *CelGetFrameStart(byte *pCelBuff, int nCel) +/** + * Returns the pointer to the start of the frame data (often a header). + */ +inline byte *CelGetFrame(byte *data, int frame) { - const auto *pFrameTable = reinterpret_cast(pCelBuff); - - return &pCelBuff[SDL_SwapLE32(pFrameTable[nCel])]; + const std::uint32_t begin = LoadLE32(&data[frame * sizeof(std::uint32_t)]); + return &data[begin]; } -inline byte *CelGetFrame(byte *pCelBuff, int nCel, int *nDataSize) +/** + * Returns the pointer to the start of the frame data (often a header) and sets `frameSize` to the size of the data in bytes. + */ +inline byte *CelGetFrame(byte *data, int frame, int *frameSize) { - const std::uint32_t nCellStart = LoadLE32(&pCelBuff[nCel * sizeof(std::uint32_t)]); - *nDataSize = static_cast(LoadLE32(&pCelBuff[(nCel + 1) * sizeof(std::uint32_t)]) - nCellStart); - return &pCelBuff[nCellStart]; + const std::uint32_t begin = LoadLE32(&data[frame * sizeof(std::uint32_t)]); + *frameSize = static_cast(LoadLE32(&data[(frame + 1) * sizeof(std::uint32_t)]) - begin); + return &data[begin]; } -inline const byte *CelGetFrame(const byte *pCelBuff, int nCel, int *nDataSize) +/** + * Returns the pointer to the start of the frame data (often a header) and sets `frameSize` to the size of the data in bytes. + */ +inline const byte *CelGetFrame(const byte *data, int frame, int *frameSize) { - const std::uint32_t nCellStart = LoadLE32(&pCelBuff[nCel * sizeof(std::uint32_t)]); - *nDataSize = static_cast(LoadLE32(&pCelBuff[(nCel + 1) * sizeof(std::uint32_t)]) - nCellStart); - return &pCelBuff[nCellStart]; + const std::uint32_t begin = LoadLE32(&data[frame * sizeof(std::uint32_t)]); + *frameSize = static_cast(LoadLE32(&data[(frame + 1) * sizeof(std::uint32_t)]) - begin); + return &data[begin]; } -struct FrameHeader { - uint16_t row0; - uint16_t row32; - uint16_t row64; - uint16_t row96; - uint16_t row128; -}; - -inline const byte *CelGetFrameClipped(const byte *pCelBuff, int nCel, int *nDataSize) +/** + * Returns the pointer to the start of the frame's pixel data and sets `frameSize` to the size of the data in bytes. + */ +inline const byte *CelGetFrameClipped(const byte *data, int frame, int *frameSize) { - const byte *pRLEBytes = CelGetFrame(pCelBuff, nCel, nDataSize); - - FrameHeader frameHeader; - std::memcpy(&frameHeader, pRLEBytes, sizeof(FrameHeader)); + const byte *frameData = CelGetFrame(data, frame, frameSize); - std::uint16_t nDataStart = SDL_SwapLE16(frameHeader.row0); - *nDataSize -= nDataStart; + // The frame begins with a header that consists of 5 little-endian 16-bit integers + // pointing to the start of the pixel data for rows 0, 32, 64, 96, and 128. + const std::uint16_t begin = LoadLE16(frameData); - return &pRLEBytes[nDataStart]; + *frameSize -= begin; + return &frameData[begin]; } } // namespace devilution diff --git a/Source/missiles.cpp b/Source/missiles.cpp index b2ca631ab..24fe48cd2 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1127,7 +1127,7 @@ void LoadMissileGFX(BYTE mi) sprintf(pszName, "Missiles\\%s.CL2", mfd->mName); byte *file = LoadFileInMem(pszName).release(); for (unsigned i = 0; i < mfd->mAnimFAmt; i++) - mfd->mAnimData[i] = CelGetFrameStart(file, i); + mfd->mAnimData[i] = CelGetFrame(file, i); } else if (mfd->mAnimFAmt == 1) { sprintf(pszName, "Missiles\\%s.CL2", mfd->mName); mfd->mAnimData[0] = LoadFileInMem(pszName).release(); diff --git a/Source/monster.cpp b/Source/monster.cpp index 4926889c8..c42c295e3 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -159,7 +159,7 @@ void InitMonsterTRN(CMonster &monst) for (int j = 0; j < 8; j++) { Cl2ApplyTrans( - CelGetFrameStart(monst.Anims[i].CMem.get(), j), + CelGetFrame(monst.Anims[i].CMem.get(), j), colorTranslations, monst.Anims[i].Frames); } @@ -359,7 +359,7 @@ void InitMonsterGFX(int monst) if (Monsters[monst].mtype != MT_GOLEM || (animletter[anim] != 's' && animletter[anim] != 'd')) { for (i = 0; i < 8; i++) { - byte *pCelStart = CelGetFrameStart(celBuf, i); + byte *pCelStart = CelGetFrame(celBuf, i); Monsters[monst].Anims[anim].CelSpritesForDirections[i].emplace(pCelStart, width); } } else { diff --git a/Source/player.cpp b/Source/player.cpp index d3ba19348..960e9a748 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -581,7 +581,7 @@ void SetPlayerGPtrs(const char *path, std::unique_ptr &data, std::array< data = LoadFileInMem(path); for (int i = 0; i < 8; i++) { - byte *pCelStart = CelGetFrameStart(data.get(), i); + byte *pCelStart = CelGetFrame(data.get(), i); anim[i].emplace(pCelStart, width); } } diff --git a/Source/towners.cpp b/Source/towners.cpp index 0c68f34be..9bcb7713e 100644 --- a/Source/towners.cpp +++ b/Source/towners.cpp @@ -238,7 +238,7 @@ void InitCows(TownerStruct &towner, const TownerInit &initData) towner.animOrder = nullptr; towner.animOrderSize = 0; for (int i = 0; i < 8; i++) { - towner._tNAnim[i] = CelGetFrameStart(CowCels.get(), i); + towner._tNAnim[i] = CelGetFrame(CowCels.get(), i); } NewTownerAnim(towner, towner._tNAnim[initData.dir], 12, 3); towner._tAnimFrame = GenerateRnd(11) + 1; diff --git a/Source/utils/endian.hpp b/Source/utils/endian.hpp index 51c740808..8e38d9ec1 100644 --- a/Source/utils/endian.hpp +++ b/Source/utils/endian.hpp @@ -4,6 +4,14 @@ namespace devilution { +template +constexpr std::uint16_t LoadLE16(const T *b) +{ + static_assert(sizeof(T) == 1, "invalid argument"); + // NOLINTNEXTLINE(readability-magic-numbers) + return (static_cast(b[1]) << 8) | static_cast(b[0]); +} + template constexpr std::uint32_t LoadLE32(const T *b) {