Subversion Repositories psp

[/] [branches/] [smsplus_adhoc/] [psp/] [menu.c] - Blame information for rev 354

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jack
#include "menu.h"
2 27 jack
 
3
#include <time.h>
4
#include <psptypes.h>
5
#include <psprtc.h>
6
#include <malloc.h>
7
#include <string.h>
8 28 jack
#include <pspkernel.h>
9 27 jack
 
10 19 jack
#include "emumain.h"
11
 
12 27 jack
#include "types.h"
13
#include "loadrom.h"
14
#include "system.h"
15 28 jack
#include "state.h"
16
#include "shared.h"
17 27 jack
 
18 204 jack
#include "file.h"
19 19 jack
#include "image.h"
20 27 jack
#include "ui.h"
21
#include "menu.h"
22
#include "ctrl.h"
23
#include "psp.h"
24
#include "util.h"
25 39 jack
#include "init.h"
26 19 jack
 
27 27 jack
#define TAB_QUICKLOAD 0
28 28 jack
#define TAB_STATE     1
29
#define TAB_CONTROL   2
30
#define TAB_OPTION    3
31 251 jack
#define TAB_NETPLAY   4
32
#define TAB_SYSTEM    5
33 250 jack
#define TAB_ABOUT     6
34 251 jack
#define TAB_MAX       TAB_SYSTEM
35 27 jack
 
36
#define OPTION_DISPLAY_MODE 1
37
#define OPTION_SYNC_FREQ    2
38
#define OPTION_FRAMESKIP    3
39
#define OPTION_VSYNC        4
40
#define OPTION_CLOCK_FREQ   5
41
#define OPTION_SHOW_FPS     6
42 166 jack
#define OPTION_CONTROL_MODE 7
43 134 jack
#define OPTION_ANIMATE      8
44 27 jack
 
45 49 jack
#define SYSTEM_SCRNSHOT     1
46
#define SYSTEM_RESET        2
47
#define SYSTEM_VERT_STRIP   3
48
#define SYSTEM_SOUND_ENGINE 4
49 52 jack
#define SYSTEM_SOUND_BOOST  5
50 29 jack
 
51 250 jack
#define NETPLAY_HOST 1
52
#define NETPLAY_JOIN 2
53
#define NETPLAY_DISC 3
54 236 jack
 
55 19 jack
extern PspImage *Screen;
56
 
57 77 jack
EmulatorOptions Options;
58 19 jack
 
59 241 jack
int AdhocMode;
60
PspMAC OpponentMAC;
61
 
62 27 jack
static int TabIndex;
63
static int ResumeEmulation;
64
static PspImage *Background;
65
static PspImage *NoSaveIcon;
66
 
67 28 jack
static const char *QuickloadFilter[] = { "SMS", "GG", "ZIP", '\0' },
68
  PresentSlotText[] = "\026\244\020 Save\t\026\001\020 Load\t\026\243\020 Delete",
69
  EmptySlotText[] = "\026\244\020 Save",
70
  ControlHelpText[] = "\026\250\020 Change mapping\t\026\001\020 Save to \271\t\026\243\020 Load defaults";
71 27 jack
 
72
static const char *ScreenshotDir = "screens";
73 28 jack
static const char *SaveStateDir = "savedata";
74
static const char *ButtonConfigFile = "buttons";
75 39 jack
static const char *OptionsFile = "smsplus.ini";
76 27 jack
 
77
char *GameName;
78
char *ScreenshotPath;
79
static char *SaveStatePath;
80 28 jack
static char *GamePath;
81 27 jack
 
82
#define WIDTH  256
83
#define HEIGHT 192
84
 
85
/* Tab labels */
86
static const char *TabLabel[] =
87
{
88
  "Game",
89 28 jack
  "Save/Load",
90
  "Controls",
91 27 jack
  "Options",
92 251 jack
  "Netplay",
93 29 jack
  "System",
94 27 jack
  "About"
95
};
96
 
97 250 jack
static int JoinGame();
98
static int HostGame();
99
 
100 27 jack
static void LoadOptions();
101 39 jack
static int  SaveOptions();
102 27 jack
 
103 28 jack
static void InitButtonConfig();
104
static int  SaveButtonConfig();
105
static int  LoadButtonConfig();
106
 
107 166 jack
static void        DisplayStateTab();
108
static PspImage*   LoadStateIcon(const char *path);
109
static int         LoadState(const char *path);
110
static PspImage*   SaveState(const char *path, PspImage *icon);
111 28 jack
 
112 166 jack
static int OnMenuItemChanged(const struct PspUiMenu *uimenu, PspMenuItem* item,
113 78 jack
  const PspMenuOption* option);
114
static int OnMenuOk(const void *uimenu, const void* sel_item);
115 166 jack
static int OnMenuButtonPress(const struct PspUiMenu *uimenu,
116 27 jack
  PspMenuItem* sel_item, u32 button_mask);
117
 
118 166 jack
static int OnSplashButtonPress(const struct PspUiSplash *splash,
119 27 jack
  u32 button_mask);
120 78 jack
static void OnSplashRender(const void *uiobject, const void *null);
121 27 jack
 
122 78 jack
static int OnGenericCancel(const void *uiobject, const void *param);
123
static void OnGenericRender(const void *uiobject, const void *item_obj);
124 166 jack
static int OnGenericButtonPress(const PspUiFileBrowser *browser,
125 78 jack
  const char *path, u32 button_mask);
126 28 jack
 
127 78 jack
static int OnSaveStateOk(const void *gallery, const void *item);
128 166 jack
static int OnSaveStateButtonPress(const PspUiGallery *gallery,
129 78 jack
  PspMenuItem* item, u32 button_mask);
130
 
131 166 jack
static int OnQuickloadOk(const void *browser, const void *path);
132 27 jack
 
133 29 jack
void OnSystemRender(const void *uiobject, const void *item_obj);
134
 
135 27 jack
/* Define various menu options */
136
static const PspMenuOptionDef
137 49 jack
  SoundEngineOptions[] = {
138 112 jack
    MENU_OPTION("Disabled",      SND_NULL),
139
    MENU_OPTION("Faster",        SND_YM2413),
140
    MENU_OPTION("More accurate", SND_EMU2413),
141 166 jack
    MENU_END_OPTIONS
142 112 jack
  },
143 52 jack
  SoundBoostOptions[] = {
144 112 jack
    MENU_OPTION("Off", 0),
145
    MENU_OPTION("2x",  1),
146
    MENU_OPTION("4x",  2),
147 166 jack
    MENU_END_OPTIONS
148 112 jack
  },
149 27 jack
  ToggleOptions[] = {
150 112 jack
    MENU_OPTION("Disabled", 0),
151
    MENU_OPTION("Enabled",  1),
152 166 jack
    MENU_END_OPTIONS
153 112 jack
  },
154 27 jack
  ScreenSizeOptions[] = {
155 112 jack
    MENU_OPTION("Actual size",              DISPLAY_MODE_UNSCALED),
156
    MENU_OPTION("4:3 scaled (fit height)",  DISPLAY_MODE_FIT_HEIGHT),
157
    MENU_OPTION("16:9 scaled (fit screen)", DISPLAY_MODE_FILL_SCREEN),
158 166 jack
    MENU_END_OPTIONS
159 112 jack
  },
160 27 jack
  FrameLimitOptions[] = {
161 112 jack
    MENU_OPTION("Disabled",      0),
162
    MENU_OPTION("60 fps (NTSC)", 60),
163 166 jack
    MENU_END_OPTIONS
164 112 jack
  },
165 27 jack
  FrameSkipOptions[] = {
166 112 jack
    MENU_OPTION("No skipping",  0),
167
    MENU_OPTION("Skip 1 frame", 1),
168
    MENU_OPTION("Skip 2 frames",2),
169
    MENU_OPTION("Skip 3 frames",3),
170
    MENU_OPTION("Skip 4 frames",4),
171
    MENU_OPTION("Skip 5 frames",5),
172 166 jack
    MENU_END_OPTIONS
173 112 jack
  },
