10 #include "oglconsole.h"
13 /* Data stored to disk */
17 }__attribute__((packed
));
18 #define SCORE_FILE (DATADIR "/high-scores")
20 #define NR_HIGH_SCORES 10
21 #define HIGH_SCORES_SIZE (sizeof(struct high_score) * NR_HIGH_SCORES)
22 #define SCORE_VALID(sc) (sc.playername[0] != '\0')
24 /* .bss initialized on program startup */
25 static struct high_score
*high_scores
;
27 #define TEMPLATE DATADIR "/scores.XXXXXX"
30 rewrite_score_file(void)
34 int score_len
= sizeof(struct high_score
);
35 struct high_score
*cur
;
38 template = strdup(TEMPLATE
);
41 /* Write out the new scores to a tmp file */
43 fd
= mkstemp(template);
45 con_printf("Unable to write out new scores file.\n");
46 con_printf("mkstemp failed with %d\n", errno
);
49 ret
= fchmod(fd
, 0660);
51 con_printf("fchmod failed with %d\n", errno
);
53 for (i
= 0; i
< NR_HIGH_SCORES
; i
++) {
54 if (!SCORE_VALID(high_scores
[i
]))
56 ret
= write(fd
, &high_scores
[i
], score_len
);
57 if (ret
!= score_len
) {
58 if (ret
< 0 && errno
== EINTR
) {
62 cur
= &high_scores
[i
];
70 /* Move the tmp file into place */
71 ret
= rename(template, SCORE_FILE
);
73 con_printf("failed to move new scores file into place [%d]\n",
82 * The high scores list is pretty small, so it's just an array. Insertion
83 * is done by allocating a new array, and copying the old contents into it,
84 * inserting the score in its proper place. The last element falls off the
88 insert_score(char *name
, uint64_t score
, int slot
)
90 struct high_score
*new_high_scores
= malloc(HIGH_SCORES_SIZE
);
93 assert(new_high_scores
);
95 for (i
= 0, j
= 0; i
< NR_HIGH_SCORES
; i
++) {
97 new_high_scores
[i
].score
= score
;
98 strcpy(new_high_scores
[i
].playername
, name
);
101 new_high_scores
[i
] = high_scores
[j
];
106 high_scores
= new_high_scores
;
110 add_high_score(char *name
, uint64_t score
)
114 for (i
= 0; i
< NR_HIGH_SCORES
; i
++) {
115 if (score
> high_scores
[i
].score
) {
116 insert_score(name
, score
, i
);
123 high_score(uint64_t score
)
125 if (score
> high_scores
[NR_HIGH_SCORES
-1].score
)
131 flock_init(struct flock
*fl
, short type
)
133 memset(fl
, 0, sizeof(*fl
));
135 fl
->l_whence
= SEEK_SET
;
146 flock_init(&fl
, F_WRLCK
);
148 fd
= open(SCORE_FILE
, O_RDWR
);
150 con_printf("failed to open scores file!\n");
155 ret
= fcntl(fd
, F_SETLKW
, &fl
);
159 con_printf("failed to lock scores file!\n");
168 unlock_scores(score_lock_t lock
)
174 flock_init(&fl
, F_UNLCK
);
177 ret
= fcntl(fd
, F_SETLKW
, &fl
);
181 con_printf("Failed to release lock on scores file!\n");
188 debug_print_high_scores(void)
192 for (i
= 0; i
< NR_HIGH_SCORES
; i
++) {
193 if (!SCORE_VALID(high_scores
[i
]))
195 con_printf("%s -> %llu\n", high_scores
[i
].playername
,
196 high_scores
[i
].score
);
201 high_scores_init(void)
204 struct high_score score
;
205 int hs_size
= sizeof(struct high_score
);
207 fd
= open(SCORE_FILE
, O_CREAT
);
210 printf("Unable to open scores file.\n");
214 /* File is sorted from highest to lowest */
215 high_scores
= malloc(HIGH_SCORES_SIZE
);
216 memset(high_scores
, 0, HIGH_SCORES_SIZE
);
218 while ((ret
= read(fd
, &score
, hs_size
)) == hs_size
)
219 add_high_score(score
.playername
, score
.score
);