-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstorage.c
More file actions
90 lines (74 loc) · 2.96 KB
/
Copy pathstorage.c
File metadata and controls
90 lines (74 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include "storage.h"
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <string.h>
#define MAGIC_NUM 0x4744 // "GD"
#define MAGIC_ADDR 0x00
// Memory layout per game (3 scores of 5 bytes each = 15 bytes per game)
// 0x00 - 0x01: Magic number
// 0x02 - 0x10: Snake scores
// 0x11 - 0x1F: Tetris scores
// 0x20 - 0x2E: Bricks scores
#define SCORE_ADDR_BASE 0x02
#define SCORE_BYTES_PER_GAME 15
#define SCORES_PER_GAME 3
void storageInit(void) {
uint16_t magic = eeprom_read_word((const uint16_t*)MAGIC_ADDR);
if (magic != MAGIC_NUM) {
// First boot, or corrupted EEPROM. Format it.
eeprom_write_word((uint16_t*)MAGIC_ADDR, MAGIC_NUM);
// Zero out all high score data
for (uint16_t i = SCORE_ADDR_BASE; i < SCORE_ADDR_BASE + (SCORE_BYTES_PER_GAME * 3); i++) {
eeprom_write_byte((uint8_t*)i, 0);
wdt_reset(); // Keep watchdog fed during long EEPROM operations
}
}
}
void storageGetHighScores(uint8_t gameId, HighScore scores[3]) {
uint16_t addr = SCORE_ADDR_BASE + (gameId * SCORE_BYTES_PER_GAME);
for (uint8_t i = 0; i < SCORES_PER_GAME; i++) {
scores[i].score = eeprom_read_word((const uint16_t*)addr);
addr += 2;
scores[i].name[0] = eeprom_read_byte((const uint8_t*)addr++);
scores[i].name[1] = eeprom_read_byte((const uint8_t*)addr++);
scores[i].name[2] = eeprom_read_byte((const uint8_t*)addr++);
scores[i].name[3] = '\0';
// Handle uninitialized names
if (scores[i].name[0] == 0 || scores[i].name[0] == 0xFF) {
strcpy(scores[i].name, "---");
}
}
}
bool storageCheckAndSaveScore(uint8_t gameId, uint16_t newScore, const char* name) {
HighScore scores[3];
storageGetHighScores(gameId, scores);
int8_t insertIdx = -1;
for (int8_t i = 0; i < SCORES_PER_GAME; i++) {
if (newScore > scores[i].score) {
insertIdx = i;
break;
}
}
if (insertIdx != -1) {
// Shift lower scores down
for (int8_t i = SCORES_PER_GAME - 1; i > insertIdx; i--) {
scores[i] = scores[i-1];
}
// Insert new score
scores[insertIdx].score = newScore;
strncpy(scores[insertIdx].name, name, 3);
scores[insertIdx].name[3] = '\0';
// Save back to EEPROM
uint16_t addr = SCORE_ADDR_BASE + (gameId * SCORE_BYTES_PER_GAME);
for (uint8_t i = 0; i < SCORES_PER_GAME; i++) {
eeprom_update_word((uint16_t*)addr, scores[i].score);
addr += 2;
eeprom_update_byte((uint8_t*)addr++, scores[i].name[0]);
eeprom_update_byte((uint8_t*)addr++, scores[i].name[1]);
eeprom_update_byte((uint8_t*)addr++, scores[i].name[2]);
wdt_reset(); // Feed watchdog during write
}
return true;
}
return false;
}