Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions Source/levels/gendung.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,11 @@ void SetDungeonMicros()
uint16_t *pieces = &levelPieces[blocks * levelPieceId];
for (uint32_t block = 0; block < blocks; block++) {
const LevelCelBlock levelCelBlock { SDL_SwapLE16(pieces[blocks - 2 + (block & 1) - (block & 0xE)]) };
LevelCelBlock &mt = DPieceMicros[levelPieceId].mt[block];
mt = levelCelBlock;
DPieceMicros[levelPieceId].mt[block] = levelCelBlock;
if (levelCelBlock.hasValue()) {
if (const auto it = frameToTypeMap.find(levelCelBlock.frame()); it == frameToTypeMap.end()) {
frameToTypeMap.emplace_hint(it, levelCelBlock.frame(),
DunFrameInfo { static_cast<uint8_t>(block), levelCelBlock.type(), SOLData[levelPieceId], &mt.data });
DunFrameInfo { static_cast<uint8_t>(block), levelCelBlock.type(), SOLData[levelPieceId] });
}
}
}
Expand All @@ -539,7 +538,21 @@ void SetDungeonMicros()
return a.first < b.first;
});
ReencodeDungeonCels(pDungeonCels, frameToTypeList);
ReindexCelBlocks(frameToTypeList);

std::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments = ComputeCelBlockAdjustments(frameToTypeList);
if (celBlockAdjustments.size() == 0) return;
for (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) {
for (uint32_t block = 0; block < blocks; block++) {
LevelCelBlock &levelCelBlock = DPieceMicros[levelPieceId].mt[block];
const uint16_t frame = levelCelBlock.frame();
const auto pair = std::make_pair(frame, frame);
const auto it = std::upper_bound(celBlockAdjustments.begin(), celBlockAdjustments.end(), pair,
[](std::pair<uint16_t, uint16_t> p1, std::pair<uint16_t, uint16_t> p2) { return p1.first < p2.first; });
if (it != celBlockAdjustments.end()) {
levelCelBlock.data -= it->second;
}
}
}
}

void DRLG_InitTrans()
Expand Down
14 changes: 11 additions & 3 deletions Source/levels/reencode_dun_cels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <memory>
#include <span>
#include <utility>
#include <vector>

#include <SDL_endian.h>

Expand Down Expand Up @@ -301,15 +303,21 @@ void ReencodeDungeonCels(std::unique_ptr<std::byte[]> &dungeonCels, std::span<st
dungeonCels = std::move(result);
}

void ReindexCelBlocks(std::span<std::pair<uint16_t, DunFrameInfo>> frames)
std::vector<std::pair<uint16_t, uint16_t>> ComputeCelBlockAdjustments(std::span<std::pair<uint16_t, DunFrameInfo>> frames)
{
std::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments;
uint16_t lastFrameIndex = 0;
uint16_t adjustment = 0;
for (auto &[frame, info] : frames) {
adjustment += frame - lastFrameIndex - 1;
uint16_t diff = frame - lastFrameIndex - 1;
if (diff > 0) celBlockAdjustments.emplace_back(frame, adjustment);
adjustment += diff;
lastFrameIndex = frame;
*info.celBlockData -= adjustment;
}
if (adjustment > 0) {
celBlockAdjustments.emplace_back(std::numeric_limits<uint16_t>::max(), adjustment);
}
return celBlockAdjustments;
}

} // namespace devilution
7 changes: 3 additions & 4 deletions Source/levels/reencode_dun_cels.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>
#include <span>
#include <utility>
#include <vector>

#include "levels/dun_tile.hpp"

Expand All @@ -17,8 +18,6 @@ struct DunFrameInfo {
TileType type;
TileProperties properties;

uint16_t *celBlockData;

[[nodiscard]] bool isFloor() const
{
// The BlockMissile check is for stairs in L3 and L4, e.g. tile 46 sub-tile 141 frame 386 in L4.
Expand All @@ -39,11 +38,11 @@ struct DunFrameInfo {
void ReencodeDungeonCels(std::unique_ptr<std::byte[]> &dungeonCels, std::span<std::pair<uint16_t, DunFrameInfo>> frames);

/**
* @brief Adjusts frame indexes in cel block data.
* @brief Computes adjustments to apply to frame indexes in cel block data.
*
* Re-encoding the dungeon cels removes frames that are not referenced.
* Indexes must also be adjusted to avoid errors when doing lookups.
*/
void ReindexCelBlocks(std::span<std::pair<uint16_t, DunFrameInfo>> frames);
std::vector<std::pair<uint16_t, uint16_t>> ComputeCelBlockAdjustments(std::span<std::pair<uint16_t, DunFrameInfo>> frames);

} // namespace devilution
Loading