diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index c5198cc317..063328eccd 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -238,7 +238,7 @@ namespace BizHawk.Client.Common try { - var ext = file.Extension.ToLower(); + var ext = file.Extension.ToLowerInvariant(); if (ext == ".m3u") { //HACK ZONE - currently only psx supports m3u @@ -398,7 +398,7 @@ namespace BizHawk.Client.Common break; } } - else if (file.Extension.ToLower() == ".xml") + else if (file.Extension.ToLowerInvariant() == ".xml") { try { @@ -463,22 +463,39 @@ namespace BizHawk.Client.Common } } } + else if (file.Extension.ToLowerInvariant() == ".psf" || file.Extension.ToLowerInvariant() == ".minipsf") + { + Func cbDeflater = (Stream instream, int size) => + { + var inflater = new ICSharpCode.SharpZipLib.Zip.Compression.Inflater(false); + var iis = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(instream, inflater); + MemoryStream ret = new MemoryStream(); + iis.CopyTo(ret); + return ret.ToArray(); + }; + PSF psf = new PSF(); + psf.Load(path, cbDeflater); + nextEmulator = new Octoshock(nextComm, psf, GetCoreSettings(), GetCoreSyncSettings()); + nextEmulator.CoreComm.RomStatusDetails = "It's a PSF, what do you want."; + + //total garbage, this + rom = new RomGame(file); + game = rom.GameInfo; + } else // most extensions { rom = new RomGame(file); //hacky for now - if (file.Extension.ToLower() == ".exe") - { + if (file.Extension.ToLowerInvariant() == ".exe") rom.GameInfo.System = "PSX"; - } if (string.IsNullOrEmpty(rom.GameInfo.System)) { // Has the user picked a preference for this extension? - if (PreferredPlatformIsDefined(rom.Extension.ToLower())) + if (PreferredPlatformIsDefined(rom.Extension.ToLowerInvariant())) { - rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLower()]; + rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLowerInvariant()]; } else if (ChoosePlatform != null) { @@ -499,7 +516,7 @@ namespace BizHawk.Client.Common var isXml = false; // other xml has already been handled - if (file.Extension.ToLower() == ".xml") + if (file.Extension.ToLowerInvariant() == ".xml") { game.System = "SNES"; isXml = true; diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index ce3e4f6018..9c9843d5ee 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -1864,7 +1864,7 @@ namespace BizHawk.Client.EmuHawk { return FormatFilter( "Rom Files", "*.nes;*.fds;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;%ARCH%", - "Music Files", "*.psf;*.sid;*.nsf", + "Music Files", "*.psf;*.minipsf;*.sid;*.nsf", "Disc Images", "*.cue;*.ccd;*.m3u", "NES", "*.nes;*.fds;*.nsf;%ARCH%", "Super NES", "*.smc;*.sfc;*.xml;%ARCH%", @@ -1882,7 +1882,7 @@ namespace BizHawk.Client.EmuHawk "Colecovision", "*.col;%ARCH%", "Intellivision (very experimental)", "*.int;*.bin;*.rom;%ARCH%", "PSX Executables (experimental)", "*.exe", - "PSF Playstation Sound File (not supported)", "*.psf", + "PSF Playstation Sound File", "*.psf;*.minipsf", "Commodore 64 (experimental)", "*.prg; *.d64, *.g64; *.crt;%ARCH%", "SID Commodore 64 Music File", "*.sid;%ARCH%", "Nintendo 64", "*.z64;*.v64;*.n64", diff --git a/BizHawk.Client.MultiHawk/Mainform.cs b/BizHawk.Client.MultiHawk/Mainform.cs index f913a775f5..4483834a48 100644 --- a/BizHawk.Client.MultiHawk/Mainform.cs +++ b/BizHawk.Client.MultiHawk/Mainform.cs @@ -217,7 +217,7 @@ namespace BizHawk.Client.MultiHawk "Colecovision", "*.col;%ARCH%", "Intellivision (very experimental)", "*.int;*.bin;*.rom;%ARCH%", "PSX Executables (experimental)", "*.exe", - "PSF Playstation Sound File (not supported)", "*.psf", + "PSF Playstation Sound File", "*.psf;*.minipsf", "Commodore 64 (experimental)", "*.prg; *.d64, *.g64; *.crt;%ARCH%", "SID Commodore 64 Music File", "*.sid;%ARCH%", "Nintendo 64", "*.z64;*.v64;*.n64", diff --git a/BizHawk.Emulation.Common/Database/Database.cs b/BizHawk.Emulation.Common/Database/Database.cs index 44f9035e4e..16d6b65e85 100644 --- a/BizHawk.Emulation.Common/Database/Database.cs +++ b/BizHawk.Emulation.Common/Database/Database.cs @@ -284,6 +284,7 @@ namespace BizHawk.Emulation.Common break; case ".PSF": + case ".MINIPSF": game.System = "PSX"; break; diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index f4eb67bf9a..d4aa48fdd5 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -769,6 +769,7 @@ + diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs index 02f1b3ddf4..1e81870c93 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs @@ -221,9 +221,21 @@ namespace BizHawk.Emulation.Cores.Sony.PSX public List HackyDiscButtons = new List(); + public Octoshock(CoreComm comm, PSF psf, object settings, object syncSettings) + { + Load(comm, null, null, null, settings, syncSettings, psf); + OctoshockDll.shock_PowerOn(psx); + } + //note: its annoying that we have to have a disc before constructing this. //might want to change that later. HOWEVER - we need to definitely have a region, at least public Octoshock(CoreComm comm, List discs, List discNames, byte[] exe, object settings, object syncSettings) + { + Load(comm, discs, discNames, exe, settings, syncSettings, null); + OctoshockDll.shock_PowerOn(psx); + } + + void Load(CoreComm comm, List discs, List discNames, byte[] exe, object settings, object syncSettings, PSF psf) { ServiceProvider = new BasicServiceProvider(this); (ServiceProvider as BasicServiceProvider).Register(tracer); @@ -237,14 +249,14 @@ namespace BizHawk.Emulation.Cores.Sony.PSX Attach(); - HackyDiscButtons.AddRange(discNames); - //assume this region for EXE and PSF, maybe not correct though string firmwareRegion = "U"; SystemRegion = OctoshockDll.eRegion.NA; if (discs != null) { + HackyDiscButtons.AddRange(discNames); + foreach (var disc in discs) { var discInterface = new DiscInterface(disc, @@ -326,11 +338,25 @@ namespace BizHawk.Emulation.Cores.Sony.PSX CurrentTrayOpen = false; CurrentDiscIndexMounted = 1; } - else + else if (psf == null) { //must be an exe fixed (byte* pExeBuffer = exe) - OctoshockDll.shock_MountEXE(psx, pExeBuffer, exe.Length); + OctoshockDll.shock_MountEXE(psx, pExeBuffer, exe.Length, false); + + //start with no disc inserted and tray closed + CurrentTrayOpen = false; + CurrentDiscIndexMounted = 0; + OctoshockDll.shock_CloseTray(psx); + } + else + { + //must be a psf + if(psf.LibData != null) + fixed (byte* pBuf = psf.LibData) + OctoshockDll.shock_MountEXE(psx, pBuf, psf.LibData.Length, true); + fixed (byte* pBuf = psf.Data) + OctoshockDll.shock_MountEXE(psx, pBuf, psf.Data.Length, false); //start with no disc inserted and tray closed CurrentTrayOpen = false; @@ -359,8 +385,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX //do this after framebuffers and peripherals and whatever crap are setup. kind of lame, but thats how it is for now StudySaveBufferSize(); - - OctoshockDll.shock_PowerOn(psx); } public IEmulatorServiceProvider ServiceProvider { get; private set; } @@ -535,7 +559,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX CurrentDiscIndexMounted = requestedDisc; } - if (CurrentDiscIndexMounted == 0) + if (CurrentDiscIndexMounted == 0 || discInterfaces.Count == 0) { currentDiscInterface = null; OctoshockDll.shock_SetDisc(psx, IntPtr.Zero); diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs index d9ea87a8c9..5f897a0c90 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs @@ -197,7 +197,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX public static extern int shock_Peripheral_PollActive(IntPtr psx, int address, bool clear); [DllImport(dd, CallingConvention = cc)] - public static extern int shock_MountEXE(IntPtr psx, void* exebuf, int size); + public static extern int shock_MountEXE(IntPtr psx, void* exebuf, int size, bool ignore_pcsp); [DllImport(dd, CallingConvention = cc)] public static extern int shock_PowerOn(IntPtr psx); diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs new file mode 100644 index 0000000000..025daee0ed --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Collections.Generic; + +using BizHawk.Common.IOExtensions; + +namespace BizHawk.Emulation.Cores.Sony.PSX +{ + public class PSF + { + public Dictionary TagsDictionary = new Dictionary(); + public List LooseTags = new List(); + + public byte[] Data; + public byte[] LibData; + + public bool Load(string fpPSF, Func cbDeflater) + { + using(var fs = File.OpenRead(fpPSF)) + { + //not endian safe + var br = new BinaryReader(fs); + var sig = br.ReadStringFixedAscii(4); + if (sig != "PSF\x1") + return false; + + int reserved_size = br.ReadInt32(); + int compressed_size = br.ReadInt32(); + int compressed_crc32 = br.ReadInt32(); + + //load tags + //tags run until the end of the file + fs.Position = 16 + reserved_size + compressed_size; + if (br.ReadStringFixedAscii(5) == "[TAG]") + { + var tagstring = br.ReadStringFixedAscii((int)(fs.Length - fs.Position)).Replace("\r\n","\n"); + foreach (var tag in tagstring.Split('\n', '\x0')) + { + if (tag.Trim() == "") + continue; + int eq = tag.IndexOf('='); + if (eq != -1) + TagsDictionary[tag.Substring(0, eq)] = tag.Substring(eq + 1); + else + LooseTags.Add(tag); + } + } + + //load compressed section buffer + fs.Position = 16 + reserved_size; + Data = cbDeflater(fs, compressed_size); + + //load lib if needed + if (TagsDictionary.ContainsKey("_lib")) + { + var fpLib = Path.Combine(Path.GetDirectoryName(fpPSF), TagsDictionary["_lib"]); + if (!File.Exists(fpLib)) + return false; + PSF lib = new PSF(); + if (!lib.Load(fpLib,cbDeflater)) + return false; + LibData = lib.Data; + } + } + + return true; + } + } +} diff --git a/BizHawk.Emulation.Cores/FileID.cs b/BizHawk.Emulation.Cores/FileID.cs index 3367a04906..edc5252484 100644 --- a/BizHawk.Emulation.Cores/FileID.cs +++ b/BizHawk.Emulation.Cores/FileID.cs @@ -280,6 +280,7 @@ namespace BizHawk.Emulation.Cores public static SimpleMagicRecord PSX = new SimpleMagicRecord { Offset = 0x24E0, Key = " Licensed by Sony Computer Entertainment" }; //there might be other ideas for checking in mednafen sources, if we need them public static SimpleMagicRecord PSX_EXE = new SimpleMagicRecord { Key = "PS-X EXE\0" }; public static SimpleMagicRecord PSP = new SimpleMagicRecord { Offset = 0x8000, Key = "\x01CD001\x01\0x00PSP GAME" }; + public static SimpleMagicRecord PSF = new SimpleMagicRecord { Offset = 0, Key = "PSF\x1" }; //https://sites.google.com/site/atari7800wiki/a78-header public static SimpleMagicRecord A78 = new SimpleMagicRecord { Offset = 0, Key = "\x01ATARI7800" }; @@ -348,7 +349,7 @@ namespace BizHawk.Emulation.Cores { "GEN", new ExtensionInfo(FileIDType.SMD, null ) }, //nothing yet... - { "PSF", new ExtensionInfo(FileIDType.PSF, null) }, + { "PSF", new ExtensionInfo(FileIDType.PSF, (j)=>Test_Simple(j,FileIDType.PSF,SimpleMagics.PSF) ) }, { "INT", new ExtensionInfo(FileIDType.INT, null) }, { "SFC", new ExtensionInfo(FileIDType.SFC, null) }, { "SMC", new ExtensionInfo(FileIDType.SFC, null) }, diff --git a/output/dll/octoshock.dll b/output/dll/octoshock.dll index 3ef1311232..ddff56da12 100644 Binary files a/output/dll/octoshock.dll and b/output/dll/octoshock.dll differ diff --git a/psx/octoshock/psx/psx.cpp b/psx/octoshock/psx/psx.cpp index 01a389580a..03b67e105c 100644 --- a/psx/octoshock/psx/psx.cpp +++ b/psx/octoshock/psx/psx.cpp @@ -146,25 +146,6 @@ uint32 PSX_GetRandU32(uint32 mina, uint32 maxa) return PSX_PRNG.RandU32(mina, maxa); } - -#ifdef WANT_PSF -class PSF1Loader : public PSFLoader -{ - public: - - PSF1Loader(MDFNFILE *fp); - virtual ~PSF1Loader(); - - virtual void HandleEXE(const uint8 *data, uint32 len, bool ignore_pcsp = false); - - PSFTags tags; -}; -#else -class PSF1Loader {}; -#endif - - -static PSF1Loader *psf_loader = NULL; static std::vector *cdifs = NULL; static std::vector cdifs_scex_ids; @@ -1404,7 +1385,7 @@ EW_EXPORT s32 shock_Step(void* psx, eShockStep step) SPU->StartFrame(espec.SoundRate, ResampleQuality); Running = -1; - timestamp = CPU->Run(timestamp, psf_loader == NULL && psx_dbg_level >= PSX_DBG_BIOS_PRINT, psf_loader != NULL); + timestamp = CPU->Run(timestamp, psx_dbg_level >= PSX_DBG_BIOS_PRINT, /*psf_loader != NULL*/ false); //huh? assert(timestamp); ForceEventUpdates(timestamp); @@ -1818,42 +1799,16 @@ static void LoadEXE(const uint8 *data, const uint32 size, bool ignore_pcsp = fal po += 4; } -EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size) +EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size, s32 ignore_pcsp) { - LoadEXE((uint8*)exebuf, (uint32)size); + LoadEXE((uint8*)exebuf, (uint32)size, !!ignore_pcsp); return SHOCK_OK; } - -#ifdef WANT_PSF -PSF1Loader::PSF1Loader(MDFNFILE *fp) -{ - tags = Load(0x01, 2033664, fp); -} - - -PSF1Loader::~PSF1Loader() -{ - -} - - -void PSF1Loader::HandleEXE(const uint8 *data, uint32 size, bool ignore_pcsp) -{ - LoadEXE(data, size, ignore_pcsp); -} -#endif - static void Cleanup(void) { TextMem.resize(0); - if(psf_loader) - { - delete psf_loader; - psf_loader = NULL; - } - if(CDC) { delete CDC; @@ -1903,16 +1858,6 @@ static void Cleanup(void) static void CloseGame(void) { - if(!psf_loader) - { - for(int i = 0; i < 8; i++) - { - //DAW - //FIO->SaveMemcard(i, MDFN_MakeFName(MDFNMKF_SAV, 0, ext).c_str()); - } - - } - Cleanup(); } diff --git a/psx/octoshock/psx/psx.h b/psx/octoshock/psx/psx.h index 362305e2c1..ad93ebb5fe 100644 --- a/psx/octoshock/psx/psx.h +++ b/psx/octoshock/psx/psx.h @@ -339,7 +339,7 @@ EW_EXPORT s32 shock_Peripheral_MemcardTransact(void* psx, s32 address, ShockMemc EW_EXPORT s32 shock_Peripheral_PollActive(void* psx, s32 address, s32 clear); //Mounts a PS-EXE executable -EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size); +EW_EXPORT s32 shock_MountEXE(void* psx, void* exebuf, s32 size, s32 ignore_pcsp); //Sets the power to ON. Returns SHOCK_NOCANDO if already on. EW_EXPORT s32 shock_PowerOn(void* psx);