Skip to content

Commit 3a44368

Browse files
major redesign + update
redesign + added save transfer functionality
1 parent 9eb0e45 commit 3a44368

File tree

12 files changed

+4327
-30
lines changed

12 files changed

+4327
-30
lines changed

Saves/Model/ISaveGame.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace EldenRingSaveCopy.Saves.Model
8+
{
9+
public interface ISaveGame
10+
{
11+
Guid Id { get; }
12+
string CharacterName { get; }
13+
}
14+
}

Saves/Model/NullSaveGame.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace EldenRingSaveCopy.Saves.Model
8+
{
9+
public class NullSaveGame: ISaveGame
10+
{
11+
public Guid Id
12+
{
13+
get => Guid.Empty;
14+
}
15+
16+
public string CharacterName
17+
{
18+
get => string.Empty;
19+
}
20+
}
21+
}

Saves/Model/SaveGame.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace EldenRingSaveCopy.Saves.Model
8+
{
9+
public class SaveGame: ISaveGame
10+
{
11+
public const int SLOT_START_INDEX = 0x310;
12+
public const int SLOT_LENGTH = 0x280000;
13+
public const int SAVE_HEADERS_SECTION_START_INDEX = 0x19003B0;
14+
public const int SAVE_HEADERS_SECTION_LENGTH = 0x60000;
15+
public const int SAVE_HEADER_START_INDEX = 0x1901D0E;
16+
public const int SAVE_HEADER_LENGTH = 0x24C;
17+
public const int CHAR_ACTIVE_STATUS_START_INDEX = 0x1901D04;
18+
19+
private const int CHAR_NAME_LENGTH = 0x22;
20+
private const int CHAR_LEVEL_LOCATION = 0x22;
21+
private const int CHAR_PLAYED_START_INDEX = 0x26;
22+
23+
24+
25+
private bool active;
26+
private string characterName;
27+
private byte[] saveData;
28+
private byte[] headerData;
29+
private Guid id;
30+
private int index;
31+
32+
public SaveGame()
33+
{
34+
this.active = false;
35+
this.characterName = string.Empty;
36+
this.saveData = new byte[0];
37+
this.id = Guid.NewGuid();
38+
this.index = -1;
39+
}
40+
41+
public int Index
42+
{
43+
get => this.index;
44+
}
45+
46+
public bool Active
47+
{
48+
get => this.active;
49+
set => this.active = value;
50+
}
51+
52+
public string CharacterName
53+
{
54+
get => this.characterName;
55+
set => this.characterName = value ?? string.Empty;
56+
}
57+
58+
public byte[] SaveData
59+
{
60+
get => this.saveData;
61+
}
62+
63+
public byte[] HeaderData
64+
{
65+
get => this.headerData;
66+
}
67+
68+
public Guid Id
69+
{
70+
get => this.id;
71+
}
72+
73+
public int CharacterLevel { get; set; }
74+
public int SecondsPlayed { get; set; }
75+
76+
public bool LoadData(byte[] data, int slotIndex)
77+
{
78+
try
79+
{
80+
this.index = slotIndex;
81+
this.active = data.Skip(CHAR_ACTIVE_STATUS_START_INDEX).ToArray()[0 + slotIndex] == 1 ? true : false;
82+
this.characterName = Encoding.Unicode.GetString(data.Skip(SAVE_HEADER_START_INDEX + (slotIndex * SAVE_HEADER_LENGTH)).Take(CHAR_NAME_LENGTH).ToArray());
83+
this.CharacterLevel = data.Skip(SAVE_HEADER_START_INDEX + (slotIndex * SAVE_HEADER_LENGTH)).ToArray()[CHAR_LEVEL_LOCATION];
84+
this.SecondsPlayed = BitConverter.ToInt32(data.Skip(SAVE_HEADER_START_INDEX + (slotIndex * SAVE_HEADER_LENGTH) + CHAR_PLAYED_START_INDEX).Take(4).ToArray(), 0);
85+
this.saveData = data.Skip(SLOT_START_INDEX + (slotIndex * 0x10) + (slotIndex * SLOT_LENGTH)).Take(SLOT_LENGTH).ToArray();
86+
this.headerData = data.Skip(SAVE_HEADER_START_INDEX + (slotIndex * SAVE_HEADER_LENGTH)).Take(SAVE_HEADER_LENGTH).ToArray();
87+
return true;
88+
}
89+
catch (Exception)
90+
{
91+
return false;
92+
}
93+
}
94+
95+
96+
97+
}
98+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace EldenRingSaveCopy
8+
{
9+
static class ArrayExtensions
10+
{
11+
12+
public static IEnumerable<int> StartingIndex(this byte[] x, byte[] y)
13+
{
14+
IEnumerable<int> index = Enumerable.Range(0, x.Length - y.Length + 1);
15+
for (int i = 0; i < y.Length; i++)
16+
{
17+
index = index.Where(n => x[n + i] == y[i]).ToArray();
18+
}
19+
return index;
20+
}
21+
22+
}
23+
}

eldenringsavebackup/FileManager.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using EldenRingSaveCopy.Saves;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace EldenRingSaveCopy
9+
{
10+
public class FileManager
11+
{
12+
private const int ID_LOCATION = 0x19003B4;
13+
14+
private byte[] sourceFile;
15+
private byte[] targetFile;
16+
private byte[] sourceID;
17+
private byte[] targetID;
18+
private string sourcePath;
19+
private string targetPath;
20+
21+
public FileManager()
22+
{
23+
sourceFile = new byte[0];
24+
targetFile = new byte[0];
25+
sourceID = new byte[8];
26+
targetID = new byte[8];
27+
}
28+
29+
public byte[] SourceFile {
30+
get => sourceFile;
31+
set
32+
{
33+
sourceFile = value ?? new byte[0];
34+
if(sourceFile.Length > 0)
35+
{
36+
try
37+
{
38+
Array.Copy(sourceFile, ID_LOCATION, sourceID, 0, 8);
39+
}
40+
catch (Exception)
41+
{
42+
43+
}
44+
}
45+
}
46+
}
47+
48+
public byte[] TargetFile
49+
{
50+
get => targetFile;
51+
set
52+
{
53+
targetFile = value ?? new byte[0];
54+
if (targetFile.Length > 0)
55+
{
56+
try
57+
{
58+
Array.Copy(targetFile, ID_LOCATION, targetID, 0, 8);
59+
}
60+
catch (Exception)
61+
{
62+
63+
}
64+
}
65+
}
66+
}
67+
68+
public string TargetPath
69+
{
70+
get => targetPath;
71+
set
72+
{
73+
targetPath = value ?? string.Empty;
74+
}
75+
}
76+
77+
public string SourcePath
78+
{
79+
get => sourcePath;
80+
set
81+
{
82+
sourcePath = value ?? string.Empty;
83+
}
84+
}
85+
86+
public byte[] TargetID
87+
{
88+
get => targetID;
89+
}
90+
91+
public byte[] SourceID
92+
{
93+
get => sourceID;
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)