From: notaz Date: Sat, 22 Sep 2007 22:53:18 +0000 (+0000) Subject: giz port, restructuring X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f013066e974c7d35b818a6fca43a9deba1ce5c3e;p=libpicofe.git giz port, restructuring git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@257 be3aeb3a-fb24-0410-a615-afba39da0efa --- diff --git a/common/emu.c b/common/emu.c new file mode 100644 index 0000000..99fca49 --- /dev/null +++ b/common/emu.c @@ -0,0 +1,775 @@ +// (c) Copyright 2006-2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +#include +#include +#include // tolower +#ifndef NO_SYNC +#include +#endif + +#include "emu.h" +#include "menu.h" +#include "fonts.h" +#include "lprintf.h" + +#include +#include +#include + +#if defined(__GP2X__) + #include "../gp2x/gp2x.h" + #define SCREEN_WIDTH 320 + #define SCREEN_BUFFER gp2x_screen +#elif defined(__GIZ__) + #include "../gizmondo/giz.h" + #define SCREEN_WIDTH 321 + #define SCREEN_BUFFER giz_screen // ? +#endif + +char *PicoConfigFile = "picoconfig.bin"; +currentConfig_t currentConfig; +unsigned char *rom_data = NULL; +char noticeMsg[64]; +int state_slot = 0; +int config_slot = 0, config_slot_current = 0; + +unsigned char *movie_data = NULL; +static int movie_size = 0; + +// provided by platform code: +extern char romFileName[]; +extern void emu_noticeMsgUpdated(void); +extern void emu_getMainDir(char *dst, int len); +extern void emu_setDefaultConfig(void); +extern void menu_romload_prepare(const char *rom_name); +extern void menu_romload_end(void); + + +// utilities +static void strlwr_(char* string) +{ + while ( (*string++ = (char)tolower(*string)) ); +} + +static int try_rfn_cut(void) +{ + FILE *tmp; + char *p; + + p = romFileName + strlen(romFileName) - 1; + for (; p > romFileName; p--) + if (*p == '.') break; + *p = 0; + + if((tmp = fopen(romFileName, "rb"))) { + fclose(tmp); + return 1; + } + return 0; +} + +static void get_ext(char *file, char *ext) +{ + char *p; + + p = file + strlen(file) - 4; + if (p < file) p = file; + strncpy(ext, p, 4); + ext[4] = 0; + strlwr_(ext); +} + +char *biosfiles_us[] = { "us_scd2_9306", "SegaCDBIOS9303", "us_scd1_9210" }; +char *biosfiles_eu[] = { "eu_mcd2_9306", "eu_mcd2_9303", "eu_mcd1_9210" }; +char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" }; + +int emu_findBios(int region, char **bios_file) +{ + static char bios_path[1024]; + int i, count; + char **files; + FILE *f = NULL; + + if (region == 4) { // US + files = biosfiles_us; + count = sizeof(biosfiles_us) / sizeof(char *); + } else if (region == 8) { // EU + files = biosfiles_eu; + count = sizeof(biosfiles_eu) / sizeof(char *); + } else if (region == 1 || region == 2) { + files = biosfiles_jp; + count = sizeof(biosfiles_jp) / sizeof(char *); + } else { + return 0; + } + + for (i = 0; i < count; i++) + { + emu_getMainDir(bios_path, sizeof(bios_path)); + strcat(bios_path, files[i]); + strcat(bios_path, ".bin"); + f = fopen(bios_path, "rb"); + if (f) break; + + bios_path[strlen(bios_path) - 4] = 0; + strcat(bios_path, ".zip"); + f = fopen(bios_path, "rb"); + if (f) break; + } + + if (f) { + lprintf("using bios: %s\n", bios_path); + fclose(f); + if (bios_file) *bios_file = bios_path; + return 1; + } else { + sprintf(menuErrorMsg, "no %s BIOS files found, read docs", + region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); + lprintf("%s\n", menuErrorMsg); + return 0; + } +} + +/* checks if romFileName points to valid MegaCD image + * if so, checks for suitable BIOS */ +int emu_cdCheck(int *pregion) +{ + unsigned char buf[32]; + pm_file *cd_f; + int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe + + cd_f = pm_open(romFileName); + if (!cd_f) return 0; // let the upper level handle this + + if (pm_read(buf, 32, cd_f) != 32) { + pm_close(cd_f); + return 0; + } + + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) + if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) + if (type == 0) { + pm_close(cd_f); + return 0; + } + + /* it seems we have a CD image here. Try to detect region now.. */ + pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); + pm_read(buf, 1, cd_f); + pm_close(cd_f); + + if (buf[0] == 0x64) region = 8; // EU + if (buf[0] == 0xa1) region = 1; // JAP + + lprintf("detected %s Sega/Mega CD image with %s region\n", + type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); + + if (pregion != NULL) *pregion = region; + + return type; +} + +int emu_ReloadRom(void) +{ + unsigned int rom_size = 0; + char *used_rom_name = romFileName; + char ext[5]; + pm_file *rom; + int ret, cd_state, cd_region, cfg_loaded = 0; + + lprintf("emu_ReloadRom(%s)\n", romFileName); + + get_ext(romFileName, ext); + + // detect wrong extensions + if(!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz + sprintf(menuErrorMsg, "Not a ROM selected."); + return 0; + } + + PicoPatchUnload(); + + // check for movie file + if(movie_data) { + free(movie_data); + movie_data = 0; + } + if(!strcmp(ext, ".gmv")) { + // check for both gmv and rom + int dummy; + FILE *movie_file = fopen(romFileName, "rb"); + if(!movie_file) { + sprintf(menuErrorMsg, "Failed to open movie."); + return 0; + } + fseek(movie_file, 0, SEEK_END); + movie_size = ftell(movie_file); + fseek(movie_file, 0, SEEK_SET); + if(movie_size < 64+3) { + sprintf(menuErrorMsg, "Invalid GMV file."); + fclose(movie_file); + return 0; + } + movie_data = malloc(movie_size); + if(movie_data == NULL) { + sprintf(menuErrorMsg, "low memory."); + fclose(movie_file); + return 0; + } + fread(movie_data, 1, movie_size, movie_file); + fclose(movie_file); + if (strncmp((char *)movie_data, "Gens Movie TEST", 15) != 0) { + sprintf(menuErrorMsg, "Invalid GMV file."); + return 0; + } + dummy = try_rfn_cut() || try_rfn_cut(); + if (!dummy) { + sprintf(menuErrorMsg, "Could't find a ROM for movie."); + return 0; + } + get_ext(romFileName, ext); + } + else if (!strcmp(ext, ".pat")) { + int dummy; + PicoPatchLoad(romFileName); + dummy = try_rfn_cut() || try_rfn_cut(); + if (!dummy) { + sprintf(menuErrorMsg, "Could't find a ROM to patch."); + return 0; + } + get_ext(romFileName, ext); + } + + if ((PicoMCD & 1) && Pico_mcd != NULL) + Stop_CD(); + + // check for MegaCD image + cd_state = emu_cdCheck(&cd_region); + if (cd_state > 0) + { + // valid CD image, check for BIOS.. + + // we need to have config loaded at this point + ret = emu_ReadConfig(1, 1); + if (!ret) emu_ReadConfig(0, 1); + cfg_loaded = 1; + + if (PicoRegionOverride) { + cd_region = PicoRegionOverride; + lprintf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA"); + } + if (!emu_findBios(cd_region, &used_rom_name)) { + // bios_help() ? + return 0; + } + + PicoMCD |= 1; + get_ext(used_rom_name, ext); + } + else + { + if (PicoMCD & 1) Stop_CD(); + PicoMCD &= ~1; + } + + rom = pm_open(used_rom_name); + if(!rom) { + sprintf(menuErrorMsg, "Failed to open rom."); + return 0; + } + + menu_romload_prepare(used_rom_name); + + if(rom_data) { + free(rom_data); + rom_data = 0; + rom_size = 0; + } + + if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { + sprintf(menuErrorMsg, "PicoCartLoad() failed."); + lprintf("%s\n", menuErrorMsg); + pm_close(rom); + menu_romload_end(); + return 0; + } + pm_close(rom); + menu_romload_end(); + + // detect wrong files (Pico crashes on very small files), also see if ROM EP is good + if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || + ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) { + if (rom_data) free(rom_data); + rom_data = 0; + sprintf(menuErrorMsg, "Not a ROM selected."); + return 0; + } + + // load config for this ROM (do this before insert to get correct region) + if (!cfg_loaded) { + ret = emu_ReadConfig(1, 1); + if (!ret) emu_ReadConfig(0, 1); + } + + lprintf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); + if(PicoCartInsert(rom_data, rom_size)) { + sprintf(menuErrorMsg, "Failed to load ROM."); + return 0; + } + + Pico.m.frame_count = 0; + + // insert CD if it was detected + if (cd_state > 0) { + ret = Insert_CD(romFileName, cd_state == 2); + if (ret != 0) { + sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?"); + lprintf("%s\n", menuErrorMsg); + return 0; + } + } + + // emu_ReadConfig() might have messed currentConfig.lastRomFile + strncpy(currentConfig.lastRomFile, romFileName, sizeof(currentConfig.lastRomFile)-1); + currentConfig.lastRomFile[sizeof(currentConfig.lastRomFile)-1] = 0; + + if (PicoPatches) { + PicoPatchPrepare(); + PicoPatchApply(); + } + + // additional movie stuff + if (movie_data) { + if(movie_data[0x14] == '6') + PicoOpt |= 0x20; // 6 button pad + else PicoOpt &= ~0x20; + PicoOpt |= 0x10040; // accurate timing, no VDP fifo timing + if(movie_data[0xF] >= 'A') { + if(movie_data[0x16] & 0x80) { + PicoRegionOverride = 8; + } else { + PicoRegionOverride = 4; + } + PicoReset(0); + // TODO: bits 6 & 5 + } + movie_data[0x18+30] = 0; + sprintf(noticeMsg, "MOVIE: %s", (char *) &movie_data[0x18]); + } + else + { + PicoOpt &= ~0x10000; + if(Pico.m.pal) { + strcpy(noticeMsg, "PAL SYSTEM / 50 FPS"); + } else { + strcpy(noticeMsg, "NTSC SYSTEM / 60 FPS"); + } + } + emu_noticeMsgUpdated(); + + // load SRAM for this ROM + if(currentConfig.EmuOpt & 1) + emu_SaveLoadGame(1, 1); + + return 1; +} + + +static void romfname_ext(char *dst, const char *prefix, const char *ext) +{ + char *p; + int prefix_len = 0; + + // make save filename + for (p = romFileName+strlen(romFileName)-1; p >= romFileName && *p != '/'; p--); p++; + *dst = 0; + if (prefix) { + strcpy(dst, prefix); + prefix_len = strlen(prefix); + } + strncpy(dst + prefix_len, p, 511-prefix_len); + dst[511-8] = 0; + if (dst[strlen(dst)-4] == '.') dst[strlen(dst)-4] = 0; + if (ext) strcat(dst, ext); +} + + +int emu_ReadConfig(int game, int no_defaults) +{ + FILE *f; + char cfg[512], extbuf[16]; + int bread = 0; + + if (!game) + { + if (!no_defaults) + { + emu_setDefaultConfig(); + } + strncpy(cfg, PicoConfigFile, 511); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } + cfg[511] = 0; + } else { + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); + f = fopen(cfg, "rb"); + if (!f) romfname_ext(cfg, NULL, ".pbcfg"); + else fclose(f); + } + + lprintf("emu_ReadConfig: %s ", cfg); + f = fopen(cfg, "rb"); + if (f) { + bread = fread(¤tConfig, 1, sizeof(currentConfig), f); + fclose(f); + } + lprintf(bread > 0 ? "(ok)\n" : "(failed)\n"); + + PicoOpt = currentConfig.PicoOpt; + PsndRate = currentConfig.PsndRate; + PicoRegionOverride = currentConfig.PicoRegion; + PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder; + PicoCDBuffers = currentConfig.PicoCDBuffers; + //scaling_update(); + // some sanity checks + if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; + if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; + if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; + // if volume keys are unbound, bind them to volume control + if (!currentConfig.KeyBinds[23] && !currentConfig.KeyBinds[22]) { + currentConfig.KeyBinds[23] = 1<<29; // vol up + currentConfig.KeyBinds[22] = 1<<30; // vol down + } + + if (bread > 0) config_slot_current = config_slot; + return (bread > 0); // == sizeof(currentConfig)); +} + + +int emu_WriteConfig(int game) +{ + FILE *f; + char cfg[512], extbuf[16]; + int bwrite = 0; + + if (!game) + { + strncpy(cfg, PicoConfigFile, 511); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } + cfg[511] = 0; + } else { + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); + } + + lprintf("emu_WriteConfig: %s ", cfg); + f = fopen(cfg, "wb"); + if (f) { + currentConfig.PicoOpt = PicoOpt; + currentConfig.PsndRate = PsndRate; + currentConfig.PicoRegion = PicoRegionOverride; + currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder; + currentConfig.PicoCDBuffers = PicoCDBuffers; + bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f); + fflush(f); + fclose(f); +#ifndef NO_SYNC + sync(); +#endif + } + lprintf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); + + if (bwrite == sizeof(currentConfig)) config_slot_current = config_slot; + return (bwrite == sizeof(currentConfig)); +} + + +void emu_textOut8(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned char *screen = (unsigned char *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + + /* always using built-in font */ + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if (fd&0x80) screen[l*SCREEN_WIDTH+0]=0xf0; + if (fd&0x40) screen[l*SCREEN_WIDTH+1]=0xf0; + if (fd&0x20) screen[l*SCREEN_WIDTH+2]=0xf0; + if (fd&0x10) screen[l*SCREEN_WIDTH+3]=0xf0; + if (fd&0x08) screen[l*SCREEN_WIDTH+4]=0xf0; + if (fd&0x04) screen[l*SCREEN_WIDTH+5]=0xf0; + if (fd&0x02) screen[l*SCREEN_WIDTH+6]=0xf0; + if (fd&0x01) screen[l*SCREEN_WIDTH+7]=0xf0; + } + screen += 8; + } +} + +void emu_textOut16(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned short *screen = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH; + + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if(fd&0x80) screen[l*SCREEN_WIDTH+0]=0xffff; + if(fd&0x40) screen[l*SCREEN_WIDTH+1]=0xffff; + if(fd&0x20) screen[l*SCREEN_WIDTH+2]=0xffff; + if(fd&0x10) screen[l*SCREEN_WIDTH+3]=0xffff; + if(fd&0x08) screen[l*SCREEN_WIDTH+4]=0xffff; + if(fd&0x04) screen[l*SCREEN_WIDTH+5]=0xffff; + if(fd&0x02) screen[l*SCREEN_WIDTH+6]=0xffff; + if(fd&0x01) screen[l*SCREEN_WIDTH+7]=0xffff; + } + screen += 8; + } +} + + +void emu_updateMovie(void) +{ + int offs = Pico.m.frame_count*3 + 0x40; + if (offs+3 > movie_size) { + free(movie_data); + movie_data = 0; + strcpy(noticeMsg, "END OF MOVIE."); + lprintf("END OF MOVIE.\n"); + emu_noticeMsgUpdated(); + } else { + // MXYZ SACB RLDU + PicoPad[0] = ~movie_data[offs] & 0x8f; // ! SCBA RLDU + if(!(movie_data[offs] & 0x10)) PicoPad[0] |= 0x40; // A + if(!(movie_data[offs] & 0x20)) PicoPad[0] |= 0x10; // B + if(!(movie_data[offs] & 0x40)) PicoPad[0] |= 0x20; // A + PicoPad[1] = ~movie_data[offs+1] & 0x8f; // ! SCBA RLDU + if(!(movie_data[offs+1] & 0x10)) PicoPad[1] |= 0x40; // A + if(!(movie_data[offs+1] & 0x20)) PicoPad[1] |= 0x10; // B + if(!(movie_data[offs+1] & 0x40)) PicoPad[1] |= 0x20; // A + PicoPad[0] |= (~movie_data[offs+2] & 0x0A) << 8; // ! MZYX + if(!(movie_data[offs+2] & 0x01)) PicoPad[0] |= 0x0400; // X + if(!(movie_data[offs+2] & 0x04)) PicoPad[0] |= 0x0100; // Z + PicoPad[1] |= (~movie_data[offs+2] & 0xA0) << 4; // ! MZYX + if(!(movie_data[offs+2] & 0x10)) PicoPad[1] |= 0x0400; // X + if(!(movie_data[offs+2] & 0x40)) PicoPad[1] |= 0x0100; // Z + } +} + + +static size_t gzRead2(void *p, size_t _size, size_t _n, void *file) +{ + return gzread(file, p, _n); +} + + +static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file) +{ + return gzwrite(file, p, _n); +} + +static int try_ropen_file(const char *fname) +{ + FILE *f; + + f = fopen(fname, "rb"); + if (f) { + fclose(f); + return 1; + } + return 0; +} + +char *emu_GetSaveFName(int load, int is_sram, int slot) +{ + static char saveFname[512]; + char ext[16]; + + if (is_sram) + { + romfname_ext(saveFname, (PicoMCD&1) ? "brm/" : "srm/", (PicoMCD&1) ? ".brm" : ".srm"); + if (load) { + if (try_ropen_file(saveFname)) return saveFname; + // try in current dir.. + romfname_ext(saveFname, NULL, (PicoMCD&1) ? ".brm" : ".srm"); + if (try_ropen_file(saveFname)) return saveFname; + return NULL; // give up + } + } + else + { + ext[0] = 0; + if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); + strcat(ext, (currentConfig.EmuOpt & 8) ? ".mds.gz" : ".mds"); + + romfname_ext(saveFname, "mds/", ext); + if (load) { + if (try_ropen_file(saveFname)) return saveFname; + romfname_ext(saveFname, NULL, ext); + if (try_ropen_file(saveFname)) return saveFname; + if (currentConfig.EmuOpt & 8) { + ext[0] = 0; + if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); + strcat(ext, ".mds"); + + romfname_ext(saveFname, "mds/", ext); + if (try_ropen_file(saveFname)) return saveFname; + romfname_ext(saveFname, NULL, ext); + if (try_ropen_file(saveFname)) return saveFname; + } + return NULL; + } + } + + return saveFname; +} + +int emu_checkSaveFile(int slot) +{ + return emu_GetSaveFName(1, 0, slot) ? 1 : 0; +} + +void emu_setSaveStateCbs(int gz) +{ + if (gz) { + areaRead = gzRead2; + areaWrite = gzWrite2; + areaEof = (areaeof *) gzeof; + areaSeek = (areaseek *) gzseek; + areaClose = (areaclose *) gzclose; + } else { + areaRead = (arearw *) fread; + areaWrite = (arearw *) fwrite; + areaEof = (areaeof *) feof; + areaSeek = (areaseek *) fseek; + areaClose = (areaclose *) fclose; + } +} + +int emu_SaveLoadGame(int load, int sram) +{ + int ret = 0; + char *saveFname; + + // make save filename + saveFname = emu_GetSaveFName(load, sram, state_slot); + if (saveFname == NULL) { + if (!sram) { + strcpy(noticeMsg, load ? "LOAD FAILED (missing file)" : "SAVE FAILED "); + emu_noticeMsgUpdated(); + } + return -1; + } + + lprintf("saveLoad (%i, %i): %s\n", load, sram, saveFname); + + if(sram) { + FILE *sramFile; + int sram_size; + unsigned char *sram_data; + int truncate = 1; + if (PicoMCD&1) { + if (PicoOpt&0x8000) { // MCD RAM cart? + sram_size = 0x12000; + sram_data = SRam.data; + if (sram_data) + memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4); + } else { + sram_size = 0x2000; + sram_data = Pico_mcd->bram; + truncate = 0; // the .brm may contain RAM cart data after normal brm + } + } else { + sram_size = SRam.end-SRam.start+1; + if(Pico.m.sram_reg & 4) sram_size=0x2000; + sram_data = SRam.data; + } + if (!sram_data) return 0; // SRam forcefully disabled for this game + + if (load) { + sramFile = fopen(saveFname, "rb"); + if(!sramFile) return -1; + fread(sram_data, 1, sram_size, sramFile); + fclose(sramFile); + if ((PicoMCD&1) && (PicoOpt&0x8000)) + memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4); + } else { + // sram save needs some special processing + // see if we have anything to save + for (; sram_size > 0; sram_size--) + if (sram_data[sram_size-1]) break; + + if (sram_size) { + sramFile = fopen(saveFname, truncate ? "wb" : "r+b"); + if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry + if (!sramFile) return -1; + ret = fwrite(sram_data, 1, sram_size, sramFile); + ret = (ret != sram_size) ? -1 : 0; + fclose(sramFile); +#ifndef NO_SYNC + sync(); +#endif + } + } + return ret; + } + else + { + void *PmovFile = NULL; + if (strcmp(saveFname + strlen(saveFname) - 3, ".gz") == 0) { + if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) { + emu_setSaveStateCbs(1); + if(!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY); + } + } + else + { + if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) { + emu_setSaveStateCbs(0); + } + } + if(PmovFile) { + ret = PmovState(load ? 6 : 5, PmovFile); + areaClose(PmovFile); + PmovFile = 0; + if (load) Pico.m.dirtyPal=1; +#ifndef NO_SYNC + else sync(); +#endif + } + else ret = -1; + if (!ret) + strcpy(noticeMsg, load ? "GAME LOADED " : "GAME SAVED "); + else + { + strcpy(noticeMsg, load ? "LOAD FAILED " : "SAVE FAILED "); + ret = -1; + } + + emu_noticeMsgUpdated(); + return ret; + } +} diff --git a/common/emu.h b/common/emu.h new file mode 100644 index 0000000..67533cb --- /dev/null +++ b/common/emu.h @@ -0,0 +1,48 @@ +// (c) Copyright 2006-2007 notaz, All rights reserved. +// Free for non-commercial use. + +// For commercial use, separate licencing terms must be obtained. + +typedef struct { + char lastRomFile[512]; + int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, + // squidgehack, no_save_cfg_on_exit, , 16_bit_mode + // craigix_ram, confirm_save, show_cd_leds, confirm_load + // A_SNs_gamma, perfect_vsync + int PicoOpt; // used for config saving only, see Pico.h + int PsndRate; // ditto + int PicoRegion; // ditto + int Frameskip; + int CPUclock; + int KeyBinds[32]; + int volume; + int gamma; + int JoyBinds[4][32]; + int PicoAutoRgnOrder; + int PicoCDBuffers; + int scaling; // 0=center, 1=hscale, 2=hvscale, 3=hsoftscale +} currentConfig_t; + + +extern currentConfig_t currentConfig; +extern char *PicoConfigFile; +extern unsigned char *rom_data; +extern char noticeMsg[64]; +extern int state_slot; +extern int config_slot, config_slot_current; +extern unsigned char *movie_data; + + +int emu_ReloadRom(void); +int emu_SaveLoadGame(int load, int sram); +int emu_ReadConfig(int game, int no_defaults); +int emu_WriteConfig(int game); +char *emu_GetSaveFName(int load, int is_sram, int slot); +int emu_checkSaveFile(int slot); +void emu_setSaveStateCbs(int gz); +void emu_updateMovie(void); +int emu_cdCheck(int *pregion); +int emu_findBios(int region, char **bios_file); +void emu_textOut8 (int x, int y, const char *text); +void emu_textOut16(int x, int y, const char *text); + diff --git a/common/menu.c b/common/menu.c index ed02ff8..d2957c2 100644 --- a/common/menu.c +++ b/common/menu.c @@ -14,16 +14,18 @@ #include "lprintf.h" #if defined(__GP2X__) -#include "../gp2x/gp2x.h" -#define SCREEN_WIDTH 320 -#define SCREEN_BUFFER gp2x_screen + #include "../gp2x/gp2x.h" + #define SCREEN_WIDTH 320 + #define SCREEN_BUFFER gp2x_screen #elif defined(__GIZ__) -#include "../gizmondo/giz.h" -#define SCREEN_WIDTH 321 -#define SCREEN_BUFFER menu_screen -extern unsigned char menu_screen[321*240*2]; + //#include "../gizmondo/giz.h" + #define SCREEN_WIDTH 321 + #define SCREEN_BUFFER menu_screen + extern unsigned char *menu_screen; #endif +char menuErrorMsg[64] = { 0, }; + static unsigned char menu_font_data[10240]; static int menu_text_color = 0xffff; // default to white static int menu_sel_color = -1; // disabled diff --git a/common/menu.h b/common/menu.h index 1e096ff..b21818d 100644 --- a/common/menu.h +++ b/common/menu.h @@ -7,6 +7,7 @@ void smalltext_out16(int x, int y, const char *texto, int color); void smalltext_out16_lim(int x, int y, const char *texto, int color, int max); void menu_draw_selection(int x, int y, int w); +extern char menuErrorMsg[64]; typedef enum diff --git a/gp2x/940ctl.c b/gp2x/940ctl.c index 9498858..0cbdb1c 100644 --- a/gp2x/940ctl.c +++ b/gp2x/940ctl.c @@ -17,6 +17,7 @@ #include "mp3.h" #include "../common/arm_utils.h" #include "../common/menu.h" +#include "../common/emu.h" #include "../../Pico/PicoInt.h" #include "../../Pico/sound/ym2612.h" #include "../../Pico/sound/mix.h" diff --git a/gp2x/Makefile b/gp2x/Makefile index 1458a34..65565f1 100644 --- a/gp2x/Makefile +++ b/gp2x/Makefile @@ -58,7 +58,7 @@ OBJS += main.o menu.o gp2x.o usbjoy.o emu.o squidgehack.o cpuctrl.o OBJS += 940ctl.o # common -OBJS += ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o +OBJS += ../common/emu.o ../common/menu.o ../common/fonts.o ../common/arm_utils.o ../common/readpng.o # Pico ifeq "$(amalgamate)" "1" @@ -183,7 +183,7 @@ testrefr.gpe : test.o gp2x.o ../../Pico/sound/mix_asm.o : ../../Pico/sound/mix.s @echo $< @$(AS) $(ASOPT) $< -o $@ -../../Pico/misc_asm.o : ../../Pico/misc.s +../../Pico/misc_asm.o : ../../Pico/Misc.s @echo $< @$(AS) $(ASOPT) $< -o $@ ../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s @@ -192,7 +192,7 @@ testrefr.gpe : test.o gp2x.o ../../Pico/cd/memory_asm.o : ../../Pico/cd/Memory.s @echo $< @$(AS) $(ASOPT) $< -o $@ -../../Pico/cd/misc_asm.o : ../../Pico/cd/misc.s +../../Pico/cd/misc_asm.o : ../../Pico/cd/Misc.s @echo $< @$(AS) $(ASOPT) $< -o $@ diff --git a/gp2x/emu.c b/gp2x/emu.c index 9615013..63b2d04 100644 --- a/gp2x/emu.c +++ b/gp2x/emu.c @@ -20,6 +20,7 @@ #include "menu.h" #include "../common/arm_utils.h" #include "../common/fonts.h" +#include "../common/emu.h" #include "cpuctrl.h" #include @@ -37,366 +38,42 @@ int engineState; int select_exits = 0; -char *PicoConfigFile = "picoconfig.bin"; -currentConfig_t currentConfig; char romFileName[PATH_MAX]; -unsigned char *rom_data = NULL; extern int crashed_940; static short sndBuffer[2*44100/50]; -static char noticeMsg[64]; // notice msg to draw static struct timeval noticeMsgTime = { 0, 0 }; // when started showing static int osd_fps_x; static int combo_keys = 0, combo_acts = 0; // keys and actions which need button combos static int gp2x_old_gamma = 100; -static unsigned char *movie_data = NULL; -static int movie_size = 0; +char noticeMsg[64]; // notice msg to draw unsigned char *PicoDraw2FB = NULL; // temporary buffer for alt renderer -int state_slot = 0; int reset_timing = 0; -int config_slot = 0, config_slot_current = 0; +static void emu_msg_cb(const char *msg); +static void emu_msg_tray_open(void); -// utilities -static void strlwr(char* string) -{ - while ( (*string++ = (char)tolower(*string)) ); -} -static int try_rfn_cut(void) +void emu_noticeMsgUpdated(void) { - FILE *tmp; - char *p; - - p = romFileName + strlen(romFileName) - 1; - for (; p > romFileName; p--) - if (*p == '.') break; - *p = 0; - - if((tmp = fopen(romFileName, "rb"))) { - fclose(tmp); - return 1; - } - return 0; + gettimeofday(¬iceMsgTime, 0); } -static void get_ext(char *file, char *ext) +void emu_getMainDir(char *dst, int len) { - char *p; + extern char **g_argv; + int j; - p = file + strlen(file) - 4; - if (p < file) p = file; - strncpy(ext, p, 4); - ext[4] = 0; - strlwr(ext); + strncpy(dst, g_argv[0], len); + len -= 32; // reserve + if (len < 0) len = 0; + dst[len] = 0; + for (j = strlen(dst); j > 0; j--) + if (dst[j] == '/') { dst[j+1] = 0; break; } } -char *biosfiles_us[] = { "us_scd2_9306", "SegaCDBIOS9303", "us_scd1_9210" }; -char *biosfiles_eu[] = { "eu_mcd2_9306", "eu_mcd2_9303", "eu_mcd1_9210" }; -char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" }; - -extern char **g_argv; - -int find_bios(int region, char **bios_file) -{ - static char bios_path[1024]; - int i, j, count; - char **files; - FILE *f = NULL; - - if (region == 4) { // US - files = biosfiles_us; - count = sizeof(biosfiles_us) / sizeof(char *); - } else if (region == 8) { // EU - files = biosfiles_eu; - count = sizeof(biosfiles_eu) / sizeof(char *); - } else if (region == 1 || region == 2) { - files = biosfiles_jp; - count = sizeof(biosfiles_jp) / sizeof(char *); - } else { - return 0; - } - - for (i = 0; i < count; i++) - { - strncpy(bios_path, g_argv[0], 1023); - bios_path[1024-32] = 0; - for (j = strlen(bios_path); j > 0; j--) - if (bios_path[j] == '/') { bios_path[j+1] = 0; break; } - strcat(bios_path, files[i]); - strcat(bios_path, ".bin"); - f = fopen(bios_path, "rb"); - if (f) break; - - bios_path[strlen(bios_path) - 4] = 0; - strcat(bios_path, ".zip"); - f = fopen(bios_path, "rb"); - if (f) break; - } - - if (f) { - printf("using bios: %s\n", bios_path); - fclose(f); - if (bios_file) *bios_file = bios_path; - return 1; - } else { - sprintf(menuErrorMsg, "no %s BIOS files found, read docs", - region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); - printf("%s\n", menuErrorMsg); - return 0; - } -} - -/* checks if romFileName points to valid MegaCD image - * if so, checks for suitable BIOS */ -int emu_cd_check(int *pregion) -{ - unsigned char buf[32]; - pm_file *cd_f; - int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe - - cd_f = pm_open(romFileName); - if (!cd_f) return 0; // let the upper level handle this - - if (pm_read(buf, 32, cd_f) != 32) { - pm_close(cd_f); - return 0; - } - - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) - if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) - if (type == 0) { - pm_close(cd_f); - return 0; - } - - /* it seems we have a CD image here. Try to detect region now.. */ - pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); - pm_read(buf, 1, cd_f); - pm_close(cd_f); - - if (buf[0] == 0x64) region = 8; // EU - if (buf[0] == 0xa1) region = 1; // JAP - - printf("detected %s Sega/Mega CD image with %s region\n", - type == 2 ? "BIN" : "ISO", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); - - if (pregion != NULL) *pregion = region; - - return type; -} - -int emu_ReloadRom(void) -{ - unsigned int rom_size = 0; - char *used_rom_name = romFileName; - char ext[5]; - pm_file *rom; - int ret, cd_state, cd_region, cfg_loaded = 0; - - printf("emu_ReloadRom(%s)\n", romFileName); - - get_ext(romFileName, ext); - - // detect wrong extensions - if(!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz - sprintf(menuErrorMsg, "Not a ROM selected."); - return 0; - } - - PicoPatchUnload(); - - // check for movie file - if(movie_data) { - free(movie_data); - movie_data = 0; - } - if(!strcmp(ext, ".gmv")) { - // check for both gmv and rom - int dummy; - FILE *movie_file = fopen(romFileName, "rb"); - if(!movie_file) { - sprintf(menuErrorMsg, "Failed to open movie."); - return 0; - } - fseek(movie_file, 0, SEEK_END); - movie_size = ftell(movie_file); - fseek(movie_file, 0, SEEK_SET); - if(movie_size < 64+3) { - sprintf(menuErrorMsg, "Invalid GMV file."); - fclose(movie_file); - return 0; - } - movie_data = malloc(movie_size); - if(movie_data == NULL) { - sprintf(menuErrorMsg, "low memory."); - fclose(movie_file); - return 0; - } - fread(movie_data, 1, movie_size, movie_file); - fclose(movie_file); - if (strncmp((char *)movie_data, "Gens Movie TEST", 15) != 0) { - sprintf(menuErrorMsg, "Invalid GMV file."); - return 0; - } - dummy = try_rfn_cut() || try_rfn_cut(); - if (!dummy) { - sprintf(menuErrorMsg, "Could't find a ROM for movie."); - return 0; - } - get_ext(romFileName, ext); - } - else if (!strcmp(ext, ".pat")) { - int dummy; - PicoPatchLoad(romFileName); - dummy = try_rfn_cut() || try_rfn_cut(); - if (!dummy) { - sprintf(menuErrorMsg, "Could't find a ROM to patch."); - return 0; - } - get_ext(romFileName, ext); - } - - if ((PicoMCD & 1) && Pico_mcd != NULL) - Stop_CD(); - - // check for MegaCD image - cd_state = emu_cd_check(&cd_region); - if (cd_state > 0) - { - // valid CD image, check for BIOS.. - - // we need to have config loaded at this point - ret = emu_ReadConfig(1, 1); - if (!ret) emu_ReadConfig(0, 1); - cfg_loaded = 1; - - if (PicoRegionOverride) { - cd_region = PicoRegionOverride; - printf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA"); - } - if (!find_bios(cd_region, &used_rom_name)) { - // bios_help() ? - return 0; - } - - PicoMCD |= 1; - get_ext(used_rom_name, ext); - } - else - { - if (PicoMCD & 1) Stop_CD(); - PicoMCD &= ~1; - } - - rom = pm_open(used_rom_name); - if(!rom) { - sprintf(menuErrorMsg, "Failed to open rom."); - return 0; - } - - menu_romload_prepare(used_rom_name); - - if(rom_data) { - free(rom_data); - rom_data = 0; - rom_size = 0; - } - - if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { - sprintf(menuErrorMsg, "PicoCartLoad() failed."); - printf("%s\n", menuErrorMsg); - pm_close(rom); - menu_romload_end(); - return 0; - } - pm_close(rom); - menu_romload_end(); - - // detect wrong files (Pico crashes on very small files), also see if ROM EP is good - if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || - ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) { - if (rom_data) free(rom_data); - rom_data = 0; - sprintf(menuErrorMsg, "Not a ROM selected."); - return 0; - } - - // load config for this ROM (do this before insert to get correct region) - if (!cfg_loaded) { - ret = emu_ReadConfig(1, 1); - if (!ret) emu_ReadConfig(0, 1); - } - - printf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); - if(PicoCartInsert(rom_data, rom_size)) { - sprintf(menuErrorMsg, "Failed to load ROM."); - return 0; - } - - Pico.m.frame_count = 0; - - // insert CD if it was detected - if (cd_state > 0) { - ret = Insert_CD(romFileName, cd_state == 2); - if (ret != 0) { - sprintf(menuErrorMsg, "Insert_CD() failed, invalid CD image?"); - printf("%s\n", menuErrorMsg); - return 0; - } - } - - // emu_ReadConfig() might have messed currentConfig.lastRomFile - strncpy(currentConfig.lastRomFile, romFileName, sizeof(currentConfig.lastRomFile)-1); - currentConfig.lastRomFile[sizeof(currentConfig.lastRomFile)-1] = 0; - - if (PicoPatches) { - PicoPatchPrepare(); - PicoPatchApply(); - } - - // additional movie stuff - if (movie_data) { - if(movie_data[0x14] == '6') - PicoOpt |= 0x20; // 6 button pad - else PicoOpt &= ~0x20; - PicoOpt |= 0x10040; // accurate timing, no VDP fifo timing - if(movie_data[0xF] >= 'A') { - if(movie_data[0x16] & 0x80) { - PicoRegionOverride = 8; - } else { - PicoRegionOverride = 4; - } - PicoReset(0); - // TODO: bits 6 & 5 - } - movie_data[0x18+30] = 0; - sprintf(noticeMsg, "MOVIE: %s", (char *) &movie_data[0x18]); - } - else - { - PicoOpt &= ~0x10000; - if(Pico.m.pal) { - strcpy(noticeMsg, "PAL SYSTEM / 50 FPS"); - } else { - strcpy(noticeMsg, "NTSC SYSTEM / 60 FPS"); - } - } - gettimeofday(¬iceMsgTime, 0); - - // load SRAM for this ROM - if(currentConfig.EmuOpt & 1) - emu_SaveLoadGame(1, 1); - - return 1; -} - - -static void emu_msg_cb(const char *msg); -static void emu_msg_tray_open(void); - void emu_Init(void) { // make temp buffer for alt renderer @@ -419,25 +96,6 @@ void emu_Init(void) } -static void romfname_ext(char *dst, const char *prefix, const char *ext) -{ - char *p; - int prefix_len = 0; - - // make save filename - for (p = romFileName+strlen(romFileName)-1; p >= romFileName && *p != '/'; p--); p++; - *dst = 0; - if (prefix) { - strcpy(dst, prefix); - prefix_len = strlen(prefix); - } - strncpy(dst + prefix_len, p, 511-prefix_len); - dst[511-8] = 0; - if (dst[strlen(dst)-4] == '.') dst[strlen(dst)-4] = 0; - if (ext) strcat(dst, ext); -} - - static void find_combos(void) { int act, u; @@ -468,7 +126,7 @@ static void find_combos(void) } -void scaling_update(void) +static void scaling_update(void) { PicoOpt &= ~0x4100; switch (currentConfig.scaling) { @@ -480,138 +138,6 @@ void scaling_update(void) } -int emu_ReadConfig(int game, int no_defaults) -{ - FILE *f; - char cfg[512], extbuf[16]; - int bread = 0; - - if (!game) - { - if (!no_defaults) - { - // set default config - memset(¤tConfig, 0, sizeof(currentConfig)); - currentConfig.lastRomFile[0] = 0; - currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds - currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda - currentConfig.PsndRate = 22050; // 44100; - currentConfig.PicoRegion = 0; // auto - currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP - currentConfig.Frameskip = -1; // auto - currentConfig.CPUclock = 200; - currentConfig.volume = 50; - currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU - currentConfig.KeyBinds[ 4] = 1<<1; - currentConfig.KeyBinds[ 2] = 1<<2; - currentConfig.KeyBinds[ 6] = 1<<3; - currentConfig.KeyBinds[14] = 1<<4; - currentConfig.KeyBinds[13] = 1<<5; - currentConfig.KeyBinds[12] = 1<<6; - currentConfig.KeyBinds[ 8] = 1<<7; - currentConfig.KeyBinds[15] = 1<<26; // switch rend - currentConfig.KeyBinds[10] = 1<<27; // save state - currentConfig.KeyBinds[11] = 1<<28; // load state - currentConfig.KeyBinds[23] = 1<<29; // vol up - currentConfig.KeyBinds[22] = 1<<30; // vol down - currentConfig.gamma = 100; - currentConfig.PicoCDBuffers = 64; - currentConfig.scaling = 0; - } - strncpy(cfg, PicoConfigFile, 511); - if (config_slot != 0) - { - char *p = strrchr(cfg, '.'); - if (p == NULL) p = cfg + strlen(cfg); - sprintf(extbuf, ".%i.pbcfg", config_slot); - strncpy(p, extbuf, 511 - (p - cfg)); - } - cfg[511] = 0; - } else { - if (config_slot != 0) - sprintf(extbuf, ".%i.pbcfg", config_slot); - else strcpy(extbuf, ".pbcfg"); - romfname_ext(cfg, "cfg/", extbuf); - f = fopen(cfg, "rb"); - if (!f) romfname_ext(cfg, NULL, ".pbcfg"); - else fclose(f); - } - - printf("emu_ReadConfig: %s ", cfg); - f = fopen(cfg, "rb"); - if (f) { - bread = fread(¤tConfig, 1, sizeof(currentConfig), f); - fclose(f); - } - printf(bread > 0 ? "(ok)\n" : "(failed)\n"); - - PicoOpt = currentConfig.PicoOpt; - PsndRate = currentConfig.PsndRate; - PicoRegionOverride = currentConfig.PicoRegion; - PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder; - PicoCDBuffers = currentConfig.PicoCDBuffers; - scaling_update(); - // some sanity checks - if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; - if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; - if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; - // if volume keys are unbound, bind them to volume control - if (!currentConfig.KeyBinds[23] && !currentConfig.KeyBinds[22]) { - currentConfig.KeyBinds[23] = 1<<29; // vol up - currentConfig.KeyBinds[22] = 1<<30; // vol down - } - - if (bread > 0) config_slot_current = config_slot; - return (bread > 0); // == sizeof(currentConfig)); -} - - -int emu_WriteConfig(int game) -{ - FILE *f; - char cfg[512], extbuf[16]; - int bwrite = 0; - - if (!game) - { - strncpy(cfg, PicoConfigFile, 511); - if (config_slot != 0) - { - char *p = strrchr(cfg, '.'); - if (p == NULL) p = cfg + strlen(cfg); - sprintf(extbuf, ".%i.pbcfg", config_slot); - strncpy(p, extbuf, 511 - (p - cfg)); - } - cfg[511] = 0; - } else { - if (config_slot != 0) - sprintf(extbuf, ".%i.pbcfg", config_slot); - else strcpy(extbuf, ".pbcfg"); - romfname_ext(cfg, "cfg/", extbuf); - } - - printf("emu_WriteConfig: %s ", cfg); - f = fopen(cfg, "wb"); - if (f) { - currentConfig.PicoOpt = PicoOpt; - currentConfig.PsndRate = PsndRate; - currentConfig.PicoRegion = PicoRegionOverride; - currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder; - currentConfig.PicoCDBuffers = PicoCDBuffers; - bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f); - fflush(f); - fclose(f); -#ifndef NO_SYNC - sync(); -#endif - } - printf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); - - if (bwrite == sizeof(currentConfig)) config_slot_current = config_slot; - return (bwrite == sizeof(currentConfig)); -} - - void emu_Deinit(void) { // save SRAM @@ -646,54 +172,36 @@ void emu_Deinit(void) set_gamma(100, 0); } -static void text_out8_builtin(int x, int y, const char *text) -{ - int i,l,len=strlen(text); - unsigned char *screen = (unsigned char *)gp2x_screen + x + y*320; - - /* always using built-in font */ - for (i = 0; i < len; i++) - { - for (l=0;l<8;l++) - { - unsigned char fd = fontdata8x8[((text[i])*8)+l]; - if (fd&0x80) screen[l*320+0]=0xf0; - if (fd&0x40) screen[l*320+1]=0xf0; - if (fd&0x20) screen[l*320+2]=0xf0; - if (fd&0x10) screen[l*320+3]=0xf0; - if (fd&0x08) screen[l*320+4]=0xf0; - if (fd&0x04) screen[l*320+5]=0xf0; - if (fd&0x02) screen[l*320+6]=0xf0; - if (fd&0x01) screen[l*320+7]=0xf0; - } - screen += 8; - } -} - -static void text_out16_builtin(int x, int y, const char *text) -{ - int i,l,len=strlen(text); - unsigned short *screen = (unsigned short *)gp2x_screen + x + y*320; - - for (i = 0; i < len; i++) - { - for (l=0;l<8;l++) - { - unsigned char fd = fontdata8x8[((text[i])*8)+l]; - if(fd&0x80) screen[l*320+0]=0xffff; - if(fd&0x40) screen[l*320+1]=0xffff; - if(fd&0x20) screen[l*320+2]=0xffff; - if(fd&0x10) screen[l*320+3]=0xffff; - if(fd&0x08) screen[l*320+4]=0xffff; - if(fd&0x04) screen[l*320+5]=0xffff; - if(fd&0x02) screen[l*320+6]=0xffff; - if(fd&0x01) screen[l*320+7]=0xffff; - } - screen += 8; - } +void emu_setDefaultConfig(void) +{ + memset(¤tConfig, 0, sizeof(currentConfig)); + currentConfig.lastRomFile[0] = 0; + currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds + currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda + currentConfig.PsndRate = 22050; // 44100; + currentConfig.PicoRegion = 0; // auto + currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP + currentConfig.Frameskip = -1; // auto + currentConfig.CPUclock = 200; + currentConfig.volume = 50; + currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU + currentConfig.KeyBinds[ 4] = 1<<1; + currentConfig.KeyBinds[ 2] = 1<<2; + currentConfig.KeyBinds[ 6] = 1<<3; + currentConfig.KeyBinds[14] = 1<<4; + currentConfig.KeyBinds[13] = 1<<5; + currentConfig.KeyBinds[12] = 1<<6; + currentConfig.KeyBinds[ 8] = 1<<7; + currentConfig.KeyBinds[15] = 1<<26; // switch rend + currentConfig.KeyBinds[10] = 1<<27; // save state + currentConfig.KeyBinds[11] = 1<<28; // load state + currentConfig.KeyBinds[23] = 1<<29; // vol up + currentConfig.KeyBinds[22] = 1<<30; // vol down + currentConfig.gamma = 100; + currentConfig.PicoCDBuffers = 64; + currentConfig.scaling = 0; } - void osd_text(int x, int y, const char *text) { int len = strlen(text)*8; @@ -706,7 +214,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned char *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = 0xe0e0e0e0; } - text_out8_builtin(x, y, text); + emu_textOut8(x, y, text); } else { int *p, i, h; x &= ~1; // align x @@ -715,7 +223,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned short *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = (*p>>2)&0x39e7; } - text_out16_builtin(x, y, text); + emu_textOut16(x, y, text); } } @@ -917,7 +425,7 @@ static void RunEvents(unsigned int which) { if(which & 0x1800) { // save or load (but not both) int do_it = 1; - if ( emu_check_save_file(state_slot) && + if ( emu_checkSaveFile(state_slot) && (( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load (!(which & 0x1000) && (currentConfig.EmuOpt & 0x200))) ) { // save unsigned long keys; @@ -962,7 +470,7 @@ static void RunEvents(unsigned int which) state_slot += 1; if(state_slot > 9) state_slot = 0; } - sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_check_save_file(state_slot) ? "USED" : "FREE"); + sprintf(noticeMsg, "SAVE SLOT %i [%s]", state_slot, emu_checkSaveFile(state_slot) ? "USED" : "FREE"); gettimeofday(¬iceMsgTime, 0); } if(which & 0x0080) { @@ -971,35 +479,6 @@ static void RunEvents(unsigned int which) } -static void updateMovie(void) -{ - int offs = Pico.m.frame_count*3 + 0x40; - if (offs+3 > movie_size) { - free(movie_data); - movie_data = 0; - strcpy(noticeMsg, "END OF MOVIE."); - printf("END OF MOVIE.\n"); - gettimeofday(¬iceMsgTime, 0); - } else { - // MXYZ SACB RLDU - PicoPad[0] = ~movie_data[offs] & 0x8f; // ! SCBA RLDU - if(!(movie_data[offs] & 0x10)) PicoPad[0] |= 0x40; // A - if(!(movie_data[offs] & 0x20)) PicoPad[0] |= 0x10; // B - if(!(movie_data[offs] & 0x40)) PicoPad[0] |= 0x20; // A - PicoPad[1] = ~movie_data[offs+1] & 0x8f; // ! SCBA RLDU - if(!(movie_data[offs+1] & 0x10)) PicoPad[1] |= 0x40; // A - if(!(movie_data[offs+1] & 0x20)) PicoPad[1] |= 0x10; // B - if(!(movie_data[offs+1] & 0x40)) PicoPad[1] |= 0x20; // A - PicoPad[0] |= (~movie_data[offs+2] & 0x0A) << 8; // ! MZYX - if(!(movie_data[offs+2] & 0x01)) PicoPad[0] |= 0x0400; // X - if(!(movie_data[offs+2] & 0x04)) PicoPad[0] |= 0x0100; // Z - PicoPad[1] |= (~movie_data[offs+2] & 0xA0) << 4; // ! MZYX - if(!(movie_data[offs+2] & 0x10)) PicoPad[1] |= 0x0400; // X - if(!(movie_data[offs+2] & 0x40)) PicoPad[1] |= 0x0100; // Z - } -} - - static void updateKeys(void) { unsigned long keys, allActions[2] = { 0, 0 }, events; @@ -1077,7 +556,7 @@ static void updateKeys(void) events &= ~prevEvents; if (events) RunEvents(events); - if (movie_data) updateMovie(); + if (movie_data) emu_updateMovie(); prevEvents = (allActions[0] | allActions[1]) >> 16; } @@ -1101,7 +580,7 @@ static void SkipFrame(int do_audio) } -void emu_forced_frame(void) +void emu_forcedFrame(void) { int po_old = PicoOpt; int eo_old = currentConfig.EmuOpt; @@ -1184,6 +663,7 @@ void emu_Loop(void) // make sure we are in correct mode vidResetMode(); + scaling_update(); Pico.m.dirtyPal = 1; oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; find_combos(); @@ -1339,7 +819,7 @@ void emu_Loop(void) } } else if(tval.tv_usec > lim_time) { // auto frameskip // no time left for this frame - skip - if (tval.tv_usec - lim_time >= 0x300000) { + if (tval.tv_usec - lim_time >= 300000) { /* something caused a slowdown for us (disk access? cache flush?) * try to recover by resetting timing... */ reset_timing = 1; @@ -1415,7 +895,7 @@ if (Pico.m.frame_count == 31563) { gettimeofday(&tval, 0); if (thissec != tval.tv_sec) tval.tv_usec+=1000000; - if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 0x300000) // slowdown detection + if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 300000) // slowdown detection reset_timing = 1; else if (PsndOut != NULL || currentConfig.Frameskip < 0) { @@ -1451,7 +931,7 @@ if (Pico.m.frame_count == 31563) { // if in 8bit mode, generate 16bit image for menu background if ((PicoOpt&0x10) || !(currentConfig.EmuOpt&0x80)) - emu_forced_frame(); + emu_forcedFrame(); } @@ -1462,196 +942,3 @@ void emu_ResetGame(void) } -size_t gzRead2(void *p, size_t _size, size_t _n, void *file) -{ - return gzread(file, p, _n); -} - - -size_t gzWrite2(void *p, size_t _size, size_t _n, void *file) -{ - return gzwrite(file, p, _n); -} - -static int try_ropen_file(const char *fname) -{ - FILE *f; - - f = fopen(fname, "rb"); - if (f) { - fclose(f); - return 1; - } - return 0; -} - -char *emu_GetSaveFName(int load, int is_sram, int slot) -{ - static char saveFname[512]; - char ext[16]; - - if (is_sram) - { - romfname_ext(saveFname, (PicoMCD&1) ? "brm/" : "srm/", (PicoMCD&1) ? ".brm" : ".srm"); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; - // try in current dir.. - romfname_ext(saveFname, NULL, (PicoMCD&1) ? ".brm" : ".srm"); - if (try_ropen_file(saveFname)) return saveFname; - return NULL; // give up - } - } - else - { - ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, (currentConfig.EmuOpt & 8) ? ".mds.gz" : ".mds"); - - romfname_ext(saveFname, "mds/", ext); - if (load) { - if (try_ropen_file(saveFname)) return saveFname; - romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - if (currentConfig.EmuOpt & 8) { - ext[0] = 0; - if(slot > 0 && slot < 10) sprintf(ext, ".%i", slot); - strcat(ext, ".mds"); - - romfname_ext(saveFname, "mds/", ext); - if (try_ropen_file(saveFname)) return saveFname; - romfname_ext(saveFname, NULL, ext); - if (try_ropen_file(saveFname)) return saveFname; - } - return NULL; - } - } - - return saveFname; -} - -int emu_check_save_file(int slot) -{ - return emu_GetSaveFName(1, 0, slot) ? 1 : 0; -} - -void emu_set_save_cbs(int gz) -{ - if (gz) { - areaRead = gzRead2; - areaWrite = gzWrite2; - areaEof = (areaeof *) gzeof; - areaSeek = (areaseek *) gzseek; - areaClose = (areaclose *) gzclose; - } else { - areaRead = (arearw *) fread; - areaWrite = (arearw *) fwrite; - areaEof = (areaeof *) feof; - areaSeek = (areaseek *) fseek; - areaClose = (areaclose *) fclose; - } -} - -int emu_SaveLoadGame(int load, int sram) -{ - int ret = 0; - char *saveFname; - - // make save filename - saveFname = emu_GetSaveFName(load, sram, state_slot); - if (saveFname == NULL) { - if (!sram) { - strcpy(noticeMsg, load ? "LOAD FAILED (missing file)" : "SAVE FAILED "); - gettimeofday(¬iceMsgTime, 0); - } - return -1; - } - - printf("saveLoad (%i, %i): %s\n", load, sram, saveFname); - - if(sram) { - FILE *sramFile; - int sram_size; - unsigned char *sram_data; - int truncate = 1; - if (PicoMCD&1) { - if (PicoOpt&0x8000) { // MCD RAM cart? - sram_size = 0x12000; - sram_data = SRam.data; - if (sram_data) - memcpy32((int *)sram_data, (int *)Pico_mcd->bram, 0x2000/4); - } else { - sram_size = 0x2000; - sram_data = Pico_mcd->bram; - truncate = 0; // the .brm may contain RAM cart data after normal brm - } - } else { - sram_size = SRam.end-SRam.start+1; - if(Pico.m.sram_reg & 4) sram_size=0x2000; - sram_data = SRam.data; - } - if (!sram_data) return 0; // SRam forcefully disabled for this game - - if (load) { - sramFile = fopen(saveFname, "rb"); - if(!sramFile) return -1; - fread(sram_data, 1, sram_size, sramFile); - fclose(sramFile); - if ((PicoMCD&1) && (PicoOpt&0x8000)) - memcpy32((int *)Pico_mcd->bram, (int *)sram_data, 0x2000/4); - } else { - // sram save needs some special processing - // see if we have anything to save - for (; sram_size > 0; sram_size--) - if (sram_data[sram_size-1]) break; - - if (sram_size) { - sramFile = fopen(saveFname, truncate ? "wb" : "r+b"); - if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry - if (!sramFile) return -1; - ret = fwrite(sram_data, 1, sram_size, sramFile); - ret = (ret != sram_size) ? -1 : 0; - fclose(sramFile); -#ifndef NO_SYNC - sync(); -#endif - } - } - return ret; - } - else - { - void *PmovFile = NULL; - if (strcmp(saveFname + strlen(saveFname) - 3, ".gz") == 0) { - if( (PmovFile = gzopen(saveFname, load ? "rb" : "wb")) ) { - emu_set_save_cbs(1); - if(!load) gzsetparams(PmovFile, 9, Z_DEFAULT_STRATEGY); - } - } - else - { - if( (PmovFile = fopen(saveFname, load ? "rb" : "wb")) ) { - emu_set_save_cbs(0); - } - } - if(PmovFile) { - ret = PmovState(load ? 6 : 5, PmovFile); - areaClose(PmovFile); - PmovFile = 0; - if (load) Pico.m.dirtyPal=1; -#ifndef NO_SYNC - else sync(); -#endif - } - else ret = -1; - if (!ret) - strcpy(noticeMsg, load ? "GAME LOADED " : "GAME SAVED "); - else - { - strcpy(noticeMsg, load ? "LOAD FAILED " : "SAVE FAILED "); - ret = -1; - } - - gettimeofday(¬iceMsgTime, 0); - return ret; - } -} diff --git a/gp2x/emu.h b/gp2x/emu.h index 6ae089d..8eddd1f 100644 --- a/gp2x/emu.h +++ b/gp2x/emu.h @@ -16,44 +16,15 @@ enum TPicoGameState { PGS_RestartRun, }; -typedef struct { - char lastRomFile[512]; - int EmuOpt; // LSb->MSb: use_sram, show_fps, enable_sound, gzip_saves, - // squidgehack, no_save_cfg_on_exit, , 16_bit_mode - // craigix_ram, confirm_save, show_cd_leds, confirm_load - // A_SNs_gamma, perfect_vsync - int PicoOpt; // used for config saving only, see Pico.h - int PsndRate; // ditto - int PicoRegion; // ditto - int Frameskip; - int CPUclock; - int KeyBinds[32]; - int volume; - int gamma; - int JoyBinds[4][32]; - int PicoAutoRgnOrder; - int PicoCDBuffers; - int scaling; // 0=center, 1=hscale, 2=hvscale, 3=hsoftscale -} currentConfig_t; - extern char romFileName[]; extern int engineState; -extern currentConfig_t currentConfig; -int emu_ReloadRom(void); void emu_Init(void); void emu_Deinit(void); -int emu_SaveLoadGame(int load, int sram); void emu_Loop(void); void emu_ResetGame(void); -int emu_ReadConfig(int game, int no_defaults); -int emu_WriteConfig(int game); -char *emu_GetSaveFName(int load, int is_sram, int slot); -int emu_check_save_file(int slot); -void emu_set_save_cbs(int gz); -void emu_forced_frame(void); -int emu_cd_check(int *pregion); -int find_bios(int region, char **bios_file); -void scaling_update(void); +void emu_forcedFrame(void); + +void osd_text(int x, int y, const char *text); diff --git a/gp2x/main.c b/gp2x/main.c index 13eb5a8..95e0e9f 100644 --- a/gp2x/main.c +++ b/gp2x/main.c @@ -12,6 +12,7 @@ #include "gp2x.h" #include "menu.h" #include "../common/menu.h" +#include "../common/emu.h" #include "emu.h" #include "940ctl.h" #include "version.h" diff --git a/gp2x/menu.c b/gp2x/menu.c index 63ba6a0..a60e4d8 100644 --- a/gp2x/menu.c +++ b/gp2x/menu.c @@ -14,8 +14,9 @@ #include "emu.h" #include "menu.h" #include "usbjoy.h" -#include "../common/arm_utils.h" +#include "../common/emu.h" #include "../common/menu.h" +#include "../common/arm_utils.h" #include "../common/readpng.h" #include "version.h" @@ -27,11 +28,7 @@ #error "need d_type for file browser #endif -extern char romFileName[PATH_MAX]; -extern char *rom_data; extern int mmuhack_status; -extern int state_slot; -extern int config_slot, config_slot_current; static const char *gp2xKeyNames[] = { "UP", "???", "LEFT", "???", "DOWN", "???", "RIGHT", "???", @@ -40,8 +37,6 @@ static const char *gp2xKeyNames[] = { "???", "???", "???", "PUSH", "???", "???", "???", "???" }; -char menuErrorMsg[40] = {0, }; - static void menu_darken_bg(void *dst, int pixels, int darker); static void menu_prepare_bg(int use_game_bg); @@ -452,7 +447,7 @@ static void state_check_slots(void) for (slot = 0; slot < 10; slot++) { - if (emu_check_save_file(slot)) + if (emu_checkSaveFile(slot)) { state_slot_flags |= 1 << slot; } @@ -480,10 +475,10 @@ static void draw_savestate_bg(int slot) if (strcmp(fname + strlen(fname) - 3, ".gz") == 0) { file = gzopen(fname, "rb"); - emu_set_save_cbs(1); + emu_setSaveStateCbs(1); } else { file = fopen(fname, "rb"); - emu_set_save_cbs(0); + emu_setSaveStateCbs(0); } if (file) { @@ -501,7 +496,7 @@ static void draw_savestate_bg(int slot) areaClose(file); } - emu_forced_frame(); + emu_forcedFrame(); menu_prepare_bg(1); memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram)); @@ -928,17 +923,17 @@ static void cd_menu_loop_options(void) menu_id selected_id; char *bios, *p; - if (find_bios(4, &bios)) { // US + 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 (find_bios(8, &bios)) { // EU + 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 (find_bios(1, &bios)) { // JP + 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"); @@ -972,21 +967,21 @@ static void cd_menu_loop_options(void) if (inp & GP2X_START) { // BIOS testers switch (selected_id) { case MA_CDOPT_TESTBIOS_USA: - if (find_bios(4, &bios)) { // test US + if (emu_findBios(4, &bios)) { // test US strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_EUR: - if (find_bios(8, &bios)) { // test EU + if (emu_findBios(8, &bios)) { // test EU strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; } break; case MA_CDOPT_TESTBIOS_JAP: - if (find_bios(1, &bios)) { // test JP + if (emu_findBios(1, &bios)) { // test JP strcpy(romFileName, bios); engineState = PGS_ReloadRom; return; @@ -1259,7 +1254,6 @@ static void menu_options_save(void) // unbind XYZ MODE, just in case unbind_action(0xf00, -1, -1); } - scaling_update(); } static int menu_loop_options(void) @@ -1697,7 +1691,7 @@ int menu_loop_tray(void) selfname = romsel_loop(curr_path); if (selfname) { int ret = -1, cd_type; - cd_type = emu_cd_check(NULL); + cd_type = emu_cdCheck(NULL); if (cd_type > 0) ret = Insert_CD(romFileName, cd_type == 2); if (ret != 0) { diff --git a/gp2x/menu.h b/gp2x/menu.h index bd216a4..7561d34 100644 --- a/gp2x/menu.h +++ b/gp2x/menu.h @@ -3,8 +3,6 @@ // For commercial use, separate licencing terms must be obtained. -extern char menuErrorMsg[40]; - void menu_loop(void); int menu_loop_tray(void); void menu_romload_prepare(const char *rom_name); diff --git a/gp2x/port_config.h b/gp2x/port_config.h index fd28f79..dcd5032 100644 --- a/gp2x/port_config.h +++ b/gp2x/port_config.h @@ -5,6 +5,9 @@ #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 diff --git a/gp2x/port_config.s b/gp2x/port_config.s index 9fac2a3..87c3e52 100644 --- a/gp2x/port_config.s +++ b/gp2x/port_config.s @@ -1,10 +1,13 @@ @ vim:filetype=armasm -@ .equiv START_ROW, 1 -@ .equiv END_ROW, 27 +@ .equiv START_ROW, 1 +@ .equiv END_ROW, 27 @ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered. -.equiv START_ROW, 0 -.equiv END_ROW, 28 +.equiv START_ROW, 0 +.equiv END_ROW, 28 + +.equiv OVERRIDE_HIGHCOL, 0 @ this should be set to one only for GP2X port -.equiv EXTERNAL_YM2612, 1 +.equiv EXTERNAL_YM2612, 1 +