Cleanup and minor refactoring of progress.cc/hh

Also document some stuff in the progress.hh header
This commit is contained in:
ROllerozxa 2026-06-02 21:23:20 +02:00
commit cfcc169661
4 changed files with 300 additions and 287 deletions

View file

@ -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:
{

View file

@ -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);

View file

@ -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,49 +41,60 @@ 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);
if (!fp) {
tms_infof("data.bin doesn't exist, creating one");
initialized = true;
return;
}
for (int x=0; x<3; x++) {
// 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);
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 (int l=0; l<nlevels; l++) {
for (uint32_t l = 0; l < nlevels; l++) {
lvl_progress p;
uint32_t r_nn=0, r_nnn=0;
uint32_t r_nn = 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;
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;
@ -146,20 +155,28 @@ progress::init(char *custom_path/*=0*/)
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;
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;};
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();
@ -178,9 +195,11 @@ progress::init(char *custom_path/*=0*/)
crc_set ++;
}
/* verify crc32 */
// verify crc32
long size = ftell(fp);
if (size < 0) {goto err; };
if (size < 0) {
goto err;
}
char *tcrc = (char*)malloc(size);
fseek(fp, 0, SEEK_SET);
@ -191,7 +210,7 @@ progress::init(char *custom_path/*=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++) {
for (uint32_t x = 0; x < 4; x++) {
tcrc[crc_pos[x]] = (uint8_t)((crc_base >> (x*8u)) & 0xffu);
}
@ -203,42 +222,22 @@ progress::init(char *custom_path/*=0*/)
//goto err;
}
initialized = true;
return;
} else {
tms_infof("data.bin doesn't exist, creating one");
initialized = true;
return;
}
err:
levels[0].clear();
levels[1].clear();
levels[2].clear();
tms_errorf("ERROR: invalid data in data.bin");
if (fp) fclose(fp);
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) {
tms_errorf("Error: could not save progress %s", path);
return;
}
if (fp) {
uint32_t crc_val = 0;
fwrite(WARNING_STR, 1, strlen(WARNING_STR), fp);
@ -252,14 +251,17 @@ progress::commit()
lvl_progress p = *i->second;
uint32_t id = (i->first+c) ^ ID_XOR;
size_t l_size;
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;
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();
@ -298,31 +300,32 @@ progress::commit()
) ^ 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;
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++) {
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++) {
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);
@ -344,8 +347,4 @@ progress::commit()
}
fclose(fp);
} else {
tms_errorf("Error: could not save progress %s", filename);
}
#endif
}

View file

@ -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();
};