2015-08-30 01:44:58 +02:00
|
|
|
#include "menu.h"
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <psp2/types.h>
|
|
|
|
|
|
|
|
#include <psp2/rtc.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <psp2/io/stat.h>
|
|
|
|
|
|
|
|
#include "emumain.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "shared.h"
|
|
|
|
|
|
|
|
#include "psplib/pl_file.h"
|
|
|
|
#include "psplib/image.h"
|
|
|
|
#include "psplib/ui.h"
|
|
|
|
#include "psplib/pl_menu.h"
|
|
|
|
#include "psplib/ctrl.h"
|
|
|
|
#include "psplib/pl_util.h"
|
|
|
|
#include "psplib/pl_psp.h"
|
|
|
|
#include "psplib/pl_ini.h"
|
|
|
|
#include "psplib/pl_rewind.h"
|
|
|
|
|
|
|
|
#define TAB_QUICKLOAD 0
|
|
|
|
#define TAB_STATE 1
|
|
|
|
#define TAB_CONTROL 2
|
|
|
|
#define TAB_OPTION 3
|
|
|
|
#define TAB_SYSTEM 4
|
|
|
|
#define TAB_ABOUT 5
|
|
|
|
#define TAB_MAX TAB_SYSTEM
|
|
|
|
|
|
|
|
#define OPTION_DISPLAY_MODE 0x01
|
|
|
|
#define OPTION_SYNC_FREQ 0x02
|
|
|
|
#define OPTION_FRAMESKIP 0x03
|
|
|
|
#define OPTION_VSYNC 0x04
|
|
|
|
#define OPTION_CLOCK_FREQ 0x05
|
|
|
|
#define OPTION_SHOW_FPS 0x06
|
|
|
|
#define OPTION_CONTROL_MODE 0x07
|
|
|
|
#define OPTION_ANIMATE 0x08
|
|
|
|
#define OPTION_AUTOFIRE 0x09
|
|
|
|
#define OPTION_REWIND_SAVE_RATE 0x0A
|
|
|
|
#define OPTION_REWIND_REPLAY_DELAY 0x0B
|
|
|
|
|
|
|
|
#define SYSTEM_SCRNSHOT 0x11
|
|
|
|
#define SYSTEM_RESET 0x12
|
|
|
|
#define SYSTEM_VERT_STRIP 0x13
|
|
|
|
#define SYSTEM_SOUND_ENGINE 0x14
|
|
|
|
#define SYSTEM_SOUND_BOOST 0x15
|
|
|
|
|
|
|
|
extern PspImage *Screen;
|
|
|
|
extern pl_rewind Rewinder;
|
|
|
|
|
|
|
|
EmulatorOptions Options;
|
|
|
|
|
|
|
|
static int ControlsModified;
|
|
|
|
static int TabIndex;
|
|
|
|
static int ResumeEmulation;
|
|
|
|
static PspImage *Background;
|
|
|
|
static PspImage *NoSaveIcon;
|
|
|
|
|
|
|
|
static const char *QuickloadFilter[] = { "BIN", "SMS", "GG", "ZIP", '\0' },
|
|
|
|
PresentSlotText[] = "\026\244\020 Save\t\026\001\020 Load\t\026\243\020 Delete",
|
|
|
|
EmptySlotText[] = "\026\244\020 Save",
|
|
|
|
ControlHelpText[] = "\026\250\020 Change mapping\t\026\243\020 Load defaults";
|
|
|
|
|
|
|
|
pl_file_path CurrentGame = "",
|
|
|
|
GamePath,
|
|
|
|
SaveStatePath,
|
|
|
|
ScreenshotPath;
|
|
|
|
|
|
|
|
#define SET_AS_CURRENT_GAME(filename) \
|
|
|
|
strncpy(CurrentGame, filename, sizeof(CurrentGame) - 1)
|
|
|
|
#define CURRENT_GAME (CurrentGame)
|
|
|
|
#define GAME_LOADED (CurrentGame[0] != '\0')
|
|
|
|
|
|
|
|
#define WIDTH 256
|
|
|
|
#define HEIGHT 192
|
|
|
|
|
|
|
|
/* Tab labels */
|
|
|
|
static const char *TabLabel[] =
|
|
|
|
{
|
|
|
|
"Game",
|
|
|
|
"Save/Load",
|
|
|
|
"Controls",
|
|
|
|
"Options",
|
|
|
|
"System",
|
|
|
|
"About"
|
|
|
|
};
|
|
|
|
|
|
|
|
static void LoadOptions();
|
|
|
|
static int SaveOptions();
|
|
|
|
|
|
|
|
static void InitButtonConfig();
|
|
|
|
static int SaveButtonConfig();
|
|
|
|
static int LoadButtonConfig();
|
|
|
|
|
|
|
|
static void DisplayStateTab();
|
|
|
|
static PspImage* LoadStateIcon(const char *path);
|
|
|
|
static int LoadState(const char *path);
|
|
|
|
static PspImage* SaveState(const char *path, PspImage *icon);
|
|
|
|
|
|
|
|
static int OnMenuItemChanged(const struct PspUiMenu *uimenu, pl_menu_item* item,
|
|
|
|
const pl_menu_option* option);
|
|
|
|
static int OnMenuOk(const void *uimenu, const void* sel_item);
|
|
|
|
static int OnMenuButtonPress(const struct PspUiMenu *uimenu,
|
|
|
|
pl_menu_item* sel_item, u32 button_mask);
|
|
|
|
|
|
|
|
static int OnSplashButtonPress(const struct PspUiSplash *splash,
|
|
|
|
u32 button_mask);
|
|
|
|
static void OnSplashRender(const void *uiobject, const void *null);
|
|
|
|
|
|
|
|
static int OnGenericCancel(const void *uiobject, const void *param);
|
|
|
|
static void OnGenericRender(const void *uiobject, const void *item_obj);
|
|
|
|
static int OnGenericButtonPress(const PspUiFileBrowser *browser,
|
|
|
|
const char *path, u32 button_mask);
|
|
|
|
|
|
|
|
static int OnSaveStateOk(const void *gallery, const void *item);
|
|
|
|
static int OnSaveStateButtonPress(const PspUiGallery *gallery,
|
|
|
|
pl_menu_item* item, u32 button_mask);
|
|
|
|
|
|
|
|
static int OnQuickloadOk(const void *browser, const void *path);
|
|
|
|
|
|
|
|
void OnSystemRender(const void *uiobject, const void *item_obj);
|
|
|
|
|
|
|
|
/* Menu options */
|
|
|
|
PL_MENU_OPTIONS_BEGIN(ToggleOptions)
|
|
|
|
PL_MENU_OPTION("Disabled", 0)
|
|
|
|
PL_MENU_OPTION("Enabled", 1)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(ScreenSizeOptions)
|
|
|
|
PL_MENU_OPTION("Actual size", DISPLAY_MODE_UNSCALED)
|
|
|
|
PL_MENU_OPTION("4:3 scaled (2x)", DISPLAY_MODE_2X)
|
|
|
|
PL_MENU_OPTION("4:3 scaled (3x)", DISPLAY_MODE_3X)
|
|
|
|
PL_MENU_OPTION("4:3 scaled (fit height)", DISPLAY_MODE_FIT_HEIGHT)
|
|
|
|
PL_MENU_OPTION("16:9 scaled (fit screen)", DISPLAY_MODE_FILL_SCREEN)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(FrameLimitOptions)
|
|
|
|
PL_MENU_OPTION("Disabled", 0)
|
|
|
|
PL_MENU_OPTION("60 fps (NTSC)", 60)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(FrameSkipOptions)
|
|
|
|
PL_MENU_OPTION("No skipping", 0)
|
|
|
|
PL_MENU_OPTION("Skip 1 frame", 1)
|
|
|
|
PL_MENU_OPTION("Skip 2 frames", 2)
|
|
|
|
PL_MENU_OPTION("Skip 3 frames", 3)
|
|
|
|
PL_MENU_OPTION("Skip 4 frames", 4)
|
|
|
|
PL_MENU_OPTION("Skip 5 frames", 5)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(PspClockFreqOptions)
|
|
|
|
PL_MENU_OPTION("222 MHz", 222)
|
|
|
|
PL_MENU_OPTION("266 MHz", 266)
|
|
|
|
PL_MENU_OPTION("300 MHz", 300)
|
|
|
|
PL_MENU_OPTION("333 MHz", 333)
|
2015-08-30 13:50:40 +02:00
|
|
|
PL_MENU_OPTION("444 MHz", 444)
|
2015-08-30 01:44:58 +02:00
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(AutofireOptions)
|
|
|
|
PL_MENU_OPTION("Once every 3 frames", 2)
|
|
|
|
PL_MENU_OPTION("Once every 10 frames", 9)
|
|
|
|
PL_MENU_OPTION("Once every 30 frames", 29)
|
|
|
|
PL_MENU_OPTION("Once every 60 frames", 59)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(ControlModeOptions)
|
|
|
|
PL_MENU_OPTION("\026\242\020 cancels, \026\241\020 confirms (US)", 0)
|
|
|
|
PL_MENU_OPTION("\026\241\020 cancels, \026\242\020 confirms (Japan)", 1)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(RewindSaveRateOptions)
|
|
|
|
PL_MENU_OPTION("Smoother", 2)
|
|
|
|
PL_MENU_OPTION("Longer", 5)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(RewindReplayDelayOptions)
|
|
|
|
PL_MENU_OPTION("50 ms", 50)
|
|
|
|
PL_MENU_OPTION("100 ms", 100)
|
|
|
|
PL_MENU_OPTION("500 ms", 500)
|
|
|
|
PL_MENU_OPTION("1 s", 1000)
|
|
|
|
PL_MENU_OPTION("2 s", 2000)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
PL_MENU_OPTIONS_BEGIN(ButtonMapOptions)
|
|
|
|
/* Unmapped */
|
|
|
|
PL_MENU_OPTION("None", 0)
|
|
|
|
/* Special */
|
|
|
|
PL_MENU_OPTION("Special: Open Menu", SPC|SPC_MENU)
|
|
|
|
PL_MENU_OPTION("Special: Rewind", SPC|SPC_REWIND)
|
|
|
|
/* Joystick */
|
|
|
|
PL_MENU_OPTION("Joystick Up", JOY|INPUT_UP)
|
|
|
|
PL_MENU_OPTION("Joystick Down", JOY|INPUT_DOWN)
|
|
|
|
PL_MENU_OPTION("Joystick Left", JOY|INPUT_LEFT)
|
|
|
|
PL_MENU_OPTION("Joystick Right", JOY|INPUT_RIGHT)
|
|
|
|
PL_MENU_OPTION("Joystick Button A", JOY|INPUT_A)
|
|
|
|
PL_MENU_OPTION("Joystick Button B", JOY|INPUT_B)
|
|
|
|
PL_MENU_OPTION("Joystick Button C", JOY|INPUT_C)
|
|
|
|
PL_MENU_OPTION("Joystick Button I (autofire)", AFI|INPUT_BUTTON1)
|
|
|
|
PL_MENU_OPTION("Joystick Button II (autofire)", AFI|INPUT_BUTTON2)
|
|
|
|
/* Joystick */
|
|
|
|
PL_MENU_OPTION("Start (GG) / Pause (SMS)", JOY|INPUT_START)
|
|
|
|
PL_MENU_OPTIONS_END
|
|
|
|
|
|
|
|
/* Menu items */
|
|
|
|
PL_MENU_ITEMS_BEGIN(OptionMenuDef)
|
|
|
|
PL_MENU_HEADER("Video")
|
|
|
|
PL_MENU_ITEM("Screen size", OPTION_DISPLAY_MODE, ScreenSizeOptions,
|
|
|
|
"\026\250\020 Change screen size")
|
|
|
|
PL_MENU_HEADER("Input")
|
|
|
|
PL_MENU_ITEM("Rate of autofire", OPTION_AUTOFIRE, AutofireOptions,
|
|
|
|
"\026\250\020 Adjust rate of autofire")
|
|
|
|
PL_MENU_HEADER("Performance")
|
|
|
|
PL_MENU_ITEM("Frame limiter", OPTION_SYNC_FREQ, FrameLimitOptions,
|
|
|
|
"\026\250\020 Change screen update frequency")
|
|
|
|
PL_MENU_ITEM("Frame skipping", OPTION_FRAMESKIP, FrameSkipOptions,
|
|
|
|
"\026\250\020 Change number of frames skipped per update")
|
|
|
|
PL_MENU_ITEM("VSync", OPTION_VSYNC, ToggleOptions,
|
|
|
|
"\026\250\020 Enable to reduce tearing; disable to increase speed")
|
|
|
|
PL_MENU_ITEM("PSP clock frequency", OPTION_CLOCK_FREQ, PspClockFreqOptions,
|
|
|
|
"\026\250\020 Larger values: faster emulation, faster battery depletion (default: 222MHz)")
|
|
|
|
PL_MENU_ITEM("Show FPS counter", OPTION_SHOW_FPS, ToggleOptions,
|
|
|
|
"\026\250\020 Show/hide the frames-per-second counter")
|
|
|
|
/*
|
|
|
|
PL_MENU_HEADER("Time rewind")
|
|
|
|
PL_MENU_ITEM("Rewind recording mode", OPTION_REWIND_SAVE_RATE,
|
|
|
|
RewindSaveRateOptions, "\026\250\020 Change rewind saving frequency")
|
|
|
|
PL_MENU_ITEM("Rewind delay", OPTION_REWIND_REPLAY_DELAY,
|
|
|
|
RewindReplayDelayOptions, "\026\250\020 Change delay between frames")
|
|
|
|
*/
|
|
|
|
PL_MENU_HEADER("Menu")
|
|
|
|
PL_MENU_ITEM("Button mode", OPTION_CONTROL_MODE, ControlModeOptions,
|
|
|
|
"\026\250\020 Change OK and Cancel button mapping")
|
|
|
|
PL_MENU_ITEM("Animations", OPTION_ANIMATE, ToggleOptions,
|
|
|
|
"\026\250\020 Enable/disable in-menu animations")
|
|
|
|
PL_MENU_ITEMS_END
|
|
|
|
PL_MENU_ITEMS_BEGIN(ControlMenuDef)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_ANALUP, MAP_ANALOG_UP, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_ANALDOWN, MAP_ANALOG_DOWN, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_ANALLEFT, MAP_ANALOG_LEFT, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_ANALRIGHT, MAP_ANALOG_RIGHT, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_UP, MAP_BUTTON_UP, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_DOWN, MAP_BUTTON_DOWN, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_LEFT, MAP_BUTTON_LEFT, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_RIGHT, MAP_BUTTON_RIGHT, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_SQUARE, MAP_BUTTON_SQUARE, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_CROSS, MAP_BUTTON_CROSS, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_CIRCLE, MAP_BUTTON_CIRCLE, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_TRIANGLE, MAP_BUTTON_TRIANGLE, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_LTRIGGER, MAP_BUTTON_LTRIGGER, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_RTRIGGER, MAP_BUTTON_RTRIGGER, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_SELECT, MAP_BUTTON_SELECT, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_START, MAP_BUTTON_START, ButtonMapOptions,
|
|
|
|
ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_RTRIGGER,
|
|
|
|
MAP_BUTTON_LRTRIGGERS, ButtonMapOptions, ControlHelpText)
|
|
|
|
PL_MENU_ITEM(PSP_CHAR_START"+"PSP_CHAR_SELECT,
|
|
|
|
MAP_BUTTON_STARTSELECT, ButtonMapOptions, ControlHelpText)
|
|
|
|
PL_MENU_ITEMS_END
|
|
|
|
PL_MENU_ITEMS_BEGIN(SystemMenuDef)
|
|
|
|
PL_MENU_HEADER("Video")
|
|
|
|
PL_MENU_ITEM("Vertical bar", SYSTEM_VERT_STRIP, ToggleOptions,
|
|
|
|
"\026\250\020 Show/hide the leftmost vertical bar (SMS)")
|
|
|
|
PL_MENU_HEADER("System")
|
|
|
|
PL_MENU_ITEM("Reset", SYSTEM_RESET, NULL, "\026\001\020 Reset")
|
|
|
|
PL_MENU_ITEM("Save screenshot", SYSTEM_SCRNSHOT, NULL,
|
|
|
|
"\026\001\020 Save screenshot")
|
|
|
|
PL_MENU_ITEMS_END
|
|
|
|
|
|
|
|
PspUiSplash SplashScreen =
|
|
|
|
{
|
|
|
|
OnSplashRender,
|
|
|
|
OnGenericCancel,
|
|
|
|
OnSplashButtonPress,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
PspUiGallery SaveStateGallery =
|
|
|
|
{
|
|
|
|
OnGenericRender, /* OnRender() */
|
|
|
|
OnSaveStateOk, /* OnOk() */
|
|
|
|
OnGenericCancel, /* OnCancel() */
|
|
|
|
OnSaveStateButtonPress, /* OnButtonPress() */
|
|
|
|
NULL /* Userdata */
|
|
|
|
};
|
|
|
|
|
|
|
|
PspUiMenu OptionUiMenu =
|
|
|
|
{
|
|
|
|
OnGenericRender, /* OnRender() */
|
|
|
|
OnMenuOk, /* OnOk() */
|
|
|
|
OnGenericCancel, /* OnCancel() */
|
|
|
|
OnMenuButtonPress, /* OnButtonPress() */
|
|
|
|
OnMenuItemChanged, /* OnItemChanged() */
|
|
|
|
};
|
|
|
|
|
|
|
|
PspUiMenu ControlUiMenu =
|
|
|
|
{
|
|
|
|
OnGenericRender, /* OnRender() */
|
|
|
|
OnMenuOk, /* OnOk() */
|
|
|
|
OnGenericCancel, /* OnCancel() */
|
|
|
|
OnMenuButtonPress, /* OnButtonPress() */
|
|
|
|
OnMenuItemChanged, /* OnItemChanged() */
|
|
|
|
};
|
|
|
|
|
|
|
|
PspUiFileBrowser QuickloadBrowser =
|
|
|
|
{
|
|
|
|
OnGenericRender,
|
|
|
|
OnQuickloadOk,
|
|
|
|
OnGenericCancel,
|
|
|
|
OnGenericButtonPress,
|
|
|
|
QuickloadFilter,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
PspUiMenu SystemUiMenu =
|
|
|
|
{
|
|
|
|
OnSystemRender, /* OnRender() */
|
|
|
|
OnMenuOk, /* OnOk() */
|
|
|
|
OnGenericCancel, /* OnCancel() */
|
|
|
|
OnMenuButtonPress, /* OnButtonPress() */
|
|
|
|
OnMenuItemChanged, /* OnItemChanged() */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Game configuration (includes button maps) */
|
|
|
|
struct ButtonConfig ActiveConfig;
|
|
|
|
|
|
|
|
/* Default configuration */
|
|
|
|
struct ButtonConfig DefaultConfig =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
JOY|INPUT_UP, /* Analog Up */
|
|
|
|
JOY|INPUT_DOWN, /* Analog Down */
|
|
|
|
JOY|INPUT_LEFT, /* Analog Left */
|
|
|
|
JOY|INPUT_RIGHT, /* Analog Right */
|
|
|
|
JOY|INPUT_UP, /* D-pad Up */
|
|
|
|
JOY|INPUT_DOWN, /* D-pad Down */
|
|
|
|
JOY|INPUT_LEFT, /* D-pad Left */
|
|
|
|
JOY|INPUT_RIGHT, /* D-pad Right */
|
|
|
|
JOY|INPUT_A,/* Square */
|
|
|
|
JOY|INPUT_B,/* Cross */
|
|
|
|
JOY|INPUT_C,/* Circle */
|
|
|
|
0, /* Triangle */
|
|
|
|
0, /* L Trigger */
|
|
|
|
0, /* R Trigger */
|
|
|
|
0, /* Select */
|
|
|
|
JOY|INPUT_START,
|
|
|
|
/* Start */
|
|
|
|
SPC|SPC_MENU, /* L+R Triggers */
|
|
|
|
0, /* Start+Select */
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Button masks */
|
|
|
|
const u64 ButtonMask[] =
|
|
|
|
{
|
|
|
|
PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER,
|
|
|
|
PSP_CTRL_START | PSP_CTRL_SELECT,
|
|
|
|
PSP_CTRL_ANALUP, PSP_CTRL_ANALDOWN,
|
|
|
|
PSP_CTRL_ANALLEFT, PSP_CTRL_ANALRIGHT,
|
|
|
|
PSP_CTRL_UP, PSP_CTRL_DOWN,
|
|
|
|
PSP_CTRL_LEFT, PSP_CTRL_RIGHT,
|
|
|
|
PSP_CTRL_SQUARE, PSP_CTRL_CROSS,
|
|
|
|
PSP_CTRL_CIRCLE, PSP_CTRL_TRIANGLE,
|
|
|
|
PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER,
|
|
|
|
PSP_CTRL_SELECT, PSP_CTRL_START,
|
|
|
|
0 /* End */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Button map ID's */
|
|
|
|
const int ButtonMapId[] =
|
|
|
|
{
|
|
|
|
MAP_BUTTON_LRTRIGGERS,
|
|
|
|
MAP_BUTTON_STARTSELECT,
|
|
|
|
MAP_ANALOG_UP, MAP_ANALOG_DOWN,
|
|
|
|
MAP_ANALOG_LEFT, MAP_ANALOG_RIGHT,
|
|
|
|
MAP_BUTTON_UP, MAP_BUTTON_DOWN,
|
|
|
|
MAP_BUTTON_LEFT, MAP_BUTTON_RIGHT,
|
|
|
|
MAP_BUTTON_SQUARE, MAP_BUTTON_CROSS,
|
|
|
|
MAP_BUTTON_CIRCLE, MAP_BUTTON_TRIANGLE,
|
|
|
|
MAP_BUTTON_LTRIGGER, MAP_BUTTON_RTRIGGER,
|
|
|
|
MAP_BUTTON_SELECT, MAP_BUTTON_START,
|
|
|
|
-1 /* End */
|
|
|
|
};
|
|
|
|
|
|
|
|
void InitMenu()
|
|
|
|
{
|
|
|
|
/* Reset variables */
|
|
|
|
TabIndex = TAB_ABOUT;
|
|
|
|
Background = NULL;
|
|
|
|
|
|
|
|
/* Initialize paths */
|
|
|
|
sprintf(SaveStatePath, "%ssavedata/", pl_psp_get_app_directory());
|
|
|
|
sprintf(ScreenshotPath, "%sscreenshot/", pl_psp_get_app_directory());
|
|
|
|
sprintf(GamePath, "%s", pl_psp_get_app_directory());
|
|
|
|
|
|
|
|
if (!pl_file_exists(SaveStatePath))
|
|
|
|
pl_file_mkdir_recursive(SaveStatePath);
|
|
|
|
|
|
|
|
/* Initialize options */
|
|
|
|
LoadOptions();
|
|
|
|
|
|
|
|
InitEmulator();
|
|
|
|
|
|
|
|
/* Load the background image */
|
|
|
|
pl_file_path background;
|
|
|
|
snprintf(background, sizeof(background) - 1, "%sbackground.png",
|
|
|
|
pl_psp_get_app_directory());
|
|
|
|
Background = pspImageLoadPng(background);
|
|
|
|
//Background = pspImageLoadPng("background.png");
|
|
|
|
|
|
|
|
/* Init NoSaveState icon image */
|
|
|
|
NoSaveIcon = pspImageCreate(136, 114, PSP_IMAGE_16BPP);
|
|
|
|
pspImageClear(NoSaveIcon, RGB(0x0c,0,0x3f));
|
|
|
|
|
|
|
|
/* Initialize state menu */
|
|
|
|
int i;
|
|
|
|
pl_menu_item *item;
|
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
item = pl_menu_append_item(&SaveStateGallery.Menu, i, NULL);
|
|
|
|
pl_menu_set_item_help_text(item, EmptySlotText);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize menus */
|
|
|
|
pl_menu_create(&SystemUiMenu.Menu, SystemMenuDef);
|
|
|
|
pl_menu_create(&OptionUiMenu.Menu, OptionMenuDef);
|
|
|
|
pl_menu_create(&ControlUiMenu.Menu, ControlMenuDef);
|
|
|
|
|
|
|
|
/* Load default configuration */
|
|
|
|
LoadButtonConfig();
|
|
|
|
|
|
|
|
/* Initialize UI components */
|
|
|
|
UiMetric.Background = Background;
|
|
|
|
UiMetric.Font = &PspStockFont;
|
|
|
|
UiMetric.Left = 16;
|
|
|
|
UiMetric.Top = 48;
|
|
|
|
UiMetric.Right = 944;
|
|
|
|
UiMetric.Bottom = 500;
|
|
|
|
UiMetric.OkButton = (!Options.ControlMode) ? PSP_CTRL_CROSS : PSP_CTRL_CIRCLE;
|
|
|
|
UiMetric.CancelButton = (!Options.ControlMode) ? PSP_CTRL_CIRCLE : PSP_CTRL_CROSS;
|
|
|
|
UiMetric.ScrollbarColor = PSP_COLOR_GRAY;
|
|
|
|
UiMetric.ScrollbarBgColor = 0x44ffffff;
|
|
|
|
UiMetric.ScrollbarWidth = 10;
|
|
|
|
UiMetric.TextColor = PSP_COLOR_GRAY;
|
|
|
|
UiMetric.SelectedColor = PSP_COLOR_YELLOW;
|
|
|
|
UiMetric.SelectedBgColor = COLOR(0xff,0xff,0xff,0x44);
|
|
|
|
UiMetric.StatusBarColor = PSP_COLOR_WHITE;
|
|
|
|
UiMetric.BrowserFileColor = PSP_COLOR_GRAY;
|
|
|
|
UiMetric.BrowserDirectoryColor = PSP_COLOR_YELLOW;
|
|
|
|
UiMetric.GalleryIconsPerRow = 5;
|
|
|
|
UiMetric.GalleryIconMarginWidth = 8;
|
|
|
|
UiMetric.MenuItemMargin = 20;
|
|
|
|
UiMetric.MenuSelOptionBg = PSP_COLOR_BLACK;
|
|
|
|
UiMetric.MenuOptionBoxColor = PSP_COLOR_GRAY;
|
|
|
|
UiMetric.MenuOptionBoxBg = COLOR(0, 0, 33, 0xBB);
|
|
|
|
UiMetric.MenuDecorColor = PSP_COLOR_YELLOW;
|
|
|
|
UiMetric.DialogFogColor = COLOR(0, 0, 0, 88);
|
|
|
|
UiMetric.TitlePadding = 4;
|
|
|
|
|
|
|
|
UiMetric.TitleColor = PSP_COLOR_WHITE;
|
|
|
|
UiMetric.MenuFps = 30;
|
|
|
|
UiMetric.TabBgColor = COLOR(0x74,0x74,0xbe,0xff);
|
|
|
|
UiMetric.BrowserScreenshotPath = ScreenshotPath;
|
|
|
|
UiMetric.BrowserScreenshotDelay = 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisplayMenu()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
pl_menu_item *item;
|
|
|
|
|
|
|
|
/* Menu loop */
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ResumeEmulation = 0;
|
|
|
|
|
|
|
|
/* Set normal clock frequency */
|
2015-08-30 13:50:40 +02:00
|
|
|
pl_psp_set_clock_freq(222);
|
2015-08-30 01:44:58 +02:00
|
|
|
/* Set buttons to autorepeat */
|
|
|
|
pspCtrlSetPollingMode(PSP_CTRL_AUTOREPEAT);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* Display appropriate tab */
|
|
|
|
switch (TabIndex)
|
|
|
|
{
|
|
|
|
case TAB_STATE:
|
|
|
|
DisplayStateTab();
|
|
|
|
break;
|
|
|
|
case TAB_CONTROL:
|
|
|
|
/* Load current button mappings */
|
|
|
|
for (item = ControlUiMenu.Menu.items, i = 0; item; item = item->next, i++)
|
|
|
|
pl_menu_select_option_by_value(item, (void*)ActiveConfig.ButtonMap[i]);
|
|
|
|
|
|
|
|
ControlsModified = 0;
|
|
|
|
pspUiOpenMenu(&ControlUiMenu, NULL);
|
|
|
|
|
|
|
|
if (ControlsModified)
|
|
|
|
SaveButtonConfig();
|
|
|
|
|
|
|
|
break;
|
|
|
|
case TAB_QUICKLOAD:
|
|
|
|
pspUiOpenBrowser(&QuickloadBrowser,
|
|
|
|
(GAME_LOADED) ? CURRENT_GAME : GamePath);
|
|
|
|
break;
|
|
|
|
case TAB_SYSTEM:
|
|
|
|
item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_VERT_STRIP);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.VertStrip);
|
|
|
|
pspUiOpenMenu(&SystemUiMenu, NULL);
|
|
|
|
break;
|
|
|
|
case TAB_OPTION:
|
|
|
|
/* Init menu options */
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_DISPLAY_MODE);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.DisplayMode);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_SYNC_FREQ);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.UpdateFreq);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_FRAMESKIP);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)(int)Options.Frameskip);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_VSYNC);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.VSync);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_CLOCK_FREQ);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.ClockFreq);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_SHOW_FPS);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.ShowFps);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_CONTROL_MODE);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.ControlMode);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_ANIMATE);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)UiMetric.Animate);
|
|
|
|
item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_AUTOFIRE);
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.AutoFire);
|
|
|
|
|
|
|
|
if ((item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_REWIND_SAVE_RATE)))
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.RewindSaveRate);
|
|
|
|
if ((item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_REWIND_REPLAY_DELAY)))
|
|
|
|
pl_menu_select_option_by_value(item, (void*)Options.RewindReplayDelay);
|
|
|
|
|
|
|
|
pspUiOpenMenu(&OptionUiMenu, NULL);
|
|
|
|
break;
|
|
|
|
case TAB_ABOUT:
|
|
|
|
pspUiSplashScreen(&SplashScreen);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (!ExitPSP && !ResumeEmulation);
|
|
|
|
|
|
|
|
if (!ExitPSP)
|
|
|
|
{
|
|
|
|
/* Set clock frequency during emulation */
|
2015-08-30 13:50:40 +02:00
|
|
|
pl_psp_set_clock_freq(Options.ClockFreq);
|
2015-08-30 01:44:58 +02:00
|
|
|
/* Set buttons to normal mode */
|
|
|
|
pspCtrlSetPollingMode(PSP_CTRL_NORMAL);
|
|
|
|
|
|
|
|
/* Resume emulation */
|
|
|
|
if (ResumeEmulation)
|
|
|
|
{
|
|
|
|
if (UiMetric.Animate) pspUiFadeout();
|
|
|
|
RunEmulator();
|
|
|
|
if (UiMetric.Animate) pspUiFadeout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (!ExitPSP);
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnGenericCancel(const void *uiobject, const void* param)
|
|
|
|
{
|
|
|
|
if (GAME_LOADED) ResumeEmulation = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnSplashRender(const void *splash, const void *null)
|
|
|
|
{
|
|
|
|
int fh, i, x, y, height;
|
|
|
|
const char *lines[] =
|
|
|
|
{
|
|
|
|
PSP_APP_NAME" version "PSP_APP_VER" ("__DATE__")",
|
|
|
|
"\026https://github.com/frangarcj/Genesis-Plus-GX",
|
|
|
|
" ",
|
|
|
|
"2015 Frangarcj",
|
|
|
|
"2006 eke-eke",
|
|
|
|
"1998-2004 Charles MacDonald",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
fh = pspFontGetLineHeight(UiMetric.Font);
|
|
|
|
|
|
|
|
for (i = 0; lines[i]; i++);
|
|
|
|
height = fh * (i - 1);
|
|
|
|
|
|
|
|
/* Render lines */
|
|
|
|
for (i = 0, y = SCR_HEIGHT / 2 - height / 2; lines[i]; i++, y += fh)
|
|
|
|
{
|
|
|
|
x = SCR_WIDTH / 2 - pspFontGetTextWidth(UiMetric.Font, lines[i]) / 2;
|
|
|
|
pspVideoPrint(UiMetric.Font, x, y, lines[i], PSP_COLOR_GRAY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Render PSP status */
|
|
|
|
OnGenericRender(splash, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnSplashButtonPress(const struct PspUiSplash *splash,
|
|
|
|
u32 button_mask)
|
|
|
|
{
|
|
|
|
return OnGenericButtonPress(NULL, NULL, button_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handles drawing of generic items */
|
|
|
|
void OnGenericRender(const void *uiobject, const void *item_obj)
|
|
|
|
{
|
|
|
|
/* Draw tabs */
|
|
|
|
int height = pspFontGetLineHeight(UiMetric.Font);
|
|
|
|
int width;
|
|
|
|
int i, x;
|
|
|
|
for (i = 0, x = 5; i <= TAB_MAX; i++, x += width + 10)
|
|
|
|
{
|
|
|
|
width = -10;
|
|
|
|
|
|
|
|
if (!GAME_LOADED && (i == TAB_STATE || i == TAB_SYSTEM))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Determine width of text */
|
|
|
|
width = pspFontGetTextWidth(UiMetric.Font, TabLabel[i]);
|
|
|
|
|
|
|
|
/* Draw background of active tab */
|
|
|
|
if (i == TabIndex)
|
|
|
|
pspVideoFillRect(x - 5, 0, x + width + 5, height + 1, UiMetric.TabBgColor);
|
|
|
|
|
|
|
|
/* Draw name of tab */
|
|
|
|
pspVideoPrint(UiMetric.Font, x, 0, TabLabel[i], PSP_COLOR_WHITE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnGenericButtonPress(const PspUiFileBrowser *browser,
|
|
|
|
const char *path, u32 button_mask)
|
|
|
|
{
|
|
|
|
int tab_index;
|
|
|
|
|
|
|
|
/* If L or R are pressed, switch tabs */
|
|
|
|
if (button_mask & PSP_CTRL_LTRIGGER)
|
|
|
|
{
|
|
|
|
TabIndex--;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tab_index = TabIndex;
|
|
|
|
if (!GAME_LOADED && (TabIndex == TAB_STATE || TabIndex == TAB_SYSTEM)) TabIndex--;
|
|
|
|
if (TabIndex < 0) TabIndex = TAB_MAX;
|
|
|
|
} while (tab_index != TabIndex);
|
|
|
|
}
|
|
|
|
else if (button_mask & PSP_CTRL_RTRIGGER)
|
|
|
|
{
|
|
|
|
TabIndex++;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tab_index = TabIndex;
|
|
|
|
if (!GAME_LOADED && (TabIndex == TAB_STATE || TabIndex == TAB_SYSTEM)) TabIndex++;
|
|
|
|
if (TabIndex > TAB_MAX) TabIndex = 0;
|
|
|
|
} while (tab_index != TabIndex);
|
|
|
|
}
|
|
|
|
else if ((button_mask & (PSP_CTRL_START | PSP_CTRL_SELECT))
|
|
|
|
== (PSP_CTRL_START | PSP_CTRL_SELECT))
|
|
|
|
{
|
|
|
|
if (pl_util_save_vram_seq(ScreenshotPath, "ui"))
|
|
|
|
pspUiAlert("Saved successfully");
|
|
|
|
else
|
|
|
|
pspUiAlert("ERROR: Not saved");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnMenuItemChanged(const struct PspUiMenu *uimenu,
|
|
|
|
pl_menu_item* item, const pl_menu_option* option)
|
|
|
|
{
|
|
|
|
if (uimenu == &ControlUiMenu)
|
|
|
|
{
|
|
|
|
ControlsModified = 1;
|
|
|
|
ActiveConfig.ButtonMap[item->id] = (unsigned int)option->value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(item->id)
|
|
|
|
{
|
|
|
|
case SYSTEM_VERT_STRIP:
|
|
|
|
Options.VertStrip = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_DISPLAY_MODE:
|
|
|
|
Options.DisplayMode = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_SYNC_FREQ:
|
|
|
|
Options.UpdateFreq = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_FRAMESKIP:
|
|
|
|
Options.Frameskip = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_VSYNC:
|
|
|
|
Options.VSync = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_CLOCK_FREQ:
|
|
|
|
Options.ClockFreq = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_SHOW_FPS:
|
|
|
|
Options.ShowFps = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_CONTROL_MODE:
|
|
|
|
Options.ControlMode = (int)option->value;
|
|
|
|
UiMetric.OkButton = (!(int)option->value) ? PSP_CTRL_CROSS
|
|
|
|
: PSP_CTRL_CIRCLE;
|
|
|
|
UiMetric.CancelButton = (!(int)option->value) ? PSP_CTRL_CIRCLE
|
|
|
|
: PSP_CTRL_CROSS;
|
|
|
|
break;
|
|
|
|
case OPTION_ANIMATE:
|
|
|
|
UiMetric.Animate = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_AUTOFIRE:
|
|
|
|
Options.AutoFire = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_REWIND_SAVE_RATE:
|
|
|
|
Options.RewindSaveRate = (int)option->value;
|
|
|
|
break;
|
|
|
|
case OPTION_REWIND_REPLAY_DELAY:
|
|
|
|
Options.RewindReplayDelay = (int)option->value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
SaveOptions();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnMenuOk(const void *uimenu, const void* sel_item)
|
|
|
|
{
|
|
|
|
if (uimenu == &ControlUiMenu)
|
|
|
|
{
|
|
|
|
/* Save to MS */
|
|
|
|
if (SaveButtonConfig())
|
|
|
|
pspUiAlert("Changes saved");
|
|
|
|
else
|
|
|
|
pspUiAlert("ERROR: Changes not saved");
|
|
|
|
}
|
|
|
|
else if (uimenu == &SystemUiMenu)
|
|
|
|
{
|
|
|
|
switch (((const pl_menu_item*)sel_item)->id)
|
|
|
|
{
|
|
|
|
case SYSTEM_RESET:
|
|
|
|
|
|
|
|
/* Reset system */
|
|
|
|
if (pspUiConfirm("Reset the system?"))
|
|
|
|
{
|
|
|
|
ResumeEmulation = 1;
|
|
|
|
system_reset();
|
|
|
|
pl_rewind_reset(&Rewinder);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SYSTEM_SCRNSHOT:
|
|
|
|
|
|
|
|
/* Save screenshot */
|
|
|
|
if (!pl_util_save_image_seq(ScreenshotPath,
|
|
|
|
pl_file_get_filename(CURRENT_GAME),
|
|
|
|
Screen))
|
|
|
|
pspUiAlert("ERROR: Screenshot not saved");
|
|
|
|
else
|
|
|
|
pspUiAlert("Screenshot saved successfully");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnMenuButtonPress(const struct PspUiMenu *uimenu,
|
|
|
|
pl_menu_item* sel_item,
|
|
|
|
u32 button_mask)
|
|
|
|
{
|
|
|
|
if (uimenu == &ControlUiMenu)
|
|
|
|
{
|
|
|
|
if (button_mask & PSP_CTRL_TRIANGLE)
|
|
|
|
{
|
|
|
|
pl_menu_item *item;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Load default mapping */
|
|
|
|
InitButtonConfig();
|
|
|
|
ControlsModified = 1;
|
|
|
|
|
|
|
|
/* Modify the menu */
|
|
|
|
for (item = ControlUiMenu.Menu.items, i = 0; item; item = item->next, i++)
|
|
|
|
pl_menu_select_option_by_value(item, (void*)DefaultConfig.ButtonMap[i]);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return OnGenericButtonPress(NULL, NULL, button_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnQuickloadOk(const void *browser, const void *path)
|
|
|
|
{
|
|
|
|
int first_time = 0;
|
|
|
|
if (!GAME_LOADED)
|
|
|
|
first_time = 1;
|
|
|
|
|
|
|
|
if (!load_rom((char*)path))
|
|
|
|
{
|
|
|
|
pspUiAlert("Error loading cartridge");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_AS_CURRENT_GAME((char*)path);
|
|
|
|
pl_file_get_parent_directory((const char*)path,
|
|
|
|
GamePath,
|
|
|
|
sizeof(GamePath));
|
|
|
|
|
|
|
|
/* Reset selected state */
|
|
|
|
SaveStateGallery.Menu.selected = NULL;
|
|
|
|
|
|
|
|
if (first_time)
|
|
|
|
{
|
|
|
|
pspUiFlashMessage("Initializing for first-time use\nPlease wait...");
|
|
|
|
audio_init(SOUND_FREQUENCY, 0);
|
|
|
|
system_init();
|
|
|
|
//error_init();
|
|
|
|
system_reset();
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
system_init();
|
|
|
|
system_reset();
|
|
|
|
audio_reset();
|
|
|
|
}
|
|
|
|
pl_rewind_reset(&Rewinder);
|
|
|
|
|
|
|
|
ResumeEmulation = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnSaveStateOk(const void *gallery, const void *item)
|
|
|
|
{
|
|
|
|
if (!GAME_LOADED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
char *path;
|
|
|
|
const char *config_name = pl_file_get_filename(CURRENT_GAME);
|
|
|
|
|
|
|
|
path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
|
|
|
|
sprintf(path, "%s%s.s%02i", SaveStatePath, config_name,
|
|
|
|
((const pl_menu_item*)item)->id);
|
|
|
|
|
|
|
|
if (pl_file_exists(path) && pspUiConfirm("Load state?"))
|
|
|
|
{
|
|
|
|
if (LoadState(path))
|
|
|
|
{
|
|
|
|
ResumeEmulation = 1;
|
|
|
|
pl_rewind_reset(&Rewinder);
|
|
|
|
pl_menu_find_item_by_id(&(((const PspUiGallery*)gallery)->Menu),
|
|
|
|
((const pl_menu_item*)item)->id);
|
|
|
|
free(path);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
pspUiAlert("ERROR: State failed to load");
|
|
|
|
}
|
|
|
|
|
|
|
|
free(path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int OnSaveStateButtonPress(const PspUiGallery *gallery,
|
|
|
|
pl_menu_item *sel, u32 button_mask)
|
|
|
|
{
|
|
|
|
if (!GAME_LOADED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (button_mask & PSP_CTRL_SQUARE
|
|
|
|
|| button_mask & PSP_CTRL_TRIANGLE)
|
|
|
|
{
|
|
|
|
char caption[32];
|
|
|
|
char *path;
|
|
|
|
const char *config_name = pl_file_get_filename(CURRENT_GAME);
|
|
|
|
|
|
|
|
path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
|
|
|
|
sprintf(path, "%s%s.s%02i", SaveStatePath, config_name, sel->id);
|
|
|
|
|
|
|
|
do /* not a real loop; flow control construct */
|
|
|
|
{
|
|
|
|
if (button_mask & PSP_CTRL_SQUARE)
|
|
|
|
{
|
|
|
|
if (pl_file_exists(path) && !pspUiConfirm("Overwrite existing state?"))
|
|
|
|
break;
|
|
|
|
|
|
|
|
pspUiFlashMessage("Saving, please wait ...");
|
|
|
|
|
|
|
|
PspImage *icon;
|
|
|
|
if (!(icon = SaveState(path, Screen)))
|
|
|
|
{
|
|
|
|
pspUiAlert("ERROR: State not saved");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
SceIoStat stat;
|
|
|
|
|
|
|
|
/* Trash the old icon (if any) */
|
|
|
|
if (sel->param && sel->param != NoSaveIcon)
|
|
|
|
pspImageDestroy((PspImage*)sel->param);
|
|
|
|
|
|
|
|
/* Update icon, help text */
|
|
|
|
sel->param = icon;
|
|
|
|
pl_menu_set_item_help_text(sel, PresentSlotText);
|
|
|
|
|
|
|
|
/* Get file modification time/date */
|
|
|
|
if (sceIoGetstat(path, &stat) < 0)
|
|
|
|
sprintf(caption, "ERROR");
|
|
|
|
else
|
|
|
|
sprintf(caption, "%02i/%02i/%02i %02i:%02i",
|
|
|
|
stat.st_mtime.month,
|
|
|
|
stat.st_mtime.day,
|
|
|
|
stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
|
|
|
|
stat.st_mtime.hour,
|
|
|
|
stat.st_mtime.minute);
|
|
|
|
|
|
|
|
pl_menu_set_item_caption(sel, caption);
|
|
|
|
}
|
|
|
|
else if (button_mask & PSP_CTRL_TRIANGLE)
|
|
|
|
{
|
|
|
|
if (!pl_file_exists(path) || !pspUiConfirm("Delete state?"))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!pl_file_rm(path))
|
|
|
|
{
|
|
|
|
pspUiAlert("ERROR: State not deleted");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Trash the old icon (if any) */
|
|
|
|
if (sel->param && sel->param != NoSaveIcon)
|
|
|
|
pspImageDestroy((PspImage*)sel->param);
|
|
|
|
|
|
|
|
/* Update icon, caption */
|
|
|
|
sel->param = NoSaveIcon;
|
|
|
|
pl_menu_set_item_help_text(sel, EmptySlotText);
|
|
|
|
pl_menu_set_item_caption(sel, "Empty");
|
|
|
|
}
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
if (path) free(path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OnGenericButtonPress(NULL, NULL, button_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handles any special drawing for the system menu */
|
|
|
|
void OnSystemRender(const void *uiobject, const void *item_obj)
|
|
|
|
{
|
|
|
|
int w, h, x, y;
|
|
|
|
w = Screen->Viewport.Width*1.5;
|
|
|
|
h = Screen->Viewport.Height*1.5;
|
|
|
|
x = SCR_WIDTH - w - 16;
|
|
|
|
y = SCR_HEIGHT - h - 80;
|
|
|
|
|
|
|
|
/* Draw a small representation of the screen */
|
|
|
|
pspVideoShadowRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_BLACK, 3);
|
|
|
|
pspVideoPutImage(Screen, x, y, w, h);
|
|
|
|
pspVideoDrawRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_GRAY);
|
|
|
|
|
|
|
|
OnGenericRender(uiobject, item_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DisplayStateTab()
|
|
|
|
{
|
|
|
|
if (!GAME_LOADED) { TabIndex++; return; }
|
|
|
|
|
|
|
|
pl_menu_item *item, *sel;
|
|
|
|
SceIoStat stat;
|
|
|
|
char caption[32];
|
|
|
|
ScePspDateTime latest;
|
|
|
|
|
|
|
|
const char *config_name = pl_file_get_filename(CURRENT_GAME);
|
|
|
|
char *path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
|
|
|
|
char *game_name = strdup(config_name);
|
|
|
|
char *dot = strrchr(game_name, '.');
|
|
|
|
if (dot) *dot='\0';
|
|
|
|
|
|
|
|
memset(&latest, 0, sizeof(latest));
|
|
|
|
|
|
|
|
/* Initialize icons */
|
|
|
|
sel = SaveStateGallery.Menu.items;
|
|
|
|
for (item = SaveStateGallery.Menu.items; item; item = item->next)
|
|
|
|
{
|
|
|
|
sprintf(path, "%s%s.s%02i", SaveStatePath, config_name, item->id);
|
|
|
|
|
|
|
|
if (pl_file_exists(path))
|
|
|
|
{
|
|
|
|
if (sceIoGetstat(path, &stat) < 0)
|
|
|
|
sprintf(caption, "ERROR");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Determine the latest save state */
|
|
|
|
if (pl_util_date_compare(&latest, &stat.st_mtime) < 0)
|
|
|
|
{
|
|
|
|
sel = item;
|
|
|
|
latest = stat.st_mtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(caption, "%02i/%02i/%02i %02i:%02i",
|
|
|
|
stat.st_mtime.month,
|
|
|
|
stat.st_mtime.day,
|
|
|
|
stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
|
|
|
|
stat.st_mtime.hour,
|
|
|
|
stat.st_mtime.minute);
|
|
|
|
}
|
|
|
|
|
|
|
|
pl_menu_set_item_caption(item, caption);
|
|
|
|
item->param = LoadStateIcon(path);
|
|
|
|
pl_menu_set_item_help_text(item, PresentSlotText);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pl_menu_set_item_caption(item, "Empty");
|
|
|
|
item->param = NoSaveIcon;
|
|
|
|
pl_menu_set_item_help_text(item, EmptySlotText);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
free(path);
|
|
|
|
|
|
|
|
/* Highlight the latest save state if none are selected */
|
|
|
|
if (SaveStateGallery.Menu.selected == NULL)
|
|
|
|
SaveStateGallery.Menu.selected = sel;
|
|
|
|
|
|
|
|
pspUiOpenGallery(&SaveStateGallery, game_name);
|
|
|
|
free(game_name);
|
|
|
|
|
|
|
|
/* Destroy any icons */
|
|
|
|
for (item = SaveStateGallery.Menu.items; item; item = item->next)
|
|
|
|
if (item->param != NULL && item->param != NoSaveIcon)
|
|
|
|
pspImageDestroy((PspImage*)item->param);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize game configuration */
|
|
|
|
static void InitButtonConfig()
|
|
|
|
{
|
|
|
|
memcpy(&ActiveConfig, &DefaultConfig, sizeof(struct ButtonConfig));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load game configuration */
|
|
|
|
static int LoadButtonConfig()
|
|
|
|
{
|
|
|
|
pl_file_path path;
|
|
|
|
snprintf(path, sizeof(path) - 1, "%sbuttons.cnf",
|
|
|
|
pl_psp_get_app_directory());
|
|
|
|
|
|
|
|
/* Open file for reading */
|
|
|
|
FILE *file = fopen(path, "r");
|
|
|
|
|
|
|
|
/* If no configuration, load defaults */
|
|
|
|
if (!file)
|
|
|
|
{
|
|
|
|
InitButtonConfig();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read contents of struct */
|
|
|
|
int nread = fread(&ActiveConfig, sizeof(struct ButtonConfig), 1, file);
|
|
|
|
fclose(file);
|
|
|
|
|
|
|
|
if (nread != 1)
|
|
|
|
{
|
|
|
|
InitButtonConfig();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save game configuration */
|
|
|
|
static int SaveButtonConfig()
|
|
|
|
{
|
|
|
|
pl_file_path path;
|
|
|
|
snprintf(path, sizeof(path) - 1, "%sbuttons.cnf", pl_psp_get_app_directory());
|
|
|
|
|
|
|
|
/* Open file for writing */
|
|
|
|
FILE *file = fopen(path, "w");
|
|
|
|
if (!file) return 0;
|
|
|
|
|
|
|
|
/* Write contents of struct */
|
|
|
|
int nwritten = fwrite(&ActiveConfig, sizeof(struct ButtonConfig), 1, file);
|
|
|
|
fclose(file);
|
|
|
|
|
|
|
|
return (nwritten == 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load options */
|
|
|
|
void LoadOptions()
|
|
|
|
{
|
|
|
|
pl_file_path path;
|
|
|
|
snprintf(path, sizeof(path) - 1, "%ssmsplus.ini", pl_psp_get_app_directory());
|
|
|
|
|
|
|
|
/* Initialize INI structure */
|
|
|
|
pl_ini_file init;
|
|
|
|
pl_ini_load(&init, path);
|
|
|
|
|
|
|
|
/* Load values */
|
|
|
|
Options.DisplayMode = pl_ini_get_int(&init, "Video", "Display Mode", DISPLAY_MODE_2X);
|
|
|
|
Options.UpdateFreq = pl_ini_get_int(&init, "Video", "Update Frequency", 60);
|
|
|
|
Options.Frameskip = pl_ini_get_int(&init, "Video", "Frameskip", 0);
|
|
|
|
Options.VSync = pl_ini_get_int(&init, "Video", "VSync", 0);
|
2015-08-30 13:50:40 +02:00
|
|
|
Options.ClockFreq = pl_ini_get_int(&init, "Video", "PSP Clock Frequency", 444);
|
2015-08-30 01:44:58 +02:00
|
|
|
Options.ShowFps = pl_ini_get_int(&init, "Video", "Show FPS", 0);
|
|
|
|
Options.ControlMode = pl_ini_get_int(&init, "Menu", "Control Mode", 0);
|
|
|
|
UiMetric.Animate = pl_ini_get_int(&init, "Menu", "Animate", 1);
|
|
|
|
Options.VertStrip = pl_ini_get_int(&init, "Game", "Vertical Strip", 1);
|
|
|
|
Options.AutoFire = pl_ini_get_int(&init, "Input", "Autofire", 2);
|
|
|
|
Options.RewindSaveRate = pl_ini_get_int(&init, "Enhancements", "Rewind Save Rate", 5);
|
|
|
|
Options.RewindReplayDelay = pl_ini_get_int(&init, "Enhancements", "Rewind Replay Delay", 50);
|
|
|
|
pl_ini_get_string(&init, "File", "Game Path", NULL, GamePath, sizeof(GamePath));
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
pl_ini_destroy(&init);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save options */
|
|
|
|
static int SaveOptions()
|
|
|
|
{
|
|
|
|
pl_file_path path;
|
|
|
|
snprintf(path, sizeof(path) - 1, "%ssmsplus.ini", pl_psp_get_app_directory());
|
|
|
|
|
|
|
|
/* Initialize INI structure */
|
|
|
|
pl_ini_file init;
|
|
|
|
pl_ini_create(&init);
|
|
|
|
|
|
|
|
/* Set values */
|
|
|
|
pl_ini_set_int(&init, "Video", "Display Mode", Options.DisplayMode);
|
|
|
|
pl_ini_set_int(&init, "Video", "Update Frequency", Options.UpdateFreq);
|
|
|
|
pl_ini_set_int(&init, "Video", "Frameskip", Options.Frameskip);
|
|
|
|
pl_ini_set_int(&init, "Video", "VSync", Options.VSync);
|
|
|
|
pl_ini_set_int(&init, "Video", "PSP Clock Frequency",Options.ClockFreq);
|
|
|
|
pl_ini_set_int(&init, "Video", "Show FPS", Options.ShowFps);
|
|
|
|
pl_ini_set_int(&init, "Menu", "Control Mode", Options.ControlMode);
|
|
|
|
pl_ini_set_int(&init, "Menu", "Animate", UiMetric.Animate);
|
|
|
|
pl_ini_set_int(&init, "Game", "Vertical Strip", Options.VertStrip);
|
|
|
|
pl_ini_set_int(&init, "Input", "Autofire", Options.AutoFire);
|
|
|
|
pl_ini_set_int(&init, "Enhancements", "Rewind Save Rate", Options.RewindSaveRate);
|
|
|
|
pl_ini_set_int(&init, "Enhancements", "Rewind Replay Delay", Options.RewindReplayDelay);
|
|
|
|
pl_ini_set_string(&init, "File", "Game Path", GamePath);
|
|
|
|
|
|
|
|
/* Save INI file */
|
|
|
|
int status = pl_ini_save(&init, path);
|
|
|
|
|
|
|
|
/* Clean up */
|
|
|
|
pl_ini_destroy(&init);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load state icon */
|
|
|
|
PspImage* LoadStateIcon(const char *path)
|
|
|
|
{
|
|
|
|
/* Open file for reading */
|
|
|
|
FILE *f = fopen(path, "r");
|
|
|
|
if (!f) return NULL;
|
|
|
|
|
|
|
|
/* Load image */
|
|
|
|
PspImage *image = pspImageLoadPngFd(f);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load state */
|
|
|
|
int LoadState(const char *path)
|
|
|
|
{
|
|
|
|
/* Open file for reading */
|
|
|
|
FILE *f = fopen(path, "r");
|
|
|
|
if (!f) return 0;
|
|
|
|
|
|
|
|
/* Load image into temporary object */
|
|
|
|
PspImage *image = pspImageLoadPngFd(f);
|
|
|
|
pspImageDestroy(image);
|
|
|
|
|
|
|
|
//system_load_state(f);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save state */
|
|
|
|
PspImage* SaveState(const char *path, PspImage *icon)
|
|
|
|
{
|
|
|
|
/* Open file for writing */
|
|
|
|
FILE *f;
|
|
|
|
if (!(f = fopen(path, "w")))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Create thumbnail */
|
|
|
|
PspImage *thumb;
|
|
|
|
thumb = (icon->Viewport.Width < 200)
|
|
|
|
? pspImageCreateCopy(icon) : pspImageCreateThumbnail(icon);
|
|
|
|
if (!thumb) { fclose(f); return NULL; }
|
|
|
|
|
|
|
|
/* Write the thumbnail */
|
|
|
|
if (!pspImageSavePngFd(f, thumb))
|
|
|
|
{
|
|
|
|
pspImageDestroy(thumb);
|
|
|
|
fclose(f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save state */
|
|
|
|
//system_save_state(f);
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
return thumb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release menu resources */
|
|
|
|
void TrashMenu()
|
|
|
|
{
|
|
|
|
TrashEmulator();
|
|
|
|
|
|
|
|
/* Save options */
|
|
|
|
SaveOptions();
|
|
|
|
|
|
|
|
/* Trash menus */
|
|
|
|
pl_menu_destroy(&SystemUiMenu.Menu);
|
|
|
|
pl_menu_destroy(&OptionUiMenu.Menu);
|
|
|
|
pl_menu_destroy(&ControlUiMenu.Menu);
|
|
|
|
pl_menu_destroy(&SaveStateGallery.Menu);
|
|
|
|
|
|
|
|
/* Trash images */
|
|
|
|
if (Background) pspImageDestroy(Background);
|
|
|
|
if (NoSaveIcon) pspImageDestroy(NoSaveIcon);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save or load SRAM */
|
|
|
|
void system_manage_sram(uint8 *sram, int slot, int mode)
|
|
|
|
{
|
|
|
|
FILE *fd;
|
|
|
|
const char *config_name = pl_file_get_filename(CURRENT_GAME);
|
|
|
|
char *path = (char*)malloc(sizeof(char)
|
|
|
|
* (strlen(SaveStatePath) + strlen(config_name) + 8));
|
|
|
|
sprintf(path, "%s%s.srm", SaveStatePath, config_name);
|
|
|
|
|
|
|
|
/*switch(mode)
|
|
|
|
{
|
|
|
|
case SRAM_SAVE:
|
|
|
|
if(sms.save)
|
|
|
|
{
|
|
|
|
fd = fopen(path, "w");
|
|
|
|
if(fd)
|
|
|
|
{
|
|
|
|
fwrite(sram, 0x8000, 1, fd);
|
|
|
|
fclose(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SRAM_LOAD:
|
|
|
|
fd = fopen(path, "r");
|
|
|
|
if(fd)
|
|
|
|
{
|
|
|
|
sms.save = 1;
|
|
|
|
fread(sram, 0x8000, 1, fd);
|
|
|
|
fclose(fd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{*/
|
|
|
|
/* No SRAM file, so initialize memory */
|
|
|
|
/* memset(sram, 0x00, 0x8000);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
free(path);
|
|
|
|
}
|