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;
}