X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=common%2Fmenu.c;h=412dbc2cdabdeaad2e036ce46133be978ccd883a;hb=93c18cb44bf9794c7c9bc93411c68880723320d1;hp=e3c8cef29c0e5e5790efbd3c7cd83c6a88426fa3;hpb=049a6b3e80151f6a5af726e25478ed15e111dfcc;p=libpicofe.git diff --git a/common/menu.c b/common/menu.c index e3c8cef..412dbc2 100644 --- a/common/menu.c +++ b/common/menu.c @@ -1,4 +1,4 @@ -// (c) Copyright 2006,2007 notaz, All rights reserved. +// (c) Copyright 2006-2009 notaz, All rights reserved. // Free for non-commercial use. // For commercial use, separate licencing terms must be obtained. @@ -12,11 +12,11 @@ #include "fonts.h" #include "readpng.h" #include "lprintf.h" -#include "common.h" #include "input.h" #include "emu.h" #include "plat.h" #include "posix.h" +#include #include #include @@ -25,20 +25,29 @@ #define array_size(x) (sizeof(x) / sizeof(x[0])) static char static_buff[64]; -char menuErrorMsg[64] = { 0, }; - +static char menu_error_msg[64] = { 0, }; +static int menu_error_time = 0; #ifndef UIQ3 -static unsigned char menu_font_data[10240]; +static unsigned char *menu_font_data = NULL; static int menu_text_color = 0xffff; // default to white static int menu_sel_color = -1; // disabled +/* note: these might become non-constant in future */ +#if MENU_X2 +static const int me_mfont_w = 16, me_mfont_h = 20; +static const int me_sfont_w = 12, me_sfont_h = 20; +#else +static const int me_mfont_w = 8, me_mfont_h = 10; +static const int me_sfont_w = 6, me_sfont_h = 10; +#endif + // draws text to current bbp16 screen static void text_out16_(int x, int y, const char *text, int color) { int i, l, u, tr, tg, tb, len; - unsigned short *dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + unsigned short *dest = (unsigned short *)g_screen_ptr + x + y * g_screen_width; tr = (color & 0xf800) >> 8; tg = (color & 0x07e0) >> 3; tb = (color & 0x001f) << 3; @@ -59,11 +68,11 @@ static void text_out16_(int x, int y, const char *text, int color) for (i = 0; i < len; i++) { - unsigned char *src = menu_font_data + (unsigned int)text[i]*4*10; + unsigned char *src = menu_font_data + (unsigned int)text[i] * me_mfont_w * me_mfont_h / 2; unsigned short *dst = dest; - for (l = 0; l < 10; l++, dst += SCREEN_WIDTH-8) + for (l = 0; l < me_mfont_h; l++, dst += g_screen_width - me_mfont_w) { - for (u = 8/2; u > 0; u--, src++) + for (u = me_mfont_w / 2; u > 0; u--, src++) { int c, r, g, b; c = *src >> 4; @@ -84,7 +93,7 @@ static void text_out16_(int x, int y, const char *text, int color) *dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3); } } - dest += 8; + dest += me_mfont_w; } } @@ -92,58 +101,73 @@ void text_out16(int x, int y, const char *texto, ...) { va_list args; char buffer[256]; - int maxw = (SCREEN_WIDTH - x) / 8; + int maxw = (g_screen_width - x) / me_mfont_w; + + if (maxw < 0) + return; va_start(args, texto); vsnprintf(buffer, sizeof(buffer), texto, args); va_end(args); - if (maxw > 255) - maxw = 255; + if (maxw > sizeof(buffer) - 1) + maxw = sizeof(buffer) - 1; buffer[maxw] = 0; text_out16_(x,y,buffer,menu_text_color); } - +/* draws in 6x8 font, might multiply size by integer */ static void smalltext_out16_(int x, int y, const char *texto, int color) { - int i; unsigned char *src; unsigned short *dst; + int multiplier = me_sfont_w / 6; + int i; - for (i = 0;; i++, x += 6) + for (i = 0;; i++, x += me_sfont_w) { unsigned char c = (unsigned char) texto[i]; int h = 8; - if (!c) break; + if (!c || c == '\n') + break; src = fontdata6x8[c]; - dst = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + dst = (unsigned short *)g_screen_ptr + x + y * g_screen_width; while (h--) { - int w = 0x20; - while (w) + int m, w2, h2; + for (h2 = multiplier; h2 > 0; h2--) { - if( *src & w ) *dst = color; - dst++; - w>>=1; + for (m = 0x20; m; m >>= 1) { + if (*src & m) + for (w2 = multiplier; w2 > 0; w2--) + *dst++ = color; + else + dst += multiplier; + } + + dst += g_screen_width - me_sfont_w; } src++; - - dst += SCREEN_WIDTH-6; } } } -void smalltext_out16(int x, int y, const char *texto, int color) +static void smalltext_out16(int x, int y, const char *texto, int color) { - char buffer[SCREEN_WIDTH/6+1]; + char buffer[128]; + int maxw = (g_screen_width - x) / 6; + + if (maxw < 0) + return; strncpy(buffer, texto, sizeof(buffer)); - buffer[sizeof(buffer) - 1] = 0; + if (maxw > sizeof(buffer) - 1) + maxw = sizeof(buffer) - 1; + buffer[maxw] = 0; smalltext_out16_(x, y, buffer, color); } @@ -158,13 +182,13 @@ static void menu_draw_selection(int x, int y, int w) if (menu_sel_color < 0) return; // no selection hilight if (y > 0) y--; - dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH + 14; - for (h = 11; h > 0; h--) + dest = (unsigned short *)g_screen_ptr + x + y * g_screen_width + 14; + for (h = me_mfont_h + 1; h > 0; h--) { dst = dest; - for (i = w; i > 0; i--) + for (i = w - 14; i > 0; i--) *dst++ = menu_sel_color; - dest += SCREEN_WIDTH; + dest += g_screen_width; } } @@ -183,33 +207,65 @@ static int parse_hex_color(char *buff) void menu_init(void) { - int c, l; - unsigned char *fd = menu_font_data; + int i, c, l; + unsigned char *fd, *fds; char buff[256]; FILE *f; - // generate default font from fontdata8x8 - memset(menu_font_data, 0, sizeof(menu_font_data)); - for (c = 0; c < 256; c++) + if (menu_font_data != NULL) + free(menu_font_data); + + menu_font_data = calloc((MENU_X2 ? 256 * 320 : 128 * 160) / 2, 1); + if (menu_font_data == NULL) + return; + + // generate default 8x10 font from fontdata8x8 + for (c = 0, fd = menu_font_data; c < 256; c++) { for (l = 0; l < 8; l++) { unsigned char fd8x8 = fontdata8x8[c*8+l]; - if (fd8x8&0x80) *fd |= 0xf0; + if (fd8x8&0x80) *fd = 0xf0; if (fd8x8&0x40) *fd |= 0x0f; fd++; - if (fd8x8&0x20) *fd |= 0xf0; + if (fd8x8&0x20) *fd = 0xf0; if (fd8x8&0x10) *fd |= 0x0f; fd++; - if (fd8x8&0x08) *fd |= 0xf0; + if (fd8x8&0x08) *fd = 0xf0; if (fd8x8&0x04) *fd |= 0x0f; fd++; - if (fd8x8&0x02) *fd |= 0xf0; + if (fd8x8&0x02) *fd = 0xf0; if (fd8x8&0x01) *fd |= 0x0f; fd++; } fd += 8*2/2; // 2 empty lines } + if (MENU_X2) { + // expand default font + fds = menu_font_data + 128 * 160 / 2 - 4; + fd = menu_font_data + 256 * 320 / 2 - 1; + for (c = 255; c >= 0; c--) + { + for (l = 9; l >= 0; l--, fds -= 4) + { + for (i = 3; i >= 0; i--) { + int px = fds[i] & 0x0f; + *fd-- = px | (px << 4); + px = (fds[i] >> 4) & 0x0f; + *fd-- = px | (px << 4); + } + for (i = 3; i >= 0; i--) { + int px = fds[i] & 0x0f; + *fd-- = px | (px << 4); + px = (fds[i] >> 4) & 0x0f; + *fd-- = px | (px << 4); + } + } + } + } + // load custom font and selector (stored as 1st symbol in font table) readpng(menu_font_data, "skin/font.png", READPNG_FONT); - memcpy(menu_font_data, menu_font_data + ((int)'>')*4*10, 4*10); // default selector symbol is '>' + // default selector symbol is '>' + memcpy(menu_font_data, menu_font_data + ((int)'>') * me_mfont_w * me_mfont_h / 2, + me_mfont_w * me_mfont_h / 2); readpng(menu_font_data, "skin/selector.png", READPNG_SELECTOR); // load custom colors @@ -272,7 +328,7 @@ static void me_draw(const menu_entry *entries, int sel) { const menu_entry *ent; int x, y, w = 0, h = 0; - int offs, opt_offs = 27*8; + int offs, opt_offs = 27 * me_mfont_w; const char *name; int asel = 0; int i, n; @@ -289,22 +345,22 @@ static void me_draw(const menu_entry *entries, int sel) asel = n; name = NULL; - wt = strlen(ent->name) * 8; /* FIXME: unhardcode font width */ + wt = strlen(ent->name) * me_mfont_w; if (wt == 0 && ent->generate_name) name = ent->generate_name(ent->id, &offs); if (name != NULL) - wt = strlen(name) * 8; + wt = strlen(name) * me_mfont_w; if (ent->beh != MB_NONE) { if (wt > opt_offs) - opt_offs = wt + 8; + opt_offs = wt + me_mfont_w; wt = opt_offs; switch (ent->beh) { case MB_NONE: break; case MB_OPT_ONOFF: - case MB_OPT_RANGE: wt += 8*3; break; + case MB_OPT_RANGE: wt += me_mfont_w * 3; break; case MB_OPT_CUSTOM: case MB_OPT_CUSTONOFF: case MB_OPT_CUSTRANGE: @@ -313,7 +369,7 @@ static void me_draw(const menu_entry *entries, int sel) if (ent->generate_name != NULL) name = ent->generate_name(ent->id, &offs); if (name != NULL) - wt += (strlen(name) + offs) * 8; + wt += (strlen(name) + offs) * me_mfont_w; break; } } @@ -322,24 +378,25 @@ static void me_draw(const menu_entry *entries, int sel) w = wt; n++; } - h = n * 10; - w += 16; /* selector */ + h = n * me_mfont_h; + w += me_mfont_w * 2; /* selector */ - if (w > SCREEN_WIDTH) { - lprintf("width %d > %d\n", w, SCREEN_WIDTH); - w = SCREEN_WIDTH; + if (w > g_screen_width) { + lprintf("width %d > %d\n", w, g_screen_width); + w = g_screen_width; } - if (h > SCREEN_HEIGHT) { - lprintf("height %d > %d\n", w, SCREEN_HEIGHT); - h = SCREEN_HEIGHT; + if (h > g_screen_height) { + lprintf("height %d > %d\n", w, g_screen_height); + h = g_screen_height; } - x = SCREEN_WIDTH / 2 - w / 2; - y = SCREEN_HEIGHT / 2 - h / 2; + x = g_screen_width / 2 - w / 2; + y = g_screen_height / 2 - h / 2; /* draw */ plat_video_menu_begin(); - menu_draw_selection(x, y + asel * 10, w); + menu_draw_selection(x, y + asel * me_mfont_h, w); + x += me_mfont_w * 2; for (ent = entries; ent->name; ent++) { @@ -352,16 +409,16 @@ static void me_draw(const menu_entry *entries, int sel) name = ent->generate_name(ent->id, &offs); } if (name != NULL) - text_out16(x + 16, y, name); + text_out16(x, y, name); switch (ent->beh) { case MB_NONE: break; case MB_OPT_ONOFF: - text_out16(x + 16 + opt_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF"); + text_out16(x + opt_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF"); break; case MB_OPT_RANGE: - text_out16(x + 16 + opt_offs, y, "%i", *(int *)ent->var); + text_out16(x + opt_offs, y, "%i", *(int *)ent->var); break; case MB_OPT_CUSTOM: case MB_OPT_CUSTONOFF: @@ -371,25 +428,22 @@ static void me_draw(const menu_entry *entries, int sel) if (ent->generate_name) name = ent->generate_name(ent->id, &offs); if (name != NULL) - text_out16(x + 16 + opt_offs + offs * 8, y, "%s", name); + text_out16(x + opt_offs + offs * me_mfont_w, y, "%s", name); break; } - y += 10; + y += me_mfont_h; } /* display message if we have one */ - if (menuErrorMsg[0] != 0) { - static int msg_redraws = 0; - if (SCREEN_HEIGHT - h >= 2*10) - text_out16(5, 226, menuErrorMsg); + if (menu_error_msg[0] != 0) { + if (g_screen_height - h >= 2 * me_mfont_h) + text_out16(5, g_screen_height - me_mfont_h - 4, menu_error_msg); else lprintf("menu msg doesn't fit!\n"); - if (++msg_redraws > 4) { - menuErrorMsg[0] = 0; - msg_redraws = 0; - } + if (plat_get_ticks_ms() - menu_error_time > 2048) + menu_error_msg[0] = 0; } plat_video_menu_end(); @@ -428,7 +482,7 @@ static void me_loop(menu_entry *menu, int *menu_sel) return; } - while (!menu[sel].enabled && sel < menu_sel_max) + while ((!menu[sel].enabled || !menu[sel].selectable) && sel < menu_sel_max) sel++; /* make sure action buttons are not pressed on entering menu */ @@ -501,14 +555,14 @@ static void draw_menu_credits(void) p++; } - x = SCREEN_WIDTH / 2 - w * 8 / 2; - y = SCREEN_HEIGHT / 2 - h * 10 / 2; + x = g_screen_width / 2 - w * me_mfont_w / 2; + y = g_screen_height / 2 - h * me_mfont_h / 2; if (x < 0) x = 0; if (y < 0) y = 0; plat_video_menu_begin(); - for (p = creds; *p != 0 && y <= SCREEN_HEIGHT - 10; y += 10) { + for (p = creds; *p != 0 && y <= g_screen_height - me_mfont_h; y += me_mfont_h) { text_out16(x, y, p); for (; *p != 0 && *p != '\n'; p++) @@ -526,30 +580,30 @@ static int cdload_called = 0; static void load_progress_cb(int percent) { - int ln, len = percent * SCREEN_WIDTH / 100; - unsigned short *dst = (unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH * 10 * 2; + int ln, len = percent * g_screen_width / 100; + unsigned short *dst = (unsigned short *)g_screen_ptr + g_screen_width * 10 * 2; - if (len > SCREEN_WIDTH) - len = SCREEN_WIDTH; - for (ln = 10 - 2; ln > 0; ln--, dst += SCREEN_WIDTH) + if (len > g_screen_width) + len = g_screen_width; + for (ln = 10 - 2; ln > 0; ln--, dst += g_screen_width) memset(dst, 0xff, len * 2); plat_video_menu_end(); } static void cdload_progress_cb(int percent) { - int ln, len = percent * SCREEN_WIDTH / 100; - unsigned short *dst = (unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH * 10 * 2; + int ln, len = percent * g_screen_width / 100; + unsigned short *dst = (unsigned short *)g_screen_ptr + g_screen_width * 10 * 2; - memset(dst, 0xff, SCREEN_WIDTH * (10 - 2) * 2); + memset(dst, 0xff, g_screen_width * (me_sfont_h - 2) * 2); - smalltext_out16(1, 3 * 10, "Processing CD image / MP3s", 0xffff); - smalltext_out16(1, 4 * 10, rom_fname_loaded, 0xffff); - dst += SCREEN_WIDTH * 30; + smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", 0xffff); + smalltext_out16(1, 4 * me_sfont_h, rom_fname_loaded, 0xffff); + dst += g_screen_width * me_sfont_h * 3; - if (len > SCREEN_WIDTH) - len = SCREEN_WIDTH; - for (ln = (10 - 2); ln > 0; ln--, dst += SCREEN_WIDTH) + if (len > g_screen_width) + len = g_screen_width; + for (ln = (me_sfont_h - 2); ln > 0; ln--, dst += g_screen_width) memset(dst, 0xff, len * 2); plat_video_menu_end(); @@ -560,18 +614,18 @@ void menu_romload_prepare(const char *rom_name) { const char *p = rom_name + strlen(rom_name); - plat_video_menu_begin(); - while (p > rom_name && *p != '/') p--; /* fill both buffers, callbacks won't update in full */ + plat_video_menu_begin(); smalltext_out16(1, 1, "Loading", 0xffff); - smalltext_out16(1, 10, p, 0xffff); + smalltext_out16(1, me_sfont_h, p, 0xffff); plat_video_menu_end(); + plat_video_menu_begin(); smalltext_out16(1, 1, "Loading", 0xffff); - smalltext_out16(1, 10, p, 0xffff); + smalltext_out16(1, me_sfont_h, p, 0xffff); plat_video_menu_end(); PicoCartLoadProgressCB = load_progress_cb; @@ -582,11 +636,49 @@ void menu_romload_prepare(const char *rom_name) void menu_romload_end(void) { PicoCartLoadProgressCB = PicoCDLoadProgressCB = NULL; - smalltext_out16(1, (cdload_called ? 6 : 3) * 10, + smalltext_out16(1, (cdload_called ? 6 : 3) * me_sfont_h, "Starting emulation...", 0xffff); plat_video_menu_end(); } +// -------------- del confirm --------------- + +static void do_delete(const char *fpath, const char *fname) +{ + int len, mid, inp; + const char *nm; + char tmp[64]; + + plat_video_menu_begin(); + + if (!rom_loaded) + menu_darken_bg(g_screen_ptr, g_screen_width * g_screen_height, 0); + + len = strlen(fname); + if (len > g_screen_width/6) + len = g_screen_width/6; + + mid = g_screen_width / 2; + text_out16(mid - me_mfont_w * 15 / 2, 8 * me_mfont_h, "About to delete"); + smalltext_out16(mid - len * me_sfont_w / 2, 9 * me_mfont_h + 5, fname, 0xbdff); + text_out16(mid - me_mfont_w * 13 / 2, 11 * me_mfont_h, "Are you sure?"); + + nm = in_get_key_name(-1, -PBTN_MA3); + snprintf(tmp, sizeof(tmp), "(%s - confirm, ", nm); + len = strlen(tmp); + nm = in_get_key_name(-1, -PBTN_MBACK); + snprintf(tmp + len, sizeof(tmp) - len, "%s - cancel)", nm); + len = strlen(tmp); + + text_out16(mid - me_mfont_w * len / 2, 12 * me_mfont_h, tmp); + plat_video_menu_end(); + + while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MA2)); + inp = in_menu_wait(PBTN_MA3|PBTN_MBACK, 100); + if (inp & PBTN_MA3) + remove(fpath); +} + // -------------- ROM selector -------------- // rrrr rggg gggb bbbb @@ -607,9 +699,9 @@ static unsigned short file2color(const char *fname) static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel) { - int max_cnt, start, i, pos; + int max_cnt, start, i, x, pos; - max_cnt = SCREEN_HEIGHT / 10; + max_cnt = g_screen_height / me_sfont_h; start = max_cnt / 2 - sel; n--; // exclude current dir (".") @@ -618,23 +710,24 @@ static void draw_dirlist(char *curdir, struct dirent **namelist, int n, int sel) // if (!rom_loaded) // menu_darken_bg(gp2x_screen, 320*240, 0); - menu_darken_bg((short *)SCREEN_BUFFER + SCREEN_WIDTH * max_cnt/2 * 10, SCREEN_WIDTH * 8, 0); + menu_darken_bg((short *)g_screen_ptr + g_screen_width * max_cnt/2 * 10, g_screen_width * 8, 0); + x = 5 + me_mfont_w + 1; if (start - 2 >= 0) - smalltext_out16(14, (start - 2)*10, curdir, 0xffff); + smalltext_out16(14, (start - 2) * me_sfont_h, curdir, 0xffff); for (i = 0; i < n; i++) { pos = start + i; if (pos < 0) continue; if (pos >= max_cnt) break; if (namelist[i+1]->d_type == DT_DIR) { - smalltext_out16(14, pos*10, "/", 0xfff6); - smalltext_out16(14+6, pos*10, namelist[i+1]->d_name, 0xfff6); + smalltext_out16(x, pos * me_sfont_h, "/", 0xfff6); + smalltext_out16(x + me_sfont_w, pos * me_sfont_h, namelist[i+1]->d_name, 0xfff6); } else { unsigned short color = file2color(namelist[i+1]->d_name); - smalltext_out16(14, pos*10, namelist[i+1]->d_name, color); + smalltext_out16(x, pos * me_sfont_h, namelist[i+1]->d_name, color); } } - text_out16(5, max_cnt/2 * 10, ">"); + smalltext_out16(5, max_cnt/2 * me_sfont_h, ">", 0xffff); plat_video_menu_end(); } @@ -714,14 +807,14 @@ rescan: { draw_dirlist(curr_path, namelist, n, sel); inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT| - PBTN_L|PBTN_R|PBTN_WEST|PBTN_MOK|PBTN_MBACK|PBTN_MENU, 33); // TODO L R + PBTN_L|PBTN_R|PBTN_MA2|PBTN_MOK|PBTN_MBACK|PBTN_MENU, 33); if (inp & PBTN_UP ) { sel--; if (sel < 0) sel = n-2; } if (inp & PBTN_DOWN) { sel++; if (sel > n-2) sel = 0; } if (inp & PBTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } if (inp & PBTN_L) { sel-=24; if (sel < 0) sel = 0; } if (inp & PBTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } if (inp & PBTN_R) { sel+=24; if (sel > n-2) sel = n-2; } - if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_WEST)) == (PBTN_MENU|PBTN_WEST)) // enter dir/select || delete + if ((inp & PBTN_MOK) || (inp & (PBTN_MENU|PBTN_MA2)) == (PBTN_MENU|PBTN_MA2)) { again: if (namelist[sel+1]->d_type == DT_REG) @@ -733,7 +826,7 @@ rescan: ret = rom_fname_reload; break; } -// do_delete(rom_fname_reload, namelist[sel+1]->d_name); // TODO + do_delete(rom_fname_reload, namelist[sel+1]->d_name); if (n > 0) { while (n--) free(namelist[n]); free(namelist); @@ -801,7 +894,7 @@ static void draw_patchlist(int sel) { int max_cnt, start, i, pos, active; - max_cnt = SCREEN_HEIGHT / 10; + max_cnt = g_screen_height / 10; start = max_cnt / 2 - sel; plat_video_menu_begin(); @@ -811,14 +904,14 @@ static void draw_patchlist(int sel) if (pos < 0) continue; if (pos >= max_cnt) break; active = PicoPatches[i].active; - smalltext_out16(14, pos*10, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff); - smalltext_out16(14+6*4, pos*10, PicoPatches[i].name, active ? 0xfff6 : 0xffff); + smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff); + smalltext_out16(14+6*4, pos * me_sfont_h, PicoPatches[i].name, active ? 0xfff6 : 0xffff); } pos = start + i; if (pos < max_cnt) - smalltext_out16(14, pos * 10, "done", 0xffff); + smalltext_out16(14, pos * me_sfont_h, "done", 0xffff); - text_out16(5, max_cnt / 2 * 10, ">"); + text_out16(5, max_cnt / 2 * me_sfont_h, ">"); plat_video_menu_end(); } @@ -904,7 +997,7 @@ static void draw_savestate_bg(int slot) } /* do a frame and fetch menu bg */ - emu_forcedFrame(POPT_EN_SOFTSCALE); + pemu_forced_frame(POPT_EN_SOFTSCALE); plat_video_menu_enter(1); memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); @@ -921,23 +1014,22 @@ static void draw_savestate_menu(int menu_sel, int is_loading) if (state_slot_flags & (1 << menu_sel)) draw_savestate_bg(menu_sel); - w = 13 * 8 + 16; - h = (1+2+10+1) * 10; - x = SCREEN_WIDTH / 2 - w / 2; + w = (13 + 2) * me_mfont_w; + h = (1+2+10+1) * me_mfont_h; + x = g_screen_width / 2 - w / 2; if (x < 0) x = 0; - y = SCREEN_HEIGHT / 2 - h / 2; + y = g_screen_height / 2 - h / 2; if (y < 0) y = 0; plat_video_menu_begin(); text_out16(x, y, is_loading ? "Load state" : "Save state"); - y += 3*10; + y += 3 * me_mfont_h; - menu_draw_selection(x - 16, y + menu_sel * 10, 13 * 8 + 4); + menu_draw_selection(x - me_mfont_w * 2, y + menu_sel * me_mfont_h, (13 + 2) * me_mfont_w + 4); /* draw all 10 slots */ - y += 10; - for (i = 0; i < 10; i++, y += 10) + for (i = 0; i < 10; i++, y += me_mfont_h) { text_out16(x, y, "SLOT %i (%s)", i, (state_slot_flags & (1 << i)) ? "USED" : "free"); } @@ -976,7 +1068,7 @@ static int menu_loop_savestate(int is_loading) if (menu_sel < 10) { state_slot = menu_sel; if (emu_SaveLoadGame(is_loading, 0)) { - strcpy(menuErrorMsg, is_loading ? "Load failed" : "Save failed"); + me_update_msg(is_loading ? "Load failed" : "Save failed"); return 0; } return 1; @@ -1001,10 +1093,11 @@ static char *action_binds(int player_idx, int action_mask, int dev_id) if (binds == NULL) return static_buff; - count = in_get_dev_bind_count(dev_id); + count = in_get_dev_info(dev_id, IN_INFO_BIND_COUNT); for (k = 0; k < count; k++) { const char *xname; + int len; if (!(binds[k] & action_mask)) continue; @@ -1012,9 +1105,12 @@ static char *action_binds(int player_idx, int action_mask, int dev_id) continue; xname = in_get_key_name(dev_id, k); - if (static_buff[0]) - strncat(static_buff, " + ", sizeof(static_buff)); - strncat(static_buff, xname, sizeof(static_buff)); + len = strlen(static_buff); + if (len) { + strncat(static_buff, " + ", sizeof(static_buff) - len - 1); + len += 3; + } + strncat(static_buff, xname, sizeof(static_buff) - len - 1); } return static_buff; @@ -1030,7 +1126,7 @@ static int count_bound_keys(int dev_id, int action_mask, int player_idx) if (binds == NULL) return 0; - count = in_get_dev_bind_count(dev_id); + count = in_get_dev_info(dev_id, IN_INFO_BIND_COUNT); for (k = 0; k < count; k++) { if (!(binds[k] & action_mask)) @@ -1048,42 +1144,46 @@ static int count_bound_keys(int dev_id, int action_mask, int player_idx) static void draw_key_config(const me_bind_action *opts, int opt_cnt, int player_idx, int sel, int dev_id, int dev_count, int is_bind) { - int x, y = 30, w, i; const char *dev_name; + int x, y, w, i; - x = SCREEN_WIDTH / 2 - 32*8 / 2; - if (x < 0) x = 0; + w = ((player_idx >= 0) ? 20 : 30) * me_mfont_w; + x = g_screen_width / 2 - w / 2; + y = (g_screen_height - 4 * me_mfont_h) / 2 - (2 + opt_cnt) * me_mfont_h / 2; + if (x < me_mfont_w * 2) + x = me_mfont_w * 2; plat_video_menu_begin(); if (player_idx >= 0) - text_out16(x, 10, "Player %i controls", player_idx + 1); + text_out16(x, y, "Player %i controls", player_idx + 1); else - text_out16(x, 10, "Emulator controls"); + text_out16(x, y, "Emulator controls"); - menu_draw_selection(x - 16, y + sel*10, (player_idx >= 0) ? 66 : 140); + y += 2 * me_mfont_h; + menu_draw_selection(x - me_mfont_w * 2, y + sel * me_mfont_h, w + 2 * me_mfont_w); - for (i = 0; i < opt_cnt; i++, y+=10) + for (i = 0; i < opt_cnt; i++, y += me_mfont_h) text_out16(x, y, "%s : %s", opts[i].name, action_binds(player_idx, opts[i].mask, dev_id)); dev_name = in_get_dev_name(dev_id, 1, 1); - w = strlen(dev_name) * 8; - if (w < 30 * 8) - w = 30 * 8; - if (w > SCREEN_WIDTH) - w = SCREEN_WIDTH; + w = strlen(dev_name) * me_mfont_w; + if (w < 30 * me_mfont_w) + w = 30 * me_mfont_w; + if (w > g_screen_width) + w = g_screen_width; - x = SCREEN_WIDTH / 2 - w / 2; + x = g_screen_width / 2 - w / 2; if (dev_count > 1) { - text_out16(x, SCREEN_HEIGHT - 4*10, "Viewing binds for:"); - text_out16(x, SCREEN_HEIGHT - 3*10, dev_name); + text_out16(x, g_screen_height - 4 * me_mfont_h, "Viewing binds for:"); + text_out16(x, g_screen_height - 3 * me_mfont_h, dev_name); } if (is_bind) - text_out16(x, SCREEN_HEIGHT - 2*10, "Press a button to bind/unbind"); + text_out16(x, g_screen_height - 2 * me_mfont_h, "Press a button to bind/unbind"); else if (dev_count > 1) - text_out16(x, SCREEN_HEIGHT - 2*10, "Press left/right for other devs"); + text_out16(x, g_screen_height - 2 * me_mfont_h, "Press left/right for other devs"); plat_video_menu_end(); } @@ -1144,7 +1244,12 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_ for (is_down = 1; is_down; ) kc = in_update_keycode(&dev_id, &is_down, -1); - unbind = count_bound_keys(dev_id, opts[sel].mask, player_idx) >= 2; + i = count_bound_keys(dev_id, opts[sel].mask, player_idx); + unbind = (i > 0); + + /* allow combos if device supports them */ + if (i == 1 && in_get_dev_info(dev_id, IN_INFO_DOES_COMBOS)) + unbind = 0; in_bind_key(dev_id, kc, opts[sel].mask, unbind); if (player_idx >= 0) { @@ -1181,19 +1286,19 @@ me_bind_action me_ctrl_actions[15] = // "LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE" me_bind_action emuctrl_actions[] = { - { "Load State ", 1<<28 }, - { "Save State ", 1<<27 }, - { "Prev Save Slot ", 1<<25 }, - { "Next Save Slot ", 1<<24 }, - { "Switch Renderer ", 1<<26 }, - { "Volume Down ", 1<<30 }, - { "Volume Up ", 1<<29 }, - { "Fast forward ", 1<<22 }, - { "Enter Menu ", 1<<23 }, - { "Pico Next page ", 1<<21 }, - { "Pico Prev page ", 1<<20 }, - { "Pico Switch input", 1<<19 }, - { NULL, 0 } + { "Load State ", PEV_STATE_LOAD }, + { "Save State ", PEV_STATE_SAVE }, + { "Prev Save Slot ", PEV_SSLOT_PREV }, + { "Next Save Slot ", PEV_SSLOT_NEXT }, + { "Switch Renderer ", PEV_SWITCH_RND }, + { "Volume Down ", PEV_VOL_DOWN }, + { "Volume Up ", PEV_VOL_UP }, + { "Fast forward ", PEV_FF }, + { "Enter Menu ", PEV_MENU }, + { "Pico Next page ", PEV_PICO_PNEXT }, + { "Pico Prev page ", PEV_PICO_PPREV }, + { "Pico Switch input", PEV_PICO_SWINP }, + { NULL, 0 } }; static int key_config_loop_wrap(menu_id id, int keys) @@ -1311,15 +1416,6 @@ static int menu_loop_cd_options(menu_id id, int keys) // ------------ adv options menu ------------ -// TODO FIXME fix if and mv -static const char *mgn_aopt_sqhack(menu_id id, int *offs) -{ - *offs = -10; - sprintf(static_buff, "%s, %s", 111 ? " active" : "inactive", - (currentConfig.EmuOpt & 0x10) ? "ON" : "OFF"); - return static_buff; -} - static menu_entry e_menu_adv_options[] = { mee_onoff ("SRAM/BRAM saves", MA_OPT_SRAM_STATES, currentConfig.EmuOpt, EOPT_USE_SRAM), @@ -1330,9 +1426,8 @@ static menu_entry e_menu_adv_options[] = mee_onoff ("Emulate SN76496 (PSG)", MA_OPT2_ENABLE_SN76496,PicoOpt, POPT_EN_PSG), mee_onoff ("gzip savestates", MA_OPT2_GZIP_STATES, currentConfig.EmuOpt, EOPT_GZIP_SAVES), mee_onoff ("Don't save last used ROM", MA_OPT2_NO_LAST_ROM, currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG), - mee_label ("- needs restart -"), - mee_onoff ("craigix's RAM timings", MA_OPT2_RAMTIMINGS, currentConfig.EmuOpt, 0x0100), - mee_onoff_cust("Squidgehack", MA_OPT2_SQUIDGEHACK, currentConfig.EmuOpt, 0x0010, mgn_aopt_sqhack), + mee_onoff ("RAM overclock", MA_OPT2_RAMTIMINGS, currentConfig.EmuOpt, EOPT_RAM_TIMINGS), + mee_onoff ("MMU hack", MA_OPT2_SQUIDGEHACK, currentConfig.EmuOpt, EOPT_MMUHACK), mee_onoff ("SVP dynarec", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), mee_onoff ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoOpt, POPT_DIS_IDLE_DET), mee_end, @@ -1349,12 +1444,12 @@ static int menu_loop_adv_options(menu_id id, int keys) static const char *mgn_opt_scaling(menu_id id, int *offs) { - *offs = -12; + *offs = -13; switch (currentConfig.scaling) { - default: return " OFF"; - case 1: return "hw horizontal"; - case 2: return "hw horiz. + vert."; - case 3: return "sw horizontal"; + default: return " OFF"; + case EOPT_SCALE_HW_H: return " hw horizontal"; + case EOPT_SCALE_HW_HV: return "hw horiz. + vert"; + case EOPT_SCALE_SW_H: return " sw horizontal"; } } @@ -1368,8 +1463,8 @@ static menu_entry e_menu_gfx_options[] = { mee_range_cust("Scaling", MA_OPT_SCALING, currentConfig.scaling, 0, 3, mgn_opt_scaling), mee_range_cust("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma), - mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, 0x1000), - mee_onoff ("Perfect vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, 0x2000), + mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA), + mee_onoff ("Perfect vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_PSYNC), mee_end, }; @@ -1493,15 +1588,15 @@ static int mh_saveloadcfg(menu_id id, int keys) case MA_OPT_SAVECFG: case MA_OPT_SAVECFG_GAME: if (emu_WriteConfig(id == MA_OPT_SAVECFG_GAME ? 1 : 0)) - strcpy(menuErrorMsg, "config saved"); + me_update_msg("config saved"); else - strcpy(menuErrorMsg, "failed to write config"); + me_update_msg("failed to write config"); break; case MA_OPT_LOADCFG: ret = emu_ReadConfig(1, 1); if (!ret) ret = emu_ReadConfig(0, 1); - if (ret) strcpy(menuErrorMsg, "config loaded"); - else strcpy(menuErrorMsg, "failed to load config"); + if (ret) me_update_msg("config loaded"); + else me_update_msg("failed to load config"); break; default: return 0; @@ -1598,11 +1693,7 @@ static menu_entry e_menu_options[] = mee_onoff ("Enable sound", MA_OPT_ENABLE_SOUND, currentConfig.EmuOpt, 0x004), mee_cust ("Sound Quality", MA_OPT_SOUND_QUALITY, mh_opt_misc, mgn_opt_sound), mee_cust ("Confirm savestate", MA_OPT_CONFIRM_STATES,mh_opt_misc, mgn_opt_c_saves), -#if defined(__GP2X__) - mee_range ("GP2X CPU clocks", MA_OPT_CPU_CLOCKS, currentConfig.CPUclock, 20, 400), -#elif defined(PSP) - mee_range ("PSP CPU clock", MA_OPT_CPU_CLOCKS, currentConfig.CPUclock, ) -#endif + mee_range (cpu_clk_name, MA_OPT_CPU_CLOCKS, currentConfig.CPUclock, 20, 900), mee_handler ("[Display options]", menu_loop_gfx_options), mee_handler ("[Advanced options]", menu_loop_adv_options), mee_handler ("[Sega/Mega CD options]", menu_loop_cd_options), @@ -1630,25 +1721,23 @@ static int menu_loop_options(menu_id id, int keys) // ------------ debug menu ------------ -#include -#include - #include extern void SekStepM68k(void); static void mplayer_loop(void) { - emu_startSound(); + pemu_sound_start(); while (1) { PDebugZ80Frame(); - if (in_menu_wait_any(0) & PBTN_NORTH) break; - emu_waitSound(); + if (in_menu_wait_any(0) & PBTN_MA3) + break; + pemu_sound_wait(); } - emu_endSound(); + pemu_sound_stop(); } static void draw_text_debug(const char *str, int skip, int from) @@ -1659,17 +1748,21 @@ static void draw_text_debug(const char *str, int skip, int from) p = str; while (skip-- > 0) { - while (*p && *p != '\n') p++; - if (*p == 0 || p[1] == 0) return; + while (*p && *p != '\n') + p++; + if (*p == 0 || p[1] == 0) + return; p++; } str = p; - for (line = from; line < SCREEN_HEIGHT/10; line++) + for (line = from; line < g_screen_height / me_sfont_h; line++) { - while (*p && *p != '\n') p++; - smalltext_out16(1, line*10, str, 0xffff); - if (*p == 0) break; + smalltext_out16(1, line * me_sfont_h, str, 0xffff); + while (*p && *p != '\n') + p++; + if (*p == 0) + break; p++; str = p; } } @@ -1682,9 +1775,10 @@ static void draw_frame_debug(void) if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6); if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6); - clear_screen(); - emu_forcedFrame(0); - smalltext_out16(4, SCREEN_HEIGHT-8, layer_str, 0xffff); + memset(g_screen_ptr, 0, g_screen_width * g_screen_height * 2); + pemu_forced_frame(0); + smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, 0xffff); + smalltext_out16(4, g_screen_height - me_sfont_h, layer_str, 0xffff); } static void debug_menu_loop(void) @@ -1699,29 +1793,30 @@ static void debug_menu_loop(void) { case 0: plat_video_menu_begin(); tmp = PDebugMain(); - emu_platformDebugCat(tmp); + plat_debug_cat(tmp); draw_text_debug(tmp, 0, 0); if (dumped) { - smalltext_out16(SCREEN_WIDTH-6*10, SCREEN_HEIGHT-8, "dumped", 0xffff); + smalltext_out16(g_screen_width - 6 * me_sfont_h, + g_screen_height - me_mfont_h, "dumped", 0xffff); dumped = 0; } break; case 1: draw_frame_debug(); break; - case 2: clear_screen(); - emu_forcedFrame(0); - darken_screen(); - PDebugShowSpriteStats((unsigned short *)SCREEN_BUFFER + (SCREEN_HEIGHT/2 - 240/2)*SCREEN_WIDTH + - SCREEN_WIDTH/2 - 320/2, SCREEN_WIDTH); break; - case 3: clear_screen(); - PDebugShowPalette(SCREEN_BUFFER, SCREEN_WIDTH); - PDebugShowSprite((unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH*120+SCREEN_WIDTH/2+16, - SCREEN_WIDTH, spr_offs); + case 2: memset(g_screen_ptr, 0, g_screen_width * g_screen_height * 2); + pemu_forced_frame(0); + menu_darken_bg(g_screen_ptr, g_screen_width * g_screen_height, 0); + PDebugShowSpriteStats((unsigned short *)g_screen_ptr + (g_screen_height/2 - 240/2)*g_screen_width + + g_screen_width/2 - 320/2, g_screen_width); break; + case 3: memset(g_screen_ptr, 0, g_screen_width * g_screen_height * 2); + PDebugShowPalette(g_screen_ptr, g_screen_width); + PDebugShowSprite((unsigned short *)g_screen_ptr + g_screen_width*120 + g_screen_width/2 + 16, + g_screen_width, spr_offs); draw_text_debug(PDebugSpriteList(), spr_offs, 6); break; } plat_video_menu_end(); - inp = in_menu_wait(PBTN_EAST|PBTN_MBACK|PBTN_WEST|PBTN_NORTH|PBTN_L|PBTN_R | + inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R | PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, 70); if (inp & PBTN_MBACK) return; if (inp & PBTN_L) { mode--; if (mode < 0) mode = 3; } @@ -1729,15 +1824,17 @@ static void debug_menu_loop(void) switch (mode) { case 0: - if (inp & PBTN_EAST) SekStepM68k(); - if (inp & PBTN_NORTH) { - while (inp & PBTN_NORTH) inp = in_menu_wait_any(-1); + if (inp & PBTN_MOK) + SekStepM68k(); + if (inp & PBTN_MA3) { + while (inp & PBTN_MA3) + inp = in_menu_wait_any(-1); mplayer_loop(); } - if ((inp & (PBTN_WEST|PBTN_LEFT)) == (PBTN_WEST|PBTN_LEFT)) { + if ((inp & (PBTN_MA2|PBTN_LEFT)) == (PBTN_MA2|PBTN_LEFT)) { mkdir("dumps", 0777); PDebugDumpMem(); - while (inp & PBTN_WEST) inp = in_menu_wait_any(-1); + while (inp & PBTN_MA2) inp = in_menu_wait_any(-1); dumped = 1; } break; @@ -1746,12 +1843,12 @@ static void debug_menu_loop(void) if (inp & PBTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON; if (inp & PBTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON; if (inp & PBTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON; - if (inp & PBTN_EAST) { + if (inp & PBTN_MOK) { PsndOut = NULL; // just in case PicoSkipFrame = 1; PicoFrame(); PicoSkipFrame = 0; - while (inp & PBTN_EAST) inp = in_menu_wait_any(-1); + while (inp & PBTN_MOK) inp = in_menu_wait_any(-1); } break; case 3: @@ -1799,7 +1896,7 @@ static int main_menu_handler(menu_id id, int keys) break; case MA_MAIN_RESET_GAME: if (rom_loaded) { - emu_ResetGame(); + emu_reset_game(); return 1; } break; @@ -1822,7 +1919,7 @@ static int main_menu_handler(menu_id id, int keys) if (rom_loaded && PicoPatches) { menu_loop_patches(); PicoPatchApply(); - strcpy(menuErrorMsg, "Patches applied"); + me_update_msg("Patches applied"); } break; default: @@ -1835,6 +1932,10 @@ static int main_menu_handler(menu_id id, int keys) static menu_entry e_menu_main[] = { + mee_label ("PicoDrive " VERSION), + mee_label (""), + mee_label (""), + mee_label (""), mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler), mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler), mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler), @@ -1861,13 +1962,15 @@ void menu_loop(void) plat_video_menu_enter(rom_loaded); in_set_blocking(1); me_loop(e_menu_main, &sel); - in_set_blocking(0); - if (rom_loaded && engineState == PGS_Menu) { + if (rom_loaded) { + if (engineState == PGS_Menu) + engineState = PGS_Running; /* wait until menu, ok, back is released */ while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK)); - engineState = PGS_Running; } + + in_set_blocking(0); } // --------- CD tray close menu ---------- @@ -1886,8 +1989,7 @@ static int mh_tray_load_cd(menu_id id, int keys) if (cd_type != CIT_NOT_CD) ret = Insert_CD(ret_name, cd_type); if (ret != 0) { - sprintf(menuErrorMsg, "Load failed, invalid CD image?"); - lprintf("%s\n", menuErrorMsg); + me_update_msg("Load failed, invalid CD image?"); return 0; } @@ -1918,7 +2020,6 @@ int menu_loop_tray(void) in_set_blocking(1); me_loop(e_menu_tray, &sel); - in_set_blocking(0); if (engineState != PGS_RestartRun) { engineState = PGS_RestartRun; @@ -1926,14 +2027,40 @@ int menu_loop_tray(void) } while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK)); + in_set_blocking(0); return ret; } #endif // !UIQ3 +void me_update_msg(const char *msg) +{ + strncpy(menu_error_msg, msg, sizeof(menu_error_msg)); + menu_error_msg[sizeof(menu_error_msg) - 1] = 0; + + menu_error_time = plat_get_ticks_ms(); + lprintf("msg: %s\n", menu_error_msg); +} + // ------------ util ------------ +/* wiz for now, probably extend later */ +void menu_plat_setup(int is_wiz) +{ + int i; + + if (!is_wiz) + return; + + me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 0); + me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 0); + me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 0); + + i = me_id2offset(e_menu_gfx_options, MA_OPT_SCALING); + e_menu_gfx_options[i].max = 1; /* only off and sw */ +} + /* TODO: rename */ void menu_darken_bg(void *dst, int pixels, int darker) {