174 27 jack
  PspClockFreqOptions[] = {
175 112 jack
    MENU_OPTION("222 MHz", 222),
176
    MENU_OPTION("266 MHz", 266),
177
    MENU_OPTION("300 MHz", 300),
178
    MENU_OPTION("333 MHz", 333),
179 166 jack
    MENU_END_OPTIONS
180 112 jack
  },
181 27 jack
  ControlModeOptions[] = {
182 112 jack
    MENU_OPTION("\026\242\020 cancels, \026\241\020 confirms (US)",    0),
183
    MENU_OPTION("\026\241\020 cancels, \026\242\020 confirms (Japan)", 1),
184 166 jack
    MENU_END_OPTIONS
185 112 jack
  },
186 28 jack
  ButtonMapOptions[] = {
187
    /* Unmapped */
188 112 jack
    MENU_OPTION("None", 0),
189 28 jack
    /* Special */
190 112 jack
    MENU_OPTION("Special: Open Menu", SPC|SPC_MENU),
191 28 jack
    /* Joystick */
192 112 jack
    MENU_OPTION("Joystick Up",    JOY|INPUT_UP),
193
    MENU_OPTION("Joystick Down",  JOY|INPUT_DOWN),
194
    MENU_OPTION("Joystick Left",  JOY|INPUT_LEFT),
195
    MENU_OPTION("Joystick Right", JOY|INPUT_RIGHT),
196
    MENU_OPTION("Joystick Button I",  JOY|INPUT_BUTTON1),
197
    MENU_OPTION("Joystick Button II", JOY|INPUT_BUTTON2),
198 28 jack
    /* Joystick */
199 112 jack
    MENU_OPTION("Start (GG) / Pause (SMS)", SYS|INPUT_START|INPUT_PAUSE),
200
    MENU_OPTION("Soft Reset (SMS)", SYS|INPUT_RESET),
201 166 jack
    MENU_END_OPTIONS
202 112 jack
  };
203 27 jack
 
204
static const PspMenuItemDef
205
  OptionMenuDef[] = {
206 112 jack
    MENU_HEADER("Video"),
207 166 jack
    MENU_ITEM("Screen size", OPTION_DISPLAY_MODE, ScreenSizeOptions, -1,
208 112 jack
      "\026\250\020 Change screen size"),
209
    MENU_HEADER("Performance"),
210 166 jack
    MENU_ITEM("Frame limiter", OPTION_SYNC_FREQ, FrameLimitOptions, -1,
211 112 jack
      "\026\250\020 Change screen update frequency"),
212 166 jack
    MENU_ITEM("Frame skipping", OPTION_FRAMESKIP, FrameSkipOptions, -1,
213 112 jack
      "\026\250\020 Change number of frames skipped per update"),
214 166 jack
    MENU_ITEM("VSync", OPTION_VSYNC, ToggleOptions, -1,
215 112 jack
      "\026\250\020 Enable to reduce tearing; disable to increase speed"),
216 166 jack
    MENU_ITEM("PSP clock frequency", OPTION_CLOCK_FREQ, PspClockFreqOptions, -1,
217 112 jack
      "\026\250\020 Larger values: faster emulation, faster battery depletion (default: 222MHz)"),
218 166 jack
    MENU_ITEM("Show FPS counter",    OPTION_SHOW_FPS, ToggleOptions, -1,
219 112 jack
      "\026\250\020 Show/hide the frames-per-second counter"),
220
    MENU_HEADER("Menu"),
221 166 jack
    MENU_ITEM("Button mode", OPTION_CONTROL_MODE, ControlModeOptions,  -1,
222 112 jack
      "\026\250\020 Change OK and Cancel button mapping"),
223 166 jack
    MENU_ITEM("Animations", OPTION_ANIMATE, ToggleOptions,  -1,
224 134 jack
      "\026\250\020 Enable/disable in-menu animations"),
225 112 jack
    MENU_END_ITEMS
226 28 jack
  },
227
  ControlMenuDef[] = {
228 166 jack
    MENU_ITEM(PSP_CHAR_ANALUP, MAP_ANALOG_UP, ButtonMapOptions, -1,
229 112 jack
      ControlHelpText),
230 166 jack
    MENU_ITEM(PSP_CHAR_ANALDOWN, MAP_ANALOG_DOWN, ButtonMapOptions, -1,
231 112 jack
      ControlHelpText),
232 166 jack
    MENU_ITEM(PSP_CHAR_ANALLEFT, MAP_ANALOG_LEFT, ButtonMapOptions, -1,
233 112 jack
      ControlHelpText),
234 166 jack
    MENU_ITEM(PSP_CHAR_ANALRIGHT, MAP_ANALOG_RIGHT, ButtonMapOptions, -1,
235 112 jack
      ControlHelpText),
236 166 jack
    MENU_ITEM(PSP_CHAR_UP, MAP_BUTTON_UP, ButtonMapOptions, -1,
237 112 jack
      ControlHelpText),
238 166 jack
    MENU_ITEM(PSP_CHAR_DOWN, MAP_BUTTON_DOWN, ButtonMapOptions, -1,
239 112 jack
      ControlHelpText),
240 166 jack
    MENU_ITEM(PSP_CHAR_LEFT, MAP_BUTTON_LEFT, ButtonMapOptions, -1,
241 112 jack
      ControlHelpText),
242 166 jack
    MENU_ITEM(PSP_CHAR_RIGHT, MAP_BUTTON_RIGHT, ButtonMapOptions, -1,
243 112 jack
      ControlHelpText),
244 166 jack
    MENU_ITEM(PSP_CHAR_SQUARE, MAP_BUTTON_SQUARE, ButtonMapOptions, -1,
245 112 jack
      ControlHelpText),
246 166 jack
    MENU_ITEM(PSP_CHAR_CROSS, MAP_BUTTON_CROSS, ButtonMapOptions, -1,
247 112 jack
      ControlHelpText),
248 166 jack
    MENU_ITEM(PSP_CHAR_CIRCLE, MAP_BUTTON_CIRCLE, ButtonMapOptions, -1,
249 112 jack
      ControlHelpText),
250 166 jack
    MENU_ITEM(PSP_CHAR_TRIANGLE, MAP_BUTTON_TRIANGLE, ButtonMapOptions,
251 112 jack
      -1, ControlHelpText),
252 166 jack
    MENU_ITEM(PSP_CHAR_LTRIGGER, MAP_BUTTON_LTRIGGER, ButtonMapOptions,
253 112 jack
      -1, ControlHelpText),
254 166 jack
    MENU_ITEM(PSP_CHAR_RTRIGGER, MAP_BUTTON_RTRIGGER, ButtonMapOptions,
255
      -1, ControlHelpText),
256
    MENU_ITEM(PSP_CHAR_SELECT, MAP_BUTTON_SELECT, ButtonMapOptions,
257
      -1, ControlHelpText),
258
    MENU_ITEM(PSP_CHAR_START, MAP_BUTTON_START, ButtonMapOptions, -1,
259 112 jack
      ControlHelpText),
260 166 jack
    MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_RTRIGGER,
261 112 jack
      MAP_BUTTON_LRTRIGGERS, ButtonMapOptions, -1, ControlHelpText),
262 134 jack
    MENU_ITEM(PSP_CHAR_START"+"PSP_CHAR_SELECT,
263 112 jack
      MAP_BUTTON_STARTSELECT, ButtonMapOptions, -1, ControlHelpText),
264
    MENU_END_ITEMS
265 29 jack
  },
266
  SystemMenuDef[] = {
267 112 jack
    MENU_HEADER("Audio"),
268 166 jack
    MENU_ITEM("FM Emulation", SYSTEM_SOUND_ENGINE, SoundEngineOptions, -1,
269 112 jack
      "\026\250\020 Select FM emulation engine"),
270 166 jack
    MENU_ITEM("Sound Boost", SYSTEM_SOUND_BOOST, SoundBoostOptions, -1,
271 112 jack
      "\026\250\020 Adjust volume scaling factor"),
272
    MENU_HEADER("Video"),
273 166 jack
    MENU_ITEM("Vertical bar", SYSTEM_VERT_STRIP, ToggleOptions, -1,
274 112 jack
      "\026\250\020 Show/hide the leftmost vertical bar (SMS)"),
275
    MENU_HEADER("System"),
276
    MENU_ITEM("Reset", SYSTEM_RESET, NULL, -1, "\026\001\020 Reset"),
277 166 jack
    MENU_ITEM("Save screenshot",  SYSTEM_SCRNSHOT, NULL, -1,
278 112 jack
      "\026\001\020 Save screenshot"),
279
    MENU_END_ITEMS
280 250 jack
  },
