savestate loader in menu
[libpicofe.git] / gp2x / menu.c
index 9ffbd40..9a2914a 100644 (file)
@@ -18,6 +18,7 @@
 #include "version.h"\r
 \r
 #include "Pico/PicoInt.h"\r
+#include "zlib/zlib.h"\r
 \r
 #ifndef _DIRENT_HAVE_D_TYPE\r
 #error "need d_type for file browser\r
@@ -390,6 +391,139 @@ static char *romsel_loop(char *curr_path)
        return ret;\r
 }\r
 \r
+// ------------ savestate loader ------------\r
+\r
+static void menu_prepare_bg(void);\r
+\r
+static int state_slot_flags = 0;\r
+\r
+static void state_check_slots(void)\r
+{\r
+       int slot;\r
+\r
+       state_slot_flags = 0;\r
+\r
+       for (slot = 0; slot < 10; slot++)\r
+       {\r
+               if (emu_check_save_file(slot))\r
+               {\r
+                       state_slot_flags |= 1 << slot;\r
+               }\r
+       }\r
+}\r
+\r
+static void draw_savestate_bg(int slot)\r
+{\r
+       struct PicoVideo tmp_pv;\r
+       unsigned short tmp_cram[0x40];\r
+       unsigned short tmp_vsram[0x40];\r
+       void *tmp_vram, *file;\r
+       char *fname;\r
+\r
+       fname = emu_GetSaveFName(1, 0, slot);\r
+       if (!fname) return;\r
+\r
+       tmp_vram = malloc(sizeof(Pico.vram));\r
+       if (tmp_vram == NULL) return;\r
+\r
+       memcpy(tmp_vram, Pico.vram, sizeof(Pico.vram));\r
+       memcpy(tmp_cram, Pico.cram, sizeof(Pico.cram));\r
+       memcpy(tmp_vsram, Pico.vsram, sizeof(Pico.vsram));\r
+       memcpy(&tmp_pv, &Pico.video, sizeof(Pico.video));\r
+\r
+       if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) {\r
+               file = gzopen(fname, "rb");\r
+               emu_set_save_cbs(1);\r
+       } else {\r
+               file = fopen(fname, "rb");\r
+               emu_set_save_cbs(0);\r
+       }\r
+\r
+       if (file) {\r
+               if (PicoMCD & 1) {\r
+                       PicoCdLoadStateGfx(file);\r
+               } else {\r
+                       areaSeek(file, 0x10020, SEEK_SET);  // skip header and RAM in state file\r
+                       areaRead(Pico.vram, 1, sizeof(Pico.vram), file);\r
+                       areaSeek(file, 0x2000, SEEK_CUR);\r
+                       areaRead(Pico.cram, 1, sizeof(Pico.cram), file);\r
+                       areaRead(Pico.vsram, 1, sizeof(Pico.vsram), file);\r
+                       areaSeek(file, 0x221a0, SEEK_SET);\r
+                       areaRead(&Pico.video, 1, sizeof(Pico.video), file);\r
+               }\r
+               areaClose(file);\r
+       }\r
+\r
+       emu_forced_frame();\r
+       gp2x_memcpy_buffers((1<<2), gp2x_screen, 0, 320*240*2);\r
+       menu_prepare_bg();\r
+\r
+       memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram));\r
+       memcpy(Pico.cram, tmp_cram, sizeof(Pico.cram));\r
+       memcpy(Pico.vsram, tmp_vsram, sizeof(Pico.vsram));\r
+       memcpy(&Pico.video, &tmp_pv,  sizeof(Pico.video));\r
+       free(tmp_vram);\r
+}\r
+\r
+static void draw_savestate_menu(int menu_sel, int is_loading)\r
+{\r
+       int tl_x = 25, tl_y = 60, y, i;\r
+\r
+       if (state_slot_flags & (1 << menu_sel))\r
+               draw_savestate_bg(menu_sel);\r
+       gp2x_pd_clone_buffer2();\r
+\r
+       gp2x_text_out8(tl_x, 30, is_loading ? "Load state" : "Save state");\r
+\r
+       /* draw all 10 slots */\r
+       y = tl_y;\r
+       for (i = 0; i < 10; i++, y+=10)\r
+       {\r
+               gp2x_text_out8(tl_x, y, "SLOT %i (%s)", i, (state_slot_flags & (1 << i)) ? "USED" : "free");\r
+       }\r
+       gp2x_text_out8(tl_x, y, "back");\r
+\r
+       // draw cursor\r
+       gp2x_text_out8(tl_x - 16, tl_y + menu_sel*10, ">");\r
+\r
+       gp2x_video_flip2();\r
+}\r
+\r
+static int savestate_menu_loop(int is_loading)\r
+{\r
+       int menu_sel = 10, menu_sel_max = 10;\r
+       unsigned long inp = 0;\r
+\r
+       state_check_slots();\r
+\r
+       for(;;)\r
+       {\r
+               draw_savestate_menu(menu_sel, is_loading);\r
+               inp = wait_for_input(GP2X_UP|GP2X_DOWN|GP2X_B|GP2X_X);\r
+               if(inp & GP2X_UP  ) {\r
+                       do {\r
+                               menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max;\r
+                       } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading);\r
+               }\r
+               if(inp & GP2X_DOWN) {\r
+                       do {\r
+                               menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0;\r
+                       } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading);\r
+               }\r
+               if(inp & GP2X_B) { // save/load\r
+                       if (menu_sel < 10) {\r
+                               state_slot = menu_sel;\r
+                               if (emu_SaveLoadGame(is_loading, 0)) {\r
+                                       strcpy(menuErrorMsg, is_loading ? "Load failed" : "Save failed");\r
+                                       return 1;\r
+                               }\r
+                               return 0;\r
+                       } else  return 1;\r
+               }\r
+               if(inp & GP2X_X) return 1;\r
+       }\r
+}\r
+\r
 // -------------- key config --------------\r
 \r
 static char *usb_joy_key_name(int joy, int num)\r
