#include #include #include #include #include #include #include #include #include "progress.h" #include "items.h" #include "level.h" #include "paths.h" static const char* progress_file = "RGBESAVE"; static const uint8_t progress_file_header_expected[PROGRESS_FILE_HEADER_SIZE] = { 'R', 'G', 'B', 'E', 0xAE, 0x01, 0x00 }; static ti_var_t appvar; static bool progress_made; struct progress_data progress; static struct progress_data_level_wip temporary_level_wip; uint8_t progress_level_get(uint16_t level_index) { return (progress.level_stuck_0 < level_index) ? LOCKED : ( (progress.level_stuck_0 != level_index && progress.level_stuck_1 != level_index && progress.level_stuck_2 != level_index) ? FINISHED : ( (progress.level_wip.index == level_index) ? WIP : AVAILABLE ) ) ; } uint8_t progress_levels_done(uint16_t level_first, uint16_t level_last) { return (level_last < progress.level_stuck_0) && (progress.level_stuck_1 < level_first || progress.level_stuck_1 > level_last) && (progress.level_stuck_2 < level_first || progress.level_stuck_2 > level_last); } void progress_level_done(uint16_t level_index) { if (progress.level_stuck_0 == level_index) ++progress.level_stuck_0; else if (progress.level_stuck_1 == level_index) progress.level_stuck_1 = 0; else if (progress.level_stuck_2 == level_index) progress.level_stuck_2 = 0; else return; progress_made = 1; } void progress_level_tried(uint16_t level_index) { if (progress.level_stuck_0 == level_index) { if (!progress.level_stuck_1) progress.level_stuck_1 = level_index; else if (!progress.level_stuck_2) progress.level_stuck_2 = level_index; else return; ++progress.level_stuck_0; progress_made = 1; } } void progress_level_load(void) { if (level.level_index == progress.level_wip.index) { uint8_t byte_index = 0; uint8_t i; for (i = 1; i <= 11; ++i) { memcpy(&paths_connections[i*16+1], &progress.level_wip.paths[byte_index], 11); byte_index += 11; } { uint8_t bit_index, bits; i = bits = byte_index = 0; bit_index = 7; do { if (++bit_index == 8) { bits = progress.level_wip.dropp[byte_index++]; bit_index = 0; } if (cells_item_type[i] == ITEM_DROPPOINT) { if (bits & (1 << bit_index)) cells_item_state[i] = 1; } } while (++i); } } } void progress_level_save(void) { temporary_level_wip.index = level.level_index; { uint8_t byte_index = 0, bit_index = 0; uint8_t i; for (i = 1; i <= 11; ++i) { memcpy(&temporary_level_wip.paths[byte_index], &paths_connections[i*16+1], 11); byte_index += 11; } { uint8_t bit_index, bits; i = bits = bit_index = byte_index = 0; do { if (cells_item_type[i] == ITEM_DROPPOINT) { if (cells_item_state[i]) bits |= 1 << bit_index; } if (++bit_index == 8) { temporary_level_wip.dropp[byte_index++] = bits; bits = bit_index = 0; } } while (++i); } for (i = 121 + 32; i > 0; --i) { if ((&temporary_level_wip.paths[0])[i-1]) break; } if (i || (progress.level_wip.index == level.level_index)) { progress.level_wip = temporary_level_wip; progress_made = 1; } } } void progress_load(void) { progress_made = 0; if (!( (appvar = ti_Open(progress_file, "r")) && (ti_Read(&progress, PROGRESS_FILE_SIZE, 1, appvar) == 1) && (memcmp(progress.header, progress_file_header_expected, PROGRESS_FILE_HEADER_SIZE) == 0) )) { memset(&progress, 0, PROGRESS_FILE_SIZE); memcpy(progress.header, progress_file_header_expected, PROGRESS_FILE_HEADER_SIZE); } if (!progress.level_stuck_0) progress.level_stuck_0 = 1; ti_CloseAll(); } void progress_save(void) { if (!progress_made) return; if ( (appvar = ti_Open(progress_file, appvar ? "r+" : "w")) ) { ti_Write(&progress, PROGRESS_FILE_SIZE, 1, appvar); ti_SetArchiveStatus(true, appvar); } ti_CloseAll(); }