Subversion Repositories psp

[/] [trunk/] [vice/] [arch/] [psp/] [c64ui.c] - Blame information for rev 519

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 345 jack
/*
2
 * c64ui.c - Implementation of the C64-specific part of the UI.
3
 *
4
 * Written by
5 453 jack
 *  Akop Karapetyan <dev@psp.akop.org>
6 345 jack
 *
7
 * This file is part of VICE, the Versatile Commodore Emulator.
8
 * See README for copyright notice.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  (at your option) any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23
 *  02111-1307  USA.
24
 *
25
 */
26
 
27 472 jack
#include "lib/video.h"
28
#include "lib/ui.h"
29
#include "lib/pl_menu.h"
30
#include "lib/pl_file.h"
31
#include "lib/ctrl.h"
32
#include "lib/pl_psp.h"
33
#include "lib/pl_ini.h"
34
#include "lib/pl_util.h"
35
#include "lib/pl_gfx.h"
36
#include "libmz/unzip.h"
37
 
38
#include <stdio.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <pspkernel.h>
42
 
43 453 jack
#include "autostart.h"
44 345 jack
#include "vice.h"
45 517 jack
#include "lib.h"
46 453 jack
#include "machine.h"
47
#include "ui.h"
48
#include "attach.h"
49
#include "util.h"
50
#include "sid.h"
51
#include "log.h"
52
#include "resources.h"
53
#include "tape.h"
54
#include "cartridge.h"
55
#include "imagecontents.h"
56 517 jack
#include "tapecontents.h"
57
#include "diskcontents.h"
58 472 jack
#include "videoarch.h"
59 345 jack
 
60 453 jack
#define TAB_QUICKLOAD 0
61
#define TAB_STATE     1
62
#define TAB_CONTROLS  2
63
#define TAB_OPTIONS   3
64
#define TAB_SYSTEM    4
65
#define TAB_MAX       TAB_SYSTEM
66
#define TAB_ABOUT     5
67
 
68
#define OPTION_DISPLAY_MODE  0x01
69
#define OPTION_FRAME_LIMITER 0x02
70
#define OPTION_CLOCK_FREQ    0x03
71
#define OPTION_SHOW_FPS      0x04
72
#define OPTION_CONTROL_MODE  0x05
73
#define OPTION_ANIMATE       0x06
74
#define OPTION_TOGGLE_VK     0x08
75
#define OPTION_AUTOLOAD      0x09
76
#define OPTION_SHOW_OSI      0x0A
77 462 jack
#define OPTION_SHOW_BORDER   0x0B
78 468 jack
#define OPTION_REFRESH_RATE  0x0C
79
#define OPTION_VSYNC         0x0D
80 453 jack
 
81
#define SYSTEM_SCRNSHOT     0x11
82
#define SYSTEM_RESET        0x12
83
#define SYSTEM_JOYPORT      0x13
84 454 jack
#define SYSTEM_SOUND        0x14
85
#define SYSTEM_SND_ENGINE   0x15
86
#define SYSTEM_TRUE_DRIVE   0x16
87 464 jack
#define SYSTEM_VIDEO_STD    0x17
88 453 jack
 
89 454 jack
#define SYSTEM_CART         0x26
90
#define SYSTEM_TAPE         0x27
91
#define SYSTEM_DRIVE8       0x28
92
 
93 453 jack
#define GET_DRIVE(code) ((code)&0x0F)
94 454 jack
#define GET_DRIVE_MENU_ID(code) (((code)&0x0F)|0x20)
95 453 jack
 
96
static const char
97
  PresentSlotText[] = "\026\244\020 Save\t\026\001\020 Load\t\026\243\020 Delete",
98
  EmptySlotText[]   = "\026\244\020 Save",
99
  ControlHelpText[] = "\026\250\020 Change mapping\t"
100
                      "\026\244\020 Set as default\t\026\243\020 Load defaults";
101
 
102
static const char
103
  *QuickloadFilter[] =
104
     { "ZIP",
105
       "D64","D71","D80","D81","D82","G64","G41","X64",
106
       "T64","TAP",
107
       "PRG","P00",
108
       "CRT",'\0' },
109
  *DiskFilter[] =
110
     { "ZIP", "D64","D71","D80","D81","D82","G64","G41","X64",'\0' },
111
  *CartFilter[] =
112
     { "ZIP", "CRT",'\0' },
113
  *TapeFilter[] =
114
     { "ZIP", "T64","TAP",'\0' };
115
 
116
/* Tab labels */
117
static const char *TabLabel[] =
118 345 jack
{
119 453 jack
  "Game",
120
  "Save/Load",
121
  "Controls",
122
  "Options",
123
  "System",
124
  "About"
125
};
126
 
127
/* Menu definitions */
128
PL_MENU_OPTIONS_BEGIN(ToggleOptions)
129
  PL_MENU_OPTION("Disabled", 0)
130
  PL_MENU_OPTION("Enabled", 1)
131
PL_MENU_OPTIONS_END
132
PL_MENU_OPTIONS_BEGIN(ScreenSizeOptions)
133
  PL_MENU_OPTION("Actual size", DISPLAY_MODE_UNSCALED)
134 466 jack
  PL_MENU_OPTION("4:3 scaled (fit height)", DISPLAY_MODE_FIT_HEIGHT)
135 453 jack
  PL_MENU_OPTION("16:9 scaled (fit screen)", DISPLAY_MODE_FILL_SCREEN)
136
PL_MENU_OPTIONS_END
137
PL_MENU_OPTIONS_BEGIN(PspClockFreqOptions)
138
  PL_MENU_OPTION("222 MHz", 222)
139
  PL_MENU_OPTION("266 MHz", 266)
140
  PL_MENU_OPTION("300 MHz", 300)
141
  PL_MENU_OPTION("333 MHz", 333)
142
PL_MENU_OPTIONS_END
143
PL_MENU_OPTIONS_BEGIN(JoyPortOptions)
144
  PL_MENU_OPTION("Port 1", 1)
145
  PL_MENU_OPTION("Port 2", 2)
146
PL_MENU_OPTIONS_END
147
PL_MENU_OPTIONS_BEGIN(ControlModeOptions)
148
  PL_MENU_OPTION("\026\242\020 cancels, \026\241\020 confirms (US)", 0)
149
  PL_MENU_OPTION("\026\241\020 cancels, \026\242\020 confirms (Japan)", 1)
150
PL_MENU_OPTIONS_END
151
PL_MENU_OPTIONS_BEGIN(VkModeOptions)
152
  PL_MENU_OPTION("Display when button is held down (classic mode)", 0)
153
  PL_MENU_OPTION("Toggle display on and off when button is pressed", 1)
154
PL_MENU_OPTIONS_END
155
PL_MENU_OPTIONS_BEGIN(SoundEngineOptions)
156
  PL_MENU_OPTION("FastSID", SID_ENGINE_FASTSID)
157
#ifdef HAVE_RESID
158
  PL_MENU_OPTION("ReSID", SID_ENGINE_RESID)
159
#endif
160
PL_MENU_OPTIONS_END
161 464 jack
PL_MENU_OPTIONS_BEGIN(VideoStandardOptions)
162
  PL_MENU_OPTION("PAL-G", MACHINE_SYNC_PAL)
163
  PL_MENU_OPTION("NTSC-M", MACHINE_SYNC_NTSC)
164
  PL_MENU_OPTION("Old NTSC-M", MACHINE_SYNC_NTSCOLD)
165
PL_MENU_OPTIONS_END
166 453 jack
PL_MENU_OPTIONS_BEGIN(AutoloadSlots)
167
  PL_MENU_OPTION("Disabled", -1)
168
  PL_MENU_OPTION("1", 0)
169
  PL_MENU_OPTION("2", 1)
170
  PL_MENU_OPTION("3", 2)
171
  PL_MENU_OPTION("4", 3)
172
  PL_MENU_OPTION("5", 4)
173
  PL_MENU_OPTION("6", 5)
174
  PL_MENU_OPTION("7", 6)
175
  PL_MENU_OPTION("8", 7)
176
  PL_MENU_OPTION("9", 8)
177
  PL_MENU_OPTION("10",9)
178
PL_MENU_OPTIONS_END
179 468 jack
PL_MENU_OPTIONS_BEGIN(RefreshRateOptions)
180
  PL_MENU_OPTION("Automatic", 0)
181
  PL_MENU_OPTION("Don't skip frames", 1)
182
  PL_MENU_OPTION("Skip 1 frame", 2)
183
  PL_MENU_OPTION("Skip 2 frames", 3)
184
  PL_MENU_OPTION("Skip 3 frames", 4)
185
  PL_MENU_OPTION("Skip 4 frames", 5)
186
PL_MENU_OPTIONS_END
187 453 jack
PL_MENU_OPTIONS_BEGIN(MappableButtons)
188
  /* Unmapped */
189
  PL_MENU_OPTION("None", 0)
190
  /* Special */
191
  PL_MENU_OPTION("Special: Open Menu",     (SPC|SPC_MENU))
192
  PL_MENU_OPTION("Special: Show keyboard", (SPC|SPC_KYBD))
193
  /* Function keys */
194
  PL_MENU_OPTION("Joystick Up",    JOY|0x01)
195
  PL_MENU_OPTION("Joystick Down",  JOY|0x02)
196
  PL_MENU_OPTION("Joystick Left",  JOY|0x04)
197
  PL_MENU_OPTION("Joystick Right", JOY|0x08)
198
  PL_MENU_OPTION("Joystick Fire",  JOY|0x10)
199
  /* Cursor */
200
  PL_MENU_OPTION("Up/Down",    CK(0,7,8))
201
  PL_MENU_OPTION("Left/Right", CK(0,2,8))
202
  PL_MENU_OPTION("Space",        CK(7,4,8))
203
  /* Function keys */
204
  PL_MENU_OPTION("F1/F2", CK(0,4,8))
205
  PL_MENU_OPTION("F3/F4", CK(0,5,8))
206
  PL_MENU_OPTION("F5/F6", CK(0,6,8))
207
  PL_MENU_OPTION("F7/F8", CK(0,3,8))