281
  NetplayMenuDef[] = {
282
    MENU_HEADER("Game"),
283
    MENU_ITEM("Host game", NETPLAY_HOST, NULL, -1,
284
      "\026\001\020 Host a wi-fi game"),
285
    MENU_ITEM("Join game", NETPLAY_JOIN, NULL, -1,
286
      "\026\001\020 Join a wi-fi game"),
287
    MENU_HEADER("Connection"),
288
    MENU_ITEM("Disconnect", NETPLAY_DISC, NULL, -1,
289 251 jack
      "\026\001\020 Disconnect from a game in progress"),
290
    MENU_END_ITEMS
291 27 jack
  };
292
 
293 28 jack
PspUiSplash SplashScreen =
294 27 jack
{
295
  OnSplashRender,
296
  OnGenericCancel,
297
  OnSplashButtonPress,
298
  NULL
299
};
300
 
301 28 jack
PspUiGallery SaveStateGallery =
302
{
303
  NULL,                        /* PspMenu */
304
  OnGenericRender,             /* OnRender() */
305
  OnSaveStateOk,               /* OnOk() */
306
  OnGenericCancel,             /* OnCancel() */
307
  OnSaveStateButtonPress,      /* OnButtonPress() */
308
  NULL                         /* Userdata */
309
};
310
 
311 27 jack
PspUiMenu OptionUiMenu =
312
{
313
  NULL,                  /* PspMenu */
314
  OnGenericRender,       /* OnRender() */
315
  OnMenuOk,              /* OnOk() */
316
  OnGenericCancel,       /* OnCancel() */
317
  OnMenuButtonPress,     /* OnButtonPress() */
318
  OnMenuItemChanged,     /* OnItemChanged() */
319
};
320
 
321 28 jack
PspUiMenu ControlUiMenu =
322
{
323
  NULL,                  /* PspMenu */
324
  OnGenericRender,       /* OnRender() */
325
  OnMenuOk,              /* OnOk() */
326
  OnGenericCancel,       /* OnCancel() */
327
  OnMenuButtonPress,     /* OnButtonPress() */
328
  OnMenuItemChanged,     /* OnItemChanged() */
329
};
330
 
331 27 jack
PspUiFileBrowser QuickloadBrowser =
332
{
333
  OnGenericRender,
334
  OnQuickloadOk,
335
  OnGenericCancel,
336
  OnGenericButtonPress,
337
  QuickloadFilter,
338
 
339
};
340
 
341 29 jack
PspUiMenu SystemUiMenu =
342
{
343
  NULL,                  /* PspMenu */
344
  OnSystemRender,        /* OnRender() */
345
  OnMenuOk,              /* OnOk() */
346
  OnGenericCancel,       /* OnCancel() */
347
  OnMenuButtonPress,     /* OnButtonPress() */
348
  OnMenuItemChanged,     /* OnItemChanged() */
349
};
350
 
351 250 jack
PspUiMenu NetplayUiMenu =
352
{
353
  NULL,                  /* PspMenu */
354
  OnGenericRender,       /* OnRender() */
355
  OnMenuOk,              /* OnOk() */
356
  OnGenericCancel,       /* OnCancel() */
357
  OnMenuButtonPress,     /* OnButtonPress() */
358
  OnMenuItemChanged,     /* OnItemChanged() */
359
};
360
 
361 28 jack
/* Game configuration (includes button maps) */
362
struct ButtonConfig ActiveConfig;
363
 
364
/* Default configuration */
365
struct ButtonConfig DefaultConfig =
366
{
367
  {
368
    JOY|INPUT_UP,     /* Analog Up    */
369
    JOY|INPUT_DOWN,   /* Analog Down  */
370
    JOY|INPUT_LEFT,   /* Analog Left  */
371
    JOY|INPUT_RIGHT,  /* Analog Right */
372
    JOY|INPUT_UP,     /* D-pad Up     */
373
    JOY|INPUT_DOWN,   /* D-pad Down   */
374
    JOY|INPUT_LEFT,   /* D-pad Left   */
375
    JOY|INPUT_RIGHT,  /* D-pad Right  */
376 32 jack
    JOY|INPUT_BUTTON2,/* Square       */
377 28 jack
    JOY|INPUT_BUTTON1,/* Cross        */
378 32 jack
    0,                /* Circle       */
379
    0,                /* Triangle     */
380 28 jack
    0,                /* L Trigger    */
381
    0,                /* R Trigger    */
382
    0,                /* Select       */
383
    SYS|INPUT_START|INPUT_PAUSE,
384
                      /* Start        */
385
    SPC|SPC_MENU,     /* L+R Triggers */
386
    0,                /* Start+Select */
387
  }
388
};
389
 
390
/* Button masks */
391
const u64 ButtonMask[] =
392
{
393
  PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER,
394
  PSP_CTRL_START    | PSP_CTRL_SELECT,
395
  PSP_CTRL_ANALUP,    PSP_CTRL_ANALDOWN,
396
  PSP_CTRL_ANALLEFT,  PSP_CTRL_ANALRIGHT,
397
  PSP_CTRL_UP,        PSP_CTRL_DOWN,
398
  PSP_CTRL_LEFT,      PSP_CTRL_RIGHT,
399
  PSP_CTRL_SQUARE,    PSP_CTRL_CROSS,
400
  PSP_CTRL_CIRCLE,    PSP_CTRL_TRIANGLE,
401
  PSP_CTRL_LTRIGGER,  PSP_CTRL_RTRIGGER,
402
  PSP_CTRL_SELECT,    PSP_CTRL_START,
403
 
404
};
405
 
406
/* Button map ID's */
407
const int ButtonMapId[] =
408
{
409
  MAP_BUTTON_LRTRIGGERS,
410
  MAP_BUTTON_STARTSELECT,
411
  MAP_ANALOG_UP,       MAP_ANALOG_DOWN,
412
  MAP_ANALOG_LEFT,     MAP_ANALOG_RIGHT,
413
  MAP_BUTTON_UP,       MAP_BUTTON_DOWN,
414
  MAP_BUTTON_LEFT,     MAP_BUTTON_RIGHT,
415
  MAP_BUTTON_SQUARE,   MAP_BUTTON_CROSS,
416
  MAP_BUTTON_CIRCLE,   MAP_BUTTON_TRIANGLE,
417
  MAP_BUTTON_LTRIGGER, MAP_BUTTON_RTRIGGER,
418
  MAP_BUTTON_SELECT,   MAP_BUTTON_START,
419
  -1 /* End */
420
};
421
 
422 19 jack
void InitMenu()
423
{
424 27 jack
  /* Reset variables */
425
  TabIndex = TAB_ABOUT;
426
  Background = NULL;
427
  GameName = NULL;
428 28 jack
  GamePath = NULL;
429 241 jack
  AdhocMode = ADHOC_NONE;
430 27 jack
 
431 52 jack
  /* Initialize options */
432
  LoadOptions();
433
 
434
  InitEmulator();
435
 
436 27 jack
  /* Load the background image */
437
  Background = pspImageLoadPng("background.png");
438
 
439
  /* Init NoSaveState icon image */
440 51 jack
  NoSaveIcon=pspImageCreate(136, 114, PSP_IMAGE_16BPP);
441 32 jack
  pspImageClear(NoSaveIcon, RGB(0x0c,0,0x3f));
442 27 jack
 
443 28 jack
  /* Initialize state menu */
444
  SaveStateGallery.Menu = pspMenuCreate();
445
  int i;
446
  PspMenuItem *item;
447
  for (i = 0; i < 10; i++)
448
  {
449 112 jack
    item = pspMenuAppendItem(SaveStateGallery.Menu, NULL, i);
450 28 jack
    pspMenuSetHelpText(item, EmptySlotText);
451
  }
452
 
453 27 jack
  /* Initialize options menu */
454
  OptionUiMenu.Menu = pspMenuCreate();
455
  pspMenuLoad(OptionUiMenu.Menu, OptionMenuDef);
456
 
457 28 jack
  /* Initialize control menu */
458
  ControlUiMenu.Menu = pspMenuCreate();
459
  pspMenuLoad(ControlUiMenu.Menu, ControlMenuDef);
460
 
461 29 jack
  /* Initialize system menu */
462
  SystemUiMenu.Menu = pspMenuCreate();
463
  pspMenuLoad(SystemUiMenu.Menu, SystemMenuDef);
464
 
465 250 jack
  /* Initialize netplay menu */
466
  NetplayUiMenu.Menu = pspMenuCreate();
467
  pspMenuLoad(NetplayUiMenu.Menu, NetplayMenuDef);
468
 
469 27 jack
  /* Initialize paths */
470
  SaveStatePath
471
    = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(SaveStateDir) + 2));
