the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 150 lines 7.9 kB view raw
1#pragma once 2 3#include <stdint.h> 4 5 6#ifndef SN_TARGET_PS3_SPU 7#include "..\..\..\stdafx.h" 8#include "..\..\..\..\Minecraft.World\Region.h" 9#endif // SN_TARGET_PS3_SPU 10 11//#include "xmcore.h" 12 13// 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 14// data is compressed as described below, with a selection of bits per tile available, in a method similar to a palettised image. 15 16// There are two elements to the storage... an index array (fixed size), and the actual storage required... 17 18// The index: 19// (1) Each index takes up 2 bytes, one for each 4x4x4 block ie 512 X 2 = 1024 bytes in total 20// (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 21// 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) 22// 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) 23// 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) 24// 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 25// the low bit of the offset (divided by 2 as in the other cases), and is zero) 26// - 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. 27// So: 28// oooooooooooooo00 - 1 bit per tile, offset oooooooooooooo0 29// oooooooooooooo01 - 2 bits per tile, offset oooooooooooooo0 30// oooooooooooooo10 - 4 bits per tile, offset oooooooooooooo0 31// ooooooooooooo011 - 8 bits per tile, offset ooooooooooooo00 32// tttttttt-----111 - 0 bits per tile - tile is tttttttt 33 34// Some notes on the logic of all of this... 35// (1) Large numbers of blocks in the world really don't need to be stored at a full 8 bits per tile. 36// 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 37// 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 38// 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 39// 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. 40// (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 41// 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 42// on balance this still was found to give much better compression - around 12.5% vs 19% by doing things per plane. 43// (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 44// 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, 45// 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 46// 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. 47// 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. 48 49//#define BLOCK_COMPRESSION_STATS 50class CompressedTileStorage_SPU 51{ 52private: 53 unsigned char *indicesAndData; 54public: 55 int allocatedSize; 56private: 57 58 static const int INDEX_OFFSET_MASK = 0x7ffe; 59 static const int INDEX_OFFSET_SHIFT = 1; 60 static const int INDEX_TILE_MASK = 0x00ff; 61 static const int INDEX_TILE_SHIFT = 8; 62 static const int INDEX_TYPE_MASK = 0x0003; 63 static const int INDEX_TYPE_1_BIT = 0x0000; 64 static const int INDEX_TYPE_2_BIT = 0x0001; 65 static const int INDEX_TYPE_4_BIT = 0x0002; 66 static const int INDEX_TYPE_0_OR_8_BIT = 0x0003; 67 static const int INDEX_TYPE_0_BIT_FLAG = 0x0004; 68 69 static const unsigned int MM_PHYSICAL_4KB_BASE = 0xE0000000; // Start of where 4KB page sized physical allocations are made 70public: 71 CompressedTileStorage_SPU(unsigned char* data); 72 ~CompressedTileStorage_SPU(); 73private: 74 inline static int getIndex(int block, int tile); 75 inline static void getBlockAndTile(int *block, int *tile, int x, int y, int z); 76public: 77 unsigned char* getDataPtr() { return indicesAndData; } 78 int get(int x, int y, int z); // Get an individual tile value 79}; 80 81class TileCompressData_SPU 82{ 83 static const int sc_size = 20; 84 85public: 86 int m_x0; 87 int m_y0; 88 int m_z0; 89 void* m_lowerBlocks[9]; 90 int m_lowerBlocksSize[9]; 91 void* m_upperBlocks[9]; 92 int m_upperBlocksSize[9]; 93 94 int64_t m_lowerSkyLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 95 int64_t m_lowerBlockLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 96 int64_t m_upperSkyLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 97 int64_t m_upperBlockLight[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 98 99 int64_t m_lowerData[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 100 int64_t m_upperData[9]; // Contains packed-together data pointer (lower 32-bits), and count of lines used (upper 32-bits) 101 102#ifdef SN_TARGET_PS3_SPU 103 void* m_pRegion; 104 105 void uncompress(uint32_t eaOutData); 106 107 void uncompressTiles(int x0, int z0, int x1, int z1, bool upper); 108 void clearTiles(int x0, int z0, int x1, int z1, bool upper); 109 110 void uncompressLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight); 111 void clearLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight); 112 113 void uncompressData(int x0, int z0, int x1, int z1, bool upper); 114 void clearData(int x0, int z0, int x1, int z1, bool upper); 115 116 void dmaSparseStorage(int64_t dataAndSize, unsigned char* pDest); 117 118 void loadAndUncompressLowerSection(int block, int x0, int z0, int x1, int z1); 119 void loadAndUncompressUpperSection(int block, int x0, int z0, int x1, int z1); 120 121 bool validY(int yVal, bool upper) 122 { 123 if(upper) 124 { 125 if(yVal >= 128) return true; 126 } 127 else 128 { 129 if(yVal <= 127) return true; 130 } 131 return false; 132 } 133 134 class OutputData 135 { 136 public: 137 unsigned char m_tileIds[16*16*256]; // byte 138 }; 139 140 static OutputData m_OutputData; 141 static CompressedTileStorage_SPU* m_pTileStorage; 142#else 143 Region* m_pRegion; 144 145 void setForChunk( Region* region, int x0, int y0, int z0 ); 146#endif // SN_TARGET_PS3_SPU 147 148 int padding[3]; 149 150};