1 // (c) Copyright 2006,2007 notaz, All rights reserved.
\r
2 // Free for non-commercial use.
\r
4 // For commercial use, separate licencing terms must be obtained.
\r
13 #include "readpng.h"
\r
14 #include "lprintf.h"
\r
19 char menuErrorMsg[64] = { 0, };
\r
21 // PicoPad[] format: MXYZ SACB RLDU
\r
22 me_bind_action me_ctrl_actions[15] =
\r
25 { "DOWN ", 0x0002 },
\r
26 { "LEFT ", 0x0004 },
\r
27 { "RIGHT ", 0x0008 },
\r
31 { "A turbo", 0x4000 },
\r
32 { "B turbo", 0x1000 },
\r
33 { "C turbo", 0x2000 },
\r
34 { "START ", 0x0080 },
\r
35 { "MODE ", 0x0800 },
\r
44 static unsigned char menu_font_data[10240];
\r
45 static int menu_text_color = 0xffff; // default to white
\r
46 static int menu_sel_color = -1; // disabled
\r
48 // draws text to current bbp16 screen
\r
49 static void text_out16_(int x, int y, const char *text, int color)
\r
51 int i, l, u, tr, tg, tb, len;
\r
52 unsigned short *dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;
\r
53 tr = (color & 0xf800) >> 8;
\r
54 tg = (color & 0x07e0) >> 3;
\r
55 tb = (color & 0x001f) << 3;
\r
57 if (text == (void *)1)
\r
66 for (i = 0; i < len; i++)
\r
68 unsigned char *src = menu_font_data + (unsigned int)text[i]*4*10;
\r
69 unsigned short *dst = dest;
\r
70 for (l = 0; l < 10; l++, dst += SCREEN_WIDTH-8)
\r
72 for (u = 8/2; u > 0; u--, src++)
\r
76 r = (*dst & 0xf800) >> 8;
\r
77 g = (*dst & 0x07e0) >> 3;
\r
78 b = (*dst & 0x001f) << 3;
\r
79 r = (c^0xf)*r/15 + c*tr/15;
\r
80 g = (c^0xf)*g/15 + c*tg/15;
\r
81 b = (c^0xf)*b/15 + c*tb/15;
\r
82 *dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);
\r
84 r = (*dst & 0xf800) >> 8;
\r
85 g = (*dst & 0x07e0) >> 3;
\r
86 b = (*dst & 0x001f) << 3;
\r
87 r = (c^0xf)*r/15 + c*tr/15;
\r
88 g = (c^0xf)*g/15 + c*tg/15;
\r
89 b = (c^0xf)*b/15 + c*tb/15;
\r
90 *dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);
\r
97 void text_out16(int x, int y, const char *texto, ...)
\r
102 va_start(args,texto);
\r
103 vsprintf(buffer,texto,args);
\r
106 text_out16_(x,y,buffer,menu_text_color);
\r
110 void smalltext_out16(int x, int y, const char *texto, int color)
\r
113 unsigned char *src;
\r
114 unsigned short *dst;
\r
116 for (i = 0;; i++, x += 6)
\r
118 unsigned char c = (unsigned char) texto[i];
\r
123 src = fontdata6x8[c];
\r
124 dst = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;
\r
131 if( *src & w ) *dst = color;
\r
137 dst += SCREEN_WIDTH-6;
\r
142 void smalltext_out16_lim(int x, int y, const char *texto, int color, int max)
\r
144 char buffer[SCREEN_WIDTH/6+1];
\r
146 strncpy(buffer, texto, SCREEN_WIDTH/6);
\r
147 if (max > SCREEN_WIDTH/6) max = SCREEN_WIDTH/6;
\r
148 if (max < 0) max = 0;
\r
151 smalltext_out16(x, y, buffer, color);
\r
154 void menu_draw_selection(int x, int y, int w)
\r
157 unsigned short *dst, *dest;
\r
159 text_out16_(x, y, (void *)1, (menu_sel_color < 0) ? menu_text_color : menu_sel_color);
\r
161 if (menu_sel_color < 0) return; // no selection hilight
\r
164 dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH + 14;
\r
165 for (h = 11; h > 0; h--)
\r
168 for (i = w; i > 0; i--)
\r
169 *dst++ = menu_sel_color;
\r
170 dest += SCREEN_WIDTH;
\r
174 static int parse_hex_color(char *buff)
\r
177 int t = (int) strtoul(buff, &endp, 16);
\r
180 return ((t<<8)&0xf800) | ((t>>5)&0x07e0) | ((t>>19)&0x1f);
\r
182 return ((t>>8)&0xf800) | ((t>>5)&0x07e0) | ((t>>3)&0x1f);
\r
187 void menu_init(void)
\r
190 unsigned char *fd = menu_font_data;
\r
194 // generate default font from fontdata8x8
\r
195 memset(menu_font_data, 0, sizeof(menu_font_data));
\r
196 for (c = 0; c < 256; c++)
\r
198 for (l = 0; l < 8; l++)
\r
200 unsigned char fd8x8 = fontdata8x8[c*8+l];
\r
201 if (fd8x8&0x80) *fd |= 0xf0;
\r
202 if (fd8x8&0x40) *fd |= 0x0f; fd++;
\r
203 if (fd8x8&0x20) *fd |= 0xf0;
\r
204 if (fd8x8&0x10) *fd |= 0x0f; fd++;
\r
205 if (fd8x8&0x08) *fd |= 0xf0;
\r
206 if (fd8x8&0x04) *fd |= 0x0f; fd++;
\r
207 if (fd8x8&0x02) *fd |= 0xf0;
\r
208 if (fd8x8&0x01) *fd |= 0x0f; fd++;
\r
210 fd += 8*2/2; // 2 empty lines
\r
213 // load custom font and selector (stored as 1st symbol in font table)
\r
214 readpng(menu_font_data, "skin/font.png", READPNG_FONT);
\r
215 memcpy(menu_font_data, menu_font_data + ((int)'>')*4*10, 4*10); // default selector symbol is '>'
\r
216 readpng(menu_font_data, "skin/selector.png", READPNG_SELECTOR);
\r
218 // load custom colors
\r
219 f = fopen("skin/skin.txt", "r");
\r
222 lprintf("found skin.txt\n");
\r
225 fgets(buff, sizeof(buff), f);
\r
226 if (buff[0] == '#' || buff[0] == '/') continue; // comment
\r
227 if (buff[0] == '\r' || buff[0] == '\n') continue; // empty line
\r
228 if (strncmp(buff, "text_color=", 11) == 0)
\r
230 int tmp = parse_hex_color(buff+11);
\r
231 if (tmp >= 0) menu_text_color = tmp;
\r
232 else lprintf("skin.txt: parse error for text_color\n");
\r
234 else if (strncmp(buff, "selection_color=", 16) == 0)
\r
236 int tmp = parse_hex_color(buff+16);
\r
237 if (tmp >= 0) menu_sel_color = tmp;
\r
238 else lprintf("skin.txt: parse error for selection_color\n");
\r
241 lprintf("skin.txt: parse error: %s\n", buff);
\r
248 int me_id2offset(const menu_entry *entries, int count, menu_id id)
\r
251 for (i = 0; i < count; i++)
\r
253 if (entries[i].id == id) return i;
\r
256 lprintf("%s: id %i not found\n", __FUNCTION__, id);
\r
260 void me_enable(menu_entry *entries, int count, menu_id id, int enable)
\r
262 int i = me_id2offset(entries, count, id);
\r
263 entries[i].enabled = enable;
\r
266 int me_count_enabled(const menu_entry *entries, int count)
\r
270 for (i = 0; i < count; i++)
\r
272 if (entries[i].enabled) ret++;
\r
278 menu_id me_index2id(const menu_entry *entries, int count, int index)
\r
282 for (i = 0; i < count; i++)
\r
284 if (entries[i].enabled)
\r
286 if (index == 0) break;
\r
290 if (i >= count) i = count - 1;
\r
291 return entries[i].id;
\r
294 void me_draw(const menu_entry *entries, int count, int x, int y, me_draw_custom_f *cust_draw, void *param)
\r
298 for (i = 0; i < count; i++)
\r
300 if (!entries[i].enabled) continue;
\r
301 if (entries[i].name == NULL)
\r
303 if (cust_draw != NULL)
\r
304 cust_draw(&entries[i], x, y1, param);
\r
308 text_out16(x, y1, entries[i].name);
\r
309 if (entries[i].beh == MB_ONOFF)
\r
310 text_out16(x + 27*8, y1, (*(int *)entries[i].var & entries[i].mask) ? "ON" : "OFF");
\r
311 else if (entries[i].beh == MB_RANGE)
\r
312 text_out16(x + 27*8, y1, "%i", *(int *)entries[i].var);
\r
317 int me_process(menu_entry *entries, int count, menu_id id, int is_next)
\r
319 int i = me_id2offset(entries, count, id);
\r
320 menu_entry *entry = &entries[i];
\r
321 switch (entry->beh)
\r
324 *(int *)entry->var ^= entry->mask;
\r
327 *(int *)entry->var += is_next ? 1 : -1;
\r
328 if (*(int *)entry->var < (int)entry->min) *(int *)entry->var = (int)entry->min;
\r
329 if (*(int *)entry->var > (int)entry->max) *(int *)entry->var = (int)entry->max;
\r
336 // ------------ debug menu ------------
\r
338 #include <sys/stat.h>
\r
339 #include <sys/types.h>
\r
341 #include <pico/pico.h>
\r
342 #include <pico/debug.h>
\r
344 void SekStepM68k(void);
\r
346 static void mplayer_loop(void)
\r
353 if (read_buttons_async(BTN_NORTH)) break;
\r
360 static void draw_text_debug(const char *str, int skip, int from)
\r
368 while (*p && *p != '\n') p++;
\r
369 if (*p == 0 || p[1] == 0) return;
\r
374 for (line = from; line < SCREEN_HEIGHT/10; line++)
\r
376 while (*p && *p != '\n') p++;
\r
378 if (len > 55) len = 55;
\r
379 smalltext_out16_lim(1, line*10, str, 0xffff, len);
\r
380 if (*p == 0) break;
\r
385 static void draw_frame_debug(void)
\r
387 char layer_str[48] = "layers: ";
\r
388 if (PicoDrawMask & PDRAW_LAYERB_ON) memcpy(layer_str + 8, "B", 1);
\r
389 if (PicoDrawMask & PDRAW_LAYERA_ON) memcpy(layer_str + 10, "A", 1);
\r
390 if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6);
\r
391 if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6);
\r
394 emu_forcedFrame(0);
\r
395 smalltext_out16(4, SCREEN_HEIGHT-8, layer_str, 0xffff);
\r
398 void debug_menu_loop(void)
\r
401 int spr_offs = 0, dumped = 0;
\r
408 case 0: menu_draw_begin();
\r
409 tmp = PDebugMain();
\r
410 emu_platformDebugCat(tmp);
\r
411 draw_text_debug(tmp, 0, 0);
\r
413 smalltext_out16(SCREEN_WIDTH-6*10, SCREEN_HEIGHT-8, "dumped", 0xffff);
\r
417 case 1: draw_frame_debug(); break;
\r
418 case 2: clear_screen();
\r
419 emu_forcedFrame(0);
\r
421 PDebugShowSpriteStats((unsigned short *)SCREEN_BUFFER + (SCREEN_HEIGHT/2 - 240/2)*SCREEN_WIDTH +
\r
422 SCREEN_WIDTH/2 - 320/2, SCREEN_WIDTH); break;
\r
423 case 3: clear_screen();
\r
424 PDebugShowPalette(SCREEN_BUFFER, SCREEN_WIDTH);
\r
425 PDebugShowSprite((unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH*120+SCREEN_WIDTH/2+16,
\r
426 SCREEN_WIDTH, spr_offs);
\r
427 draw_text_debug(PDebugSpriteList(), spr_offs, 6);
\r
432 inp = read_buttons(BTN_EAST|BTN_SOUTH|BTN_WEST|BTN_NORTH|BTN_L|BTN_R|BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT);
\r
433 if (inp & BTN_SOUTH) return;
\r
434 if (inp & BTN_L) { mode--; if (mode < 0) mode = 3; }
\r
435 if (inp & BTN_R) { mode++; if (mode > 3) mode = 0; }
\r
439 if (inp & BTN_EAST) SekStepM68k();
\r
440 if (inp & BTN_NORTH) {
\r
441 while (inp & BTN_NORTH) inp = read_buttons_async(BTN_NORTH);
\r
444 if ((inp & (BTN_WEST|BTN_LEFT)) == (BTN_WEST|BTN_LEFT)) {
\r
445 mkdir("dumps", 0777);
\r
447 while (inp & BTN_WEST) inp = read_buttons_async(BTN_WEST);
\r
452 if (inp & BTN_LEFT) PicoDrawMask ^= PDRAW_LAYERB_ON;
\r
453 if (inp & BTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON;
\r
454 if (inp & BTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON;
\r
455 if (inp & BTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON;
\r
456 if (inp & BTN_EAST) {
\r
457 PsndOut = NULL; // just in case
\r
461 while (inp & BTN_EAST) inp = read_buttons_async(BTN_EAST);
\r
465 if (inp & BTN_DOWN) spr_offs++;
\r
466 if (inp & BTN_UP) spr_offs--;
\r
467 if (spr_offs < 0) spr_offs = 0;
\r
475 // ------------ util ------------
\r
477 const char *me_region_name(unsigned int code, int auto_order)
\r
479 static const char *names[] = { "Auto", " Japan NTSC", " Japan PAL", " USA", " Europe" };
\r
480 static const char *names_short[] = { "", " JP", " JP", " US", " EU" };
\r
484 while((code >>= 1)) i++;
\r
485 if (i > 4) return "unknown";
\r
488 static char name[24];
\r
489 strcpy(name, "Auto:");
\r
490 for (u = 0; u < 3; u++) {
\r
491 i = 0; code = ((auto_order >> u*4) & 0xf) << 1;
\r
492 while((code >>= 1)) i++;
\r
493 strcat(name, names_short[i]);
\r