208
  /* Etc.. */
209
  PL_MENU_OPTION("Clr/Home",     CK(6,3,8))
210
  PL_MENU_OPTION("Ins/Del",      CK(0,0,8))
211
  PL_MENU_OPTION("Ctrl",         CK(7,2,8))
212
  PL_MENU_OPTION("Restore",      CK(0xf,0xf,8))
213
  PL_MENU_OPTION("Run/Stop",     CK(7,7,8))
214
  PL_MENU_OPTION("Return",       CK(0,1,8))
215
  PL_MENU_OPTION("C= (CBM)",     CK(7,5,2))
216
  PL_MENU_OPTION("L. Shift",     CK(1,7,2))
217
  PL_MENU_OPTION("R. Shift",     CK(6,4,4))
218
  /* Symbols */
219
  PL_MENU_OPTION("+", CK(5,0,8))
220
  PL_MENU_OPTION("-", CK(5,3,8))
221
  PL_MENU_OPTION("Pound sterling", CK(6,0,8))
222
  PL_MENU_OPTION("@", CK(5,6,8))
223
  PL_MENU_OPTION("*", CK(6,1,8))
224
  PL_MENU_OPTION("^", CK(6,6,8))
225
  PL_MENU_OPTION("[", CK(5,5,8))
226
  PL_MENU_OPTION("]", CK(6,2,8))
227
  PL_MENU_OPTION("=", CK(6,5,8))
228
  PL_MENU_OPTION("<", CK(5,7,8))
229
  PL_MENU_OPTION(">", CK(5,4,8))
230
  PL_MENU_OPTION("?", CK(6,7,8))
231
  /* Digits */
232 519 jack
  PL_MENU_OPTION("<-",CK(7,1,8))
233 453 jack
  PL_MENU_OPTION("1", CK(7,0,8))
234
  PL_MENU_OPTION("2", CK(7,3,8))
235
  PL_MENU_OPTION("3", CK(1,0,8))
236
  PL_MENU_OPTION("4", CK(1,3,8))
237
  PL_MENU_OPTION("5", CK(2,0,8))
238
  PL_MENU_OPTION("6", CK(2,3,8))
239
  PL_MENU_OPTION("7", CK(3,0,8))
240
  PL_MENU_OPTION("8", CK(3,3,8))
241
  PL_MENU_OPTION("9", CK(4,0,8))
242
  PL_MENU_OPTION("0", CK(4,3,8))
243
  /* Alphabet */
244
  PL_MENU_OPTION("A", CK(1,2,8))
245
  PL_MENU_OPTION("B", CK(3,4,8))
246
  PL_MENU_OPTION("C", CK(2,4,8))
247
  PL_MENU_OPTION("D", CK(2,2,8))
248
  PL_MENU_OPTION("E", CK(1,6,8))
249
  PL_MENU_OPTION("F", CK(2,5,8))
250
  PL_MENU_OPTION("G", CK(3,2,8))
251
  PL_MENU_OPTION("H", CK(3,5,8))
252
  PL_MENU_OPTION("I", CK(4,1,8))
253
  PL_MENU_OPTION("J", CK(4,2,8))
254
  PL_MENU_OPTION("K", CK(4,5,8))
255
  PL_MENU_OPTION("L", CK(5,2,8))
256
  PL_MENU_OPTION("M", CK(4,4,8))
257
  PL_MENU_OPTION("N", CK(4,7,8))
258
  PL_MENU_OPTION("O", CK(4,6,8))
259
  PL_MENU_OPTION("P", CK(5,1,8))
260
  PL_MENU_OPTION("Q", CK(7,6,8))
261
  PL_MENU_OPTION("R", CK(2,1,8))
262
  PL_MENU_OPTION("S", CK(1,5,8))
263
  PL_MENU_OPTION("T", CK(2,6,8))
264
  PL_MENU_OPTION("U", CK(3,6,8))
265
  PL_MENU_OPTION("V", CK(3,7,8))
266
  PL_MENU_OPTION("W", CK(1,1,8))
267
  PL_MENU_OPTION("X", CK(2,7,8))
268
  PL_MENU_OPTION("Y", CK(3,1,8))
269
  PL_MENU_OPTION("Z", CK(1,4,8))
270
PL_MENU_OPTIONS_END
271
 
272
PL_MENU_ITEMS_BEGIN(SystemMenuDef)
273 464 jack
  PL_MENU_HEADER("Video")
274
  PL_MENU_ITEM("Video standard",SYSTEM_VIDEO_STD,VideoStandardOptions,
275
               "\026\250\020 Select video standard")
276 453 jack
  PL_MENU_HEADER("Sound")
277 454 jack
  PL_MENU_ITEM("Playback",SYSTEM_SOUND,ToggleOptions,
278
               "\026\250\020 Enable/disable sound playback")
279
  PL_MENU_ITEM("SID engine",SYSTEM_SND_ENGINE,SoundEngineOptions,
280 453 jack
               "\026\250\020 Select sound engine")
281
  PL_MENU_HEADER("Input")
282
  PL_MENU_ITEM("Joystick port",SYSTEM_JOYPORT,JoyPortOptions,
283
               "\026\250\020 Select joystick port")
284
  PL_MENU_HEADER("Peripherals")
285
  PL_MENU_ITEM("Cartridge",SYSTEM_CART,NULL,
286
               "\026\001\020 Browse\t\026\243\020 Eject")
287
  PL_MENU_ITEM("Tape",SYSTEM_TAPE,NULL,
288
               "\026\001\020 Browse\t\026\250\020 Autoload program (if image present)\t\026\243\020 Eject")
289
  PL_MENU_ITEM("Drive 8",SYSTEM_DRIVE8,NULL,
290
               "\026\001\020 Browse\t\026\250\020 Autoload program (if image present)\t\026\243\020 Eject")
291
  PL_MENU_ITEM("True drive emulation",SYSTEM_TRUE_DRIVE,ToggleOptions,
292
               "\026\250\020 Enable/disable true drive emulation")
293
  PL_MENU_HEADER("Options")
294
  PL_MENU_ITEM("Reset",SYSTEM_RESET,NULL,
295
               "\026\001\020 Reset system")
296
  PL_MENU_ITEM("Save screenshot",SYSTEM_SCRNSHOT,NULL,
297
               "\026\001\020 Save screenshot")
298
PL_MENU_ITEMS_END
299
PL_MENU_ITEMS_BEGIN(OptionMenuDef)
300
  PL_MENU_HEADER("Video")
301
  PL_MENU_ITEM("Screen size",OPTION_DISPLAY_MODE,ScreenSizeOptions,
302
               "\026\250\020 Change screen size")
303 462 jack
  PL_MENU_ITEM("Border",OPTION_SHOW_BORDER,ToggleOptions,
304
               "\026\250\020 Show/hide border surrounding the main display area")
305 453 jack
  PL_MENU_HEADER("Input")
306
  PL_MENU_ITEM("Virtual keyboard mode",OPTION_TOGGLE_VK,VkModeOptions,
307
               "\026\250\020 Select virtual keyboard mode")
308
  PL_MENU_HEADER("Enhancements")
309
  PL_MENU_ITEM("Autoload slot",OPTION_AUTOLOAD,AutoloadSlots,
310
               "\026\250\020 Select save state to be loaded automatically")
311
  PL_MENU_HEADER("Performance")
312 470 jack
  PL_MENU_ITEM("VSync (NTSC only)",OPTION_VSYNC,ToggleOptions,
313
               "\026\250\020 Enable/disable vertical blanking synchronization")
314
#if 0
315 468 jack
  PL_MENU_ITEM("Frame skipping",OPTION_REFRESH_RATE,RefreshRateOptions,
316
               "\026\250\020 Set frameskip preferences")
317 470 jack
#endif
318 453 jack
  PL_MENU_ITEM("PSP clock frequency",OPTION_CLOCK_FREQ,PspClockFreqOptions,
319
               "\026\250\020 Larger values: faster emulation, faster battery depletion (default: 222MHz)")
320
  PL_MENU_ITEM("Show FPS counter",OPTION_SHOW_FPS,ToggleOptions,
321
               "\026\250\020 Show/hide the frames-per-second counter")
322
  PL_MENU_ITEM("Show system indicators",OPTION_SHOW_OSI,ToggleOptions,
323
               "\026\250\020 Show/hide system status indicators (LED's, etc...)")
324
  PL_MENU_HEADER("Menu")
325
  PL_MENU_ITEM("Button mode",OPTION_CONTROL_MODE,ControlModeOptions,
326
               "\026\250\020 Change OK and Cancel button mapping")
327
  PL_MENU_ITEM("Animations",OPTION_ANIMATE,ToggleOptions,
328
               "\026\250\020 Enable/disable menu animations")
329
PL_MENU_ITEMS_END
330
PL_MENU_ITEMS_BEGIN(ControlMenuDef)
331
  PL_MENU_ITEM(PSP_CHAR_ANALUP,0,MappableButtons,ControlHelpText)
332
  PL_MENU_ITEM(PSP_CHAR_ANALDOWN,1,MappableButtons,ControlHelpText)
333
  PL_MENU_ITEM(PSP_CHAR_ANALLEFT,2,MappableButtons,ControlHelpText)
334
  PL_MENU_ITEM(PSP_CHAR_ANALRIGHT,3,MappableButtons,ControlHelpText)
335
  PL_MENU_ITEM(PSP_CHAR_UP,4,MappableButtons,ControlHelpText)
336
  PL_MENU_ITEM(PSP_CHAR_DOWN,5,MappableButtons,ControlHelpText)
337
  PL_MENU_ITEM(PSP_CHAR_LEFT,6,MappableButtons,ControlHelpText)
338
  PL_MENU_ITEM(PSP_CHAR_RIGHT,7,MappableButtons,ControlHelpText)
339
  PL_MENU_ITEM(PSP_CHAR_SQUARE,8,MappableButtons,ControlHelpText)
340
  PL_MENU_ITEM(PSP_CHAR_CROSS,9,MappableButtons,ControlHelpText)
341
  PL_MENU_ITEM(PSP_CHAR_CIRCLE,10,MappableButtons,ControlHelpText)
