Allow cell overflow in block data (pre-1.16 style)
This commit is contained in:
parent
b218552cc4
commit
e7d18f7dff
|
@ -6,7 +6,8 @@
|
|||
|
||||
namespace Feather
|
||||
{
|
||||
// A container that maps values from a local palette to a
|
||||
// A container that maps values from a local palette to a global palette
|
||||
// Implemented like Minecraft's BitStorage in 1.15.2 (with cell overflow)
|
||||
template <typename T, uint MaxSize, uint MaxBits>
|
||||
struct PalettedContainer
|
||||
{
|
||||
|
@ -25,7 +26,6 @@ namespace Feather
|
|||
uint size = MaxSize;
|
||||
uint8 bits = MaxBits;
|
||||
uint64 mask = 0;
|
||||
uint valuesPerCell = 0;
|
||||
|
||||
public:
|
||||
PalettedContainer(uint size, uint8 bits) : size(size), data() { SetBits(bits); }
|
||||
|
@ -33,43 +33,51 @@ namespace Feather
|
|||
inline void SetBits(uint8 nbits)
|
||||
{
|
||||
bits = nbits;
|
||||
mask = (1 << bits) - 1;
|
||||
valuesPerCell = BITS_PER_CELL / bits;
|
||||
|
||||
Log::Debug("PalettedContainer::SetBits: {}, mask = {:#b}, valuesPerCell = {}", bits, mask, valuesPerCell);
|
||||
mask = (1UL << bits) - 1UL;
|
||||
}
|
||||
|
||||
// TODO: optimize all math here
|
||||
|
||||
inline int CellIndex(int index)
|
||||
{
|
||||
return index / valuesPerCell;
|
||||
}
|
||||
|
||||
// Update value, returns previous value
|
||||
// TODO: change from uint to const T&
|
||||
inline uint GetAndSet(int index, uint value)
|
||||
{
|
||||
// Note: Java >> is signed, while >>> is used for zero-fill shift.
|
||||
// Usage of signed >> instead of >>> has been marked.
|
||||
|
||||
// Bit # we want to read from
|
||||
int bitIndex = index * bits;
|
||||
|
||||
// Cell index
|
||||
uint cell = bitIndex >> 6; // java signed >>
|
||||
// Next cell, if bits overflow
|
||||
uint next = ((index + 1) * bits - 1) >> 6; // java signed >>
|
||||
|
||||
uint shift = bitIndex ^ cell << 6;
|
||||
|
||||
auto [d, lock] = data.borrow();
|
||||
|
||||
// read previous value
|
||||
uint64 cellValue = d[cell];
|
||||
uint prev = (uint)(d[cell] >> shift & mask);
|
||||
|
||||
int id = value; // palette.GetID(value);
|
||||
int cellIndex = CellIndex(index);
|
||||
uint64 shift = (index - cellIndex * valuesPerCell) * bits;//(index % valuesPerCell) * bits;
|
||||
d[cell] &= ~(mask << shift); // clear target bits
|
||||
d[cell] |= ((uint64)value & mask) << shift; // set target bits
|
||||
|
||||
Log::Debug("PalettedContainer::GetAndSet: index {} -> cell {}, [{}:{}]", index, cellIndex, shift, shift + bits);
|
||||
// Bits overflow into next cell
|
||||
if (next != cell)
|
||||
{
|
||||
uint shift1 = BITS_PER_CELL - shift;
|
||||
uint shift2 = bits - shift1;
|
||||
|
||||
uint64 cell = d[cellIndex];
|
||||
int prev = (cell >> shift) & mask;
|
||||
uint64 nextValue = d[next];
|
||||
|
||||
//d[cellIndex] = ((cell & (mask << shift ^ 0xFFFFFFFFFFFFFFFFL)) | (uint64(id) & mask)) << shift;
|
||||
prev |= (uint)(d[next] << shift1 & mask);
|
||||
// TODO: not 100% on the math here
|
||||
d[next] = d[next] >> shift2 << shift2 | ((uint64)value & mask) >> shift1; // last shift is java signed >>
|
||||
}
|
||||
|
||||
d[cellIndex] &= ~(mask << shift); // clear target bits
|
||||
d[cellIndex] |= ((uint64)id & mask) << shift; // set target bits
|
||||
|
||||
//Log::Debug("Changed from {:#b} to {:#b}", cell, d[cellIndex]);
|
||||
Log::Debug("Changed from {} (g: {}) to {} (g: {})", prev, palette.ByID(prev), value, palette.ByID(value));
|
||||
|
||||
return (uint)prev; // palette.ByID(prev);
|
||||
return prev;
|
||||
}
|
||||
|
||||
inline constexpr size_t GetNumLongs() { return NUM_LONGS; }
|
||||
|
|
Loading…
Reference in New Issue