472
  sprintf(SaveStatePath, "%s%s/", pspGetAppDirectory(), SaveStateDir);
473
  ScreenshotPath
474
    = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(ScreenshotDir) + 2));
475
  sprintf(ScreenshotPath, "%s%s/", pspGetAppDirectory(), ScreenshotDir);
476
 
477 28 jack
  /* Load default configuration */
478
  LoadButtonConfig();
479
 
480 27 jack
  /* Initialize UI components */
481
  UiMetric.Background = Background;
482
  UiMetric.Font = &PspStockFont;
483
  UiMetric.Left = 8;
484
  UiMetric.Top = 24;
485
  UiMetric.Right = 472;
486 32 jack
  UiMetric.Bottom = 250;
487 77 jack
  UiMetric.OkButton = (!Options.ControlMode) ? PSP_CTRL_CROSS : PSP_CTRL_CIRCLE;
488
  UiMetric.CancelButton = (!Options.ControlMode) ? PSP_CTRL_CIRCLE : PSP_CTRL_CROSS;
489 61 jack
  UiMetric.ScrollbarColor = PSP_COLOR_GRAY;
490 27 jack
  UiMetric.ScrollbarBgColor = 0x44ffffff;
491
  UiMetric.ScrollbarWidth = 10;
492 61 jack
  UiMetric.TextColor = PSP_COLOR_GRAY;
493
  UiMetric.SelectedColor = PSP_COLOR_YELLOW;
494 32 jack
  UiMetric.SelectedBgColor = COLOR(0xff,0xff,0xff,0x44);
495 61 jack
  UiMetric.StatusBarColor = PSP_COLOR_WHITE;
496
  UiMetric.BrowserFileColor = PSP_COLOR_GRAY;
497
  UiMetric.BrowserDirectoryColor = PSP_COLOR_YELLOW;
498 27 jack
  UiMetric.GalleryIconsPerRow = 5;
499
  UiMetric.GalleryIconMarginWidth = 8;
500
  UiMetric.MenuItemMargin = 20;
501 61 jack
  UiMetric.MenuSelOptionBg = PSP_COLOR_BLACK;
502
  UiMetric.MenuOptionBoxColor = PSP_COLOR_GRAY;
503 49 jack
  UiMetric.MenuOptionBoxBg = COLOR(0, 0, 33, 0xBB);
504 61 jack
  UiMetric.MenuDecorColor = PSP_COLOR_YELLOW;
505 27 jack
  UiMetric.DialogFogColor = COLOR(0, 0, 0, 88);
506
  UiMetric.TitlePadding = 4;
507 61 jack
  UiMetric.TitleColor = PSP_COLOR_WHITE;
508 27 jack
  UiMetric.MenuFps = 30;
509 71 jack
  UiMetric.TabBgColor = COLOR(0x74,0x74,0xbe,0xff);
510 19 jack
}
511
 
512
void DisplayMenu()
513
{
514 28 jack
  int i;
515 27 jack
  PspMenuItem *item;
516
 
517
  /* Menu loop */
518
  do
519
  {
520
    ResumeEmulation = 0;
521
 
522
    /* Set normal clock frequency */
523
    pspSetClockFrequency(222);
524
    /* Set buttons to autorepeat */
525
    pspCtrlSetPollingMode(PSP_CTRL_AUTOREPEAT);
526
 
527
    /* Display appropriate tab */
528
    switch (TabIndex)
529
    {
530 28 jack
    case TAB_STATE:
531
      DisplayStateTab();
532
      break;
533
    case TAB_CONTROL:
534
      /* Load current button mappings */
535
      for (item = ControlUiMenu.Menu->First, i = 0; item; item = item->Next, i++)
536
        pspMenuSelectOptionByValue(item, (void*)ActiveConfig.ButtonMap[i]);
537
      pspUiOpenMenu(&ControlUiMenu, NULL);
538
      break;
539 166 jack
    case TAB_QUICKLOAD:
540 28 jack
      pspUiOpenBrowser(&QuickloadBrowser, (GameName) ? GameName : GamePath);
541 27 jack
      break;
542 29 jack
    case TAB_SYSTEM:
543 112 jack
      item = pspMenuFindItemById(SystemUiMenu.Menu, SYSTEM_VERT_STRIP);
544 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.VertStrip);
545 112 jack
      item = pspMenuFindItemById(SystemUiMenu.Menu, SYSTEM_SOUND_ENGINE);
546 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.SoundEngine);
547 112 jack
      item = pspMenuFindItemById(SystemUiMenu.Menu, SYSTEM_SOUND_BOOST);
548 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.SoundBoost);
549 29 jack
      pspUiOpenMenu(&SystemUiMenu, NULL);
550
      break;
551 27 jack
    case TAB_OPTION:
552
      /* Init menu options */
553 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_DISPLAY_MODE);
554 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.DisplayMode);
555 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_SYNC_FREQ);
556 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.UpdateFreq);
557 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_FRAMESKIP);
558 77 jack
      pspMenuSelectOptionByValue(item, (void*)(int)Options.Frameskip);
559 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_VSYNC);
560 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.VSync);
561 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_CLOCK_FREQ);
562 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.ClockFreq);
563 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_SHOW_FPS);
564 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.ShowFps);
565 112 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_CONTROL_MODE);
566 77 jack
      pspMenuSelectOptionByValue(item, (void*)Options.ControlMode);
567 134 jack
      item = pspMenuFindItemById(OptionUiMenu.Menu, OPTION_ANIMATE);
568
      pspMenuSelectOptionByValue(item, (void*)UiMetric.Animate);
569 27 jack
 
570
      pspUiOpenMenu(&OptionUiMenu, NULL);
571
      break;
572 251 jack
    case TAB_NETPLAY:
573
      pspUiOpenMenu(&NetplayUiMenu, NULL);
574
      break;
575 27 jack
    case TAB_ABOUT:
576
      pspUiSplashScreen(&SplashScreen);
577
      break;
578
    }
579
 
580
    if (!ExitPSP)
581
    {
582
      /* Set buttons to normal mode */
583
      pspCtrlSetPollingMode(PSP_CTRL_NORMAL);
584
 
585
      /* Resume emulation */
586 166 jack
      if (ResumeEmulation)
587 354 jack
      {
588
        if (AdhocMode)
589
        {
590
          /* TODO */
591
          int code = pspUiBETA(OpponentMAC, AdhocMode == ADHOC_HOST);
592
          if (code == PSP_UI_NO)
593
          {
594
            pspAdhocShutdown();
595
            AdhocMode = ADHOC_NONE;
596
          }
597
          else if (code == PSP_UI_CANCEL)
598
          {
599
            ResumeEmulation = 0;
600
            continue;
601
          }
602
        }
603
 
604 166 jack
        if (UiMetric.Animate) pspUiFadeout();
605
        RunEmulator();
606
        if (UiMetric.Animate) pspUiFadeout();
607
      }
608 27 jack
    }
609
  } while (!ExitPSP);
610 19 jack
}
611
 
612 27 jack
int OnGenericCancel(const void *uiobject, const void* param)
613
{
614
  if (GameName) ResumeEmulation = 1;
615
  return 1;
616
}
617
 