342
  PL_MENU_ITEM(PSP_CHAR_TRIANGLE,11,MappableButtons,ControlHelpText)
343
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER,12,MappableButtons,ControlHelpText)
344
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER,13,MappableButtons,ControlHelpText)
345
  PL_MENU_ITEM(PSP_CHAR_SELECT,14,MappableButtons,ControlHelpText)
346
  PL_MENU_ITEM(PSP_CHAR_START,15,MappableButtons,ControlHelpText)
347
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_RTRIGGER,16,MappableButtons,ControlHelpText)
348
  PL_MENU_ITEM(PSP_CHAR_START"+"PSP_CHAR_SELECT,17,MappableButtons,ControlHelpText)
349
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_SELECT,18,MappableButtons,ControlHelpText)
350
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER"+"PSP_CHAR_SELECT,19,MappableButtons,ControlHelpText)
351
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_SQUARE,20,MappableButtons,ControlHelpText)
352
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_CROSS,21,MappableButtons,ControlHelpText)
353
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_CIRCLE,22,MappableButtons,ControlHelpText)
354
  PL_MENU_ITEM(PSP_CHAR_LTRIGGER"+"PSP_CHAR_TRIANGLE,23,MappableButtons,ControlHelpText)
355
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER"+"PSP_CHAR_SQUARE,24,MappableButtons,ControlHelpText)
356
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER"+"PSP_CHAR_CROSS,25,MappableButtons,ControlHelpText)
357
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER"+"PSP_CHAR_CIRCLE,26,MappableButtons,ControlHelpText)
358
  PL_MENU_ITEM(PSP_CHAR_RTRIGGER"+"PSP_CHAR_TRIANGLE,27,MappableButtons,ControlHelpText)
359
PL_MENU_ITEMS_END
360
 
361
/* Default configuration */
362
static psp_ctrl_map_t default_map =
363
{
364
  {
365
    JOY|0x01,  /* Analog Up    */
366
    JOY|0x02,  /* Analog Down  */
367
    JOY|0x04,  /* Analog Left  */
368
    JOY|0x08,  /* Analog Right */
369
    JOY|0x01,  /* D-pad Up     */
370
    JOY|0x02,  /* D-pad Down   */
371
    JOY|0x04,  /* D-pad Left   */
372
    JOY|0x08,  /* D-pad Right  */
373
    0,         /* Square       */
374
    JOY|0x10,  /* Cross        */
375
    CK(7,4,8), /* Circle       */
376
    0,         /* Triangle     */
377
    0,         /* L Trigger    */
378
    SPC|SPC_KYBD,          /* R Trigger    */
379
    0,         /* Select       */
380
    CK(7,7,8), /* Start        */
381
    SPC|SPC_MENU,          /* L+R Triggers */
382
    0,                     /* Start+Select */
383
    0,                     /* L + Select   */
384
    0,                     /* R + Select   */
385
    0,                     /* L + Square   */
386
    0,                     /* L + Cross    */
387
    0,                     /* L + Circle   */
388
    0,                     /* L + Triangle */
389
    0,                     /* R + Square   */
390
    0,                     /* R + Cross    */
391
    0,                     /* R + Circle   */
392
    0,                     /* R + Triangle */
393
  }
394
};
395
 
396
/* Menu callbacks */
397
static int         OnSplashButtonPress(const struct PspUiSplash *splash,
398
                                       u32 button_mask);
399
static void        OnSplashRender(const void *uiobject, const void *null);
400
static const char* OnSplashGetStatusBarText(const struct PspUiSplash *splash);
401
 
402
static int  OnGenericCancel(const void *uiobject, const void* param);
403
static void OnGenericRender(const void *uiobject, const void *item_obj);
404
static int  OnGenericButtonPress(const PspUiFileBrowser *browser, const char *path,
405
                                 u32 button_mask);
406
 
407
static int OnMenuOk(const void *menu, const void *item);
408
static int OnMenuButtonPress(const struct PspUiMenu *uimenu, pl_menu_item* item,
409
                             u32 button_mask);
410
static int OnMenuItemChanged(const struct PspUiMenu *uimenu, pl_menu_item* item,
411
                             const pl_menu_option* option);
412
 
413
static void OnSystemRender(const void *uiobject, const void *item_obj);
414
 
415
static int OnQuickloadOk(const void *browser, const void *path);
416
static int OnFileOk(const void *browser, const void *path);
417
 
418
static int OnSaveStateOk(const void *gallery, const void *item);
419
static int OnSaveStateButtonPress(const PspUiGallery *gallery,
420
                                  pl_menu_item *sel,
421
                                  u32 button_mask);
422
 
423
PspUiSplash SplashScreen =
424
{
425
  OnSplashRender,
426
  OnGenericCancel,
427
  OnSplashButtonPress,
428
  OnSplashGetStatusBarText
429
};
430
PspUiFileBrowser
431
  QuickloadBrowser =
432
{
433
  OnGenericRender,
434
  OnQuickloadOk,
435
  OnGenericCancel,
436
  OnGenericButtonPress,
437
  QuickloadFilter,
438
 
439
},
440
  FileBrowser =
441
{
442
  OnGenericRender,
443
  OnFileOk,
444
  NULL,
445
  NULL,
446
  NULL,
447
  NULL
448
};
449
 
450
PspUiMenu
451
  OptionUiMenu =
452
  {
453
    OnGenericRender,       /* OnRender() */
454
    OnMenuOk,              /* OnOk() */
455
    OnGenericCancel,       /* OnCancel() */
456
    OnMenuButtonPress,     /* OnButtonPress() */
457
    OnMenuItemChanged,     /* OnItemChanged() */
458
  },
459
  SystemUiMenu =
460
  {
461
    OnSystemRender,        /* OnRender() */
462
    OnMenuOk,              /* OnOk() */
463
    OnGenericCancel,       /* OnCancel() */
464
    OnMenuButtonPress,     /* OnButtonPress() */
465
    OnMenuItemChanged,     /* OnItemChanged() */
466
  },
467
  ControlUiMenu =
468
  {
469
    OnGenericRender,       /* OnRender() */
470
    OnMenuOk,              /* OnOk() */
471
    OnGenericCancel,       /* OnCancel() */
472
    OnMenuButtonPress,     /* OnButtonPress() */
473
    OnMenuItemChanged,     /* OnItemChanged() */
474
  };
475
PspUiGallery SaveStateGallery =
476
{
477
  OnGenericRender,             /* OnRender() */
478
  OnSaveStateOk,               /* OnOk() */
479
  OnGenericCancel,             /* OnCancel() */
480
  OnSaveStateButtonPress,      /* OnButtonPress() */
481
  NULL                         /* Userdata */
482
};
483
 
484
pl_file_path psp_current_game = {'\0'},
485
             psp_game_path = {'\0'},
486
             psp_save_state_path,
487
             psp_screenshot_path,
488
             psp_config_path,
489
             psp_temp_path,
490
             psp_tmp_file[] = { "","","","" };
491
psp_options_t psp_options;
492
 
493
#define CURRENT_GAME (psp_current_game)
494
#define GAME_LOADED (psp_current_game[0] != '\0')
495
#define SET_AS_CURRENT_GAME(filename) \
496
  strncpy(psp_current_game, filename, sizeof(psp_current_game) - 1)
497
 
498
static int psp_controls_changed;
499
static int psp_tab_index;
500
static PspImage *psp_menu_bg;
501
static PspImage *psp_blank_ss_icon;
502
static int psp_exit_menu;
503 467 jack
static int psp_options_loaded = 0;
504 453 jack
extern PspImage *Screen;
505
psp_ctrl_map_t current_map;
506
 
507
static void psp_load_options();
508
static int  psp_save_options();
509
 
510
static void psp_init_controls(psp_ctrl_map_t *config);
511
static int  psp_load_controls(const char *filename, psp_ctrl_map_t *config);
512
static int  psp_save_controls(const char *filename, const psp_ctrl_map_t *config);
513
 
514
static PspImage* psp_load_state_icon(const char *path);
515
static int psp_load_state(const char *path);
516 472 jack
static PspImage* psp_save_state(const char *path);
517 453 jack
 
518
static void psp_display_state_tab();
519
static void psp_display_control_tab();
520
static void psp_display_system_tab();
521
static void psp_refresh_devices();
522
 
