Skip to content

Commit 33b2751

Browse files
fix broken ch2-3-4 conversion in some cases, added warnings
1 parent 2d219de commit 33b2751

5 files changed

Lines changed: 121 additions & 43 deletions

File tree

.github/workflows/build.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
7+
jobs:
8+
build:
9+
strategy:
10+
matrix:
11+
rid: [win-x64, osx-arm64, linux-x64]
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- name: Setup .NET
16+
uses: actions/setup-dotnet@v4
17+
with:
18+
dotnet-version: 8.0.x
19+
- name: Build and Publish
20+
run: dotnet publish -c Release -r ${{ matrix.rid }}
21+
- name: Upload
22+
uses: actions/upload-artifact@v4
23+
with:
24+
name: DeltaruneSaveConverter-${{ matrix.rid }}-${{ github.sha }}
25+
path: bin/Release/net8.0/${{ matrix.rid }}/publish/

DeltaruneCh1.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,5 +589,17 @@ public void WriteToConsoleFile(string ConsoleFilePath)
589589
filelines[line] = time.ToString();
590590
File.WriteAllText(ConsoleFilePath, string.Join("\r\n", filelines));
591591
}
592+
593+
public static bool IsPCSaveFile(string filename)
594+
{
595+
string[] lines = File.ReadAllLines(filename);
596+
return lines.Length == 10318;
597+
}
598+
599+
public static bool IsConsoleSaveFile(string filename)
600+
{
601+
string[] lines = File.ReadAllLines(filename);
602+
return lines.Length == 223;
603+
}
592604
}
593605
}

DeltaruneCh2.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class DeltaruneCh2
2727
public double[] charweapon = new double[5];
2828
public double[] chararmor1 = new double[5];
2929
public double[] chararmor2 = new double[5];
30-
public string[] weaponstyle = new string[5];
30+
public double[] weaponstyle = new double[5];
3131
public double[,] itemat = new double[5, 4];
3232
public double[,] itemdf = new double[5, 4];
3333
public double[,] itemmag = new double[5, 4];
@@ -115,7 +115,7 @@ public void ReadFromPCFile(string PCFilePath)
115115
line++;
116116
chararmor2[i] = Convert.ToDouble(filelines[line]);
117117
line++;
118-
weaponstyle[i] = filelines[line];
118+
weaponstyle[i] = Convert.ToDouble(filelines[line]);
119119
line++;
120120
for (int q = 0; q < 4; q++)
121121
{
@@ -264,7 +264,7 @@ public void WriteToPCFile(string PCFilePath)
264264
line++;
265265
filelines[line] = chararmor2[i].ToString();
266266
line++;
267-
filelines[line] = weaponstyle[i];
267+
filelines[line] = weaponstyle[i].ToString();
268268
line++;
269269
for (int q = 0; q < 4; q++)
270270
{
@@ -410,7 +410,7 @@ public void ReadFromConsoleFile(string ConsoleFilePath)
410410
line++;
411411
new GMSListDecoder(filelines[line]).ToRealArray(ref chararmor2, 5);
412412
line++;
413-
new GMSListDecoder(filelines[line]).ToStringArray(ref weaponstyle, 5);
413+
new GMSListDecoder(filelines[line]).ToRealArray(ref weaponstyle, 5);
414414
line++;
415415
for (int i = 0; i < 5; i++)
416416
{
@@ -630,5 +630,17 @@ public void WriteToConsoleFile(string ConsoleFilePath)
630630
//File.WriteAllLines(ConsoleFilePath, filelines); - trailing newline
631631
File.WriteAllText(ConsoleFilePath, string.Join("\r\n", filelines));
632632
}
633+
634+
public static bool IsPCSaveFile(string filename)
635+
{
636+
string[] lines = File.ReadAllLines(filename);
637+
return lines.Length == 3055;
638+
}
639+
640+
public static bool IsConsoleSaveFile(string filename)
641+
{
642+
string[] lines = File.ReadAllLines(filename);
643+
return lines.Length == 308;
644+
}
633645
}
634646
}

Program.cs

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.IO;
3+
using System.Runtime;
34
using System.Text.Json;
45

