forked from mirrors/principia
Cleanup and minor refactoring of progress.cc/hh
Also document some stuff in the progress.hh header
This commit is contained in:
parent
2a8ad3df09
commit
cfcc169661
4 changed files with 300 additions and 287 deletions
|
|
@ -1896,9 +1896,13 @@ initial_loader(int step)
|
|||
P.s_loading_screen->set_text("Loading progress...");
|
||||
break;
|
||||
|
||||
case 15:
|
||||
progress::init();
|
||||
case 15: {
|
||||
char tmp[1024];
|
||||
const char *storage = tms_storage_path();
|
||||
snprintf(tmp, 1024, "%s/data.bin", storage);
|
||||
progress::init(tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
case 16:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -916,11 +916,6 @@ _submit_score(void *p)
|
|||
|
||||
CURLcode r;
|
||||
|
||||
char data_path[1024];
|
||||
|
||||
const char *storage = tms_storage_path();
|
||||
snprintf(data_path, 1023, "%s/data.bin", storage);
|
||||
|
||||
int highscore_level_offset = highscore_offset(W->level.community_id);
|
||||
|
||||
lvledit lvl;
|
||||
|
|
@ -975,7 +970,7 @@ _submit_score(void *p)
|
|||
|
||||
part = curl_mime_addpart(mime);
|
||||
curl_mime_name(part, "data.bin");
|
||||
curl_mime_filedata(part, data_path);
|
||||
curl_mime_filedata(part, progress::path);
|
||||
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%u", W->level.community_id);
|
||||
|
|
|
|||
565
src/progress.cc
565
src/progress.cc
|
|
@ -22,11 +22,9 @@
|
|||
std::map<uint32_t, lvl_progress*> progress::levels[3];
|
||||
|
||||
bool progress::initialized = false;
|
||||
char progress::path[1024] = {0};
|
||||
|
||||
lvl_progress*
|
||||
progress::get_level_progress(int level_type,
|
||||
uint32_t level_id)
|
||||
{
|
||||
lvl_progress *progress::get_level_progress(int level_type, uint32_t level_id) {
|
||||
if (level_type < 0 || level_type >= 3)
|
||||
return 0;
|
||||
|
||||
|
|
@ -43,309 +41,310 @@ progress::get_level_progress(int level_type,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
progress::init(char *custom_path/*=0*/)
|
||||
{
|
||||
void progress::init(char *data_path) {
|
||||
char tmp[1024];
|
||||
if (custom_path) {
|
||||
strcpy(tmp, custom_path);
|
||||
} else {
|
||||
#ifdef _NO_TMS
|
||||
return;
|
||||
#else
|
||||
const char *storage = tms_storage_path();
|
||||
snprintf(tmp, 1023, "%s/data.bin", storage);
|
||||
#endif
|
||||
}
|
||||
memcpy(path, data_path, 1024);
|
||||
|
||||
long crc_pos[4]={0,0,0,0};
|
||||
uint32_t crc_set=0;
|
||||
long crc_pos[4] = {0,0,0,0};
|
||||
uint32_t crc_set = 0;
|
||||
|
||||
uint32_t crc_v=0;
|
||||
uint32_t crc_v = 0;
|
||||
uint32_t crc_base = 0;
|
||||
|
||||
FILE *fp = fopen(tmp, "rb");
|
||||
FILE *fp = fopen(path, "rb");
|
||||
|
||||
if (fp) {
|
||||
fread(&tmp, 1, strlen(WARNING_STR), fp);
|
||||
|
||||
for (int x=0; x<3; x++) {
|
||||
uint32_t nlevels;
|
||||
fread(&nlevels, 1, sizeof(uint32_t), fp);
|
||||
|
||||
nlevels ^= A_XOR;
|
||||
|
||||
for (int l=0; l<nlevels; l++) {
|
||||
lvl_progress p;
|
||||
uint32_t r_nn=0, r_nnn=0;
|
||||
uint32_t id;
|
||||
switch (l%5) {
|
||||
case 0: fread(tmp, 1, sizeof(uint8_t), fp); break;
|
||||
case 1: fread(tmp, 3, sizeof(uint8_t), fp); break;
|
||||
case 2: fread(tmp, 4, sizeof(uint8_t), fp); break;
|
||||
case 3: fread(tmp, 2, sizeof(uint8_t), fp); break;
|
||||
case 4: fread(tmp, 5, sizeof(uint8_t), fp); break;
|
||||
}
|
||||
fread(&id, 1, sizeof(uint32_t), fp);
|
||||
id ^= ID_XOR;
|
||||
id -= l;
|
||||
|
||||
if (crc_set < 4u) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t t;
|
||||
fread(&t, 1, sizeof(uint8_t), fp);
|
||||
|
||||
crc_v |= t << crc_set*8u;
|
||||
|
||||
crc_set ++;
|
||||
}
|
||||
|
||||
fread(&p.num_plays, 1, sizeof(uint32_t), fp);
|
||||
r_nn = p.num_plays;
|
||||
p.completed = p.num_plays >> 31;
|
||||
p.num_plays &= ~(1<<31);
|
||||
|
||||
fread(&p.top_score, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.top_score;
|
||||
p.top_score ^= O_XOR;
|
||||
|
||||
//tms_infof("reading: %u, %u", id, p.top_score);
|
||||
|
||||
fread(&p.last_score, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.last_score;
|
||||
p.last_score ^= O_XOR;
|
||||
|
||||
fread(&p.time, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.time;
|
||||
p.time ^= O_XOR;
|
||||
|
||||
uint32_t n;
|
||||
fread(&n, 1, sizeof(uint32_t), fp);
|
||||
n ^= X_XOR;
|
||||
|
||||
/* verify lower 16 bits of top score */
|
||||
uint32_t t = p.top_score;
|
||||
|
||||
if ((t & 0xffff) != (n & 0xffff)) {
|
||||
tms_infof("invalid score 1");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ( (((t < 1000000000) << 31) != (n & (1<<31)))
|
||||
|| ((t < 100000) << 30) != (n & (1<<30))
|
||||
|| ((t < 10000000) << 29) != (n & (1<<29))
|
||||
|| ((t < 100) << 28) != (n & (1<<28))
|
||||
|| ((t < 100000000) << 27) != (n & (1<<27))
|
||||
|| ((t < 10000) << 26) != (n & (1<<26))
|
||||
|| ((t < 1000000) << 25) != (n & (1<<25))
|
||||
|| ((t < 1000) << 24) != (n & (1<<24))
|
||||
|| ((t < 10) << 23) != (n & (1<<23))) {
|
||||
tms_infof("invalid score 2");
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint32_t nn,nnn;
|
||||
fread(&nn, 1, sizeof(uint32_t), fp);
|
||||
switch (l%9) {
|
||||
case 0: fread(tmp, 9, sizeof(uint8_t), fp); break;
|
||||
case 1: fread(tmp, 1, sizeof(uint8_t), fp); break;
|
||||
case 2: fread(tmp, 2, sizeof(uint8_t), fp); break;
|
||||
case 3: fread(tmp, 5, sizeof(uint8_t), fp); break;
|
||||
case 4: fread(tmp, 7, sizeof(uint8_t), fp); break;
|
||||
case 5: fread(tmp, 8, sizeof(uint8_t), fp); break;
|
||||
case 6: fread(tmp, 3, sizeof(uint8_t), fp); break;
|
||||
case 7: fread(tmp, 4, sizeof(uint8_t), fp); break;
|
||||
case 8: fread(tmp, 6, sizeof(uint8_t), fp); break;
|
||||
}
|
||||
fread(&nnn, 1, sizeof(uint32_t), fp);
|
||||
if (nn != r_nn) {tms_errorf("invalid r_nn"); goto err;};
|
||||
if (nnn != (p.num_plays + p.top_score + p.last_score + p.time)) {tms_errorf("invalid nnn");goto err;};
|
||||
crc_base += p.top_score;
|
||||
|
||||
lvl_progress *pp = new lvl_progress();
|
||||
*pp = p;
|
||||
levels[x].insert(std::pair<uint32_t, lvl_progress*>(id, pp));
|
||||
}
|
||||
}
|
||||
|
||||
while (crc_set < 4u) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t t;
|
||||
fread(&t, 1, sizeof(uint8_t), fp);
|
||||
|
||||
crc_v |= t << crc_set*8u;
|
||||
|
||||
crc_set ++;
|
||||
}
|
||||
|
||||
/* verify crc32 */
|
||||
long size = ftell(fp);
|
||||
if (size < 0) {goto err; };
|
||||
char *tcrc = (char*)malloc(size);
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(tcrc, 1, size, fp);
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
|
||||
tms_infof("crc base read: %x", crc_base);
|
||||
tms_infof("crc sum read: %x", crc_v);
|
||||
|
||||
for (uint32_t x=0; x<4; x++) {
|
||||
tcrc[crc_pos[x]] = (uint8_t)((crc_base >> (x*8u)) & 0xffu);
|
||||
}
|
||||
|
||||
uint32_t crc = crc32(0L, (const Bytef*)tcrc, size);
|
||||
free(tcrc);
|
||||
|
||||
if (crc != crc_v) {
|
||||
tms_infof("crc mismatch");
|
||||
//goto err;
|
||||
}
|
||||
initialized = true;
|
||||
return;
|
||||
|
||||
} else {
|
||||
if (!fp) {
|
||||
tms_infof("data.bin doesn't exist, creating one");
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// well...
|
||||
goto load;
|
||||
|
||||
err:
|
||||
levels[0].clear();
|
||||
levels[1].clear();
|
||||
levels[2].clear();
|
||||
tms_errorf("ERROR: invalid data in data.bin");
|
||||
if (fp) fclose(fp);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
initialized = true;
|
||||
return;
|
||||
|
||||
load:
|
||||
fread(tmp, 1, strlen(WARNING_STR), fp);
|
||||
|
||||
for (int x = 0; x < 3; x++) {
|
||||
uint32_t nlevels;
|
||||
fread(&nlevels, 1, sizeof(uint32_t), fp);
|
||||
|
||||
nlevels ^= A_XOR;
|
||||
|
||||
for (uint32_t l = 0; l < nlevels; l++) {
|
||||
lvl_progress p;
|
||||
uint32_t r_nn = 0;
|
||||
uint32_t id;
|
||||
size_t l_size;
|
||||
switch (l % 5) {
|
||||
case 0: l_size = 1; break;
|
||||
case 1: l_size = 3; break;
|
||||
case 2: l_size = 4; break;
|
||||
case 3: l_size = 2; break;
|
||||
case 4: l_size = 5; break;
|
||||
}
|
||||
fread(tmp, l_size, sizeof(uint8_t), fp);
|
||||
|
||||
fread(&id, 1, sizeof(uint32_t), fp);
|
||||
id ^= ID_XOR;
|
||||
id -= l;
|
||||
|
||||
if (crc_set < 4u) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t t;
|
||||
fread(&t, 1, sizeof(uint8_t), fp);
|
||||
|
||||
crc_v |= t << crc_set*8u;
|
||||
|
||||
crc_set ++;
|
||||
}
|
||||
|
||||
fread(&p.num_plays, 1, sizeof(uint32_t), fp);
|
||||
r_nn = p.num_plays;
|
||||
p.completed = p.num_plays >> 31;
|
||||
p.num_plays &= ~(1<<31);
|
||||
|
||||
fread(&p.top_score, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.top_score;
|
||||
p.top_score ^= O_XOR;
|
||||
|
||||
//tms_infof("reading: %u, %u", id, p.top_score);
|
||||
|
||||
fread(&p.last_score, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.last_score;
|
||||
p.last_score ^= O_XOR;
|
||||
|
||||
fread(&p.time, 1, sizeof(uint32_t), fp);
|
||||
r_nn += p.time;
|
||||
p.time ^= O_XOR;
|
||||
|
||||
uint32_t n;
|
||||
fread(&n, 1, sizeof(uint32_t), fp);
|
||||
n ^= X_XOR;
|
||||
|
||||
/* verify lower 16 bits of top score */
|
||||
uint32_t t = p.top_score;
|
||||
|
||||
if ((t & 0xffff) != (n & 0xffff)) {
|
||||
tms_infof("invalid score 1");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ( (((t < 1000000000) << 31) != (n & (1<<31)))
|
||||
|| ((t < 100000) << 30) != (n & (1<<30))
|
||||
|| ((t < 10000000) << 29) != (n & (1<<29))
|
||||
|| ((t < 100) << 28) != (n & (1<<28))
|
||||
|| ((t < 100000000) << 27) != (n & (1<<27))
|
||||
|| ((t < 10000) << 26) != (n & (1<<26))
|
||||
|| ((t < 1000000) << 25) != (n & (1<<25))
|
||||
|| ((t < 1000) << 24) != (n & (1<<24))
|
||||
|| ((t < 10) << 23) != (n & (1<<23))) {
|
||||
tms_infof("invalid score 2");
|
||||
goto err;
|
||||
}
|
||||
|
||||
uint32_t nn,nnn;
|
||||
fread(&nn, 1, sizeof(uint32_t), fp);
|
||||
switch (l % 9) {
|
||||
case 0: l_size = 9; break;
|
||||
case 1: l_size = 1; break;
|
||||
case 2: l_size = 2; break;
|
||||
case 3: l_size = 5; break;
|
||||
case 4: l_size = 7; break;
|
||||
case 5: l_size = 8; break;
|
||||
case 6: l_size = 3; break;
|
||||
case 7: l_size = 4; break;
|
||||
case 8: l_size = 6; break;
|
||||
}
|
||||
fread(tmp, l_size, sizeof(uint8_t), fp);
|
||||
|
||||
fread(&nnn, 1, sizeof(uint32_t), fp);
|
||||
if (nn != r_nn) {
|
||||
tms_errorf("invalid r_nn");
|
||||
goto err;
|
||||
}
|
||||
if (nnn != (p.num_plays + p.top_score + p.last_score + p.time)) {
|
||||
tms_errorf("invalid nnn");
|
||||
goto err;
|
||||
}
|
||||
crc_base += p.top_score;
|
||||
|
||||
lvl_progress *pp = new lvl_progress();
|
||||
*pp = p;
|
||||
levels[x].insert(std::pair<uint32_t, lvl_progress*>(id, pp));
|
||||
}
|
||||
}
|
||||
|
||||
while (crc_set < 4u) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t t;
|
||||
fread(&t, 1, sizeof(uint8_t), fp);
|
||||
|
||||
crc_v |= t << crc_set*8u;
|
||||
|
||||
crc_set ++;
|
||||
}
|
||||
|
||||
// verify crc32
|
||||
long size = ftell(fp);
|
||||
if (size < 0) {
|
||||
goto err;
|
||||
}
|
||||
char *tcrc = (char*)malloc(size);
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(tcrc, 1, size, fp);
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
|
||||
tms_infof("crc base read: %x", crc_base);
|
||||
tms_infof("crc sum read: %x", crc_v);
|
||||
|
||||
for (uint32_t x = 0; x < 4; x++) {
|
||||
tcrc[crc_pos[x]] = (uint8_t)((crc_base >> (x*8u)) & 0xffu);
|
||||
}
|
||||
|
||||
uint32_t crc = crc32(0L, (const Bytef*)tcrc, size);
|
||||
free(tcrc);
|
||||
|
||||
if (crc != crc_v) {
|
||||
tms_infof("crc mismatch");
|
||||
//goto err;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
progress::commit()
|
||||
{
|
||||
#ifndef _NO_TMS
|
||||
|
||||
if (!initialized) {
|
||||
void progress::commit() {
|
||||
if (!initialized)
|
||||
return;
|
||||
}
|
||||
|
||||
char filename[1024];
|
||||
const char *storage = tms_storage_path();
|
||||
snprintf(filename, 1023, "%s/data.bin", storage);
|
||||
|
||||
long crc_pos[4]={0,0,0,0};
|
||||
uint32_t crc_set=0;
|
||||
|
||||
FILE *fp = fopen(filename, "w+b");
|
||||
FILE *fp = fopen(path, "w+b");
|
||||
|
||||
if (fp) {
|
||||
uint32_t crc_val = 0;
|
||||
fwrite(WARNING_STR, 1, strlen(WARNING_STR), fp);
|
||||
|
||||
for (int x=0; x<3; x++) {
|
||||
uint32_t t = levels[x].size() ^ A_XOR;
|
||||
fwrite(&t, 1, sizeof(uint32_t), fp);
|
||||
uint32_t c = 0;
|
||||
|
||||
for (std::map<uint32_t, lvl_progress*>::iterator i = levels[x].begin();
|
||||
i != levels[x].end(); i++) {
|
||||
lvl_progress p = *i->second;
|
||||
|
||||
uint32_t id = (i->first+c) ^ ID_XOR;
|
||||
switch (c%5) {
|
||||
case 0: fwrite(i->second, 1, sizeof(uint8_t), fp); break;
|
||||
case 1: fwrite(i->second, 3, sizeof(uint8_t), fp); break;
|
||||
case 2: fwrite(i->second, 4, sizeof(uint8_t), fp); break;
|
||||
case 3: fwrite(i->second, 2, sizeof(uint8_t), fp); break;
|
||||
case 4: fwrite(i->second, 5, sizeof(uint8_t), fp); break;
|
||||
}
|
||||
fwrite(&id, 1, sizeof(uint32_t), fp);
|
||||
if (crc_set < 4) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t xx = (uint8_t)levels[1].size();
|
||||
fwrite(&xx, 1, sizeof(uint8_t), fp);
|
||||
crc_set ++;
|
||||
}
|
||||
uint32_t n = p.num_plays | (p.completed << 31), nn=0,nnn=0;
|
||||
nn += n;
|
||||
nnn += p.num_plays;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.top_score ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.top_score;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.last_score ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.last_score;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.time ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.time;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
crc_val += p.top_score;
|
||||
|
||||
n =(
|
||||
((uint32_t)(p.top_score < 1000000000) << 31)
|
||||
| ((uint32_t)(p.top_score < 100000) << 30)
|
||||
| ((uint32_t)(p.top_score < 10000000) << 29)
|
||||
| ((uint32_t)(p.top_score < 100) << 28)
|
||||
| ((uint32_t)(p.top_score < 100000000) << 27)
|
||||
| ((uint32_t)(p.top_score < 10000) << 26)
|
||||
| ((uint32_t)(p.top_score < 1000000) << 25)
|
||||
| ((uint32_t)(p.top_score < 1000) << 24)
|
||||
| ((uint32_t)(p.top_score < 10) << 23)
|
||||
| (p.top_score & 0xffff)
|
||||
) ^ X_XOR;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
fwrite(&nn, 1, sizeof(uint32_t), fp);
|
||||
switch (c%9) {
|
||||
case 0: fwrite(i->second, 9, sizeof(uint8_t), fp); break;
|
||||
case 1: fwrite(i->second, 1, sizeof(uint8_t), fp); break;
|
||||
case 2: fwrite(i->second, 2, sizeof(uint8_t), fp); break;
|
||||
case 3: fwrite(i->second, 5, sizeof(uint8_t), fp); break;
|
||||
case 4: fwrite(i->second, 7, sizeof(uint8_t), fp); break;
|
||||
case 5: fwrite(i->second, 8, sizeof(uint8_t), fp); break;
|
||||
case 6: fwrite(i->second, 3, sizeof(uint8_t), fp); break;
|
||||
case 7: fwrite(i->second, 4, sizeof(uint8_t), fp); break;
|
||||
case 8: fwrite(i->second, 6, sizeof(uint8_t), fp); break;
|
||||
}
|
||||
fwrite(&nnn, 1, sizeof(uint32_t), fp);
|
||||
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
for (; crc_set<4; crc_set++) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t xx = (uint8_t)levels[1].size();
|
||||
fwrite(&xx, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
long size = ftell(fp);
|
||||
|
||||
for (uint32_t x=0; x<4; x++) {
|
||||
fseek(fp, crc_pos[x], SEEK_SET);
|
||||
uint8_t v = (uint8_t)((crc_val >> (x*8u)) & 0xffu);
|
||||
fwrite(&v, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
size_t bl;
|
||||
unsigned char b[1024];
|
||||
uint32_t crc = crc32(0L, Z_NULL, 0);
|
||||
while ((bl = fread(b, 1, 1024, fp)) > 0) {
|
||||
crc = crc32(crc, b, bl);
|
||||
}
|
||||
|
||||
for (uint32_t x=0; x<4; x++) {
|
||||
fseek(fp, crc_pos[x], SEEK_SET);
|
||||
uint8_t v = (uint8_t)((crc >> (x*8u)) & 0xffu);
|
||||
fwrite(&v, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
} else {
|
||||
tms_errorf("Error: could not save progress %s", filename);
|
||||
if (!fp) {
|
||||
tms_errorf("Error: could not save progress %s", path);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t crc_val = 0;
|
||||
fwrite(WARNING_STR, 1, strlen(WARNING_STR), fp);
|
||||
|
||||
for (int x=0; x<3; x++) {
|
||||
uint32_t t = levels[x].size() ^ A_XOR;
|
||||
fwrite(&t, 1, sizeof(uint32_t), fp);
|
||||
uint32_t c = 0;
|
||||
|
||||
for (std::map<uint32_t, lvl_progress*>::iterator i = levels[x].begin();
|
||||
i != levels[x].end(); i++) {
|
||||
lvl_progress p = *i->second;
|
||||
|
||||
uint32_t id = (i->first+c) ^ ID_XOR;
|
||||
size_t l_size;
|
||||
switch (c%5) {
|
||||
case 0: l_size = 1; break;
|
||||
case 1: l_size = 3; break;
|
||||
case 2: l_size = 4; break;
|
||||
case 3: l_size = 2; break;
|
||||
case 4: l_size = 5; break;
|
||||
}
|
||||
fwrite(i->second, l_size, sizeof(uint8_t), fp);
|
||||
fwrite(&id, 1, sizeof(uint32_t), fp);
|
||||
|
||||
if (crc_set < 4) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t xx = (uint8_t)levels[1].size();
|
||||
fwrite(&xx, 1, sizeof(uint8_t), fp);
|
||||
crc_set ++;
|
||||
}
|
||||
uint32_t n = p.num_plays | (p.completed << 31), nn=0,nnn=0;
|
||||
nn += n;
|
||||
nnn += p.num_plays;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.top_score ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.top_score;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.last_score ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.last_score;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
n = p.time ^ O_XOR;
|
||||
nn += n;
|
||||
nnn += p.time;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
crc_val += p.top_score;
|
||||
|
||||
n =(
|
||||
((uint32_t)(p.top_score < 1000000000) << 31)
|
||||
| ((uint32_t)(p.top_score < 100000) << 30)
|
||||
| ((uint32_t)(p.top_score < 10000000) << 29)
|
||||
| ((uint32_t)(p.top_score < 100) << 28)
|
||||
| ((uint32_t)(p.top_score < 100000000) << 27)
|
||||
| ((uint32_t)(p.top_score < 10000) << 26)
|
||||
| ((uint32_t)(p.top_score < 1000000) << 25)
|
||||
| ((uint32_t)(p.top_score < 1000) << 24)
|
||||
| ((uint32_t)(p.top_score < 10) << 23)
|
||||
| (p.top_score & 0xffff)
|
||||
) ^ X_XOR;
|
||||
fwrite(&n, 1, sizeof(uint32_t), fp);
|
||||
fwrite(&nn, 1, sizeof(uint32_t), fp);
|
||||
switch (c % 9) {
|
||||
case 0: l_size = 9; break;
|
||||
case 1: l_size = 1; break;
|
||||
case 2: l_size = 2; break;
|
||||
case 3: l_size = 5; break;
|
||||
case 4: l_size = 7; break;
|
||||
case 5: l_size = 8; break;
|
||||
case 6: l_size = 3; break;
|
||||
case 7: l_size = 4; break;
|
||||
case 8: l_size = 6; break;
|
||||
}
|
||||
fwrite(i->second, l_size, sizeof(uint8_t), fp);
|
||||
fwrite(&nnn, 1, sizeof(uint32_t), fp);
|
||||
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
for (; crc_set < 4; crc_set++) {
|
||||
crc_pos[crc_set] = ftell(fp);
|
||||
uint8_t xx = (uint8_t)levels[1].size();
|
||||
fwrite(&xx, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
long size = ftell(fp);
|
||||
|
||||
for (uint32_t x = 0; x < 4; x++) {
|
||||
fseek(fp, crc_pos[x], SEEK_SET);
|
||||
uint8_t v = (uint8_t)((crc_val >> (x*8u)) & 0xffu);
|
||||
fwrite(&v, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
size_t bl;
|
||||
unsigned char b[1024];
|
||||
uint32_t crc = crc32(0L, Z_NULL, 0);
|
||||
while ((bl = fread(b, 1, 1024, fp)) > 0) {
|
||||
crc = crc32(crc, b, bl);
|
||||
}
|
||||
|
||||
for (uint32_t x=0; x<4; x++) {
|
||||
fseek(fp, crc_pos[x], SEEK_SET);
|
||||
uint8_t v = (uint8_t)((crc >> (x*8u)) & 0xffu);
|
||||
fwrite(&v, 1, sizeof(uint8_t), fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,21 @@
|
|||
#include <stdint.h>
|
||||
#include <map>
|
||||
|
||||
class lvl_progress
|
||||
{
|
||||
/// Class representing progress information of a specific level
|
||||
class lvl_progress {
|
||||
public:
|
||||
// Whether the level has been completed at least once
|
||||
uint8_t completed;
|
||||
/// Top score achieved by the player in this level (or lowest, if LVL_LOWER_SCORE_IS_BETTER)
|
||||
uint32_t top_score;
|
||||
/// Last score achieved by the player in this level
|
||||
uint32_t last_score;
|
||||
/// Amount of time in seconds it took to complete the level? (Currently unused, always 0)
|
||||
uint32_t time;
|
||||
/// Amount of times a level has been played
|
||||
uint32_t num_plays;
|
||||
|
||||
lvl_progress()
|
||||
{
|
||||
lvl_progress() {
|
||||
completed = 0;
|
||||
top_score = 0;
|
||||
last_score = 0;
|
||||
|
|
@ -22,13 +26,24 @@ class lvl_progress
|
|||
}
|
||||
};
|
||||
|
||||
class progress
|
||||
{
|
||||
/// Class used for storing and loading player persistent progress in a way that
|
||||
/// is not easily tampered with.
|
||||
class progress {
|
||||
public:
|
||||
static bool initialized;
|
||||
static char path[1024];
|
||||
|
||||
static std::map<uint32_t, lvl_progress*> levels[3];
|
||||
|
||||
/**
|
||||
* Return a pointer to a level progress instance. If there is no progress for the
|
||||
* given level, a new instance is created, added to the internal map and returned.
|
||||
*/
|
||||
static lvl_progress *get_level_progress(int level_type, uint32_t level_id);
|
||||
|
||||
static void init(char *custom_path=0);
|
||||
/// Initialise progress and load from disk if it exists
|
||||
static void init(char *data_path);
|
||||
|
||||
/// Save progress to disk
|
||||
static void commit();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue