Menüausrichtung verbessert: Bei Eintritt ins Menü Vorauswahl möglichst weit
[hackover2013-badge-firmware.git] / badge / jumpnrun / starter.c
index 2e7eebf..bb69f2e 100644 (file)
@@ -1,40 +1,58 @@
 #include "jumpnrun.h"
 #include "../ui/menu.h"
+#include "../ui/browser.h"
 
 #include <drivers/fatfs/ff.h>
 
+#define CREDITS_FNAME  "credits.txt"
+#define POSITION_FNAME "selected.dat"
+#define PROGRESS_FNAME "progress.dat"
+
 enum {
   LEVELFILE_MAX        = 12,
   LEVELDESCRIPTION_MAX = 14,
   MENU_BUFLEN          = LEVELDESCRIPTION_MAX + 1 + LEVELFILE_MAX + 1
 };
 
-#define PROGRESS_FNAME "progress.dat"
+enum {
+  CHOICE_LEVEL,
+  CHOICE_CREDITS,
+  CHOICE_EXIT,
+  CHOICE_ERROR
+};
 
-static uint8_t jumpnrun_load_progress(void) {
-  uint8_t progress = 0;
+static uint8_t read_byte_from_file(char const *fname) {
   FIL fd;
+  uint8_t x = 0;
 
-  if(FR_OK == f_open(&fd, PROGRESS_FNAME, FA_OPEN_EXISTING | FA_READ)) {
+  if(FR_OK == f_chdir(JUMPNRUN_PATH) &&
+     FR_OK == f_open(&fd, fname, FA_OPEN_EXISTING | FA_READ)) {
     UINT bytes;
-    f_read(&fd, &progress, sizeof(progress), &bytes);
+    f_read(&fd, &x, sizeof(x), &bytes);
     f_close(&fd);
   }
 
-  return progress;
+  return x;
 }
 
-static void jumpnrun_save_progress(uint8_t progress) {
+static void save_byte_to_file(char const *fname, uint8_t x) {
   FIL fd;
 
-  if(FR_OK == f_open(&fd, PROGRESS_FNAME, FA_CREATE_ALWAYS | FA_WRITE)) {
+  if(FR_OK == f_chdir(JUMPNRUN_PATH) &&
+     FR_OK == f_open(&fd, fname, FA_CREATE_ALWAYS | FA_WRITE)) {
     UINT bytes;
-    f_write(&fd, &progress, sizeof(progress), &bytes);
+    f_write(&fd, &x, sizeof(x), &bytes);
     f_close(&fd);
   }
 }
 
-static uint8_t jumpnrun_pick_level_from_fd(char *buf, size_t *first_visible, size_t *selected, uint8_t progress, FIL *fd) {
+static uint8_t jumpnrun_load_selected(void            ) { return read_byte_from_file(POSITION_FNAME          ); }
+static void    jumpnrun_save_selected(uint8_t selected) {        save_byte_to_file  (POSITION_FNAME, selected); }
+
+static uint8_t jumpnrun_load_progress(void            ) { return read_byte_from_file(PROGRESS_FNAME          ); }
+static void    jumpnrun_save_progress(uint8_t progress) {        save_byte_to_file  (PROGRESS_FNAME, progress); }
+
+static uint8_t jumpnrun_pick_level_from_fd(char *buf, uint8_t *first_visible, uint8_t *selected, uint8_t progress, FIL *fd) {
   unsigned levelcount = 0;
 
   {
@@ -48,9 +66,11 @@ static uint8_t jumpnrun_pick_level_from_fd(char *buf, size_t *first_visible, siz
     return JUMPNRUN_ERROR;
   }
 
-  char menu_buf[levelcount][MENU_BUFLEN];
-  char const *menu_index[levelcount];
-  char const *fnames[levelcount];
+  uint8_t menulen   = levelcount + (levelcount <= progress) + 1;
+
+  char        menu_buf  [menulen][MENU_BUFLEN];
+  char const *menu_index[menulen];
+  char const *fnames    [menulen];
   unsigned i;
 
   for(i = 0; i < levelcount && f_gets(menu_buf[i], MENU_BUFLEN, fd); ++i) {
@@ -64,16 +84,43 @@ static uint8_t jumpnrun_pick_level_from_fd(char *buf, size_t *first_visible, siz
     fnames[i] = p;
   }
 
-  *selected = badge_menu(menu_index, i, first_visible, *selected);
+  uint8_t creditspos = -1;
+  uint8_t exitpos   = i;
+
+  if(levelcount <= progress) {
+    creditspos = i;
+    strcpy(menu_buf[creditspos], "Credits");
+    menu_index[creditspos] = menu_buf[creditspos];
+
+    ++exitpos;
+  }
 
-  strcpy(buf, fnames[*selected]);
-  return 0;
+  strcpy(menu_buf[exitpos], "Zurück");
+  menu_index[exitpos] = menu_buf[exitpos];
+
+  uint8_t choice = badge_menu(menu_index, exitpos + 1, first_visible, *selected);
+
+  if(choice == exitpos) {
+    return CHOICE_EXIT;
+  }
+
+  *selected = choice;
+
+  if(choice == creditspos) {
+    return CHOICE_CREDITS;
+  }
+
+  strncpy(buf, fnames[*selected], LEVELFILE_MAX);
+  buf[LEVELFILE_MAX] = '\0';
+
+  return CHOICE_LEVEL;
 }
 
-static uint8_t jumpnrun_pick_level(char *buf, size_t *first_visible, size_t *selected, uint8_t progress) {
+static uint8_t jumpnrun_pick_level(char *buf, uint8_t *first_visible, uint8_t *selected, uint8_t progress) {
   FIL fd;
 
-  if(FR_OK != f_open(&fd, "levels.lst", FA_OPEN_EXISTING | FA_READ)) {
+  if(FR_OK != f_chdir(JUMPNRUN_PATH) ||
+     FR_OK != f_open(&fd, "levels.lst", FA_OPEN_EXISTING | FA_READ)) {
     return JUMPNRUN_ERROR;
   }
 
@@ -85,15 +132,31 @@ static uint8_t jumpnrun_pick_level(char *buf, size_t *first_visible, size_t *sel
 }
 
 void jumpnrun_play(void) {
-  char buf[LEVELFILE_MAX + 1];
-  size_t first_visible = 0;
-  size_t selected = 0;
+  char    buf[LEVELFILE_MAX + 1];
+  uint8_t selected = jumpnrun_load_selected();
   uint8_t progress = jumpnrun_load_progress();
+  uint8_t first_visible = selected;
+  uint8_t choice;
+  uint8_t oldselected = selected;
+
+  do {
+    if(oldselected != selected) {
+      jumpnrun_save_selected((uint8_t) selected);
+      oldselected = selected;
+    }
 
-  while(0 == jumpnrun_pick_level(buf, &first_visible, &selected, progress)) {
-    if(JUMPNRUN_WON == jumpnrun_play_level(buf) && selected == progress) {
-      selected = ++progress;
-      jumpnrun_save_progress(progress);
+    choice = jumpnrun_pick_level(buf, &first_visible, &selected, progress);
+
+    switch(choice) {
+    case CHOICE_LEVEL:
+      if(JUMPNRUN_WON == jumpnrun_play_level(buf) && selected == progress) {
+        selected = ++progress;
+        jumpnrun_save_progress(progress);
+      }
+      break;
+    case CHOICE_CREDITS:
+      badge_browse_textfile(CREDITS_FNAME);
+      break;
     }
-  }
+  } while(choice != CHOICE_EXIT);
 }
This page took 0.022922 seconds and 4 git commands to generate.