the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 156 lines 8.3 kB view raw
1#pragma once 2 3#include <stdint.h> 4 5#include "SparseLightStorage_SPU.h" 6#include "SparseDataStorage_SPU.h" 7 8#ifndef SN_TARGET_PS3_SPU 9#include "..\..\..\stdafx.h" 10#include "..\..\..\..\Minecraft.World\Region.h" 11#endif // SN_TARGET_PS3_SPU 12 13//#include "xmcore.h" 14 15// This class is used for the compressed storage of tile data. Unlike the SparseLightingStorage class, data is split into 512 blocks of 4x4x4 tiles. Then within each block, the 16// data is compressed as described below, with a selection of bits per tile available, in a method similar to a palettised image. 17 18// There are two elements to the storage... an index array (fixed size), and the actual storage required... 19 20// The index: 21// (1) Each index takes up 2 bytes, one for each 4x4x4 block ie 512 X 2 = 1024 bytes in total 22// (2) The type of index is determined by the least significant 2 bits, the other 14 bits represent an offset for the data, stored divided by 2 23// 0 - the data for this block is represented at 1 bit per tile. Data pointed to is 2 bytes describing the 2 possible tiles stored in this block, followed by 32 bytes of data (total 34 bytes) 24// 1 - the data for this block is represented at 2 bit per tile. Data pointed to is 4 bytes describing the 4 possible tiles stored in this block, followed by 64 bytes of data (total 68 bytes) 25// 2 - the data for this block is represented at 4 bit per tile. Data pointed to is 16 bytes describing the 16 possible tiles stored in this block, followed by 128 bytes of data (total 144 bytes) 26// 3 - if bit 2 is 0, then this block is represented at 8 bits per tile. Data pointed to is 64 bytes, offset must be a multiple of 4 (since bit 2 can also be thought of as being 27// the low bit of the offset (divided by 2 as in the other cases), and is zero) 28// - if bit 2 is 1, then this block is represented at 0 bits per tile. The upper 8 bits of the index store the tile value that is used by the entire block. 29// So: 30// oooooooooooooo00 - 1 bit per tile, offset oooooooooooooo0 31// oooooooooooooo01 - 2 bits per tile, offset oooooooooooooo0 32// oooooooooooooo10 - 4 bits per tile, offset oooooooooooooo0 33// ooooooooooooo011 - 8 bits per tile, offset ooooooooooooo00 34// tttttttt-----111 - 0 bits per tile - tile is tttttttt 35 36// Some notes on the logic of all of this... 37// (1) Large numbers of blocks in the world really don't need to be stored at a full 8 bits per tile. 38// In a worst-case scenario, all planes would be 256 bytes and we'd have to store offsets of up to 32704 ( 64 x 511). This would require 15 bits per offset to store, but since in all cases 39// the data can be stored with a 2 byte alignment, we can store offsets divided by 2, freeing up 2 bits to store the type of index for each plane. This allows us to encode 4 types, but we really have 40// 5 types (0, 1, 2, 4 or 8 bits per tile). Since the 8-bit per tile planes are likely to be very rare, we can free up an extra bit in those by making their offset 4-byte aligned, and 41// then use the extra bit to determine whether its a 0 or 8-bit per tile index. In the 0 bit case, we can use the bits used for the offset to store the actual tile value represented throughout the plane. 42// (2) The compression is done per 4x4x4 block rather than planes like the lighting, as that gives many more regions that have a small number of tile types than per plane, and can therefore 43// be compressed using less bits per tile. This is at the expense of a larger index, and more overhead from storing the tile types in each block (since there are more blocks than planes). However 44// on balance this still was found to give much better compression - around 12.5% vs 19% by doing things per plane. 45// (3) Another compromise is being made on how the memory is allocated. This is all currently done with physical allocations to bypass the general heap manager, in particular to allow the freeing 46// of memory to actually free whole memory pages cleanly rather than leaving them as managed by the heap manager. The downside to this is that all storage is done in whole 4K pages. Annoyingly, 47// a lot of our compressed chunks are just on the edge of fitting in 4K, so an awful lot of them end up being 8K when they are just a small amount over. However, in testing absolutely no chunks 48// were seen that got close to going over 8K compressed, so doing things this way then we at least know that we are reliably getting 25% compression, and freeing things up cleanly. 49// Note: see the comments on the getIndex and getBlockAndTile for an explanation of how the blocks themselves are organised in terms of mapping a chunk-wide x/y/z into a block and tile index. 50 51//#define BLOCK_COMPRESSION_STATS 52class CompressedTileStorage_SPU 53{ 54private: 55 unsigned char *indicesAndData; 56public: 57 int allocatedSize; 58private: 59 60 static const int INDEX_OFFSET_MASK = 0x7ffe; 61 static const int INDEX_OFFSET_SHIFT = 1; 62 static const int INDEX_TILE_MASK = 0x00ff; 63 static const int INDEX_TILE_SHIFT = 8; 64 static const int INDEX_TYPE_MASK = 0x0003; 65 static const int INDEX_TYPE_1_BIT = 0x0000; 66 static const int INDEX_TYPE_2_BIT = 0x0001; 67 static const int INDEX_TYPE_4_BIT = 0x0002; 68 static const int INDEX_TYPE_0_OR_8_BIT = 0x0003; 69 static const int INDEX_TYPE_0_BIT_FLAG = 0x0004; 70 71 static const unsigned int MM_PHYSICAL_4KB_BASE = 0xE0000000; // Start of where 4KB page sized physical allocations are made 72public: 73 CompressedTileStorage_SPU(unsigned char* data); 74 ~CompressedTileStorage_SPU(); 75private: 76 inline static int getIndex(int block, int tile); 77 inline static void getBlockAndTile(int *block, int *tile, int x, int y, int z); 78public: 79 unsigned char* getDataPtr() { return indicesAndData; } 80 int get(int x, int y, int z); // Get an individual tile value 81}; 82 83class TileCompressData_SPU 84{ 85 static const int sc_size = 20; 86 87public: 88 int m_x0; 89 int m_y0; 90 int m_z0; 91 void* m_lowerBlocks[9]; 92 int m_lowerBlocksSize[9]; 93 void* m_upperBlocks[9]; 94 int m_upperBlocksSize[9]; 95 96 int64_t m_lowerSkyLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 97 int64_t m_lowerBlockLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 98 int64_t m_upperSkyLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 99 int64_t m_upperBlockLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 100 101 int64_t m_lowerData[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 102 int64_t m_upperData[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 103 104#ifdef SN_TARGET_PS3_SPU 105 void* m_pRegion; 106 107 void uncompress(uint32_t eaOutData); 108 109 void uncompressTiles(int x0, int z0, int x1, int z1, bool upper); 110 void clearTiles(int x0, int z0, int x1, int z1, bool upper); 111 112 void uncompressLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight); 113 void clearLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight); 114 115 void uncompressData(int x0, int z0, int x1, int z1, bool upper); 116 void clearData(int x0, int z0, int x1, int z1, bool upper); 117 118 void dmaSparseStorage(int64_t dataAndSize, unsigned char* pDest); 119 120 void loadAndUncompressLowerSection(int block, int x0, int z0, int x1, int z1); 121 void loadAndUncompressUpperSection(int block, int x0, int z0, int x1, int z1); 122 123 bool validY(int yVal, bool upper) 124 { 125 if(upper) 126 { 127 if(yVal >= 128) return true; 128 } 129 else 130 { 131 if(yVal <= 127) return true; 132 } 133 return false; 134 } 135 136 class OutputData 137 { 138 public: 139 unsigned char m_tileIds[sc_size*sc_size*sc_size]; // byte 140 unsigned char m_brightness[sc_size*sc_size*sc_size]; // 2x 4bit 141 unsigned char m_data_flags[sc_size*sc_size*sc_size]; // 2x 4bit 142 }; 143 144 static OutputData m_OutputData; 145 static CompressedTileStorage_SPU* m_pTileStorage; 146 static SparseLightStorage_SPU* m_pLightStorage; 147 static SparseDataStorage_SPU* m_pDataStorage; 148#else 149 Region* m_pRegion; 150 151 void setForChunk( Region* region, int x0, int y0, int z0 ); 152#endif // SN_TARGET_PS3_SPU 153 154 int padding[3]; 155 156};