618
void OnSplashRender(const void *splash, const void *null)
619
{
620
  int fh, i, x, y, height;
621
  const char *lines[] =
622
  {
623 71 jack
    PSP_APP_NAME" version "PSP_APP_VER" ("__DATE__")",
624 27 jack
    "\026http://psp.akop.org/smsplus",
625
    " ",
626 52 jack
    "2007 Akop Karapetyan (port)",
627
    "1998-2004 Charles MacDonald (emulation)",
628 27 jack
    NULL
629
  };
630
 
631
  fh = pspFontGetLineHeight(UiMetric.Font);
632
 
633
  for (i = 0; lines[i]; i++);
634
  height = fh * (i - 1);
635
 
636
  /* Render lines */
637
  for (i = 0, y = SCR_HEIGHT / 2 - height / 2; lines[i]; i++, y += fh)
638
  {
639
    x = SCR_WIDTH / 2 - pspFontGetTextWidth(UiMetric.Font, lines[i]) / 2;
640 61 jack
    pspVideoPrint(UiMetric.Font, x, y, lines[i], PSP_COLOR_GRAY);
641 27 jack
  }
642
 
643
  /* Render PSP status */
644
  OnGenericRender(splash, null);
645
}
646
 
647
int  OnSplashButtonPress(const struct PspUiSplash *splash,
648
  u32 button_mask)
649
{
650
  return OnGenericButtonPress(NULL, NULL, button_mask);
651
}
652
 
653
/* Handles drawing of generic items */
654
void OnGenericRender(const void *uiobject, const void *item_obj)
655
{
656
  /* Draw tabs */
657
  int height = pspFontGetLineHeight(UiMetric.Font);
658 134 jack
  int width;
659 71 jack
  int i, x;
660 353 jack
 
661 27 jack
  for (i = 0, x = 5; i <= TAB_MAX; i++, x += width + 10)
662
  {
663 28 jack
    width = -10;
664
 
665 29 jack
    if (!GameName && (i == TAB_STATE || i == TAB_SYSTEM))
666
      continue;
667 28 jack
 
668 27 jack
    /* Determine width of text */
669
    width = pspFontGetTextWidth(UiMetric.Font, TabLabel[i]);
670
 
671
    /* Draw background of active tab */
672
    if (i == TabIndex)
673 71 jack
      pspVideoFillRect(x - 5, 0, x + width + 5, height + 1, UiMetric.TabBgColor);
674 27 jack
 
675
    /* Draw name of tab */
676 61 jack
    pspVideoPrint(UiMetric.Font, x, 0, TabLabel[i], PSP_COLOR_WHITE);
677 27 jack
  }
678
}
679
 
680
int OnGenericButtonPress(const PspUiFileBrowser *browser,
681
  const char *path, u32 button_mask)
682
{
683 29 jack
  int tab_index;
684
 
685 27 jack
  /* If L or R are pressed, switch tabs */
686
  if (button_mask & PSP_CTRL_LTRIGGER)
687 28 jack
  {
688 29 jack
    TabIndex--;
689
    do
690
    {
691
      tab_index = TabIndex;
692
      if (!GameName && (TabIndex == TAB_STATE || TabIndex == TAB_SYSTEM)) TabIndex--;
693
      if (TabIndex < 0) TabIndex = TAB_MAX;
694
    } while (tab_index != TabIndex);
695 28 jack
  }
696 27 jack
  else if (button_mask & PSP_CTRL_RTRIGGER)
697 28 jack
  {
698 29 jack
    TabIndex++;
699
    do
700
    {
701
      tab_index = TabIndex;
702
      if (!GameName && (TabIndex == TAB_STATE || TabIndex == TAB_SYSTEM)) TabIndex++;
703
      if (TabIndex > TAB_MAX) TabIndex = 0;
704
    } while (tab_index != TabIndex);
705 28 jack
  }
706 27 jack
  else if ((button_mask & (PSP_CTRL_START | PSP_CTRL_SELECT))
707
    == (PSP_CTRL_START | PSP_CTRL_SELECT))
708
  {
709
    if (pspUtilSaveVramSeq(ScreenshotPath, "ui"))
710
      pspUiAlert("Saved successfully");
711
    else
712
      pspUiAlert("ERROR: Not saved");
713
    return 0;
714
  }
715
  else return 0;
716
 
717
  return 1;
718
}
719
 
720
int  OnMenuItemChanged(const struct PspUiMenu *uimenu,
721
  PspMenuItem* item, const PspMenuOption* option)
722
{
723 28 jack
  if (uimenu == &ControlUiMenu)
724 27 jack
  {
725 112 jack
    ActiveConfig.ButtonMap[item->ID] = (unsigned int)option->Value;
726 28 jack
  }
727 49 jack
  else if (uimenu == &SystemUiMenu)
728
  {
729 112 jack
    switch(item->ID)
730 49 jack
    {
731
    case SYSTEM_VERT_STRIP:
732 77 jack
      Options.VertStrip = (int)option->Value;
733 49 jack
      break;
734
    case SYSTEM_SOUND_ENGINE:
735 77 jack
      if (Options.SoundEngine != (int)option->Value)
736 49 jack
      {
737
        pspUiFlashMessage("Initializing sound\nPlease wait...");
738
        sound_shutdown();
739 77 jack
        snd.fm_which = (Options.SoundEngine = (int)option->Value);
740 49 jack
        sound_init();
741
      }
742
      break;
743 52 jack
    case SYSTEM_SOUND_BOOST:
744 77 jack
      Options.SoundBoost = (int)option->Value;
745 52 jack
      break;
746 49 jack
    }
747
  }
748 28 jack
  else if (uimenu == &OptionUiMenu)
749
  {
750 112 jack
    switch(item->ID)
751 27 jack
    {
752
    case OPTION_DISPLAY_MODE:
753 77 jack
      Options.DisplayMode = (int)option->Value;
754 27 jack
      break;
755
    case OPTION_SYNC_FREQ:
756 77 jack
      Options.UpdateFreq = (int)option->Value;
757 27 jack
      break;
758
    case OPTION_FRAMESKIP:
759 77 jack
      Options.Frameskip = (int)option->Value;
760 27 jack
      break;
761
    case OPTION_VSYNC:
762 77 jack
      Options.VSync = (int)option->Value;
763 27 jack
      break;
764
    case OPTION_CLOCK_FREQ:
765 77 jack
      Options.ClockFreq = (int)option->Value;
766 27 jack
      break;
767
    case OPTION_SHOW_FPS:
768 77 jack
      Options.ShowFps = (int)option->Value;
769 27 jack
      break;
770
    case OPTION_CONTROL_MODE:
771 77 jack
      Options.ControlMode = (int)option->Value;
772 27 jack
      UiMetric.OkButton = (!(int)option->Value) ? PSP_CTRL_CROSS
773
        : PSP_CTRL_CIRCLE;
774
      UiMetric.CancelButton = (!(int)option->Value) ? PSP_CTRL_CIRCLE
775
        : PSP_CTRL_CROSS;
776
      break;
777 134 jack
    case OPTION_ANIMATE:
778
      UiMetric.Animate = (int)option->Value;
779
      break;
780 27 jack
    }
781
  }
782
 
783
  return 1;
784
}
785
 
786
int OnMenuOk(const void *uimenu, const void* sel_item)
787
{
788 28 jack
  if (uimenu == &ControlUiMenu)
789
  {
790
    /* Save to MS */
791
    if (SaveButtonConfig())
792
      pspUiAlert("Changes saved");
793
    else
794
      pspUiAlert("ERROR: Changes not saved");
795
  }
796 29 jack
  else if (uimenu == &SystemUiMenu)
797
  {
798 112 jack
    switch (((const PspMenuItem*)sel_item)->ID)
799 29 jack
    {
800
    case SYSTEM_RESET:
801
      /* Reset system */
802
      if (pspUiConfirm("Reset the system?"))
803
      {
804
        ResumeEmulation = 1;
805
        system_reset();
806
        return 1;
807
      }
808
      break;
809
 
810
    case SYSTEM_SCRNSHOT:
811
      /* Save screenshot */
812 204 jack
      if (!pspUtilSavePngSeq(ScreenshotPath, pspFileGetFilename(GameName), Screen))
813 29 jack
        pspUiAlert("ERROR: Screenshot not saved");
814
      else
815
        pspUiAlert("Screenshot saved successfully");
816
      break;
817 250 jack
    }
818
  }
819
  else if (uimenu == &NetplayUiMenu)
820
  {
821
    switch (((const PspMenuItem*)sel_item)->ID)
822
    {
823
    case NETPLAY_HOST:
824
      if (HostGame())
825 236 jack
      {
826 250 jack
        ResumeEmulation = 1;
827
        return 1;
828 236 jack
      }
829
      break;
830 250 jack
    case NETPLAY_JOIN:
831
      if (JoinGame())
832
      {
833
        ResumeEmulation = 1;
834
        return 1;
835
      }
836
      break;
837
    case NETPLAY_DISC:
838
      if (AdhocMode)
839
      {
840
        pspAdhocShutdown();
841
        AdhocMode = ADHOC_NONE;
842
      }
843
      break;
844 29 jack
    }
845
  }
846
 
847 27 jack
  return 0;
848
}
849
 