523
int c64ui_init(int *argc, char **argv)
524
{
525
  /* Initialize paths */
526
  sprintf(psp_save_state_path, "%sstates/", pl_psp_get_app_directory());
527
  sprintf(psp_screenshot_path, "ms0:/PSP/PHOTO/%s/", PSP_APP_NAME);
528
  sprintf(psp_config_path, "%sconfig/", pl_psp_get_app_directory());
529
  sprintf(psp_temp_path, "%stemp/", pl_psp_get_app_directory());
530
 
531
  /* Create directories, if necessary */
532
  if (!pl_file_exists(psp_save_state_path))
533
    pl_file_mkdir_recursive(psp_save_state_path);
534
  if (!pl_file_exists(psp_config_path))
535
    pl_file_mkdir_recursive(psp_config_path);
536
  if (!pl_file_exists(psp_temp_path))
537
    pl_file_mkdir_recursive(psp_temp_path);
538
 
539
  /* Initialize menus */
540
  pl_menu_create(&OptionUiMenu.Menu, OptionMenuDef);
541
  pl_menu_create(&SystemUiMenu.Menu, SystemMenuDef);
542
  pl_menu_create(&ControlUiMenu.Menu, ControlMenuDef);
543
 
544
  /* Init NoSaveState icon image */
545 472 jack
  psp_blank_ss_icon = pspImageCreate(160, 100, PSP_IMAGE_16BPP);
546 453 jack
  pspImageClear(psp_blank_ss_icon, RGB(0x3e,0x31,0xa2));
547
 
548
  /* Initialize state menu */
549
  int i;
550
  pl_menu_item *item;
551
  for (i = 0; i < 10; i++)
552
  {
553
    item = pl_menu_append_item(&SaveStateGallery.Menu, i, NULL);
554
    pl_menu_set_item_help_text(item, EmptySlotText);
555
  }
556
 
557
  /* Load the background image */
558
  psp_menu_bg = pspImageLoadPng("background.png");
559
 
560
  /* Initialize UI components */
561
  UiMetric.Background = psp_menu_bg;
562
  UiMetric.Font = &PspStockFont;
563
  UiMetric.Left = 8;
564
  UiMetric.Top = 24;
565
  UiMetric.Right = 472;
566
  UiMetric.Bottom = 240;
567
  UiMetric.ScrollbarColor = PSP_COLOR_GRAY;
568
  UiMetric.ScrollbarBgColor = 0x44ffffff;
569
  UiMetric.ScrollbarWidth = 10;
570
  UiMetric.TextColor = PSP_COLOR_GRAY;
571
  UiMetric.SelectedColor = COLOR(0xf7,0xc2,0x50,0xFF);
572
  UiMetric.SelectedBgColor = COLOR(0xff,0xff,0xff,0x99);
573
  UiMetric.StatusBarColor = PSP_COLOR_WHITE;
574
  UiMetric.BrowserFileColor = PSP_COLOR_GRAY;
575
  UiMetric.BrowserDirectoryColor = PSP_COLOR_YELLOW;
576
  UiMetric.GalleryIconsPerRow = 5;
577
  UiMetric.GalleryIconMarginWidth = 8;
578
  UiMetric.MenuItemMargin = 20;
579
  UiMetric.MenuSelOptionBg = PSP_COLOR_BLACK;
580
  UiMetric.MenuOptionBoxColor = PSP_COLOR_GRAY;
581
  UiMetric.MenuOptionBoxBg = COLOR(0x3e,0x31,0xa2,0xCC);
582
  UiMetric.MenuDecorColor = UiMetric.SelectedColor;
583
  UiMetric.DialogFogColor = COLOR(0x3e,0x31,0xa2,0x66);
584
  UiMetric.TitlePadding = 4;
585
  UiMetric.TitleColor = PSP_COLOR_WHITE;
586
  UiMetric.MenuFps = 30;
587
  UiMetric.TabBgColor = PSP_COLOR_WHITE;
588
  UiMetric.BrowserScreenshotPath = psp_screenshot_path;
589
  UiMetric.BrowserScreenshotDelay = 30;
590
 
591
  psp_tab_index = TAB_ABOUT;
592 467 jack
  psp_options_loaded = 0;
593 453 jack
 
594
  /* Load default configuration */
595
  psp_load_controls("DEFAULT", &default_map);
596
  psp_init_controls(&current_map);
597
 
598
  return 0;
599
}
600
 
601
void c64ui_shutdown()
602
{
603
  if (psp_menu_bg) pspImageDestroy(psp_menu_bg);
604
 
605
  pl_menu_destroy(&ControlUiMenu.Menu);
606
  pl_menu_destroy(&OptionUiMenu.Menu);
607
  pl_menu_destroy(&SystemUiMenu.Menu);
608
  pl_menu_destroy(&SaveStateGallery.Menu);
609
 
610
  /* Remove temp. files (if any) */
611
  int i;
612
  for (i = 0; i < 4; i++)
613
    if (*psp_tmp_file[i] && pl_file_exists(psp_tmp_file[i]))
614
      pl_file_rm(psp_tmp_file[i]);
615
 
616
  psp_save_options();
617
}
618
 
619
/**************************/
620
/* Helper functions       */
621
/**************************/
622
 
623
static void psp_refresh_devices()
624
{
625
  int unit;
626
  pl_menu_item *item;
627
  const char *name;
628
 
629
  /* Refresh tape contents */
630
  do /* For flow control - not a loop */
631
  {
632
    name = tape_image_dev1->name; /* Filename */
633
    item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_TAPE);
634
    pl_menu_clear_options(item); /* Clear current names */
635
 
636
    if (!name) break;
637
 
638 517 jack
    image_contents_t *listing = tapecontents_read(name);
639 453 jack
 
640 517 jack
    if (listing == NULL)
641
      break;
642 453 jack
 
643 517 jack
    image_contents_file_list_t *element = listing->file_list;
644
 
645
    do
646 453 jack
    {
647 517 jack
      char *string = image_contents_file_to_string(element, 1);
648
      pl_menu_append_option(item, string, NULL, 0);
649
      lib_free(string);
650
    } while ( (element = element->next) != NULL);
651 453 jack
 
652
    /* Select first option */
653
    pl_menu_select_option_by_index(item, 0);
654
  } while (0);
655
 
656
  /* Refresh drive contents */
657
  for (unit = 8; unit <= 8; unit++)
658
  {
659
    name = file_system_get_disk_name(unit); /* Filename */
660
    item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, GET_DRIVE_MENU_ID(unit));
661
    pl_menu_clear_options(item); /* Clear current names */
662
 
663
    if (!name) continue;
664
 
665 517 jack
    image_contents_t *listing = diskcontents_read(name, unit);
666 453 jack
 
667 517 jack
    if (listing == NULL)
668
      continue;
669 453 jack
 
670 517 jack
    image_contents_file_list_t *element = listing->file_list;
671
 
672
    do
673 453 jack
    {
674 517 jack
      char *string = image_contents_file_to_string(element, 1);
675
      pl_menu_append_option(item, string, NULL, 0);
676
      lib_free(string);
677
    } while ( (element = element->next) != NULL);
678 453 jack
 
679
    /* Select first option */
680
    pl_menu_select_option_by_index(item, 0);
681
  }
682
 
683
  /* Cart name */
684
  name = cartridge_get_file_name(0);
685
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_CART);
686
  pl_menu_clear_options(item); /* Clear current names */
687
  if (name)
688
    pl_menu_append_option(item, pl_file_get_filename(name), NULL, 1);
689
}
690
 
691
static void psp_display_system_tab()
692
{
693
  pl_menu_item *item;
694
 
695
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_JOYPORT);
696
  pl_menu_select_option_by_value(item, (void*)psp_options.joyport);
697
 
698
  int setting;
699
  resources_get_int("SidEngine", &setting);
700
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_SND_ENGINE);
701
  pl_menu_select_option_by_value(item, (void*)setting);
702 454 jack
  resources_get_int("Sound", &setting);
703
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_SOUND);
704
  pl_menu_select_option_by_value(item, (void*)setting);
705 453 jack
  resources_get_int("DriveTrueEmulation", &setting);
706
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_TRUE_DRIVE);
707
  pl_menu_select_option_by_value(item, (void*)setting);
708 464 jack
  resources_get_int("MachineVideoStandard", &setting);
709
  item = pl_menu_find_item_by_id(&SystemUiMenu.Menu, SYSTEM_VIDEO_STD);
710
  pl_menu_select_option_by_value(item, (void*)setting);
711 453 jack
 
712
  psp_refresh_devices();
713
  pspUiOpenMenu(&SystemUiMenu, NULL);
714
}
715
 
716
static void psp_display_control_tab()
717
{
718
  pl_menu_item *item;
719
  const char *config_name = (GAME_LOADED)
720
    ? pl_file_get_filename(psp_current_game) : "BASIC";
721
  char *game_name = strdup(config_name);
722
  char *dot = strrchr(game_name, '.');
723
  int i;
724
  if (dot) *dot='\0';
725
 
726
  /* Load current button mappings */
727
  for (item = ControlUiMenu.Menu.items, i = 0; item; item = item->next, i++)
728
    pl_menu_select_option_by_value(item, (void*)current_map.button_map[i]);
729
 
730
  psp_controls_changed = 0;
731
 
732
  pspUiOpenMenu(&ControlUiMenu, game_name);
733
  free(game_name);
734
 
735
  /* Save to MS, if configuration changed */
736
  if (psp_controls_changed)
737
  {
738
    pspUiFlashMessage("Saving configuration, please wait...");
739
    if (!psp_save_controls(config_name, &current_map))
740
      pspUiAlert("ERROR: Changes not saved");
741
  }
742
}
743
 
744
static void psp_init_controls(psp_ctrl_map_t *config)
745
{
746
  /* Initialize to default configuration */
747
  if (config != &default_map)
748
    memcpy(config, &default_map, sizeof(psp_ctrl_map_t));
749
}
750
 
751
static int psp_load_controls(const char *filename, psp_ctrl_map_t *config)
752
{
753
  pl_file_path path;
754
  snprintf(path, sizeof(path), "%s%s.cnf", psp_config_path, filename);
755
 
756
  /* Initialize default controls */
757
  psp_init_controls(config);
758
 
759
  /* No configuration; defaults are fine */
760
  if (!pl_file_exists(path))
761
    return 1;
762
 
763
  /* Open file for reading */
764
  FILE *file = fopen(path, "r");
765
  if (!file) return 0;
766
 
767
  /* Load defaults; attempt to read controls from file */
768
  psp_init_controls(config);
769
  int nread = fread(config, sizeof(uint32_t), MAP_BUTTONS, file);
770
 
771
  fclose(file);
772
 
773
  /* Reading less than MAP_BUTTONS is ok; may be an older config file */
774
  if (nread < 1)
775
  {
776
    psp_init_controls(config);
777 345 jack
    return 0;
778 453 jack
  }
779
 
780
  return 1;
781 345 jack
}
782
 
783 453 jack
static int psp_save_controls(const char *filename, const psp_ctrl_map_t *config)
784 345 jack
{
785 453 jack
  pl_file_path path;
786
  snprintf(path, sizeof(path)-1, "%s%s.cnf", psp_config_path, filename);
787
 
788
  /* Open file for writing */
789
  FILE *file = fopen(path, "w");
790
  if (!file) return 0;
791
 
792
  /* Write contents of struct */
793
  int nwritten = fwrite(config, sizeof(psp_ctrl_map_t), 1, file);
794
  fclose(file);
795
 
796
  return (nwritten == 1);
797 345 jack
}
798 453 jack
 
799
/* Load state icon */
800
static PspImage* psp_load_state_icon(const char *path)
801
{
802
  FILE *f = fopen(path, "r");
803
  if (!f) return NULL;
804
 
805
  /* Load image */
806
  PspImage *image = pspImageLoadPngFd(f);
807
  fclose(f);
808
 
809
  return image;
810
}
811
 
