keep scores and settings in SRAM
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 30 Oct 2022 18:45:04 +0000 (20:45 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 30 Oct 2022 18:45:04 +0000 (20:45 +0200)
src/gamescr.c
src/gba/main.c
src/menuscr.c
src/scoredb.c [new file with mode: 0644]
src/scoredb.h [new file with mode: 0644]

index 5b4786d..18ef9e5 100644 (file)
@@ -12,6 +12,7 @@
 #include "debug.h"
 #include "voxscape.h"
 #include "data.h"
+#include "scoredb.h"
 
 #define FOV            30
 #define NEAR   2
@@ -441,6 +442,10 @@ static void victory(void)
 {
        total_time = timer_msec - start_time;
        score = 42;
+
+       /* TODO enter name */
+       save_score("???", score, total_time, 0);
+       save_scores();
 }
 
 static inline void xform_pixel(int *xp, int *yp)
index 5240dff..4ade404 100644 (file)
@@ -7,6 +7,7 @@
 #include "input.h"
 #include "timer.h"
 #include "xgl.h"
+#include "scoredb.h"
 
 static void vblank(void);
 
@@ -35,13 +36,16 @@ int main(void)
        REG_DISPSTAT |= DISPSTAT_IEN_VBLANK;
        unmask(INTR_VBLANK);
 
+       load_scores();
+       gba_colors = scores[10].score & 1;
+
        xgl_init();
 
        if(init_screens() == -1) {
                panic(get_pc(), "failed to initialize screens");
        }
 
-       if(change_screen(find_screen("game")) == -1) {
+       if(change_screen(find_screen("logo")) == -1) {
                panic(get_pc(), "failed to find starting screen");
        }
 
index 43b9204..9185fa9 100644 (file)
@@ -6,6 +6,7 @@
 #include "input.h"
 #include "sprite.h"
 #include "debug.h"
+#include "scoredb.h"
 
 enum {
        MENU_START,
@@ -101,6 +102,8 @@ static void menuscr_frame(void)
        if((KEYPRESS(BN_LEFT) || KEYPRESS(BN_RIGHT)) && sel == MENU_COLORS) {
                gba_colors ^= 1;
                setup_palette();
+               scores[10].score = (scores[10].score & ~1) | (gba_colors & 1);
+               save_scores();
        }
 
        wait_vblank();
diff --git a/src/scoredb.c b/src/scoredb.c
new file mode 100644 (file)
index 0000000..28f88dc
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+Score-keeping for GBA with SRAM cartridge (originally part of gbatris)
+Copyright (C) 2019-2022  John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "scoredb.h"
+#include "debug.h"
+#include "gbaregs.h"
+
+#define MAGIC "VOXBURG1"
+#define SCORE_OFFS     8
+
+
+#define read_sram(offs, buf, sz) \
+       sramcpy(buf, (unsigned char*)SRAM_ADDR + (offs), sz)
+#define write_sram(offs, buf, sz) \
+       sramcpy((unsigned char*)SRAM_ADDR + (offs), buf, sz)
+
+static void sramcpy(void *dst, void *src, int size);
+
+int last_score_rank = -1;
+
+int load_scores(void)
+{
+       int i;
+       char magic[8];
+
+       read_sram(0, magic, 8);
+       if(memcmp(magic, MAGIC, sizeof magic) != 0) {
+               for(i=0; i<10; i++) {
+                       memcpy(scores[i].name, "----", NAME_SIZE + 1);
+               }
+               /* scores[10] keeps the last entered name. initialize it empty */
+               scores[10].name[0] = 0;
+               return -1;
+       }
+
+       read_sram(SCORE_OFFS, scores, sizeof scores);
+       return 0;
+}
+
+void save_scores(void)
+{
+       write_sram(0, MAGIC, 8);
+       write_sram(SCORE_OFFS, scores, sizeof scores);
+}
+
+void save_score(char *name, int score, int time, int level)
+{
+       int i, rank = -1;
+
+       if(!score) {
+               last_score_rank = -1;
+               return;
+       }
+
+       for(i=0; i<10; i++) {
+               if(scores[i].score <= score) {
+                       rank = i;
+                       break;
+               }
+       }
+       last_score_rank = rank;
+
+       if(rank == -1) return;
+
+       memmove(scores + rank + 1, scores + rank, (9 - rank) * sizeof(struct score_entry));
+
+       if(strlen(name) > NAME_SIZE) {
+               name[NAME_SIZE] = 0;
+       }
+       sprintf(scores[rank].name, "%s", name);
+       scores[rank].score = score;
+       scores[rank].time = time;
+       scores[rank].level = level;
+
+       /* also copy to the last entered name slot */
+       scores[10] = scores[rank];
+
+       save_scores();
+}
+
+int is_highscore(int score)
+{
+       return scores[9].score <= score;
+}
+
+static void sramcpy(void *dst, void *src, int size)
+{
+       unsigned char *sptr = src;
+       unsigned char *dptr = dst;
+       while(size-- > 0) {
+               *dptr++ = *sptr++;
+       }
+}
diff --git a/src/scoredb.h b/src/scoredb.h
new file mode 100644 (file)
index 0000000..63c0489
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Score-keeping for GBA with SRAM cartridge (originally part of gbatris)
+Copyright (C) 2019-2022  John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef SCOREDB_H_
+#define SCOREDB_H_
+
+#define NAME_SIZE      4
+
+struct score_entry {
+       char name[8];
+       uint32_t time;
+       uint16_t score;
+       uint8_t level, unused;
+} __attribute__((packed));
+
+/* last entry is used just to keep the last entered name
+ * and present it as a default choice in the highscore UI
+ */
+struct score_entry scores[11];
+
+int last_score_rank;
+
+int load_scores(void);
+void save_scores(void);
+void save_score(char *name, int score, int time, int level);
+int is_highscore(int score);
+
+#endif /* SCOREDB_H_ */