850 237 jack
int OnMenuButtonPress(const struct PspUiMenu *uimenu,
851
                      PspMenuItem* sel_item,
852
                      u32 button_mask)
853 27 jack
{
854 28 jack
  if (uimenu == &ControlUiMenu)
855
  {
856
    if (button_mask & PSP_CTRL_TRIANGLE)
857
    {
858
      PspMenuItem *item;
859
      int i;
860
 
861
      /* Load default mapping */
862
      InitButtonConfig();
863
 
864
      /* Modify the menu */
865
      for (item = ControlUiMenu.Menu->First, i = 0; item; item = item->Next, i++)
866
        pspMenuSelectOptionByValue(item, (void*)DefaultConfig.ButtonMap[i]);
867
 
868
      return 0;
869
    }
870
  }
871
 
872 27 jack
  return OnGenericButtonPress(NULL, NULL, button_mask);
873
}
874
 
875
int OnQuickloadOk(const void *browser, const void *path)
876
{
877
  if (GameName)
878
  {
879
    free(GameName);
880
    system_poweroff();
881
  }
882
 
883 237 jack
  if (!load_rom((void*)path))
884 27 jack
  {
885
    pspUiAlert("Error loading cartridge");
886
    return 0;
887
  }
888 240 jack
 
889
  GameName = strdup(path);
890
 
891
  if (GamePath) free(GamePath);
892
  GamePath = pspFileGetParentDirectory(GameName);
893
 
894
  system_reinit();
895 27 jack
  system_poweron();
896
 
897
  ResumeEmulation = 1;
898
  return 1;
899
}
900
 
901 28 jack
int OnSaveStateOk(const void *gallery, const void *item)
902
{
903
  if (!GameName) { TabIndex++; return 0; }
904
 
905
  char *path;
906 204 jack
  const char *config_name = pspFileGetFilename(GameName);
907 28 jack
 
908
  path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
909
  sprintf(path, "%s%s.s%02i", SaveStatePath, config_name,
910 112 jack
    ((const PspMenuItem*)item)->ID);
911 28 jack
 
912 204 jack
  if (pspFileCheckIfExists(path) && pspUiConfirm("Load state?"))
913 28 jack
  {
914
    if (LoadState(path))
915
    {
916
      ResumeEmulation = 1;
917 112 jack
      pspMenuFindItemById(((const PspUiGallery*)gallery)->Menu,
918
        ((const PspMenuItem*)item)->ID);
919 28 jack
      free(path);
920
 
921
      return 1;
922
    }
923
    pspUiAlert("ERROR: State failed to load");
924
  }
925
 
926
  free(path);
927
  return 0;
928
}
929
 
930
int OnSaveStateButtonPress(const PspUiGallery *gallery,
931 166 jack
      PspMenuItem *sel, u32 button_mask)
932 28 jack
{
933
  if (!GameName) { TabIndex++; return 0; }
934
 
935
  if (button_mask & PSP_CTRL_SQUARE
936
    || button_mask & PSP_CTRL_TRIANGLE)
937
  {
938
    char *path;
939
    char caption[32];
940 204 jack
    const char *config_name = pspFileGetFilename(GameName);
941 112 jack
    PspMenuItem *item = pspMenuFindItemById(gallery->Menu, sel->ID);
942 28 jack
 
943
    path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
944 112 jack
    sprintf(path, "%s%s.s%02i", SaveStatePath, config_name, item->ID);
945 28 jack
 
946
    do /* not a real loop; flow control construct */
947
    {
948
      if (button_mask & PSP_CTRL_SQUARE)
949
      {
950 204 jack
        if (pspFileCheckIfExists(path) && !pspUiConfirm("Overwrite existing state?"))
951 28 jack
          break;
952
 
953
        pspUiFlashMessage("Saving, please wait ...");
954
 
955
        PspImage *icon;
956
        if (!(icon = SaveState(path, Screen)))
957
        {
958
          pspUiAlert("ERROR: State not saved");
959
          break;
960
        }
961
 
962
        SceIoStat stat;
963
 
964
        /* Trash the old icon (if any) */
965
        if (item->Icon && item->Icon != NoSaveIcon)
966
          pspImageDestroy((PspImage*)item->Icon);
967
 
968
        /* Update icon, help text */
969
        item->Icon = icon;
970
        pspMenuSetHelpText(item, PresentSlotText);
971
 
972
        /* Get file modification time/date */
973
        if (sceIoGetstat(path, &stat) < 0)
974
          sprintf(caption, "ERROR");
975
        else
976
          sprintf(caption, "%02i/%02i/%02i %02i:%02i",
977
            stat.st_mtime.month,
978
            stat.st_mtime.day,
979
            stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
980
            stat.st_mtime.hour,
981
            stat.st_mtime.minute);
982
 
983
        pspMenuSetCaption(item, caption);
984
      }
985
      else if (button_mask & PSP_CTRL_TRIANGLE)
986
      {
987 204 jack
        if (!pspFileCheckIfExists(path) || !pspUiConfirm("Delete state?"))
988 28 jack
          break;
989
 
990 204 jack
        if (!pspFileDelete(path))
991 28 jack
        {
992
          pspUiAlert("ERROR: State not deleted");
993
          break;
994
        }
995
 
996
        /* Trash the old icon (if any) */
997
        if (item->Icon && item->Icon != NoSaveIcon)
998
          pspImageDestroy((PspImage*)item->Icon);
999
 
1000
        /* Update icon, caption */
1001
        item->Icon = NoSaveIcon;
1002
        pspMenuSetHelpText(item, EmptySlotText);
1003
        pspMenuSetCaption(item, "Empty");
1004
      }
1005
    } while (0);
1006
 
1007
    if (path) free(path);
1008
    return 0;
1009
  }
1010
 
1011
  return OnGenericButtonPress(NULL, NULL, button_mask);
1012
}
1013
 
1014 29 jack
/* Handles any special drawing for the system menu */
1015
void OnSystemRender(const void *uiobject, const void *item_obj)
1016
{
1017
  int w, h, x, y;
1018 78 jack
  w = Screen->Viewport.Width >> 1;
1019
  h = Screen->Viewport.Height >> 1;
1020 29 jack
  x = SCR_WIDTH - w - 8;
1021
  y = SCR_HEIGHT - h - 80;
1022
 
1023
  /* Draw a small representation of the screen */
1024 61 jack
  pspVideoShadowRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_BLACK, 3);
1025 29 jack
  pspVideoPutImage(Screen, x, y, w, h);
1026 61 jack
  pspVideoDrawRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_GRAY);
1027 29 jack
 
1028
  OnGenericRender(uiobject, item_obj);
1029
}
1030
 