812
/* Load state */
813
static int psp_load_state(const char *path)
814
{
815
  /* Open file for reading */
816
  FILE *f = fopen(path, "r");
817
  if (!f) return 0;
818
 
819
  pspUiFlashMessage("Loading state, please wait...");
820
 
821
  /* Load image into temporary object */
822
  PspImage *image = pspImageLoadPngFd(f);
823
  pspImageDestroy(image);
824
 
825
  /* Load the state data */
826
  /* HACK: snapshot saving overridden in snapshot.c */
827
  int status = machine_read_snapshot((char*)f, 0);
828
  fclose(f);
829
 
830
  return status == 0;
831
}
832
 
833
/* Save state */
834 472 jack
static PspImage* psp_save_state(const char *path)
835 453 jack
{
836 472 jack
  /* Create copy of the screen */
837
  PspImage *copy = pspImageCreateCopy(Screen);
838
  if (!copy) return NULL;
839
 
840
  /* Reset viewport to 320x200 */
841
  psp_reset_viewport(&copy->Viewport, 0);
842
 
843
  /* Create thumbnail, destroy copy */
844
  PspImage *thumb = pspImageCreateThumbnail(copy);
845
  pspImageDestroy(copy);
846
  if (!thumb) return NULL;
847
 
848 453 jack
  /* Open file for writing */
849
  FILE *f;
850
  if (!(f = fopen(path, "w")))
851 472 jack
  {
852
    pspImageDestroy(thumb);
853 453 jack
    return NULL;
854 472 jack
  }
855 453 jack
 
856
  /* Write the thumbnail */
857
  if (!pspImageSavePngFd(f, thumb))
858
  {
859
    pspImageDestroy(thumb);
860
    fclose(f);
861
    return NULL;
862
  }
863
 
864
  /* Write the state */
865
  /* HACK: snapshot saving overridden in snapshot.c */
866
  if (machine_write_snapshot((char*)f, 0, 0, 0) < 0)
867
  {
868
    pspImageDestroy(thumb);
869
    thumb = NULL;
870
  }
871
 
872
  fclose(f);
873
  return thumb;
874
}
875
 
876
static void psp_load_options()
877
{
878
  pl_file_path path;
879
  snprintf(path, sizeof(path) - 1, "%s%s", pl_psp_get_app_directory(), "options.ini");
880
 
881
  /* Load INI */
882
  pl_ini_file file;
883
  pl_ini_load(&file, path);
884
 
885
  psp_options.autoload_slot = pl_ini_get_int(&file, "System", "AutoloadSlot", 9);
886
  psp_options.joyport = pl_ini_get_int(&file, "System", "JoystickPort", 2);
887 462 jack
  psp_options.show_border = pl_ini_get_int(&file, "Video", "ShowBorder", 1);
888 453 jack
  psp_options.display_mode = pl_ini_get_int(&file, "Video", "DisplayMode",
889
                                            DISPLAY_MODE_UNSCALED);
890
  psp_options.clock_freq = pl_ini_get_int(&file, "Video", "PSPClockFrequency", 300);
891
  psp_options.show_fps = pl_ini_get_int(&file, "Video", "ShowFPS", 0);
892
  psp_options.show_osi = pl_ini_get_int(&file, "Video", "ShowOSI", 0);
893 468 jack
  psp_options.vsync = pl_ini_get_int(&file, "Video", "VSync", 0);
894 453 jack
  psp_options.control_mode = pl_ini_get_int(&file, "Menu", "ControlMode", 0);
895
  psp_options.animate_menu = pl_ini_get_int(&file, "Menu", "Animate", 1);
896
  psp_options.toggle_vk = pl_ini_get_int(&file, "Input", "VKMode", 0);
897
  pl_ini_get_string(&file, "File", "GamePath", NULL, psp_game_path, sizeof(psp_game_path));
898
 
899
  /* VICE settings */
900
  int vice_setting;
901
  vice_setting = pl_ini_get_int(&file, "VICE", "SidEngine", SID_ENGINE_FASTSID);
902
  resources_set_int("SidEngine", vice_setting);
903
  vice_setting = pl_ini_get_int(&file, "VICE", "DriveTrueEmulation", 1);
904
  resources_set_int("DriveTrueEmulation", vice_setting);
905 454 jack
  vice_setting = pl_ini_get_int(&file, "VICE", "Sound", 1);
906
  resources_set_int("Sound", vice_setting);
907 464 jack
  vice_setting = pl_ini_get_int(&file, "VICE", "MachineVideoStandard", MACHINE_SYNC_PAL);
908
  resources_set_int("MachineVideoStandard", vice_setting);
909 468 jack
  vice_setting = pl_ini_get_int(&file, "VICE", "RefreshRate", MACHINE_SYNC_PAL);
910
  resources_set_int("RefreshRate", vice_setting);
911 453 jack
 
912
  /* Clean up */
913
  pl_ini_destroy(&file);
914 467 jack
 
915
  /* Reset menu prefs */
916
  UiMetric.OkButton = (!psp_options.control_mode)
917
    ? PSP_CTRL_CROSS : PSP_CTRL_CIRCLE;
918
  UiMetric.CancelButton = (!psp_options.control_mode)
919
    ? PSP_CTRL_CIRCLE : PSP_CTRL_CROSS;
920
  UiMetric.Animate = psp_options.animate_menu;
921 453 jack
}
922
 
923
static int psp_save_options()
924
{
925
  pl_file_path path;
926
  snprintf(path, sizeof(path)-1, "%s%s", pl_psp_get_app_directory(), "options.ini");
927
 
928
  /* Initialize INI structure */
929
  pl_ini_file file;
930
  pl_ini_create(&file);
931
  pl_ini_set_int(&file, "System", "AutoloadSlot", psp_options.autoload_slot);
932
  pl_ini_set_int(&file, "System", "JoystickPort", psp_options.joyport);
933 462 jack
  pl_ini_set_int(&file, "Video", "ShowBorder", psp_options.show_border);
934 453 jack
  pl_ini_set_int(&file, "Video", "DisplayMode", psp_options.display_mode);
935
  pl_ini_set_int(&file, "Video", "PSPClockFrequency", psp_options.clock_freq);
936
  pl_ini_set_int(&file, "Video", "ShowFPS", psp_options.show_fps);
937
  pl_ini_set_int(&file, "Video", "ShowOSI", psp_options.show_osi);
938 468 jack
  pl_ini_set_int(&file, "Video", "VSync", psp_options.vsync);
939 453 jack
  pl_ini_set_int(&file, "Menu", "ControlMode", psp_options.control_mode);
940
  pl_ini_set_int(&file, "Menu", "Animate", psp_options.animate_menu);
941
  pl_ini_set_int(&file, "Input", "VKMode", psp_options.toggle_vk);
942
  pl_ini_set_string(&file, "File", "GamePath", psp_game_path);
943
 
944
  /* VICE settings */
945
  int vice_setting;
946
  resources_get_int("SidEngine", &vice_setting);
947
  pl_ini_set_int(&file, "VICE", "SidEngine", vice_setting);
948
  resources_get_int("DriveTrueEmulation", &vice_setting);
949
  pl_ini_set_int(&file, "VICE", "DriveTrueEmulation", vice_setting);
950 454 jack
  resources_get_int("Sound", &vice_setting);
951
  pl_ini_set_int(&file, "VICE", "Sound", vice_setting);
952 464 jack
  resources_get_int("MachineVideoStandard", &vice_setting);
953
  pl_ini_set_int(&file, "VICE", "MachineVideoStandard", vice_setting);
954 468 jack
  resources_get_int("RefreshRate", &vice_setting);
955
  pl_ini_set_int(&file, "VICE", "RefreshRate", vice_setting);
956 453 jack
 
957
  int status = pl_ini_save(&file, path);
958
  pl_ini_destroy(&file);
959
 
960
  return status;
961
}
962
 
963
static const char *prepare_file(const char *path, int slot)
964
{
965
  const char *game_path = path;
966
  void *file_buffer = NULL;
967
  int file_size = 0;
968
 
969
  if (pl_file_is_of_type(path, "ZIP"))
970
  {
971
    pspUiFlashMessage("Loading compressed file, please wait...");
972
 
973
    char archived_file[512];
974
    unzFile zipfile = NULL;
975
    unz_global_info gi;
976
    unz_file_info fi;
977
 
978
    /* Open archive for reading */
979
    if (!(zipfile = unzOpen(path)))
980
      return NULL;
981
 
982
    /* Get global ZIP file information */
983
    if (unzGetGlobalInfo(zipfile, &gi) != UNZ_OK)
984
    {
985
      unzClose(zipfile);
986
      return NULL;
987
    }
988
 
989
    const char *extension;
990
    int i, j;
991
 
992
    for (i = 0; i < (int)gi.number_entry; i++)
993
    {
994
      /* Get name of the archived file */
995
      if (unzGetCurrentFileInfo(zipfile, &fi, archived_file,
996
          sizeof(archived_file), NULL, 0, NULL, 0) != UNZ_OK)
997
      {
998
        unzClose(zipfile);
999
        return NULL;
1000
      }
1001
 
1002
      extension = pl_file_get_extension(archived_file);
1003
      for (j = 1; QuickloadFilter[j]; j++)
1004
      {
1005
        if (strcasecmp(QuickloadFilter[j], extension) == 0)
1006
        {
1007
          file_size = fi.uncompressed_size;
1008
 
1009
          /* Open archived file for reading */
1010
          if(unzOpenCurrentFile(zipfile) != UNZ_OK)
1011
          {
1012
            unzClose(zipfile);
1013
            return NULL;
1014
          }
1015
 
1016
          if (!(file_buffer = malloc(file_size)))
1017
          {
1018
            unzCloseCurrentFile(zipfile);
1019
            unzClose(zipfile);
1020
            return NULL;
1021
          }
1022
 
1023
          unzReadCurrentFile(zipfile, file_buffer, file_size);
1024
          unzCloseCurrentFile(zipfile);
1025
 
1026
          goto close_archive;
1027
        }
1028
      }
1029
 
1030
      /* Go to the next file in the archive */
1031
      if (i + 1 < (int)gi.number_entry)
1032
      {
1033
        if (unzGoToNextFile(zipfile) != UNZ_OK)
1034
        {
1035
          unzClose(zipfile);
1036
          return NULL;
1037
        }
1038
      }
1039
    }
1040
 
1041
    /* No eligible files */
1042
    return NULL;
1043
 
1044
close_archive:
1045
    unzClose(zipfile);
1046
 
1047
    /* Remove temp. file (if any) */
1048
    if (*psp_tmp_file[slot] && pl_file_exists(psp_tmp_file[slot]))
1049
      pl_file_rm(psp_tmp_file[slot]);
1050
 
1051
    /* Define temp filename */
1052
    sprintf(psp_tmp_file[slot], "%s%s", psp_temp_path, archived_file);
1053
 
1054
    /* Write file to stick */
1055
    FILE *file = fopen(psp_tmp_file[slot], "w");
1056
    if (!file)
1057
    {
1058
      *psp_tmp_file[slot] = '\0';
1059
      return NULL;
1060
    }
1061
    if (fwrite(file_buffer, 1, file_size, file) < file_size)
1062
    {
1063
      fclose(file);
1064
      *psp_tmp_file[slot] = '\0';
1065
      return NULL;
1066
    }
1067
    fclose(file);
1068
 
1069
    game_path = psp_tmp_file[slot];
1070
  }
1071
 
1072
  return game_path;
1073
}
1074
 
