c7a4ff64 |
1 | // (c) Copyright 2006,2007 notaz, All rights reserved.\r |
2 | // Free for non-commercial use.\r |
3 | \r |
4 | // For commercial use, separate licencing terms must be obtained.\r |
5 | \r |
6 | #include <stdio.h>\r |
7 | #include <string.h>\r |
8 | #include <stdlib.h>\r |
9 | #include <stdarg.h>\r |
10 | \r |
11 | #include "menu.h"\r |
12 | #include "fonts.h"\r |
13 | #include "readpng.h"\r |
14 | #include "lprintf.h"\r |
b8464531 |
15 | #include "common.h"\r |
fce20e73 |
16 | #include "input.h"\r |
b8464531 |
17 | #include "emu.h"\r |
24b24674 |
18 | #include "plat.h"\r |
c7a4ff64 |
19 | \r |
24b24674 |
20 | #include <pico/patch.h>\r |
c7a4ff64 |
21 | \r |
f013066e |
22 | char menuErrorMsg[64] = { 0, };\r |
23 | \r |
367b6f1f |
24 | // PicoPad[] format: MXYZ SACB RLDU\r |
6589c840 |
25 | me_bind_action me_ctrl_actions[15] =\r |
367b6f1f |
26 | {\r |
6589c840 |
27 | { "UP ", 0x0001 },\r |
28 | { "DOWN ", 0x0002 },\r |
29 | { "LEFT ", 0x0004 },\r |
30 | { "RIGHT ", 0x0008 },\r |
31 | { "A ", 0x0040 },\r |
32 | { "B ", 0x0010 },\r |
33 | { "C ", 0x0020 },\r |
34 | { "A turbo", 0x4000 },\r |
35 | { "B turbo", 0x1000 },\r |
36 | { "C turbo", 0x2000 },\r |
37 | { "START ", 0x0080 },\r |
38 | { "MODE ", 0x0800 },\r |
39 | { "X ", 0x0400 },\r |
40 | { "Y ", 0x0200 },\r |
41 | { "Z ", 0x0100 }\r |
367b6f1f |
42 | };\r |
43 | \r |
44 | \r |
36f6fd5a |
45 | #ifndef UIQ3\r |
46 | \r |
c7a4ff64 |
47 | static unsigned char menu_font_data[10240];\r |
48 | static int menu_text_color = 0xffff; // default to white\r |
49 | static int menu_sel_color = -1; // disabled\r |
50 | \r |
51 | // draws text to current bbp16 screen\r |
52 | static void text_out16_(int x, int y, const char *text, int color)\r |
53 | {\r |
54 | int i, l, u, tr, tg, tb, len;\r |
55 | unsigned short *dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;\r |
56 | tr = (color & 0xf800) >> 8;\r |
57 | tg = (color & 0x07e0) >> 3;\r |
58 | tb = (color & 0x001f) << 3;\r |
59 | \r |
60 | if (text == (void *)1)\r |
61 | {\r |
62 | // selector symbol\r |
63 | text = "";\r |
64 | len = 1;\r |
65 | }\r |
66 | else\r |
67 | len = strlen(text);\r |
68 | \r |
69 | for (i = 0; i < len; i++)\r |
70 | {\r |
71 | unsigned char *src = menu_font_data + (unsigned int)text[i]*4*10;\r |
72 | unsigned short *dst = dest;\r |
73 | for (l = 0; l < 10; l++, dst += SCREEN_WIDTH-8)\r |
74 | {\r |
75 | for (u = 8/2; u > 0; u--, src++)\r |
76 | {\r |
77 | int c, r, g, b;\r |
78 | c = *src >> 4;\r |
79 | r = (*dst & 0xf800) >> 8;\r |
80 | g = (*dst & 0x07e0) >> 3;\r |
81 | b = (*dst & 0x001f) << 3;\r |
82 | r = (c^0xf)*r/15 + c*tr/15;\r |
83 | g = (c^0xf)*g/15 + c*tg/15;\r |
84 | b = (c^0xf)*b/15 + c*tb/15;\r |
85 | *dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);\r |
86 | c = *src & 0xf;\r |
87 | r = (*dst & 0xf800) >> 8;\r |
88 | g = (*dst & 0x07e0) >> 3;\r |
89 | b = (*dst & 0x001f) << 3;\r |
90 | r = (c^0xf)*r/15 + c*tr/15;\r |
91 | g = (c^0xf)*g/15 + c*tg/15;\r |
92 | b = (c^0xf)*b/15 + c*tb/15;\r |
93 | *dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);\r |
94 | }\r |
95 | }\r |
96 | dest += 8;\r |
97 | }\r |
98 | }\r |
99 | \r |
100 | void text_out16(int x, int y, const char *texto, ...)\r |
101 | {\r |
102 | va_list args;\r |
24b24674 |
103 | char buffer[256];\r |
104 | int maxw = (SCREEN_WIDTH - x) / 8;\r |
c7a4ff64 |
105 | \r |
24b24674 |
106 | va_start(args, texto);\r |
107 | vsnprintf(buffer, sizeof(buffer), texto, args);\r |
c7a4ff64 |
108 | va_end(args);\r |
109 | \r |
24b24674 |
110 | if (maxw > 255)\r |
111 | maxw = 255;\r |
112 | buffer[maxw] = 0;\r |
113 | \r |
c7a4ff64 |
114 | text_out16_(x,y,buffer,menu_text_color);\r |
115 | }\r |
116 | \r |
117 | \r |
118 | void smalltext_out16(int x, int y, const char *texto, int color)\r |
119 | {\r |
120 | int i;\r |
121 | unsigned char *src;\r |
122 | unsigned short *dst;\r |
123 | \r |
124 | for (i = 0;; i++, x += 6)\r |
125 | {\r |
126 | unsigned char c = (unsigned char) texto[i];\r |
127 | int h = 8;\r |
128 | \r |
129 | if (!c) break;\r |
130 | \r |
131 | src = fontdata6x8[c];\r |
132 | dst = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;\r |
133 | \r |
134 | while (h--)\r |
135 | {\r |
136 | int w = 0x20;\r |
137 | while (w)\r |
138 | {\r |
139 | if( *src & w ) *dst = color;\r |
140 | dst++;\r |
141 | w>>=1;\r |
142 | }\r |
143 | src++;\r |
144 | \r |
145 | dst += SCREEN_WIDTH-6;\r |
146 | }\r |
147 | }\r |
148 | }\r |
149 | \r |
150 | void smalltext_out16_lim(int x, int y, const char *texto, int color, int max)\r |
151 | {\r |
152 | char buffer[SCREEN_WIDTH/6+1];\r |
153 | \r |
154 | strncpy(buffer, texto, SCREEN_WIDTH/6);\r |
155 | if (max > SCREEN_WIDTH/6) max = SCREEN_WIDTH/6;\r |
156 | if (max < 0) max = 0;\r |
157 | buffer[max] = 0;\r |
158 | \r |
159 | smalltext_out16(x, y, buffer, color);\r |
160 | }\r |
161 | \r |
162 | void menu_draw_selection(int x, int y, int w)\r |
163 | {\r |
164 | int i, h;\r |
165 | unsigned short *dst, *dest;\r |
166 | \r |
167 | text_out16_(x, y, (void *)1, (menu_sel_color < 0) ? menu_text_color : menu_sel_color);\r |
168 | \r |
169 | if (menu_sel_color < 0) return; // no selection hilight\r |
170 | \r |
171 | if (y > 0) y--;\r |
172 | dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH + 14;\r |
173 | for (h = 11; h > 0; h--)\r |
174 | {\r |
175 | dst = dest;\r |
176 | for (i = w; i > 0; i--)\r |
177 | *dst++ = menu_sel_color;\r |
178 | dest += SCREEN_WIDTH;\r |
179 | }\r |
180 | }\r |
181 | \r |
182 | static int parse_hex_color(char *buff)\r |
183 | {\r |
184 | char *endp = buff;\r |
185 | int t = (int) strtoul(buff, &endp, 16);\r |
703e4c7b |
186 | if (endp != buff)\r |
187 | #ifdef PSP\r |
188 | return ((t<<8)&0xf800) | ((t>>5)&0x07e0) | ((t>>19)&0x1f);\r |
189 | #else\r |
190 | return ((t>>8)&0xf800) | ((t>>5)&0x07e0) | ((t>>3)&0x1f);\r |
191 | #endif\r |
c7a4ff64 |
192 | return -1;\r |
193 | }\r |
194 | \r |
195 | void menu_init(void)\r |
196 | {\r |
197 | int c, l;\r |
198 | unsigned char *fd = menu_font_data;\r |
199 | char buff[256];\r |
200 | FILE *f;\r |
201 | \r |
202 | // generate default font from fontdata8x8\r |
203 | memset(menu_font_data, 0, sizeof(menu_font_data));\r |
204 | for (c = 0; c < 256; c++)\r |
205 | {\r |
206 | for (l = 0; l < 8; l++)\r |
207 | {\r |
208 | unsigned char fd8x8 = fontdata8x8[c*8+l];\r |
209 | if (fd8x8&0x80) *fd |= 0xf0;\r |
210 | if (fd8x8&0x40) *fd |= 0x0f; fd++;\r |
211 | if (fd8x8&0x20) *fd |= 0xf0;\r |
212 | if (fd8x8&0x10) *fd |= 0x0f; fd++;\r |
213 | if (fd8x8&0x08) *fd |= 0xf0;\r |
214 | if (fd8x8&0x04) *fd |= 0x0f; fd++;\r |
215 | if (fd8x8&0x02) *fd |= 0xf0;\r |
216 | if (fd8x8&0x01) *fd |= 0x0f; fd++;\r |
217 | }\r |
218 | fd += 8*2/2; // 2 empty lines\r |
219 | }\r |
220 | \r |
221 | // load custom font and selector (stored as 1st symbol in font table)\r |
222 | readpng(menu_font_data, "skin/font.png", READPNG_FONT);\r |
223 | memcpy(menu_font_data, menu_font_data + ((int)'>')*4*10, 4*10); // default selector symbol is '>'\r |
224 | readpng(menu_font_data, "skin/selector.png", READPNG_SELECTOR);\r |
225 | \r |
226 | // load custom colors\r |
227 | f = fopen("skin/skin.txt", "r");\r |
228 | if (f != NULL)\r |
229 | {\r |
230 | lprintf("found skin.txt\n");\r |
231 | while (!feof(f))\r |
232 | {\r |
233 | fgets(buff, sizeof(buff), f);\r |
234 | if (buff[0] == '#' || buff[0] == '/') continue; // comment\r |
235 | if (buff[0] == '\r' || buff[0] == '\n') continue; // empty line\r |
236 | if (strncmp(buff, "text_color=", 11) == 0)\r |
237 | {\r |
238 | int tmp = parse_hex_color(buff+11);\r |
239 | if (tmp >= 0) menu_text_color = tmp;\r |
240 | else lprintf("skin.txt: parse error for text_color\n");\r |
241 | }\r |
242 | else if (strncmp(buff, "selection_color=", 16) == 0)\r |
243 | {\r |
244 | int tmp = parse_hex_color(buff+16);\r |
245 | if (tmp >= 0) menu_sel_color = tmp;\r |
246 | else lprintf("skin.txt: parse error for selection_color\n");\r |
247 | }\r |
248 | else\r |
249 | lprintf("skin.txt: parse error: %s\n", buff);\r |
250 | }\r |
251 | fclose(f);\r |
252 | }\r |
253 | }\r |
254 | \r |
255 | \r |
24b24674 |
256 | int me_id2offset(const menu_entry *ent, menu_id id)\r |
c7a4ff64 |
257 | {\r |
258 | int i;\r |
24b24674 |
259 | for (i = 0; ent->name; ent++, i++)\r |
260 | if (ent->id == id) return i;\r |
c7a4ff64 |
261 | \r |
262 | lprintf("%s: id %i not found\n", __FUNCTION__, id);\r |
263 | return 0;\r |
264 | }\r |
265 | \r |
24b24674 |
266 | void me_enable(menu_entry *entries, menu_id id, int enable)\r |
c7a4ff64 |
267 | {\r |
24b24674 |
268 | int i = me_id2offset(entries, id);\r |
c7a4ff64 |
269 | entries[i].enabled = enable;\r |
270 | }\r |
271 | \r |
24b24674 |
272 | int me_count(const menu_entry *ent)\r |
c7a4ff64 |
273 | {\r |
24b24674 |
274 | int ret;\r |
c7a4ff64 |
275 | \r |
24b24674 |
276 | for (ret = 0; ent->name; ent++, ret++)\r |
277 | ;\r |
c7a4ff64 |
278 | \r |
279 | return ret;\r |
280 | }\r |
281 | \r |
24b24674 |
282 | menu_id me_index2id(const menu_entry *ent, int index)\r |
c7a4ff64 |
283 | {\r |
24b24674 |
284 | const menu_entry *last;\r |
c7a4ff64 |
285 | \r |
24b24674 |
286 | for (; ent->name; ent++)\r |
c7a4ff64 |
287 | {\r |
24b24674 |
288 | if (ent->enabled)\r |
c7a4ff64 |
289 | {\r |
290 | if (index == 0) break;\r |
291 | index--;\r |
292 | }\r |
24b24674 |
293 | last = ent;\r |
c7a4ff64 |
294 | }\r |
24b24674 |
295 | if (ent->name == NULL)\r |
296 | ent = last;\r |
297 | return ent->id;\r |
c7a4ff64 |
298 | }\r |
299 | \r |
24b24674 |
300 | /* TODO rm */\r |
c7a4ff64 |
301 | void me_draw(const menu_entry *entries, int count, int x, int y, me_draw_custom_f *cust_draw, void *param)\r |
302 | {\r |
303 | int i, y1 = y;\r |
304 | \r |
305 | for (i = 0; i < count; i++)\r |
306 | {\r |
307 | if (!entries[i].enabled) continue;\r |
308 | if (entries[i].name == NULL)\r |
309 | {\r |
310 | if (cust_draw != NULL)\r |
311 | cust_draw(&entries[i], x, y1, param);\r |
312 | y1 += 10;\r |
313 | continue;\r |
314 | }\r |
315 | text_out16(x, y1, entries[i].name);\r |
24b24674 |
316 | if (entries[i].beh == MB_OPT_ONOFF)\r |
c7a4ff64 |
317 | text_out16(x + 27*8, y1, (*(int *)entries[i].var & entries[i].mask) ? "ON" : "OFF");\r |
24b24674 |
318 | else if (entries[i].beh == MB_OPT_RANGE)\r |
c7a4ff64 |
319 | text_out16(x + 27*8, y1, "%i", *(int *)entries[i].var);\r |
320 | y1 += 10;\r |
321 | }\r |
24b24674 |
322 | \r |
323 | }\r |
324 | \r |
325 | static void me_draw2(const menu_entry *entries, int sel)\r |
326 | {\r |
327 | const menu_entry *ent;\r |
328 | int x, y, w = 0, h = 0;\r |
329 | int opt_offs = 27*8;\r |
330 | const char *name;\r |
331 | int asel = 0;\r |
332 | int i, n;\r |
333 | \r |
334 | /* calculate size of menu rect */\r |
335 | for (ent = entries, i = n = 0; ent->name; ent++, i++)\r |
336 | {\r |
337 | int wt;\r |
338 | \r |
339 | if (!ent->enabled)\r |
340 | continue;\r |
341 | \r |
342 | if (i == sel)\r |
343 | asel = n;\r |
344 | \r |
345 | name = NULL;\r |
346 | wt = strlen(ent->name) * 8; /* FIXME: unhardcode font width */\r |
347 | if (wt == 0 && ent->generate_name)\r |
348 | name = ent->generate_name(1);\r |
349 | if (name != NULL)\r |
350 | wt = strlen(name) * 8;\r |
351 | \r |
352 | if (ent->beh != MB_NONE)\r |
353 | {\r |
354 | if (wt > opt_offs)\r |
355 | opt_offs = wt + 8;\r |
356 | wt = opt_offs;\r |
357 | \r |
358 | switch (ent->beh) {\r |
359 | case MB_NONE: break;\r |
360 | case MB_OPT_ONOFF:\r |
361 | case MB_OPT_RANGE: wt += 8*3; break;\r |
362 | case MB_OPT_CUSTOM:\r |
363 | name = NULL;\r |
364 | if (ent->generate_name != NULL)\r |
365 | name = ent->generate_name(0);\r |
366 | if (name != NULL)\r |
367 | wt += strlen(name) * 8;\r |
368 | break;\r |
369 | }\r |
370 | }\r |
371 | \r |
372 | if (wt > w)\r |
373 | w = wt;\r |
374 | n++;\r |
375 | }\r |
376 | h = n * 10;\r |
377 | w += 16; /* selector */\r |
378 | \r |
379 | if (w > SCREEN_WIDTH) {\r |
380 | lprintf("width %d > %d\n", w, SCREEN_WIDTH);\r |
381 | w = SCREEN_WIDTH;\r |
382 | }\r |
383 | if (h > SCREEN_HEIGHT) {\r |
384 | lprintf("height %d > %d\n", w, SCREEN_HEIGHT);\r |
385 | h = SCREEN_HEIGHT;\r |
386 | }\r |
387 | \r |
388 | x = SCREEN_WIDTH / 2 - w / 2;\r |
389 | y = SCREEN_HEIGHT / 2 - h / 2;\r |
390 | \r |
391 | /* draw */\r |
392 | plat_video_menu_begin();\r |
393 | menu_draw_selection(x, y + asel * 10, w);\r |
394 | \r |
395 | for (ent = entries; ent->name; ent++)\r |
396 | {\r |
397 | if (!ent->enabled)\r |
398 | continue;\r |
399 | \r |
400 | name = ent->name;\r |
401 | if (strlen(name) == 0) {\r |
402 | if (ent->generate_name)\r |
403 | name = ent->generate_name(1);\r |
404 | }\r |
405 | if (name != NULL)\r |
406 | text_out16(x + 16, y, name);\r |
407 | \r |
408 | switch (ent->beh) {\r |
409 | case MB_NONE:\r |
410 | break;\r |
411 | case MB_OPT_ONOFF:\r |
412 | text_out16(x + 16 + opt_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF");\r |
413 | break;\r |
414 | case MB_OPT_RANGE:\r |
415 | text_out16(x + 16 + opt_offs, y, "%i", *(int *)ent->var);\r |
416 | break;\r |
417 | case MB_OPT_CUSTOM:\r |
418 | name = NULL;\r |
419 | if (ent->generate_name)\r |
420 | name = ent->generate_name(0);\r |
421 | if (name != NULL)\r |
422 | text_out16(x + 16 + opt_offs, y, "%s", name);\r |
423 | break;\r |
424 | }\r |
425 | \r |
426 | y += 10;\r |
427 | }\r |
428 | \r |
429 | plat_video_menu_end();\r |
c7a4ff64 |
430 | }\r |
431 | \r |
24b24674 |
432 | int me_process(menu_entry *entries, menu_id id, int is_next)\r |
c7a4ff64 |
433 | {\r |
24b24674 |
434 | int i = me_id2offset(entries, id);\r |
c7a4ff64 |
435 | menu_entry *entry = &entries[i];\r |
436 | switch (entry->beh)\r |
437 | {\r |
24b24674 |
438 | case MB_OPT_ONOFF:\r |
c7a4ff64 |
439 | *(int *)entry->var ^= entry->mask;\r |
440 | return 1;\r |
24b24674 |
441 | case MB_OPT_RANGE:\r |
c7a4ff64 |
442 | *(int *)entry->var += is_next ? 1 : -1;\r |
443 | if (*(int *)entry->var < (int)entry->min) *(int *)entry->var = (int)entry->min;\r |
444 | if (*(int *)entry->var > (int)entry->max) *(int *)entry->var = (int)entry->max;\r |
445 | return 1;\r |
446 | default:\r |
447 | return 0;\r |
448 | }\r |
449 | }\r |
450 | \r |
24b24674 |
451 | static void me_loop(menu_entry *menu, int *menu_sel)\r |
452 | {\r |
453 | int ret, inp, sel = *menu_sel, menu_sel_max;\r |
454 | \r |
455 | menu_sel_max = me_count(menu) - 1;\r |
456 | if (menu_sel_max < 1) {\r |
457 | lprintf("no enabled menu entries\n");\r |
458 | return;\r |
459 | }\r |
460 | \r |
461 | while (!menu[sel].enabled && sel < menu_sel_max)\r |
462 | sel++;\r |
463 | \r |
464 | /* make sure action buttons are not pressed on entering menu */\r |
465 | me_draw2(menu, sel);\r |
466 | while (in_menu_wait_any(50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU));\r |
467 | \r |
468 | for (;;)\r |
469 | {\r |
470 | me_draw2(menu, sel);\r |
471 | inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_L|PBTN_R);\r |
472 | if (inp & PBTN_UP ) {\r |
473 | do {\r |
474 | sel--;\r |
475 | if (sel < 0)\r |
476 | sel = menu_sel_max;\r |
477 | }\r |
478 | while (!menu[sel].enabled);\r |
479 | }\r |
480 | if (inp & PBTN_DOWN) {\r |
481 | do {\r |
482 | sel++;\r |
483 | if (sel > menu_sel_max)\r |
484 | sel = 0;\r |
485 | }\r |
486 | while (!menu[sel].enabled);\r |
487 | }\r |
488 | // if ((inp & (PBTN_L|PBTN_R)) == (PBTN_L|PBTN_R)) debug_menu_loop(); // TODO\r |
489 | if (inp & (PBTN_MENU|PBTN_MBACK))\r |
490 | break;\r |
491 | \r |
492 | if (inp & PBTN_MOK)\r |
493 | {\r |
494 | if (menu[sel].submenu_handler != NULL) {\r |
495 | ret = menu[sel].submenu_handler(menu[sel].id);\r |
496 | if (ret) break;\r |
497 | }\r |
498 | }\r |
499 | // menuErrorMsg[0] = 0; // TODO: clear error msg\r |
500 | }\r |
501 | *menu_sel = sel;\r |
502 | }\r |
503 | \r |
504 | /* ***************************************** */\r |
505 | \r |
506 | /* TODO s */\r |
507 | int menu_loop_tray(void) { return 0; }\r |
508 | void menu_romload_prepare(const char *rom_name) {}\r |
509 | void menu_romload_end(void) {}\r |
510 | me_bind_action emuctrl_actions[1];\r |
511 | menu_entry opt_entries[1];\r |
512 | menu_entry opt2_entries[1];\r |
513 | menu_entry cdopt_entries[1];\r |
514 | menu_entry ctrlopt_entries[1];\r |
515 | const int opt_entry_count = 0;\r |
516 | const int opt2_entry_count = 0;\r |
517 | const int cdopt_entry_count = 0;\r |
518 | const int ctrlopt_entry_count = 0;\r |
519 | \r |
520 | extern int engineState;\r |
521 | \r |
522 | int savestate_menu_loop(int a) { return 1; }\r |
523 | int menu_loop_options() { return 1; }\r |
524 | void kc_sel_loop() {}\r |
525 | void draw_menu_credits() {}\r |
526 | void patches_menu_loop() {}\r |
527 | \r |
528 | // ------------ main menu ------------\r |
529 | \r |
530 | static int main_menu_handler(menu_id id)\r |
531 | {\r |
532 | int ret;\r |
533 | \r |
534 | switch (id)\r |
535 | {\r |
536 | case MA_MAIN_RESUME_GAME:\r |
537 | if (rom_loaded) {\r |
538 | while (in_menu_wait_any(50) & PBTN_MOK);\r |
539 | engineState = PGS_Running;\r |
540 | return 1;\r |
541 | }\r |
542 | break;\r |
543 | case MA_MAIN_SAVE_STATE:\r |
544 | if (rom_loaded) {\r |
545 | if (savestate_menu_loop(0))\r |
546 | break;\r |
547 | engineState = PGS_Running;\r |
548 | return 1;\r |
549 | }\r |
550 | break;\r |
551 | case MA_MAIN_LOAD_STATE:\r |
552 | if (rom_loaded) {\r |
553 | if (savestate_menu_loop(1))\r |
554 | break;\r |
555 | while (in_menu_wait_any(50) & PBTN_MOK);\r |
556 | engineState = PGS_Running;\r |
557 | return 1;\r |
558 | }\r |
559 | break;\r |
560 | case MA_MAIN_RESET_GAME:\r |
561 | if (rom_loaded) {\r |
562 | emu_ResetGame();\r |
563 | while (in_menu_wait_any(50) & PBTN_MOK);\r |
564 | engineState = PGS_Running;\r |
565 | return 1;\r |
566 | }\r |
567 | break;\r |
568 | case MA_MAIN_LOAD_ROM:\r |
569 | {\r |
570 | /* char curr_path[PATH_MAX], *selfname;\r |
571 | FILE *tstf;\r |
572 | if ( (tstf = fopen(loadedRomFName, "rb")) )\r |
573 | {\r |
574 | fclose(tstf);\r |
575 | strcpy(curr_path, loadedRomFName);\r |
576 | }\r |
577 | else\r |
578 | getcwd(curr_path, PATH_MAX);\r |
579 | selfname = romsel_loop(curr_path);\r |
580 | if (selfname) {\r |
581 | printf("selected file: %s\n", selfname);\r |
582 | engineState = PGS_ReloadRom;\r |
583 | return;\r |
584 | }*/\r |
585 | break;\r |
586 | }\r |
587 | case MA_MAIN_OPTIONS:\r |
588 | ret = menu_loop_options();\r |
589 | if (ret == 1) break; // status update\r |
590 | if (engineState == PGS_ReloadRom)\r |
591 | return 1; // BIOS test\r |
592 | break;\r |
593 | case MA_MAIN_CONTROLS:\r |
594 | kc_sel_loop();\r |
595 | break;\r |
596 | case MA_MAIN_CREDITS:\r |
597 | draw_menu_credits();\r |
598 | usleep(500*1000); /* FIXME */\r |
599 | in_menu_wait(PBTN_MOK|PBTN_MBACK);\r |
600 | break;\r |
601 | case MA_MAIN_EXIT:\r |
602 | engineState = PGS_Quit;\r |
603 | return 1;\r |
604 | case MA_MAIN_PATCHES:\r |
605 | if (rom_loaded && PicoPatches) {\r |
606 | patches_menu_loop();\r |
607 | PicoPatchApply();\r |
608 | strcpy(menuErrorMsg, "Patches applied");\r |
609 | }\r |
610 | break;\r |
611 | default:\r |
612 | lprintf("%s: something unknown selected\n", __FUNCTION__);\r |
613 | break;\r |
614 | }\r |
615 | \r |
616 | return 0;\r |
617 | }\r |
618 | \r |
619 | menu_entry e_main_menu[] =\r |
620 | {\r |
621 | mee_submenu_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler),\r |
622 | mee_submenu_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler),\r |
623 | mee_submenu_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler),\r |
624 | mee_submenu_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler),\r |
625 | mee_submenu_id("Load new ROM/ISO", MA_MAIN_LOAD_ROM, main_menu_handler),\r |
626 | mee_submenu_id("Change options", MA_MAIN_OPTIONS, main_menu_handler),\r |
627 | mee_submenu_id("Credits", MA_MAIN_CREDITS, main_menu_handler),\r |
628 | mee_submenu_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler),\r |
629 | mee_submenu_id("Exit", MA_MAIN_EXIT, main_menu_handler),\r |
630 | mee_end,\r |
631 | };\r |
632 | \r |
633 | void menu_loop(void)\r |
634 | {\r |
635 | static int sel = 0;\r |
636 | \r |
637 | me_enable(e_main_menu, MA_MAIN_RESUME_GAME, rom_loaded);\r |
638 | me_enable(e_main_menu, MA_MAIN_SAVE_STATE, rom_loaded);\r |
639 | me_enable(e_main_menu, MA_MAIN_LOAD_STATE, rom_loaded);\r |
640 | me_enable(e_main_menu, MA_MAIN_RESET_GAME, rom_loaded);\r |
641 | me_enable(e_main_menu, MA_MAIN_PATCHES, PicoPatches != NULL);\r |
642 | \r |
643 | plat_video_menu_enter(rom_loaded);\r |
644 | in_set_blocking(1);\r |
645 | me_loop(e_main_menu, &sel);\r |
646 | in_set_blocking(0);\r |
647 | \r |
648 | if (rom_loaded) {\r |
649 | while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MBACK)); // wait until select is released\r |
650 | engineState = PGS_Running;\r |
651 | }\r |
652 | \r |
653 | }\r |
654 | \r |
b8464531 |
655 | // ------------ debug menu ------------\r |
656 | \r |
657 | #include <sys/stat.h>\r |
658 | #include <sys/types.h>\r |
659 | \r |
f11bad75 |
660 | #include <pico/pico.h>\r |
661 | #include <pico/debug.h>\r |
b8464531 |
662 | \r |
663 | void SekStepM68k(void);\r |
664 | \r |
725d7f6c |
665 | static void mplayer_loop(void)\r |
666 | {\r |
667 | emu_startSound();\r |
668 | \r |
669 | while (1)\r |
670 | {\r |
671 | PDebugZ80Frame();\r |
fce20e73 |
672 | if (in_menu_wait_any(0) & PBTN_NORTH) break;\r |
725d7f6c |
673 | emu_waitSound();\r |
674 | }\r |
675 | \r |
676 | emu_endSound();\r |
677 | }\r |
678 | \r |
b8464531 |
679 | static void draw_text_debug(const char *str, int skip, int from)\r |
680 | {\r |
681 | const char *p;\r |
682 | int len, line;\r |
683 | \r |
684 | p = str;\r |
685 | while (skip-- > 0)\r |
686 | {\r |
687 | while (*p && *p != '\n') p++;\r |
688 | if (*p == 0 || p[1] == 0) return;\r |
689 | p++;\r |
690 | }\r |
691 | \r |
692 | str = p;\r |
693 | for (line = from; line < SCREEN_HEIGHT/10; line++)\r |
694 | {\r |
695 | while (*p && *p != '\n') p++;\r |
696 | len = p - str;\r |
697 | if (len > 55) len = 55;\r |
698 | smalltext_out16_lim(1, line*10, str, 0xffff, len);\r |
699 | if (*p == 0) break;\r |
700 | p++; str = p;\r |
701 | }\r |
702 | }\r |
703 | \r |
704 | static void draw_frame_debug(void)\r |
705 | {\r |
706 | char layer_str[48] = "layers: ";\r |
707 | if (PicoDrawMask & PDRAW_LAYERB_ON) memcpy(layer_str + 8, "B", 1);\r |
708 | if (PicoDrawMask & PDRAW_LAYERA_ON) memcpy(layer_str + 10, "A", 1);\r |
709 | if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6);\r |
710 | if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6);\r |
711 | \r |
712 | clear_screen();\r |
713 | emu_forcedFrame(0);\r |
714 | smalltext_out16(4, SCREEN_HEIGHT-8, layer_str, 0xffff);\r |
715 | }\r |
716 | \r |
717 | void debug_menu_loop(void)\r |
718 | {\r |
719 | int inp, mode = 0;\r |
720 | int spr_offs = 0, dumped = 0;\r |
7443ecd9 |
721 | char *tmp;\r |
b8464531 |
722 | \r |
723 | while (1)\r |
724 | {\r |
725 | switch (mode)\r |
726 | {\r |
24b24674 |
727 | case 0: plat_video_menu_begin();\r |
7443ecd9 |
728 | tmp = PDebugMain();\r |
729 | emu_platformDebugCat(tmp);\r |
730 | draw_text_debug(tmp, 0, 0);\r |
b8464531 |
731 | if (dumped) {\r |
732 | smalltext_out16(SCREEN_WIDTH-6*10, SCREEN_HEIGHT-8, "dumped", 0xffff);\r |
733 | dumped = 0;\r |
734 | }\r |
735 | break;\r |
736 | case 1: draw_frame_debug(); break;\r |
737 | case 2: clear_screen();\r |
738 | emu_forcedFrame(0);\r |
739 | darken_screen();\r |
dfa8d77a |
740 | PDebugShowSpriteStats((unsigned short *)SCREEN_BUFFER + (SCREEN_HEIGHT/2 - 240/2)*SCREEN_WIDTH +\r |
741 | SCREEN_WIDTH/2 - 320/2, SCREEN_WIDTH); break;\r |
b8464531 |
742 | case 3: clear_screen();\r |
743 | PDebugShowPalette(SCREEN_BUFFER, SCREEN_WIDTH);\r |
744 | PDebugShowSprite((unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH*120+SCREEN_WIDTH/2+16,\r |
745 | SCREEN_WIDTH, spr_offs);\r |
746 | draw_text_debug(PDebugSpriteList(), spr_offs, 6);\r |
747 | break;\r |
748 | }\r |
24b24674 |
749 | plat_video_menu_end();\r |
b8464531 |
750 | \r |
fce20e73 |
751 | inp = in_menu_wait(PBTN_EAST|PBTN_MBACK|PBTN_WEST|PBTN_NORTH|PBTN_L|PBTN_R|PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT);\r |
752 | if (inp & PBTN_MBACK) return;\r |
b3972d82 |
753 | if (inp & PBTN_L) { mode--; if (mode < 0) mode = 3; }\r |
754 | if (inp & PBTN_R) { mode++; if (mode > 3) mode = 0; }\r |
b8464531 |
755 | switch (mode)\r |
756 | {\r |
757 | case 0:\r |
b3972d82 |
758 | if (inp & PBTN_EAST) SekStepM68k();\r |
759 | if (inp & PBTN_NORTH) {\r |
fce20e73 |
760 | while (inp & PBTN_NORTH) inp = in_menu_wait_any(-1);\r |
725d7f6c |
761 | mplayer_loop();\r |
762 | }\r |
b3972d82 |
763 | if ((inp & (PBTN_WEST|PBTN_LEFT)) == (PBTN_WEST|PBTN_LEFT)) {\r |
b8464531 |
764 | mkdir("dumps", 0777);\r |
765 | PDebugDumpMem();\r |
fce20e73 |
766 | while (inp & PBTN_WEST) inp = in_menu_wait_any(-1);\r |
b8464531 |
767 | dumped = 1;\r |
768 | }\r |
769 | break;\r |
770 | case 1:\r |
b3972d82 |
771 | if (inp & PBTN_LEFT) PicoDrawMask ^= PDRAW_LAYERB_ON;\r |
772 | if (inp & PBTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON;\r |
773 | if (inp & PBTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON;\r |
774 | if (inp & PBTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON;\r |
775 | if (inp & PBTN_EAST) {\r |
8e6cbce1 |
776 | PsndOut = NULL; // just in case\r |
777 | PicoSkipFrame = 1;\r |
778 | PicoFrame();\r |
779 | PicoSkipFrame = 0;\r |
fce20e73 |
780 | while (inp & PBTN_EAST) inp = in_menu_wait_any(-1);\r |
8e6cbce1 |
781 | }\r |
b8464531 |
782 | break;\r |
783 | case 3:\r |
b3972d82 |
784 | if (inp & PBTN_DOWN) spr_offs++;\r |
785 | if (inp & PBTN_UP) spr_offs--;\r |
b8464531 |
786 | if (spr_offs < 0) spr_offs = 0;\r |
787 | break;\r |
788 | }\r |
789 | }\r |
790 | }\r |
791 | \r |
36f6fd5a |
792 | #endif // !UIQ3\r |
793 | \r |
794 | // ------------ util ------------\r |
795 | \r |
796 | const char *me_region_name(unsigned int code, int auto_order)\r |
797 | {\r |
798 | static const char *names[] = { "Auto", " Japan NTSC", " Japan PAL", " USA", " Europe" };\r |
799 | static const char *names_short[] = { "", " JP", " JP", " US", " EU" };\r |
800 | int u, i = 0;\r |
801 | if (code) {\r |
802 | code <<= 1;\r |
803 | while((code >>= 1)) i++;\r |
804 | if (i > 4) return "unknown";\r |
805 | return names[i];\r |
806 | } else {\r |
807 | static char name[24];\r |
808 | strcpy(name, "Auto:");\r |
809 | for (u = 0; u < 3; u++) {\r |
810 | i = 0; code = ((auto_order >> u*4) & 0xf) << 1;\r |
811 | while((code >>= 1)) i++;\r |
812 | strcat(name, names_short[i]);\r |
813 | }\r |
814 | return name;\r |
815 | }\r |
816 | }\r |
817 | \r |
24b24674 |
818 | /* TODO: rename */\r |
819 | void menu_darken_bg(void *dst, int pixels, int darker)\r |
820 | {\r |
821 | unsigned int *screen = dst;\r |
822 | pixels /= 2;\r |
823 | if (darker)\r |
824 | {\r |
825 | while (pixels--)\r |
826 | {\r |
827 | unsigned int p = *screen;\r |
828 | *screen++ = ((p&0xf79ef79e)>>1) - ((p&0xc618c618)>>3);\r |
829 | }\r |
830 | }\r |
831 | else\r |
832 | {\r |
833 | while (pixels--)\r |
834 | {\r |
835 | unsigned int p = *screen;\r |
836 | *screen++ = (p&0xf79ef79e)>>1;\r |
837 | }\r |
838 | }\r |
839 | }\r |
b8464531 |
840 | \r |