From 9caf44b59bf20d0beb614d4249cf908c7fb7434d Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Nov 2007 15:48:32 +0000 Subject: [PATCH] UI adjustments, nub support git-svn-id: file:///home/notaz/opt/svn/PicoDrive@291 be3aeb3a-fb24-0410-a615-afba39da0efa --- platform/common/emu.h | 2 +- platform/common/lprintf.h | 2 +- platform/common/menu.h | 1 + platform/psp/Makefile | 6 +- platform/psp/data/icon.png | Bin 19571 -> 12767 bytes platform/psp/emu.c | 31 +++++---- platform/psp/main.c | 2 + platform/psp/menu.c | 135 ++++++++++++++++++++----------------- platform/psp/menu.h | 3 +- platform/psp/psp.c | 49 ++++++++++++-- platform/psp/psp.h | 8 +++ 11 files changed, 152 insertions(+), 87 deletions(-) diff --git a/platform/common/emu.h b/platform/common/emu.h index 42a1bfb..b4f3c26 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -9,7 +9,7 @@ typedef struct { // squidgehack, no_save_cfg_on_exit, , 16_bit_mode // craigix_ram, confirm_save, show_cd_leds, confirm_load // A_SNs_gamma, perfect_vsync, giz_scanlines, giz_dblbuff - // vsync_mode + // vsync_mode, show_clock int PicoOpt; // used for config saving only, see Pico.h int PsndRate; // ditto int PicoRegion; // ditto diff --git a/platform/common/lprintf.h b/platform/common/lprintf.h index dc49c65..a8d9ee1 100644 --- a/platform/common/lprintf.h +++ b/platform/common/lprintf.h @@ -2,7 +2,7 @@ #include #define lprintf printf #elif defined(PSP) - #if 1 + #ifdef LPRINTF_STDIO #include #define lprintf printf #else diff --git a/platform/common/menu.h b/platform/common/menu.h index 2635967..df990d3 100644 --- a/platform/common/menu.h +++ b/platform/common/menu.h @@ -63,6 +63,7 @@ typedef enum MA_OPT2_NO_LAST_ROM, MA_OPT2_RAMTIMINGS, /* gp2x */ MA_OPT2_SQUIDGEHACK, /* gp2x */ + MA_OPT2_STATUS_LINE, /* psp */ MA_OPT2_DONE, MA_OPT3_SCALE, /* psp (all OPT3) */ MA_OPT3_HSCALE32, diff --git a/platform/psp/Makefile b/platform/psp/Makefile index 49f9f7b..d60078e 100644 --- a/platform/psp/Makefile +++ b/platform/psp/Makefile @@ -10,7 +10,7 @@ amalgamate = 0 #up = 1 -CFLAGS += -I../.. -I. -DNO_SYNC +CFLAGS += -I../.. -I. -DNO_SYNC -DLPRINTF_STDIO CFLAGS += -Wall -Winline -G0 ifeq ($(DEBUG),) CFLAGS += -O2 -ftracer -fstrength-reduce -ffast-math @@ -76,12 +76,12 @@ endif OBJS += data/bg32.o data/bg40.o -LIBS += -lpng -lm -lpspgu -lpsppower -Wl,-Map=PicoDrive.map -lpspaudio +LIBS += -lpng -lm -lpspgu -lpsppower -lpspaudio -lpsprtc -Wl,-Map=PicoDrive.map # target TARGET = PicoDrive EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = PICODRIVE +PSP_EBOOT_TITLE = PicoDrive PSP_EBOOT_ICON = data/icon.png #PSP_EBOOT_PIC1 = .png diff --git a/platform/psp/data/icon.png b/platform/psp/data/icon.png index 757a40b4dda3291b28e2753f4da1d38f7c4d1d1b..4bb5ac0018b4cb565e0c87f060dd83bb3e7e4c5a 100644 GIT binary patch literal 12767 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 NE@zvpt5>zdEtmtZ9!_m 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 ikNVmx_}cT8JpT(Q=ou!dfb_cn0000s68k_regs[0] ^ old_reg) & 3)) return; // no change - old_reg = Pico_mcd->s68k_regs[0]; + reg = Pico_mcd->s68k_regs[0]; p = (unsigned int *)((short *)psp_screen + 512*2+4+2); - col_g = (old_reg & 2) ? 0x06000600 : 0; - col_r = (old_reg & 1) ? 0x00180018 : 0; + col_g = (reg & 2) ? 0x06000600 : 0; + col_r = (reg & 1) ? 0x00180018 : 0; *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; @@ -798,23 +802,22 @@ static void find_combos(void) if (act == 16 || act == 17) continue; // player2 flag if (act > 17) { - for (u = 0; u < 32; u++) + for (u = 0; u < 28; u++) // 28 because nub can't produce combos if (currentConfig.KeyBinds[u] & (1 << act)) keyc++; } else { - for (u = 0; u < 32; u++) + for (u = 0; u < 28; u++) if ((currentConfig.KeyBinds[u] & 0x30000) == 0 && // pl. 1 (currentConfig.KeyBinds[u] & (1 << act))) keyc++; - for (u = 0; u < 32; u++) + for (u = 0; u < 28; u++) if ((currentConfig.KeyBinds[u] & 0x30000) == 1 && // pl. 2 (currentConfig.KeyBinds[u] & (1 << act))) keyc2++; - if (keyc2 > keyc) keyc = keyc2; } - if (keyc > 1) + if (keyc > 1 || keyc2 > 1) { // loop again and mark those keys and actions as combo - for (u = 0; u < 32; u++) + for (u = 0; u < 28; u++) { if (currentConfig.KeyBinds[u] & (1 << act)) { combo_keys |= 1 << u; diff --git a/platform/psp/main.c b/platform/psp/main.c index 606ca02..0d12196 100644 --- a/platform/psp/main.c +++ b/platform/psp/main.c @@ -4,9 +4,11 @@ #include "../common/menu.h" #include "../common/emu.h" #include "../common/lprintf.h" +#include "version.h" int main() { + lprintf("\nPicoDrive v" VERSION " " __DATE__ " " __TIME__ "\n"); psp_init(); emu_ReadConfig(0, 0); diff --git a/platform/psp/menu.c b/platform/psp/menu.c index cdcf1e6..ccb472b 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -33,10 +33,10 @@ #define pspKeyUnkn "???" static const char * const pspKeyNames[] = { - "SELECT", pspKeyUnkn, pspKeyUnkn, "START", "UP", "RIGHT", "DOWN", "LEFT", - "L", "R", pspKeyUnkn, pspKeyUnkn, "TRIANGLE", "CIRCLE", "X", "SQUARE", - "HOME", "HOLD", "WLAN_UP", "REMOTE", "VOLUP", "VOLDOWN", "SCREEN", "NOTE", - pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn + "SELECT", pspKeyUnkn, pspKeyUnkn, "START", "UP", "RIGHT", "DOWN", "LEFT", + "L", "R", pspKeyUnkn, pspKeyUnkn, "TRIANGLE", "CIRCLE", "X", "SQUARE", + "HOME", "HOLD", "WLAN_UP", "REMOTE", "VOLUP", "VOLDOWN", "SCREEN", "NOTE", + pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, "NUB UP", "NUB RIGHT", "NUB DOWN", "NUB LEFT" // fake }; static unsigned short bg_buffer[480*272] __attribute__((aligned(16))); @@ -48,11 +48,14 @@ static void menu_prepare_bg(int use_game_bg, int use_fg); static unsigned int inp_prev = 0; -static unsigned long wait_for_input(unsigned int interesting) +static unsigned long wait_for_input(unsigned int interesting, int is_key_config) { unsigned int ret; static int repeats = 0, wait = 50; - int release = 0, i; + int release = 0, count, i; + + if (!is_key_config) + interesting |= (interesting & 0xf0) << 24; // also use analog if (repeats == 2 || repeats == 4) wait /= 2; if (repeats == 6) wait = 15; @@ -62,7 +65,7 @@ static unsigned long wait_for_input(unsigned int interesting) psp_msleep(wait); } - while ( !((ret = psp_pad_read(1)) & interesting) ) { + for (count = 0; !((ret = psp_pad_read(1)) & interesting) && count < 100; count++) { psp_msleep(50); release = 1; } @@ -73,6 +76,9 @@ static unsigned long wait_for_input(unsigned int interesting) } inp_prev = ret; + if (!is_key_config) + ret |= (ret & 0xf0000000) >> 24; // use analog as d-pad + // we don't need diagonals in menus if ((ret&BTN_UP) && (ret&BTN_LEFT)) ret &= ~BTN_LEFT; if ((ret&BTN_UP) && (ret&BTN_RIGHT)) ret &= ~BTN_RIGHT; @@ -350,14 +356,14 @@ static char *romsel_loop(char *curr_path) for (;;) { draw_dirlist(curr_path, namelist, n, sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE, 0); if(inp & BTN_UP ) { sel--; if (sel < 0) sel = n-2; } if(inp & BTN_DOWN) { sel++; if (sel > n-2) sel = 0; } if(inp & BTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } if(inp & BTN_L) { sel-=24; if (sel < 0) sel = 0; } if(inp & BTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } if(inp & BTN_R) { sel+=24; if (sel > n-2) sel = n-2; } - if(inp & BTN_X) { // enter dir/select + if(inp & BTN_CIRCLE) { // enter dir/select if (namelist[sel+1]->d_type & DT_REG) { strcpy(romFileName, curr_path); strcat(romFileName, "/"); @@ -386,7 +392,7 @@ static char *romsel_loop(char *curr_path) break; } } - if(inp & BTN_CIRCLE) break; // cancel + if(inp & BTN_X) break; // cancel } if (n > 0) { @@ -424,7 +430,7 @@ static void draw_debug(void) static void debug_menu_loop(void) { draw_debug(); - wait_for_input(BTN_X|BTN_CIRCLE); + wait_for_input(BTN_X|BTN_CIRCLE, 0); } // ------------ patch/gg menu ------------ @@ -461,17 +467,17 @@ static void patches_menu_loop(void) for(;;) { draw_patchlist(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE, 0); if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = PicoPatchCount; } if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > PicoPatchCount) menu_sel = 0; } if(inp &(BTN_LEFT|BTN_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; } if(inp &(BTN_RIGHT|BTN_R)) { menu_sel+=10; if (menu_sel > PicoPatchCount) menu_sel = PicoPatchCount; } - if(inp & BTN_X) { // action + if(inp & BTN_CIRCLE) { // action if (menu_sel < PicoPatchCount) PicoPatches[menu_sel].active = !PicoPatches[menu_sel].active; else return; } - if(inp & BTN_CIRCLE) return; + if(inp & BTN_X) return; } } @@ -591,7 +597,7 @@ static int savestate_menu_loop(int is_loading) for(;;) { draw_savestate_menu(menu_sel, is_loading); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE, 0); if(inp & BTN_UP ) { do { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; @@ -602,7 +608,7 @@ static int savestate_menu_loop(int is_loading) menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading); } - if(inp & BTN_X) { // save/load + if(inp & BTN_CIRCLE) { // save/load if (menu_sel < 10) { state_slot = menu_sel; PicoStateProgressCB = emu_msg_cb; /* also suitable for menu */ @@ -613,7 +619,7 @@ static int savestate_menu_loop(int is_loading) return 0; } else return 1; } - if(inp & BTN_CIRCLE) return 1; + if(inp & BTN_X) return 1; } } @@ -630,7 +636,11 @@ static char *action_binds(int player_idx, int action_mask) if (currentConfig.KeyBinds[i] & action_mask) { if (player_idx >= 0 && ((currentConfig.KeyBinds[i] >> 16) & 3) != player_idx) continue; - if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, pspKeyNames[i]); break; } + if (strkeys[0]) { + strcat(strkeys, i >= 28 ? ", " : " + "); // nub "buttons" don't create combos + strcat(strkeys, pspKeyNames[i]); + break; + } else strcpy(strkeys, pspKeyNames[i]); } } @@ -683,14 +693,14 @@ static void draw_key_config(const bind_action_t *opts, int opt_cnt, int player_i text_out16(x, y, "Done"); if (sel < opt_cnt) { - text_out16(80+30, 180, "Press a button to bind/unbind"); - text_out16(80+30, 190, "Use SELECT to clear"); - text_out16(80+30, 200, "To bind UP/DOWN, hold SELECT"); - text_out16(80+30, 210, "Select \"Done\" to exit"); + text_out16(80+30, 220, "Press a button to bind/unbind"); + text_out16(80+30, 230, "Use SELECT to clear"); + text_out16(80+30, 240, "To bind UP/DOWN, hold SELECT"); + text_out16(80+30, 250, "Select \"Done\" to exit"); } else { - text_out16(80+30, 190, "Use Options -> Save cfg"); - text_out16(80+30, 200, "to save controls"); - text_out16(80+30, 210, "Press X or O to exit"); + text_out16(80+30, 230, "Use Options -> Save cfg"); + text_out16(80+30, 240, "to save controls"); + text_out16(80+30, 250, "Press X or O to exit"); } menu_draw_end(); } @@ -703,7 +713,7 @@ static void key_config_loop(const bind_action_t *opts, int opt_cnt, int player_i for (;;) { draw_key_config(opts, opt_cnt, player_idx, sel); - inp = wait_for_input(CONFIGURABLE_KEYS|BTN_SELECT); + inp = wait_for_input(CONFIGURABLE_KEYS|BTN_SELECT, 1); if (!(inp & BTN_SELECT)) { prev_select = 0; if(inp & BTN_UP ) { sel--; if (sel < 0) sel = menu_sel_max; continue; } @@ -776,8 +786,6 @@ static bind_action_t emuctrl_actions[] = { "Prev Save Slot ", 1<<25 }, { "Next Save Slot ", 1<<24 }, { "Switch Renderer", 1<<26 }, - { "Volume Down ", 1<<30 }, - { "Volume Up ", 1<<29 }, }; static void kc_sel_loop(void) @@ -789,10 +797,10 @@ static void kc_sel_loop(void) while (1) { draw_kc_sel(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE, 0); if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } - if (inp & BTN_X) { + if (inp & BTN_CIRCLE) { switch (menu_sel) { case 0: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 0); return; case 1: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 1); return; @@ -802,7 +810,7 @@ static void kc_sel_loop(void) default: return; } } - if (inp & BTN_CIRCLE) return; + if (inp & BTN_X) return; } } @@ -870,7 +878,7 @@ static void draw_cd_menu_options(int menu_sel, struct bios_names_t *bios_names) if ((selected_id == MA_CDOPT_TESTBIOS_USA && strcmp(bios_names->us, "NOT FOUND")) || (selected_id == MA_CDOPT_TESTBIOS_EUR && strcmp(bios_names->eu, "NOT FOUND")) || (selected_id == MA_CDOPT_TESTBIOS_JAP && strcmp(bios_names->jp, "NOT FOUND"))) - text_out16(tl_x, 210, "Press start to test selected BIOS"); + text_out16(tl_x, 250, "Press start to test selected BIOS"); menu_draw_end(); } @@ -902,7 +910,7 @@ static void cd_menu_loop_options(void) for(;;) { draw_cd_menu_options(menu_sel, &bios_names); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE, 0); if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel); @@ -919,7 +927,7 @@ static void cd_menu_loop_options(void) } } } - if (inp & BTN_X) { // toggleable options + if (inp & BTN_CIRCLE) { // toggleable options if (!me_process(cdopt_entries, CDOPT_ENTRY_COUNT, selected_id, 1) && selected_id == MA_CDOPT_DONE) { return; @@ -950,7 +958,7 @@ static void cd_menu_loop_options(void) break; } } - if (inp & BTN_CIRCLE) return; + if (inp & BTN_X) return; } } @@ -1054,7 +1062,7 @@ static void dispmenu_loop_options(void) for (;;) { draw_dispmenu_options(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE, 0); if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } selected_id = me_index2id(opt3_entries, OPT3_ENTRY_COUNT, menu_sel); @@ -1087,7 +1095,7 @@ static void dispmenu_loop_options(void) } } } - if (inp & BTN_X) { // toggleable options + if (inp & BTN_CIRCLE) { // toggleable options me_process(opt3_entries, OPT3_ENTRY_COUNT, selected_id, 1); switch (selected_id) { case MA_OPT3_DONE: @@ -1108,7 +1116,7 @@ static void dispmenu_loop_options(void) default: break; } } - if (inp & BTN_CIRCLE) return; + if (inp & BTN_X) return; } } @@ -1117,11 +1125,12 @@ static void dispmenu_loop_options(void) menu_entry opt2_entries[] = { - { "Emulate Z80", MB_ONOFF, MA_OPT2_ENABLE_Z80, ¤tConfig.PicoOpt,0x0004, 0, 0, 1 }, - { "Emulate YM2612 (FM)", MB_ONOFF, MA_OPT2_ENABLE_YM2612, ¤tConfig.PicoOpt,0x0001, 0, 0, 1 }, - { "Emulate SN76496 (PSG)", MB_ONOFF, MA_OPT2_ENABLE_SN76496,¤tConfig.PicoOpt,0x0002, 0, 0, 1 }, - { "gzip savestates", MB_ONOFF, MA_OPT2_GZIP_STATES, ¤tConfig.EmuOpt, 0x0008, 0, 0, 1 }, - { "Don't save last used ROM", MB_ONOFF, MA_OPT2_NO_LAST_ROM, ¤tConfig.EmuOpt, 0x0020, 0, 0, 1 }, + { "Emulate Z80", MB_ONOFF, MA_OPT2_ENABLE_Z80, ¤tConfig.PicoOpt,0x00004, 0, 0, 1 }, + { "Emulate YM2612 (FM)", MB_ONOFF, MA_OPT2_ENABLE_YM2612, ¤tConfig.PicoOpt,0x00001, 0, 0, 1 }, + { "Emulate SN76496 (PSG)", MB_ONOFF, MA_OPT2_ENABLE_SN76496,¤tConfig.PicoOpt,0x00002, 0, 0, 1 }, + { "gzip savestates", MB_ONOFF, MA_OPT2_GZIP_STATES, ¤tConfig.EmuOpt, 0x00008, 0, 0, 1 }, + { "Don't save last used ROM", MB_ONOFF, MA_OPT2_NO_LAST_ROM, ¤tConfig.EmuOpt, 0x00020, 0, 0, 1 }, + { "Status line in main menu", MB_ONOFF, MA_OPT2_STATUS_LINE, ¤tConfig.EmuOpt, 0x20000, 0, 0, 1 }, { "done", MB_NONE, MA_OPT2_DONE, NULL, 0, 0, 0, 1 }, }; @@ -1153,7 +1162,7 @@ static void amenu_loop_options(void) for(;;) { draw_amenu_options(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE, 0); if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } selected_id = me_index2id(opt2_entries, OPT2_ENTRY_COUNT, menu_sel); @@ -1163,13 +1172,13 @@ static void amenu_loop_options(void) // TODO? } } - if (inp & BTN_X) { // toggleable options + if (inp & BTN_CIRCLE) { // toggleable options if (!me_process(opt2_entries, OPT2_ENTRY_COUNT, selected_id, 1) && selected_id == MA_OPT2_DONE) { return; } } - if (inp & BTN_CIRCLE) return; + if (inp & BTN_X) return; } } @@ -1360,7 +1369,7 @@ static int menu_loop_options(void) while (1) { draw_menu_options(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE, 0); if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } selected_id = me_index2id(opt_entries, OPT_ENTRY_COUNT, menu_sel); @@ -1421,7 +1430,7 @@ static int menu_loop_options(void) } } } - if (inp & BTN_X) { + if (inp & BTN_CIRCLE) { if (!me_process(opt_entries, OPT_ENTRY_COUNT, selected_id, 1)) { switch (selected_id) @@ -1459,7 +1468,7 @@ static int menu_loop_options(void) } } } - if(inp & BTN_CIRCLE) { + if(inp & BTN_X) { menu_options_save(); return 0; // done (update, no write) } @@ -1512,11 +1521,15 @@ menu_entry main_entries[] = static void draw_menu_root(int menu_sel) { - const int tl_x = 80+70, tl_y = 16+70; + const int tl_x = 86+70, tl_y = 16+70; + char *stat = NULL; menu_draw_begin(); - text_out16(tl_x, 16+20, "PicoDrive v" VERSION); + if ((currentConfig.EmuOpt&0x20000) && (stat = psp_get_status_line())) + text_out16(287, 12, "%s", stat); + + text_out16(tl_x, 48, "PicoDrive v" VERSION); menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 146); @@ -1552,23 +1565,23 @@ static void menu_loop_root(void) for (;;) { draw_menu_root(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE|BTN_SELECT|BTN_L|BTN_R); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE|BTN_SELECT|BTN_L|BTN_R, 0); if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } if((inp & (BTN_L|BTN_R)) == (BTN_L|BTN_R)) debug_menu_loop(); - if( inp & (BTN_SELECT|BTN_CIRCLE)) { + if( inp & (BTN_SELECT|BTN_X)) { if (rom_data) { - while (psp_pad_read(1) & (BTN_SELECT|BTN_CIRCLE)) psp_msleep(50); // wait until released + while (psp_pad_read(1) & (BTN_SELECT|BTN_X)) psp_msleep(50); // wait until released engineState = PGS_Running; break; } } - if(inp & BTN_X) { + if(inp & BTN_CIRCLE) { switch (me_index2id(main_entries, MAIN_ENTRY_COUNT, menu_sel)) { case MA_MAIN_RESUME_GAME: if (rom_data) { - while (psp_pad_read(1) & BTN_X) psp_msleep(50); + while (psp_pad_read(1) & BTN_CIRCLE) psp_msleep(50); engineState = PGS_Running; return; } @@ -1627,7 +1640,9 @@ static void menu_loop_root(void) case MA_MAIN_CREDITS: draw_menu_credits(); psp_msleep(500); - inp = wait_for_input(BTN_X|BTN_CIRCLE); + inp = 0; + while (!(inp & (BTN_X|BTN_CIRCLE))) + inp = wait_for_input(BTN_X|BTN_CIRCLE, 0); break; case MA_MAIN_EXIT: engineState = PGS_Quit; @@ -1757,15 +1772,15 @@ int menu_loop_tray(void) /* make sure action buttons are not pressed on entering menu */ draw_menu_tray(menu_sel); - while (psp_pad_read(1) & BTN_X) psp_msleep(50); + while (psp_pad_read(1) & BTN_CIRCLE) psp_msleep(50); for (;;) { draw_menu_tray(menu_sel); - inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X, 0); if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } - if(inp & BTN_X ) { + if(inp & BTN_CIRCLE) { switch (menu_sel) { case 0: // select image selfname = romsel_loop(curr_path); diff --git a/platform/psp/menu.h b/platform/psp/menu.h index fa6c90c..a36b2a4 100644 --- a/platform/psp/menu.h +++ b/platform/psp/menu.h @@ -9,5 +9,6 @@ void menu_romload_prepare(const char *rom_name); void menu_romload_end(void); -#define CONFIGURABLE_KEYS (BTN_UP|BTN_LEFT|BTN_RIGHT|BTN_DOWN|BTN_L|BTN_R|BTN_TRIANGLE|BTN_CIRCLE|BTN_X|BTN_SQUARE|BTN_START|BTN_NOTE) +#define CONFIGURABLE_KEYS (BTN_UP|BTN_LEFT|BTN_RIGHT|BTN_DOWN|BTN_L|BTN_R|BTN_TRIANGLE|BTN_CIRCLE|BTN_X|BTN_SQUARE|BTN_START| \ + BTN_NUB_UP|BTN_NUB_RIGHT|BTN_NUB_DOWN|BTN_NUB_LEFT|BTN_NOTE) diff --git a/platform/psp/psp.c b/platform/psp/psp.c index b2d0d72..a21507f 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "psp.h" @@ -18,7 +19,7 @@ unsigned int __attribute__((aligned(16))) guCmdList[GU_CMDLIST_SIZE]; void *psp_screen = VRAM_FB0; static int current_screen = 0; /* front bufer */ -static SceUID logfd = -1; +#define ANALOG_DEADZONE 80 /* Exit callback */ static int exit_callback(int arg1, int arg2, void *common) @@ -47,6 +48,7 @@ void psp_init(void) { SceUID thid; + lprintf("running in %08x kernel\n", sceKernelDevkitVersion()), lprintf("entered psp_init, threadId %i, priority %i\n", sceKernelGetThreadId(), sceKernelGetThreadCurrentPriority()); @@ -93,7 +95,7 @@ void psp_init(void) /* input */ sceCtrlSetSamplingCycle(0); - sceCtrlSetSamplingMode(0); + sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); } void psp_finish(void) @@ -132,12 +134,21 @@ void psp_msleep(int ms) unsigned int psp_pad_read(int blocking) { + unsigned int buttons; SceCtrlData pad; if (blocking) sceCtrlReadBufferPositive(&pad, 1); else sceCtrlPeekBufferPositive(&pad, 1); + buttons = pad.Buttons; + + // analog.. + buttons &= ~(BTN_NUB_UP|BTN_NUB_DOWN|BTN_NUB_LEFT|BTN_NUB_RIGHT); + if (pad.Lx < 128 - ANALOG_DEADZONE) buttons |= BTN_NUB_LEFT; + if (pad.Lx > 128 + ANALOG_DEADZONE) buttons |= BTN_NUB_RIGHT; + if (pad.Ly < 128 - ANALOG_DEADZONE) buttons |= BTN_NUB_UP; + if (pad.Ly > 128 + ANALOG_DEADZONE) buttons |= BTN_NUB_DOWN; - return pad.Buttons; + return buttons; } int psp_get_cpu_clock(void) @@ -153,19 +164,42 @@ int psp_set_cpu_clock(int clock) return ret; } +char *psp_get_status_line(void) +{ + static char buff[64]; + int ret, bat_percent, bat_time; + pspTime time; + + ret = sceRtcGetCurrentClockLocalTime(&time); + bat_percent = scePowerGetBatteryLifePercent(); + bat_time = scePowerGetBatteryLifeTime(); + if (ret < 0 || bat_percent < 0 || bat_time < 0) return NULL; + + snprintf(buff, sizeof(buff), "%02i:%02i bat: %3i%%", time.hour, time.minutes, bat_percent); + if (!scePowerIsPowerOnline()) + snprintf(buff+strlen(buff), sizeof(buff)-strlen(buff), " (%i:%02i)", bat_time/60, bat_time%60); + return buff; +} + /* alt logging */ #define LOG_FILE "log.log" +static SceUID logfd = -1; + void lprintf_f(const char *fmt, ...) { va_list vl; char buff[256]; + if (logfd == -2) return; // disabled + if (logfd < 0) { logfd = sceIoOpen(LOG_FILE, PSP_O_WRONLY|PSP_O_APPEND, 0777); - if (logfd < 0) + if (logfd < 0) { + logfd = -2; return; + } } va_start(vl, fmt); @@ -173,9 +207,10 @@ void lprintf_f(const char *fmt, ...) va_end(vl); sceIoWrite(logfd, buff, strlen(buff)); -//sceKernelDelayThread(200 * 1000); -sceIoClose(logfd); -logfd = -1; + + // make sure it gets flushed + sceIoClose(logfd); + logfd = -1; } diff --git a/platform/psp/psp.h b/platform/psp/psp.h index 8a2828e..7f2d70d 100644 --- a/platform/psp/psp.h +++ b/platform/psp/psp.h @@ -36,6 +36,8 @@ unsigned int psp_pad_read(int blocking); int psp_get_cpu_clock(void); int psp_set_cpu_clock(int clock); +char *psp_get_status_line(void); + /* shorter btn names */ #define BTN_UP PSP_CTRL_UP #define BTN_LEFT PSP_CTRL_LEFT @@ -51,3 +53,9 @@ int psp_set_cpu_clock(int clock); #define BTN_START PSP_CTRL_START #define BTN_NOTE PSP_CTRL_NOTE // doesn't seem to work? +/* fake 'nub' btns */ +#define BTN_NUB_UP (1 << 28) +#define BTN_NUB_RIGHT (1 << 29) +#define BTN_NUB_DOWN (1 << 30) +#define BTN_NUB_LEFT (1 << 31) + -- 2.39.2