From 1820b5a7a18fc8c37dddb2ab88159e513ceb3b16 Mon Sep 17 00:00:00 2001 From: notaz Date: Thu, 11 Oct 2007 20:43:48 +0000 Subject: [PATCH] initial psp code, functional menu git-svn-id: file:///home/notaz/opt/svn/PicoDrive@274 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Pico.c | 2 +- Pico/sound/sound.c | 2 +- cpu/mz80/driver.h | 13 + platform/common/emu.c | 6 +- platform/common/lprintf.h | 3 +- platform/common/menu.c | 5 + platform/common/readpng.c | 14 +- platform/psp/Makefile | 127 +++ platform/psp/emu.c | 76 ++ platform/psp/emu.h | 31 + platform/psp/main.c | 59 ++ platform/psp/menu.c | 1632 ++++++++++++++++++++++++++++++ platform/psp/menu.h | 13 + platform/psp/mp3.c | 20 + platform/psp/port_config.h | 24 + platform/psp/psp.c | 96 ++ platform/psp/psp.h | 32 + platform/psp/skin/background.png | Bin 0 -> 84002 bytes platform/psp/skin/font.png | Bin 0 -> 3185 bytes platform/psp/skin/readme.txt | 8 + platform/psp/skin/selector.png | Bin 0 -> 261 bytes platform/psp/skin/skin.txt | 4 + platform/psp/version.h | 2 + 23 files changed, 2162 insertions(+), 7 deletions(-) create mode 100644 cpu/mz80/driver.h create mode 100644 platform/psp/Makefile create mode 100644 platform/psp/emu.c create mode 100644 platform/psp/emu.h create mode 100644 platform/psp/main.c create mode 100644 platform/psp/menu.c create mode 100644 platform/psp/menu.h create mode 100644 platform/psp/mp3.c create mode 100644 platform/psp/port_config.h create mode 100644 platform/psp/psp.c create mode 100644 platform/psp/psp.h create mode 100644 platform/psp/skin/background.png create mode 100644 platform/psp/skin/font.png create mode 100644 platform/psp/skin/readme.txt create mode 100644 platform/psp/skin/selector.png create mode 100644 platform/psp/skin/skin.txt create mode 100644 platform/psp/version.h diff --git a/Pico/Pico.c b/Pico/Pico.c index c6bf03e..48899a0 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -638,7 +638,7 @@ void PicoFrameDrawOnly(void) // callback to output message from emu void (*PicoMessage)(const char *msg)=NULL; -#if defined(__DEBUG_PRINT) || defined(__GP2X__) || defined(__GIZ__) +#if 1 // defined(__DEBUG_PRINT) // tmp debug: dump some stuff #define bit(r, x) ((r>>x)&1) void z80_debug(char *dstr); diff --git a/Pico/sound/sound.c b/Pico/sound/sound.c index 8bec0ba..ab56bb9 100644 --- a/Pico/sound/sound.c +++ b/Pico/sound/sound.c @@ -463,7 +463,7 @@ PICO_INTERNAL void z80_exit(void) #endif } -#if defined(__DEBUG_PRINT) || defined(__GP2X__) || defined(__GIZ__) +#if 1 // defined(__DEBUG_PRINT) || defined(__GP2X__) || defined(__GIZ__) PICO_INTERNAL void z80_debug(char *dstr) { #if defined(_USE_DRZ80) diff --git a/cpu/mz80/driver.h b/cpu/mz80/driver.h new file mode 100644 index 0000000..0705ea9 --- /dev/null +++ b/cpu/mz80/driver.h @@ -0,0 +1,13 @@ +/* compiler dependence */ +#ifndef UINT8 +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +#endif +#ifndef INT8 +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif + + diff --git a/platform/common/emu.c b/platform/common/emu.c index 723dfb7..9e07260 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -26,7 +26,11 @@ #elif defined(__GIZ__) #include "../gizmondo/giz.h" #define SCREEN_WIDTH 321 - #define SCREEN_BUFFER giz_screen // ? + #define SCREEN_BUFFER giz_screen +#elif defined(PSP) + #include "../psp/psp.h" + #define SCREEN_WIDTH 512 + #define SCREEN_BUFFER psp_screen #endif char *PicoConfigFile = "picoconfig.bin"; diff --git a/platform/common/lprintf.h b/platform/common/lprintf.h index 5cd176f..d09a461 100644 --- a/platform/common/lprintf.h +++ b/platform/common/lprintf.h @@ -1,4 +1,5 @@ -#if defined(__GP2X__) +#if defined(__GP2X__) || defined(PSP) +#include #define lprintf printf #else #include "giz.h" diff --git a/platform/common/menu.c b/platform/common/menu.c index d2957c2..b6bd019 100644 --- a/platform/common/menu.c +++ b/platform/common/menu.c @@ -22,6 +22,10 @@ #define SCREEN_WIDTH 321 #define SCREEN_BUFFER menu_screen extern unsigned char *menu_screen; +#elif defined(PSP) + #include "../psp/psp.h" + #define SCREEN_WIDTH 512 + #define SCREEN_BUFFER psp_screen #endif char menuErrorMsg[64] = { 0, }; @@ -216,6 +220,7 @@ void menu_init(void) int tmp = parse_hex_color(buff+16); if (tmp >= 0) menu_sel_color = tmp; else lprintf("skin.txt: parse error for selection_color\n"); + lprintf("sel color: %04x\n", menu_sel_color); } else lprintf("skin.txt: parse error: %s\n", buff); diff --git a/platform/common/readpng.c b/platform/common/readpng.c index 2a74668..1dd05a8 100644 --- a/platform/common/readpng.c +++ b/platform/common/readpng.c @@ -4,6 +4,14 @@ #include "readpng.h" #include "lprintf.h" +#ifdef PSP +#define BG_WIDTH 480 +#define BG_HEIGHT 272 +#else +#define BG_WIDTH 320 +#define BG_HEIGHT 240 +#endif + void readpng(void *dest, const char *fname, readpng_what what) { FILE *fp; @@ -62,9 +70,9 @@ void readpng(void *dest, const char *fname, readpng_what what) break; } height = info_ptr->height; - if (height > 240) height = 240; + if (height > BG_HEIGHT) height = BG_HEIGHT; width = info_ptr->width; - if (width > 320) width = 320; + if (width > BG_WIDTH) width = BG_WIDTH; for (h = 0; h < height; h++) { @@ -75,7 +83,7 @@ void readpng(void *dest, const char *fname, readpng_what what) *dst++ = ((src[0]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[2] >> 3); src += 3; } - dst += 320 - width; + dst += BG_WIDTH - width; } break; } diff --git a/platform/psp/Makefile b/platform/psp/Makefile new file mode 100644 index 0000000..769f3ed --- /dev/null +++ b/platform/psp/Makefile @@ -0,0 +1,127 @@ + +# pspdev is expected to be in path +PSPSDK = $(shell psp-config --pspsdk-path) + +# settings +use_musashi = 1 +use_mz80 = 1 +amalgamate = 0 +#profile = 1 +#up = 1 + + +CFLAGS += -I../.. -I. -D_UNZIP_SUPPORT -DNO_SYNC # -DBENCHMARK +CFLAGS += -Wall -Winline +ifeq ($(DEBUG),) +CFLAGS += -O2 -G0 -ftracer -fstrength-reduce -fomit-frame-pointer -fstrict-aliasing -ffast-math +else +CFLAGS += -ggdb +endif +ifeq "$(profile)" "1" +CFLAGS += -fprofile-generate +endif +ifeq "$(profile)" "2" +CFLAGS += -fprofile-use +endif + + +# frontend +OBJS += main.o emu.o mp3.o menu.o psp.o + +# common +OBJS += ../common/emu.o ../common/menu.o ../common/fonts.o ../common/readpng.o + +# Pico +ifeq "$(amalgamate)" "1" +OBJS += ../../PicoAll.o +else +OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Memory.o ../../Pico/Misc.o \ + ../../Pico/Pico.o ../../Pico/Sek.o ../../Pico/VideoPort.o ../../Pico/Draw2.o ../../Pico/Draw.o \ + ../../Pico/Patch.o +# Pico - CD +OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \ + ../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \ + ../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o +endif + +# Pico - sound +ifneq "$(amalgamate)" "1" +OBJS += ../../Pico/sound/sound.o +endif +OBJS += ../../Pico/sound/mix.o +OBJS += ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o +# zlib (hacked) +OBJS += ../../zlib/gzio.o ../../zlib/inffast.o ../../zlib/inflate.o ../../zlib/inftrees.o ../../zlib/trees.o \ + ../../zlib/deflate.o ../../zlib/crc32.o ../../zlib/adler32.o ../../zlib/zutil.o ../../zlib/compress.o +# unzip +OBJS += ../../unzip/unzip.o ../../unzip/unzip_stream.o +# CPU cores +ifeq "$(use_musashi)" "1" +CFLAGS += -DEMU_M68K +OBJS += ../../cpu/musashi/m68kops.o ../../cpu/musashi/m68kcpu.o +endif +# z80 +ifeq "$(use_mz80)" "1" +CFLAGS += -D_USE_MZ80 +OBJS += ../../cpu/mz80/mz80.o +else +$(error nothing here!) +endif + + +LIBS += -lpng -lm -lpspgu # -lpspaudio -lpspgu -lpsppower -lpsphprm -lz -lm -lstdc++ + +# target +TARGET = PicoDrive +EXTRA_TARGETS = EBOOT.PBP +PSP_EBOOT_TITLE = PICODRIVE +#PSP_EBOOT_ICON = .png +#PSP_EBOOT_PIC1 = .png + +CUSTOM_CLEAN = myclean + +include $(PSPSDK)/lib/build.mak + + +# some additional rules +.c.o: + @echo ">>>" $< + $(CC) $(CFLAGS) -c $< -o $@ + +../../cpu/musashi/m68kops.c : + make -C ../../cpu/musashi + +readme.txt: ../../tools/textfilter ../base_readme.txt + ../../tools/textfilter ../base_readme.txt $@ PSP + +../../tools/textfilter: ../../tools/textfilter.c + make -C ../../tools/ textfilter + + +# ? +up: EBOOT.PBP + @cp -v $^ /media/disk/PSP/GAME/PicoDrive/ + + +# cleanup + +myclean: + make -C ../../cpu/musashi clean + + +clean_prof: + find ../.. -name '*.gcno' -delete + find ../.. -name '*.gcda' -delete + +# ----------- release ----------- +ifneq ($(findstring rel,$(MAKECMDGOALS)),) +ifeq ($(VER),) +$(error need VER) +endif +endif + +# ? +rel: EBOOT.PBP readme.txt + zip -9 -j ../../PicoDrive_$(VER).zip $^ +# zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt + diff --git a/platform/psp/emu.c b/platform/psp/emu.c new file mode 100644 index 0000000..0d22e42 --- /dev/null +++ b/platform/psp/emu.c @@ -0,0 +1,76 @@ +#include +#include +#include // PATH_MAX + +#include "../../Pico/PicoInt.h" + +char romFileName[PATH_MAX]; +unsigned char *PicoDraw2FB; // temporary buffer for alt renderer ( (8+320)*(8+240+8) ) +int engineState; + + +void emu_noticeMsgUpdated(void) +{ +} + +void emu_getMainDir(char *dst, int len) +{ +} + +void emu_stateCb(const char *str) +{ +} + +void emu_setDefaultConfig(void) +{ +} + +void emu_forcedFrame(void) +{ +} + +void emu_Init(void) +{ + // make dirs for saves, cfgs, etc. + mkdir("mds", 0777); + mkdir("srm", 0777); + mkdir("brm", 0777); + mkdir("cfg", 0777); + + PicoInit(); +// PicoMessage = emu_msg_cb; +// PicoMCDopenTray = emu_msg_tray_open; +// PicoMCDcloseTray = menu_loop_tray; +} + +void emu_Deinit(void) +{ + // save SRAM +/* if ((currentConfig.EmuOpt & 1) && SRam.changed) { + emu_SaveLoadGame(0, 1); + SRam.changed = 0; + } + + if (!(currentConfig.EmuOpt & 0x20)) { + FILE *f = fopen(PicoConfigFile, "r+b"); + if (!f) emu_WriteConfig(0); + else { + // if we already have config, reload it, except last ROM + fseek(f, sizeof(currentConfig.lastRomFile), SEEK_SET); + fread(¤tConfig.EmuOpt, 1, sizeof(currentConfig) - sizeof(currentConfig.lastRomFile), f); + fseek(f, 0, SEEK_SET); + fwrite(¤tConfig, 1, sizeof(currentConfig), f); + fflush(f); + fclose(f); + } + } +*/ + PicoExit(); +} + +void emu_ResetGame(void) +{ + PicoReset(0); + //reset_timing = 1; +} + diff --git a/platform/psp/emu.h b/platform/psp/emu.h new file mode 100644 index 0000000..48ce9a3 --- /dev/null +++ b/platform/psp/emu.h @@ -0,0 +1,31 @@ +// (c) Copyright 2006-2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + + + +// engine states +enum TPicoGameState { + PGS_Paused = 1, + PGS_Running, + PGS_Quit, + PGS_KeyConfig, + PGS_ReloadRom, + PGS_Menu, + PGS_RestartRun, +}; + +extern char romFileName[]; +extern int engineState; + + +void emu_Init(void); +void emu_Deinit(void); +void emu_Loop(void); +void emu_ResetGame(void); +void emu_forcedFrame(void); + +void emu_stateCb(const char *str); + + diff --git a/platform/psp/main.c b/platform/psp/main.c new file mode 100644 index 0000000..8d5fbf4 --- /dev/null +++ b/platform/psp/main.c @@ -0,0 +1,59 @@ +#include "psp.h" +#include "emu.h" +#include "menu.h" +#include "../common/menu.h" +#include "../common/lprintf.h" + +int main() +{ + psp_init(); + +// emu_ReadConfig(0, 0); + emu_Init(); + menu_init(); + + engineState = PGS_Menu; + + for (;;) + { + switch (engineState) + { + case PGS_Menu: + menu_loop(); + break; + + case PGS_ReloadRom: +/* + if (emu_ReloadRom()) + engineState = PGS_Running; + else { + lprintf("PGS_ReloadRom == 0\n"); + engineState = PGS_Menu; + } +*/ + break; + + case PGS_RestartRun: + engineState = PGS_Running; + + case PGS_Running: +// emu_Loop(); + break; + + case PGS_Quit: + goto endloop; + + default: + lprintf("engine got into unknown state (%i), exitting\n", engineState); + goto endloop; + } + } + + endloop: + + emu_Deinit(); + psp_finish(); + + return 0; +} + diff --git a/platform/psp/menu.c b/platform/psp/menu.c new file mode 100644 index 0000000..18c8536 --- /dev/null +++ b/platform/psp/menu.c @@ -0,0 +1,1632 @@ +// (c) Copyright 2006,2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +// don't like to use loads of #ifdefs, so duplicating GP2X code +// horribly instead + +//#include +#include +#include +#include +#include +#include // for opendir +#include // PATH_MAX + +#include +#include +#include + +#include "psp.h" +#include "emu.h" +#include "menu.h" +#include "../common/menu.h" +#include "../common/emu.h" +#include "../common/readpng.h" +#include "../common/lprintf.h" +#include "version.h" + +#include +#include +#include + + +#define pspKeyUnkn "???" +static const char * const pspKeyNames[] = { + "SELECT", pspKeyUnkn, pspKeyUnkn, "START", "UP", "RIGHT", "DOWN", "LEFT", + "L", "R", pspKeyUnkn, pspKeyUnkn, "TRIANGLE", "CIRCLE", "X", "SQUARE", + "HOME", "HOLD", "WLAN_UP", "REMOTE", "VOLUP", "VOLDOWN", "SCREEN", "NOTE", + pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn, pspKeyUnkn +}; + +unsigned int __attribute__((aligned(16))) guCmdList[1024]; // TODO: adjust, mv + +static unsigned char bg_buffer[480*272*2] __attribute__((aligned(16))); // TODO: move to vram? +#define menu_screen psp_screen + +static void menu_darken_bg(void *dst, const void *src, int pixels, int darker); +static void menu_prepare_bg(int use_game_bg); + + +static unsigned int inp_prev = 0; + +static unsigned long wait_for_input(unsigned int interesting) +{ + unsigned int ret; + static int repeats = 0, wait = 50; + int release = 0, i; + + if (repeats == 2 || repeats == 4) wait /= 2; + if (repeats == 6) wait = 15; + + for (i = 0; i < 6 && inp_prev == psp_pad_read(); i++) { + if (i == 0) repeats++; + psp_msleep(wait); + } + + while ( !((ret = psp_pad_read()) & interesting) ) { + psp_msleep(50); + release = 1; + } + + if (release || ret != inp_prev) { + repeats = 0; + wait = 50; + } + inp_prev = ret; + + // we don't need diagonals in menus + if ((ret&BTN_UP) && (ret&BTN_LEFT)) ret &= ~BTN_LEFT; + if ((ret&BTN_UP) && (ret&BTN_RIGHT)) ret &= ~BTN_RIGHT; + if ((ret&BTN_DOWN) && (ret&BTN_LEFT)) ret &= ~BTN_LEFT; + if ((ret&BTN_DOWN) && (ret&BTN_RIGHT)) ret &= ~BTN_RIGHT; + + return ret; +} + +static void menu_draw_begin(void) +{ + // short *src = (short *)bg_buffer, *dst = (short *)menu_screen; + // int i; + + // for (i = 272; i >= 0; i--, dst += 512, src += 480) + // memcpy32((int *)dst, (int *)src, 480*2/4); + + sceGuStart(GU_DIRECT, guCmdList); + sceGuCopyImage(GU_PSM_5650, 0, 0, 480, 272, 480, bg_buffer, 0, 0, 512, menu_screen); + sceGuFinish(); + sceGuSync(0, GU_SYNC_FINISH); +} + + +static void menu_draw_end(void) +{ + sceDisplayWaitVblankStart(); + psp_video_flip(); +} + + +// --------- loading ROM screen ---------- + +static void load_progress_cb(int percent) +{ + int ln, len = percent * 480 / 100; + unsigned short *dst; + + sceDisplayWaitVblankStart(); + + dst = (unsigned short *)menu_screen + 512*20; + + if (len > 480) len = 480; + for (ln = 10; ln > 0; ln--, dst += 512) + memset(dst, 0xff, len*2); +} + +void menu_romload_prepare(const char *rom_name) +{ + const char *p = rom_name + strlen(rom_name); + while (p > rom_name && *p != '/') p--; + + psp_video_switch_to_single(); + menu_draw_begin(); + + smalltext_out16(1, 1, "Loading", 0xffff); + smalltext_out16_lim(1, 10, p, 0xffff, 80); + PicoCartLoadProgressCB = load_progress_cb; +} + +void menu_romload_end(void) +{ + PicoCartLoadProgressCB = NULL; + smalltext_out16(1, 30, "Starting emulation...", 0xffff); +} + +// -------------- ROM selector -------------- + +// SceIoDirent +#define DT_DIR FIO_SO_IFDIR +#define DT_REG FIO_SO_IFREG + +struct my_dirent +{ + unsigned char d_type; + char d_name[255]; +}; + +// rrrr rggg gggb bbbb +static unsigned short file2color(const char *fname) +{ + const char *ext = fname + strlen(fname) - 3; + static const char *rom_exts[] = { "zip", "bin", "smd", "gen", "iso" }; + static const char *other_exts[] = { "gmv", "pat" }; + int i; + + if (ext < fname) ext = fname; + for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++) + if (strcasecmp(ext, rom_exts[i]) == 0) return 0xbdff; + for (i = 0; i < sizeof(other_exts)/sizeof(other_exts[0]); i++) + if (strcasecmp(ext, other_exts[i]) == 0) return 0xaff5; + return 0xffff; +} + +static void draw_dirlist(char *curdir, struct my_dirent **namelist, int n, int sel) +{ + int start, i, pos; + + start = 13 - sel; + n--; // exclude current dir (".") + + menu_draw_begin(); + + if (rom_data == NULL) { +// menu_darken_bg(menu_screen, menu_screen, 321*240, 0); + } + + menu_darken_bg((char *)menu_screen + 512*129*2, (char *)menu_screen + 512*129*2, 512*10, 0); + + if (start - 2 >= 0) + smalltext_out16_lim(14, (start - 2)*10, curdir, 0xffff, 53-2); + for (i = 0; i < n; i++) { + pos = start + i; + if (pos < 0) continue; + if (pos > 26) break; + if (namelist[i+1]->d_type & DT_DIR) { + smalltext_out16_lim(14, pos*10, "/", 0xfff6, 1); + smalltext_out16_lim(14+6, pos*10, namelist[i+1]->d_name, 0xfff6, 53-3); + } else { + unsigned short color = file2color(namelist[i+1]->d_name); + smalltext_out16_lim(14, pos*10, namelist[i+1]->d_name, color, 53-2); + } + } + text_out16(5, 130, ">"); + menu_draw_end(); +} + +static int scandir_cmp(const void *p1, const void *p2) +{ + struct my_dirent **d1 = (struct my_dirent **)p1, **d2 = (struct my_dirent **)p2; + if ((*d1)->d_type == (*d2)->d_type) return strcasecmp((*d1)->d_name, (*d2)->d_name); + if ((*d1)->d_type & DT_DIR) return -1; // put before + if ((*d2)->d_type & DT_DIR) return 1; + return strcasecmp((*d1)->d_name, (*d2)->d_name); +} + +static char *filter_exts[] = { + ".mp3", ".srm", ".brm", "s.gz", ".mds", "bcfg", ".txt", ".htm", "html", + ".jpg", ".cue", ".pbp" +}; + +static int scandir_filter(const struct my_dirent *ent) +{ + const char *p; + int i; + + if (ent == NULL || ent->d_name == NULL) return 0; + if (strlen(ent->d_name) < 5) return 1; + + p = ent->d_name + strlen(ent->d_name) - 4; + + for (i = 0; i < sizeof(filter_exts)/sizeof(filter_exts[0]); i++) + { + if (strcasecmp(p, filter_exts[i]) == 0) return 0; + } + + return 1; +} + +static int my_scandir(const char *dir, struct my_dirent ***namelist_out, + int(*filter)(const struct my_dirent *), + int(*compar)(const void *, const void *)) +{ + int ret = -1, dir_uid = -1, name_alloc = 4, name_count = 0; + struct my_dirent **namelist = NULL, *ent; + SceIoDirent sce_ent; + + namelist = malloc(sizeof(*namelist) * name_alloc); + if (namelist == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } + + // try to read first.. + dir_uid = sceIoDopen(dir); + if (dir_uid >= 0) + { + ret = sceIoDread(dir_uid, &sce_ent); + if (ret < 0) + { + lprintf("sceIoDread(\"%s\") failed with %i\n", dir, ret); + goto fail; + } + } + else + lprintf("sceIoDopen(\"%s\") failed with %i\n", dir, dir_uid); + + while (ret > 0) + { + ent = malloc(sizeof(*ent)); + if (ent == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } + ent->d_type = sce_ent.d_stat.st_attr; + strncpy(ent->d_name, sce_ent.d_name, sizeof(ent->d_name)); + ent->d_name[sizeof(ent->d_name)] = 0; + if (filter == NULL || filter(ent)) + namelist[name_count++] = ent; + else free(ent); + + if (name_count >= name_alloc) + { + void *tmp; + name_alloc *= 2; + tmp = realloc(namelist, sizeof(*namelist) * name_alloc); + if (tmp == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } + namelist = tmp; + } + + ret = sceIoDread(dir_uid, &sce_ent); + } + + // sort + if (compar != NULL && name_count > 3) qsort(&namelist[2], name_count - 2, sizeof(namelist[0]), compar); + + // all done. + ret = name_count; + *namelist_out = namelist; + goto end; + +fail: + if (namelist != NULL) + { + while (name_count--) + free(namelist[name_count]); + free(namelist); + } +end: + if (dir_uid >= 0) sceIoDclose(dir_uid); + return ret; +} + + +static char *romsel_loop(char *curr_path) +{ + struct my_dirent **namelist; + DIR *dir; + int n, sel = 0; + unsigned long inp = 0; + char *ret = NULL, *fname = NULL; + + // is this a dir or a full path? + if ((dir = opendir(curr_path))) { + closedir(dir); + } else { + char *p; + for (p = curr_path + strlen(curr_path) - 1; p > curr_path && *p != '/'; p--); + *p = 0; + fname = p+1; + } + + n = my_scandir(curr_path, &namelist, scandir_filter, scandir_cmp); + if (n < 0) { + // try root.. + n = my_scandir("/", &namelist, scandir_filter, scandir_cmp); + if (n < 0) { + // oops, we failed + lprintf("scandir failed, dir: "); lprintf(curr_path); lprintf("\n"); + return NULL; + } + } + + // try to find sel + if (fname != NULL) { + int i; + for (i = 1; i < n; i++) { + if (strcmp(namelist[i]->d_name, fname) == 0) { + sel = i - 1; + break; + } + } + } + + for (;;) + { + draw_dirlist(curr_path, namelist, n, sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE); + if(inp & BTN_UP ) { sel--; if (sel < 0) sel = n-2; } + if(inp & BTN_DOWN) { sel++; if (sel > n-2) sel = 0; } + if(inp & BTN_LEFT) { sel-=10; if (sel < 0) sel = 0; } + if(inp & BTN_L) { sel-=24; if (sel < 0) sel = 0; } + if(inp & BTN_RIGHT) { sel+=10; if (sel > n-2) sel = n-2; } + if(inp & BTN_R) { sel+=24; if (sel > n-2) sel = n-2; } + if(inp & BTN_X) { // enter dir/select + if (namelist[sel+1]->d_type & DT_REG) { + strcpy(romFileName, curr_path); + strcat(romFileName, "/"); + strcat(romFileName, namelist[sel+1]->d_name); + ret = romFileName; + break; + } else if (namelist[sel+1]->d_type & DT_DIR) { + int newlen = strlen(curr_path) + strlen(namelist[sel+1]->d_name) + 2; + char *p, *newdir = malloc(newlen); + if (strcmp(namelist[sel+1]->d_name, "..") == 0) { + char *start = curr_path; + p = start + strlen(start) - 1; + while (*p == '/' && p > start) p--; + while (*p != '/' && p > start) p--; + if (p <= start) strcpy(newdir, "/"); + else { strncpy(newdir, start, p-start); newdir[p-start] = 0; } + } else { + strcpy(newdir, curr_path); + p = newdir + strlen(newdir) - 1; + while (*p == '/' && p >= newdir) *p-- = 0; + strcat(newdir, "/"); + strcat(newdir, namelist[sel+1]->d_name); + } + ret = romsel_loop(newdir); + free(newdir); + break; + } + } + if(inp & BTN_CIRCLE) break; // cancel + } + + if (n > 0) { + while(n--) free(namelist[n]); + free(namelist); + } + + return ret; +} + +// ------------ debug menu ------------ + +char *debugString(void); + +static void draw_debug(void) +{ + char *p, *str = debugString(); + int len, line; + + menu_draw_begin(); + + p = str; + for (line = 0; line < 24; line++) + { + while (*p && *p != '\n') p++; + len = p - str; + if (len > 55) len = 55; + smalltext_out16_lim(1, line*10, str, 0xffff, len); + if (*p == 0) break; + p++; str = p; + } + menu_draw_end(); +} + +static void debug_menu_loop(void) +{ + draw_debug(); + wait_for_input(BTN_X|BTN_CIRCLE); +} + +// ------------ patch/gg menu ------------ + +static void draw_patchlist(int sel) +{ + int start, i, pos, active; + + start = 13 - sel; + + menu_draw_begin(); + + for (i = 0; i < PicoPatchCount; i++) { + pos = start + i; + if (pos < 0) continue; + if (pos > 26) break; + active = PicoPatches[i].active; + smalltext_out16_lim(14, pos*10, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff, 3); + smalltext_out16_lim(14+6*4, pos*10, PicoPatches[i].name, active ? 0xfff6 : 0xffff, 53-6); + } + pos = start + i; + if (pos < 27) smalltext_out16_lim(14, pos*10, "done", 0xffff, 4); + + text_out16(5, 130, ">"); + menu_draw_end(); +} + + +static void patches_menu_loop(void) +{ + int menu_sel = 0; + unsigned long inp = 0; + + for(;;) + { + draw_patchlist(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_L|BTN_R|BTN_X|BTN_CIRCLE); + if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = PicoPatchCount; } + if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > PicoPatchCount) menu_sel = 0; } + if(inp &(BTN_LEFT|BTN_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; } + if(inp &(BTN_RIGHT|BTN_R)) { menu_sel+=10; if (menu_sel > PicoPatchCount) menu_sel = PicoPatchCount; } + if(inp & BTN_X) { // action + if (menu_sel < PicoPatchCount) + PicoPatches[menu_sel].active = !PicoPatches[menu_sel].active; + else return; + } + if(inp & BTN_CIRCLE) return; + } + +} + +// ------------ savestate loader ------------ + +static int state_slot_flags = 0; + +static void state_check_slots(void) +{ + int slot; + + state_slot_flags = 0; + + for (slot = 0; slot < 10; slot++) + { + if (emu_checkSaveFile(slot)) + { + state_slot_flags |= 1 << slot; + } + } +} + +static void draw_savestate_bg(int slot) +{ + struct PicoVideo tmp_pv; + unsigned short tmp_cram[0x40]; + unsigned short tmp_vsram[0x40]; + void *tmp_vram, *file; + char *fname; + + fname = emu_GetSaveFName(1, 0, slot); + if (!fname) return; + + tmp_vram = malloc(sizeof(Pico.vram)); + if (tmp_vram == NULL) return; + + memcpy(tmp_vram, Pico.vram, sizeof(Pico.vram)); + memcpy(tmp_cram, Pico.cram, sizeof(Pico.cram)); + memcpy(tmp_vsram, Pico.vsram, sizeof(Pico.vsram)); + memcpy(&tmp_pv, &Pico.video, sizeof(Pico.video)); + + if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) { + file = gzopen(fname, "rb"); + emu_setSaveStateCbs(1); + } else { + file = fopen(fname, "rb"); + emu_setSaveStateCbs(0); + } + + if (file) { + if (PicoMCD & 1) { + PicoCdLoadStateGfx(file); + } else { + areaSeek(file, 0x10020, SEEK_SET); // skip header and RAM in state file + areaRead(Pico.vram, 1, sizeof(Pico.vram), file); + areaSeek(file, 0x2000, SEEK_CUR); + areaRead(Pico.cram, 1, sizeof(Pico.cram), file); + areaRead(Pico.vsram, 1, sizeof(Pico.vsram), file); + areaSeek(file, 0x221a0, SEEK_SET); + areaRead(&Pico.video, 1, sizeof(Pico.video), file); + } + areaClose(file); + } + + emu_forcedFrame(); + menu_prepare_bg(1); + + memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); + memcpy(Pico.cram, tmp_cram, sizeof(Pico.cram)); + memcpy(Pico.vsram, tmp_vsram, sizeof(Pico.vsram)); + memcpy(&Pico.video, &tmp_pv, sizeof(Pico.video)); + free(tmp_vram); +} + +static void draw_savestate_menu(int menu_sel, int is_loading) +{ + int tl_x = 80+25, tl_y = 16+60, y, i; + + if (state_slot_flags & (1 << menu_sel)) + draw_savestate_bg(menu_sel); + menu_draw_begin(); + + text_out16(tl_x, 16+30, is_loading ? "Load state" : "Save state"); + + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 108); + + /* draw all 10 slots */ + y = tl_y; + for (i = 0; i < 10; i++, y+=10) + { + text_out16(tl_x, y, "SLOT %i (%s)", i, (state_slot_flags & (1 << i)) ? "USED" : "free"); + } + text_out16(tl_x, y, "back"); + + menu_draw_end(); +} + +static int savestate_menu_loop(int is_loading) +{ + static int menu_sel = 10; + int menu_sel_max = 10; + unsigned long inp = 0; + + state_check_slots(); + + for(;;) + { + draw_savestate_menu(menu_sel, is_loading); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE); + if(inp & BTN_UP ) { + do { + menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; + } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading); + } + if(inp & BTN_DOWN) { + do { + menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; + } while (!(state_slot_flags & (1 << menu_sel)) && menu_sel != menu_sel_max && is_loading); + } + if(inp & BTN_X) { // save/load + if (menu_sel < 10) { + state_slot = menu_sel; + PicoStateProgressCB = emu_stateCb; /* also suitable for menu */ + if (emu_SaveLoadGame(is_loading, 0)) { + strcpy(menuErrorMsg, is_loading ? "Load failed" : "Save failed"); + return 1; + } + return 0; + } else return 1; + } + if(inp & BTN_CIRCLE) return 1; + } +} + +// -------------- key config -------------- + +static char *action_binds(int player_idx, int action_mask) +{ + static char strkeys[32*5]; + int i; + + strkeys[0] = 0; + for (i = 0; i < 32; i++) // i is key index + { + if (currentConfig.KeyBinds[i] & action_mask) + { + if (player_idx >= 0 && ((currentConfig.KeyBinds[i] >> 16) & 3) != player_idx) continue; + if (strkeys[0]) { strcat(strkeys, " + "); strcat(strkeys, pspKeyNames[i]); break; } + else strcpy(strkeys, pspKeyNames[i]); + } + } + + return strkeys; +} + +static void unbind_action(int action) +{ + int i; + + for (i = 0; i < 32; i++) + currentConfig.KeyBinds[i] &= ~action; +} + +static int count_bound_keys(int action, int pl_idx) +{ + int i, keys = 0; + + for (i = 0; i < 32; i++) + { + if (pl_idx >= 0 && (currentConfig.KeyBinds[i]&0x30000) != (pl_idx<<16)) continue; + if (currentConfig.KeyBinds[i] & action) keys++; + } + + return keys; +} + +typedef struct { char *name; int mask; } bind_action_t; + +static void draw_key_config(const bind_action_t *opts, int opt_cnt, int player_idx, int sel) +{ + int x, y, tl_y = 16+40, i; + + menu_draw_begin(); + if (player_idx >= 0) { + text_out16(80+80, 16+20, "Player %i controls", player_idx + 1); + x = 80+80; + } else { + text_out16(80+80, 16+20, "Emulator controls"); + x = 80+40; + } + + menu_draw_selection(x - 16, tl_y + sel*10, (player_idx >= 0) ? 66 : 130); + + y = tl_y; + for (i = 0; i < opt_cnt; i++, y+=10) + text_out16(x, y, "%s : %s", opts[i].name, action_binds(player_idx, opts[i].mask)); + + text_out16(x, y, "Done"); + + if (sel < opt_cnt) { + text_out16(80+30, 180, "Press a button to bind/unbind"); + text_out16(80+30, 190, "Use SELECT to clear"); + text_out16(80+30, 200, "To bind UP/DOWN, hold SELECT"); + text_out16(80+30, 210, "Select \"Done\" to exit"); + } else { + text_out16(80+30, 190, "Use Options -> Save cfg"); + text_out16(80+30, 200, "to save controls"); + text_out16(80+30, 210, "Press X or O to exit"); + } + menu_draw_end(); +} + +static void key_config_loop(const bind_action_t *opts, int opt_cnt, int player_idx) +{ + int sel = 0, menu_sel_max = opt_cnt, prev_select = 0, i; + unsigned long inp = 0; + + for (;;) + { + draw_key_config(opts, opt_cnt, player_idx, sel); + inp = wait_for_input(CONFIGURABLE_KEYS|BTN_SELECT); + if (!(inp & BTN_SELECT)) { + prev_select = 0; + if(inp & BTN_UP ) { sel--; if (sel < 0) sel = menu_sel_max; continue; } + if(inp & BTN_DOWN) { sel++; if (sel > menu_sel_max) sel = 0; continue; } + } + if (sel >= opt_cnt) { + if (inp & (BTN_X|BTN_CIRCLE)) break; + else continue; + } + // if we are here, we want to bind/unbind something + if ((inp & BTN_SELECT) && !prev_select) + unbind_action(opts[sel].mask); + prev_select = inp & BTN_SELECT; + inp &= CONFIGURABLE_KEYS; + inp &= ~BTN_SELECT; + for (i = 0; i < 32; i++) + if (inp & (1 << i)) { + if (count_bound_keys(opts[sel].mask, player_idx) >= 2) + currentConfig.KeyBinds[i] &= ~opts[sel].mask; // allow to unbind only + else currentConfig.KeyBinds[i] ^= opts[sel].mask; + if (player_idx >= 0 && (currentConfig.KeyBinds[i] & opts[sel].mask)) { + currentConfig.KeyBinds[i] &= ~(3 << 16); + currentConfig.KeyBinds[i] |= player_idx << 16; + } + } + } +} + +static void draw_kc_sel(int menu_sel) +{ + int tl_x = 80+25+40, tl_y = 16+60, y; + + y = tl_y; + menu_draw_begin(); + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 138); + + text_out16(tl_x, y, "Player 1"); + text_out16(tl_x, (y+=10), "Player 2"); + text_out16(tl_x, (y+=10), "Emulator controls"); + text_out16(tl_x, (y+=10), "Done"); + + menu_draw_end(); +} + + +// PicoPad[] format: MXYZ SACB RLDU +static bind_action_t ctrl_actions[] = +{ + { "UP ", 0x001 }, + { "DOWN ", 0x002 }, + { "LEFT ", 0x004 }, + { "RIGHT ", 0x008 }, + { "A ", 0x040 }, + { "B ", 0x010 }, + { "C ", 0x020 }, + { "START ", 0x080 }, + { "MODE ", 0x800 }, + { "X ", 0x400 }, + { "Y ", 0x200 }, + { "Z ", 0x100 }, +}; + +// player2_flag, ?, ?, ?, ?, ?, ?, menu +// "NEXT SAVE SLOT", "PREV SAVE SLOT", "SWITCH RENDERER", "SAVE STATE", +// "LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE" +static bind_action_t emuctrl_actions[] = +{ + { "Load State ", 1<<28 }, + { "Save State ", 1<<27 }, + { "Prev Save Slot ", 1<<25 }, + { "Next Save Slot ", 1<<24 }, + { "Switch Renderer", 1<<26 }, + { "Volume Down ", 1<<30 }, + { "Volume Up ", 1<<29 }, +}; + +static void kc_sel_loop(void) +{ + int menu_sel = 3, menu_sel_max = 3; + unsigned long inp = 0; + int is_6button = currentConfig.PicoOpt & 0x020; + + while (1) + { + draw_kc_sel(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE); + if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if (inp & BTN_X) { + switch (menu_sel) { + case 0: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 0); return; + case 1: key_config_loop(ctrl_actions, is_6button ? 12 : 8, 1); return; + case 2: key_config_loop(emuctrl_actions, + sizeof(emuctrl_actions)/sizeof(emuctrl_actions[0]), -1); return; + case 3: if (rom_data == NULL) emu_WriteConfig(0); return; + default: return; + } + } + if (inp & BTN_CIRCLE) return; + } +} + + +// --------- sega/mega cd options ---------- + +menu_entry cdopt_entries[] = +{ + { NULL, MB_NONE, MA_CDOPT_TESTBIOS_USA, NULL, 0, 0, 0, 1 }, + { NULL, MB_NONE, MA_CDOPT_TESTBIOS_EUR, NULL, 0, 0, 0, 1 }, + { NULL, MB_NONE, MA_CDOPT_TESTBIOS_JAP, NULL, 0, 0, 0, 1 }, + { "CD LEDs", MB_ONOFF, MA_CDOPT_LEDS, ¤tConfig.EmuOpt, 0x0400, 0, 0, 1 }, + { "CDDA audio (using mp3s)", MB_ONOFF, MA_CDOPT_CDDA, ¤tConfig.PicoOpt, 0x0800, 0, 0, 1 }, + { "PCM audio", MB_ONOFF, MA_CDOPT_PCM, ¤tConfig.PicoOpt, 0x0400, 0, 0, 1 }, + { NULL, MB_NONE, MA_CDOPT_READAHEAD, NULL, 0, 0, 0, 1 }, + { "SaveRAM cart", MB_ONOFF, MA_CDOPT_SAVERAM, ¤tConfig.PicoOpt, 0x8000, 0, 0, 1 }, + { "Scale/Rot. fx (slow)", MB_ONOFF, MA_CDOPT_SCALEROT_CHIP,¤tConfig.PicoOpt, 0x1000, 0, 0, 1 }, + { "Better sync (slow)", MB_ONOFF, MA_CDOPT_BETTER_SYNC, ¤tConfig.PicoOpt, 0x2000, 0, 0, 1 }, + { "done", MB_NONE, MA_CDOPT_DONE, NULL, 0, 0, 0, 1 }, +}; + +#define CDOPT_ENTRY_COUNT (sizeof(cdopt_entries) / sizeof(cdopt_entries[0])) + + +struct bios_names_t +{ + char us[32], eu[32], jp[32]; +}; + +static void menu_cdopt_cust_draw(const menu_entry *entry, int x, int y, void *param) +{ + struct bios_names_t *bios_names = param; + char ra_buff[16]; + + switch (entry->id) + { + case MA_CDOPT_TESTBIOS_USA: text_out16(x, y, "USA BIOS: %s", bios_names->us); break; + case MA_CDOPT_TESTBIOS_EUR: text_out16(x, y, "EUR BIOS: %s", bios_names->eu); break; + case MA_CDOPT_TESTBIOS_JAP: text_out16(x, y, "JAP BIOS: %s", bios_names->jp); break; + case MA_CDOPT_READAHEAD: + if (PicoCDBuffers > 1) sprintf(ra_buff, "%5iK", PicoCDBuffers * 2); + else strcpy(ra_buff, " OFF"); + text_out16(x, y, "ReadAhead buffer %s", ra_buff); + break; + default:break; + } +} + +static void draw_cd_menu_options(int menu_sel, struct bios_names_t *bios_names) +{ + int tl_x = 80+25, tl_y = 16+60; + menu_id selected_id; + char ra_buff[16]; + + if (PicoCDBuffers > 1) sprintf(ra_buff, "%5iK", PicoCDBuffers * 2); + else strcpy(ra_buff, " OFF"); + + menu_draw_begin(); + + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 246); + + me_draw(cdopt_entries, CDOPT_ENTRY_COUNT, tl_x, tl_y, menu_cdopt_cust_draw, bios_names); + + selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel); + if ((selected_id == MA_CDOPT_TESTBIOS_USA && strcmp(bios_names->us, "NOT FOUND")) || + (selected_id == MA_CDOPT_TESTBIOS_EUR && strcmp(bios_names->eu, "NOT FOUND")) || + (selected_id == MA_CDOPT_TESTBIOS_JAP && strcmp(bios_names->jp, "NOT FOUND"))) + text_out16(tl_x, 210, "Press start to test selected BIOS"); + + menu_draw_end(); +} + +static void cd_menu_loop_options(void) +{ + static int menu_sel = 0; + int menu_sel_max = 10; + unsigned long inp = 0; + struct bios_names_t bios_names; + menu_id selected_id; + char *bios, *p; + + if (emu_findBios(4, &bios)) { // US + for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; + strncpy(bios_names.us, p, sizeof(bios_names.us)); bios_names.us[sizeof(bios_names.us)-1] = 0; + } else strcpy(bios_names.us, "NOT FOUND"); + + if (emu_findBios(8, &bios)) { // EU + for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; + strncpy(bios_names.eu, p, sizeof(bios_names.eu)); bios_names.eu[sizeof(bios_names.eu)-1] = 0; + } else strcpy(bios_names.eu, "NOT FOUND"); + + if (emu_findBios(1, &bios)) { // JP + for (p = bios+strlen(bios)-1; p > bios && *p != '/'; p--); p++; + strncpy(bios_names.jp, p, sizeof(bios_names.jp)); bios_names.jp[sizeof(bios_names.jp)-1] = 0; + } else strcpy(bios_names.jp, "NOT FOUND"); + + for(;;) + { + draw_cd_menu_options(menu_sel, &bios_names); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel); + if (inp & (BTN_LEFT|BTN_RIGHT)) { // multi choise + if (!me_process(cdopt_entries, CDOPT_ENTRY_COUNT, selected_id, (inp&BTN_RIGHT) ? 1 : 0) && + selected_id == MA_CDOPT_READAHEAD) { + if (inp & BTN_LEFT) { + PicoCDBuffers >>= 1; + if (PicoCDBuffers < 64) PicoCDBuffers = 0; + } else { + if (PicoCDBuffers < 64) PicoCDBuffers = 64; + else PicoCDBuffers <<= 1; + if (PicoCDBuffers > 8*1024) PicoCDBuffers = 8*1024; // 16M + } + } + } + if (inp & BTN_X) { // toggleable options + if (!me_process(cdopt_entries, CDOPT_ENTRY_COUNT, selected_id, 1) && + selected_id == MA_CDOPT_DONE) { + return; + } + switch (selected_id) { // BIOS testers + case MA_CDOPT_TESTBIOS_USA: + if (emu_findBios(4, &bios)) { // test US + strcpy(romFileName, bios); + engineState = PGS_ReloadRom; + return; + } + break; + case MA_CDOPT_TESTBIOS_EUR: + if (emu_findBios(8, &bios)) { // test EU + strcpy(romFileName, bios); + engineState = PGS_ReloadRom; + return; + } + break; + case MA_CDOPT_TESTBIOS_JAP: + if (emu_findBios(1, &bios)) { // test JP + strcpy(romFileName, bios); + engineState = PGS_ReloadRom; + return; + } + break; + default: + break; + } + } + if (inp & BTN_CIRCLE) return; + } +} + + +// --------- advanced options ---------- + +menu_entry opt2_entries[] = +{ + { "Emulate Z80", MB_ONOFF, MA_OPT2_ENABLE_Z80, ¤tConfig.PicoOpt,0x0004, 0, 0, 1 }, + { "Emulate YM2612 (FM)", MB_ONOFF, MA_OPT2_ENABLE_YM2612, ¤tConfig.PicoOpt,0x0001, 0, 0, 1 }, + { "Emulate SN76496 (PSG)", MB_ONOFF, MA_OPT2_ENABLE_SN76496,¤tConfig.PicoOpt,0x0002, 0, 0, 1 }, + { "Double buffering", MB_ONOFF, MA_OPT2_DBLBUFF, ¤tConfig.EmuOpt, 0x8000, 0, 0, 1 }, + { "Wait for V-sync (slow)", MB_ONOFF, MA_OPT2_VSYNC, ¤tConfig.EmuOpt, 0x2000, 0, 0, 1 }, + { "gzip savestates", MB_ONOFF, MA_OPT2_GZIP_STATES, ¤tConfig.EmuOpt, 0x0008, 0, 0, 1 }, + { "Don't save last used ROM", MB_ONOFF, MA_OPT2_NO_LAST_ROM, ¤tConfig.EmuOpt, 0x0020, 0, 0, 1 }, + { "done", MB_NONE, MA_OPT2_DONE, NULL, 0, 0, 0, 1 }, +}; + +#define OPT2_ENTRY_COUNT (sizeof(opt2_entries) / sizeof(opt2_entries[0])) + + +static void draw_amenu_options(int menu_sel) +{ + int tl_x = 80+25, tl_y = 16+50; + + menu_draw_begin(); + + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 252); + + me_draw(opt2_entries, OPT2_ENTRY_COUNT, tl_x, tl_y, NULL, NULL); + + menu_draw_end(); +} + +static void amenu_loop_options(void) +{ + static int menu_sel = 0; + int menu_sel_max; + unsigned long inp = 0; + menu_id selected_id; + + menu_sel_max = me_count_enabled(opt2_entries, OPT2_ENTRY_COUNT) - 1; + + for(;;) + { + draw_amenu_options(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + selected_id = me_index2id(opt2_entries, OPT2_ENTRY_COUNT, menu_sel); + if (inp & (BTN_LEFT|BTN_RIGHT)) { // multi choise + if (!me_process(opt2_entries, OPT2_ENTRY_COUNT, selected_id, (inp&BTN_RIGHT) ? 1 : 0) && + selected_id == MA_OPT2_GAMMA) { + while ((inp = psp_pad_read()) & (BTN_LEFT|BTN_RIGHT)) { + currentConfig.gamma += (inp & BTN_LEFT) ? -1 : 1; + if (currentConfig.gamma < 1) currentConfig.gamma = 1; + if (currentConfig.gamma > 300) currentConfig.gamma = 300; + draw_amenu_options(menu_sel); + psp_msleep(18); + } + } + } + if (inp & BTN_X) { // toggleable options + if (!me_process(opt2_entries, OPT2_ENTRY_COUNT, selected_id, 1) && + selected_id == MA_OPT2_DONE) { + return; + } + } + if (inp & BTN_CIRCLE) return; + } +} + +// -------------- options -------------- + + +menu_entry opt_entries[] = +{ + { NULL, MB_NONE, MA_OPT_RENDERER, NULL, 0, 0, 0, 1 }, + { "Scanline mode (faster)", MB_ONOFF, MA_OPT_INTERLACED, ¤tConfig.EmuOpt, 0x4000, 0, 0, 1 }, + { "Scale low res mode", MB_ONOFF, MA_OPT_SCALING, ¤tConfig.scaling, 0x0001, 0, 3, 1 }, + { "Accurate timing (slower)", MB_ONOFF, MA_OPT_ACC_TIMING, ¤tConfig.PicoOpt, 0x0040, 0, 0, 1 }, + { "Accurate sprites (slower)", MB_ONOFF, MA_OPT_ACC_SPRITES, ¤tConfig.PicoOpt, 0x0080, 0, 0, 1 }, + { "Show FPS", MB_ONOFF, MA_OPT_SHOW_FPS, ¤tConfig.EmuOpt, 0x0002, 0, 0, 1 }, + { NULL, MB_RANGE, MA_OPT_FRAMESKIP, ¤tConfig.Frameskip, 0, -1, 16, 1 }, + { "Enable sound", MB_ONOFF, MA_OPT_ENABLE_SOUND, ¤tConfig.EmuOpt, 0x0004, 0, 0, 1 }, + { NULL, MB_NONE, MA_OPT_SOUND_QUALITY, NULL, 0, 0, 0, 1 }, + { "6 button pad", MB_ONOFF, MA_OPT_6BUTTON_PAD, ¤tConfig.PicoOpt, 0x0020, 0, 0, 1 }, + { NULL, MB_NONE, MA_OPT_REGION, NULL, 0, 0, 0, 1 }, + { "Use SRAM/BRAM savestates", MB_ONOFF, MA_OPT_SRAM_STATES, ¤tConfig.EmuOpt, 0x0001, 0, 0, 1 }, + { NULL, MB_NONE, MA_OPT_CONFIRM_STATES,NULL, 0, 0, 0, 1 }, + { "Save slot", MB_RANGE, MA_OPT_SAVE_SLOT, &state_slot, 0, 0, 9, 1 }, + { "[Sega/Mega CD options]", MB_NONE, MA_OPT_SCD_OPTS, NULL, 0, 0, 0, 1 }, + { "[advanced options]", MB_NONE, MA_OPT_ADV_OPTS, NULL, 0, 0, 0, 1 }, + { NULL, MB_NONE, MA_OPT_SAVECFG, NULL, 0, 0, 0, 1 }, + { "Save cfg for current game only",MB_NONE,MA_OPT_SAVECFG_GAME,NULL, 0, 0, 0, 1 }, + { NULL, MB_NONE, MA_OPT_LOADCFG, NULL, 0, 0, 0, 1 }, +}; + +#define OPT_ENTRY_COUNT (sizeof(opt_entries) / sizeof(opt_entries[0])) + + +static const char *region_name(unsigned int code) +{ + static const char *names[] = { "Auto", " Japan NTSC", " Japan PAL", " USA", " Europe" }; + static const char *names_short[] = { "", " JP", " JP", " US", " EU" }; + int u, i = 0; + if (code) { + code <<= 1; + while((code >>= 1)) i++; + if (i > 4) return "unknown"; + return names[i]; + } else { + static char name[24]; + strcpy(name, "Auto:"); + for (u = 0; u < 3; u++) { + i = 0; code = ((PicoAutoRgnOrder >> u*4) & 0xf) << 1; + while((code >>= 1)) i++; + strcat(name, names_short[i]); + } + return name; + } +} + + +static void menu_opt_cust_draw(const menu_entry *entry, int x, int y, void *param) +{ + char *str, str24[24]; + + switch (entry->id) + { + case MA_OPT_RENDERER: + if (currentConfig.PicoOpt&0x10) + str = " 8bit fast"; + else if (currentConfig.EmuOpt&0x80) + str = "16bit accurate"; + else + str = " 8bit accurate"; + text_out16(x, y, "Renderer: %s", str); + break; + case MA_OPT_FRAMESKIP: + if (currentConfig.Frameskip < 0) + strcpy(str24, "Auto"); + else sprintf(str24, "%i", currentConfig.Frameskip); + text_out16(x, y, "Frameskip %s", str24); + break; + case MA_OPT_SOUND_QUALITY: + str = (currentConfig.PicoOpt&0x08)?"stereo":"mono"; + text_out16(x, y, "Sound Quality: %5iHz %s", currentConfig.PsndRate, str); + break; + case MA_OPT_REGION: + text_out16(x, y, "Region: %s", region_name(currentConfig.PicoRegion)); + break; + case MA_OPT_CONFIRM_STATES: + switch ((currentConfig.EmuOpt >> 9) & 5) { + default: str = "OFF"; break; + case 1: str = "writes"; break; + case 4: str = "loads"; break; + case 5: str = "both"; break; + } + text_out16(x, y, "Confirm savestate %s", str); + break; + case MA_OPT_SAVECFG: + str24[0] = 0; + if (config_slot != 0) sprintf(str24, " (profile: %i)", config_slot); + text_out16(x, y, "Save cfg as default%s", str24); + break; + case MA_OPT_LOADCFG: + text_out16(x, y, "Load cfg from profile %i", config_slot); + break; + default: + lprintf("%s: unimplemented (%i)\n", __FUNCTION__, entry->id); + break; + } +} + + + +static void draw_menu_options(int menu_sel) +{ + int tl_x = 80+25, tl_y = 16+24; + + menu_draw_begin(); + + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 284); + + me_draw(opt_entries, OPT_ENTRY_COUNT, tl_x, tl_y, menu_opt_cust_draw, NULL); + + menu_draw_end(); +} + +static int sndrate_prevnext(int rate, int dir) +{ + int i, rates[] = { 11025, 22050, 44100 }; + + for (i = 0; i < 5; i++) + if (rates[i] == rate) break; + + i += dir ? 1 : -1; + if (i > 2) return dir ? 44100 : 22050; + if (i < 0) return dir ? 22050 : 11025; + return rates[i]; +} + +static void region_prevnext(int right) +{ + // jp_ntsc=1, jp_pal=2, usa=4, eu=8 + static int rgn_orders[] = { 0x148, 0x184, 0x814, 0x418, 0x841, 0x481 }; + int i; + if (right) { + if (!currentConfig.PicoRegion) { + for (i = 0; i < 6; i++) + if (rgn_orders[i] == PicoAutoRgnOrder) break; + if (i < 5) PicoAutoRgnOrder = rgn_orders[i+1]; + else currentConfig.PicoRegion=1; + } + else currentConfig.PicoRegion<<=1; + if (currentConfig.PicoRegion > 8) currentConfig.PicoRegion = 8; + } else { + if (!currentConfig.PicoRegion) { + for (i = 0; i < 6; i++) + if (rgn_orders[i] == PicoAutoRgnOrder) break; + if (i > 0) PicoAutoRgnOrder = rgn_orders[i-1]; + } + else currentConfig.PicoRegion>>=1; + } +} + +static void menu_options_save(void) +{ + PicoOpt = currentConfig.PicoOpt; + PsndRate = currentConfig.PsndRate; + PicoRegionOverride = currentConfig.PicoRegion; + if (!(PicoOpt & 0x20)) { + // unbind XYZ MODE, just in case + unbind_action(0xf00); + } +} + +static int menu_loop_options(void) +{ + static int menu_sel = 0; + int menu_sel_max, ret; + unsigned long inp = 0; + menu_id selected_id; + + currentConfig.PicoOpt = PicoOpt; + currentConfig.PsndRate = PsndRate; + currentConfig.PicoRegion = PicoRegionOverride; + + me_enable(opt_entries, OPT_ENTRY_COUNT, MA_OPT_SAVECFG_GAME, rom_data != NULL); + me_enable(opt_entries, OPT_ENTRY_COUNT, MA_OPT_LOADCFG, config_slot != config_slot_current); + menu_sel_max = me_count_enabled(opt_entries, OPT_ENTRY_COUNT) - 1; + if (menu_sel > menu_sel_max) menu_sel = menu_sel_max; + + while (1) + { + draw_menu_options(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE); + if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + selected_id = me_index2id(opt_entries, OPT_ENTRY_COUNT, menu_sel); + if (inp & (BTN_LEFT|BTN_RIGHT)) { // multi choise + if (!me_process(opt_entries, OPT_ENTRY_COUNT, selected_id, (inp&BTN_RIGHT) ? 1 : 0)) { + switch (selected_id) { + case MA_OPT_RENDERER: + if (inp & BTN_LEFT) { + if ((currentConfig.PicoOpt&0x10) || !(currentConfig.EmuOpt &0x80)) { + currentConfig.PicoOpt&= ~0x10; + currentConfig.EmuOpt |= 0x80; + } + } else { + if (!(currentConfig.PicoOpt&0x10) || (currentConfig.EmuOpt &0x80)) { + currentConfig.PicoOpt|= 0x10; + currentConfig.EmuOpt &= ~0x80; + } + } + break; + case MA_OPT_SOUND_QUALITY: + if ((inp & BTN_RIGHT) && currentConfig.PsndRate == 44100 && + !(currentConfig.PicoOpt&0x08)) + { + currentConfig.PsndRate = 11025; + currentConfig.PicoOpt |= 8; + } else if ((inp & BTN_LEFT) && currentConfig.PsndRate == 11025 && + (currentConfig.PicoOpt&0x08) && !(PicoMCD&1)) + { + currentConfig.PsndRate = 44100; + currentConfig.PicoOpt &= ~8; + } else + currentConfig.PsndRate = sndrate_prevnext(currentConfig.PsndRate, inp & BTN_RIGHT); + break; + case MA_OPT_REGION: + region_prevnext(inp & BTN_RIGHT); + break; + case MA_OPT_CONFIRM_STATES: { + int n = ((currentConfig.EmuOpt>>9)&1) | ((currentConfig.EmuOpt>>10)&2); + n += (inp & BTN_LEFT) ? -1 : 1; + if (n < 0) n = 0; else if (n > 3) n = 3; + n |= n << 1; n &= ~2; + currentConfig.EmuOpt &= ~0xa00; + currentConfig.EmuOpt |= n << 9; + break; + } + case MA_OPT_SAVE_SLOT: + if (inp & BTN_RIGHT) { + state_slot++; if (state_slot > 9) state_slot = 0; + } else {state_slot--; if (state_slot < 0) state_slot = 9; + } + break; + case MA_OPT_SAVECFG: + case MA_OPT_SAVECFG_GAME: + case MA_OPT_LOADCFG: + config_slot += (inp&BTN_RIGHT) ? 1 : -1; + if (config_slot > 9) config_slot = 0; + if (config_slot < 0) config_slot = 9; + me_enable(opt_entries, OPT_ENTRY_COUNT, MA_OPT_LOADCFG, config_slot != config_slot_current); + menu_sel_max = me_count_enabled(opt_entries, OPT_ENTRY_COUNT) - 1; + if (menu_sel > menu_sel_max) menu_sel = menu_sel_max; + break; + default: + //lprintf("%s: something unknown selected (%i)\n", __FUNCTION__, selected_id); + break; + } + } + } + if (inp & BTN_X) { + if (!me_process(opt_entries, OPT_ENTRY_COUNT, selected_id, 1)) + { + switch (selected_id) + { + case MA_OPT_SCD_OPTS: + cd_menu_loop_options(); + if (engineState == PGS_ReloadRom) + return 0; // test BIOS + break; + case MA_OPT_ADV_OPTS: + amenu_loop_options(); + break; + case MA_OPT_SAVECFG: // done (update and write) + menu_options_save(); + if (emu_WriteConfig(0)) strcpy(menuErrorMsg, "config saved"); + else strcpy(menuErrorMsg, "failed to write config"); + return 1; + case MA_OPT_SAVECFG_GAME: // done (update and write for current game) + menu_options_save(); + if (emu_WriteConfig(1)) strcpy(menuErrorMsg, "config saved"); + else strcpy(menuErrorMsg, "failed to write config"); + return 1; + case MA_OPT_LOADCFG: + ret = emu_ReadConfig(1, 1); + if (!ret) ret = emu_ReadConfig(0, 1); + if (ret) strcpy(menuErrorMsg, "config loaded"); + else strcpy(menuErrorMsg, "failed to load config"); + return 1; + default: + //lprintf("%s: something unknown selected (%i)\n", __FUNCTION__, selected_id); + break; + } + } + } + if(inp & BTN_CIRCLE) { + menu_options_save(); + return 0; // done (update, no write) + } + } +} + +// -------------- credits -------------- + +static void draw_menu_credits(void) +{ + int tl_x = 80+15, tl_y = 16+64, y; + menu_draw_begin(); + + text_out16(tl_x, 16+20, "PicoDrive v" VERSION " (c) notaz, 2006,2007"); + + y = tl_y; + text_out16(tl_x, y, "Credits:"); + text_out16(tl_x, (y+=10), "Dave: base code of PicoDrive"); + text_out16(tl_x, (y+=10), "MAME devs: YM2612 and SN76496 cores"); + text_out16(tl_x, (y+=10), "Charles MacDonald: Genesis hw docs"); + text_out16(tl_x, (y+=10), "Stephane Dallongeville:"); + text_out16(tl_x, (y+=10), " opensource Gens"); + text_out16(tl_x, (y+=10), "Haze: Genesis hw info"); + text_out16(tl_x, (y+=10), "ketchupgun: skin design"); + + menu_draw_end(); +} + + +// -------------- root menu -------------- + +menu_entry main_entries[] = +{ + { "Resume game", MB_NONE, MA_MAIN_RESUME_GAME, NULL, 0, 0, 0, 0 }, + { "Save State", MB_NONE, MA_MAIN_SAVE_STATE, NULL, 0, 0, 0, 0 }, + { "Load State", MB_NONE, MA_MAIN_LOAD_STATE, NULL, 0, 0, 0, 0 }, + { "Reset game", MB_NONE, MA_MAIN_RESET_GAME, NULL, 0, 0, 0, 0 }, + { "Load new ROM/ISO", MB_NONE, MA_MAIN_LOAD_ROM, NULL, 0, 0, 0, 1 }, + { "Change options", MB_NONE, MA_MAIN_OPTIONS, NULL, 0, 0, 0, 1 }, + { "Configure controls", MB_NONE, MA_MAIN_CONTROLS, NULL, 0, 0, 0, 1 }, + { "Credits", MB_NONE, MA_MAIN_CREDITS, NULL, 0, 0, 0, 1 }, + { "Patches / GameGenie",MB_NONE, MA_MAIN_PATCHES, NULL, 0, 0, 0, 0 }, + { "Exit", MB_NONE, MA_MAIN_EXIT, NULL, 0, 0, 0, 1 } +}; + +#define MAIN_ENTRY_COUNT (sizeof(main_entries) / sizeof(main_entries[0])) + +static void draw_menu_root(int menu_sel) +{ + const int tl_x = 80+70, tl_y = 16+70; + + menu_draw_begin(); + + text_out16(tl_x, 16+20, "PicoDrive v" VERSION); + + menu_draw_selection(tl_x - 16, tl_y + menu_sel*10, 146); + + me_draw(main_entries, MAIN_ENTRY_COUNT, tl_x, tl_y, NULL, NULL); + + // error + if (menuErrorMsg[0]) { + // memset((char *)menu_screen + 321*224*2, 0, 321*16*2); + text_out16(5, 258, menuErrorMsg); + } + menu_draw_end(); +} + + +static void menu_loop_root(void) +{ + static int menu_sel = 0; + int ret, menu_sel_max; + unsigned long inp = 0; + + me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_RESUME_GAME, rom_data != NULL); + me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_SAVE_STATE, rom_data != NULL); + me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_LOAD_STATE, rom_data != NULL); + me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_RESET_GAME, rom_data != NULL); + me_enable(main_entries, MAIN_ENTRY_COUNT, MA_MAIN_PATCHES, PicoPatches != NULL); + + menu_sel_max = me_count_enabled(main_entries, MAIN_ENTRY_COUNT) - 1; + if (menu_sel > menu_sel_max) menu_sel = menu_sel_max; + + /* make sure action buttons are not pressed on entering menu */ + draw_menu_root(menu_sel); + + while (psp_pad_read() & (BTN_X|BTN_CIRCLE|BTN_SELECT)) psp_msleep(50); + + for (;;) + { + draw_menu_root(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X|BTN_CIRCLE|BTN_SELECT|BTN_L|BTN_R); + if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if((inp & (BTN_L|BTN_R)) == (BTN_L|BTN_R)) debug_menu_loop(); + if( inp & (BTN_SELECT|BTN_CIRCLE)) { + if (rom_data) { + while (psp_pad_read() & (BTN_SELECT|BTN_CIRCLE)) psp_msleep(50); // wait until released + engineState = PGS_Running; + break; + } + } + if(inp & BTN_X) { + switch (me_index2id(main_entries, MAIN_ENTRY_COUNT, menu_sel)) + { + case MA_MAIN_RESUME_GAME: + if (rom_data) { + while (psp_pad_read() & BTN_X) psp_msleep(50); + engineState = PGS_Running; + return; + } + break; + case MA_MAIN_SAVE_STATE: + if (rom_data) { + if(savestate_menu_loop(0)) + continue; + engineState = PGS_Running; + return; + } + break; + case MA_MAIN_LOAD_STATE: + if (rom_data) { + if(savestate_menu_loop(1)) + continue; + engineState = PGS_Running; + return; + } + break; + case MA_MAIN_RESET_GAME: + if (rom_data) { + emu_ResetGame(); + engineState = PGS_Running; + return; + } + break; + case MA_MAIN_LOAD_ROM: + { + char curr_path[PATH_MAX], *selfname; + FILE *tstf; + if ( (tstf = fopen(currentConfig.lastRomFile, "rb")) ) + { + fclose(tstf); + strcpy(curr_path, currentConfig.lastRomFile); + } + else + getcwd(curr_path, PATH_MAX); + selfname = romsel_loop(curr_path); + if (selfname) { + lprintf("selected file: %s\n", selfname); + engineState = PGS_ReloadRom; + return; + } + break; + } + case MA_MAIN_OPTIONS: + ret = menu_loop_options(); + if (ret == 1) continue; // status update + if (engineState == PGS_ReloadRom) + return; // BIOS test + break; + case MA_MAIN_CONTROLS: + kc_sel_loop(); + break; + case MA_MAIN_CREDITS: + draw_menu_credits(); + psp_msleep(500); + inp = wait_for_input(BTN_X|BTN_CIRCLE); + break; + case MA_MAIN_EXIT: + engineState = PGS_Quit; + return; + case MA_MAIN_PATCHES: + if (rom_data && PicoPatches) { + patches_menu_loop(); + PicoPatchApply(); + strcpy(menuErrorMsg, "Patches applied"); + continue; + } + break; + default: + lprintf("%s: something unknown selected\n", __FUNCTION__); + break; + } + } + menuErrorMsg[0] = 0; // clear error msg + } +} + +// warning: alignment +static void menu_darken_bg(void *dst, const void *src, int pixels, int darker) +{ + unsigned int *dest = dst; + const unsigned int *srce = src; + pixels /= 2; + if (darker) + { + while (pixels--) + { + unsigned int p = *srce++; + *dest++ = ((p&0xf79ef79e)>>1) - ((p&0xc618c618)>>3); + } + } + else + { + while (pixels--) + { + unsigned int p = *srce++; + *dest++ = (p&0xf79ef79e)>>1; + } + } +} + +static void menu_prepare_bg(int use_game_bg) +{ + memset(bg_buffer, 0, sizeof(bg_buffer)); + + if (use_game_bg) + { + // darken the active framebuffer + /* + memset(bg_buffer, 0, 321*8*2); + menu_darken_bg(bg_buffer + 321*8*2, (char *)giz_screen + 321*8*2, 321*224, 1); + memset(bg_buffer + 321*232*2, 0, 321*8*2); + */ + } + else + { + // should really only happen once, on startup.. + readpng(bg_buffer, "skin/background.png", READPNG_BG); + } +} + +static void menu_gfx_prepare(void) +{ + menu_prepare_bg(rom_data != NULL); + + menu_draw_begin(); + menu_draw_end(); +} + + +void menu_loop(void) +{ + menu_gfx_prepare(); + + menu_loop_root(); + + menuErrorMsg[0] = 0; +} + + +// --------- CD tray close menu ---------- + +static void draw_menu_tray(int menu_sel) +{ + int tl_x = 70, tl_y = 90, y; + + menu_draw_begin(); + + text_out16(tl_x, 20, "The unit is about to"); + text_out16(tl_x, 30, "close the CD tray."); + + y = tl_y; + text_out16(tl_x, y, "Load new CD image"); + text_out16(tl_x, (y+=10), "Insert nothing"); + + // draw cursor + text_out16(tl_x - 16, tl_y + menu_sel*10, ">"); + // error + if (menuErrorMsg[0]) text_out16(5, 226, menuErrorMsg); + menu_draw_end(); +} + + +int menu_loop_tray(void) +{ + int menu_sel = 0, menu_sel_max = 1; + unsigned long inp = 0; + char curr_path[PATH_MAX], *selfname; + FILE *tstf; + + menu_gfx_prepare(); + + if ( (tstf = fopen(currentConfig.lastRomFile, "rb")) ) + { + fclose(tstf); + strcpy(curr_path, currentConfig.lastRomFile); + } + else + { + getcwd(curr_path, PATH_MAX); + } + + /* make sure action buttons are not pressed on entering menu */ + draw_menu_tray(menu_sel); + while (psp_pad_read() & BTN_X) psp_msleep(50); + + for (;;) + { + draw_menu_tray(menu_sel); + inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X); + if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } + if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } + if(inp & BTN_X ) { + switch (menu_sel) { + case 0: // select image + selfname = romsel_loop(curr_path); + if (selfname) { + int ret = -1, cd_type; + cd_type = emu_cdCheck(NULL); + if (cd_type > 0) + ret = Insert_CD(romFileName, cd_type == 2); + if (ret != 0) { + sprintf(menuErrorMsg, "Load failed, invalid CD image?"); + lprintf("%s\n", menuErrorMsg); + continue; + } + engineState = PGS_RestartRun; + return 1; + } + break; + case 1: // insert nothing + engineState = PGS_RestartRun; + return 0; + } + } + menuErrorMsg[0] = 0; // clear error msg + } +} + + diff --git a/platform/psp/menu.h b/platform/psp/menu.h new file mode 100644 index 0000000..fa6c90c --- /dev/null +++ b/platform/psp/menu.h @@ -0,0 +1,13 @@ +// (c) Copyright 2006,2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +void menu_loop(void); +int menu_loop_tray(void); +void menu_romload_prepare(const char *rom_name); +void menu_romload_end(void); + + +#define CONFIGURABLE_KEYS (BTN_UP|BTN_LEFT|BTN_RIGHT|BTN_DOWN|BTN_L|BTN_R|BTN_TRIANGLE|BTN_CIRCLE|BTN_X|BTN_SQUARE|BTN_START|BTN_NOTE) + diff --git a/platform/psp/mp3.c b/platform/psp/mp3.c new file mode 100644 index 0000000..ac00660 --- /dev/null +++ b/platform/psp/mp3.c @@ -0,0 +1,20 @@ +#include + +int mp3_get_bitrate(FILE *f, int size) +{ + return 0; +} + +void mp3_start_play(FILE *f, int pos) +{ +} + +int mp3_get_offset(void) // 0-1023 +{ + return 0; +} + +void mp3_update(int *buffer, int length, int stereo) +{ +} + diff --git a/platform/psp/port_config.h b/platform/psp/port_config.h new file mode 100644 index 0000000..dcd5032 --- /dev/null +++ b/platform/psp/port_config.h @@ -0,0 +1,24 @@ +// port specific settings + +#ifndef PORT_CONFIG_H +#define PORT_CONFIG_H + +#define CPU_CALL + +// draw.c +#define OVERRIDE_HIGHCOL 0 + +// draw2.c +#define START_ROW 0 // which row of tiles to start rendering at? +#define END_ROW 28 // ..end + +// pico.c +#define CAN_HANDLE_240_LINES 1 + +// logging emu events +#define EL_LOGMASK 0 // (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO) // xffff + +//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__) +#define dprintf(x...) + +#endif //PORT_CONFIG_H diff --git a/platform/psp/psp.c b/platform/psp/psp.c new file mode 100644 index 0000000..4bc1020 --- /dev/null +++ b/platform/psp/psp.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#include "psp.h" +#include "../common/lprintf.h" + +PSP_MODULE_INFO("PicoDrive", 0, 1, 34); + +void *psp_screen = PSP_VRAM_BASE0; +static int current_screen = 0; /* front bufer */ + + +/* Exit callback */ +static int exit_callback(int arg1, int arg2, void *common) +{ + sceKernelExitGame(); + return 0; +} + +/* Callback thread */ +static int callback_thread(SceSize args, void *argp) +{ + int cbid; + + lprintf("callback_thread started with id %i\n", sceKernelGetThreadId()); + + cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); + sceKernelRegisterExitCallback(cbid); + + sceKernelSleepThreadCB(); + + return 0; +} + +void psp_init(void) +{ + int thid; + + lprintf("entered psp_init, threadId %i\n", sceKernelGetThreadId()); + + thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); + if (thid >= 0) + { + sceKernelStartThread(thid, 0, 0); + } + + /* video */ + sceDisplaySetMode(0, 480, 272); + sceDisplaySetFrameBuf(PSP_VRAM_BASE1, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); + current_screen = 1; + psp_screen = PSP_VRAM_BASE0; + + /* gu */ + sceGuInit(); + + /* input */ + sceCtrlSetSamplingCycle(0); + sceCtrlSetSamplingMode(0); +} + +void psp_finish(void) +{ + sceGuTerm(); + + //sceKernelSleepThread(); + sceKernelExitGame(); +} + +void psp_video_flip(void) +{ + sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); + current_screen ^= 1; + psp_screen = current_screen ? PSP_VRAM_BASE1 : PSP_VRAM_BASE0; +} + +void psp_video_switch_to_single(void) +{ + psp_screen = PSP_VRAM_BASE0; + sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); + current_screen = 0; +} + +void psp_msleep(int ms) +{ + sceKernelDelayThread(ms * 1000); +} + +unsigned int psp_pad_read(void) +{ + SceCtrlData pad; + sceCtrlReadBufferPositive(&pad, 1); + + return pad.Buttons; +} + diff --git a/platform/psp/psp.h b/platform/psp/psp.h new file mode 100644 index 0000000..cece8cf --- /dev/null +++ b/platform/psp/psp.h @@ -0,0 +1,32 @@ +#include + +void psp_init(void); +void psp_finish(void); + +void psp_msleep(int ms); + +#define PSP_VRAM_BASE0 ((void *) 0x44000000) +#define PSP_VRAM_BASE1 ((void *) 0x44044000) + +void psp_video_switch_to_single(void); +void psp_video_flip(void); +extern void *psp_screen; + +unsigned int psp_pad_read(void); + + +/* shorter btn names */ +#define BTN_UP PSP_CTRL_UP +#define BTN_LEFT PSP_CTRL_LEFT +#define BTN_RIGHT PSP_CTRL_RIGHT +#define BTN_DOWN PSP_CTRL_DOWN +#define BTN_L PSP_CTRL_LTRIGGER +#define BTN_R PSP_CTRL_RTRIGGER +#define BTN_TRIANGLE PSP_CTRL_TRIANGLE +#define BTN_CIRCLE PSP_CTRL_CIRCLE +#define BTN_X PSP_CTRL_CROSS +#define BTN_SQUARE PSP_CTRL_SQUARE +#define BTN_SELECT PSP_CTRL_SELECT +#define BTN_START PSP_CTRL_START +#define BTN_NOTE PSP_CTRL_NOTE + diff --git a/platform/psp/skin/background.png b/platform/psp/skin/background.png new file mode 100644 index 0000000000000000000000000000000000000000..cb6a3779fef0186c808f95631f02854dd328bb72 GIT binary patch literal 84002 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%0D&0n^)N%R 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 HXcO^2qn9ob literal 0 HcmV?d00001 diff --git a/platform/psp/skin/font.png b/platform/psp/skin/font.png new file mode 100644 index 0000000000000000000000000000000000000000..c526a086ddb3e2ac97f4966004884071552bbc41 GIT binary patch literal 3185 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 XqVG$syRXKc00000NkvXXu0mjfg_gw( literal 0 HcmV?d00001 diff --git a/platform/psp/skin/readme.txt b/platform/psp/skin/readme.txt new file mode 100644 index 0000000..dd83963 --- /dev/null +++ b/platform/psp/skin/readme.txt @@ -0,0 +1,8 @@ +The skin images can be customized, but there are several limitations: + +background.png - must be 320x240 image with 24bit RGB colors. +font.png - must be 128x160 8bit grayscale image. +selector.png - must be 8x10 8bit grayscale image. + +Font and selector colors can be changed by editing skin.txt. + diff --git a/platform/psp/skin/selector.png b/platform/psp/skin/selector.png new file mode 100644 index 0000000000000000000000000000000000000000..5062cc23b08bd35ebbe7c5dca0c10ae479103c56 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^96-zkA{f@Jafks@+9j?LCC){ui6xo&c?uz!xv31^ zB??By3PI@w3PuJ7<_d-;Rt6SUMrI1y20;F2g|&S^ZR{nUzOL-oImEd+jkE=q{{RYc z7I;J!Gca%qfiUBxyLEqnf-LEdzK#qG8~eHcB(ehev7RoDAr-fh{~RxP%DLW-pZWCr zo!jgFC7ivOXlD2K_3`iDpYNF=YFG3B+uQT$vD5tH>;L@w{QSMX+Eab|`oF)G{8J%^uZPiw_?7(a*>