1075
static int psp_load_game(const char *path)
1076
{
1077
  /* Eject all cartridges, tapes & disks */
1078
  cartridge_detach_image();
1079
  tape_image_detach(1);
1080
  file_system_detach_disk(GET_DRIVE(8));
1081
 
1082
  const char *game_path = prepare_file(path, 0);
1083
 
1084
  if (!game_path)
1085
  {
1086
    pspUiAlert("Error loading compressed file");
1087
    return 0;
1088
  }
1089
 
1090
  if (pl_file_is_of_type(game_path, "CRT"))
1091
    return !cartridge_attach_image(CARTRIDGE_CRT, game_path);
1092
 
1093
  return !autostart_autodetect(game_path, NULL, 0, AUTOSTART_MODE_RUN);
1094
}
1095
 
1096
void psp_display_menu()
1097
{
1098 467 jack
  /* Load the options. Loading them in c64_init crashes the emulator */
1099
  if (!psp_options_loaded)
1100
  {
1101
    psp_load_options();
1102
    psp_options_loaded = 1;
1103
  }
1104
 
1105 470 jack
  int setting = 0;
1106 453 jack
  pl_menu_item *item;
1107
  psp_exit_menu = 0;
1108
 
1109
  /* Set normal clock frequency */
1110
  pl_psp_set_clock_freq(222);
1111
  /* Set buttons to autorepeat */
1112
  pspCtrlSetPollingMode(PSP_CTRL_AUTOREPEAT);
1113
 
1114
  /* Menu loop */
1115
  while (!ExitPSP && !psp_exit_menu)
1116
  {
1117
    /* Display appropriate tab */
1118
    switch (psp_tab_index)
1119
    {
1120
    case TAB_QUICKLOAD:
1121
      pspUiOpenBrowser(&QuickloadBrowser,
1122
        (GAME_LOADED) ? psp_current_game
1123
          : ((psp_game_path[0]) ? psp_game_path : NULL));
1124
      break;
1125
    case TAB_CONTROLS:
1126
      psp_display_control_tab();
1127
      break;
1128
    case TAB_OPTIONS:
1129
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_DISPLAY_MODE);
1130
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.display_mode);
1131
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_CLOCK_FREQ);
1132
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.clock_freq);
1133
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_SHOW_FPS);
1134
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.show_fps);
1135
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_SHOW_OSI);
1136
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.show_osi);
1137
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_CONTROL_MODE);
1138
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.control_mode);
1139
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_ANIMATE);
1140
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.animate_menu);
1141
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_TOGGLE_VK);
1142
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.toggle_vk);
1143
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_AUTOLOAD);
1144
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.autoload_slot);
1145 462 jack
      item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_SHOW_BORDER);
1146
      pl_menu_select_option_by_value(item, (void*)(int)psp_options.show_border);
1147 468 jack
      if ((item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_VSYNC)))
1148
        pl_menu_select_option_by_value(item, (void*)(int)psp_options.vsync);
1149
      resources_get_int("RefreshRate", &setting);
1150 470 jack
      if ((item = pl_menu_find_item_by_id(&OptionUiMenu.Menu, OPTION_REFRESH_RATE)))
1151
        pl_menu_select_option_by_value(item, (void*)setting);
1152 453 jack
 
1153
      pspUiOpenMenu(&OptionUiMenu, NULL);
1154
      break;
1155
    case TAB_STATE:
1156
      psp_display_state_tab();
1157
      break;
1158
    case TAB_SYSTEM:
1159
      psp_display_system_tab();
1160
      break;
1161
    case TAB_ABOUT:
1162
      pspUiSplashScreen(&SplashScreen);
1163
      break;
1164
    }
1165
  }
1166
 
1167
  if (!ExitPSP)
1168
  {
1169
    /* Set clock frequency during emulation */
1170
    pl_psp_set_clock_freq(psp_options.clock_freq);
1171
    /* Set buttons to normal mode */
1172
    pspCtrlSetPollingMode(PSP_CTRL_NORMAL);
1173
 
1174
    if (psp_options.animate_menu)
1175
      pspUiFadeout();
1176
  }
1177
}
1178
 
1179
static void psp_display_state_tab()
1180
{
1181
  pl_menu_item *item, *sel = NULL;
1182
  SceIoStat stat;
1183
  ScePspDateTime latest;
1184
  char caption[32];
1185
  const char *config_name = (GAME_LOADED)
1186
    ? pl_file_get_filename(psp_current_game) : "BASIC";
1187
  char *path = (char*)malloc(strlen(psp_save_state_path) + strlen(config_name) + 8);
1188
  char *game_name = strdup(config_name);
1189
  char *dot = strrchr(game_name, '.');
1190
  if (dot) *dot='\0';
1191
 
1192
  memset(&latest,0,sizeof(latest));
1193
 
1194
  /* Initialize icons */
1195
  for (item = SaveStateGallery.Menu.items; item; item = item->next)
1196
  {
1197
    sprintf(path, "%s%s_%02i.sna", psp_save_state_path, config_name, item->id);
1198
 
1199
    if (pl_file_exists(path))
1200
    {
1201
      if (sceIoGetstat(path, &stat) < 0)
1202
        sprintf(caption, "ERROR");
1203
      else
1204
      {
1205
        /* Determine the latest save state */
1206
        if (pl_util_date_compare(&latest, &stat.st_mtime) < 0)
1207
        {
1208
          sel = item;
1209
          latest = stat.st_mtime;
1210
        }
1211
 
1212
        sprintf(caption, "%02i/%02i/%02i %02i:%02i%s",
1213
          stat.st_mtime.month,
1214
          stat.st_mtime.day,
1215
          stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
1216
          stat.st_mtime.hour,
1217
          stat.st_mtime.minute,
1218
          ((int)item->id == psp_options.autoload_slot) ? "*" : "");
1219
      }
1220
 
1221
      pl_menu_set_item_caption(item, caption);
1222
      item->param = psp_load_state_icon(path);
1223
      pl_menu_set_item_help_text(item, PresentSlotText);
1224
    }
1225
    else
1226
    {
1227
      pl_menu_set_item_caption(item, ((int)item->id == psp_options.autoload_slot)
1228
          ? "Autoload" : "Empty");
1229
      item->param = psp_blank_ss_icon;
1230
      pl_menu_set_item_help_text(item, EmptySlotText);
1231
    }
1232
  }
1233
 
1234
  free(path);
1235
 
1236
  /* Highlight the latest save state if none are selected */
1237
  if (SaveStateGallery.Menu.selected == NULL)
1238
    SaveStateGallery.Menu.selected = sel;
1239
 
1240
  pspUiOpenGallery(&SaveStateGallery, game_name);
1241
  free(game_name);
1242
 
1243
  /* Destroy any icons */
1244
  for (item = SaveStateGallery.Menu.items; item; item = item->next)
1245
    if (item->param != NULL && item->param != psp_blank_ss_icon)
1246
      pspImageDestroy((PspImage*)item->param);
1247
}
1248
 
1249
/**************************/
1250
/* psplib event callbacks */
1251
/**************************/
1252
static int OnGenericCancel(const void *uiobject, const void* param)
1253
{
1254
  psp_exit_menu = 1;
1255
  return 1;
1256
}
1257
 
1258
static void OnGenericRender(const void *uiobject, const void *item_obj)
1259
{
1260
  int height = pspFontGetLineHeight(UiMetric.Font);
1261
  int width;
1262
 
1263
  /* Draw tabs */
1264
  int i, x;
1265
  for (i = 0, x = 5; i <= TAB_MAX; i++, x += width + 10)
1266
  {
1267
    /* Determine width of text */
1268
    width = pspFontGetTextWidth(UiMetric.Font, TabLabel[i]);
1269
 
1270
    /* Draw background of active tab */
1271
    if (i == psp_tab_index)
1272
      pspVideoFillRect(x - 5, 0, x + width + 5, height + 1,
1273
        UiMetric.TabBgColor);
1274
 
1275
    /* Draw name of tab */
1276
    pspVideoPrint(UiMetric.Font, x, 0, TabLabel[i], PSP_COLOR_WHITE);
1277
  }
1278
}
1279
 
1280
static int OnGenericButtonPress(const PspUiFileBrowser *browser,
1281
  const char *path, u32 button_mask)
