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