-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSaveFile.cs
More file actions
74 lines (66 loc) · 2.7 KB
/
Copy pathSaveFile.cs
File metadata and controls
74 lines (66 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using AliceSaveFileEditor.Structs;
using System.IO;
using System.Runtime.InteropServices;
namespace AliceSaveFileEditor
{
internal class SaveFile(string filePath)
{
public SaveFileHeader Header;
public List<SaveFileSlot> Slots = [];
public SaveFileOptions Options;
private readonly string filePath = filePath;
public void Read()
{
using FileStream fileStream = File.OpenRead(this.filePath);
this.Slots = [];
fileStream.Seek(0, SeekOrigin.Begin);
this.ReadHeader(fileStream);
int nextSlotStart = this.Header.FirstSlotStartAddress;
int slotCount = this.Header.FileSetting >> 1;
for (int slotNum = 0; slotNum < slotCount - 1; slotNum++)
{
fileStream.Seek(nextSlotStart + 0x11, SeekOrigin.Begin);
this.ReadSlot(fileStream);
nextSlotStart = this.Slots[slotNum].NextSlotStartAddress;
}
this.ReadOptionsSlot(fileStream);
}
public void Save()
{
using FileStream fileStream = File.OpenWrite(this.filePath);
fileStream.Seek(0, SeekOrigin.Begin);
}
private unsafe void ReadHeader(FileStream fileStream)
{
int sizeOfHeader = sizeof(SaveFileHeader); // should be 0x1E
byte[] buffer = new byte[sizeOfHeader];
fileStream.Read(buffer, 0, sizeOfHeader);
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
this.Header = *(SaveFileHeader*)handle.AddrOfPinnedObject();
handle.Free();
}
private unsafe void ReadSlot(FileStream fileStream)
{
SaveFileSlot slot;
int sizeOfSlot = sizeof(SaveFileSlot);
byte[] buffer = new byte[sizeOfSlot];
fileStream.Read(buffer, 0, sizeOfSlot);
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
slot = *(SaveFileSlot*)handle.AddrOfPinnedObject();
handle.Free();
this.Slots.Add(slot);
}
private unsafe void ReadOptionsSlot(FileStream fileStream)
{
// options data always seems to be at the same offset
// this also follows the +0x11 pattern of slots
fileStream.Seek(0x010000 + 0x11, SeekOrigin.Begin);
int sizeOfOptions = Marshal.SizeOf<SaveFileOptions>();
byte[] buffer = new byte[sizeOfOptions];
fileStream.Read(buffer, 0, sizeOfOptions);
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
this.Options = *(SaveFileOptions*)handle.AddrOfPinnedObject();
handle.Free();
}
}
}