summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/menu.c
diff options
context:
space:
mode:
authorKarl Kurbjun <kkurbjun@gmail.com>2006-06-19 01:47:45 +0000
committerKarl Kurbjun <kkurbjun@gmail.com>2006-06-19 01:47:45 +0000
commit6952f03a7dfef2424164762ecd98fb128b7e44eb (patch)
tree2fa98afcc33e145d3c88417be24eb58a6f90cc9a /apps/plugins/rockboy/menu.c
parentdb8316fa52ed8eeb55136bc3aad2c98b25d249fb (diff)
downloadrockbox-6952f03a7dfef2424164762ecd98fb128b7e44eb.tar.gz
rockbox-6952f03a7dfef2424164762ecd98fb128b7e44eb.zip
Update for Rockboy: - fix scaling for other color screens than H300 - full menu rewrite to display choices properly - some small tweaks to code - some formatting updates
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10137 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/rockboy/menu.c')
-rw-r--r--apps/plugins/rockboy/menu.c783
1 files changed, 265 insertions, 518 deletions
diff --git a/apps/plugins/rockboy/menu.c b/apps/plugins/rockboy/menu.c
index 15f34582a6..e27be48e9b 100644
--- a/apps/plugins/rockboy/menu.c
+++ b/apps/plugins/rockboy/menu.c
@@ -4,8 +4,6 @@
4/* Note: this file only exposes one function: do_user_menu(). */ 4/* Note: this file only exposes one function: do_user_menu(). */
5/*********************************************************************/ 5/*********************************************************************/
6 6
7#include "stdlib.h"
8#include "string.h"
9#include "button.h" 7#include "button.h"
10#include "rockmacros.h" 8#include "rockmacros.h"
11#include "mem.h" 9#include "mem.h"
@@ -15,149 +13,68 @@
15#define MENU_BUTTON_DOWN BUTTON_SCROLL_FWD 13#define MENU_BUTTON_DOWN BUTTON_SCROLL_FWD
16#define MENU_BUTTON_LEFT BUTTON_LEFT 14#define MENU_BUTTON_LEFT BUTTON_LEFT
17#define MENU_BUTTON_RIGHT BUTTON_RIGHT 15#define MENU_BUTTON_RIGHT BUTTON_RIGHT
18#define MENU_BUTTON_CANCEL BUTTON_MENU
19#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 16#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
20#define MENU_BUTTON_UP BUTTON_UP 17#define MENU_BUTTON_UP BUTTON_UP
21#define MENU_BUTTON_DOWN BUTTON_DOWN 18#define MENU_BUTTON_DOWN BUTTON_DOWN
22#define MENU_BUTTON_LEFT BUTTON_LEFT 19#define MENU_BUTTON_LEFT BUTTON_LEFT
23#define MENU_BUTTON_RIGHT BUTTON_RIGHT 20#define MENU_BUTTON_RIGHT BUTTON_RIGHT
24#define MENU_BUTTON_CANCEL BUTTON_A
25#else 21#else
26#define MENU_BUTTON_UP BUTTON_UP 22#define MENU_BUTTON_UP BUTTON_UP
27#define MENU_BUTTON_DOWN BUTTON_DOWN 23#define MENU_BUTTON_DOWN BUTTON_DOWN
28#define MENU_BUTTON_LEFT BUTTON_LEFT 24#define MENU_BUTTON_LEFT BUTTON_LEFT
29#define MENU_BUTTON_RIGHT BUTTON_RIGHT 25#define MENU_BUTTON_RIGHT BUTTON_RIGHT
30#define MENU_BUTTON_CANCEL BUTTON_OFF
31#endif 26#endif
32 27
28void setvidmode(int);
29
33/* load/save state function declarations */ 30/* load/save state function declarations */
34static void do_slot_menu(bool is_load);
35static void do_opt_menu(void); 31static void do_opt_menu(void);
32static void do_slot_menu(bool is_load);
36static void munge_name(char *buf, size_t bufsiz); 33static void munge_name(char *buf, size_t bufsiz);
37 34
38/* directory ROM save slots belong in */ 35/* directory ROM save slots belong in */
39#define STATE_DIR "/.rockbox/rockboy" 36#define STATE_DIR "/.rockbox/rockboy"
40 37
41#define MENU_CANCEL (-1)
42static int do_menu(char *title, char **items, size_t num_items, int sel_item);
43
44/* main menu items */
45#define MAIN_MENU_TITLE "Rockboy"
46typedef enum {
47 MM_ITEM_BACK,
48 MM_ITEM_LOAD,
49 MM_ITEM_SAVE,
50 MM_ITEM_OPT,
51 MM_ITEM_QUIT,
52 MM_ITEM_LAST
53} MainMenuItem;
54
55/* strings for the main menu */
56static const char *main_menu[] = {
57 "Back to Game",
58 "Load State...",
59 "Save State...",
60 "Options...",
61 "Quit RockBoy"
62};
63
64typedef enum {
65 SM_ITEM_SLOT1,
66 SM_ITEM_SLOT2,
67 SM_ITEM_SLOT3,
68 SM_ITEM_SLOT4,
69 SM_ITEM_SLOT5,
70 SM_ITEM_FILE,
71 SM_ITEM_BACK,
72 SM_ITEM_LAST
73} SlotMenuItem;
74
75/* this semi-evil, but we snprintf() into these strings later
76 * Note: if you want more save slots, just add more lines
77 * to this array */
78static const char *slot_menu[] = {
79 "1. ",
80 "2. ",
81 "3. ",
82 "4. ",
83 "5. ",
84 "Save to File... ",
85 "Previous Menu... "
86};
87
88#define OPT_MENU_TITLE "Options"
89typedef enum {
90 OM_ITEM_FS,
91 OM_ITEM_SOUND,
92 OM_ITEM_STATS,
93 OM_ITEM_FULLSCREEN,
94 OM_ITEM_KEYS,
95 OM_ITEM_BACK,
96 OM_MENU_LAST
97} OptMenuItem;
98
99static const char *opt_menu[] = {
100 "Frameskip",
101 "Sound ON/OFF",
102 "Stats ON/OFF",
103 "Fullscreen ON/OFF",
104 "Set Keys (BUGGY)",
105 "Previous Menu..."
106};
107
108#define FS_MENU_TITLE "Frameskip"
109typedef enum {
110 FS_ITEM_FS0,
111 FS_ITEM_FS1,
112 FS_ITEM_FS2,
113 FS_ITEM_FS3,
114 FS_ITEM_BACK,
115 FS_MENU_LAST
116} FSMenuItem;
117
118static const char *fs_menu[] = {
119 "Frameskip 3 Max",
120 "Frameskip 4 Max",
121 "Frameskip 5 Max",
122 "Frameskip 7 Max",
123 "Previous Menu..."
124};
125
126int getbutton(char *text) 38int getbutton(char *text)
127{ 39{
128 rb->lcd_putsxy(0, 0, text); 40 rb->lcd_putsxy(0, 0, text);
129 rb->lcd_update(); 41 rb->lcd_update();
130 rb->sleep(30); 42 rb->sleep(30);
131 while (rb->button_get(false) != BUTTON_NONE) 43
132 rb->yield(); 44 while (rb->button_get(false) != BUTTON_NONE)
133 int button; 45 rb->yield();
134 while(true){ 46
135 button = rb->button_get(true); 47 int button;
136 button=button&0x00000FFF; 48 while(true)
137 switch(button) { 49 {
138 case MENU_BUTTON_LEFT: 50 button = rb->button_get(true);
139 case MENU_BUTTON_RIGHT: 51 button=button&0x00000FFF;
140 case MENU_BUTTON_UP: 52
141 case MENU_BUTTON_DOWN: 53 switch(button)
142 break; 54 {
143 default: 55 case MENU_BUTTON_LEFT:
144 return button; 56 case MENU_BUTTON_RIGHT:
145 break; 57 case MENU_BUTTON_UP:
146 } 58 case MENU_BUTTON_DOWN:
147 } 59 break;
60 default:
61 return button;
62 break;
63 }
64 }
148} 65}
149 66
150void setupkeys(void) 67void setupkeys(void)
151{ 68{
152 options.A=getbutton("Press A"); 69 options.A=getbutton("Press A");
153 70
154 options.B=getbutton("Press B"); 71 options.B=getbutton("Press B");
155 72
156 options.START=getbutton("Press Start"); 73 options.START=getbutton("Press Start");
157 74
158 options.SELECT=getbutton("Press Select"); 75 options.SELECT=getbutton("Press Select");
159 76
160 options.MENU=getbutton("Press Menu"); 77 options.MENU=getbutton("Press Menu");
161} 78}
162 79
163/* 80/*
@@ -165,67 +82,74 @@ void setupkeys(void)
165 * 82 *
166 * Returns USER_MENU_QUIT if the user selected "quit", otherwise 83 * Returns USER_MENU_QUIT if the user selected "quit", otherwise
167 * returns zero. 84 * returns zero.
168 *
169 * Note: this is the only non-static function in this file at the
170 * moment. In the future I may turn do_menu/etc into a proper API, in
171 * which case they'll be exposed as well.
172 *
173 */ 85 */
174int do_user_menu(void) { 86int do_user_menu(void) {
175 int mi, ret, num_items; 87 bool done=false;
176 bool done = false; 88 int m, ret=0;
89 int result;
90
91 /* Clean out the button Queue */
92 while (rb->button_get(false) != BUTTON_NONE)
93 rb->yield();
94
95 static const struct menu_item items[] = {
96 {"Load Game", NULL },
97 {"Save Game", NULL },
98 {"Options", NULL },
99 {"Quit", NULL },
100 };
101
102 pcm_init();
103
104 m = rb->menu_init(items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL);
105
106 while(!done)
107 {
108 result=rb->menu_show(m);
109
110 switch (result)
111 {
112 case 0: /* Load Game */
113 do_slot_menu(true);
114 break;
115 case 1: /* Save Game */
116 do_slot_menu(false);
117 break;
118 case 2: /* Options */
119 do_opt_menu();
120 break;
121 case 3: /* Quit */
122 ret = USER_MENU_QUIT;
123 done=true;
124 break;
125 default:
126 done=true;
127 break;
128 }
129 }
177 130
178 pcm_init(); 131 rb->menu_exit(m);
179 132
180 /* set defaults */ 133 rb->lcd_setfont(0); /* Reset the font */
181 ret = 0; /* return value */ 134 rb->lcd_clear_display(); /* Clear display for screen size changes */
182 mi = 0; /* initial menu selection */ 135
183 num_items = sizeof(main_menu) / sizeof(char*); 136 return ret;
184
185 /* loop until we should exit menu */
186 while (!done) {
187 /* get item selection */
188 mi = do_menu(MAIN_MENU_TITLE, (char**) main_menu, num_items, mi);
189
190 /* handle selected menu item */
191 switch (mi) {
192 case MM_ITEM_QUIT:
193 ret = USER_MENU_QUIT;
194 case MENU_CANCEL:
195 case MM_ITEM_BACK:
196 done = true;
197 break;
198 case MM_ITEM_LOAD:
199 do_slot_menu(true);
200 break;
201 case MM_ITEM_SAVE:
202 do_slot_menu(false);
203 break;
204 case MM_ITEM_OPT:
205 do_opt_menu();
206 break;
207 }
208 }
209 rb->lcd_clear_display();
210 rb->lcd_update();
211 /* return somethin' */
212 return ret;
213} 137}
214 138
215/* 139/*
216 * munge_name - munge a string into a filesystem-safe name 140 * munge_name - munge a string into a filesystem-safe name
217 */ 141 */
218static void munge_name(char *buf, const size_t bufsiz) { 142static void munge_name(char *buf, const size_t bufsiz) {
219 unsigned int i, max; 143 unsigned int i, max;
220 144
221 /* check strlen */ 145 /* check strlen */
222 max = strlen(buf); 146 max = strlen(buf);
223 max = (max < bufsiz) ? max : bufsiz; 147 max = (max < bufsiz) ? max : bufsiz;
224 148
225 /* iterate over characters and munge them (if necessary) */ 149 /* iterate over characters and munge them (if necessary) */
226 for (i = 0; i < max; i++) 150 for (i = 0; i < max; i++)
227 if (!isalnum(buf[i])) 151 if (!isalnum(buf[i]))
228 buf[i] = '_'; 152 buf[i] = '_';
229} 153}
230 154
231/* 155/*
@@ -235,15 +159,15 @@ static void munge_name(char *buf, const size_t bufsiz) {
235 * checksum or something like that? 159 * checksum or something like that?
236 */ 160 */
237static void build_slot_path(char *buf, size_t bufsiz, size_t slot_id) { 161static void build_slot_path(char *buf, size_t bufsiz, size_t slot_id) {
238 char name_buf[40]; 162 char name_buf[40];
239 163
240 /* munge state file name */ 164 /* munge state file name */
241 strncpy(name_buf, rom.name, sizeof(name_buf)); 165 strncpy(name_buf, rom.name, 40);
242 name_buf[16] = '\0'; 166 name_buf[16] = '\0';
243 munge_name(name_buf, strlen(name_buf)); 167 munge_name(name_buf, strlen(name_buf));
244 168
245 /* glom the whole mess together */ 169 /* glom the whole mess together */
246 snprintf(buf, bufsiz, "%s/%s-%d.rbs", STATE_DIR, name_buf, slot_id + 1); 170 snprintf(buf, bufsiz, "%s/%s-%d.rbs", STATE_DIR, name_buf, slot_id + 1);
247} 171}
248 172
249/* 173/*
@@ -256,43 +180,46 @@ static void build_slot_path(char *buf, size_t bufsiz, size_t slot_id) {
256 * 180 *
257 */ 181 */
258static bool do_file(char *path, char *desc, bool is_load) { 182static bool do_file(char *path, char *desc, bool is_load) {
259 char buf[200], desc_buf[20]; 183 char buf[200], desc_buf[20];
260 int fd, file_mode; 184 int fd, file_mode;
261 185
262 /* set file mode */ 186 /* set file mode */
263 file_mode = is_load ? O_RDONLY : (O_WRONLY | O_CREAT); 187 file_mode = is_load ? O_RDONLY : (O_WRONLY | O_CREAT);
264 188
265 /* attempt to open file descriptor here */ 189 /* attempt to open file descriptor here */
266 if ((fd = open(path, file_mode)) <= 0) 190 if ((fd = open(path, file_mode)) <= 0)
267 return false; 191 return false;
268 192
269 /* load/save state */ 193 /* load/save state */
270 if (is_load) { 194 if (is_load)
271 /* load description */ 195 {
272 read(fd, desc_buf, 20); 196 /* load description */
273 197 read(fd, desc_buf, 20);
274 /* load state */ 198
275 loadstate(fd); 199 /* load state */
276 200 loadstate(fd);
277 /* print out a status message so the user knows the state loaded */ 201
278 snprintf(buf, sizeof(buf), "Loaded state from \"%s\"", path); 202 /* print out a status message so the user knows the state loaded */
279 rb->splash(HZ * 1, true, buf); 203 snprintf(buf, 200, "Loaded state from \"%s\"", path);
280 } else { 204 rb->splash(HZ * 1, true, buf);
281 /* build description buffer */ 205 }
282 memset(desc_buf, 0, sizeof(desc_buf)); 206 else
283 if (desc) 207 {
284 strncpy(desc_buf, desc, sizeof(desc_buf)); 208 /* build description buffer */
285 209 memset(desc_buf, 0, 20);
286 /* save state */ 210 if (desc)
287 write(fd, desc_buf, 20); 211 strncpy(desc_buf, desc, 20);
288 savestate(fd); 212
289 } 213 /* save state */
290 214 write(fd, desc_buf, 20);
291 /* close file descriptor */ 215 savestate(fd);
292 close(fd); 216 }
293 217
294 /* return true (for success) */ 218 /* close file descriptor */
295 return true; 219 close(fd);
220
221 /* return true (for success) */
222 return true;
296} 223}
297 224
298/* 225/*
@@ -301,339 +228,159 @@ static bool do_file(char *path, char *desc, bool is_load) {
301 * Returns true on success and false on failure. 228 * Returns true on success and false on failure.
302 */ 229 */
303static bool do_slot(size_t slot_id, bool is_load) { 230static bool do_slot(size_t slot_id, bool is_load) {
304 char path_buf[256], desc_buf[20]; 231 char path_buf[256], desc_buf[20];
305 232
306 /* build slot filename, clear desc buf */ 233 /* build slot filename, clear desc buf */
307 build_slot_path(path_buf, sizeof(path_buf), slot_id); 234 build_slot_path(path_buf, 256, slot_id);
308 memset(desc_buf, 0, sizeof(desc_buf)); 235 memset(desc_buf, 0, 20);
309 236
310 /* if we're saving to a slot, then get a brief description */ 237 /* if we're saving to a slot, then get a brief description */
311 if (!is_load) { 238 if (!is_load)
312 if (rb->kbd_input(desc_buf, sizeof(desc_buf)) || !strlen(desc_buf)) { 239 if (rb->kbd_input(desc_buf, 20) || !strlen(desc_buf))
313 memset(desc_buf, 0, sizeof(desc_buf)); 240 {
314 strncpy(desc_buf, "Untitled", sizeof(desc_buf)); 241 memset(desc_buf, 0, 20);
315 } 242 strncpy(desc_buf, "Untitled", 20);
316 } 243 }
317 244
318 /* load/save file */ 245 /* load/save file */
319 return do_file(path_buf, desc_buf, is_load); 246 return do_file(path_buf, desc_buf, is_load);
320} 247}
321 248
322/* 249/*
323 * get information on the given slot 250 * get information on the given slot
324 */ 251 */
325static void slot_info(char *info_buf, size_t info_bufsiz, size_t slot_id) { 252static void slot_info(char *info_buf, size_t info_bufsiz, size_t slot_id) {
326 char buf[256]; 253 char buf[256];
327 int fd; 254 int fd;
328 255
329 /* get slot file path */ 256 /* get slot file path */
330 build_slot_path(buf, sizeof(buf), slot_id); 257 build_slot_path(buf, 256, slot_id);
331 258
332 /* attempt to open slot */ 259 /* attempt to open slot */
333 if ((fd = open(buf, O_RDONLY)) >= 0) { 260 if ((fd = open(buf, O_RDONLY)) >= 0)
334 /* this slot has a some data in it, read it */ 261 {
335 if (read(fd, buf, 20) > 0) { 262 /* this slot has a some data in it, read it */
336 buf[20] = '\0'; 263 if (read(fd, buf, 20) > 0)
337 snprintf(info_buf, info_bufsiz, "%2d. %s", slot_id + 1, buf); 264 {
338 } else { 265 buf[20] = '\0';
339 snprintf(info_buf, info_bufsiz, "%2d. ERROR", slot_id + 1); 266 snprintf(info_buf, info_bufsiz, "%d. %s", slot_id + 1, buf);
267 }
268 else
269 snprintf(info_buf, info_bufsiz, "%d. ERROR", slot_id + 1);
270
271 close(fd);
272 }
273 else
274 {
275 /* if we couldn't open the file, then the slot is empty */
276 snprintf(info_buf, info_bufsiz, "%d. %s", slot_id + 1, "<Empty>");
340 } 277 }
341 close(fd);
342 } else {
343 /* if we couldn't open the file, then the slot is empty */
344 snprintf(info_buf, info_bufsiz, "%2d.", slot_id + 1);
345 }
346} 278}
347 279
348/* 280/*
349 * do_slot_menu - prompt the user for a load/save memory slot 281 * do_slot_menu - prompt the user for a load/save memory slot
350 */ 282 */
351static void do_slot_menu(bool is_load) { 283static void do_slot_menu(bool is_load) {
352 int i, mi, ret, num_items; 284 bool done=false;
353 bool done = false;
354 char *title, buf[256];
355
356 /* set defaults */
357 ret = 0; /* return value */
358 mi = 0; /* initial menu selection */
359 num_items = sizeof(slot_menu) / sizeof(char*);
360
361 /* create menu items (the last two are file and previous menu,
362 * so don't populate those) */
363 for (i = 0; i < num_items - 2; i++)
364 slot_info((char*) slot_menu[i], 20, i);
365
366 /* set text of file item */
367 snprintf((char*) slot_menu[SM_ITEM_FILE], 20, "%s File...", is_load ? "Load from" : "Save to");
368
369 /* set menu title */
370 title = is_load ? "Load State" : "Save State";
371
372 /* loop until we should exit menu */
373 while (!done) {
374 /* get item selection */
375 mi = do_menu(title, (char**) slot_menu, num_items, mi);
376
377 /* handle selected menu item */
378 done = true;
379 if (mi != MENU_CANCEL && mi != SM_ITEM_BACK) {
380 if (mi == SM_ITEM_FILE) {
381 char rom_name_buf[40];
382
383 /* munge rom name to valid filename */
384 strncpy(rom_name_buf, rom.name, 16);
385 munge_name(rom_name_buf, sizeof(rom_name_buf));
386
387 /* create default filename */
388 snprintf(buf, sizeof(buf), "/%s.rbs", rom_name_buf);
389
390 /* prompt for output filename, save to file */
391 if (!rb->kbd_input(buf, sizeof(buf)))
392 done = do_file(buf, NULL, is_load);
393 } else {
394 done = do_slot(mi, is_load);
395 }
396
397 /* if we couldn't save the state file, then print out an
398 * error message */
399 if (!is_load && !done)
400 rb->splash(HZ * 2, true, "Couldn't save state file.");
401 }
402 }
403}
404 285
405static void do_fs_menu(void) { 286 char buf[5][20];
406 int mi, ret, num_items;
407 bool done = false;
408 287
409 /* set defaults */ 288 int m;
410 ret = 0; /* return value */ 289 int result;
411 mi = 0; /* initial menu selection */ 290 int i;
412 num_items = sizeof(fs_menu) / sizeof(char*);
413
414 /* loop until we should exit menu */
415 while (!done) {
416 /* get item selection */
417 mi = do_menu(FS_MENU_TITLE, (char**) fs_menu, num_items, mi);
418
419 /* handle selected menu item */
420 switch (mi) {
421 case MENU_CANCEL:
422 case FS_ITEM_BACK:
423 done = true;
424 break;
425 case FS_ITEM_FS0:
426 options.maxskip=3;
427 break;
428 case FS_ITEM_FS1:
429 options.maxskip=4;
430 break;
431 case FS_ITEM_FS2:
432 options.maxskip=5;
433 break;
434 case FS_ITEM_FS3:
435 options.maxskip=7;
436 break;
437 }
438 }
439}
440 291
441static void do_opt_menu(void) { 292 struct menu_item items[] = {
442 int mi, num_items; 293 { buf[0] , NULL },
443 bool done = false; 294 { buf[1] , NULL },
295 { buf[2] , NULL },
296 { buf[3] , NULL },
297 { buf[4] , NULL },
298 };
444 299
445 /* set a couple of defaults */ 300 int num_items = sizeof(items) / sizeof(*items);
446 num_items = sizeof(opt_menu) / sizeof(char*);
447 mi = 0;
448
449 while (!done) {
450 mi = do_menu(OPT_MENU_TITLE, (char**) opt_menu, num_items, mi);
451 switch (mi) {
452 case OM_ITEM_FS:
453 do_fs_menu();
454 break;
455 case OM_ITEM_SOUND:
456 options.sound=!options.sound;
457 break;
458 case OM_ITEM_STATS:
459 options.showstats=!options.showstats;
460 break;
461 case OM_ITEM_FULLSCREEN:
462 options.fullscreen=!options.fullscreen;
463 break;
464 case OM_ITEM_KEYS:
465 setupkeys();
466 break;
467 case MENU_CANCEL:
468 case OM_ITEM_BACK:
469 done = true;
470 break;
471 }
472 }
473}
474 301
475/*********************************************************************/ 302 /* create menu items */
476/* MENU FUNCTIONS */ 303 for (i = 0; i < num_items; i++)
477/*********************************************************************/ 304 slot_info(buf[i], 20, i);
478/* at some point i'll make this a generic menu interface, but for now,
479 * these defines will suffice */
480#define MENU_X 10
481#define MENU_Y 8
482#define MENU_WIDTH (LCD_WIDTH - 2 * MENU_X)
483#define MENU_HEIGHT (LCD_HEIGHT - 2 * MENU_Y)
484#define MENU_RECT MENU_X, MENU_Y, MENU_WIDTH, MENU_HEIGHT
485#define SHADOW_RECT MENU_X + 1, MENU_Y + 1, MENU_WIDTH, MENU_HEIGHT
486#define MENU_ITEM_PAD 2
487
488/*
489 * select_item - select menu item (after deselecting current item)
490 */
491static void select_item(char *title, int curr_item, size_t item_i) {
492 int x, y, w, h;
493
494 /* get size of title, use that as height ofr all lines */
495 rb->lcd_getstringsize(title, &w, &h);
496 h += MENU_ITEM_PAD * 2;
497
498 /* calc x and width */
499 x = MENU_X + MENU_ITEM_PAD;
500 w = MENU_WIDTH - 2 * MENU_ITEM_PAD;
501
502 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
503 /* if there is a current item, then deselect it */
504 if (curr_item >= 0) {
505 /* deselect old item */
506 y = MENU_Y + h + MENU_ITEM_PAD * 2; /* account for title */
507 y += h * curr_item;
508 rb->lcd_fillrect(x, y, w, h);
509 }
510
511 /* select new item */
512 curr_item = item_i;
513
514 /* select new item */
515 y = MENU_Y + h + MENU_ITEM_PAD * 2; /* account for title */
516 y += h * curr_item;
517 rb->lcd_fillrect(x, y, w, h);
518 rb->lcd_set_drawmode(DRMODE_SOLID);
519
520 /* update the menu window */
521 rb->lcd_update_rect(MENU_RECT);
522}
523
524/*
525 * draw_menu - draw menu on screen
526 *
527 * Returns MENU_CANCEL if the user cancelled, or the item number of the
528 * selected item.
529 *
530 */
531static void draw_menu(char *title, char **items, size_t num_items) {
532 size_t i;
533 int x, y, w, h, by;
534 305
535 /* set to default? font */ 306 m = rb->menu_init(items, num_items, NULL, NULL, NULL, NULL);
536 rb->lcd_setfont(0);
537
538 /* draw the outline */
539 rb->lcd_fillrect(SHADOW_RECT);
540 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
541 rb->lcd_fillrect(MENU_RECT);
542 rb->lcd_set_drawmode(DRMODE_SOLID);
543 rb->lcd_drawrect(MENU_RECT);
544
545 /* calculate x/y */
546 x = MENU_X + MENU_ITEM_PAD;
547 y = MENU_Y + MENU_ITEM_PAD * 2;
548 rb->lcd_getstringsize(title, &w, &h);
549 h += MENU_ITEM_PAD * 2;
550
551 /* draw menu stipple */
552 for (i = MENU_Y; i < (size_t) y + h; i += 2)
553 rb->lcd_drawline(MENU_X, i, MENU_X + MENU_WIDTH, i);
554
555 /* clear title rect */
556 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
557 rb->lcd_fillrect((LCD_WIDTH - w) / 2 - 2, y - 2, w + 4, h);
558 rb->lcd_set_drawmode(DRMODE_SOLID);
559
560 /* draw centered title on screen */
561 rb->lcd_putsxy((LCD_WIDTH - w)/2, y, title);
562
563 /* calculate base Y for items */
564 by = y + h + MENU_ITEM_PAD;
565
566 /* iterate over each item and draw it on the screen */
567 for (i = 0; i < num_items; i++)
568 rb->lcd_putsxy(x, by + h * i, items[i]);
569 307
570 /* update the screen */ 308 while(!done)
571 rb->lcd_update(); 309 {
310 result=rb->menu_show(m);
311
312 if (result<num_items && result >= 0 )
313 done = do_slot(result, is_load);
314 else
315 done = true;
316 }
317 rb->menu_exit(m);
572} 318}
573 319
574/* 320static void do_opt_menu(void)
575 * do_menu - draw menu on screen. 321{
576 * 322 bool done=false;
577 * Draw a menu titled @title on the screen, with @num_items elements 323 int m;
578 * from @items, and select the @sel element. If in doubt, set @sel to 324 int result;
579 * -1 :). 325
580 * 326 static const struct opt_items onoff[2] = {
581 */ 327 { "Off", NULL },
582static int do_menu(char *title, char **items, size_t num_items, int sel) { 328 { "On" , NULL },
583 int btn, sel_item, ret, curr_item; 329 };
584 bool done = false; 330
585 ret = MENU_CANCEL; 331 static const struct opt_items fullscreen[]= {
586 332 { "Off", NULL },
587 /* draw menu on screen and select the first item */ 333 { "Fullscreen", NULL },
588 draw_menu(title, items, num_items); 334 { "Full - Maintain Ratio", NULL },
589 curr_item = -1; 335 };
590 select_item(title, curr_item, sel); 336
591 curr_item = sel; 337 static const struct opt_items frameskip[]= {
592 338 { "3 Max", NULL },
593 /* make sure button state is empty */ 339 { "4 Max", NULL },
594 while (rb->button_get(false) != BUTTON_NONE) 340 { "5 Max", NULL },
595 rb->yield(); 341 { "6 Max", NULL },
596 342 };
597 /* loop until the menu is finished */ 343
598 while (!done) { 344 static const struct menu_item items[] = {
599 /* grab a button */ 345 {"Max Frameskip", NULL },
600 btn = rb->button_get(true); 346 {"Sound" , NULL },
601 347 {"Stats" , NULL },
602 /* handle the button */ 348 {"Fullscreen" , NULL },
603 switch (btn) { 349 {"Set Keys (Buggy)", NULL },
604 case MENU_BUTTON_DOWN: 350 };
605 /* select next item in list */ 351
606 sel_item = curr_item + 1; 352 m = rb->menu_init(items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL);
607 if (sel_item >= (int) num_items) 353
608 sel_item = 0; 354 while(!done)
609 select_item(title, curr_item, sel_item); 355 {
610 curr_item = sel_item; 356
611 break; 357 result=rb->menu_show(m);
612 case MENU_BUTTON_UP:
613 /* select prev item in list */
614 sel_item = curr_item - 1;
615 if (sel_item < 0)
616 sel_item = num_items - 1;
617 select_item(title, curr_item, sel_item);
618 curr_item = sel_item;
619 break;
620 case MENU_BUTTON_RIGHT:
621 /* select current item */
622 ret = curr_item;
623 done = true;
624 break;
625 case MENU_BUTTON_LEFT:
626 case MENU_BUTTON_CANCEL:
627 /* cancel out of menu */
628 ret = MENU_CANCEL;
629 done = true;
630 break;
631 }
632 358
633 /* give the OS some love */ 359 switch (result)
634 rb->yield(); 360 {
635 } 361 case 0: /* Frameskip */
636 362 options.maxskip-=3;
637 /* return selected item */ 363 rb->set_option(items[0].desc, &options.maxskip, INT, frameskip, 4, NULL );
638 return ret; 364 options.maxskip+=3;
365 break;
366 case 1: /* Sound */
367 if(options.sound>1) options.sound=1;
368 rb->set_option(items[1].desc, &options.sound, INT, onoff, 2, NULL );
369 break;
370 case 2: /* Stats */
371 rb->set_option(items[2].desc, &options.showstats, INT, onoff, 2, NULL );
372 break;
373 case 3: /* Fullscreen */
374 rb->set_option(items[3].desc, &options.fullscreen, INT, fullscreen, 3, NULL );
375 setvidmode(options.fullscreen);
376 break;
377 case 4: /* Keys */
378 setupkeys();
379 break;
380 default:
381 done=true;
382 break;
383 }
384 }
385 rb->menu_exit(m);
639} 386}