input: get rid of pl2 flag, use 'bind types' instead
[picodrive.git] / platform / common / emu.c
CommitLineData
ea8c405f 1// (c) Copyright 2006-2007 notaz, All rights reserved.\r
2// Free for non-commercial use.\r
3\r
4// For commercial use, separate licencing terms must be obtained.\r
5\r
6#include <stdio.h>\r
7#include <stdlib.h>\r
ea8c405f 8#ifndef NO_SYNC\r
9#include <unistd.h>\r
10#endif\r
11\r
12#include "emu.h"\r
13#include "menu.h"\r
14#include "fonts.h"\r
15#include "lprintf.h"\r
58c86d00 16#include "config.h"\r
713c9224 17#include "plat.h"\r
d34a42f9 18#include "input.h"\r
f2cf8472 19#include "posix.h"\r
ea8c405f 20\r
efcba75f 21#include <pico/pico_int.h>\r
22#include <pico/patch.h>\r
23#include <pico/cd/cue.h>\r
ea8c405f 24#include <zlib/zlib.h>\r
25\r
ea8c405f 26\r
e2de9939 27void *g_screen_ptr;\r
28\r
29#if !SCREEN_SIZE_FIXED\r
30int g_screen_width = SCREEN_WIDTH;\r
31int g_screen_height = SCREEN_HEIGHT;\r
32#endif\r
33\r
c46ffd31 34char *PicoConfigFile = "config.cfg";\r
58c86d00 35currentConfig_t currentConfig, defaultConfig;\r
ea8c405f 36int state_slot = 0;\r
37int config_slot = 0, config_slot_current = 0;\r
f2cf8472 38int pico_pen_x = 320/2, pico_pen_y = 240/2;\r
c060a9ab 39int pico_inp_mode = 0;\r
713c9224 40int engineState = PGS_Menu;\r
41\r
42/* TODO: len checking */\r
43char rom_fname_reload[512] = { 0, };\r
44char rom_fname_loaded[512] = { 0, };\r
45int rom_loaded = 0;\r
f2cf8472 46int reset_timing = 0;\r
ea8c405f 47\r
48unsigned char *movie_data = NULL;\r
49static int movie_size = 0;\r
50\r
ea8c405f 51\r
ee2a3bdf 52/* don't use tolower() for easy old glibc binary compatibility */\r
f8af9634 53static void strlwr_(char *string)\r
ea8c405f 54{\r
f8af9634 55 char *p;\r
56 for (p = string; *p; p++)\r
ee2a3bdf 57 if ('A' <= *p && *p <= 'Z')\r
58 *p += 'a' - 'A';\r
ea8c405f 59}\r
60\r
ca482e5d 61static int try_rfn_cut(char *fname)\r
ea8c405f 62{\r
63 FILE *tmp;\r
64 char *p;\r
65\r
ca482e5d 66 p = fname + strlen(fname) - 1;\r
67 for (; p > fname; p--)\r
ea8c405f 68 if (*p == '.') break;\r
69 *p = 0;\r
70\r
ca482e5d 71 if((tmp = fopen(fname, "rb"))) {\r
ea8c405f 72 fclose(tmp);\r
73 return 1;\r
74 }\r
75 return 0;\r
76}\r
77\r
78static void get_ext(char *file, char *ext)\r
79{\r
80 char *p;\r
81\r
82 p = file + strlen(file) - 4;\r
83 if (p < file) p = file;\r
84 strncpy(ext, p, 4);\r
85 ext[4] = 0;\r
86 strlwr_(ext);\r
87}\r
88\r
a47dd663 89static const char *biosfiles_us[] = { "us_scd1_9210", "us_scd2_9306", "SegaCDBIOS9303" };\r
90static const char *biosfiles_eu[] = { "eu_mcd1_9210", "eu_mcd2_9306", "eu_mcd2_9303" };\r
91static const char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" };\r
ea8c405f 92\r
a47dd663 93static int find_bios(int region, char **bios_file)\r
ea8c405f 94{\r
95 static char bios_path[1024];\r
96 int i, count;\r
a47dd663 97 const char **files;\r
ea8c405f 98 FILE *f = NULL;\r
99\r
100 if (region == 4) { // US\r
101 files = biosfiles_us;\r
102 count = sizeof(biosfiles_us) / sizeof(char *);\r
103 } else if (region == 8) { // EU\r
104 files = biosfiles_eu;\r
105 count = sizeof(biosfiles_eu) / sizeof(char *);\r
106 } else if (region == 1 || region == 2) {\r
107 files = biosfiles_jp;\r
108 count = sizeof(biosfiles_jp) / sizeof(char *);\r
109 } else {\r
110 return 0;\r
111 }\r
112\r
113 for (i = 0; i < count; i++)\r
114 {\r
f2cf8472 115 plat_get_root_dir(bios_path, sizeof(bios_path));\r
ea8c405f 116 strcat(bios_path, files[i]);\r
117 strcat(bios_path, ".bin");\r
118 f = fopen(bios_path, "rb");\r
119 if (f) break;\r
120\r
121 bios_path[strlen(bios_path) - 4] = 0;\r
122 strcat(bios_path, ".zip");\r
123 f = fopen(bios_path, "rb");\r
124 if (f) break;\r
125 }\r
126\r
127 if (f) {\r
128 lprintf("using bios: %s\n", bios_path);\r
129 fclose(f);\r
130 if (bios_file) *bios_file = bios_path;\r
131 return 1;\r
132 } else {\r
c6c6c9cd 133 sprintf(bios_path, "no %s BIOS files found, read docs",\r
ea8c405f 134 region != 4 ? (region == 8 ? "EU" : "JAP") : "USA");\r
c6c6c9cd 135 me_update_msg(bios_path);\r
ea8c405f 136 return 0;\r
137 }\r
138}\r
139\r
c6196c0f 140/* check if the name begins with BIOS name */\r
1ca2ea4f 141/*\r
c6196c0f 142static int emu_isBios(const char *name)\r
143{\r
144 int i;\r
145 for (i = 0; i < sizeof(biosfiles_us)/sizeof(biosfiles_us[0]); i++)\r
146 if (strstr(name, biosfiles_us[i]) != NULL) return 1;\r
147 for (i = 0; i < sizeof(biosfiles_eu)/sizeof(biosfiles_eu[0]); i++)\r
148 if (strstr(name, biosfiles_eu[i]) != NULL) return 1;\r
149 for (i = 0; i < sizeof(biosfiles_jp)/sizeof(biosfiles_jp[0]); i++)\r
150 if (strstr(name, biosfiles_jp[i]) != NULL) return 1;\r
151 return 0;\r
152}\r
1ca2ea4f 153*/\r
c6196c0f 154\r
1ca2ea4f 155static unsigned char id_header[0x100];\r
58c86d00 156\r
ca482e5d 157/* checks if fname points to valid MegaCD image\r
ea8c405f 158 * if so, checks for suitable BIOS */\r
a47dd663 159int emu_cd_check(int *pregion, char *fname_in)\r
ea8c405f 160{\r
161 unsigned char buf[32];\r
162 pm_file *cd_f;\r
9037e45d 163 int region = 4; // 1: Japan, 4: US, 8: Europe\r
ca482e5d 164 char ext[5], *fname = fname_in;\r
9037e45d 165 cue_track_type type = CT_UNKNOWN;\r
166 cue_data_t *cue_data = NULL;\r
b923ecbe 167\r
ca482e5d 168 get_ext(fname_in, ext);\r
9037e45d 169 if (strcasecmp(ext, ".cue") == 0) {\r
ca482e5d 170 cue_data = cue_parse(fname_in);\r
9037e45d 171 if (cue_data != NULL) {\r
172 fname = cue_data->tracks[1].fname;\r
173 type = cue_data->tracks[1].type;\r
174 }\r
f9f40f10 175 else\r
176 return -1;\r
9037e45d 177 }\r
178\r
179 cd_f = pm_open(fname);\r
180 if (cue_data != NULL)\r
181 cue_destroy(cue_data);\r
ea8c405f 182\r
f9f40f10 183 if (cd_f == NULL) return 0; // let the upper level handle this\r
ea8c405f 184\r
185 if (pm_read(buf, 32, cd_f) != 32) {\r
186 pm_close(cd_f);\r
f9f40f10 187 return -1;\r
ea8c405f 188 }\r
189\r
9037e45d 190 if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) {\r
191 if (type && type != CT_ISO)\r
192 elprintf(EL_STATUS, ".cue has wrong type: %i", type);\r
193 type = CT_ISO; // Sega CD (ISO)\r
194 }\r
195 if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) {\r
196 if (type && type != CT_BIN)\r
197 elprintf(EL_STATUS, ".cue has wrong type: %i", type);\r
198 type = CT_BIN; // Sega CD (BIN)\r
199 }\r
200\r
201 if (type == CT_UNKNOWN) {\r
ea8c405f 202 pm_close(cd_f);\r
203 return 0;\r
204 }\r
205\r
9037e45d 206 pm_seek(cd_f, (type == CT_ISO) ? 0x100 : 0x110, SEEK_SET);\r
1ca2ea4f 207 pm_read(id_header, sizeof(id_header), cd_f);\r
58c86d00 208\r
ea8c405f 209 /* it seems we have a CD image here. Try to detect region now.. */\r
9037e45d 210 pm_seek(cd_f, (type == CT_ISO) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET);\r
ea8c405f 211 pm_read(buf, 1, cd_f);\r
212 pm_close(cd_f);\r
213\r
214 if (buf[0] == 0x64) region = 8; // EU\r
215 if (buf[0] == 0xa1) region = 1; // JAP\r
216\r
217 lprintf("detected %s Sega/Mega CD image with %s region\n",\r
9037e45d 218 type == CT_BIN ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA");\r
ea8c405f 219\r
220 if (pregion != NULL) *pregion = region;\r
221\r
222 return type;\r
223}\r
224\r
7a87643e 225static int extract_text(char *dest, const unsigned char *src, int len, int swab)\r
58c86d00 226{\r
227 char *p = dest;\r
228 int i;\r
229\r
230 if (swab) swab = 1;\r
231\r
232 for (i = len - 1; i >= 0; i--)\r
233 {\r
234 if (src[i^swab] != ' ') break;\r
235 }\r
236 len = i + 1;\r
237\r
238 for (i = 0; i < len; i++)\r
239 {\r
240 unsigned char s = src[i^swab];\r
241 if (s >= 0x20 && s < 0x7f && s != '#' && s != '|' &&\r
242 s != '[' && s != ']' && s != '\\')\r
243 {\r
244 *p++ = s;\r
245 }\r
246 else\r
247 {\r
248 sprintf(p, "\\%02x", s);\r
249 p += 3;\r
250 }\r
251 }\r
252\r
253 return p - dest;\r
254}\r
255\r
a47dd663 256static char *emu_make_rom_id(void)\r
58c86d00 257{\r
ca482e5d 258 static char id_string[3+0xe*3+0x3*3+0x30*3+3];\r
bdec53c9 259 int pos, swab = 1;\r
58c86d00 260\r
602133e1 261 if (PicoAHW & PAHW_MCD) {\r
bdec53c9 262 strcpy(id_string, "CD|");\r
263 swab = 0;\r
264 }\r
1ca2ea4f 265 else strcpy(id_string, "MD|");\r
58c86d00 266 pos = 3;\r
267\r
bdec53c9 268 pos += extract_text(id_string + pos, id_header + 0x80, 0x0e, swab); // serial\r
58c86d00 269 id_string[pos] = '|'; pos++;\r
bdec53c9 270 pos += extract_text(id_string + pos, id_header + 0xf0, 0x03, swab); // region\r
58c86d00 271 id_string[pos] = '|'; pos++;\r
bdec53c9 272 pos += extract_text(id_string + pos, id_header + 0x50, 0x30, swab); // overseas name\r
58c86d00 273 id_string[pos] = 0;\r
274\r
58c86d00 275 return id_string;\r
276}\r
277\r
ca482e5d 278// buffer must be at least 150 byte long\r
a47dd663 279void emu_get_game_name(char *str150)\r
ca482e5d 280{\r
281 int ret, swab = (PicoAHW & PAHW_MCD) ? 0 : 1;\r
282 char *s, *d;\r
283\r
284 ret = extract_text(str150, id_header + 0x50, 0x30, swab); // overseas name\r
285\r
286 for (s = d = str150 + 1; s < str150+ret; s++)\r
287 {\r
288 if (*s == 0) break;\r
289 if (*s != ' ' || d[-1] != ' ')\r
290 *d++ = *s;\r
291 }\r
292 *d = 0;\r
293}\r
294\r
a47dd663 295static void shutdown_MCD(void)\r
296{\r
297 if ((PicoAHW & PAHW_MCD) && Pico_mcd != NULL)\r
298 Stop_CD();\r
299 PicoAHW &= ~PAHW_MCD;\r
300}\r
301\r
ca482e5d 302// note: this function might mangle rom_fname\r
a47dd663 303int emu_reload_rom(char *rom_fname)\r
ea8c405f 304{\r
305 unsigned int rom_size = 0;\r
ca482e5d 306 char *used_rom_name = rom_fname;\r
eacee137 307 unsigned char *rom_data = NULL;\r
ea8c405f 308 char ext[5];\r
f9f40f10 309 pm_file *rom = NULL;\r
ea8c405f 310 int ret, cd_state, cd_region, cfg_loaded = 0;\r
311\r
ca482e5d 312 lprintf("emu_ReloadRom(%s)\n", rom_fname);\r
ea8c405f 313\r
ca482e5d 314 get_ext(rom_fname, ext);\r
ea8c405f 315\r
316 // detect wrong extensions\r
eacee137 317 if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz\r
c6c6c9cd 318 me_update_msg("Not a ROM/CD selected.");\r
ea8c405f 319 return 0;\r
320 }\r
321\r
322 PicoPatchUnload();\r
323\r
324 // check for movie file\r
eacee137 325 if (movie_data) {\r
ea8c405f 326 free(movie_data);\r
327 movie_data = 0;\r
328 }\r
2d2247c2 329 if (!strcmp(ext, ".gmv"))\r
330 {\r
ea8c405f 331 // check for both gmv and rom\r
332 int dummy;\r
ca482e5d 333 FILE *movie_file = fopen(rom_fname, "rb");\r
ea8c405f 334 if(!movie_file) {\r
c6c6c9cd 335 me_update_msg("Failed to open movie.");\r
ea8c405f 336 return 0;\r
337 }\r
338 fseek(movie_file, 0, SEEK_END);\r
339 movie_size = ftell(movie_file);\r
340 fseek(movie_file, 0, SEEK_SET);\r
341 if(movie_size < 64+3) {\r
c6c6c9cd 342 me_update_msg("Invalid GMV file.");\r
ea8c405f 343 fclose(movie_file);\r
344 return 0;\r
345 }\r
346 movie_data = malloc(movie_size);\r
347 if(movie_data == NULL) {\r
c6c6c9cd 348 me_update_msg("low memory.");\r
ea8c405f 349 fclose(movie_file);\r
350 return 0;\r
351 }\r
352 fread(movie_data, 1, movie_size, movie_file);\r
353 fclose(movie_file);\r
354 if (strncmp((char *)movie_data, "Gens Movie TEST", 15) != 0) {\r
c6c6c9cd 355 me_update_msg("Invalid GMV file.");\r
ea8c405f 356 return 0;\r
357 }\r
ca482e5d 358 dummy = try_rfn_cut(rom_fname) || try_rfn_cut(rom_fname);\r
ea8c405f 359 if (!dummy) {\r
c6c6c9cd 360 me_update_msg("Could't find a ROM for movie.");\r
ea8c405f 361 return 0;\r
362 }\r
ca482e5d 363 get_ext(rom_fname, ext);\r
f8af9634 364 lprintf("gmv loaded for %s\n", rom_fname);\r
ea8c405f 365 }\r
ca482e5d 366 else if (!strcmp(ext, ".pat"))\r
367 {\r
ea8c405f 368 int dummy;\r
ca482e5d 369 PicoPatchLoad(rom_fname);\r
370 dummy = try_rfn_cut(rom_fname) || try_rfn_cut(rom_fname);\r
ea8c405f 371 if (!dummy) {\r
c6c6c9cd 372 me_update_msg("Could't find a ROM to patch.");\r
ea8c405f 373 return 0;\r
374 }\r
ca482e5d 375 get_ext(rom_fname, ext);\r
ea8c405f 376 }\r
377\r
a47dd663 378 shutdown_MCD();\r
ea8c405f 379\r
380 // check for MegaCD image\r
a47dd663 381 cd_state = emu_cd_check(&cd_region, rom_fname);\r
f9f40f10 382 if (cd_state >= 0 && cd_state != CIT_NOT_CD)\r
ea8c405f 383 {\r
602133e1 384 PicoAHW |= PAHW_MCD;\r
ea8c405f 385 // valid CD image, check for BIOS..\r
386\r
387 // we need to have config loaded at this point\r
a47dd663 388 ret = emu_read_config(1, 1);\r
389 if (!ret) emu_read_config(0, 1);\r
ea8c405f 390 cfg_loaded = 1;\r
391\r
392 if (PicoRegionOverride) {\r
393 cd_region = PicoRegionOverride;\r
394 lprintf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA");\r
395 }\r
a47dd663 396 if (!find_bios(cd_region, &used_rom_name)) {\r
602133e1 397 PicoAHW &= ~PAHW_MCD;\r
ea8c405f 398 return 0;\r
399 }\r
400\r
ea8c405f 401 get_ext(used_rom_name, ext);\r
402 }\r
403 else\r
404 {\r
602133e1 405 if (PicoAHW & PAHW_MCD) Stop_CD();\r
406 PicoAHW &= ~PAHW_MCD;\r
ea8c405f 407 }\r
408\r
409 rom = pm_open(used_rom_name);\r
eacee137 410 if (!rom) {\r
c6c6c9cd 411 me_update_msg("Failed to open ROM/CD image");\r
f9f40f10 412 goto fail;\r
413 }\r
414\r
415 if (cd_state < 0) {\r
c6c6c9cd 416 me_update_msg("Invalid CD image");\r
f9f40f10 417 goto fail;\r
ea8c405f 418 }\r
419\r
4b167c12 420 menu_romload_prepare(used_rom_name); // also CD load\r
ea8c405f 421\r
eacee137 422 PicoCartUnload();\r
423 rom_loaded = 0;\r
ea8c405f 424\r
eacee137 425 if ( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) {\r
c6c6c9cd 426 if (ret == 2) me_update_msg("Out of memory");\r
427 else if (ret == 3) me_update_msg("Read failed");\r
428 else me_update_msg("PicoCartLoad() failed.");\r
f9f40f10 429 goto fail2;\r
ea8c405f 430 }\r
431 pm_close(rom);\r
f9f40f10 432 rom = NULL;\r
ea8c405f 433\r
434 // detect wrong files (Pico crashes on very small files), also see if ROM EP is good\r
eacee137 435 if (rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 ||\r
ea8c405f 436 ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) {\r
437 if (rom_data) free(rom_data);\r
c6c6c9cd 438 me_update_msg("Not a ROM selected.");\r
f9f40f10 439 goto fail2;\r
ea8c405f 440 }\r
441\r
442 // load config for this ROM (do this before insert to get correct region)\r
602133e1 443 if (!(PicoAHW & PAHW_MCD))\r
1ca2ea4f 444 memcpy(id_header, rom_data + 0x100, sizeof(id_header));\r
ea8c405f 445 if (!cfg_loaded) {\r
a47dd663 446 ret = emu_read_config(1, 1);\r
447 if (!ret) emu_read_config(0, 1);\r
ea8c405f 448 }\r
449\r
450 lprintf("PicoCartInsert(%p, %d);\n", rom_data, rom_size);\r
eacee137 451 if (PicoCartInsert(rom_data, rom_size)) {\r
c6c6c9cd 452 me_update_msg("Failed to load ROM.");\r
f9f40f10 453 goto fail2;\r
ea8c405f 454 }\r
455\r
ea8c405f 456 // insert CD if it was detected\r
b923ecbe 457 if (cd_state != CIT_NOT_CD) {\r
ca482e5d 458 ret = Insert_CD(rom_fname, cd_state);\r
ea8c405f 459 if (ret != 0) {\r
c6c6c9cd 460 me_update_msg("Insert_CD() failed, invalid CD image?");\r
f9f40f10 461 goto fail2;\r
ea8c405f 462 }\r
463 }\r
464\r
4b167c12 465 menu_romload_end();\r
466\r
ea8c405f 467 if (PicoPatches) {\r
468 PicoPatchPrepare();\r
469 PicoPatchApply();\r
470 }\r
471\r
472 // additional movie stuff\r
f9f40f10 473 if (movie_data)\r
474 {\r
475 if (movie_data[0x14] == '6')\r
602133e1 476 PicoOpt |= POPT_6BTN_PAD; // 6 button pad\r
477 else PicoOpt &= ~POPT_6BTN_PAD;\r
2aa27095 478 PicoOpt |= POPT_DIS_VDP_FIFO; // no VDP fifo timing\r
f9f40f10 479 if (movie_data[0xF] >= 'A') {\r
480 if (movie_data[0x16] & 0x80) {\r
ea8c405f 481 PicoRegionOverride = 8;\r
482 } else {\r
483 PicoRegionOverride = 4;\r
484 }\r
1cb1584b 485 PicoReset();\r
ea8c405f 486 // TODO: bits 6 & 5\r
487 }\r
488 movie_data[0x18+30] = 0;\r
d34a42f9 489 plat_status_msg("MOVIE: %s", (char *) &movie_data[0x18]);\r
ea8c405f 490 }\r
491 else\r
492 {\r
602133e1 493 PicoOpt &= ~POPT_DIS_VDP_FIFO;\r
d34a42f9 494 plat_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS");\r
ea8c405f 495 }\r
ea8c405f 496\r
497 // load SRAM for this ROM\r
a47dd663 498 if (currentConfig.EmuOpt & EOPT_EN_SRAM)\r
499 emu_save_load_game(1, 1);\r
ea8c405f 500\r
713c9224 501 strncpy(rom_fname_loaded, rom_fname, sizeof(rom_fname_loaded)-1);\r
502 rom_fname_loaded[sizeof(rom_fname_loaded)-1] = 0;\r
eacee137 503 rom_loaded = 1;\r
ea8c405f 504 return 1;\r
f9f40f10 505\r
506fail2:\r
507 menu_romload_end();\r
508fail:\r
509 if (rom != NULL) pm_close(rom);\r
510 return 0;\r
ea8c405f 511}\r
512\r
ea8c405f 513static void romfname_ext(char *dst, const char *prefix, const char *ext)\r
514{\r
515 char *p;\r
516 int prefix_len = 0;\r
517\r
518 // make save filename\r
713c9224 519 p = rom_fname_loaded + strlen(rom_fname_loaded) - 1;\r
520 for (; p >= rom_fname_loaded && *p != PATH_SEP_C; p--); p++;\r
ea8c405f 521 *dst = 0;\r
522 if (prefix) {\r
f2cf8472 523 int len = plat_get_root_dir(dst, 512);\r
ca482e5d 524 strcpy(dst + len, prefix);\r
525 prefix_len = len + strlen(prefix);\r
ea8c405f 526 }\r
ca482e5d 527#ifdef UIQ3\r
713c9224 528 else p = rom_fname_loaded; // backward compatibility\r
ca482e5d 529#endif\r
ea8c405f 530 strncpy(dst + prefix_len, p, 511-prefix_len);\r
531 dst[511-8] = 0;\r
532 if (dst[strlen(dst)-4] == '.') dst[strlen(dst)-4] = 0;\r
533 if (ext) strcat(dst, ext);\r
534}\r
535\r
08fe8094 536static void make_config_cfg(char *cfg)\r
537{\r
ca482e5d 538 int len;\r
f2cf8472 539 len = plat_get_root_dir(cfg, 512);\r
ca482e5d 540 strncpy(cfg + len, PicoConfigFile, 512-6-1-len);\r
08fe8094 541 if (config_slot != 0)\r
542 {\r
543 char *p = strrchr(cfg, '.');\r
544 if (p == NULL) p = cfg + strlen(cfg);\r
545 sprintf(p, ".%i.cfg", config_slot);\r
546 }\r
547 cfg[511] = 0;\r
548}\r
549\r
a47dd663 550static void emu_setDefaultConfig(void)\r
ca482e5d 551{\r
a47dd663 552 memcpy(&currentConfig, &defaultConfig, sizeof(currentConfig));\r
ca482e5d 553 PicoOpt = currentConfig.s_PicoOpt;\r
554 PsndRate = currentConfig.s_PsndRate;\r
555 PicoRegionOverride = currentConfig.s_PicoRegion;\r
556 PicoAutoRgnOrder = currentConfig.s_PicoAutoRgnOrder;\r
557 PicoCDBuffers = currentConfig.s_PicoCDBuffers;\r
558}\r
559\r
a47dd663 560int emu_read_config(int game, int no_defaults)\r
ea8c405f 561{\r
58c86d00 562 char cfg[512];\r
58c86d00 563 int ret;\r
ea8c405f 564\r
565 if (!game)\r
566 {\r
567 if (!no_defaults)\r
ea8c405f 568 emu_setDefaultConfig();\r
08fe8094 569 make_config_cfg(cfg);\r
58c86d00 570 ret = config_readsect(cfg, NULL);\r
ea8c405f 571 }\r
58c86d00 572 else\r
573 {\r
a47dd663 574 char *sect = emu_make_rom_id();\r
ea8c405f 575\r
58c86d00 576 // try new .cfg way\r
577 if (config_slot != 0)\r
578 sprintf(cfg, "game.%i.cfg", config_slot);\r
579 else strcpy(cfg, "game.cfg");\r
1ca2ea4f 580\r
581 ret = -1;\r
08fe8094 582 if (config_havesect(cfg, sect))\r
583 {\r
584 // read user's config\r
7b802576 585 int vol = currentConfig.volume;\r
1ca2ea4f 586 emu_setDefaultConfig();\r
587 ret = config_readsect(cfg, sect);\r
7b802576 588 currentConfig.volume = vol; // make vol global (bah)\r
1ca2ea4f 589 }\r
a39b7867 590 else\r
08fe8094 591 {\r
592 // read global config, and apply game_def.cfg on top\r
593 make_config_cfg(cfg);\r
594 config_readsect(cfg, NULL);\r
595 ret = config_readsect("game_def.cfg", sect);\r
596 }\r
58c86d00 597\r
ca482e5d 598 if (ret == 0)\r
58c86d00 599 {\r
1ca2ea4f 600 lprintf("loaded cfg from sect \"%s\"\n", sect);\r
58c86d00 601 }\r
ea8c405f 602 }\r
58c86d00 603\r
ee2a3bdf 604 plat_validate_config();\r
605\r
ea8c405f 606 // some sanity checks\r
2445b7cb 607#ifdef PSP\r
ee2a3bdf 608 /* TODO: mv to plat_validate_config() */\r
609 if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200;\r
2445b7cb 610 if (currentConfig.gamma < -4 || currentConfig.gamma > 16) currentConfig.gamma = 0;\r
6fc57144 611 if (currentConfig.gamma2 < 0 || currentConfig.gamma2 > 2) currentConfig.gamma2 = 0;\r
2445b7cb 612#endif\r
ee2a3bdf 613 if (currentConfig.volume < 0 || currentConfig.volume > 99)\r
614 currentConfig.volume = 50;\r
615\r
616 if (ret == 0)\r
617 config_slot_current = config_slot;\r
991473ad 618\r
58c86d00 619 return (ret == 0);\r
ea8c405f 620}\r
621\r
622\r
a47dd663 623int emu_write_config(int is_game)\r
ea8c405f 624{\r
58c86d00 625 char cfg[512], *game_sect = NULL;\r
626 int ret, write_lrom = 0;\r
ea8c405f 627\r
58c86d00 628 if (!is_game)\r
ea8c405f 629 {\r
ca482e5d 630 make_config_cfg(cfg);\r
58c86d00 631 write_lrom = 1;\r
ea8c405f 632 } else {\r
633 if (config_slot != 0)\r
58c86d00 634 sprintf(cfg, "game.%i.cfg", config_slot);\r
635 else strcpy(cfg, "game.cfg");\r
a47dd663 636 game_sect = emu_make_rom_id();\r
637 lprintf("emu_write_config: sect \"%s\"\n", game_sect);\r
ea8c405f 638 }\r
639\r
a47dd663 640 lprintf("emu_write_config: %s ", cfg);\r
58c86d00 641 ret = config_writesect(cfg, game_sect);\r
1ca2ea4f 642 if (write_lrom) config_writelrom(cfg);\r
ea8c405f 643#ifndef NO_SYNC\r
58c86d00 644 sync();\r
ea8c405f 645#endif\r
58c86d00 646 lprintf((ret == 0) ? "(ok)\n" : "(failed)\n");\r
ea8c405f 647\r
58c86d00 648 if (ret == 0) config_slot_current = config_slot;\r
649 return ret == 0;\r
ea8c405f 650}\r
651\r
652\r
d7dd4d66 653void emu_writelrom(void)\r
654{\r
655 char cfg[512];\r
656 make_config_cfg(cfg);\r
657 config_writelrom(cfg);\r
658#ifndef NO_SYNC\r
659 sync();\r
660#endif\r
661}\r
662\r
e2de9939 663/* always using built-in font */\r
664\r
665#define mk_text_out(name, type, val) \\r
666void name(int x, int y, const char *text) \\r
667{ \\r
668 int i, l, len = strlen(text); \\r
669 type *screen = (type *)g_screen_ptr + x + y * g_screen_width; \\r
670 \\r
671 for (i = 0; i < len; i++, screen += 8) \\r
672 { \\r
673 for (l = 0; l < 8; l++) \\r
674 { \\r
675 unsigned char fd = fontdata8x8[text[i] * 8 + l];\\r
676 type *s = screen + l * g_screen_width; \\r
677 if (fd&0x80) s[0] = val; \\r
678 if (fd&0x40) s[1] = val; \\r
679 if (fd&0x20) s[2] = val; \\r
680 if (fd&0x10) s[3] = val; \\r
681 if (fd&0x08) s[4] = val; \\r
682 if (fd&0x04) s[5] = val; \\r
683 if (fd&0x02) s[6] = val; \\r
684 if (fd&0x01) s[7] = val; \\r
685 } \\r
686 } \\r
ea8c405f 687}\r
688\r
e2de9939 689mk_text_out(emu_textOut8, unsigned char, 0xf0)\r
690mk_text_out(emu_textOut16, unsigned short, 0xffff)\r
ea8c405f 691\r
e2de9939 692#undef mk_text_out\r
ea8c405f 693\r
694\r
d34a42f9 695void update_movie(void)\r
ea8c405f 696{\r
697 int offs = Pico.m.frame_count*3 + 0x40;\r
698 if (offs+3 > movie_size) {\r
699 free(movie_data);\r
700 movie_data = 0;\r
d34a42f9 701 plat_status_msg("END OF MOVIE.");\r
ea8c405f 702 lprintf("END OF MOVIE.\n");\r
ea8c405f 703 } else {\r
704 // MXYZ SACB RLDU\r
705 PicoPad[0] = ~movie_data[offs] & 0x8f; // ! SCBA RLDU\r
f8af9634 706 if(!(movie_data[offs] & 0x10)) PicoPad[0] |= 0x40; // C\r
707 if(!(movie_data[offs] & 0x20)) PicoPad[0] |= 0x10; // A\r
708 if(!(movie_data[offs] & 0x40)) PicoPad[0] |= 0x20; // B\r
ea8c405f 709 PicoPad[1] = ~movie_data[offs+1] & 0x8f; // ! SCBA RLDU\r
f8af9634 710 if(!(movie_data[offs+1] & 0x10)) PicoPad[1] |= 0x40; // C\r
711 if(!(movie_data[offs+1] & 0x20)) PicoPad[1] |= 0x10; // A\r
712 if(!(movie_data[offs+1] & 0x40)) PicoPad[1] |= 0x20; // B\r
ea8c405f 713 PicoPad[0] |= (~movie_data[offs+2] & 0x0A) << 8; // ! MZYX\r
714 if(!(movie_data[offs+2] & 0x01)) PicoPad[0] |= 0x0400; // X\r
715 if(!(movie_data[offs+2] & 0x04)) PicoPad[0] |= 0x0100; // Z\r
716 PicoPad[1] |= (~movie_data[offs+2] & 0xA0) << 4; // ! MZYX\r
717 if(!(movie_data[offs+2] & 0x10)) PicoPad[1] |= 0x0400; // X\r
718 if(!(movie_data[offs+2] & 0x40)) PicoPad[1] |= 0x0100; // Z\r
719 }\r
720}\r
721\r
722\r
723static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)\r
724{\r
725 return gzread(file, p, _n);\r
726}\r
727\r
728\r
729static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)\r
730{\r
731 return gzwrite(file, p, _n);\r
732}\r
733\r
734static int try_ropen_file(const char *fname)\r
735{\r
736 FILE *f;\r
737\r
738 f = fopen(fname, "rb");\r
739 if (f) {\r
740 fclose(f);\r
741 return 1;\r
742 }\r
743 return 0;\r
744}\r
745\r
a47dd663 746char *emu_get_save_fname(int load, int is_sram, int slot)\r
ea8c405f 747{\r
748 static char saveFname[512];\r
749 char ext[16];\r
750\r
751 if (is_sram)\r
752 {\r
ca482e5d 753 romfname_ext(saveFname, (PicoAHW&1) ? "brm"PATH_SEP : "srm"PATH_SEP, (PicoAHW&1) ? ".brm" : ".srm");\r
ea8c405f 754 if (load) {\r
755 if (try_ropen_file(saveFname)) return saveFname;\r
756 // try in current dir..\r
602133e1 757 romfname_ext(saveFname, NULL, (PicoAHW & PAHW_MCD) ? ".brm" : ".srm");\r
ea8c405f 758 if (try_ropen_file(saveFname)) return saveFname;\r
759 return NULL; // give up\r
760 }\r
761 }\r
762 else\r
763 {\r
764 ext[0] = 0;\r
765 if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot);\r
ca482e5d 766 strcat(ext, (currentConfig.EmuOpt & EOPT_GZIP_SAVES) ? ".mds.gz" : ".mds");\r
ea8c405f 767\r
ca482e5d 768 romfname_ext(saveFname, "mds" PATH_SEP, ext);\r
ea8c405f 769 if (load) {\r
770 if (try_ropen_file(saveFname)) return saveFname;\r
771 romfname_ext(saveFname, NULL, ext);\r
772 if (try_ropen_file(saveFname)) return saveFname;\r
ca482e5d 773 // no gzipped states, search for non-gzipped\r
774 if (currentConfig.EmuOpt & EOPT_GZIP_SAVES)\r
775 {\r
ea8c405f 776 ext[0] = 0;\r
777 if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot);\r
778 strcat(ext, ".mds");\r
779\r
ca482e5d 780 romfname_ext(saveFname, "mds"PATH_SEP, ext);\r
ea8c405f 781 if (try_ropen_file(saveFname)) return saveFname;\r
782 romfname_ext(saveFname, NULL, ext);\r
783 if (try_ropen_file(saveFname)) return saveFname;\r
784 }\r
785 return NULL;\r
786 }\r
787 }\r
788\r
789 return saveFname;\r
790}\r
791\r
a47dd663 792int emu_check_save_file(int slot)\r
ea8c405f 793{\r
a47dd663 794 return emu_get_save_fname(1, 0, slot) ? 1 : 0;\r
ea8c405f 795}\r
796\r
797void emu_setSaveStateCbs(int gz)\r
798{\r
799 if (gz) {\r
800 areaRead = gzRead2;\r
801 areaWrite = gzWrite2;\r
802 areaEof = (areaeof *) gzeof;\r
803 areaSeek = (areaseek *) gzseek;\r
804 areaClose = (areaclose *) gzclose;\r
805 } else {\r
806 areaRead = (arearw *) fread;\r
807 areaWrite = (arearw *) fwrite;\r
808 areaEof = (areaeof *) feof;\r
809 areaSeek = (areaseek *) fseek;\r
810 areaClose = (areaclose *) fclose;\r
811 }\r
812}\r
813\r
a47dd663 814int emu_save_load_game(int load, int sram)\r
ea8c405f 815{\r
816 int ret = 0;\r
817 char *saveFname;\r
818\r
819 // make save filename\r
a47dd663 820 saveFname = emu_get_save_fname(load, sram, state_slot);\r
ea8c405f 821 if (saveFname == NULL) {\r
d34a42f9 822 if (!sram)\r
823 plat_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED");\r
ea8c405f 824 return -1;\r
825 }\r
826\r
827 lprintf("saveLoad (%i, %i): %s\n", load, sram, saveFname);\r
828\r
da42200b 829 if (sram)\r
830 {\r
ea8c405f 831 FILE *sramFile;\r
832 int sram_size;\r
833 unsigned char *sram_data;\r
834 int truncate = 1;\r
602133e1 835 if (PicoAHW & PAHW_MCD)\r
836 {\r
837 if (PicoOpt&POPT_EN_MCD_RAMCART) {\r
ea8c405f 838 sram_size = 0x12000;\r
839 sram_data = SRam.data;\r
840 if (sram_data)\r
841 memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4);\r
842 } else {\r
843 sram_size = 0x2000;\r
844 sram_data = Pico_mcd->bram;\r
845 truncate = 0; // the .brm may contain RAM cart data after normal brm\r
846 }\r
847 } else {\r
848 sram_size = SRam.end-SRam.start+1;\r
849 if(Pico.m.sram_reg & 4) sram_size=0x2000;\r
850 sram_data = SRam.data;\r
851 }\r
852 if (!sram_data) return 0; // SRam forcefully disabled for this game\r
853\r
602133e1 854 if (load)\r
855 {\r
ea8c405f 856 sramFile = fopen(saveFname, "rb");\r
857 if(!sramFile) return -1;\r
858 fread(sram_data, 1, sram_size, sramFile);\r
859 fclose(sramFile);\r
602133e1 860 if ((PicoAHW & PAHW_MCD) && (PicoOpt&POPT_EN_MCD_RAMCART))\r
ea8c405f 861 memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4);\r
862 } else {\r
863 // sram save needs some special processing\r
864 // see if we have anything to save\r
865 for (; sram_size > 0; sram_size--)\r
866 if (sram_data[sram_size-1]) break;\r
867\r
868 if (sram_size) {\r
869 sramFile = fopen(saveFname, truncate ? "wb" : "r+b");\r
870 if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry\r
871 if (!sramFile) return -1;\r
872 ret = fwrite(sram_data, 1, sram_size, sramFile);\r
873 ret = (ret != sram_size) ? -1 : 0;\r
874 fclose(sramFile);\r
875#ifndef NO_SYNC\r
876 sync();\r
877#endif\r
878 }\r
879 }\r
880 return ret;\r
881 }\r
882 else\r
883 {\r
884 void *PmovFile = NULL;\r
da42200b 885 if (strcmp(saveFname + strlen(saveFname) - 3, ".gz") == 0)\r
886 {\r
ea8c405f 887 if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) {\r
888 emu_setSaveStateCbs(1);\r
da42200b 889 if (!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY);\r
ea8c405f 890 }\r
891 }\r
892 else\r
893 {\r
894 if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) {\r
895 emu_setSaveStateCbs(0);\r
896 }\r
897 }\r
898 if(PmovFile) {\r
899 ret = PmovState(load ? 6 : 5, PmovFile);\r
900 areaClose(PmovFile);\r
901 PmovFile = 0;\r
902 if (load) Pico.m.dirtyPal=1;\r
903#ifndef NO_SYNC\r
904 else sync();\r
905#endif\r
906 }\r
907 else ret = -1;\r
908 if (!ret)\r
d34a42f9 909 plat_status_msg(load ? "GAME LOADED" : "GAME SAVED");\r
ea8c405f 910 else\r
911 {\r
d34a42f9 912 plat_status_msg(load ? "LOAD FAILED" : "SAVE FAILED");\r
ea8c405f 913 ret = -1;\r
914 }\r
915\r
ea8c405f 916 return ret;\r
917 }\r
918}\r
bdec53c9 919\r
a47dd663 920void emu_set_fastforward(int set_on)\r
c060a9ab 921{\r
922 static void *set_PsndOut = NULL;\r
923 static int set_Frameskip, set_EmuOpt, is_on = 0;\r
924\r
925 if (set_on && !is_on) {\r
926 set_PsndOut = PsndOut;\r
927 set_Frameskip = currentConfig.Frameskip;\r
928 set_EmuOpt = currentConfig.EmuOpt;\r
929 PsndOut = NULL;\r
930 currentConfig.Frameskip = 8;\r
931 currentConfig.EmuOpt &= ~4;\r
932 currentConfig.EmuOpt |= 0x40000;\r
933 is_on = 1;\r
d34a42f9 934 plat_status_msg("FAST FORWARD");\r
c060a9ab 935 }\r
936 else if (!set_on && is_on) {\r
937 PsndOut = set_PsndOut;\r
938 currentConfig.Frameskip = set_Frameskip;\r
939 currentConfig.EmuOpt = set_EmuOpt;\r
940 PsndRerate(1);\r
941 is_on = 0;\r
942 }\r
943}\r
944\r
f2cf8472 945static void emu_msg_tray_open(void)\r
c060a9ab 946{\r
f2cf8472 947 plat_status_msg("CD tray opened");\r
948}\r
949\r
950void emu_reset_game(void)\r
951{\r
952 PicoReset();\r
953 reset_timing = 1;\r
954}\r
955\r
956void run_events_pico(unsigned int events)\r
957{\r
958 int lim_x;\r
959\r
960 if (events & PEV_PICO_SWINP) {\r
c060a9ab 961 pico_inp_mode++;\r
d34a42f9 962 if (pico_inp_mode > 2)\r
963 pico_inp_mode = 0;\r
c060a9ab 964 switch (pico_inp_mode) {\r
d34a42f9 965 case 2: plat_status_msg("Input: Pen on Pad"); break;\r
966 case 1: plat_status_msg("Input: Pen on Storyware"); break;\r
967 case 0: plat_status_msg("Input: Joystick");\r
c060a9ab 968 PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000;\r
969 break;\r
970 }\r
c060a9ab 971 }\r
f2cf8472 972 if (events & PEV_PICO_PPREV) {\r
c060a9ab 973 PicoPicohw.page--;\r
d34a42f9 974 if (PicoPicohw.page < 0)\r
975 PicoPicohw.page = 0;\r
976 plat_status_msg("Page %i", PicoPicohw.page);\r
c060a9ab 977 }\r
f2cf8472 978 if (events & PEV_PICO_PNEXT) {\r
c060a9ab 979 PicoPicohw.page++;\r
d34a42f9 980 if (PicoPicohw.page > 6)\r
981 PicoPicohw.page = 6;\r
982 plat_status_msg("Page %i", PicoPicohw.page);\r
c060a9ab 983 }\r
f2cf8472 984\r
985 if (pico_inp_mode == 0)\r
986 return;\r
987\r
988 /* handle other input modes */\r
989 if (PicoPad[0] & 1) pico_pen_y--;\r
990 if (PicoPad[0] & 2) pico_pen_y++;\r
991 if (PicoPad[0] & 4) pico_pen_x--;\r
992 if (PicoPad[0] & 8) pico_pen_x++;\r
993 PicoPad[0] &= ~0x0f; // release UDLR\r
994\r
995 lim_x = (Pico.video.reg[12]&1) ? 319 : 255;\r
996 if (pico_pen_y < 8)\r
997 pico_pen_y = 8;\r
998 if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y)\r
999 pico_pen_y = 224 - PICO_PEN_ADJUST_Y;\r
1000 if (pico_pen_x < 0)\r
1001 pico_pen_x = 0;\r
1002 if (pico_pen_x > lim_x - PICO_PEN_ADJUST_X)\r
1003 pico_pen_x = lim_x - PICO_PEN_ADJUST_X;\r
1004\r
1005 PicoPicohw.pen_pos[0] = pico_pen_x;\r
1006 if (!(Pico.video.reg[12] & 1))\r
1007 PicoPicohw.pen_pos[0] += pico_pen_x / 4;\r
1008 PicoPicohw.pen_pos[0] += 0x3c;\r
1009 PicoPicohw.pen_pos[1] = pico_inp_mode == 1 ? (0x2f8 + pico_pen_y) : (0x1fc + pico_pen_y);\r
c060a9ab 1010}\r
1011\r
d34a42f9 1012static void do_turbo(int *pad, int acts)\r
f0f0d2df 1013{\r
1014 static int turbo_pad = 0;\r
1015 static unsigned char turbo_cnt[3] = { 0, 0, 0 };\r
1016 int inc = currentConfig.turbo_rate * 2;\r
1017\r
1018 if (acts & 0x1000) {\r
1019 turbo_cnt[0] += inc;\r
1020 if (turbo_cnt[0] >= 60)\r
1021 turbo_pad ^= 0x10, turbo_cnt[0] = 0;\r
1022 }\r
1023 if (acts & 0x2000) {\r
1024 turbo_cnt[1] += inc;\r
1025 if (turbo_cnt[1] >= 60)\r
1026 turbo_pad ^= 0x20, turbo_cnt[1] = 0;\r
1027 }\r
1028 if (acts & 0x4000) {\r
1029 turbo_cnt[2] += inc;\r
1030 if (turbo_cnt[2] >= 60)\r
1031 turbo_pad ^= 0x40, turbo_cnt[2] = 0;\r
1032 }\r
1033 *pad |= turbo_pad & (acts >> 8);\r
1034}\r
c060a9ab 1035\r
f2cf8472 1036static void run_events_ui(unsigned int which)\r
d34a42f9 1037{\r
1038 if (which & (PEV_STATE_LOAD|PEV_STATE_SAVE))\r
1039 {\r
1040 int do_it = 1;\r
a47dd663 1041 if ( emu_check_save_file(state_slot) &&\r
d34a42f9 1042 (((which & PEV_STATE_LOAD) && (currentConfig.EmuOpt & EOPT_CONFIRM_LOAD)) ||\r
1043 ((which & PEV_STATE_SAVE) && (currentConfig.EmuOpt & EOPT_CONFIRM_SAVE))) )\r
1044 {\r
1045 const char *nm;\r
1046 char tmp[64];\r
1047 int keys, len;\r
1048\r
1049 strcpy(tmp, (which & PEV_STATE_LOAD) ? "LOAD STATE?" : "OVERWRITE SAVE?");\r
1050 len = strlen(tmp);\r
1051 nm = in_get_key_name(-1, -PBTN_MA3);\r
1052 snprintf(tmp + len, sizeof(tmp) - len, "(%s=yes, ", nm);\r
1053 len = strlen(tmp);\r
1054 nm = in_get_key_name(-1, -PBTN_MBACK);\r
1055 snprintf(tmp + len, sizeof(tmp) - len, "%s=no)", nm);\r
1056\r
1057 plat_status_msg_busy_first(tmp);\r
1058\r
1059 in_set_blocking(1);\r
1060 while (in_menu_wait_any(50) & (PBTN_MA3|PBTN_MBACK))\r
1061 ;\r
1062 while ( !((keys = in_menu_wait_any(50)) & (PBTN_MA3|PBTN_MBACK)) )\r
1063 ;\r
1064 if (keys & PBTN_MBACK)\r
1065 do_it = 0;\r
1066 while (in_menu_wait_any(50) & (PBTN_MA3|PBTN_MBACK))\r
1067 ;\r
1068 in_set_blocking(0);\r
1069 }\r
1070 if (do_it) {\r
1071 plat_status_msg_busy_first((which & PEV_STATE_LOAD) ? "LOADING GAME" : "SAVING GAME");\r
1072 PicoStateProgressCB = plat_status_msg_busy_next;\r
a47dd663 1073 emu_save_load_game((which & PEV_STATE_LOAD) ? 1 : 0, 0);\r
d34a42f9 1074 PicoStateProgressCB = NULL;\r
1075 }\r
1076 }\r
1077 if (which & PEV_SWITCH_RND)\r
1078 {\r
1079 plat_video_toggle_renderer();\r
1080 }\r
1081 if (which & (PEV_SSLOT_PREV|PEV_SSLOT_NEXT))\r
1082 {\r
1083 if (which & PEV_SSLOT_PREV) {\r
1084 state_slot -= 1;\r
1085 if (state_slot < 0)\r
1086 state_slot = 9;\r
1087 } else {\r
1088 state_slot += 1;\r
1089 if (state_slot > 9)\r
1090 state_slot = 0;\r
1091 }\r
1092\r
1093 plat_status_msg("SAVE SLOT %i [%s]", state_slot,\r
a47dd663 1094 emu_check_save_file(state_slot) ? "USED" : "FREE");\r
d34a42f9 1095 }\r
1096 if (which & PEV_MENU)\r
1097 engineState = PGS_Menu;\r
1098}\r
1099\r
1100void emu_update_input(void)\r
1101{\r
093b8a42 1102 static int prev_events = 0;\r
1103 int actions[IN_BINDTYPE_COUNT] = { 0, };\r
1104 int pl_actions[2];\r
1105 int events;\r
d34a42f9 1106\r
093b8a42 1107 in_update(actions);\r
d34a42f9 1108\r
093b8a42 1109 pl_actions[0] = actions[IN_BINDTYPE_PLAYER12];\r
1110 pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16;\r
d34a42f9 1111\r
093b8a42 1112 PicoPad[0] = pl_actions[0] & 0xfff;\r
1113 PicoPad[1] = pl_actions[1] & 0xfff;\r
d34a42f9 1114\r
093b8a42 1115 if (pl_actions[0] & 0x7000)\r
1116 do_turbo(&PicoPad[0], pl_actions[0]);\r
1117 if (pl_actions[1] & 0x7000)\r
1118 do_turbo(&PicoPad[1], pl_actions[1]);\r
1119\r
1120 events = actions[IN_BINDTYPE_EMU] & PEV_MASK;\r
d34a42f9 1121\r
1122 // volume is treated in special way and triggered every frame\r
1123 if (events & (PEV_VOL_DOWN|PEV_VOL_UP))\r
1124 plat_update_volume(1, events & PEV_VOL_UP);\r
1125\r
093b8a42 1126 if ((events ^ prev_events) & PEV_FF) {\r
a47dd663 1127 emu_set_fastforward(events & PEV_FF);\r
d34a42f9 1128 plat_update_volume(0, 0);\r
f2cf8472 1129 reset_timing = 1;\r
d34a42f9 1130 }\r
1131\r
093b8a42 1132 events &= ~prev_events;\r
d34a42f9 1133\r
f2cf8472 1134 if (PicoAHW == PAHW_PICO)\r
1135 run_events_pico(events);\r
d34a42f9 1136 if (events)\r
f2cf8472 1137 run_events_ui(events);\r
d34a42f9 1138 if (movie_data)\r
1139 update_movie();\r
1140\r
093b8a42 1141 prev_events = actions[IN_BINDTYPE_EMU] & PEV_MASK;\r
d34a42f9 1142}\r
1143\r
f2cf8472 1144static void mkdir_path(char *path_with_reserve, int pos, const char *name)\r
1145{\r
1146 strcpy(path_with_reserve + pos, name);\r
1147 if (plat_is_dir(path_with_reserve))\r
1148 return;\r
1149 if (mkdir(path_with_reserve, 0777) < 0)\r
1150 lprintf("failed to create: %s\n", path_with_reserve);\r
1151}\r
1152\r
1153void emu_init(void)\r
1154{\r
1155 char dir[256];\r
1156 int pos;\r
1157\r
1158 /* make dirs for saves */\r
1159 pos = plat_get_root_dir(dir, sizeof(dir) - 4);\r
1160 mkdir_path(dir, pos, "mds");\r
1161 mkdir_path(dir, pos, "srm");\r
1162 mkdir_path(dir, pos, "brm");\r
1163\r
1164 PicoInit();\r
1165 PicoMessage = plat_status_msg_busy_next;\r
1166 PicoMCDopenTray = emu_msg_tray_open;\r
1167 PicoMCDcloseTray = menu_loop_tray;\r
1168}\r
1169\r
1170void emu_finish(void)\r
1171{\r
1172 // save SRAM\r
a47dd663 1173 if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) {\r
1174 emu_save_load_game(0, 1);\r
f2cf8472 1175 SRam.changed = 0;\r
1176 }\r
1177\r
1178 if (!(currentConfig.EmuOpt & EOPT_NO_AUTOSVCFG))\r
1179 emu_writelrom();\r
1180\r
1181 PicoExit();\r
1182}\r
1183\r