整个项目和核心都不再强依赖System.IO进行文件读写,为Switch坐准备

This commit is contained in:
sin365 2025-04-25 10:30:52 +08:00
parent 1f33d35394
commit 24036739a7
17 changed files with 264 additions and 223 deletions

View File

@ -9,7 +9,6 @@ public static class EmuStandInfo
//public static string datDirectoryPath; //public static string datDirectoryPath;
//public static string metadataDatabaseFilePath; //public static string metadataDatabaseFilePath;
public static string jsonConfigFileName;//= "Config.json"; public static string jsonConfigFileName;//= "Config.json";
public static string saveDataDirectoryName;//= "Saves"; public static string saveDataDirectoryName;//= "Saves";
public static string screenshotDirectoryName;//= "Screenshots"; public static string screenshotDirectoryName;//= "Screenshots";

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace StoicGooseUnity namespace StoicGooseUnity
@ -95,21 +94,21 @@ namespace StoicGooseUnity
} }
#endregion #endregion
public static void Write(this BinaryWriter bw, byte* bufferPtr, int offset, int count) public static void Write(this System.IO.BinaryWriter bw, byte* bufferPtr, int offset, int count)
{ {
// 使用指针复制数据到临时数组 // 使用指针复制数据到临时数组
Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count); Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count);
// 使用BinaryWriter写入临时数组 // 使用BinaryWriter写入临时数组
bw.Write(TempBuffer_src, 0, count); bw.Write(TempBuffer_src, 0, count);
} }
public static void Write(this FileStream fs, byte* bufferPtr, int offset, int count) public static void Write(this System.IO.FileStream fs, byte* bufferPtr, int offset, int count)
{ {
// 使用指针复制数据到临时数组 // 使用指针复制数据到临时数组
Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count); Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count);
// 使用BinaryWriter写入临时数组 // 使用BinaryWriter写入临时数组
fs.Write(TempBuffer_src, 0, count); fs.Write(TempBuffer_src, 0, count);
} }
public static int Read(this FileStream fs, byte* bufferPtr, int offset, int count) public static int Read(this System.IO.FileStream fs, byte* bufferPtr, int offset, int count)
{ {
// 使用BinaryWriter写入临时数组 // 使用BinaryWriter写入临时数组
count = fs.Read(TempBuffer_src, offset, count); count = fs.Read(TempBuffer_src, offset, count);

View File

@ -1,5 +1,5 @@
using System; using System;
using System.IO; //using System.IO;
using System.Linq; using System.Linq;
namespace StoicGoose.Common.Drawing namespace StoicGoose.Common.Drawing
@ -10,46 +10,46 @@ namespace StoicGoose.Common.Drawing
public class RgbaFile public class RgbaFile
{ {
const string expectedMagic = "RGBA"; //const string expectedMagic = "RGBA";
public string MagicNumber { get; protected set; } //public string MagicNumber { get; protected set; }
public uint Width { get; protected set; } //public uint Width { get; protected set; }
public uint Height { get; protected set; } //public uint Height { get; protected set; }
public byte[] PixelData { get; protected set; } //public byte[] PixelData { get; protected set; }
public RgbaFile(string filename) : this(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } //public RgbaFile(string filename) : this(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
public RgbaFile(Stream stream) //public RgbaFile(System.IO.Stream stream)
{ //{
MagicNumber = ReadString(stream, 4); // MagicNumber = ReadString(stream, 4);
Width = ReadUInt32(stream); // Width = ReadUInt32(stream);
Height = ReadUInt32(stream); // Height = ReadUInt32(stream);
PixelData = new byte[Width * Height * 4]; // PixelData = new byte[Width * Height * 4];
stream.Read(PixelData); // stream.Read(PixelData);
} //}
public RgbaFile(uint width, uint height, byte[] pixelData) //public RgbaFile(uint width, uint height, byte[] pixelData)
{ //{
MagicNumber = expectedMagic; // MagicNumber = expectedMagic;
Width = width; // Width = width;
Height = height; // Height = height;
PixelData = pixelData; // PixelData = pixelData;
} //}
public void Save(string filename) => Save(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)); //public void Save(string filename) => Save(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite));
public void Save(Stream stream) //public void Save(Stream stream)
{ //{
WriteString(stream, MagicNumber); // WriteString(stream, MagicNumber);
WriteUInt32(stream, Width); // WriteUInt32(stream, Width);
WriteUInt32(stream, Height); // WriteUInt32(stream, Height);
stream.Write(PixelData); // stream.Write(PixelData);
} //}
private static string ReadString(Stream stream, int length) => new(Enumerable.Range(0, length).Select(_ => (char)stream.ReadByte()).ToArray()); //private static string ReadString(Stream stream, int length) => new(Enumerable.Range(0, length).Select(_ => (char)stream.ReadByte()).ToArray());
private static uint ReadUInt32(Stream stream) => (uint)(((stream.ReadByte() & 0xFF) << 24) | ((stream.ReadByte() & 0xFF) << 16) | ((stream.ReadByte() & 0xFF) << 8) | ((stream.ReadByte() & 0xFF) << 0)); //private static uint ReadUInt32(Stream stream) => (uint)(((stream.ReadByte() & 0xFF) << 24) | ((stream.ReadByte() & 0xFF) << 16) | ((stream.ReadByte() & 0xFF) << 8) | ((stream.ReadByte() & 0xFF) << 0));
private static void WriteString(Stream stream, string str) => Array.ForEach(str.ToCharArray(), (x) => stream.WriteByte((byte)x)); //private static void WriteString(Stream stream, string str) => Array.ForEach(str.ToCharArray(), (x) => stream.WriteByte((byte)x));
private static void WriteUInt32(Stream stream, uint val) { stream.WriteByte((byte)((val >> 24) & 0xFF)); stream.WriteByte((byte)((val >> 16) & 0xFF)); stream.WriteByte((byte)((val >> 8) & 0xFF)); stream.WriteByte((byte)((val >> 0) & 0xFF)); } //private static void WriteUInt32(Stream stream, uint val) { stream.WriteByte((byte)((val >> 24) & 0xFF)); stream.WriteByte((byte)((val >> 16) & 0xFF)); stream.WriteByte((byte)((val >> 8) & 0xFF)); stream.WriteByte((byte)((val >> 0) & 0xFF)); }
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.IO;
namespace StoicGoose.Common.Utilities namespace StoicGoose.Common.Utilities
{ {
@ -32,37 +31,37 @@ namespace StoicGoose.Common.Utilities
if ((segmentStart + segmentLength) > dataLength) throw new Exception("Segment end offset is greater than total length"); if ((segmentStart + segmentLength) > dataLength) throw new Exception("Segment end offset is greater than total length");
} }
public static uint Calculate(FileInfo fileInfo) //public static uint Calculate(FileInfo fileInfo)
{ //{
return Calculate(fileInfo, 0, (int)fileInfo.Length); // return Calculate(fileInfo, 0, (int)fileInfo.Length);
} //}
public static uint Calculate(FileInfo fileInfo, int start, int length) //public static uint Calculate(FileInfo fileInfo, int start, int length)
{ //{
VerifyStartAndLength((int)fileInfo.Length, start, length); // VerifyStartAndLength((int)fileInfo.Length, start, length);
using FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // using FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Calculate(file, start, length); // return Calculate(file, start, length);
} //}
public static uint Calculate(Stream stream) //public static uint Calculate(Stream stream)
{ //{
return Calculate(stream, 0, (int)stream.Length); // return Calculate(stream, 0, (int)stream.Length);
} //}
public static uint Calculate(Stream stream, int start, int length) //public static uint Calculate(Stream stream, int start, int length)
{ //{
VerifyStartAndLength((int)stream.Length, start, length); // VerifyStartAndLength((int)stream.Length, start, length);
var lastStreamPosition = stream.Position; // var lastStreamPosition = stream.Position;
var data = new byte[length]; // var data = new byte[length];
stream.Position = start; // stream.Position = start;
stream.Read(data, 0, length); // stream.Read(data, 0, length);
var crc = Calculate(data, 0, data.Length); // var crc = Calculate(data, 0, data.Length);
stream.Position = lastStreamPosition; // stream.Position = lastStreamPosition;
return crc; // return crc;
} //}
public static uint Calculate(byte[] data) public static uint Calculate(byte[] data)
{ {

View File

@ -1,41 +1,40 @@
using System.IO; //using System.Reflection;
using System.Reflection;
using StoicGoose.Common.Drawing; //using StoicGoose.Common.Drawing;
namespace StoicGoose.Common.Utilities //namespace StoicGoose.Common.Utilities
{ //{
public static class Resources // public static class Resources
{ // {
private static Stream GetEmbeddedResourceStream(string name) // //private static System.IO.Stream GetEmbeddedResourceStream(string name)
{ // //{
var assembly = Assembly.GetEntryAssembly(); // // var assembly = Assembly.GetEntryAssembly();
name = $"{assembly.GetName().Name}.{name}"; // // name = $"{assembly.GetName().Name}.{name}";
return assembly.GetManifestResourceStream(name); // // return assembly.GetManifestResourceStream(name);
} // //}
public static RgbaFile GetEmbeddedRgbaFile(string name) // //public static RgbaFile GetEmbeddedRgbaFile(string name)
{ // //{
using var stream = GetEmbeddedResourceStream(name); // // using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return null; // // if (stream == null) return null;
return new RgbaFile(stream); // // return new RgbaFile(stream);
} // //}
public static string GetEmbeddedText(string name) // //public static string GetEmbeddedText(string name)
{ // //{
using var stream = GetEmbeddedResourceStream(name); // // using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return string.Empty; // // if (stream == null) return string.Empty;
using var reader = new StreamReader(stream); // // using var reader = new StreamReader(stream);
return reader.ReadToEnd(); // // return reader.ReadToEnd();
} // //}
public static byte[] GetEmbeddedRawData(string name) // //public static byte[] GetEmbeddedRawData(string name)
{ // //{
using var stream = GetEmbeddedResourceStream(name); // // using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return null; // // if (stream == null) return null;
var buffer = new byte[stream.Length]; // // var buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length); // // stream.Read(buffer, 0, buffer.Length);
return buffer; // // return buffer;
} // //}
} // }
} //}

View File

@ -55,9 +55,12 @@ namespace AxibugEmuOnline.Client.ClientCore
static string s_persistentRoot = static string s_persistentRoot =
#if UNITY_PSP2 && !UNITY_EDITOR //PSV真机 #if UNITY_PSP2 && !UNITY_EDITOR //PSV真机
"ux0:data/AxibugEmu"; "ux0:data/AxibugEmu";
#elif UNITY_SWITCH && !UNITY_EDITOR //Switch 真机
$"save:/AxibugEmu";
#else #else
Application.persistentDataPath; Application.persistentDataPath;
#endif #endif
public static string PersistentDataPath(RomPlatformType emuPlatform) public static string PersistentDataPath(RomPlatformType emuPlatform)
{ {
return s_persistentRoot + "/" + emuPlatform.ToString(); return s_persistentRoot + "/" + emuPlatform.ToString();

View File

@ -1,122 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using UnityEngine;
namespace AxiIO namespace AxiIO
{ {
public interface IAxiIO
{
bool dir_Exists(string dirpath);
void dir_CreateDirectory(string dirpath);
IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern);
void dir_Delete(string path, bool recursive);
byte[] file_ReadAllBytes(string filePath);
bool file_Exists(string filePath);
void file_Delete(string filePath);
void file_WriteAllBytes(string filePath, byte[] data);
void file_WriteAllBytes(string filePath, System.IO.MemoryStream ms);
};
public class CSharpIO : IAxiIO
{
public void dir_CreateDirectory(string dirpath)
{
System.IO.Directory.CreateDirectory(dirpath);
}
public void dir_Delete(string path, bool recursive)
{
System.IO.Directory.Delete(path, recursive);
}
public IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern)
{
return System.IO.Directory.EnumerateFiles(path, searchPattern);
}
public bool dir_Exists(string dirpath)
{
return System.IO.Directory.Exists(dirpath);
}
public void file_WriteAllBytes(string filePath, byte[] data)
{
System.IO.File.WriteAllBytes(filePath, data);
}
public void file_WriteAllBytes(string filePath, MemoryStream ms)
{
System.IO.File.WriteAllBytes(filePath, ms.ToArray());
}
public void file_Delete(string filePath)
{
System.IO.File.Delete(filePath);
}
public bool file_Exists(string filePath)
{
return System.IO.File.Exists(filePath);
}
public byte[] file_ReadAllBytes(string filePath)
{
return System.IO.File.ReadAllBytes(filePath);
}
}
public class NintendoSwitchIO : IAxiIO
{
public NintendoSwitchIO()
{
AxiNS.instance.Init();
}
public void dir_CreateDirectory(string dirpath)
{
AxiNS.instance.io.CreateDir(dirpath);
}
public void dir_Delete(string path, bool recursive)
{
AxiNS.instance.io.DeletePathFile(path);
}
public IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern)
{
throw new NotImplementedException();
}
public bool dir_Exists(string dirpath)
{
return AxiNS.instance.io.CheckPathExists(dirpath);
}
public void file_Delete(string filePath)
{
AxiNS.instance.io.DeletePathFile(filePath);
}
public bool file_Exists(string filePath)
{
return AxiNS.instance.io.CheckPathExists(filePath);
}
public byte[] file_ReadAllBytes(string filePath)
{
return AxiNS.instance.io.LoadSwitchDataFile(filePath);
}
public void file_WriteAllBytes(string filePath, byte[] data)
{
AxiNS.instance.io.FileToSaveWithCreate(filePath, data);
}
public void file_WriteAllBytes(string filePath, MemoryStream ms)
{
AxiNS.instance.io.FileToSaveWithCreate(filePath,ms);
}
}
public static class AxiIO public static class AxiIO
{ {
static IAxiIO m_io; static IAxiIO m_io;
@ -126,10 +14,11 @@ namespace AxiIO
{ {
if (m_io == null) if (m_io == null)
{ {
if (UnityEngine.Application.platform == RuntimePlatform.Switch) #if UNITY_SWITCH && !UNITY_EDITOR
m_io = new NintendoSwitchIO(); m_io = new NintendoSwitchIO();
else #else
m_io = new CSharpIO(); m_io = new CSharpIO();
#endif
} }
return m_io; return m_io;
} }
@ -151,6 +40,10 @@ namespace AxiIO
{ {
return AxiIO.io.file_ReadAllBytes(filePath); return AxiIO.io.file_ReadAllBytes(filePath);
} }
internal static int ReadBytesToArr(string filePath, byte[] readToArr, int start, int len)
{
return AxiIO.io.file_ReadBytesToArr(filePath, readToArr, start, len);
}
internal static void WriteAllBytes(string path, byte[] data) internal static void WriteAllBytes(string path, byte[] data)
{ {
@ -162,6 +55,7 @@ namespace AxiIO
AxiIO.io.file_WriteAllBytes(path, ms); AxiIO.io.file_WriteAllBytes(path, ms);
} }
} }
public static class Directory public static class Directory
{ {
public static bool Exists(string dirpath) public static bool Exists(string dirpath)

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace AxiIO
{
public class CSharpIO : IAxiIO
{
public void dir_CreateDirectory(string dirpath)
{
System.IO.Directory.CreateDirectory(dirpath);
}
public void dir_Delete(string path, bool recursive)
{
System.IO.Directory.Delete(path, recursive);
}
public IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern)
{
return System.IO.Directory.EnumerateFiles(path, searchPattern);
}
public bool dir_Exists(string dirpath)
{
return System.IO.Directory.Exists(dirpath);
}
public void file_WriteAllBytes(string filePath, byte[] data)
{
System.IO.File.WriteAllBytes(filePath, data);
}
public void file_WriteAllBytes(string filePath, MemoryStream ms)
{
System.IO.File.WriteAllBytes(filePath, ms.ToArray());
}
public void file_Delete(string filePath)
{
System.IO.File.Delete(filePath);
}
public bool file_Exists(string filePath)
{
return System.IO.File.Exists(filePath);
}
public byte[] file_ReadAllBytes(string filePath)
{
return System.IO.File.ReadAllBytes(filePath);
}
public int file_ReadBytesToArr(string filePath, byte[] readToArr, int start, int len)
{
FileStream streaming = System.IO.File.OpenRead(filePath);
return streaming.Read(readToArr, 0, 4);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f01df62ce36a4da4f9a20b4758d59102

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace AxiIO
{
public interface IAxiIO
{
bool dir_Exists(string dirpath);
void dir_CreateDirectory(string dirpath);
IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern);
void dir_Delete(string path, bool recursive);
byte[] file_ReadAllBytes(string filePath);
bool file_Exists(string filePath);
void file_Delete(string filePath);
void file_WriteAllBytes(string filePath, byte[] data);
void file_WriteAllBytes(string filePath, System.IO.MemoryStream ms);
int file_ReadBytesToArr(string filePath, byte[] readToArr, int start, int len);
};
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 588eae2a7e121cc40907d8ac6f4250d4

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace AxiIO
{
public class NintendoSwitchIO : IAxiIO
{
public NintendoSwitchIO()
{
AxiNS.instance.Init();
}
public void dir_CreateDirectory(string dirpath)
{
AxiNS.instance.io.CreateDir(dirpath);
}
public void dir_Delete(string path, bool recursive)
{
AxiNS.instance.io.DeletePathFile(path);
}
public IEnumerable<string> dir_EnumerateFiles(string path, string searchPattern)
{
throw new NotImplementedException();
}
public bool dir_Exists(string dirpath)
{
return AxiNS.instance.io.CheckPathExists(dirpath);
}
public void file_Delete(string filePath)
{
AxiNS.instance.io.DeletePathFile(filePath);
}
public bool file_Exists(string filePath)
{
return AxiNS.instance.io.CheckPathExists(filePath);
}
public byte[] file_ReadAllBytes(string filePath)
{
return AxiNS.instance.io.LoadSwitchDataFile(filePath);
}
public int file_ReadBytesToArr(string filePath, byte[] readToArr, int start, int len)
{
byte[] bytes = file_ReadAllBytes(filePath);
int templen = Math.Min(len, bytes.Length);
Array.Copy(readToArr, readToArr, len);
return templen;
}
public void file_WriteAllBytes(string filePath, byte[] data)
{
AxiNS.instance.io.FileToSaveWithCreate(filePath, data);
}
public void file_WriteAllBytes(string filePath, MemoryStream ms)
{
AxiNS.instance.io.FileToSaveWithCreate(filePath, ms);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3da9b14bf7568f34989774dc5f5fbcf4

View File

@ -178,7 +178,7 @@ public class UEssgee : MonoBehaviour, IEmuCore
private void InitAppEnvironment(string CustonDataDir, IEssgeeIOSupport uegIO) private void InitAppEnvironment(string CustonDataDir, IEssgeeIOSupport uegIO)
{ {
EmulatorHandler.io = uegIO; Essgee.Emulation.EmulatorHandler.io = uegIO;
EssgeeLogger.Init(uegLog); EssgeeLogger.Init(uegLog);
//EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro"); //EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro");

View File

@ -1,5 +1,4 @@
using MAME.Core; using MAME.Core;
using System.IO;
public class UniIO : IMAMEIOSupport public class UniIO : IMAMEIOSupport
{ {
@ -13,7 +12,7 @@ public class UniIO : IMAMEIOSupport
return AxiIO.File.ReadAllBytes(path); return AxiIO.File.ReadAllBytes(path);
} }
public void File_WriteAllBytesFromStre(string path, MemoryStream ms) public void File_WriteAllBytesFromStre(string path, System.IO.MemoryStream ms)
{ {
AxiIO.File.WriteAllBytesFromStream(path, ms); AxiIO.File.WriteAllBytesFromStream(path, ms);
} }

View File

@ -9,7 +9,6 @@ public class EmulatorHandler
{ {
readonly static string threadName = $"Unity_Emulation"; readonly static string threadName = $"Unity_Emulation";
public static IEssgeeIOSupport io;
//Thread thread = default; //Thread thread = default;
volatile bool threadRunning = false, threadPaused = false; volatile bool threadRunning = false, threadPaused = false;

View File

@ -98,15 +98,14 @@ namespace AxibugEmuOnline.Client
//} //}
//streaming.Dispose(); //streaming.Dispose();
byte[] bytes = AxiIO.File.ReadAllBytes(FilePath); int res = AxiIO.File.ReadBytesToArr(FilePath, saveOrderData,0,4);
if (bytes.Length < 4) //无效的存档文件 if (res < 4) //无效的存档文件
{ {
IsEmpty = true; IsEmpty = true;
AxiIO.File.Delete(FilePath); AxiIO.File.Delete(FilePath);
} }
else else
{ {
Array.Copy(bytes, 0, saveOrderData, 0, 4);
Sequecen = BitConverter.ToUInt32(saveOrderData, 0); Sequecen = BitConverter.ToUInt32(saveOrderData, 0);
} }
} }