56
namespace DeltaruneSaveConverter
@@ -14,11 +15,6 @@ static void PrintUsage()
1415
Console.WriteLine("commands:");
1516
Console.WriteLine("ConvertFromConsole: extracts a SAV file from path1 into path2 and converts the save files into PC format");
1617
Console.WriteLine("ConvertFromPC: converts save files from path1 into console format and packs them into a SAV at path2");
17-
Console.WriteLine("ExtractSAV: extracts a SAV file from path1 into path2 - supports UNDERTALE");
18-
Console.WriteLine("PackSAV: packs a SAV file with files from path1 into path2 - supports UNDERTALE");
19-
Console.WriteLine("ConvertFileFromConsole: converts the save file at path1 into PC format and saves it at path2");
20-
Console.WriteLine("ConvertFileFromPC: converts the save file at path1 into console format and saves it at path2");
21-
Console.WriteLine("BuildINI: builds a dr.ini file from a folder containing PC-format save files");
2218
Console.WriteLine();
2319
Console.WriteLine("example:");
2420
Console.WriteLine("DeltaruneSaveConverter ConvertFromConsole deltarune_ch1.sav ./pcsave/");
@@ -63,8 +59,50 @@ static void Main(string[] args)
6359
return;
6460
}
6561

62+
/*
63+
* Okay, this one's annoying.
64+
* DELTARUNE Chapter 1&2 DEMO, at least on Switch, has leftover files that are outdated and broken.
65+
* Only deltarune_ch1.sav is good, EVEN FOR CHAPTER 2 SAVES. This has been the cause of too much confusion.
66+
* No, ChatGPT doesn't know this.
67+
*/
68+
static bool DetectIfDemoSavegameWithOldStuff(string consoleSAV)
69+
{
70+
if (Path.GetFileName(consoleSAV) == "deltarune_ch2.sav")
71+
{
72+
string possibleCh1Path = consoleSAV.Replace("deltarune_ch2.sav", "deltarune_ch1.sav");
73+
if (File.Exists(possibleCh1Path))
74+
return true;
75+
}
76+
else if (Path.GetFileName(consoleSAV) == "deltarune.sav")
77+
{
78+
string possibleCh1Path = consoleSAV.Replace("deltarune.sav", "deltarune_ch1.sav");
79+
if (File.Exists(possibleCh1Path))
80+
return true;
81+
}
82+
return false;
83+
}
84+
6685
static void ConvertFromConsole(string consoleSAV, string pcPath)
6786
{
87+
if (DetectIfDemoSavegameWithOldStuff(consoleSAV))
88+
{
89+
Console.WriteLine("!! WARNING !! If you're extracting from Chapter 1 & 2 DEMO, use \"deltarune_ch1.sav\" instead!");
90+
Console.WriteLine("Press Y to continue conversion, press any other button to cancel.");
91+
ConsoleKeyInfo cki = Console.ReadKey(true);
92+
if (cki.KeyChar != 'Y' && cki.KeyChar != 'y')
93+
return;
94+
Console.WriteLine("");
95+
}
96+
if (Directory.Exists(pcPath))
97+
{
98+
Console.WriteLine("!! WARNING !! You're extracting to a folder that already contains save files.");
99+
Console.WriteLine("You will overwrite any existing save data.");
100+
Console.WriteLine("Press Y to continue conversion, press any other button to cancel.");
101+
ConsoleKeyInfo cki = Console.ReadKey(true);
102+
if (cki.KeyChar != 'Y' && cki.KeyChar != 'y')
103+
return;
104+
Console.WriteLine("");
105+
}
68106
Console.Write("Extracting console SAV file... ");
69107
try
70108
{
@@ -83,11 +121,15 @@ static void ConvertFromConsole(string consoleSAV, string pcPath)
83121
{
84122
try
85123
{
86-
Console.Write($"Converting save file {filename} from console to PC... ");
87-
DeltaruneCh1 save = new();
88-
save.ReadFromConsoleFile(file);
89-
save.WriteToPCFile(file);
90-
Console.WriteLine("done!");
124+
if (DeltaruneCh1.IsConsoleSaveFile(file)) {
125+
Console.Write($"Converting save file {filename} from console to PC... ");
126+
DeltaruneCh1 save = new();
127+
save.ReadFromConsoleFile(file);
128+
save.WriteToPCFile(file);
129+
Console.WriteLine("done!");
130+
} else {
131+
Console.WriteLine($"{filename} is already PC format, skipping...!");
132+
}
91133
} catch (Exception ex)
92134
{
93135
Console.WriteLine($"error: {ex.Message}");
@@ -98,11 +140,15 @@ static void ConvertFromConsole(string consoleSAV, string pcPath)
98140
{
99141
try
100142
{
101-
Console.Write($"Converting save file {filename} from console to PC... ");
102-
DeltaruneCh2 save = new();
103-
save.ReadFromConsoleFile(file);
104-
save.WriteToPCFile(file);
105-
Console.WriteLine("done!");
143+
if (DeltaruneCh2.IsConsoleSaveFile(file)) {
144+
Console.Write($"Converting save file {filename} from console to PC... ");
145+
DeltaruneCh2 save = new();
146+
save.ReadFromConsoleFile(file);
147+
save.WriteToPCFile(file);
148+
Console.WriteLine("done!");
149+
} else {
150+
Console.WriteLine($"{filename} is already PC format, skipping...!");
151+
}
106152
}
107153
catch (Exception ex)
108154
{

README.md

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
# DeltaruneSaveConverter
22

3-
A C#.NET command line tool to convert DELTARUNE Chapter 1 & 2 save files between PC and console editions of the game. This tool can also, in theory, be used to extract and pack UNDERTALE save files between consoles.
3+
A C#.NET command line tool to convert DELTARUNE save files between PC and console editions of the game.
44

5-
This program is a work in progress and may not work in all situations - this has only been tested converting 1 file from the Nintendo Switch version of DELTARUNE to the PC version and back.
6-
7-
I am not responsible if you lose any progress if using this tool.
5+
This program is a work in progress and may not work in all situations - this has not been extensively tested. I am not responsible if you lose any progress if using this tool.
86

97
## Usage
108

119
Requires [.NET 8.0 Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/8.0/runtime) installed.
1210

11+
Download and extract the latest release ZIP from [the releases page](https://github.com/InvoxiPlayGames/DeltaruneSaveConverter/releases).
12+
13+
Open a command prompt to the window containing DeltaruneSaveConverter.exe.
14+
1315
```
1416
DeltaruneSaveConverter [command] [path1] [path2]
1517
1618
Commands:
1719
---------
1820
ConvertFromConsole: extracts a SAV file from path1 into path2 and converts the save files into PC format
1921
ConvertFromPC: converts save files from path1 into console format and packs them into a SAV at path2
20-
ExtractSAV: extracts a SAV file from path1 into path2 - supports UNDERTALE
21-
PackSAV: packs a SAV file with files from path1 into path2 - supports UNDERTALE
22-
ConvertFileFromConsole: converts the save file at path1 into PC format and saves it at path2
23-
ConvertFileFromPC: converts the save file at path1 into console format and saves it at path2
2422
2523
Examples:
2624
---------
@@ -29,20 +27,6 @@ DeltaruneSaveConverter ConvertFromConsole deltarune_ch1.sav ./pcsave/
2927
3028
DeltaruneSaveConverter ConvertFromPC ./pcsave/ deltarune_ch1.sav
3129
- Converts the save files from ./pcsave/ into console format, packs it into deltarune_ch1.sav
32-
33-
DeltaruneSaveConverter ExtractSAV deltarune_ch1.sav ./consolesave/
34-
- Extracts the save file from deltarune_ch1.sav and saves it into ./consolesave/
35-
- This should also work for extracting UNDERTALE save files. (No conversion required.)
36-
37-
DeltaruneSaveConverter PackSAV ./consolesave/ deltarune_ch1.sav
38-
- Packs the save file contents from ./consolesave/ into deltarune_ch1.sav
39-
- This should also work for packing UNDERTALE save files. (No conversion required.)
40-
41-
DeltaruneSaveConverter ConvertFileFromConsole ./consolesave/filech1_0 ./pcsave/filech1_0
42-
- Converts the console save file ./consolesave/filech1_0 into PC format and saves it into ./pcsave/filech1_0
43-
44-
DeltaruneSaveConverter ConvertFileFromPC ./pcsave/filech1_0 ./consolesave/filech1_0
45-
- Converts the PC save file ./pcsave/filech1_0 into console format and saves it into /consolesave/filech1_0
4630
```
4731

4832
**Notice:** When converting from Chapter1&2 DEMO, you will still be converting `deltarune_ch1.sav` to get your Chapter 2 saves. **The other .sav files must be ignored.**
@@ -55,10 +39,9 @@ Compiling the program requires the [.NET 8.0 SDK](https://dotnet.microsoft.com/d
5539

5640
(in no particular order)
5741

58-
- Chapter 3/4 support - Chapter 3 seems to be identical to Chapter 2.
42+
- Properly test Chapter 4
5943
- Test conversion between PS4/PS5 and PC.
6044
- Test making sure "weird route"/"SideB"(?) information is preserved.
61-
- macOS/Linux support, NativeAOT stuff?
6245
- Friendlier user interface (+ GUI/web edition?)
6346

6447
## License

0 commit comments

Comments
 (0)