+31
-1
Saves/Amp2016/AmpCampaign.cs
+31
-1
Saves/Amp2016/AmpCampaign.cs
···
8
8
public byte mDifficulty;
9
9
#pragma warning restore CS8618
10
10
11
+
public void WriteToStream(Stream stream, bool isBE = false)
12
+
{
13
+
if (isBE)
14
+
stream.WriteUInt16BE(mScore);
15
+
else
16
+
stream.WriteUInt16LE(mScore);
17
+
stream.WriteUInt8(mZero);
18
+
stream.WriteUInt8(mDifficulty);
19
+
}
20
+
11
21
public static AmpCampaignScore ReadFromStream(Stream stream, bool isBE = false)
12
22
{
13
23
AmpCampaignScore score = new();
···
28
38
#pragma warning disable CS8618
29
39
public byte mUnknown1; // possibly bool mCompletedCampaign or bool mStartedCampaign?
30
40
public byte mUnknown2;
31
-
public byte mUnknownPS3Byte; // only exists in PS3 saves
41
+
public byte mUnknownPS3Byte; // only exists in PS3 saves, 0x01?
32
42
public uint mUnknown3; // 127 on a complete save, 0 on fresh
33
43
public byte mUnknown4; // 0 on both
34
44
public byte mUnknown5; // 255 on a complete save, 2 on fresh
···
38
48
public byte mUnknown7; // always 0xFF
39
49
public AmpCampaignScore[] mScores;
40
50
#pragma warning restore CS8618
51
+
52
+
public void WriteToStream(Stream stream, bool isPS3 = false)
53
+
{
54
+
stream.WriteUInt8(mUnknown1);
55
+
stream.WriteUInt8(mUnknown2);
56
+
if (isPS3)
57
+
stream.WriteUInt8(mUnknownPS3Byte);
58
+
if (isPS3)
59
+
stream.WriteUInt32BE(mUnknown3);
60
+
else
61
+
stream.WriteUInt32LE(mUnknown3);
62
+
stream.WriteUInt8(mUnknown4);
63
+
stream.WriteUInt8(mUnknown5);
64
+
stream.WriteUInt8(mUnknown6);
65
+
stream.WriteLengthUTF8(mNextSong, isPS3);
66
+
stream.WriteUInt8(mSongIndex);
67
+
stream.WriteUInt8(mUnknown7);
68
+
for (int i = 0; i < 15; i++)
69
+
mScores[i].WriteToStream(stream, isPS3);
70
+
}
41
71
42
72
public static AmpCampaignPersistentData ReadFromStream(Stream stream, bool isPS3 = false)
43
73
{
+48
Saves/Amp2016/AmpProfile.cs
+48
Saves/Amp2016/AmpProfile.cs
···
8
8
public int mUnknown3;
9
9
#pragma warning restore CS8618
10
10
11
+
public void WriteToStream(Stream stream, bool isBE = false)
12
+
{
13
+
stream.WriteUInt8(mUnknown1);
14
+
stream.WriteUInt8(mUnknown2);
15
+
if (isBE)
16
+
stream.WriteUInt32BE((uint)mUnknown3);
17
+
else
18
+
stream.WriteInt32LE(mUnknown3);
19
+
}
20
+
11
21
public static AmpProfileFooter ReadFromStream(Stream stream, bool isBE = false)
12
22
{
13
23
AmpProfileFooter footer = new();
···
35
45
public AmpCampaignPersistentData mCampaignData;
36
46
public AmpProfileFooter mFooter;
37
47
#pragma warning restore CS8618
48
+
49
+
public void WriteToStream(Stream stream, bool isPS3 = false)
50
+
{
51
+
RevisionStream rev = new RevisionStream(stream, 0x1, isPS3);
52
+
53
+
rev.WriteUInt8(mVersion);
54
+
rev.WriteLengthUTF8(mUnused, isPS3);
55
+
if (isPS3)
56
+
rev.WriteUInt32BE((uint)mSongData.Length);
57
+
else
58
+
rev.WriteInt32LE(mSongData.Length);
59
+
for (int i = 0; i < mSongData.Length; i++)
60
+
mSongData[i].WriteToStream(rev, isPS3);
61
+
62
+
mOptions.WriteToStream(rev, isPS3);
63
+
rev.WriteUInt8(mUnknown);
64
+
65
+
if (isPS3)
66
+
rev.WriteUInt32BE((uint)mUnlocks.Length);
67
+
else
68
+
rev.WriteInt32LE(mUnlocks.Length);
69
+
for (int i = 0; i < mUnlocks.Length; i++)
70
+
rev.WriteLengthUTF8(mUnlocks[i], isPS3);
71
+
72
+
mCampaignData.WriteToStream(rev, isPS3);
73
+
mFooter.WriteToStream(rev, isPS3);
74
+
75
+
// PS3 pads the save file
76
+
if (isPS3)
77
+
{
78
+
// TODO: is this correct?
79
+
long numPadding = 0x7FFE - (rev.Position) - 5 - 4;
80
+
byte[] bytesToWrite = new byte[numPadding];
81
+
rev.Write(bytesToWrite, 0, (int)numPadding);
82
+
}
83
+
84
+
rev.FinishWriting();
85
+
}
38
86
39
87
public static AmpProfile ReadFromStream(Stream stream, bool isPS3 = false)
40
88
{
+14
Saves/Amp2016/AmpSong.cs
+14
Saves/Amp2016/AmpSong.cs
···
12
12
public byte mProgress; // always 100
13
13
#pragma warning restore CS8618
14
14
15
+
public void WriteToStream(Stream stream, bool isBE = false)
16
+
{
17
+
stream.WriteLengthUTF8(mSongName, isBE);
18
+
if (isBE)
19
+
stream.WriteUInt16BE(mScore);
20
+
else
21
+
stream.WriteUInt16LE(mScore);
22
+
stream.WriteUInt8(mDifficulty);
23
+
stream.WriteUInt8(mHighestStreak);
24
+
stream.WriteUInt8(mPercentCleared);
25
+
stream.WriteUInt8(mScoreType);
26
+
stream.WriteUInt8(mProgress);
27
+
}
28
+
15
29
public static AmpSongPersistentData ReadFromStream(Stream stream, bool isBE = false)
16
30
{
17
31
AmpSongPersistentData song = new();
+23
Saves/Amp2016/AmpSystemOptions.cs
+23
Saves/Amp2016/AmpSystemOptions.cs
···
9
9
public int[] mFlags2; // always 2 entries
10
10
#pragma warning restore CS8618
11
11
12
+
public void WriteToStream(Stream stream, bool isBE = false)
13
+
{
14
+
stream.WriteLengthUTF8(mControlScheme, isBE);
15
+
if (isBE)
16
+
{
17
+
stream.WriteUInt32BE((uint)mFlags1.Length);
18
+
for (int i = 0; i < mFlags1.Length; i++)
19
+
stream.WriteUInt32BE((uint)mFlags1[i]);
20
+
stream.WriteUInt32BE((uint)mFlags2.Length);
21
+
for (int i = 0; i < mFlags2.Length; i++)
22
+
stream.WriteUInt32BE((uint)mFlags2[i]);
23
+
}
24
+
else
25
+
{
26
+
stream.WriteInt32LE(mFlags1.Length);
27
+
for (int i = 0; i < mFlags1.Length; i++)
28
+
stream.WriteInt32LE(mFlags1[i]);
29
+
stream.WriteInt32LE(mFlags2.Length);
30
+
for (int i = 0; i < mFlags2.Length; i++)
31
+
stream.WriteInt32LE(mFlags2[i]);
32
+
}
33
+
}
34
+
12
35
public static AmpSystemOptionsPersistentData ReadFromStream(Stream stream, bool isBE = false)
13
36
{
14
37
AmpSystemOptionsPersistentData options = new();
+97
Saves/RB4/RBSystemOptions.cs
+97
Saves/RB4/RBSystemOptions.cs
···
11
11
public bool mHasCalibrated;
12
12
#pragma warning restore CS8618
13
13
14
+
public void WriteToStream(Stream stream)
15
+
{
16
+
RevisionStream rev = new RevisionStream(stream, 0x5);
17
+
18
+
rev.WriteFloat(mOverscan);
19
+
rev.WriteFloat(mAudioOffset);
20
+
rev.WriteFloat(mVideoOffset);
21
+
rev.WriteFloat(mDialogVolume);
22
+
rev.WriteFloat(mGammaValue);
23
+
rev.WriteUInt8(mHasCalibrated ? (byte)0x01 : (byte)0x00);
24
+
25
+
rev.FinishWriting();
26
+
}
27
+
14
28
public static SystemOptions ReadFromStream(Stream stream)
15
29
{
16
30
SystemOptions opt = new();
···
66
80
public RBSongCache mSongCache;
67
81
#pragma warning restore CS8618
68
82
83
+
public void WriteToStream(Stream stream)
84
+
{
85
+
RevisionStream rev = new RevisionStream(stream, 0x1C);
86
+
87
+
mSystemOptions.WriteToStream(rev);
88
+
rev.WriteInt32LE(mBackgroundVolume);
89
+
rev.WriteInt32LE(mInstrumentsVolume);
90
+
rev.WriteInt32LE(mSFXVolume);
91
+
rev.WriteInt32LE(mCrowdVolume);
92
+
rev.WriteUInt8(mDolby ? (byte)0x01 : (byte)0x00);
93
+
rev.WriteUInt8(mBassBoost ? (byte)0x01 : (byte)0x00);
94
+
rev.WriteUInt8(mOverscan ? (byte)0x01 : (byte)0x00);
95
+
rev.WriteInt32LE(mProDrumCymbalLanes);
96
+
rev.WriteUInt8(mIsDrumNavigationAllowed ? (byte)0x01 : (byte)0x00);
97
+
rev.WriteUInt8(mNoFail ? (byte)0x01 : (byte)0x00);
98
+
rev.WriteUInt8(mIndependentTrackSpeeds ? (byte)0x01 : (byte)0x00);
99
+
rev.WriteUInt8(mImprovSolosScored ? (byte)0x01 : (byte)0x00);
100
+
rev.WriteUInt8(mAwesomenessDetection ? (byte)0x01 : (byte)0x00);
101
+
rev.WriteUInt8(mLeaderboardLadder ? (byte)0x01 : (byte)0x00);
102
+
rev.WriteUInt8(mHide1RatedSongs ? (byte)0x01 : (byte)0x00);
103
+
rev.WriteUInt8(mUseSubtitles ? (byte)0x01 : (byte)0x00);
104
+
rev.WriteInt32LE(mSongLibSort);
105
+
rev.WriteInt32LE(mLastPlayedPatchVersion);
106
+
rev.WriteUInt8(mSeenRivalsUpsell ? (byte)0x01 : (byte)0x00);
107
+
rev.WriteUInt8(mDrumAutoKickEnabled ? (byte)0x01 : (byte)0x00);
108
+
rev.WriteLengthUTF8(mUnknown1);
109
+
rev.WriteLengthUTF8(mUnknown2);
110
+
rev.WriteUInt8(mHideUnavailableSOMPSongs ? (byte)0x01 : (byte)0x00);
111
+
rev.WriteUInt8(mUnknown3 ? (byte)0x01 : (byte)0x00);
112
+
rev.WriteUInt32LE(mUnknown4);
113
+
rev.WriteUInt32LE(mUnknown5);
114
+
rev.WriteUInt8(mUnknown6 ? (byte)0x01 : (byte)0x00);
115
+
rev.WriteUInt32LE(mUnknown7);
116
+
rev.WriteUInt32LE(mUnknown8);
117
+
mSongCache.WriteToStream(rev);
118
+
119
+
rev.FinishWriting();
120
+
}
121
+
69
122
public static RBSystemOptions ReadFromStream(Stream stream)
70
123
{
71
124
RBSystemOptions opt = new RBSystemOptions();
···
123
176
// the number of refreshes it's been since the song was last seen
124
177
// and the other is the most recent changelist version.
125
178
179
+
public void WriteToStream(Stream stream)
180
+
{
181
+
stream.Write(mData, 0, 0x4B8);
182
+
}
183
+
126
184
public static RBSongMetadata ReadFromStream(Stream stream)
127
185
{
128
186
RBSongMetadata meta = new();
···
143
201
public Dictionary<int, RBSongMetadata> mMetadataMap;
144
202
public int[] mRecentlyAcquiredSongs;
145
203
#pragma warning restore CS8618
204
+
205
+
public void WriteToStream(Stream stream)
206
+
{
207
+
RevisionStream rev = new RevisionStream(stream, 0x8, false);
208
+
209
+
rev.WriteInt32LE(mCacheVersion);
210
+
211
+
rev.WriteInt32LE(mSongsInContent.Count);
212
+
foreach (string content in mSongsInContent.Keys)
213
+
{
214
+
rev.WriteLengthUTF8(content);
215
+
rev.WriteInt32LE(mSongsInContent[content].Length);
216
+
for (int i = 0; i < mSongsInContent[content].Length; i++)
217
+
rev.WriteInt32LE(mSongsInContent[content][i]);
218
+
}
219
+
220
+
rev.WriteInt32LE(mShortNametoSongDir.Count);
221
+
foreach (string shortname in mShortNametoSongDir.Keys)
222
+
{
223
+
rev.WriteLengthUTF8(shortname);
224
+
rev.WriteLengthUTF8(mShortNametoSongDir[shortname]);
225
+
}
226
+
227
+
rev.WriteInt32LE(0x4B8);
228
+
229
+
rev.WriteInt32LE(mMetadataMap.Count);
230
+
foreach (int songId in mMetadataMap.Keys)
231
+
{
232
+
rev.WriteInt32LE(songId);
233
+
mMetadataMap[songId].WriteToStream(stream);
234
+
}
235
+
236
+
rev.WriteInt32LE(mRecentlyAcquiredSongs.Length);
237
+
for (int i = 0; i < mRecentlyAcquiredSongs.Length; i++)
238
+
rev.WriteInt32LE(mRecentlyAcquiredSongs[i]);
239
+
240
+
rev.FinishWriting();
241
+
return;
242
+
}
146
243
147
244
public static RBSongCache ReadFromStream(Stream stream)
148
245
{
+22
Saves/RevisionStream.cs
+22
Saves/RevisionStream.cs
···
7
7
private int _curVersion;
8
8
private bool _bigEndian;
9
9
10
+
// Reading constructor
10
11
public RevisionStream(Stream original, int minVersion, int curVersion, bool bigEndian = false)
11
12
{
12
13
byte magic = original.ReadUInt8();
···
31
32
_bigEndian = bigEndian;
32
33
}
33
34
35
+
// Writing constructor
36
+
public RevisionStream(Stream original, int curVersion, bool bigEndian = false)
37
+
{
38
+
original.WriteUInt8(0x7A);
39
+
40
+
if (bigEndian)
41
+
original.WriteUInt32BE((uint)curVersion);
42
+
else
43
+
original.WriteInt32LE(curVersion);
44
+
45
+
Version = curVersion;
46
+
_stream = original;
47
+
_curVersion = curVersion;
48
+
_bigEndian = bigEndian;
49
+
}
50
+
34
51
public override bool CanRead => _stream.CanRead;
35
52
36
53
public override bool CanSeek => _stream.CanSeek;
···
46
63
byte magic = _stream.ReadUInt8();
47
64
if (magic != 0x7B)
48
65
throw new Exception($"Unexpected {magic:X2} at end of RevisionStream!");
66
+
}
67
+
68
+
public void FinishWriting()
69
+
{
70
+
_stream.WriteUInt8(0x7B);
49
71
}
50
72
51
73
public override void Flush()
+8
StreamExtensions.cs
+8
StreamExtensions.cs
···
58
58
s.Write(tmp, 0, 2);
59
59
}
60
60
61
+
public static void WriteUInt16BE(this Stream s, ushort i)
62
+
{
63
+
byte[] tmp = new byte[2];
64
+
tmp[0] = (byte)((i >> 8) & 0xFF);
65
+
tmp[1] = (byte)(i & 0xFF);
66
+
s.Write(tmp, 0, 2);
67
+
}
68
+
61
69
/// <summary>
62
70
/// Read an unsigned 16-bit Big-endian integer from the stream.
63
71
/// </summary>