the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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