整个项目和核心都不再强依赖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 metadataDatabaseFilePath;
public static string jsonConfigFileName;//= "Config.json";
public static string saveDataDirectoryName;//= "Saves";
public static string screenshotDirectoryName;//= "Screenshots";

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
namespace StoicGooseUnity
@ -95,21 +94,21 @@ namespace StoicGooseUnity
}
#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);
// 使用BinaryWriter写入临时数组
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);
// 使用BinaryWriter写入临时数组
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写入临时数组
count = fs.Read(TempBuffer_src, offset, count);

View File

@ -1,5 +1,5 @@
using System;
using System.IO;
//using System.IO;
using System.Linq;
namespace StoicGoose.Common.Drawing
@ -10,46 +10,46 @@ namespace StoicGoose.Common.Drawing
public class RgbaFile
{
const string expectedMagic = "RGBA";
//const string expectedMagic = "RGBA";
public string MagicNumber { get; protected set; }
public uint Width { get; protected set; }
public uint Height { get; protected set; }
public byte[] PixelData { get; protected set; }
//public string MagicNumber { get; protected set; }
//public uint Width { get; protected set; }
//public uint Height { 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)
{
MagicNumber = ReadString(stream, 4);
Width = ReadUInt32(stream);
Height = ReadUInt32(stream);
PixelData = new byte[Width * Height * 4];
stream.Read(PixelData);
}
//public RgbaFile(System.IO.Stream stream)
//{
// MagicNumber = ReadString(stream, 4);
// Width = ReadUInt32(stream);
// Height = ReadUInt32(stream);
// PixelData = new byte[Width * Height * 4];
// stream.Read(PixelData);
//}
public RgbaFile(uint width, uint height, byte[] pixelData)
{
MagicNumber = expectedMagic;
Width = width;
Height = height;
PixelData = pixelData;
}
//public RgbaFile(uint width, uint height, byte[] pixelData)
//{
// MagicNumber = expectedMagic;
// Width = width;
// Height = height;
// 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)
{
WriteString(stream, MagicNumber);
WriteUInt32(stream, Width);
WriteUInt32(stream, Height);
stream.Write(PixelData);
}
//public void Save(Stream stream)
//{
// WriteString(stream, MagicNumber);
// WriteUInt32(stream, Width);
// WriteUInt32(stream, Height);
// stream.Write(PixelData);
//}
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 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 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 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)); }
}
}

View File

@ -1,5 +1,4 @@
using System;
using System.IO;
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");
}
public static uint Calculate(FileInfo fileInfo)
{
return Calculate(fileInfo, 0, (int)fileInfo.Length);
}
//public static uint Calculate(FileInfo fileInfo)
//{
// return Calculate(fileInfo, 0, (int)fileInfo.Length);
//}
public static uint Calculate(FileInfo fileInfo, int start, int length)
{
VerifyStartAndLength((int)fileInfo.Length, start, length);
//public static uint Calculate(FileInfo fileInfo, int start, int length)
//{
// VerifyStartAndLength((int)fileInfo.Length, start, length);
using FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Calculate(file, start, length);
}
// using FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// return Calculate(file, start, length);
//}
public static uint Calculate(Stream stream)
{
return Calculate(stream, 0, (int)stream.Length);
}
//public static uint Calculate(Stream stream)
//{
// return Calculate(stream, 0, (int)stream.Length);
//}
public static uint Calculate(Stream stream, int start, int length)
{
VerifyStartAndLength((int)stream.Length, start, length);
//public static uint Calculate(Stream stream, int start, int length)
//{
// VerifyStartAndLength((int)stream.Length, start, length);
var lastStreamPosition = stream.Position;
var data = new byte[length];
stream.Position = start;
stream.Read(data, 0, length);
var crc = Calculate(data, 0, data.Length);
stream.Position = lastStreamPosition;
// var lastStreamPosition = stream.Position;
// var data = new byte[length];
// stream.Position = start;
// stream.Read(data, 0, length);
// var crc = Calculate(data, 0, data.Length);
// stream.Position = lastStreamPosition;
return crc;
}
// return crc;
//}
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
{
public static class Resources
{
private static Stream GetEmbeddedResourceStream(string name)
{
var assembly = Assembly.GetEntryAssembly();
name = $"{assembly.GetName().Name}.{name}";
return assembly.GetManifestResourceStream(name);
}
//namespace StoicGoose.Common.Utilities
//{
// public static class Resources
// {
// //private static System.IO.Stream GetEmbeddedResourceStream(string name)
// //{
// // var assembly = Assembly.GetEntryAssembly();
// // name = $"{assembly.GetName().Name}.{name}";
// // return assembly.GetManifestResourceStream(name);
// //}
public static RgbaFile GetEmbeddedRgbaFile(string name)
{
using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return null;
return new RgbaFile(stream);
}
// //public static RgbaFile GetEmbeddedRgbaFile(string name)
// //{
// // using var stream = GetEmbeddedResourceStream(name);
// // if (stream == null) return null;
// // return new RgbaFile(stream);
// //}
public static string GetEmbeddedText(string name)
{
using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return string.Empty;
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
// //public static string GetEmbeddedText(string name)
// //{
// // using var stream = GetEmbeddedResourceStream(name);
// // if (stream == null) return string.Empty;
// // using var reader = new StreamReader(stream);
// // return reader.ReadToEnd();
// //}
public static byte[] GetEmbeddedRawData(string name)
{
using var stream = GetEmbeddedResourceStream(name);
if (stream == null) return null;
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
return buffer;
}
}
}
// //public static byte[] GetEmbeddedRawData(string name)
// //{
// // using var stream = GetEmbeddedResourceStream(name);
// // if (stream == null) return null;
// // var buffer = new byte[stream.Length];
// // stream.Read(buffer, 0, buffer.Length);
// // return buffer;
// //}
// }
//}

View File

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

View File

@ -1,122 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
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
{
static IAxiIO m_io;
@ -126,10 +14,11 @@ namespace AxiIO
{
if (m_io == null)
{
if (UnityEngine.Application.platform == RuntimePlatform.Switch)
#if UNITY_SWITCH && !UNITY_EDITOR
m_io = new NintendoSwitchIO();
else
#else
m_io = new CSharpIO();
#endif
}
return m_io;
}
@ -151,6 +40,10 @@ namespace AxiIO
{
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)
{
@ -162,6 +55,7 @@ namespace AxiIO
AxiIO.io.file_WriteAllBytes(path, ms);
}
}
public static class Directory
{
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)
{
EmulatorHandler.io = uegIO;
Essgee.Emulation.EmulatorHandler.io = uegIO;
EssgeeLogger.Init(uegLog);
//EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro");

View File

@ -1,5 +1,4 @@
using MAME.Core;
using System.IO;
public class UniIO : IMAMEIOSupport
{
@ -13,7 +12,7 @@ public class UniIO : IMAMEIOSupport
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);
}

View File

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

View File

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