Skip to content

Commit c871ec4

Browse files
committed
Added special patches for sapphire #31
1 parent 527639e commit c871ec4

5 files changed

Lines changed: 100 additions & 27 deletions

File tree

Hacktice/Emulator.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using Hacktice.ProcessExtensions;
1+
using EndianExtension;
2+
using Hacktice.ProcessExtensions;
23
using System;
34
using System.Collections.Generic;
45
using System.Diagnostics;
56
using System.Linq;
67
using System.Runtime.InteropServices;
8+
using System.Text;
79
using System.Windows.Forms.VisualStyles;
810

911
namespace Hacktice
@@ -14,6 +16,7 @@ internal class Emulator
1416
private ulong _ramPtrBase = 0;
1517

1618
private IntPtr _ptrRam;
19+
private IntPtr _ptrEEPROMName;
1720

1821
/*
1922
Hacktice header has 20 bytes in size and consists of
@@ -173,6 +176,7 @@ public PrepareResult Prepare()
173176
MagicManager mm = new MagicManager(_process, romPtrBaseSuggestions.ToArray(), ramPtrBaseSuggestions.ToArray(), offset);
174177
_ramPtrBase = mm.ramPtrBase;
175178
_ptrRam = new IntPtr((long)_ramPtrBase);
179+
_ptrEEPROMName = new IntPtr((long)mm.romPtrBase + 0x20);
176180
// only for binary
177181
_ptrOnFrameHook = new IntPtr((long)(_ramPtrBase + 0x3805D4));
178182
return PrepareResult.OK;
@@ -409,5 +413,30 @@ public void WriteHackticeDetours(uint fn, int repeats)
409413
}
410414
_process.WriteBytes(new IntPtr((long)(_ramPtrBase + 0x4e000)), bytes);
411415
}
416+
417+
public string EEPROMName()
418+
{
419+
try
420+
{
421+
var bytes = _process.ReadBytes(_ptrEEPROMName, 20);
422+
var stringBytes = new byte[20];
423+
Endian.CopyByteswap(bytes, 0, stringBytes, 0, bytes.Length);
424+
return Encoding.ASCII.GetString(stringBytes, 0, stringBytes.Length).Trim();
425+
}
426+
catch (Exception)
427+
{
428+
return "";
429+
}
430+
}
431+
432+
public void FixSapphireTimer()
433+
{
434+
// 812E3A66 011B
435+
// 812E3A4E 00F9
436+
// 812E3A36 00E5
437+
_process.WriteBytes(new IntPtr((long)(_ramPtrBase + 0x2E3A64)), new byte[] { 0x1b, 0x01 });
438+
_process.WriteBytes(new IntPtr((long)(_ramPtrBase + 0x2E3A4C)), new byte[] { 0xf9, 0x00 });
439+
_process.WriteBytes(new IntPtr((long)(_ramPtrBase + 0x2E3A34)), new byte[] { 0xe5, 0x00 });
440+
}
412441
}
413442
}

Hacktice/Endian.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using static System.Net.IPAddress;
3+
4+
namespace EndianExtension
5+
{
6+
public static class Endian
7+
{
8+
public static short ToBigEndian(this short value) => HostToNetworkOrder(value);
9+
public static int ToBigEndian(this int value) => HostToNetworkOrder(value);
10+
public static long ToBigEndian(this long value) => HostToNetworkOrder(value);
11+
public static short FromBigEndian(this short value) => NetworkToHostOrder(value);
12+
public static int FromBigEndian(this int value) => NetworkToHostOrder(value);
13+
public static long FromBigEndian(this long value) => NetworkToHostOrder(value);
14+
15+
public static void CopyByteswap(byte[] src, int srcOff, byte[] dst, int dstOff, int amount)
16+
{
17+
if (amount % 4 != 0)
18+
throw new ArgumentException($"Amount {amount} is not divisible by 4");
19+
20+
for (int i = 0; i < amount; i++)
21+
{
22+
int iswap = (4 * (i / 4)) + (3 - (i % 4));
23+
dst[dstOff + i] = src[srcOff + iswap];
24+
}
25+
}
26+
}
27+
}

Hacktice/Hacktice.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
<Compile Include="Canary.cs" />
7777
<Compile Include="Config.cs" />
7878
<Compile Include="Emulator.cs" />
79+
<Compile Include="Endian.cs" />
7980
<Compile Include="MagicManager.cs" />
8081
<Compile Include="MemFind.cs" />
8182
<Compile Include="N64CRC.cs" />

Hacktice/Patcher.cs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,8 @@
1-
using BigEndianExtension;
1+
using EndianExtension;
22
using System;
3-
using System.Collections.Generic;
4-
using System.Diagnostics;
53
using System.IO;
64
using System.Runtime.InteropServices;
75
using System.Text;
8-
using System.Xml;
9-
using static System.Net.IPAddress;
10-
11-
namespace BigEndianExtension
12-
{
13-
public static class BigEndian
14-
{
15-
public static short ToBigEndian(this short value) => HostToNetworkOrder(value);
16-
public static int ToBigEndian(this int value) => HostToNetworkOrder(value);
17-
public static long ToBigEndian(this long value) => HostToNetworkOrder(value);
18-
public static short FromBigEndian(this short value) => NetworkToHostOrder(value);
19-
public static int FromBigEndian(this int value) => NetworkToHostOrder(value);
20-
public static long FromBigEndian(this long value) => NetworkToHostOrder(value);
21-
}
22-
}
236

247
namespace Hacktice
258
{
@@ -89,15 +72,15 @@ public Version FindHackticeVersion()
8972
return null;
9073
}
9174

92-
void CopyByteswap(byte[] src, int srcOff, byte[] dst, int dstOff, int amount)
75+
public string EEPROMName()
9376
{
94-
if (amount % 4 != 0)
95-
throw new ArgumentException($"Amount {amount} is not divisible by 4");
96-
97-
for (int i = 0; i < amount; i++)
77+
try
9878
{
99-
int iswap = (4 * (i / 4)) + (3 - (i % 4));
100-
dst[dstOff + i] = src[srcOff + iswap];
79+
return Encoding.ASCII.GetString(_rom, 0x20, 20).Trim();
80+
}
81+
catch(Exception)
82+
{
83+
return "";
10184
}
10285
}
10386

@@ -131,7 +114,7 @@ public void WriteConfig(Config cfg)
131114
Marshal.Copy(ptr, bytes, 0, size);
132115
Marshal.FreeHGlobal(ptr);
133116

134-
CopyByteswap(bytes, 0, _rom, configLocation + 8, writeSize);
117+
Endian.CopyByteswap(bytes, 0, _rom, configLocation + 8, writeSize);
135118
}
136119

137120
public void Save(string path)
@@ -142,5 +125,18 @@ public void Save(string path)
142125
var hackticePath = AppendToFileName(path, ".hacktice");
143126
File.WriteAllBytes(hackticePath, _rom);
144127
}
128+
129+
public void FixSapphireTimer()
130+
{
131+
// 812E3A66 011B
132+
// 812E3A4E 00F9
133+
// 812E3A36 00E5
134+
_rom[0x2E3A66 - 0x245000 + 0] = 0x01;
135+
_rom[0x2E3A66 - 0x245000 + 1] = 0x1b;
136+
_rom[0x2E3A4E - 0x245000 + 0] = 0x00;
137+
_rom[0x2E3A4E - 0x245000 + 1] = 0xf9;
138+
_rom[0x2E3A36 - 0x245000 + 0] = 0x00;
139+
_rom[0x2E3A36 - 0x245000 + 1] = 0xe5;
140+
}
145141
}
146142
}

Hacktice/Tool.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ enum State
2525
HACKTICE_RUNNING_CAN_UPGRADE,
2626
};
2727

28+
const string SapphireEEPROMName = "SM64 Sapphire";
29+
2830
readonly System.Threading.Timer _timer;
2931

3032
// Access from '_timer' thread only
@@ -273,6 +275,15 @@ private void InjectHacktice()
273275
{
274276
InjectHackticePayloadData();
275277
InjectHackticePayloadHeaderAndHooks();
278+
var name = _emulator.EEPROMName();
279+
if (name == SapphireEEPROMName)
280+
{
281+
var result = MessageBox.Show($"This ROM seems to be '{SapphireEEPROMName}'. Do you want to apply special fixes for it?", "hacktice", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
282+
if (result == DialogResult.Yes)
283+
{
284+
_emulator.FixSapphireTimer();
285+
}
286+
}
276287
}
277288

278289
private void DisableHacktice()
@@ -449,6 +460,15 @@ private void buttonPatch_Click(object sender, EventArgs e)
449460
if (binary)
450461
{
451462
patcher.Apply();
463+
var name = patcher.EEPROMName();
464+
if (name == SapphireEEPROMName)
465+
{
466+
var result = MessageBox.Show($"This ROM seems to be '{SapphireEEPROMName}'. Do you want to apply special fixes for it?", "hacktice", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
467+
if (result == DialogResult.Yes)
468+
{
469+
patcher.FixSapphireTimer();
470+
}
471+
}
452472
}
453473

454474
var version = patcher.FindHackticeVersion();

0 commit comments

Comments
 (0)