diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index 611e8db33d..ade0cb89de 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -357,6 +357,7 @@ + diff --git a/BizHawk.Emulation/Consoles/Sega/Saturn/FilePiping.cs b/BizHawk.Emulation/Consoles/Sega/Saturn/FilePiping.cs new file mode 100644 index 0000000000..ca7c297752 --- /dev/null +++ b/BizHawk.Emulation/Consoles/Sega/Saturn/FilePiping.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.IO.Pipes; +using System.Threading; + +namespace BizHawk.Emulation.Consoles.Sega.Saturn +{ + /// + /// helpers for moving files across named pipes + /// + public class FilePiping + { + public void Offer(byte[] data) + { + MemoryStream ms = new MemoryStream(data, false); + Offer(ms); + } + + string PipeName; + Thread thr; + Exception e; + + public string GetPipeName() + { + return PipeName; + } + + public string GetPipeNameNative() + { + return @"\\.\pipe\" + PipeName; + } + + public FilePiping() + { + PipeName = "BizHawk-" + Guid.NewGuid().ToString(); + } + + public void Offer(Stream s) + { + if (thr != null) + throw new Exception("Can only serve one thing at a time!"); + if (e != null) + throw new Exception("Previous attempt failed!", e); + if (!s.CanRead) + throw new ArgumentException("Stream must be readable!"); + + thr = new Thread(delegate() + { + try + { + using (var srv = new NamedPipeServerStream(PipeName, PipeDirection.Out)) + { + srv.WaitForConnection(); + s.CopyTo(srv); + srv.WaitForPipeDrain(); + } + } + catch (Exception ee)// might want to do something about this... + { + e = ee; + } + }); + thr.Start(); + } + + public Exception GetResults() + { + if (thr == null) + throw new Exception("No pending!"); + thr.Join(); + thr = null; + Exception ret = e; + e = null; + return ret; + } + } +} diff --git a/BizHawk.Emulation/Consoles/Sega/Saturn/LibYabause.cs b/BizHawk.Emulation/Consoles/Sega/Saturn/LibYabause.cs index 1eeac89f85..30e2aa2f3e 100644 --- a/BizHawk.Emulation/Consoles/Sega/Saturn/LibYabause.cs +++ b/BizHawk.Emulation/Consoles/Sega/Saturn/LibYabause.cs @@ -83,9 +83,10 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn /// /// /// cd interface. struct need not persist after call, but the function pointers better + /// path to bios, pass null to use built in bios emulation /// [DllImport("libyabause.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libyabause_init(ref CDInterface intf); + public static extern bool libyabause_init(ref CDInterface intf, string biosfn); public struct CDInterface { diff --git a/BizHawk.Emulation/Consoles/Sega/Saturn/Yabause.cs b/BizHawk.Emulation/Consoles/Sega/Saturn/Yabause.cs index b5465bd53d..be795792ef 100644 --- a/BizHawk.Emulation/Consoles/Sega/Saturn/Yabause.cs +++ b/BizHawk.Emulation/Consoles/Sega/Saturn/Yabause.cs @@ -33,16 +33,16 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn LibYabause.CDInterface.ReadSectorFAD ReadSectorFADH; LibYabause.CDInterface.ReadAheadFAD ReadAheadFADH; - public Yabause(CoreComm CoreComm, DiscSystem.Disc CD) + public Yabause(CoreComm CoreComm, DiscSystem.Disc CD, byte[] bios) { CoreComm.RomStatusDetails = "Yeh"; this.CoreComm = CoreComm; this.CD = CD; ResetFrameCounter(); - Init(); + Init(bios); } - void Init() + void Init(byte[] bios) { if (AttachedCore != null) { @@ -60,9 +60,17 @@ namespace BizHawk.Emulation.Consoles.Sega.Saturn CDInt.ReadSectorFADFunc = ReadSectorFADH = new LibYabause.CDInterface.ReadSectorFAD(CD_ReadSectorFAD); CDInt.ReadAheadFADFunc = ReadAheadFADH = new LibYabause.CDInterface.ReadAheadFAD(CD_ReadAheadFAD); - if (!LibYabause.libyabause_init(ref CDInt)) + var fp = new FilePiping(); + string BiosPipe = fp.GetPipeNameNative(); + fp.Offer(bios); + + if (!LibYabause.libyabause_init(ref CDInt, BiosPipe)) throw new Exception("libyabause_init() failed!"); + var e = fp.GetResults(); + if (e != null) + throw e; + LibYabause.libyabause_setvidbuff(VideoHandle.AddrOfPinnedObject()); LibYabause.libyabause_setsndbuff(SoundHandle.AddrOfPinnedObject()); AttachedCore = this; diff --git a/BizHawk.MultiClient/Config.cs b/BizHawk.MultiClient/Config.cs index e732f3cb6d..48c9cc1708 100644 --- a/BizHawk.MultiClient/Config.cs +++ b/BizHawk.MultiClient/Config.cs @@ -256,6 +256,7 @@ namespace BizHawk.MultiClient public string FilenameA78PALBios = "7800PALBIOS.bin"; public string FilenameA78HSCBios = "7800highscore.bin"; public string FilenameINTVEROM = "erom.bin"; + public string FilenameSaturnBios = "Sega Saturn BIOS v1.01 (JAP).bin"; public string FFMpegPath = "%exe%/dll/ffmpeg.exe"; diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index efa481cc3a..37b1d0a5bc 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -2082,8 +2082,16 @@ namespace BizHawk.MultiClient switch (game.System) { case "SAT": - var saturn = new Emulation.Consoles.Sega.Saturn.Yabause(nextComm, disc); - nextEmulator = saturn; + { + string biosPath = PathManager.StandardFirmwareName(Global.Config.FilenameSaturnBios); + if (!File.Exists(biosPath)) + { + MessageBox.Show("Saturn BIOS not found. Please check firmware configurations."); + return false; + } + var saturn = new Emulation.Consoles.Sega.Saturn.Yabause(nextComm, disc, File.ReadAllBytes(biosPath)); + nextEmulator = saturn; + } break; case "PSX": diff --git a/BizHawk.MultiClient/output/dll/libyabause.dll b/BizHawk.MultiClient/output/dll/libyabause.dll index db22f4b26c..e437a48e49 100644 Binary files a/BizHawk.MultiClient/output/dll/libyabause.dll and b/BizHawk.MultiClient/output/dll/libyabause.dll differ diff --git a/yabause/src/libyabause/yui.cpp b/yabause/src/libyabause/yui.cpp index c147e1fbc8..91cf54a18e 100644 --- a/yabause/src/libyabause/yui.cpp +++ b/yabause/src/libyabause/yui.cpp @@ -201,7 +201,7 @@ extern "C" __declspec(dllexport) void libyabause_setpads(u8 p11, u8 p12, u8 p21, ctrl2->padbits[1] = p22; } -extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD) +extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD, const char *biosfn) { FECD.DeInit = _CD->DeInit; FECD.GetStatus = _CD->GetStatus; @@ -227,7 +227,7 @@ extern "C" __declspec(dllexport) int libyabause_init(CDInterface *_CD) yinit.m68kcoretype = M68KCORE_C68K; yinit.cartpath = CART_NONE; yinit.regionid = REGION_AUTODETECT; - yinit.biospath = NULL; + yinit.biospath = biosfn; yinit.cdpath = "Saturnus"; //NULL; yinit.buppath = NULL; yinit.mpegpath = NULL; diff --git a/yabause/src/memory.h b/yabause/src/memory.h index 2de4cbdc47..7cab523ea7 100644 --- a/yabause/src/memory.h +++ b/yabause/src/memory.h @@ -194,7 +194,7 @@ static INLINE void T3WriteLong(T3Memory * mem, u32 addr, u32 val) static INLINE int T123Load(void * mem, u32 size, int type, const char *filename) { FILE *fp; - u32 filesize, filesizecheck; + u32 filesizecheck; u8 *buffer; u32 i; @@ -205,41 +205,47 @@ static INLINE int T123Load(void * mem, u32 size, int type, const char *filename) return -1; // Calculate file size - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fseek(fp, 0, SEEK_SET); + //fseek(fp, 0, SEEK_END); + //filesize = ftell(fp); + //fseek(fp, 0, SEEK_SET); - if (filesize > size) - return -1; + //if (filesize > size) + // return -1; - if ((buffer = (u8 *)malloc(filesize)) == NULL) + if ((buffer = (u8 *)malloc(size)) == NULL) { fclose(fp); return -1; } - filesizecheck = (u32)fread((void *)buffer, 1, filesize, fp); - fclose(fp); + filesizecheck = (u32)fread((void *)buffer, 1, size, fp); + // make sure there are no bytes left in the file + if (filesizecheck != size || fgetc(fp) != EOF) + { + free(buffer); + fclose(fp); + return -1; + } - if (filesizecheck != filesize) return -1; + fclose(fp); switch (type) { case 1: { - for (i = 0; i < filesize; i++) + for (i = 0; i < size; i++) T1WriteByte((u8 *) mem, i, buffer[i]); break; } case 2: { - for (i = 0; i < filesize; i++) + for (i = 0; i < size; i++) T2WriteByte((u8 *) mem, i, buffer[i]); break; } case 3: { - for (i = 0; i < filesize; i++) + for (i = 0; i < size; i++) T3WriteByte((T3Memory *) mem, i, buffer[i]); break; }