@@ -1018,20 +1152,16 @@ static void menu_loop_root(void)
                                        break;\r
                                case 1: // save state\r
                                        if (rom_data) {\r
-                                               if(emu_SaveLoadGame(0, 0)) {\r
-                                                       strcpy(menuErrorMsg, "save failed");\r
+                                               if(savestate_menu_loop(0))\r
                                                        continue;\r
-                                               }\r
                                                engineState = PGS_Running;\r
                                                return;\r
                                        }\r
                                        break;\r
                                case 2: // load state\r
                                        if (rom_data) {\r
-                                               if(emu_SaveLoadGame(1, 0)) {\r
-                                                       strcpy(menuErrorMsg, "load failed");\r
+                                               if(savestate_menu_loop(1))\r
                                                        continue;\r
-                                               }\r
                                                engineState = PGS_Running;\r
                                                return;\r
                                        }\r
@@ -1074,21 +1204,29 @@ static void menu_loop_root(void)
 }\r
 \r
 \r
-static void menu_gfx_prepare(void)\r
+static void menu_prepare_bg(void)\r
 {\r
        extern int localPal[0x100];\r
-       int i;\r
+       int c, i;\r
 \r
        // don't clear old palette just for fun (but make it dark)\r
-       for (i = 0x100-1; i >= 0; i--)\r
-               localPal[i] = (localPal[i] >> 2) & 0x003f3f3f;\r
+       for (i = 0x100-1; i >= 0; i--) {\r
+               c = localPal[i];\r
+               localPal[i] = ((c >> 1) & 0x007f7f7f) - ((c >> 3) & 0x001f1f1f);\r
+       }\r
        localPal[0xe0] = 0x00000000; // reserved pixels for OSD\r
        localPal[0xf0] = 0x00ffffff;\r
 \r
+       gp2x_video_setpalette(localPal, 0x100);\r
+}\r
+\r
+static void menu_gfx_prepare(void)\r
+{\r
+       menu_prepare_bg();\r
+\r
        // switch to 8bpp\r
        gp2x_video_changemode2(8);\r
        gp2x_video_RGB_setscaling(320, 240);\r
-       gp2x_video_setpalette(localPal, 0x100);\r
        gp2x_video_flip2();\r
 }\r
 \r