Skip to content

Commit

Permalink
Merge pull request #1 from minishmaker/name-change
Browse files Browse the repository at this point in the history
Ability to change save file names.
  • Loading branch information
mikeskydev authored May 4, 2019
2 parents 14e48e2 + d1c5716 commit 306d843
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 67 deletions.
98 changes: 69 additions & 29 deletions Core/SRAM.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.IO;
using System.Runtime.InteropServices;
using SaveEditor.Utilities;

namespace SaveEditor.Core
Expand All @@ -20,8 +18,9 @@ public class SRAM
public static SRAM Instance { get; private set; }
public readonly string path;

private byte[] romData;
private byte[] saveData;
public readonly Reader reader;
public readonly Writer writer;

public RegionVersion version { get; private set; } = RegionVersion.None;

Expand All @@ -30,44 +29,97 @@ public SRAM(string filePath)
{
Instance = this;
path = filePath;
romData = File.ReadAllBytes(filePath);
saveData = File.ReadAllBytes(filePath);

File.WriteAllBytes(path+".bak", saveData);

// Data is stored in reversed blocked of 8; when read by GBA it assumes the correct order, so we need to change it.
for (int block = 0; block < romData.Length;)
for (int block = 0; block < saveData.Length;)
{
Array.Reverse(romData, block, 8);
Array.Reverse(saveData, block, 8);
block += 8;
}

Stream stream = Stream.Synchronized(new MemoryStream(romData));
Stream stream = Stream.Synchronized(new MemoryStream(saveData));
reader = new Reader(stream);
writer = new Writer(stream);


Debug.WriteLine("Read " + stream.Length + " bytes.");
}

public SaveFile GetSaveFile(int fileNumber)
{
if (fileNumber < 0 || fileNumber > 2) throw new IndexOutOfRangeException("File number must be either 0, 1, 2.");

return new SaveFile(ReadChecksum(fileNumber), ReadData(fileNumber));

}

public void SaveFile(SaveFile save, int fileNumber)
{
uint checksum = CalculateChecksum(fileNumber);
writer.WriteBytes(save.data, 0x80 + (fileNumber * 0x500));

uint newchecksum = CalculateChecksum(fileNumber);

// temp test checksum
uint sum = ReadChecksum(0);
uint calcsum = CalculateChecksum(0);
Console.WriteLine("old checksum {0}", StringUtil.AsStringHex8((int)checksum));
Console.WriteLine("new checksum {0}", StringUtil.AsStringHex8((int)newchecksum));

writer.WriteUInt16((ushort)((newchecksum & 0xFFFF0000) >> 16),0x30 + (fileNumber * 0x10));
writer.WriteUInt16((ushort)(newchecksum & 0xFFFF));

writer.Flush();

byte[] dataToWrite = new byte[saveData.Length];

Array.Copy(saveData, dataToWrite, saveData.Length);


// Flip data back for output write, but don't touch current data
for (int block = 0; block < dataToWrite.Length;)
{
Array.Reverse(dataToWrite, block, 8);
block += 8;
}

if (dataToWrite == saveData) Console.WriteLine("Same!");

File.WriteAllBytes(path, dataToWrite);

if (sum == calcsum) Console.WriteLine("Checksum correct.");
}

public uint ReadChecksum(int fileID)
private uint ReadChecksum(int fileNumber)
{
uint sum = (uint)(reader.ReadUInt16(0x30 + (fileID * 0x10)) << 16);
uint sum = (uint)(reader.ReadUInt16(0x30 + (fileNumber * 0x10)) << 16);

sum += reader.ReadUInt16();

return sum;
}

public uint CalculateChecksum(int fileID)
private byte[] ReadData(int fileNumber)
{
byte[] gameState = reader.ReadBytes(0x04, 0x34 + (fileID * 0x10));
return reader.ReadBytes(0x500, 0x80 + (fileNumber * 0x500));
}

byte[] gameData = reader.ReadBytes(0x500, 0x80 + (fileID * 0x500));
public uint CalculateChecksum(int fileNumber)
{
byte[] gameState = reader.ReadBytes(0x04, 0x34 + (fileNumber * 0x10));

byte[] gameData = reader.ReadBytes(0x500, 0x80 + (fileNumber * 0x500));

uint shortcheck = PartialCheck(gameState);
uint longcheck = PartialCheck(gameData);

return Combine(shortcheck, longcheck);
uint combined = (shortcheck + longcheck) & 0xFFFF;
uint upper = combined << 16;
uint lower = ~combined & 0xFFFF;

lower += 1;
combined = upper + lower;

return combined;
}

private uint PartialCheck(byte[] data)
Expand All @@ -87,17 +139,5 @@ private uint PartialCheck(byte[] data)

return sum;
}

private uint Combine(uint shortcheck, uint longcheck)
{
uint combined = (shortcheck + longcheck) & 0xFFFF;
uint upper = combined << 16;
uint lower = ~combined & 0xFFFF;

lower += 1;
combined = upper + lower;

return combined;
}
}
}
38 changes: 38 additions & 0 deletions Core/SaveFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.CodeDom;
using System.IO;
using System.Linq;
using System.Text;
using SaveEditor.Utilities;

namespace SaveEditor.Core
{
public class SaveFile
{
public uint checksum { get; private set; }
public byte[] data { get; private set; }

private readonly Reader reader_;
private readonly Writer writer_;

public SaveFile(uint fileChecksum, byte[] fileData)
{
checksum = fileChecksum;
data = fileData;

Stream stream = Stream.Synchronized(new MemoryStream(data));
reader_ = new Reader(stream);
writer_ = new Writer(stream);
}

public string GetName()
{
return Encoding.Default.GetString(reader_.ReadBytes(6, 0x80));
}

public void WriteName(string name)
{
writer_.WriteBytes(Encoding.ASCII.GetBytes(name.PadRight(6, (char)0x00).Substring(0, 6)), 0x80);
}
}
}
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@
[![Documentation](https://img.shields.io/badge/gitbook-docs-187818.svg)](https://docs.minishmaker.com)
[![Discord](https://discordapp.com/api/guilds/342341497024151553/embed.png?style=shield)](https://discord.gg/ndFuWbV)

<p align="center">
<img src="https://i.imgur.com/lVw0Ip9.png" alt="Title Image">
</p>

A Save Editor for The Legend of Zelda: The Minish Cap
A Save Editor for The Legend of Zelda: The Minish Cap. The project aims to allow you to change to any aspect of a minish cap save, allowing you to explore the game out of sequence, get a complete save file, or just skip a pesky dungeon boss.

The project is still in early development and will not see a full release for a while.
Get the latest release [here](https://github.com/minishmaker/save-editor/releases).

### Current Features
- Choose which save file to edit
- Change the save name

### Planned Features
- Save File Name Editing
- Item Editing
- Inventory Editing
- Kinstone Editing
- Event Flag Editing
- Conversion of saves between different versions (EU,JP,US)
- Preset macros, e.g. completed all fusions, have all figurines, completed up to Cave of Flames etc.

Please join our [Discord server](https://discord.gg/ndFuWbV) to discuss the project!

Expand Down
2 changes: 2 additions & 0 deletions SaveEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Core\SaveFile.cs" />
<Compile Include="Utilities\Reader.cs" />
<Compile Include="Core\SRAM.cs" />
<Compile Include="UI\MainWindow.cs">
Expand All @@ -59,6 +60,7 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\StringUtil.cs" />
<Compile Include="Utilities\Writer.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
Expand Down
Loading

0 comments on commit 306d843

Please sign in to comment.