Schrift fest in Firmware eingebacken, damit die auch funktioniert, wenn auf dem
[hackover2013-badge-firmware.git] / badge / jumpnrun / starter.c
1 #include "jumpnrun.h"
2 #include "../ui/menu.h"
3 #include "../ui/browser.h"
4
5 #include <drivers/fatfs/ff.h>
6
7 #define CREDITS_FNAME "credits.txt"
8 #define POSITION_FNAME "selected.dat"
9 #define PROGRESS_FNAME "progress.dat"
10
11 enum {
12 LEVELFILE_MAX = 12,
13 LEVELDESCRIPTION_MAX = 14,
14 MENU_BUFLEN = LEVELDESCRIPTION_MAX + 1 + LEVELFILE_MAX + 1
15 };
16
17 enum {
18 CHOICE_LEVEL,
19 CHOICE_CREDITS,
20 CHOICE_EXIT,
21 CHOICE_ERROR
22 };
23
24 static uint8_t read_byte_from_file(char const *fname) {
25 FIL fd;
26 uint8_t x = 0;
27
28 if(FR_OK == f_chdir(JUMPNRUN_PATH) &&
29 FR_OK == f_open(&fd, fname, FA_OPEN_EXISTING | FA_READ)) {
30 UINT bytes;
31 f_read(&fd, &x, sizeof(x), &bytes);
32 f_close(&fd);
33 }
34
35 return x;
36 }
37
38 static void save_byte_to_file(char const *fname, uint8_t x) {
39 FIL fd;
40
41 if(FR_OK == f_chdir(JUMPNRUN_PATH) &&
42 FR_OK == f_open(&fd, fname, FA_CREATE_ALWAYS | FA_WRITE)) {
43 UINT bytes;
44 f_write(&fd, &x, sizeof(x), &bytes);
45 f_close(&fd);
46 }
47 }
48
49 static uint8_t jumpnrun_load_selected(void ) { return read_byte_from_file(POSITION_FNAME ); }
50 static void jumpnrun_save_selected(uint8_t selected) { save_byte_to_file (POSITION_FNAME, selected); }
51
52 static uint8_t jumpnrun_load_progress(void ) { return read_byte_from_file(PROGRESS_FNAME ); }
53 static void jumpnrun_save_progress(uint8_t progress) { save_byte_to_file (PROGRESS_FNAME, progress); }
54
55 static uint8_t jumpnrun_pick_level_from_fd(char *buf, uint8_t *first_visible, uint8_t *selected, uint8_t progress, FIL *fd) {
56 unsigned levelcount = 0;
57
58 {
59 char buf[MENU_BUFLEN];
60 while(f_gets(buf, MENU_BUFLEN, fd) && levelcount <= progress) {
61 ++levelcount;
62 }
63 }
64
65 if(FR_OK != f_lseek(fd, 0)) {
66 return JUMPNRUN_ERROR;
67 }
68
69 uint8_t menulen = levelcount + (levelcount <= progress) + 1;
70
71 char menu_buf [menulen][MENU_BUFLEN];
72 char const *menu_index[menulen];
73 char const *fnames [menulen];
74 unsigned i;
75
76 for(i = 0; i < levelcount && f_gets(menu_buf[i], MENU_BUFLEN, fd); ++i) {
77 menu_index[i] = menu_buf[i];
78 char *p;
79 for(p = menu_buf[i]; *p && *p != '|'; ++p)
80 ;
81 if(*p) {
82 *p++ = '\0';
83 }
84 fnames[i] = p;
85 }
86
87 uint8_t creditspos = -1;
88 uint8_t exitpos = i;
89
90 if(levelcount <= progress) {
91 creditspos = i;
92 strcpy(menu_buf[creditspos], "Credits");
93 menu_index[creditspos] = menu_buf[creditspos];
94
95 ++exitpos;
96 }
97
98 strcpy(menu_buf[exitpos], "Zurück");
99 menu_index[exitpos] = menu_buf[exitpos];
100
101 uint8_t choice = badge_menu(menu_index, exitpos + 1, first_visible, *selected);
102
103 if(choice == exitpos) {
104 return CHOICE_EXIT;
105 }
106
107 *selected = choice;
108
109 if(choice == creditspos) {
110 return CHOICE_CREDITS;
111 }
112
113 strncpy(buf, fnames[*selected], LEVELFILE_MAX);
114 buf[LEVELFILE_MAX] = '\0';
115
116 return CHOICE_LEVEL;
117 }
118
119 static uint8_t jumpnrun_pick_level(char *buf, uint8_t *first_visible, uint8_t *selected, uint8_t progress) {
120 FIL fd;
121
122 if(FR_OK != f_chdir(JUMPNRUN_PATH) ||
123 FR_OK != f_open(&fd, "levels.lst", FA_OPEN_EXISTING | FA_READ)) {
124 return JUMPNRUN_ERROR;
125 }
126
127 uint8_t err = jumpnrun_pick_level_from_fd(buf, first_visible, selected, progress, &fd);
128
129 f_close(&fd);
130
131 return err;
132 }
133
134 void jumpnrun_play(void) {
135 char buf[LEVELFILE_MAX + 1];
136 uint8_t selected = jumpnrun_load_selected();
137 uint8_t progress = jumpnrun_load_progress();
138 uint8_t first_visible = selected;
139 uint8_t choice;
140 uint8_t oldselected = selected;
141
142 do {
143 if(oldselected != selected) {
144 jumpnrun_save_selected((uint8_t) selected);
145 oldselected = selected;
146 }
147
148 choice = jumpnrun_pick_level(buf, &first_visible, &selected, progress);
149
150 switch(choice) {
151 case CHOICE_LEVEL:
152 if(JUMPNRUN_WON == jumpnrun_play_level(buf) && selected == progress) {
153 selected = ++progress;
154 jumpnrun_save_progress(progress);
155 }
156 break;
157 case CHOICE_CREDITS:
158 badge_browse_textfile(CREDITS_FNAME);
159 break;
160 }
161 } while(choice != CHOICE_EXIT);
162 }
This page took 0.048414 seconds and 5 git commands to generate.