1282
{
1283
  /* If L or R are pressed, switch tabs */
1284
  if (button_mask & PSP_CTRL_LTRIGGER)
1285
  { if (--psp_tab_index < 0) psp_tab_index = TAB_MAX; }
1286
  else if (button_mask & PSP_CTRL_RTRIGGER)
1287
  { if (++psp_tab_index > TAB_MAX) psp_tab_index = 0; }
1288
  else if ((button_mask & (PSP_CTRL_START | PSP_CTRL_SELECT))
1289
    == (PSP_CTRL_START | PSP_CTRL_SELECT))
1290
  {
1291
    if (pl_util_save_vram_seq(psp_screenshot_path, "UI"))
1292
      pspUiAlert("Saved successfully");
1293
    else
1294
      pspUiAlert("ERROR: Not saved");
1295
    return 0;
1296
  }
1297
  else return 0;
1298
 
1299
  return 1;
1300
}
1301
 
1302
static void OnSplashRender(const void *splash, const void *null)
1303
{
1304
  int fh, i, x, y, height;
1305
  const char *lines[] =
1306
  {
1307
    PSP_APP_NAME" version "PSP_APP_VER" ("__DATE__")",
1308
    "\026http://psp.akop.org/vice",
1309
    " ",
1310
    "2009 Akop Karapetyan",
1311
    "1998-2009 VICE team",
1312
    NULL
1313
  };
1314
 
1315
  fh = pspFontGetLineHeight(UiMetric.Font);
1316
 
1317
  for (i = 0; lines[i]; i++);
1318
  height = fh * (i - 1);
1319
 
1320
  /* Render lines */
1321
  for (i = 0, y = SCR_HEIGHT / 2 - height / 2; lines[i]; i++, y += fh)
1322
  {
1323
    x = SCR_WIDTH / 2 - pspFontGetTextWidth(UiMetric.Font, lines[i]) / 2;
1324
    pspVideoPrint(UiMetric.Font, x, y, lines[i], PSP_COLOR_GRAY);
1325
  }
1326
 
1327
  /* Render PSP status */
1328
  OnGenericRender(splash, null);
1329
}
1330
 
1331
static int OnSplashButtonPress(const struct PspUiSplash *splash,
1332
                               u32 button_mask)
1333
{
1334
  return OnGenericButtonPress(NULL, NULL, button_mask);
1335
}
1336
 
1337
static const char* OnSplashGetStatusBarText(const struct PspUiSplash *splash)
1338
{
1339
  return "\026\255\020/\026\256\020 Switch tabs";
1340
}
1341
 
1342
static int OnMenuOk(const void *uimenu, const void* sel_item)
1343
{
1344
  switch (((const pl_menu_item*)sel_item)->id)
1345
  {
1346
  case SYSTEM_CART:
1347
    FileBrowser.Userdata = (void*)0; /* Cartridge */
1348
    FileBrowser.Filter = CartFilter;
1349
    pspUiOpenBrowser(&FileBrowser, (*psp_game_path) ? psp_game_path : NULL);
1350
    psp_refresh_devices();
1351
    break;
1352
  case SYSTEM_TAPE:
1353
    FileBrowser.Userdata = (void*)1; /* Tape */
1354
    FileBrowser.Filter = TapeFilter;
1355
    pspUiOpenBrowser(&FileBrowser, (*psp_game_path) ? psp_game_path : NULL);
1356
    psp_refresh_devices();
1357
    break;
1358
  case SYSTEM_DRIVE8:
1359
    FileBrowser.Userdata = (void*)GET_DRIVE(((const pl_menu_item*)sel_item)->id);
1360
    FileBrowser.Filter = DiskFilter;
1361
    pspUiOpenBrowser(&FileBrowser, (*psp_game_path) ? psp_game_path : NULL);
1362
    psp_refresh_devices();
1363
    break;
1364
  case SYSTEM_RESET:
1365
    if (pspUiConfirm("Reset the system?"))
1366
    {
1367
      psp_exit_menu = 1;
1368
      machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
1369
      return 1;
1370
    }
1371
    break;
1372
  case SYSTEM_SCRNSHOT:
1373
    /* Save screenshot */
1374
    if (!pl_util_save_image_seq(psp_screenshot_path, (GAME_LOADED)
1375
                                ? pl_file_get_filename(psp_current_game) : "BASIC",
1376
                                Screen))
1377
      pspUiAlert("ERROR: Screenshot not saved");
1378
    else
1379
      pspUiAlert("Screenshot saved successfully");
1380
    break;
1381
  }
1382
 
1383
  return 0;
1384
}
1385
 
1386
static int OnMenuButtonPress(const struct PspUiMenu *uimenu,
1387
                             pl_menu_item* sel_item,
1388
                             u32 button_mask)
1389
{
1390
  if (uimenu == &ControlUiMenu)
1391
  {
1392
    if (button_mask & PSP_CTRL_SQUARE)
1393
    {
1394
      /* Save to MS as default mapping */
1395
      if (psp_save_controls("DEFAULT", &current_map))
1396
      {
1397
        /* Modify in-memory defaults */
1398
        memcpy(&default_map, &current_map, sizeof(psp_ctrl_map_t));
1399
        pspUiAlert("Changes saved");
1400
      }
1401
      else
1402
        pspUiAlert("ERROR: Changes not saved");
1403
 
1404
      return 0;
1405
    }
1406
    else if (button_mask & PSP_CTRL_TRIANGLE)
1407
    {
1408
      pl_menu_item *item;
1409
      int i;
1410
 
1411
      /* Load default mapping */
1412
      memcpy(&current_map, &default_map, sizeof(psp_ctrl_map_t));
1413
 
1414
      /* Modify the menu */
1415
      for (item = ControlUiMenu.Menu.items, i = 0; item; item = item->next, i++)
1416
        pl_menu_select_option_by_value(item, (void*)default_map.button_map[i]);
1417
 
1418
      return 0;
1419
    }
1420
  }
1421
  else
1422
  {
1423
    int id = ((const pl_menu_item*)sel_item)->id;
1424
    if (button_mask & PSP_CTRL_TRIANGLE)
1425
    {
1426
      switch (id)
1427
      {
1428
      case SYSTEM_CART:
1429
        cartridge_detach_image();
1430
        psp_refresh_devices();
1431
        break;
1432
      case SYSTEM_TAPE:
1433
        tape_image_detach(1);
1434
        psp_refresh_devices();
1435
        break;
1436
      case SYSTEM_DRIVE8:
1437
        file_system_detach_disk(GET_DRIVE(id));
1438
        psp_refresh_devices();
1439
        break;
1440
      }
1441
    }
1442
  }
1443
 
1444
  return OnGenericButtonPress(NULL, NULL, button_mask);
1445
}
1446
 
1447
static int OnMenuItemChanged(const struct PspUiMenu *uimenu,
1448
                             pl_menu_item* item,
1449
                             const pl_menu_option* option)
1450
{
1451
  if (uimenu == &ControlUiMenu)
1452
  {
1453
    current_map.button_map[item->id] = (unsigned int)option->value;
1454
    psp_controls_changed = 1;
1455
  }
1456
  else
1457
  {
1458
    switch((int)item->id)
1459
    {
1460
    case OPTION_DISPLAY_MODE:
1461
      psp_options.display_mode = (int)option->value;
1462
      break;
1463
    case OPTION_CLOCK_FREQ:
1464
      psp_options.clock_freq = (int)option->value;
1465
      break;
1466
    case OPTION_SHOW_FPS:
1467
      psp_options.show_fps = (int)option->value;
1468
      break;
1469
    case OPTION_SHOW_OSI:
1470
      psp_options.show_osi = (int)option->value;
1471
      break;
1472
    case OPTION_TOGGLE_VK:
1473
      psp_options.toggle_vk = (int)option->value;
1474
      break;
1475
    case OPTION_CONTROL_MODE:
1476
      psp_options.control_mode = (int)option->value;
1477
      UiMetric.OkButton = (!psp_options.control_mode)
1478
                          ? PSP_CTRL_CROSS : PSP_CTRL_CIRCLE;
1479
      UiMetric.CancelButton = (!psp_options.control_mode)
1480
                              ? PSP_CTRL_CIRCLE : PSP_CTRL_CROSS;
1481
      break;
1482
    case OPTION_ANIMATE:
1483
      psp_options.animate_menu = (int)option->value;
1484
      UiMetric.Animate = psp_options.animate_menu;
1485
      break;
1486
    case OPTION_AUTOLOAD:
1487
      psp_options.autoload_slot = (int)option->value;
1488
      break;
1489 462 jack
    case OPTION_SHOW_BORDER:
1490
      psp_options.show_border = (int)option->value;
1491
      break;
1492 468 jack
    case OPTION_REFRESH_RATE:
1493
      resources_set_int("RefreshRate", (int)option->value);
1494
      break;
1495
    case OPTION_VSYNC:
1496
      psp_options.vsync = (int)option->value;
1497
      resources_set_int("VBLANKSync", (int)option->value);
1498
      break;
1499 453 jack
    case SYSTEM_SND_ENGINE:
1500
      resources_set_int("SidEngine", (int)option->value);
1501
      break;
1502 454 jack
    case SYSTEM_SOUND:
1503
      resources_set_int("Sound", (int)option->value);
1504
      break;
1505 453 jack
    case SYSTEM_TRUE_DRIVE:
1506
      resources_set_int("DriveTrueEmulation", (int)option->value);
1507
      break;
1508 464 jack
    case SYSTEM_VIDEO_STD:
1509
      resources_set_int("MachineVideoStandard", (int)option->value);
1510
      break;
1511 453 jack
    case SYSTEM_TAPE:
1512
      {
1513
        int index = pl_menu_get_option_index(item, option);
1514
        const char *name = tape_image_dev1->name; /* Filename */
1515
 
1516
        pspUiFlashMessage("Autoloading, please wait...");
1517
 
1518
        if (autostart_autodetect(name, NULL, index, AUTOSTART_MODE_RUN))
1519
        {
1520
          pspUiAlert("Error loading program");
1521
          return 0;
1522
        }
1523
      }
1524
      break;
1525
    case SYSTEM_DRIVE8:
1526
      {
1527
        int index = pl_menu_get_option_index(item, option);
1528
        const char *name = file_system_get_disk_name(GET_DRIVE((int)item->id));
1529
 
1530
        pspUiFlashMessage("Autoloading, please wait...");
1531
 
1532
        if (autostart_autodetect(name, NULL, index, AUTOSTART_MODE_RUN))
1533
        {
1534
          pspUiAlert("Error loading program");
1535
          return 0;
1536
        }
1537
      }
1538
      break;
1539
    case SYSTEM_JOYPORT:
1540
      psp_options.joyport = (int)option->value;
1541
      break;
1542
    }
1543
  }
1544
 
1545
  return 1;
1546
}
1547
 
