the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 480 lines 13 kB view raw
1include "stdafx.h" 2#include "CompressedTileStorage_SPU.h" 3#ifdef SN_TARGET_PS3_SPU 4#include "..\Common\DmaData.h" 5#else 6#include "..\..\..\..\Minecraft.World\Tile.h" 7#include "..\..\..\..\Minecraft.World\TilePos.h" 8#include "..\..\..\..\Minecraft.World\LevelChunk.h" 9#endif 10 11#include <stdlib.h> 12 13#ifdef SN_TARGET_PS3_SPU 14TileCompressData_SPU::OutputData TileCompressData_SPU::m_OutputData; 15CompressedTileStorage_SPU* TileCompressData_SPU::m_pTileStorage; 16#endif 17 18// Note: See header for an overview of this class 19 20// int CompressedTileStorage::deleteQueueIndex; 21// XLockFreeStack <unsigned char> CompressedTileStorage::deleteQueue[3]; 22// 23// CRITICAL_SECTION CompressedTileStorage::cs_write; 24 25CompressedTileStorage_SPU::CompressedTileStorage_SPU(unsigned char* data) 26{ 27 indicesAndData = data; 28 allocatedSize = 0; 29} 30 31 32CompressedTileStorage_SPU::~CompressedTileStorage_SPU() 33{ 34} 35 36// Get an index into the normal ordering of tiles for the java game, given a block index (0 to 511) and a tile index (0 to 63) 37inline int CompressedTileStorage_SPU::getIndex(int block, int tile) 38{ 39 // bits for index into data is: xxxxzzzzyyyyyyy 40 // we want block(b) & tile(t) spread out as: 41 // from: ______bbbbbbbbb 42 // to: bb__bb__bbbbb__ 43 // 44 // from: _________tttttt 45 // to: __tt__tt_____tt 46 47 int index = ( ( block & 0x180) << 6 ) | ( ( block & 0x060 ) << 4 ) | ( ( block & 0x01f ) << 2 ); 48 index |= ( ( tile & 0x30 ) << 7) | ( ( tile & 0x0c ) << 5 ) | ( tile & 0x03 ); 49 50 return index; 51} 52 53// Get the block and tile (reversing getIndex above) for a given x, y, z coordinate 54// 55// bits for index into data is: xxxxzzzzyyyyyyy 56// bbttbbttbbbbbtt 57// 58// so x is: ___________xxxx 59// and maps to this bit of b ______bb_______ 60// and this bit of t _________tt____ 61// 62// y is: ________yyyyyyy 63// and maps to this bit of b __________bbbbb 64// and this bit of t _____________tt 65// 66// and z is: ___________zzzz 67// and maps to this bit of b ________bb_____ 68// and this bit of t ___________tt__ 69// 70 71inline void CompressedTileStorage_SPU::getBlockAndTile(int *block, int *tile, int x, int y, int z) 72{ 73 *block = ( ( x & 0x0c ) << 5 ) | ( ( z & 0x0c ) << 3 ) | ( y >> 2 ); 74 *tile = ( ( x & 0x03 ) << 4 ) | ( ( z & 0x03 ) << 2 ) | ( y & 0x03 ); 75} 76 77 78// Get an individual tile value 79int CompressedTileStorage_SPU::get(int x, int y, int z) 80{ 81 if(y<0) 82 return 0; 83 if(!indicesAndData) return 0; 84 85 unsigned short *blockIndices = (unsigned short *)indicesAndData; 86 unsigned char *data = indicesAndData + 1024; 87 88 int block, tile; 89 getBlockAndTile( &block, &tile, x, y, z ); 90 int indexType = blockIndices[block] & INDEX_TYPE_MASK; 91 92 if( indexType == INDEX_TYPE_0_OR_8_BIT ) 93 { 94 if( blockIndices[block] & INDEX_TYPE_0_BIT_FLAG ) 95 { 96 // 0 bit reads are easy - the value is packed in the index 97 return ( blockIndices[block] >> INDEX_TILE_SHIFT ) & INDEX_TILE_MASK; 98 } 99 else 100 { 101 // 8-bit reads are just directly read from the 64 long array of values stored for the block 102 unsigned char *packed = data + ( ( blockIndices[block] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK ); 103 return packed[tile]; 104 } 105 } 106 else 107 { 108 int bitspertile = 1 << indexType; // will be 1, 2 or 4 (from index values of 0, 1, 2) 109 int tiletypecount = 1 << bitspertile; // will be 2, 4 or 16 (from index values of 0, 1, 2) 110 int tiletypemask = tiletypecount - 1; // will be 1, 3 or 15 (from index values of 0, 1, 2) 111 int indexshift = 3 - indexType; // will be 3, 2 or 1 (from index values of 0, 1, 2) 112 int indexmask_bits = 7 >> indexType; // will be 7, 3 or 1 (from index values of 0, 1, 2) 113 int indexmask_bytes = 62 >> indexshift; // will be 7, 15 or 31 (from index values of 0, 1, 2) 114 115 unsigned char *tile_types = data + ( ( blockIndices[block] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK ); 116 unsigned char *packed = tile_types + tiletypecount; 117 int idx = ( tile >> indexshift ) & indexmask_bytes; 118 int bit = ( tile & indexmask_bits ) * bitspertile; 119 return tile_types[( packed[idx] >> bit ) & tiletypemask]; 120 } 121 return 0; 122} 123 124#ifdef SN_TARGET_PS3_SPU 125 126 127 128 129void TileCompressData_SPU::uncompressTiles(int x0, int z0, int x1, int z1, bool upper) 130{ 131 int y0 = -2; 132 int y1 = 18; 133 for(int iY=y0;iY<y1;iY++) 134 { 135 if(validY(iY+m_y0, upper)) 136 { 137 for(int iX=x0;iX<x1;iX++) 138 { 139 for(int iZ=z0;iZ<z1;iZ++) 140 { 141 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 142 int sectionX = (iX+m_x0) & 0xf; 143 int sectionY = (iY+m_y0); 144 if(upper) 145 sectionY -= 128; 146 int sectionZ = (iZ+m_z0) & 0xf; 147 m_OutputData.m_tileIds[index] = m_pTileStorage->get(sectionX, sectionY, sectionZ); 148 } 149 } 150 } 151 } 152} 153 154 155void TileCompressData_SPU::clearTiles(int x0, int z0, int x1, int z1, bool upper) 156{ 157 int y0 = -2; 158 int y1 = 18; 159 for(int iY=y0;iY<y1;iY++) 160 { 161 if(validY((iY+m_y0), upper)) 162 { 163 for(int iX=x0;iX<x1;iX++) 164 { 165 for(int iZ=z0;iZ<z1;iZ++) 166 { 167 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 168 m_OutputData.m_tileIds[index] = 0; 169 } 170 } 171 } 172 } 173} 174 175 176void TileCompressData_SPU::uncompressLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight) 177{ 178 int y0 = -2; 179 int y1 = 18; 180 for(int iY=y0;iY<y1;iY++) 181 { 182 if(validY(iY+m_y0, upper)) 183 { 184 for(int iX=x0;iX<x1;iX++) 185 { 186 for(int iZ=z0;iZ<z1;iZ++) 187 { 188 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 189 int sectionX = (iX+m_x0) & 0xf; 190 int sectionY = (iY+m_y0); 191 if(upper) 192 sectionY -= 128; 193 int sectionZ = (iZ+m_z0) & 0xf; 194 if(skyLight) 195 { 196 m_OutputData.m_brightness[index] = m_pLightStorage->get(sectionX, sectionY, sectionZ); 197 } 198 else 199 { 200 m_OutputData.m_brightness[index] |= m_pLightStorage->get(sectionX, sectionY, sectionZ) << 4; 201 } 202 } 203 } 204 } 205 } 206} 207 208void TileCompressData_SPU::clearLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight) 209{ 210 int y0 = -2; 211 int y1 = 18; 212 for(int iY=y0;iY<y1;iY++) 213 { 214 if(validY((iY+m_y0), upper)) 215 { 216 for(int iX=x0;iX<x1;iX++) 217 { 218 for(int iZ=z0;iZ<z1;iZ++) 219 { 220 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 221 if(skyLight) 222 m_OutputData.m_tileIds[index] &= 0xf0; 223 else 224 m_OutputData.m_tileIds[index] &= 0x0f; 225 } 226 } 227 } 228 } 229} 230 231void TileCompressData_SPU::uncompressData(int x0, int z0, int x1, int z1, bool upper) 232{ 233 int y0 = -2; 234 int y1 = 18; 235 for(int iY=y0;iY<y1;iY++) 236 { 237 if(validY(iY+m_y0, upper)) 238 { 239 for(int iX=x0;iX<x1;iX++) 240 { 241 for(int iZ=z0;iZ<z1;iZ++) 242 { 243 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 244 int sectionX = (iX+m_x0) & 0xf; 245 int sectionY = (iY+m_y0); 246 if(upper) 247 sectionY -= 128; 248 int sectionZ = (iZ+m_z0) & 0xf; 249 m_OutputData.m_data_flags[index] = m_pDataStorage->get(sectionX, sectionY, sectionZ); 250 } 251 } 252 } 253 } 254} 255 256void TileCompressData_SPU::clearData(int x0, int z0, int x1, int z1, bool upper) 257{ 258 int y0 = -2; 259 int y1 = 18; 260 for(int iY=y0;iY<y1;iY++) 261 { 262 if(validY((iY+m_y0), upper)) 263 { 264 for(int iX=x0;iX<x1;iX++) 265 { 266 for(int iZ=z0;iZ<z1;iZ++) 267 { 268 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2); 269 m_OutputData.m_data_flags[index] = 0; 270 } 271 } 272 } 273 } 274} 275 276 277void TileCompressData_SPU::dmaSparseStorage(int64_t dataAndSize, unsigned char* pDest) 278{ 279 uint32_t loadFrom = (uint32_t)dataAndSize & 0x00000000ffffffffL; 280 unsigned int loadSize = (uint32_t)((dataAndSize >> 48)*128)+128; 281 DmaData_SPU::getAndWait(pDest, loadFrom, loadSize); 282} 283 284int padTo16(int size) 285{ 286 if(size & 0x0f) 287 { 288 size &= ~0x0f; 289 size += 0x10; 290 } 291 return size; 292} 293void TileCompressData_SPU::loadAndUncompressLowerSection(int block, int x0, int z0, int x1, int z1) 294{ 295 296 // tile IDs first 297 // --------------------------- 298 if(m_lowerBlocks[block] != NULL) 299 { 300 int dmaSize = padTo16(m_lowerBlocksSize[block]); 301 DmaData_SPU::getAndWait(m_pTileStorage->getDataPtr(), (uint32_t)m_lowerBlocks[block], dmaSize); 302// spu_print("Grabbed %d of data\n", m_lowerBlocksSize[block]); 303 uncompressTiles(x0, z0, x1, z1, false); 304 } 305 else 306 { 307 clearTiles(x0, z0, x1, z1, false); 308 } 309 310} 311 312void TileCompressData_SPU::loadAndUncompressUpperSection(int block, int x0, int z0, int x1, int z1) 313{ 314 if(m_upperBlocks[block] != NULL) 315 { 316 int dmaSize = padTo16(m_upperBlocksSize[block]); 317 DmaData_SPU::getAndWait(m_pTileStorage->getDataPtr(), (uint32_t)m_upperBlocks[block], dmaSize); 318 uncompressTiles(x0, z0, x1, z1, true); 319 } 320 else 321 { 322 clearTiles(x0, z0, x1, z1, true); 323 } 324 325 // Sky Lights 326 // --------------------------- 327 if(m_upperSkyLight[block] != 0) 328 { 329 dmaSparseStorage(m_upperSkyLight[block], m_pLightStorage->getDataPtr()); 330 uncompressLights(x0, z0, x1, z1, true, true); 331 } 332 else 333 { 334 clearLights(x0, z0, x1, z1, true, true); 335 } 336 337 // Block Lights 338 // --------------------------- 339 if(m_upperBlockLight[block] != 0) 340 { 341 dmaSparseStorage(m_upperBlockLight[block], m_pLightStorage->getDataPtr()); 342 uncompressLights(x0, z0, x1, z1, true, false); 343 } 344 else 345 { 346 clearLights(x0, z0, x1, z1, true, false); 347 } 348 349 // Data 350 // --------------------------- 351 if(m_upperData[block] != 0) 352 { 353 dmaSparseStorage(m_upperData[block], m_pDataStorage->getDataPtr()); 354 uncompressData(x0, z0, x1, z1, true); 355 } 356 else 357 { 358 clearData(x0, z0, x1, z1, true); 359 } 360} 361 362 363void TileCompressData_SPU::uncompress( uint32_t eaDataOut ) 364{ 365 unsigned char pScratchArea[33*1024]; 366 int outDataSize = sc_size*sc_size*sc_size*3; 367 CompressedTileStorage_SPU ts(pScratchArea); 368 SparseLightStorage_SPU ls(pScratchArea); 369 SparseDataStorage_SPU ds(pScratchArea); 370 371 m_pTileStorage = &ts; 372 m_pLightStorage = &ls; 373 m_pDataStorage = &ds; 374 375 if(m_y0 <= 127) 376 { 377 loadAndUncompressLowerSection(0, -2,-2, 0,0); 378 loadAndUncompressLowerSection(1, -2,0, 0,16); 379 loadAndUncompressLowerSection(2, -2,16, 0,18); 380 381 loadAndUncompressLowerSection(3, 0,-2, 16,0); 382 loadAndUncompressLowerSection(4, 0,0, 16,16); 383 loadAndUncompressLowerSection(5, 0,16, 16,18); 384 385 loadAndUncompressLowerSection(6, 16,-2, 18,0); 386 loadAndUncompressLowerSection(7, 16,0, 18,16); 387 loadAndUncompressLowerSection(8, 16,16, 18,18); 388 } 389 if(m_y0 >= 128) 390 { 391 loadAndUncompressUpperSection(0, -2,-2, 0,0); 392 loadAndUncompressUpperSection(1, -2,0, 0,16); 393 loadAndUncompressUpperSection(2, -2,16, 0,18); 394 395 loadAndUncompressUpperSection(3, 0,-2, 16,0); 396 loadAndUncompressUpperSection(4, 0,0, 16,16); 397 loadAndUncompressUpperSection(5, 0,16, 16,18); 398 399 loadAndUncompressUpperSection(6, 16,-2, 18,0); 400 loadAndUncompressUpperSection(7, 16,0, 18,16); 401 loadAndUncompressUpperSection(8, 16,16, 18,18); 402 } 403 404// for(int i=0;i<20*20*20; i++) 405// { 406// m_OutputData.m_data_flags[i] = 0xEE; 407// m_OutputData.m_data_flags[i] = 0xEE; 408// m_OutputData.m_data_flags[i] = 0xEE; 409// 410// if(m_OutputData.m_data_flags[i] == 32) 411// { 412// spu_print("Help! 32 in flags\n"); 413// } 414// } 415 DmaData_SPU::putAndWait(m_OutputData.m_tileIds, eaDataOut, outDataSize); 416} 417 418#else 419 420 421void TileCompressData_SPU::setForChunk( Region* region, int x0, int y0, int z0 ) 422{ 423 m_x0 = x0; 424 m_y0 = y0; 425 m_z0 = z0; 426 427 // we have to grab a 20x20x20 section, so we need 9 chunks in total, the centre chunk and all neighbours in x and z 428 int offsets[3] = {-2, 0, 18}; 429 for(int i=0;i<3;i++) 430 { 431 for(int j=0; j<3;j++) 432 { 433 if(y0 <= 127) 434 { 435 LevelChunk* pLevelChunk = region->getLevelChunk(m_x0+offsets[i], 0, m_z0+offsets[j]); 436 if(pLevelChunk && !pLevelChunk->isEmpty()) 437 { 438 m_lowerBlocks[i*3+j] = pLevelChunk->lowerBlocks->indicesAndData; 439 m_lowerBlocksSize[i*3+j] = pLevelChunk->lowerBlocks->allocatedSize; 440 m_lowerSkyLight[i*3+j] = pLevelChunk->lowerSkyLight->dataAndCount; 441 m_lowerBlockLight[i*3+j] = pLevelChunk->lowerBlockLight->dataAndCount; 442 m_lowerData[i*3+j] = pLevelChunk->lowerData->dataAndCount; 443 } 444 else 445 { 446 m_lowerBlocks[i*3+j] = NULL; 447 m_lowerBlocksSize[i*3+j] = 0; 448 m_lowerSkyLight[i*3+j] = 0; 449 m_lowerBlockLight[i*3+j] = 0; 450 m_lowerData[i*3+j] = 0; 451 } 452 } 453 if(y0 >= 128) 454 { 455 LevelChunk* pLevelChunk = region->getLevelChunk(m_x0+offsets[i], 128, m_z0+offsets[j]); 456 if(pLevelChunk && !pLevelChunk->isEmpty()) 457 { 458 m_upperBlocks[i*3+j] = pLevelChunk->upperBlocks->indicesAndData; 459 m_upperBlocksSize[i*3+j] = pLevelChunk->upperBlocks->allocatedSize; 460 m_upperSkyLight[i*3+j] = pLevelChunk->upperSkyLight->dataAndCount; 461 m_upperBlockLight[i*3+j] = pLevelChunk->upperBlockLight->dataAndCount; 462 m_upperData[i*3+j] = pLevelChunk->upperData->dataAndCount; 463 } 464 else 465 { 466 m_upperBlocks[i*3+j] = NULL; 467 m_upperBlocksSize[i*3+j] = 0; 468 m_upperSkyLight[i*3+j] = 0; 469 m_upperBlockLight[i*3+j] = 0; 470 m_upperData[i*3+j] = 0; 471 } 472 } 473 474 } 475 } 476} 477 478 479 480#endif