static void LoadCommon(MDFNFILE *fp) { try { /* Assign default settings (US NTSC machine) */ sms.display = DISPLAY_NTSC; sms.territory = MDFN_GetSettingI("sms.territory"); sms.use_fm = FALSE; Cart_Init(fp); Cart_LoadNV(); if(IS_SMS && sms.territory == TERRITORY_DOMESTIC) sms.use_fm = MDFN_GetSettingB("sms.fm"); MDFNMP_Init(1024, 65536 / 1024); system_assign_device(PORT_A, DEVICE_PAD2B); system_assign_device(PORT_B, DEVICE_PAD2B); MDFNMP_AddRAM(8192, 0xC000, sms.wram); sms_init(); pio_init(); vdp_init(IS_SMS && sms.territory == TERRITORY_DOMESTIC); render_init(); MDFNGameInfo->GameSetMD5Valid = FALSE; uint32 sndclk; if(sms.display == DISPLAY_PAL) { sndclk = 3546893; MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 313 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198 } else { sndclk = 3579545; MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 262 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198 } MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(sndclk); SMS_SoundInit(sndclk, sms.use_fm); sms.save = 0; system_reset(); } catch(...) { Cleanup(); throw; } }
static int Load(const char *name, MDFNFILE *fp) { LoadFunction_t LoadFunction = NULL; LoadFunction = GetLoadFunctionByMagic(name, fp); // If the file type isn't recognized, return -1! if(!LoadFunction) return(-1); InitCommon(name); if(!LoadFunction(name, fp, GameInterface)) { free(GameInterface); GameInterface = NULL; return(0); } { int w; if(MDFNGameInfo->VideoSystem == VIDSYS_NTSC) w = 0; else if(MDFNGameInfo->VideoSystem == VIDSYS_PAL) w = 1; else { w = MDFN_GetSettingB("nes.pal"); MDFNGameInfo->VideoSystem = w ? VIDSYS_PAL : VIDSYS_NTSC; } PAL=w?1:0; MDFNGameInfo->fps = PAL? 838977920 : 1008307711; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); } X6502_Init(); MDFNPPU_Init(); MDFNSND_Init(PAL); NESINPUT_Init(); if(NESIsVSUni) MDFN_VSUniInstallRWHooks(); if(MDFNGameInfo->GameType != GMT_PLAYER) if(MDFN_GetSettingB("nes.gg")) Genie_Init(); PowerNES(); MDFN_InitPalette(NESIsVSUni ? MDFN_VSUniGetPaletteNum() : 0); return(1); }
static void Load(MDFNFILE* fp) { try { std::vector<std::string> SongNames; ssf_loader = new SSFLoader(fp->stream()); SongNames.push_back(ssf_loader->tags.GetTag("title")); Player_Init(1, ssf_loader->tags.GetTag("game"), ssf_loader->tags.GetTag("artist"), ssf_loader->tags.GetTag("copyright"), SongNames, false); SOUND_Init(); EmulatedSSFPlay.fps = 75 * 65536 * 256; EmulatedSSFPlay.MasterClock = MDFN_MASTERCLOCK_FIXED(44100 * 256); Reset(); } catch(...) { Cleanup(); throw; } }
static MDFN_COLD void Load(GameFile* gf) { try { LoadFunction_t LoadFunction = NULL; LoadFunction = GetLoadFunctionByMagic(gf); // If the file type isn't recognized, return -1! if(!LoadFunction) throw MDFN_Error(0, _("File format is unknown to module \"%s\"."), MDFNGameInfo->shortname); InitCommon(gf->fbase); LoadFunction(gf->stream, &GameInterface); { int w; if(MDFNGameInfo->VideoSystem == VIDSYS_NTSC) w = 0; else if(MDFNGameInfo->VideoSystem == VIDSYS_PAL) w = 1; else { w = MDFN_GetSettingB("nes.pal"); MDFNGameInfo->VideoSystem = w ? VIDSYS_PAL : VIDSYS_NTSC; } PAL=w?1:0; MDFNGameInfo->fps = PAL? 838977920 : 1008307711; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(PAL ? PAL_CPU : NTSC_CPU); } X6502_Init(); MDFNPPU_Init(); MDFNSND_Init(PAL); NESINPUT_Init(); if(NESIsVSUni) MDFN_VSUniInstallRWHooks(); if(MDFNGameInfo->GameType != GMT_PLAYER) if(MDFN_GetSettingB("nes.gg")) Genie_Init(); PowerNES(); MDFN_InitPalette(NESIsVSUni ? MDFN_VSUniGetPaletteNum() : (bool)PAL, NULL, 0); if(MDFNGameInfo->GameType != GMT_PLAYER) MDFNGameInfo->CPInfoActiveBF = 1 << (NESIsVSUni ? MDFN_VSUniGetPaletteNum() : (bool)PAL); else MDFNGameInfo->CPInfoActiveBF = 0; } catch(...) { Cleanup(); throw; } }
namespace MODULENAMESPACE { extern MDFNGI ModuleInfo; static const InputDeviceInputInfoStruct GamepadIDII[] = { {"select", "SELECT", 15, IDIT_BUTTON, NULL}, {"l3", "L3", 13, IDIT_BUTTON, NULL}, {"r3", "R3", 10, IDIT_BUTTON, NULL}, {"start", "START", 14, IDIT_BUTTON, NULL}, {"up", "UP", 0, IDIT_BUTTON, "down"}, {"right", "RIGHT", 3, IDIT_BUTTON, "left"}, {"down", "DOWN", 1, IDIT_BUTTON, "up"}, {"left", "LEFT", 2, IDIT_BUTTON, "right"}, {"l2", "L2", 12, IDIT_BUTTON, NULL}, {"r2", "R2", 9, IDIT_BUTTON, NULL}, {"l1", "L1", 11, IDIT_BUTTON, NULL}, {"r1", "R1", 8, IDIT_BUTTON, NULL}, {"triangle","TRIANGLE", 4, IDIT_BUTTON, 0}, {"circle", "CIRCLE", 5, IDIT_BUTTON, 0}, {"cross", "CROSS", 6, IDIT_BUTTON, 0}, {"square", "SQUARE", 7, IDIT_BUTTON, 0}, }; static InputDeviceInfoStruct InputDeviceInfoPSXPort[] = { {"none", "none", NULL, 0, NULL}, {"gamepad", "Gamepad", NULL, 16, GamepadIDII}, }; static const InputPortInfoStruct PortInfo[] = { {0, "port1", "Port 1", 2, InputDeviceInfoPSXPort, "gamepad"}, {0, "port2", "Port 2", 2, InputDeviceInfoPSXPort, "gamepad"}, }; static InputInfoStruct ModuleInput = { 1, PortInfo }; static FileExtensionSpecStruct ModuleExtensions[] = { {".cue", "PSX Cue File"}, {0, 0} }; static MDFNSetting ModuleSettings[] = { {"pcsxr.bios", MDFNSF_EMU_STATE, "Path to required PSX BIOS ROM image.", NULL, MDFNST_STRING, "scph1001.bin"}, {"pcsxr.recompiler", MDFNSF_NOFLAGS, "Enable the dynamic recompiler. (Need to restart mednafen to change).", NULL, MDFNST_BOOL, "0"}, {"pcsxr.slowboot", MDFNSF_NOFLAGS, "Show the BIOS booting screen.", NULL, MDFNST_BOOL, "1"}, {NULL} }; static int ModuleLoad () { //Load the BIOS MDFNFILE biosFile; if(biosFile.Open(MDFN_MakeFName(MDFNMKF_FIRMWARE, 0, MDFN_GetSettingS("pcsxr.bios").c_str()).c_str(), 0)) { if(biosFile.size == 512 * 1024) { memcpy(BiosBuffer, biosFile.data, 512 * 1024); } else { MDFN_printf("pcsxr: BIOS file size incorrect\n"); } } else { MDFN_printf("pcsxr: Failed to load bios\n"); return 0; } //Setup the config structure memset(&Config, 0, sizeof(Config)); Config.PsxAuto = 1; Config.Cpu = MDFN_GetSettingB("pcsxr.recompiler") ? CPU_DYNAREC : CPU_INTERPRETER; Config.SlowBoot = MDFN_GetSettingB("pcsxr.slowboot"); strcpy(Config.PluginsDir, "builtin"); strcpy(Config.Gpu, "builtin"); strcpy(Config.Spu, "builtin"); strcpy(Config.Pad1, "builtin"); strcpy(Config.Pad2, "builtin"); strcpy(Config.Cdr, "builtin"); strcpy(Config.Net, "Disabled"); strncpy(Config.Mcd1, MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), MAXPATHLEN); strncpy(Config.Mcd2, MDFN_MakeFName(MDFNMKF_SAV, 0, "sav2").c_str(), MAXPATHLEN); //Init psx cpu emulator and memory mapping EmuInit(); //Open and initialize all of the plugins OpenPlugins(); //Load memory cards LoadMcds(Config.Mcd1, Config.Mcd2); //Get cdrom ID and init PPF support... CheckCdrom(); //Reset the emulated CPU and Memory EmuReset(); //Prepares the game to run, either runs the CPU thru the bios or finds and loads the game EXE if using the emulated bios LoadCdrom(); //TODO: Set the clock if the machine is PAL //Just say two 1M pages, for fun not profit MDFNMP_Init(1024 * 1024, 2); MDFNMP_AddRAM(1024 * 1024 * 2, 0, (uint8_t*)psxM); return 1; } static bool ModuleTestMagic () { //TODO: Does this work in all cases? uint8_t Buffer[4000]; CDIF_ReadRawSector(Buffer, 4); return Buffer[56] == 'S' && Buffer[57] == 'o' && Buffer[58] == 'n' && Buffer[59] == 'y'; } static void ModuleCloseGame () { EmuShutdown(); ClosePlugins(); //Kill resampler Resampler::Kill(); //Close the cheat engine MDFNMP_Kill(); } static int ModuleStateAction (StateMem *sm, int load, int data_only) { //TODO: if(!load) { stateMemory = sm; int result = SaveState(""); stateMemory = 0; return result == 0; } else { stateMemory = sm; int result = LoadState(""); stateMemory = 0; return result == 0; } } static void ModuleEmulate (EmulateSpecStruct *espec) { //AUDIO PREP Resampler::Init(espec, 44100.0); //INPUT g.PadState[0].JoyKeyStatus = ~Input::GetPort<0, 2>(); g.PadState[0].KeyStatus = ~Input::GetPort<0, 2>(); g.PadState[1].JoyKeyStatus = ~Input::GetPort<1, 2>(); g.PadState[1].KeyStatus = ~Input::GetPort<1, 2>(); //CHEATS MDFNMP_ApplyPeriodicCheats(); //EMULATE psxCpu->Execute(); //VIDEO #define RED(x) (x & 0xff) #define BLUE(x) ((x>>16) & 0xff) #define GREEN(x) ((x>>8) & 0xff) #define COLOR(x) (x & 0xffffff) Video::SetDisplayRect(espec, 0, 0, 320, 240); if((g_gpu.dsp.mode.x && g_gpu.dsp.mode.y) && (!(g_gpu.status_reg & STATUS_DISPLAYDISABLED)) && !espec->skip) { Video::SetDisplayRect(espec, 0, 0, (g_gpu.dsp.range.x1 - g_gpu.dsp.range.x0) / g_gpu.dsp.mode.x, (g_gpu.dsp.range.y1 - g_gpu.dsp.range.y0) * g_gpu.dsp.mode.y); uint32_t* pixels = espec->surface->pixels; if(g_gpu.status_reg & STATUS_RGB24) { for(int i = 0; i != espec->DisplayRect.h; i++) { int startxy = ((1024) * (i + g_gpu.dsp.position.y)) + g_gpu.dsp.position.x; unsigned char* pD = (unsigned char *)&g_gpu.psx_vram.u16[startxy]; uint32_t* destpix = (uint32_t *)(pixels + (i * espec->surface->pitchinpix)); for(int j = 0; j != espec->DisplayRect.w; j++) { uint32_t lu = SWAP32(*((uint32_t *)pD)); destpix[j] = 0xff000000 | (RED(lu) << 16) | (GREEN(lu) << 8) | (BLUE(lu)); pD += 3; } } } else { Video::BlitRGB15<0, 1, 2, 2, 1, 0, -1>(espec, &g_gpu.psx_vram.u16[1024 * g_gpu.dsp.position.y + g_gpu.dsp.position.x], espec->DisplayRect.w, espec->DisplayRect.h, 1024); } } else if(g_gpu.status_reg & STATUS_DISPLAYDISABLED) { Video::Clear<uint32_t>(espec, 320, 240); } //AUDIO Resampler::Fetch(espec); //Update timing espec->MasterCycles = 1LL * 100; } static void ModuleSetInput (int port, const char *type, void *ptr) { Input::SetPort(port, (uint8_t*)ptr); } static void ModuleDoSimpleCommand (int cmd) { if(cmd == MDFN_MSC_RESET) { EmuReset(); } else if(cmd == MDFN_MSC_POWER) { EmuReset(); } } MDFNGI ModuleInfo = { /* shortname: */ "pcsxr", /* fullname: */ "Sony Playstation (PCSX-Reloaded)", /* FileExtensions: */ ModuleExtensions, /* ModulePriority: */ MODPRIO_EXTERNAL_HIGH, /* Debugger: */ 0, /* InputInfo: */ &ModuleInput, /* Load: */ 0, /* TestMagic: */ 0, /* LoadCD: */ ModuleLoad, /* TestMagicCD: */ ModuleTestMagic, /* CloseGame: */ ModuleCloseGame, /* ToggleLayer: */ 0, /* LayerNames: */ 0, /* InstallReadPatch: */ 0, /* RemoveReadPatches: */ 0, /* MemRead: */ 0, /* StateAction: */ ModuleStateAction, /* Emulate: */ ModuleEmulate, /* SetInput: */ ModuleSetInput, /* DoSimpleCommand: */ ModuleDoSimpleCommand, /* Settings: */ ModuleSettings, /* MasterClock: */ MDFN_MASTERCLOCK_FIXED(6000), /* fps: */ 0, /* multires: */ true, /* lcm_width: */ 1280, //? /* lcm_height: */ 960, //? /* dummy_separator: */ 0, /* nominal_width: */ 640, //? /* nominal_height: */ 480, //? /* fb_width: */ 1024, /* fb_height: */ 512, /* soundchan: */ 2 }; }
static void LoadCommonPost(const md_game_info &ginfo) { MDFN_printf(_("ROM: %dKiB\n"), (ginfo.rom_size + 1023) / 1024); MDFN_printf(_("ROM CRC32: 0x%08x\n"), ginfo.crc32); MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(ginfo.md5, 0).c_str()); MDFN_printf(_("Header MD5: 0x%s\n"), md5_context::asciistr(ginfo.info_header_md5, 0).c_str()); MDFN_printf(_("Product Code: %s\n"), ginfo.product_code); MDFN_printf(_("Domestic name: %s\n"), ginfo.domestic_name); // TODO: Character set conversion(shift_jis -> utf-8) MDFN_printf(_("Overseas name: %s\n"), ginfo.overseas_name); MDFN_printf(_("Copyright: %s\n"), ginfo.copyright); if(ginfo.checksum == ginfo.checksum_real) MDFN_printf(_("Checksum: 0x%04x\n"), ginfo.checksum); else MDFN_printf(_("Checksum: 0x%04x\n Warning: calculated checksum(0x%04x) does not match\n"), ginfo.checksum, ginfo.checksum_real); MDFN_printf(_("Supported I/O devices:\n")); MDFN_indent(1); for(unsigned int iot = 0; iot < sizeof(IO_types) / sizeof(IO_type_t); iot++) { if(ginfo.io_support & (1 << IO_types[iot].id)) MDFN_printf(_("%s\n"), _(IO_types[iot].name)); } MDFN_indent(-1); MDFNMP_Init(8192, (1 << 24) / 8192); MDFNMP_AddRAM(65536, 0x7 << 21, work_ram); MDFNGameInfo->GameSetMD5Valid = FALSE; MDSound_Init(); MDFN_printf(_("Supported regions:\n")); MDFN_indent(1); if(ginfo.region_support & REGIONMASK_JAPAN_NTSC) MDFN_printf(_("Japan/Domestic NTSC\n")); if(ginfo.region_support & REGIONMASK_JAPAN_PAL) MDFN_printf(_("Japan/Domestic PAL\n")); if(ginfo.region_support & REGIONMASK_OVERSEAS_NTSC) MDFN_printf(_("Overseas NTSC\n")); if(ginfo.region_support & REGIONMASK_OVERSEAS_PAL) MDFN_printf(_("Overseas PAL\n")); MDFN_indent(-1); { const int region_setting = MDFN_GetSettingI("md.region"); const int reported_region_setting = MDFN_GetSettingI("md.reported_region"); // Default, in case the game doesn't support any regions! bool game_overseas = TRUE; bool game_pal = FALSE; bool overseas; bool pal; bool overseas_reported; bool pal_reported; // Preference order, TODO: Make it configurable if(ginfo.region_support & REGIONMASK_OVERSEAS_NTSC) { game_overseas = TRUE; game_pal = FALSE; } else if(ginfo.region_support & REGIONMASK_JAPAN_NTSC) { game_overseas = FALSE; game_pal = FALSE; } else if(ginfo.region_support & REGIONMASK_OVERSEAS_PAL) { game_overseas = TRUE; game_pal = TRUE; } else if(ginfo.region_support & REGIONMASK_JAPAN_PAL) // WTF? { game_overseas = FALSE; game_pal = TRUE; } if(region_setting == REGION_GAME) { overseas = game_overseas; pal = game_pal; } else { decode_region_setting(region_setting, overseas, pal); } if(reported_region_setting == REGION_GAME) { overseas_reported = game_overseas; pal_reported = game_pal; } else if(reported_region_setting == REGION_SAME) { overseas_reported = overseas; pal_reported = pal; } else { decode_region_setting(reported_region_setting, overseas_reported, pal_reported); } MDFN_printf("\n"); MDFN_printf(_("Active Region: %s %s\n"), overseas ? _("Overseas") : _("Domestic"), pal ? _("PAL") : _("NTSC")); MDFN_printf(_("Active Region Reported: %s %s\n"), overseas_reported ? _("Overseas") : _("Domestic"), pal_reported ? _("PAL") : _("NTSC")); system_init(overseas, pal, overseas_reported, pal_reported); if(pal) MDFNGameInfo->nominal_height = 240; else MDFNGameInfo->nominal_height = 224; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(pal ? CLOCK_PAL : CLOCK_NTSC); if(pal) MDFNGameInfo->fps = (int64)CLOCK_PAL * 65536 * 256 / (313 * 3420); else MDFNGameInfo->fps = (int64)CLOCK_NTSC * 65536 * 256 / (262 * 3420); //printf("%f\n", (double)MDFNGameInfo->fps / 65536 / 256); } if(MDFN_GetSettingB("md.correct_aspect")) { MDFNGameInfo->nominal_width = 292; MDFNGameInfo->lcm_width = 1280; } else { MDFNGameInfo->nominal_width = 320; MDFNGameInfo->lcm_width = 320; } MDFNGameInfo->lcm_height = MDFNGameInfo->nominal_height * 2; MDFNGameInfo->LayerNames = "BG0\0BG1\0OBJ\0"; // // { unsigned mtt = MDFN_GetSettingUI("md.input.multitap"); if(MDFN_GetSettingB("md.input.auto")) { for(auto const& e : InputDB) { if(e.crc32 == ginfo.crc32 && (!e.prod_code || !strcmp(e.prod_code, ginfo.product_code))) { MDFNGameInfo->DesiredInput.resize(8); for(unsigned n = e.max_players; n < 8; n++) // Particularly for Gauntlet 4. MDFNGameInfo->DesiredInput[n] = "none"; mtt = e.tap; break; } } } for(const auto* mte = MultiTap_List; mte->string; mte++) { if((unsigned)mte->number == mtt) { MDFN_printf(_("Active Multitap(s): %s\n"), mte->description); break; } } MDINPUT_SetMultitap(mtt); } // // system_reset(true); }
CloseGame, SetLayerEnableMask, "Background Scroll\0Foreground Scroll\0Sprites\0", NULL, NULL, NULL, NULL, NULL, NULL, false, StateAction, Emulate, SetInput, DoSimpleCommand, NGPSettings, MDFN_MASTERCLOCK_FIXED(6144000), 0, false, // Multires possible? 160, // lcm_width 152, // lcm_height NULL, // Dummy 160, // Nominal width 152, // Nominal height 160, // Framebuffer width 152, // Framebuffer height 2, // Number of output sound channels
TestMagicCD, CloseGame, VDC_SetLayerEnableMask, NULL, NULL, NULL, NULL, NULL, MemRead, false, StateAction, Emulate, PCEINPUT_SetInput, DoSimpleCommand, PCESettings, MDFN_MASTERCLOCK_FIXED(PCE_MASTER_CLOCK), 0, true, // Multires possible? 0, // lcm_width 0, // lcm_height NULL, // Dummy 320, // Nominal width 232, // Nominal height 512, // Framebuffer width 242, // Framebuffer height 2, // Number of output sound channels
static int LoadCommon(MDFNFILE *fp) { int32 size = fp->size; const uint8 *data_ptr = fp->data; if(size & 512) { size -= 512; data_ptr += 512; } /* Assign default settings (US NTSC machine) */ sms.display = DISPLAY_NTSC; sms.territory = MDFN_GetSettingI("sms.territory"); sms.use_fm = FALSE; if(!SMS_CartInit(data_ptr, size)) return(0); if(IS_SMS && sms.territory == TERRITORY_DOMESTIC) sms.use_fm = MDFN_GetSettingB("sms.fm"); MDFNMP_Init(1024, 65536 / 1024); system_assign_device(PORT_A, DEVICE_PAD2B); system_assign_device(PORT_B, DEVICE_PAD2B); MDFNMP_AddRAM(8192, 0xC000, sms.wram); sms_init(); pio_init(); vdp_init(IS_SMS && sms.territory == TERRITORY_DOMESTIC); render_init(); MDFNGameInfo->GameSetMD5Valid = FALSE; uint32 sndclk; if(sms.display == DISPLAY_PAL) { sndclk = 3546893; MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 313 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198 } else { sndclk = 3579545; MDFNGameInfo->fps = (uint32)((uint64)65536 * 256 * sndclk / 262 / 228); //6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198 } MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(sndclk); SMS_SoundInit(sndclk, sms.use_fm); sms.save = 0; system_reset(); return(1); }
TestMagicCD, CloseGame, VDC_SetLayerEnableMask, NULL, NULL, NULL, NULL, NULL, MemRead, false, StateAction, Emulate, PCEINPUT_SetInput, DoSimpleCommand, PCESettings, int64(MDFN_MASTERCLOCK_FIXED(PCE_MASTER_CLOCK)), 0, true, // Multires possible? 0, // lcm_width 0, // lcm_height NULL, // Dummy 320, // Nominal width 232, // Nominal height 512, // Framebuffer width 242, // Framebuffer height 2, // Number of output sound channels