Skip to content

Commit 09f24ae

Browse files
StephenCWillsAJenbo
authored andcommitted
Reindex all level cel blocks
1 parent 729c794 commit 09f24ae

File tree

3 files changed

+31
-11
lines changed

3 files changed

+31
-11
lines changed

Source/levels/gendung.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,12 +524,11 @@ void SetDungeonMicros()
524524
uint16_t *pieces = &levelPieces[blocks * levelPieceId];
525525
for (uint32_t block = 0; block < blocks; block++) {
526526
const LevelCelBlock levelCelBlock { SDL_SwapLE16(pieces[blocks - 2 + (block & 1) - (block & 0xE)]) };
527-
LevelCelBlock &mt = DPieceMicros[levelPieceId].mt[block];
528-
mt = levelCelBlock;
527+
DPieceMicros[levelPieceId].mt[block] = levelCelBlock;
529528
if (levelCelBlock.hasValue()) {
530529
if (const auto it = frameToTypeMap.find(levelCelBlock.frame()); it == frameToTypeMap.end()) {
531530
frameToTypeMap.emplace_hint(it, levelCelBlock.frame(),
532-
DunFrameInfo { static_cast<uint8_t>(block), levelCelBlock.type(), SOLData[levelPieceId], &mt.data });
531+
DunFrameInfo { static_cast<uint8_t>(block), levelCelBlock.type(), SOLData[levelPieceId] });
533532
}
534533
}
535534
}
@@ -539,7 +538,21 @@ void SetDungeonMicros()
539538
return a.first < b.first;
540539
});
541540
ReencodeDungeonCels(pDungeonCels, frameToTypeList);
542-
ReindexCelBlocks(frameToTypeList);
541+
542+
std::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments = ComputeCelBlockAdjustments(frameToTypeList);
543+
if (celBlockAdjustments.size() == 0) return;
544+
for (size_t levelPieceId = 0; levelPieceId < tileCount / blocks; levelPieceId++) {
545+
for (uint32_t block = 0; block < blocks; block++) {
546+
LevelCelBlock &levelCelBlock = DPieceMicros[levelPieceId].mt[block];
547+
const uint16_t frame = levelCelBlock.frame();
548+
const auto pair = std::make_pair(frame, frame);
549+
const auto it = std::upper_bound(celBlockAdjustments.begin(), celBlockAdjustments.end(), pair,
550+
[](std::pair<uint16_t, uint16_t> p1, std::pair<uint16_t, uint16_t> p2) { return p1.first < p2.first; });
551+
if (it != celBlockAdjustments.end()) {
552+
levelCelBlock.data -= it->second;
553+
}
554+
}
555+
}
543556
}
544557

545558
void DRLG_InitTrans()

Source/levels/reencode_dun_cels.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
#include <cstddef>
44
#include <cstdint>
55
#include <cstring>
6+
#include <limits>
67
#include <memory>
78
#include <span>
89
#include <utility>
10+
#include <vector>
911

1012
#include <SDL_endian.h>
1113

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

304-
void ReindexCelBlocks(std::span<std::pair<uint16_t, DunFrameInfo>> frames)
306+
std::vector<std::pair<uint16_t, uint16_t>> ComputeCelBlockAdjustments(std::span<std::pair<uint16_t, DunFrameInfo>> frames)
305307
{
308+
std::vector<std::pair<uint16_t, uint16_t>> celBlockAdjustments;
306309
uint16_t lastFrameIndex = 0;
307310
uint16_t adjustment = 0;
308311
for (auto &[frame, info] : frames) {
309-
adjustment += frame - lastFrameIndex - 1;
312+
uint16_t diff = frame - lastFrameIndex - 1;
313+
if (diff > 0) celBlockAdjustments.emplace_back(frame, adjustment);
314+
adjustment += diff;
310315
lastFrameIndex = frame;
311-
*info.celBlockData -= adjustment;
312316
}
317+
if (adjustment > 0) {
318+
celBlockAdjustments.emplace_back(std::numeric_limits<uint16_t>::max(), adjustment);
319+
}
320+
return celBlockAdjustments;
313321
}
314322

315323
} // namespace devilution

Source/levels/reencode_dun_cels.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <memory>
66
#include <span>
77
#include <utility>
8+
#include <vector>
89

910
#include "levels/dun_tile.hpp"
1011

@@ -17,8 +18,6 @@ struct DunFrameInfo {
1718
TileType type;
1819
TileProperties properties;
1920

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

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

4948
} // namespace devilution

0 commit comments

Comments
 (0)