mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-22 07:53:00 +02:00
This commit is contained in:
@@ -45,8 +45,8 @@
|
|||||||
#define BUILD_NUM 350
|
#define BUILD_NUM 350
|
||||||
#mesondefine SNAPSHOT_ID
|
#mesondefine SNAPSHOT_ID
|
||||||
#mesondefine MOD_ID
|
#mesondefine MOD_ID
|
||||||
#define FUTURE_SAVE_VERSION 96
|
#define FUTURE_SAVE_VERSION 97
|
||||||
#define FUTURE_MINOR_VERSION 2
|
#define FUTURE_MINOR_VERSION 0
|
||||||
|
|
||||||
#if !(defined(SNAPSHOT) || defined(BETA) || defined(DEBUG) || MOD_ID > 0)
|
#if !(defined(SNAPSHOT) || defined(BETA) || defined(DEBUG) || MOD_ID > 0)
|
||||||
#undef FUTURE_SAVE_VERSION
|
#undef FUTURE_SAVE_VERSION
|
||||||
|
@@ -1024,7 +1024,7 @@ void GameSave::readOPS(char * data, int dataLength)
|
|||||||
//Read particle data
|
//Read particle data
|
||||||
if (partsData && partsPosData)
|
if (partsData && partsPosData)
|
||||||
{
|
{
|
||||||
int newIndex = 0, fieldDescriptor, tempTemp;
|
int newIndex = 0, tempTemp;
|
||||||
int posCount, posTotal, partsPosDataIndex = 0;
|
int posCount, posTotal, partsPosDataIndex = 0;
|
||||||
if (fullW * fullH * 3 > partsPosDataLen)
|
if (fullW * fullH * 3 > partsPosDataLen)
|
||||||
throw ParseException(ParseException::Corrupt, "Not enough particle position data");
|
throw ParseException(ParseException::Corrupt, "Not enough particle position data");
|
||||||
@@ -1052,8 +1052,8 @@ void GameSave::readOPS(char * data, int dataLength)
|
|||||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer");
|
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer");
|
||||||
x = saved_x + fullX;
|
x = saved_x + fullX;
|
||||||
y = saved_y + fullY;
|
y = saved_y + fullY;
|
||||||
fieldDescriptor = partsData[i+1];
|
unsigned int fieldDescriptor = (unsigned int)(partsData[i+1]);
|
||||||
fieldDescriptor |= partsData[i+2] << 8;
|
fieldDescriptor |= (unsigned int)(partsData[i+2]) << 8;
|
||||||
if (x >= fullW || y >= fullH)
|
if (x >= fullW || y >= fullH)
|
||||||
throw ParseException(ParseException::Corrupt, "Particle out of range");
|
throw ParseException(ParseException::Corrupt, "Particle out of range");
|
||||||
|
|
||||||
@@ -1092,6 +1092,14 @@ void GameSave::readOPS(char * data, int dataLength)
|
|||||||
particles[newIndex].temp = tempTemp+294.15f;
|
particles[newIndex].temp = tempTemp+294.15f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fieldDesc3
|
||||||
|
if (fieldDescriptor & 0x8000)
|
||||||
|
{
|
||||||
|
if (i >= partsDataLen)
|
||||||
|
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading third byte of field descriptor");
|
||||||
|
fieldDescriptor |= (unsigned int)(partsData[i++]) << 16;
|
||||||
|
}
|
||||||
|
|
||||||
//Read life
|
//Read life
|
||||||
if(fieldDescriptor & 0x02)
|
if(fieldDescriptor & 0x02)
|
||||||
{
|
{
|
||||||
@@ -1194,13 +1202,28 @@ void GameSave::readOPS(char * data, int dataLength)
|
|||||||
{
|
{
|
||||||
if (i+3 >= partsDataLen)
|
if (i+3 >= partsDataLen)
|
||||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading tmp3 and tmp4");
|
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading tmp3 and tmp4");
|
||||||
|
if (fieldDescriptor & 0x10000 && i+7 >= partsDataLen)
|
||||||
|
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading high halves of tmp3 and tmp4");
|
||||||
unsigned int tmp34;
|
unsigned int tmp34;
|
||||||
tmp34 = (unsigned int)partsData[i++];
|
tmp34 = (unsigned int)partsData[i + 0];
|
||||||
tmp34 |= (unsigned int)partsData[i++] << 8;
|
tmp34 |= (unsigned int)partsData[i + 1] << 8;
|
||||||
particles[newIndex].tmp3 = tmp34;
|
if (fieldDescriptor & 0x10000)
|
||||||
tmp34 = (unsigned int)partsData[i++];
|
{
|
||||||
tmp34 |= (unsigned int)partsData[i++] << 8;
|
tmp34 |= (unsigned int)partsData[i + 4] << 16;
|
||||||
particles[newIndex].tmp4 = tmp34;
|
tmp34 |= (unsigned int)partsData[i + 5] << 24;
|
||||||
|
}
|
||||||
|
particles[newIndex].tmp3 = int(tmp34);
|
||||||
|
tmp34 = (unsigned int)partsData[i + 2];
|
||||||
|
tmp34 |= (unsigned int)partsData[i + 3] << 8;
|
||||||
|
if (fieldDescriptor & 0x10000)
|
||||||
|
{
|
||||||
|
tmp34 |= (unsigned int)partsData[i + 6] << 16;
|
||||||
|
tmp34 |= (unsigned int)partsData[i + 7] << 24;
|
||||||
|
}
|
||||||
|
particles[newIndex].tmp4 = int(tmp34);
|
||||||
|
i += 4;
|
||||||
|
if (fieldDescriptor & 0x10000)
|
||||||
|
i += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Particle specific parsing:
|
//Particle specific parsing:
|
||||||
@@ -2186,14 +2209,21 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Copy parts data
|
//Copy parts data
|
||||||
/* Field descriptor format:
|
/* Field descriptor [1+2] format:
|
||||||
| 0 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
| RESERVED | type[2] | tmp3 and tmp4 | tmp[3+4] | tmp2[2] | tmp2 | ctype[2] | vy | vx | decorations | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len |
|
| fieldDesc3 | type[2] | tmp3/4[1+2] | tmp[3+4] | tmp2[2] | tmp2 | ctype[2] | vy | vx | decorations | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len |
|
||||||
life[2] means a second byte (for a 16 bit field) if life[1] is present
|
life[2] means a second byte (for a 16 bit field) if life[1] is present
|
||||||
|
fieldDesc3 means Field descriptor [3] exists
|
||||||
|
Field descriptor [3] format:
|
||||||
|
| 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
|
||||||
|
| RESERVED | FREE | FREE | FREE | FREE | FREE | FREE | tmp3/4[3+4] |
|
||||||
last bit is reserved. If necessary, use it to signify that fieldDescriptor will have another byte
|
last bit is reserved. If necessary, use it to signify that fieldDescriptor will have another byte
|
||||||
That way, if we ever need a 17th bit, we won't have to change the save format
|
That way, if we ever need a 25th bit, we won't have to change the save format
|
||||||
*/
|
*/
|
||||||
auto partsData = std::unique_ptr<unsigned char[]>(new unsigned char[NPART * (sizeof(Particle)+1)]);
|
|
||||||
|
// Allocate enough space to store all Particles and 3 bytes on top of that per Particle, for the field descriptors.
|
||||||
|
// In practice, a Particle will never need as much space in the save as in memory; this is just an upper bound to simplify allocation.
|
||||||
|
auto partsData = std::unique_ptr<unsigned char[]>(new unsigned char[NPART * (sizeof(Particle)+3)]);
|
||||||
unsigned int partsDataLen = 0;
|
unsigned int partsDataLen = 0;
|
||||||
auto partsSaveIndex = std::unique_ptr<unsigned[]>(new unsigned[NPART]);
|
auto partsSaveIndex = std::unique_ptr<unsigned[]>(new unsigned[NPART]);
|
||||||
unsigned int partsCount = 0;
|
unsigned int partsCount = 0;
|
||||||
@@ -2210,8 +2240,8 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
|||||||
//Loop while there is a pmap entry
|
//Loop while there is a pmap entry
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
unsigned short fieldDesc = 0;
|
unsigned int fieldDesc = 0;
|
||||||
int fieldDescLoc = 0, tempTemp, vTemp;
|
int tempTemp, vTemp;
|
||||||
|
|
||||||
//Turn pmap entry into a particles index
|
//Turn pmap entry into a particles index
|
||||||
i = i>>8;
|
i = i>>8;
|
||||||
@@ -2223,9 +2253,22 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
|||||||
partsData[partsDataLen++] = particles[i].type;
|
partsData[partsDataLen++] = particles[i].type;
|
||||||
|
|
||||||
//Location of the field descriptor
|
//Location of the field descriptor
|
||||||
fieldDescLoc = partsDataLen++;
|
int fieldDesc3Loc;
|
||||||
|
int fieldDescLoc = partsDataLen++;
|
||||||
partsDataLen++;
|
partsDataLen++;
|
||||||
|
|
||||||
|
auto tmp3 = (unsigned int)(particles[i].tmp3);
|
||||||
|
auto tmp4 = (unsigned int)(particles[i].tmp4);
|
||||||
|
if ((tmp3 || tmp4) && (!PressureInTmp3(particles[i].type) || hasPressure))
|
||||||
|
{
|
||||||
|
fieldDesc |= 1 << 13;
|
||||||
|
if ((tmp3 >> 16) || (tmp4 >> 16))
|
||||||
|
{
|
||||||
|
fieldDesc |= 1 << 15;
|
||||||
|
fieldDesc |= 1 << 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Extra type byte if necessary
|
// Extra type byte if necessary
|
||||||
if (particles[i].type & 0xFF00)
|
if (particles[i].type & 0xFF00)
|
||||||
{
|
{
|
||||||
@@ -2249,6 +2292,12 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
|||||||
partsData[partsDataLen++] = tempTemp >> 8;
|
partsData[partsDataLen++] = tempTemp >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fieldDesc & (1 << 15))
|
||||||
|
{
|
||||||
|
RESTRICTVERSION(97, 0);
|
||||||
|
fieldDesc3Loc = partsDataLen++;
|
||||||
|
}
|
||||||
|
|
||||||
//Life (optional), 1 to 2 bytes
|
//Life (optional), 1 to 2 bytes
|
||||||
if(particles[i].life)
|
if(particles[i].life)
|
||||||
{
|
{
|
||||||
@@ -2341,20 +2390,28 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//tmp3 and tmp4, 4 bytes
|
//tmp3 and tmp4, 4 bytes
|
||||||
if ((particles[i].tmp3 || particles[i].tmp4) && (!PressureInTmp3(particles[i].type) || hasPressure))
|
if (fieldDesc & (1 << 13))
|
||||||
{
|
{
|
||||||
auto tmp3 = (unsigned int)(particles[i].tmp3);
|
|
||||||
auto tmp4 = (unsigned int)(particles[i].tmp4);
|
|
||||||
fieldDesc |= 1 << 13;
|
|
||||||
partsData[partsDataLen++] = tmp3 ;
|
partsData[partsDataLen++] = tmp3 ;
|
||||||
partsData[partsDataLen++] = tmp3 >> 8;
|
partsData[partsDataLen++] = tmp3 >> 8;
|
||||||
partsData[partsDataLen++] = tmp4 ;
|
partsData[partsDataLen++] = tmp4 ;
|
||||||
partsData[partsDataLen++] = tmp4 >> 8;
|
partsData[partsDataLen++] = tmp4 >> 8;
|
||||||
|
if (fieldDesc & (1 << 16))
|
||||||
|
{
|
||||||
|
partsData[partsDataLen++] = tmp3 >> 16;
|
||||||
|
partsData[partsDataLen++] = tmp3 >> 24;
|
||||||
|
partsData[partsDataLen++] = tmp4 >> 16;
|
||||||
|
partsData[partsDataLen++] = tmp4 >> 24;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Write the field descriptor
|
//Write the field descriptor
|
||||||
partsData[fieldDescLoc] = fieldDesc;
|
partsData[fieldDescLoc] = fieldDesc;
|
||||||
partsData[fieldDescLoc+1] = fieldDesc>>8;
|
partsData[fieldDescLoc+1] = fieldDesc>>8;
|
||||||
|
if (fieldDesc & (1 << 15))
|
||||||
|
{
|
||||||
|
partsData[fieldDesc3Loc] = fieldDesc>>16;
|
||||||
|
}
|
||||||
|
|
||||||
if (particles[i].type == PT_SOAP)
|
if (particles[i].type == PT_SOAP)
|
||||||
soapCount++;
|
soapCount++;
|
||||||
|
Reference in New Issue
Block a user