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