1031 28 jack
static void DisplayStateTab()
1032
{
1033
  if (!GameName) { TabIndex++; return; }
1034
 
1035 245 jack
  ScePspDateTime latest;
1036
  PspMenuItem *item, *sel = NULL;
1037 28 jack
  SceIoStat stat;
1038
  char caption[32];
1039
 
1040 204 jack
  const char *config_name = pspFileGetFilename(GameName);
1041 28 jack
  char *path = (char*)malloc(strlen(SaveStatePath) + strlen(config_name) + 8);
1042
  char *game_name = strdup(config_name);
1043
  char *dot = strrchr(game_name, '.');
1044
  if (dot) *dot='\0';
1045
 
1046 245 jack
  memset(&latest,0,sizeof(latest));
1047
 
1048 28 jack
  /* Initialize icons */
1049
  for (item = SaveStateGallery.Menu->First; item; item = item->Next)
1050
  {
1051 112 jack
    sprintf(path, "%s%s.s%02i", SaveStatePath, config_name, item->ID);
1052 28 jack
 
1053 204 jack
    if (pspFileCheckIfExists(path))
1054 28 jack
    {
1055
      if (sceIoGetstat(path, &stat) < 0)
1056
        sprintf(caption, "ERROR");
1057
      else
1058 245 jack
      {
1059
        /* Determine the latest save state */
1060
        if (pspUtilCompareDates(&latest, &stat.st_mtime) < 0)
1061
        {
1062
          sel = item;
1063
          latest = stat.st_mtime;
1064
        }
1065
 
1066 28 jack
        sprintf(caption, "%02i/%02i/%02i %02i:%02i",
1067
          stat.st_mtime.month,
1068
          stat.st_mtime.day,
1069
          stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
1070
          stat.st_mtime.hour,
1071
          stat.st_mtime.minute);
1072 245 jack
      }
1073 28 jack
 
1074
      pspMenuSetCaption(item, caption);
1075
      item->Icon = LoadStateIcon(path);
1076
      pspMenuSetHelpText(item, PresentSlotText);
1077
    }
1078
    else
1079
    {
1080
      pspMenuSetCaption(item, "Empty");
1081
      item->Icon = NoSaveIcon;
1082
      pspMenuSetHelpText(item, EmptySlotText);
1083
    }
1084
  }
1085
 
1086
  free(path);
1087 245 jack
 
1088
  /* Highlight the latest save state if none are selected */
1089
  if (SaveStateGallery.Menu->Selected == NULL)
1090
    SaveStateGallery.Menu->Selected = sel;
1091
 
1092 28 jack
  pspUiOpenGallery(&SaveStateGallery, game_name);
1093
  free(game_name);
1094
 
1095
  /* Destroy any icons */
1096
  for (item = SaveStateGallery.Menu->First; item; item = item->Next)
1097
    if (item->Icon != NULL && item->Icon != NoSaveIcon)
1098
      pspImageDestroy((PspImage*)item->Icon);
1099
}
1100
 
1101
/* Initialize game configuration */
1102
static void InitButtonConfig()
1103
{
1104
  memcpy(&ActiveConfig, &DefaultConfig, sizeof(struct ButtonConfig));
1105
}
1106
 
1107
/* Load game configuration */
1108
static int LoadButtonConfig()
1109
{
1110
  char *path;
1111
  if (!(path = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(ButtonConfigFile) + 6))))
1112
    return 0;
1113
  sprintf(path, "%s%s.cnf", pspGetAppDirectory(), ButtonConfigFile);
1114
 
1115
  /* Open file for reading */
1116
  FILE *file = fopen(path, "r");
1117
  free(path);
1118
 
1119
  /* If no configuration, load defaults */
1120
  if (!file)
1121
  {
1122
    InitButtonConfig();
1123
    return 1;
1124
  }
1125
 
1126
  /* Read contents of struct */
1127
  int nread = fread(&ActiveConfig, sizeof(struct ButtonConfig), 1, file);
1128
  fclose(file);
1129
 
1130
  if (nread != 1)
1131
  {
1132
    InitButtonConfig();
1133
    return 0;
1134
  }
1135
 
1136
  return 1;
1137
}
1138
 
1139
/* Save game configuration */
1140
static int SaveButtonConfig()
1141
{
1142
  char *path;
1143
  if (!(path = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(ButtonConfigFile) + 6))))
1144
    return 0;
1145
  sprintf(path, "%s%s.cnf", pspGetAppDirectory(), ButtonConfigFile);
1146
 
1147
  /* Open file for writing */
1148
  FILE *file = fopen(path, "w");
1149
  free(path);
1150
  if (!file) return 0;
1151
 
1152
  /* Write contents of struct */
1153
  int nwritten = fwrite(&ActiveConfig, sizeof(struct ButtonConfig), 1, file);
1154
  fclose(file);
1155
 
1156
  return (nwritten == 1);
1157
}
1158
 
1159 27 jack
/* Load options */
1160
void LoadOptions()
1161
{
1162
  char *path = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(OptionsFile) + 1));
1163
  sprintf(path, "%s%s", pspGetAppDirectory(), OptionsFile);
1164
 
1165 39 jack
  /* Initialize INI structure */
1166
  PspInit *init = pspInitCreate();
1167 27 jack
 
1168 39 jack
  /* Read the file */
1169 112 jack
  pspInitLoad(init, path);
1170 166 jack
 
1171 112 jack
  /* Load values */
1172
  Options.DisplayMode = pspInitGetInt(init, "Video", "Display Mode", DISPLAY_MODE_UNSCALED);
1173
  Options.UpdateFreq = pspInitGetInt(init, "Video", "Update Frequency", 60);
1174
  Options.Frameskip = pspInitGetInt(init, "Video", "Frameskip", 1);
1175
  Options.VSync = pspInitGetInt(init, "Video", "VSync", 0);
1176
  Options.ClockFreq = pspInitGetInt(init, "Video", "PSP Clock Frequency", 222);
1177
  Options.ShowFps = pspInitGetInt(init, "Video", "Show FPS", 0);
1178
  Options.ControlMode = pspInitGetInt(init, "Menu", "Control Mode", 0);
1179 134 jack
  UiMetric.Animate = pspInitGetInt(init, "Menu", "Animate", 1);
1180 112 jack
  Options.VertStrip = pspInitGetInt(init, "Game", "Vertical Strip", 1);
1181
  Options.SoundEngine = pspInitGetInt(init, "System", "FM Engine", SND_NULL);
1182
  Options.SoundBoost = pspInitGetInt(init, "System", "Sound Boost", 0);
1183 27 jack
 
1184 112 jack
  if (GamePath) free(GamePath);
1185
  GamePath = pspInitGetString(init, "File", "Game Path", NULL);
1186 27 jack
 
1187 39 jack
  /* Clean up */
1188
  free(path);
1189
  pspInitDestroy(init);
1190
}
1191 27 jack
 
1192 39 jack
/* Save options */
1193
static int SaveOptions()
1194
{
1195
  char *path = (char*)malloc(sizeof(char) * (strlen(pspGetAppDirectory()) + strlen(OptionsFile) + 1));
1196
  sprintf(path, "%s%s", pspGetAppDirectory(), OptionsFile);
1197 27 jack
 
1198 39 jack
  /* Initialize INI structure */
1199
  PspInit *init = pspInitCreate();
1200 27 jack
 
1201 39 jack
  /* Set values */
1202 77 jack
  pspInitSetInt(init, "Video", "Display Mode", Options.DisplayMode);
1203
  pspInitSetInt(init, "Video", "Update Frequency", Options.UpdateFreq);
1204
  pspInitSetInt(init, "Video", "Frameskip", Options.Frameskip);
1205
  pspInitSetInt(init, "Video", "VSync", Options.VSync);
1206
  pspInitSetInt(init, "Video", "PSP Clock Frequency",Options.ClockFreq);
1207
  pspInitSetInt(init, "Video", "Show FPS", Options.ShowFps);
1208
  pspInitSetInt(init, "Menu", "Control Mode", Options.ControlMode);
1209 134 jack
  pspInitSetInt(init, "Menu", "Animate", UiMetric.Animate);
1210 77 jack
  pspInitSetInt(init, "Game", "Vertical Strip", Options.VertStrip);
1211
  pspInitSetInt(init, "System", "FM Engine", Options.SoundEngine);
1212
  pspInitSetInt(init, "System", "Sound Boost", Options.SoundBoost);
1213 39 jack
 
1214
  if (GamePath) pspInitSetString(init, "File", "Game Path", GamePath);
1215
 
1216
  /* Save INI file */
1217
  int status = pspInitSave(init, path);
1218
 
1219
  /* Clean up */
1220
  pspInitDestroy(init);
1221 27 jack
  free(path);
1222 39 jack
 
1223
  return status;
1224 27 jack
}
1225
 