1548
static void OnSystemRender(const void *uiobject, const void *item_obj)
1549
{
1550
  int w, h, x, y;
1551
  w = Screen->Viewport.Width >> 1;
1552
  h = Screen->Viewport.Height >> 1;
1553
  x = UiMetric.Right - w - UiMetric.ScrollbarWidth;
1554
  y = SCR_HEIGHT - h - 80;
1555
 
1556
  /* Draw a small representation of the screen */
1557
  pspVideoShadowRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_BLACK, 3);
1558
  pl_gfx_put_image(Screen, x, y, w, h);
1559
  pspVideoDrawRect(x, y, x + w - 1, y + h - 1, PSP_COLOR_GRAY);
1560
 
1561
  OnGenericRender(uiobject, item_obj);
1562
}
1563
 
1564
static int OnFileOk(const void *browser, const void *path)
1565
{
1566
  const char *game_path;
1567
  int set_as_current = 0,
1568
      slot,
1569
      drive_num = (int)((const PspUiFileBrowser*)browser)->Userdata;
1570
 
1571
  /* Detach */
1572
  switch (drive_num)
1573
  {
1574
  case 0:
1575
    cartridge_detach_image();
1576
    slot = 1;
1577
    break;
1578
  case 1:
1579
    tape_image_detach(1);
1580
    slot = 2;
1581
    break;
1582
  default:
1583
    file_system_detach_disk(drive_num);
1584
    slot = 3;
1585
    break;
1586
  }
1587
 
1588
  if (!(game_path = prepare_file(path, slot)))
1589
  {
1590
    pspUiAlert("Error loading file");
1591
    return 0;
1592
  }
1593
 
1594
  /* Attach */
1595
  if (drive_num == 0) /* Cart */
1596
  {
1597
    if (cartridge_attach_image(CARTRIDGE_CRT, game_path) < 0)
1598
    {
1599
      pspUiAlert("Error loading cartridge");
1600
      return 0;
1601
    }
1602
 
1603
    set_as_current = 1;
1604
  }
1605
  else if (drive_num == 1) /* Tape */
1606
  {
1607
    if (tape_image_attach(1, game_path) < 0)
1608
    {
1609
      pspUiAlert("Error loading tape image");
1610
      return 0;
1611
    }
1612
 
1613
    set_as_current = 1;
1614
  }
1615
  else /* Disk */
1616
  {
1617
    if (file_system_attach_disk(drive_num, game_path) < 0)
1618
    {
1619
      pspUiAlert("Error loading disk image");
1620
      return 0;
1621
    }
1622
 
1623
    /* If disk 8, set as currently loaded game */
1624
    set_as_current = (drive_num == 8);
1625
  }
1626
 
1627
  if (set_as_current)
1628
  {
1629
    /* Set as currently loaded game */
1630
    SET_AS_CURRENT_GAME(path);
1631
    pl_file_get_parent_directory(path, psp_game_path, sizeof(psp_game_path));
1632
    psp_load_controls(pl_file_get_filename(psp_current_game), &current_map);
1633
 
1634
    /* Reset selected state */
1635
    SaveStateGallery.Menu.selected = NULL;
1636
  }
1637
 
1638
  return 1;
1639
}
1640
 
1641
static int OnQuickloadOk(const void *browser, const void *path)
1642
{
1643
  if (!psp_load_game(path))
1644
  {
1645
    pspUiAlert("Error loading file");
1646
    return 0;
1647
  }
1648
 
1649
  psp_exit_menu = 1;
1650
 
1651
  SET_AS_CURRENT_GAME(path);
1652
  pl_file_get_parent_directory(path,
1653
                               psp_game_path,
1654
                               sizeof(psp_game_path));
1655
  if (!psp_load_controls((GAME_LOADED)
1656
                           ? pl_file_get_filename(psp_current_game) : "BASIC",
1657
                         &current_map));
1658
 
1659
  /* Autoload saved state */
1660
  if (psp_options.autoload_slot >= 0)
1661
  {
1662
    const char *config_name = (GAME_LOADED)
1663
                              ? pl_file_get_filename(psp_current_game) : "BASIC";
1664
    pl_file_path state_file;
1665
    snprintf(state_file, sizeof(state_file) - 1,
1666
             "%s%s_%02i.sna", psp_save_state_path, config_name,
1667
             psp_options.autoload_slot);
1668
 
1669
    /* Attempt loading saved state (don't care if fails) */
1670
    psp_load_state(state_file);
1671
  }
1672
 
1673
  /* Reset selected state */
1674
  SaveStateGallery.Menu.selected = NULL;
1675
 
1676
  return 1;
1677
}
1678
 
1679
static int OnSaveStateOk(const void *gallery, const void *item)
1680
{
1681
  char *path;
1682
  const char *config_name = (GAME_LOADED)
1683
    ? pl_file_get_filename(psp_current_game) : "BASIC";
1684
 
1685
  path = (char*)malloc(strlen(psp_save_state_path) + strlen(config_name) + 8);
1686
  sprintf(path, "%s%s_%02i.sna", psp_save_state_path, config_name,
1687
    ((const pl_menu_item*)item)->id);
1688
 
1689
  if (pl_file_exists(path) && pspUiConfirm("Load state?"))
1690
  {
1691
    if (psp_load_state(path))
1692
    {
1693
      psp_exit_menu = 1;
1694
      pl_menu_find_item_by_id(&((PspUiGallery*)gallery)->Menu,
1695
        ((pl_menu_item*)item)->id);
1696
      free(path);
1697
 
1698
      return 1;
1699
    }
1700
 
1701
    pspUiAlert("ERROR: State failed to load\nSee documentation for possible reasons");
1702
  }
1703
 
1704
  free(path);
1705
  return 0;
1706
}
1707
 
1708
static int OnSaveStateButtonPress(const PspUiGallery *gallery,
1709
                                  pl_menu_item *sel,
1710
                                  u32 button_mask)
1711
{
1712
  if (button_mask & PSP_CTRL_SQUARE
1713
    || button_mask & PSP_CTRL_TRIANGLE
1714
    || button_mask & PSP_CTRL_START)
1715
  {
1716
    char *path;
1717
    char caption[32];
1718
    const char *config_name = (GAME_LOADED)
1719
      ? pl_file_get_filename(psp_current_game) : "BASIC";
1720
    pl_menu_item *item = pl_menu_find_item_by_id(&gallery->Menu, sel->id);
1721
 
1722
    path = (char*)malloc(strlen(psp_save_state_path) + strlen(config_name) + 8);
1723
    sprintf(path, "%s%s_%02i.sna", psp_save_state_path, config_name, item->id);
1724
 
1725
    do /* not a real loop; flow control construct */
1726
    {
1727
      if (button_mask & PSP_CTRL_SQUARE)
1728
      {
1729
        if (pl_file_exists(path) && !pspUiConfirm("Overwrite existing state?"))
1730
          break;
1731
 
1732
        pspUiFlashMessage("Saving, please wait ...");
1733
 
1734
        PspImage *icon;
1735 472 jack
        if (!(icon = psp_save_state(path)))
1736 453 jack
        {
1737
          pspUiAlert("ERROR: State not saved");
1738
          break;
1739
        }
1740
 
1741
        SceIoStat stat;
1742
 
1743
        /* Trash the old icon (if any) */
1744
        if (item->param && item->param != psp_blank_ss_icon)
1745
          pspImageDestroy((PspImage*)item->param);
1746
 
1747
        /* Update icon, help text */
1748
        item->param = icon;
1749
        pl_menu_set_item_help_text(item, PresentSlotText);
1750
 
1751
        /* Get file modification time/date */
1752
        if (sceIoGetstat(path, &stat) < 0)
1753
          sprintf(caption, "ERROR");
1754
        else
1755
          sprintf(caption, "%02i/%02i/%02i %02i:%02i",
1756
            stat.st_mtime.month,
1757
            stat.st_mtime.day,
1758
            stat.st_mtime.year - (stat.st_mtime.year / 100) * 100,
1759
            stat.st_mtime.hour,
1760
            stat.st_mtime.minute);
1761
 
1762
        pl_menu_set_item_caption(item, caption);
1763
      }
1764
      else if (button_mask & PSP_CTRL_TRIANGLE)
1765
      {
1766
        if (!pl_file_exists(path) || !pspUiConfirm("Delete state?"))
1767
          break;
1768
 
1769
        if (!pl_file_rm(path))
1770
        {
1771
          pspUiAlert("ERROR: State not deleted");
1772
          break;
1773
        }
1774
 
1775
        /* Trash the old icon (if any) */
1776
        if (item->param && item->param != psp_blank_ss_icon)
1777
          pspImageDestroy((PspImage*)item->param);
1778
 
1779
        /* Update icon, caption */
1780
        item->param = psp_blank_ss_icon;
1781
        pl_menu_set_item_help_text(item, EmptySlotText);
1782
        pl_menu_set_item_caption(item, ((int)item->id == psp_options.autoload_slot)
1783
            ? "Autoload" : "Empty");
1784
      }
1785
    } while (0);
1786
 
1787
    if (path) free(path);
1788
    return 0;
1789
  }
1790
 
1791
  return OnGenericButtonPress(NULL, NULL, button_mask);
1792
}
1793
 
1794
/* Show a CPU JAM dialog.  */
1795
ui_jam_action_t ui_jam_dialog(const char *format, ...)
1796
{
1797
  static char message[512];
1798
 
1799
  va_list ap;
1800
  va_start (ap, format);
1801
  vsnprintf(message, sizeof(message) - 1, format, ap);
1802
  va_end (ap);
1803
 
1804
  pspUiAlert(message);
1805
  machine_trigger_reset(MACHINE_RESET_MODE_HARD);
1806
 
1807
  return UI_JAM_NONE;
1808
}
1809