You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.2 KiB
169 lines
4.2 KiB
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using UnityEngine;
|
|
|
|
public partial class SystemModule
|
|
{
|
|
private const int MaxFileHandles = 50;
|
|
|
|
private readonly UniQuake uq;
|
|
|
|
private readonly FileStream[] fileHandles = new FileStream[MaxFileHandles];
|
|
|
|
public SystemModule(UniQuake uniQuake)
|
|
{
|
|
uq = uniQuake;
|
|
BuildCallbacks();
|
|
}
|
|
|
|
public override void Destroy()
|
|
{
|
|
for (int i = 0; i < MaxFileHandles; ++i)
|
|
{
|
|
if (fileHandles[i] != null)
|
|
fileHandles[i].Dispose();
|
|
}
|
|
|
|
base.Destroy();
|
|
}
|
|
|
|
private void Print(string message)
|
|
{
|
|
// Debug.Log(message); // TODO: collect logs per frame and print after each Update loop
|
|
}
|
|
|
|
private void Error(string message)
|
|
{
|
|
// Use an exception to emulate Quake's behavior of immediately terminating the game's code execution on error
|
|
throw new QuakeException(message, 1);
|
|
}
|
|
|
|
private void Quit()
|
|
{
|
|
// This exception will be caught by the UniQuake update loop where the game will be shut down
|
|
throw new QuakeException("Quitting application normally");
|
|
}
|
|
|
|
private double DoubleTime()
|
|
{
|
|
return uq.CurrentTime;
|
|
}
|
|
|
|
private int FileOpenRead(string path, out int handle)
|
|
{
|
|
int i = FindFileHandle();
|
|
try
|
|
{
|
|
Debug.Log($"Opening file for reading: {path}");
|
|
FileStream fileStream = File.OpenRead(path);
|
|
fileHandles[i] = fileStream;
|
|
handle = i;
|
|
return (int)fileStream.Length;
|
|
}
|
|
catch
|
|
{
|
|
handle = -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
private int FileOpenWrite(string path)
|
|
{
|
|
int i = FindFileHandle();
|
|
try
|
|
{
|
|
Debug.Log($"Opening file for writing: {path}");
|
|
FileStream fileStream = File.OpenWrite(path);
|
|
fileHandles[i] = fileStream;
|
|
return i;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Error($"Error opening {path}: {ex.Message}");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
private int FindFileHandle()
|
|
{
|
|
for (int i = 1; i < MaxFileHandles; ++i)
|
|
{
|
|
if (fileHandles[i] == null)
|
|
return i;
|
|
}
|
|
|
|
Error("Out of handles!");
|
|
return -1;
|
|
}
|
|
|
|
private void FileClose(int handle)
|
|
{
|
|
if (handle < 0 || handle >= MaxFileHandles)
|
|
{
|
|
Debug.LogWarning($"Invalid file handle! {handle}");
|
|
return;
|
|
}
|
|
|
|
fileHandles[handle].Dispose();
|
|
fileHandles[handle] = null;
|
|
}
|
|
|
|
private void FileSeek(int handle, int position)
|
|
{
|
|
if (handle < 0 || handle >= MaxFileHandles)
|
|
{
|
|
Debug.LogWarning($"Invalid file handle! {handle}");
|
|
return;
|
|
}
|
|
|
|
fileHandles[handle].Seek(position, SeekOrigin.Begin);
|
|
}
|
|
|
|
private int FileRead(int handle, IntPtr dest, int count)
|
|
{
|
|
if (handle < 0 || handle >= MaxFileHandles)
|
|
{
|
|
Debug.LogWarning($"Invalid file handle! {handle}");
|
|
return 0;
|
|
}
|
|
|
|
byte[] buf = new byte[count]; // TODO: reuse buffer
|
|
int numRead = fileHandles[handle].Read(buf, 0, count);
|
|
Marshal.Copy(buf, 0, dest, numRead);
|
|
return numRead;
|
|
}
|
|
|
|
private int FileWrite(int handle, IntPtr data, int count)
|
|
{
|
|
if (handle < 0 || handle >= MaxFileHandles)
|
|
{
|
|
Debug.LogWarning($"Invalid file handle! {handle}");
|
|
return 0;
|
|
}
|
|
|
|
byte[] buf = new byte[count]; // TODO: reuse buffer
|
|
Marshal.Copy(data, buf, 0, count);
|
|
fileHandles[handle].Write(buf, 0, count);
|
|
return count;
|
|
}
|
|
|
|
private int FileTime(string path)
|
|
{
|
|
// It would logically make more sense to return an actual file write time here,
|
|
// but a signed 32-bit int is quite limited and we don't want any Year 2038 problems here.
|
|
return File.Exists(path) ? 1 : -1;
|
|
}
|
|
|
|
private void MkDir(string path)
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(path);
|
|
}
|
|
catch
|
|
{
|
|
Debug.LogWarning($"Could not create directory: {path}");
|
|
}
|
|
}
|
|
}
|