1226 28 jack
/* Load state icon */
1227
PspImage* LoadStateIcon(const char *path)
1228
{
1229
  /* Open file for reading */
1230
  FILE *f = fopen(path, "r");
1231
  if (!f) return NULL;
1232
 
1233
  /* Load image */
1234 53 jack
  PspImage *image = pspImageLoadPngFd(f);
1235 28 jack
  fclose(f);
1236
 
1237
  return image;
1238
}
1239
 
1240
/* Load state */
1241
int LoadState(const char *path)
1242
{
1243
  /* Open file for reading */
1244
  FILE *f = fopen(path, "r");
1245
  if (!f) return 0;
1246
 
1247
  /* Load image into temporary object */
1248 53 jack
  PspImage *image = pspImageLoadPngFd(f);
1249 28 jack
  pspImageDestroy(image);
1250
 
1251
  system_load_state(f);
1252
  fclose(f);
1253
 
1254
  return 1;
1255
}
1256
 
1257
/* Save state */
1258
PspImage* SaveState(const char *path, PspImage *icon)
1259
{
1260
  /* Open file for writing */
1261
  FILE *f;
1262
  if (!(f = fopen(path, "w")))
1263
    return NULL;
1264
 
1265
  /* Create thumbnail */
1266 32 jack
  PspImage *thumb;
1267
  thumb = (icon->Viewport.Width < 200)
1268
    ? pspImageCreateCopy(icon) : pspImageCreateThumbnail(icon);
1269 28 jack
  if (!thumb) { fclose(f); return NULL; }
1270
 
1271
  /* Write the thumbnail */
1272 53 jack
  if (!pspImageSavePngFd(f, thumb))
1273 28 jack
  {
1274
    pspImageDestroy(thumb);
1275
    fclose(f);
1276
    return NULL;
1277
  }
1278
 
1279
  /* Save state */
1280
  system_save_state(f);
1281
 
1282
  fclose(f);
1283
  return thumb;
1284
}
1285
 
1286 27 jack
/* Release menu resources */
1287 19 jack
void TrashMenu()
1288
{
1289
  TrashEmulator();
1290 27 jack
 
1291 39 jack
  /* Save options */
1292
  SaveOptions();
1293
 
1294 27 jack
  /* Trash menus */
1295
  pspMenuDestroy(OptionUiMenu.Menu);
1296 28 jack
  pspMenuDestroy(ControlUiMenu.Menu);
1297
  pspMenuDestroy(SaveStateGallery.Menu);
1298 27 jack
  pspMenuDestroy(SystemUiMenu.Menu);
1299 250 jack
  pspMenuDestroy(NetplayUiMenu.Menu);
1300 27 jack
 
1301
  /* Trash images */
1302
  if (Background) pspImageDestroy(Background);
1303
  if (NoSaveIcon) pspImageDestroy(NoSaveIcon);
1304
 
1305
  if (GameName) free(GameName);
1306 28 jack
  if (GamePath) free(GamePath);
1307
 
1308 27 jack
  free(ScreenshotPath);
1309
  free(SaveStatePath);
1310 19 jack
}
1311 28 jack
 
1312
/* Save or load SRAM */
1313
void system_manage_sram(uint8 *sram, int slot, int mode)
1314
{
1315 244 jack
  if (AdhocMode)
1316
  {
1317
    memset(sram, 0x00, 0x8000);
1318
    return;
1319
  }
1320
 
1321 28 jack
  FILE *fd;
1322 204 jack
  const char *config_name = pspFileGetFilename(GameName);
1323 28 jack
  char *path = (char*)malloc(sizeof(char)
1324
    * (strlen(SaveStatePath) + strlen(config_name) + 8));
1325
  sprintf(path, "%s%s.srm", SaveStatePath, config_name);
1326
 
1327
  switch(mode)
1328
  {
1329
  case SRAM_SAVE:
1330
    if(sms.save)
1331
    {
1332
      fd = fopen(path, "w");
1333
      if(fd)
1334
      {
1335
        fwrite(sram, 0x8000, 1, fd);
1336
        fclose(fd);
1337
      }
1338
    }
1339
    break;
1340
 
1341
  case SRAM_LOAD:
1342
    fd = fopen(path, "r");
1343
    if(fd)
1344
    {
1345
      sms.save = 1;
1346
      fread(sram, 0x8000, 1, fd);
1347
      fclose(fd);
1348
    }
1349
    else
1350
    {
1351
      /* No SRAM file, so initialize memory */
1352
      memset(sram, 0x00, 0x8000);
1353
    }
1354
    break;
1355
  }
1356
 
1357
  free(path);
1358
}
1359 250 jack
 
1360
static int JoinGame()
1361
{
1362
  if (AdhocMode && !pspUiConfirm("You are currently connected. Disconnect?"))
1363
    return 0;
1364
 
1365
  PspMAC mac;
1366
  AdhocMode = ADHOC_NONE;
1367
 
1368
  if (!pspUiAdhocJoin(mac))
1369
    return 0;
1370
 
1371
  sceKernelDelayThread(1000000);
1372
  pspUiFlashMessage("Receiving game...");
1373
 
1374
  /* TODO: this needs to be done elsewhere */
1375
  if (GameName)
1376
  {
1377
    free(GameName);
1378
    system_poweroff();
1379
  }
1380
 
1381
  /* Receive ROM */
1382
  int size = 0;
1383
  if (cart.rom)
1384
  {
1385
    free(cart.rom);
1386
    cart.rom = NULL;
1387
  }
1388
 
1389
  if (!pspAdhocRecvBlob((void*)&cart.rom, &size))
1390
  {
1391
    pspAdhocShutdown();
1392
    pspUiAlert("An error occurred while receiving game");
1393
    return 0;
1394
  }
1395
 
1396
  /* TODO? this is from loadrom.c */
1397
  cart.pages    = (size / 0x4000);
1398
  cart.mapper   = MAPPER_SEGA;
1399
  sms.display   = DISPLAY_NTSC;
1400
  sms.territory = TERRITORY_EXPORT;
1401
  sms.console   = CONSOLE_SMS;
1402
  system_assign_device(PORT_A, DEVICE_PAD2B);
1403
  system_assign_device(PORT_B, DEVICE_PAD2B);
1404
 
1405
  GameName = strdup((GamePath) ? GamePath : pspGetAppDirectory()); /* TODO */
1406
 
1407
  /* TODO: this needs to be done elsewhere */
1408
  system_reinit();
1409
  system_poweron();
1410
 
1411
  AdhocMode = ADHOC_CLIENT;
1412
  memcpy(OpponentMAC, mac, sizeof(PspMAC));
1413
 
1414
  return 1;
1415
}
1416
 
1417
static int HostGame()
1418
{
1419 251 jack
  if (!GameName)
1420 250 jack
  {
1421
    pspUiAlert("No game is currently loaded. Load a game and try again");
1422
    return 0;
1423
  }
1424
 
1425
  if (sms.console != CONSOLE_SMS)
1426
  {
1427
    pspUiAlert("Only Master System games are currently supported for net play");
1428
    return 0;
1429
  }
1430
 
1431 353 jack
  if ((AdhocMode && !pspUiConfirm("You are currently connected. Disconnect?"))
1432 250 jack
    || (!AdhocMode && !pspUiConfirm("Any game progress will be lost. Proceed?")))
1433
    return 0;
1434
 
1435
  system_poweroff();
1436 353 jack
 
1437 250 jack
  PspMAC mac;
1438
  AdhocMode = ADHOC_NONE;
1439
 
1440
  if (!pspUiAdhocHost(pspFileGetFilename(GamePath), mac))
1441
    return 0;
1442
 
1443
  sceKernelDelayThread(3000000);
1444
  pspUiFlashMessage("Sending game...");
1445
 
1446
  /* Send ROM */
1447
  int size = cart.pages * 0x4000;
1448
  if (!pspAdhocSendBlob(mac, cart.rom, size))
1449
  {
1450
    pspAdhocShutdown();
1451
    pspUiAlert("An error occurred while sending game");
1452
    return 0;
1453
  }
1454
 
1455
  system_reinit();
1456
  system_poweron();
1457
 
1458
  AdhocMode = ADHOC_HOST;
1459
  memcpy(OpponentMAC, mac, sizeof(PspMAC));
1460
 
1461
  return 1;
1462
}