Added ScriptTool
This commit is contained in:
parent
acfe5ddb8e
commit
52900e9c50
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptTool", "ScriptTool\ScriptTool.csproj", "{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class CommandOptions
|
||||
{
|
||||
public string WorkingDirectory { get; set; }
|
||||
public CommandType Command { get; set; }
|
||||
public bool DoMiscText { get; set; }
|
||||
public bool DoMainText { get; set; }
|
||||
public string EbRom { get; set; }
|
||||
public string M12Rom { get; set; }
|
||||
}
|
||||
|
||||
enum CommandType
|
||||
{
|
||||
Compile,
|
||||
Decompile
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class ControlCode
|
||||
{
|
||||
public IList<byte> Identifier { get; private set; }
|
||||
public bool End { get; set; }
|
||||
public bool Multiple { get; set; }
|
||||
public int Length { get; set; }
|
||||
public string Description { get; set; }
|
||||
const string HexChars = "0123456789ABCDEFabcdef";
|
||||
|
||||
public ControlCode()
|
||||
{
|
||||
Identifier = new List<byte>();
|
||||
}
|
||||
|
||||
public bool Match(byte[] rom, int address)
|
||||
{
|
||||
for (int i = 0; i < Identifier.Count; i++)
|
||||
if (rom[address + i] != Identifier[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool BeginsWith(params byte[] bytes)
|
||||
{
|
||||
if (bytes.Length > Identifier.Count)
|
||||
return false;
|
||||
|
||||
var first = Identifier.Take(bytes.Length);
|
||||
if (!first.SequenceEqual(bytes))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Description;
|
||||
}
|
||||
|
||||
public static IList<ControlCode> LoadEbControlCodes(string path)
|
||||
{
|
||||
var codeList = new List<ControlCode>();
|
||||
string[] lines = File.ReadAllLines(path);
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var code = new ControlCode();
|
||||
string def = line.Substring(0, line.IndexOf(','));
|
||||
string desc = line.Substring(line.IndexOf(',') + 1);
|
||||
code.Description = desc.Substring(1, desc.Length - 3);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (def.StartsWith("!"))
|
||||
{
|
||||
code.End = true;
|
||||
def = def.Substring(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (def.StartsWith("*"))
|
||||
{
|
||||
code.Multiple = true;
|
||||
def = def.Substring(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
string[] defs = def.Split(' ');
|
||||
for (int i = 0; i < defs.Length; i++)
|
||||
{
|
||||
if (!HexChars.Contains(defs[i][0]))
|
||||
break;
|
||||
|
||||
code.Identifier.Add(byte.Parse(defs[i], System.Globalization.NumberStyles.HexNumber));
|
||||
}
|
||||
|
||||
if (code.Multiple)
|
||||
code.Length = -1;
|
||||
else
|
||||
code.Length = defs.Length;
|
||||
|
||||
codeList.Add(code);
|
||||
}
|
||||
|
||||
return codeList;
|
||||
}
|
||||
|
||||
public static IList<ControlCode> LoadM12ControlCodes(string path)
|
||||
{
|
||||
var codeList = new List<ControlCode>();
|
||||
string[] lines = File.ReadAllLines(path);
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var code = new ControlCode();
|
||||
string def = line.Substring(0, line.IndexOf(','));
|
||||
string desc = line.Substring(line.IndexOf(',') + 1);
|
||||
code.Description = desc;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (def.StartsWith("!"))
|
||||
{
|
||||
code.End = true;
|
||||
def = def.Substring(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (def.StartsWith("*"))
|
||||
{
|
||||
code.Multiple = true;
|
||||
def = def.Substring(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
string[] defs = def.Split(' ');
|
||||
code.Identifier.Add(byte.Parse(defs[0], System.Globalization.NumberStyles.HexNumber));
|
||||
code.Identifier.Add(0xFF);
|
||||
|
||||
if (code.Multiple)
|
||||
code.Length = -1;
|
||||
else
|
||||
code.Length = defs.Length;
|
||||
|
||||
codeList.Add(code);
|
||||
}
|
||||
|
||||
return codeList;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class DecompileContext
|
||||
{
|
||||
public LabelMap LabelMap { get; private set; }
|
||||
public IList<string> Strings { get; private set; }
|
||||
|
||||
public DecompileContext()
|
||||
{
|
||||
LabelMap = new LabelMap();
|
||||
Strings = new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,324 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class EbTextDecompiler
|
||||
{
|
||||
private IList<ControlCode> _controlCodes;
|
||||
public IList<ControlCode> ControlCodes
|
||||
{
|
||||
get { return _controlCodes; }
|
||||
set
|
||||
{
|
||||
// Grab the jump table codes
|
||||
foreach (var code in value)
|
||||
{
|
||||
if (code.BeginsWith(9))
|
||||
jumpTableReturn = code;
|
||||
|
||||
if (code.BeginsWith(0x1f, 0xc0))
|
||||
jumpTableNoReturn = code;
|
||||
}
|
||||
|
||||
_controlCodes = value;
|
||||
}
|
||||
}
|
||||
|
||||
private ControlCode jumpTableReturn;
|
||||
private ControlCode jumpTableNoReturn;
|
||||
|
||||
private const string charMapEb = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZØØØØØ`abcdefghijklmnopqrstuvwxyz{|}~\\";
|
||||
|
||||
private static string[][] compressedStringsEb;
|
||||
private static IList<int[]> textRanges = new List<int[]>();
|
||||
|
||||
static EbTextDecompiler()
|
||||
{
|
||||
// Load compressed strings
|
||||
compressedStringsEb = new string[3][];
|
||||
string[] stringsFromFile = File.ReadAllLines(@"eb-compressed-strings.txt");
|
||||
compressedStringsEb[0] = stringsFromFile.Take(0x100).ToArray();
|
||||
compressedStringsEb[1] = stringsFromFile.Skip(0x100).Take(0x100).ToArray();
|
||||
compressedStringsEb[2] = stringsFromFile.Skip(0x200).Take(0x100).ToArray();
|
||||
|
||||
// Load text ranges
|
||||
textRanges.Add(new int[] { 0x50000, 0x5FFEC });
|
||||
textRanges.Add(new int[] { 0x60000, 0x6FFE3 });
|
||||
textRanges.Add(new int[] { 0x70000, 0x7FF40 });
|
||||
textRanges.Add(new int[] { 0x80000, 0x8BC2D });
|
||||
textRanges.Add(new int[] { 0x8D9ED, 0x8FFF3 });
|
||||
textRanges.Add(new int[] { 0x90000, 0x9FF2F });
|
||||
textRanges.Add(new int[] { 0x2F4E20, 0x2FA460 });
|
||||
}
|
||||
|
||||
public void Decompile(byte[] rom, int[] addresses, DecompileContext context)
|
||||
{
|
||||
if (ControlCodes == null)
|
||||
throw new Exception("Codelist is null");
|
||||
|
||||
// First pass -- define labels
|
||||
foreach (var address in addresses)
|
||||
context.LabelMap.Append(address);
|
||||
|
||||
foreach(var range in textRanges)
|
||||
ScanAt(rom, range[0], range[1], context, ScanMode.FirstPass);
|
||||
|
||||
// Second pass -- decompile the strings
|
||||
foreach (var range in textRanges)
|
||||
ScanAt(rom, range[0], range[1], context, ScanMode.SecondPass);
|
||||
}
|
||||
|
||||
private void ScanAt(byte[] rom, int startAddress, int endAddress, DecompileContext context, ScanMode mode, bool newLines = true)
|
||||
{
|
||||
bool ended = false;
|
||||
bool foundMatch = false;
|
||||
bool prev1902 = false;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
int address = startAddress;
|
||||
|
||||
if (address == 0)
|
||||
{
|
||||
throw new Exception("Null pointer");
|
||||
}
|
||||
|
||||
if (mode == ScanMode.FirstPass)
|
||||
{
|
||||
context.LabelMap.Append(address);
|
||||
}
|
||||
|
||||
while (!ended)
|
||||
{
|
||||
// Check for label definition
|
||||
if (mode == ScanMode.SecondPass && context.LabelMap.Labels.ContainsKey(address))
|
||||
{
|
||||
sb.Append("^" + context.LabelMap[address] + "^");
|
||||
}
|
||||
|
||||
// Check for control codes
|
||||
|
||||
// No codes begin with a value above 0x1F, so check for that first
|
||||
if (rom[address] < 0x20)
|
||||
{
|
||||
// Loop through each control code until we find a match
|
||||
foundMatch = false;
|
||||
foreach (var code in ControlCodes)
|
||||
{
|
||||
if (code.Match(rom, address))
|
||||
{
|
||||
foundMatch = true;
|
||||
|
||||
if (mode == ScanMode.SecondPass && !IsCompressedCode(code))
|
||||
{
|
||||
// Output the start of the code block
|
||||
sb.Append('[');
|
||||
|
||||
// Output the identifier bytes
|
||||
sb.Append(String.Join(" ", code.Identifier.Select(b => b.ToString("X2")).ToArray()));
|
||||
}
|
||||
|
||||
// Skip the identifier bytes
|
||||
address += code.Identifier.Count;
|
||||
|
||||
// Found a match -- check if it's variable-length
|
||||
if (code.Multiple)
|
||||
{
|
||||
if (code.BeginsWith(9) ||
|
||||
code.BeginsWith(0x1F, 0xC0))
|
||||
{
|
||||
int count = rom[address++];
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(count.ToString("X2"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int jump = rom.ReadSnesPointer(address);
|
||||
address += 4;
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
{
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if it references any other addresses -- scan those too
|
||||
if (code.BeginsWith(8) ||
|
||||
code.BeginsWith(0xA) ||
|
||||
code.BeginsWith(0x1B, 0x02) ||
|
||||
code.BeginsWith(0x1B, 0x03) ||
|
||||
code.BeginsWith(0x1F, 0x63))
|
||||
{
|
||||
// Single address at next byte
|
||||
int jump = rom.ReadSnesPointer(address);
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
{
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else if (code.BeginsWith(0x1F, 0x66) ||
|
||||
code.BeginsWith(6))
|
||||
{
|
||||
// Skip two bytes; single address afterwards
|
||||
int jump = rom.ReadSnesPointer(address + 2);
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address].ToString("X2"));
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address + 1].ToString("X2"));
|
||||
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else if (
|
||||
code.BeginsWith(0x1F, 0x18) ||
|
||||
code.BeginsWith(0x1F, 0x19))
|
||||
{
|
||||
// Check
|
||||
}
|
||||
|
||||
else if (mode == ScanMode.SecondPass &&
|
||||
(code.BeginsWith(0x15) ||
|
||||
code.BeginsWith(0x16) ||
|
||||
code.BeginsWith(0x17)))
|
||||
{
|
||||
// Check for compressed codes
|
||||
int bank = code.Identifier[0] - 0x15;
|
||||
int index = rom[address];
|
||||
sb.Append(compressedStringsEb[bank][index]);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Regular control code -- output the rest of the bytes
|
||||
if (mode == ScanMode.SecondPass)
|
||||
{
|
||||
for (int i = 0; i < (code.Length - code.Identifier.Count); i++)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address + i].ToString("X2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the rest of the bytes
|
||||
address += code.Length - code.Identifier.Count;
|
||||
}
|
||||
|
||||
if (mode == ScanMode.SecondPass && !IsCompressedCode(code))
|
||||
{
|
||||
// Output the end of the code block
|
||||
sb.Append(']');
|
||||
}
|
||||
|
||||
// End the block if necessary
|
||||
if (address >= endAddress)
|
||||
{
|
||||
ended = true;
|
||||
}
|
||||
|
||||
// Insert a newline after each end code for readibility
|
||||
if (mode == ScanMode.SecondPass && code.End && !prev1902)
|
||||
{
|
||||
sb.AppendLine();
|
||||
/*sb.Append('(');
|
||||
sb.Append(address.ToString("X"));
|
||||
sb.Append(')');*/
|
||||
}
|
||||
|
||||
// Check if we're in a menu string
|
||||
if (code.BeginsWith(0x19, 0x02))
|
||||
prev1902 = true;
|
||||
else
|
||||
prev1902 = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatch)
|
||||
{
|
||||
// Bad!
|
||||
throw new Exception("Found unknown control code");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's not a control code -- just skip it
|
||||
if (mode == ScanMode.SecondPass)
|
||||
sb.Append(CharLookup(rom[address]));
|
||||
|
||||
address++;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
context.Strings.Add(sb.ToString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private string CharLookup(byte value)
|
||||
{
|
||||
if (value >= 0x8B && value <= 0x8F)
|
||||
{
|
||||
// Greek letters -- output hex literals instead
|
||||
return "[" + value.ToString("X2") + "]";
|
||||
}
|
||||
else if (value == 0xAF)
|
||||
{
|
||||
// Musical note -- output \ instead of the garbage char that normally would get outputted
|
||||
return "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
return charMapEb[value - 0x50].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCompressedCode(ControlCode code)
|
||||
{
|
||||
if (code.Identifier[0] == 0x15 || code.Identifier[0] == 0x16 ||
|
||||
code.Identifier[0] == 0x17)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private enum ScanMode
|
||||
{
|
||||
FirstPass,
|
||||
SecondPass
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class EbTextTables
|
||||
{
|
||||
public static MainStringRef[] ReadTptRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
|
||||
int address = 0xF8985;
|
||||
int entries = 1584;
|
||||
|
||||
for (int i = 0; i < entries; i++)
|
||||
{
|
||||
int firstPointer = rom.ReadSnesPointer(address + 9);
|
||||
if (firstPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 9, OldPointer = firstPointer });
|
||||
|
||||
byte type = rom[address];
|
||||
if (type != 2)
|
||||
{
|
||||
int secondPointer = rom.ReadSnesPointer(address + 13);
|
||||
if (secondPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 13, OldPointer = secondPointer });
|
||||
}
|
||||
|
||||
address += 17;
|
||||
}
|
||||
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadBattleActionRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x157B68;
|
||||
for (int i = 0; i < 318; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address + 4);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 4, OldPointer = pointer });
|
||||
address += 12;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadPrayerRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x4A309;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address, OldPointer = pointer });
|
||||
address += 4;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadItemHelpRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x155000;
|
||||
for (int i = 0; i < 254; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address + 0x23);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 0x23, OldPointer = pointer });
|
||||
address += 39;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadPsiHelpRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x158A50;
|
||||
for (int i = 0; i < 53; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address + 11);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 11, OldPointer = pointer });
|
||||
address += 15;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadPhoneRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x157AAE;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address + 0x1B);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 0x1B, OldPointer = pointer });
|
||||
address += 31;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static MainStringRef[] ReadEnemyTextRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
int address = 0x159589;
|
||||
for (int i = 0; i < 231; i++)
|
||||
{
|
||||
int pointer = rom.ReadSnesPointer(address + 0x2D);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 0x2D, OldPointer = pointer });
|
||||
|
||||
pointer = rom.ReadSnesPointer(address + 0x31);
|
||||
if (pointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 0x31, OldPointer = pointer });
|
||||
|
||||
address += 94;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static int ReadInt(this byte[] rom, int address)
|
||||
{
|
||||
int value = rom[address] |
|
||||
(rom[address + 1] << 8) |
|
||||
(rom[address + 2] << 16) |
|
||||
(rom[address + 3] << 24);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int ReadSnesPointer(this byte[] rom, int address)
|
||||
{
|
||||
int offset = rom.ReadInt(address);
|
||||
if (offset == 0) return 0;
|
||||
return offset - 0xC00000;
|
||||
}
|
||||
|
||||
public static int ReadGbaPointer(this byte[] rom, int address)
|
||||
{
|
||||
int offset = rom.ReadInt(address);
|
||||
if (offset == 0) return 0;
|
||||
return offset & 0x1FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class FixedStringCollection
|
||||
{
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int StringsLocation { get; set; }
|
||||
|
||||
public int NumEntries { get; set; }
|
||||
public int EntryLength { get; set; }
|
||||
public IList<FixedStringRef> StringRefs { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
public class FixedStringRef
|
||||
{
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int OldPointer { get; set; }
|
||||
|
||||
public string Old { get; set; }
|
||||
public string New { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
public class JsonHexConverter : JsonConverter
|
||||
{
|
||||
private static readonly Type[] allowedTypes = {
|
||||
typeof(int),
|
||||
typeof(uint),
|
||||
typeof(byte),
|
||||
typeof(sbyte),
|
||||
typeof(short),
|
||||
typeof(ushort),
|
||||
typeof(long),
|
||||
typeof(ulong)
|
||||
};
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return allowedTypes.Contains(objectType);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Integer)
|
||||
{
|
||||
var hex = serializer.Deserialize(reader, objectType);
|
||||
return hex;
|
||||
}
|
||||
throw new Exception("Unexpected token");
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteRawValue(String.Format("0x{0:X}", value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class LabelMap
|
||||
{
|
||||
public IDictionary<int, string> Labels { get; private set; }
|
||||
private int counter = 0;
|
||||
|
||||
public LabelMap()
|
||||
{
|
||||
Labels = new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
public string this[int address]
|
||||
{
|
||||
get
|
||||
{
|
||||
return Labels[address];
|
||||
}
|
||||
set
|
||||
{
|
||||
Labels[address] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Append(int address)
|
||||
{
|
||||
if (!Labels.ContainsKey(address))
|
||||
{
|
||||
string newLabel = String.Concat("L", counter.ToString());
|
||||
Labels.Add(address, newLabel);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Reset();
|
||||
Labels.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class M12TextDecompiler
|
||||
{
|
||||
public IList<ControlCode> ControlCodes { get; set; }
|
||||
private static string[] charMap;
|
||||
private static IList<int[]> textRanges = new List<int[]>();
|
||||
private static DecompileContext staticContext = new DecompileContext();
|
||||
|
||||
static M12TextDecompiler()
|
||||
{
|
||||
// Load strings
|
||||
charMap = File.ReadAllLines("m12-text-table.txt");
|
||||
|
||||
// Load text ranges
|
||||
textRanges.Add(new int[] { 0x3697F, 0x8C4B0 });
|
||||
}
|
||||
|
||||
public void Decompile(byte[] rom, int[] addresses, DecompileContext context)
|
||||
{
|
||||
if (ControlCodes == null)
|
||||
throw new Exception("Codelist is null");
|
||||
|
||||
// First pass -- define labels
|
||||
foreach (var address in addresses)
|
||||
context.LabelMap.Append(address);
|
||||
|
||||
foreach(var range in textRanges)
|
||||
ScanAt(rom, range[0], range[1], context, ScanMode.FirstPass, false, false, false);
|
||||
|
||||
// Second pass -- decompile the strings
|
||||
foreach (var range in textRanges)
|
||||
ScanAt(rom, range[0], range[1], context, ScanMode.SecondPass, false, false, true);
|
||||
}
|
||||
|
||||
public string ReadString(byte[] rom, int address, int endAddress, bool basicMode)
|
||||
{
|
||||
return ScanAt(rom, address, endAddress, null, ScanMode.ReadOnce, true, basicMode, false);
|
||||
}
|
||||
|
||||
private string ScanAt(byte[] rom, int startAddress, int endAddress, DecompileContext context,
|
||||
ScanMode mode, bool stopOnEnd, bool basicMode, bool newLines)
|
||||
{
|
||||
bool ended = false;
|
||||
bool foundMatch = false;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
int address = startAddress;
|
||||
|
||||
if (address == 0)
|
||||
{
|
||||
throw new Exception("Null pointer");
|
||||
}
|
||||
|
||||
if (mode == ScanMode.FirstPass)
|
||||
{
|
||||
context.LabelMap.Append(address);
|
||||
}
|
||||
|
||||
while (!ended)
|
||||
{
|
||||
// Check for label definition
|
||||
if (mode == ScanMode.SecondPass && context.LabelMap.Labels.ContainsKey(address))
|
||||
{
|
||||
sb.Append("^" + context.LabelMap[address] + "^");
|
||||
}
|
||||
|
||||
// Check for control codes (unless it's in basic mode)
|
||||
|
||||
// No codes begin with a value above 0x1F, so check for that first
|
||||
if (rom[address + 1] == 0xFF && (!basicMode || (basicMode && (rom[address] == 0))))
|
||||
{
|
||||
// Loop through each control code until we find a match
|
||||
foundMatch = false;
|
||||
foreach (var code in ControlCodes)
|
||||
{
|
||||
if (code.Match(rom, address))
|
||||
{
|
||||
foundMatch = true;
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
// Output the start of the code block
|
||||
sb.Append('[');
|
||||
|
||||
// Output the identifier bytes
|
||||
sb.Append(String.Join(" ", code.Identifier.Select(b => b.ToString("X2")).ToArray()));
|
||||
}
|
||||
|
||||
// Skip the identifier bytes
|
||||
address += code.Identifier.Count;
|
||||
|
||||
// Found a match -- check if it's variable-length
|
||||
if (code.Multiple)
|
||||
{
|
||||
if (code.BeginsWith(0x95) ||
|
||||
code.BeginsWith(0xBD))
|
||||
{
|
||||
int count = rom[address++];
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(count.ToString("X2"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int jump = rom.ReadInt(address);
|
||||
jump += address;
|
||||
|
||||
address += 4;
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if it references any other addresses -- scan those too
|
||||
if (code.BeginsWith(0x04) ||
|
||||
code.BeginsWith(0x05) ||
|
||||
code.BeginsWith(0x80) ||
|
||||
code.BeginsWith(0x81) ||
|
||||
code.BeginsWith(0x82) ||
|
||||
code.BeginsWith(0x86))
|
||||
{
|
||||
// Single relative address at next byte
|
||||
int jump = rom.ReadInt(address);
|
||||
jump += address;
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else if (code.BeginsWith(0x1C))
|
||||
{
|
||||
// Skip two bytes; single relative address afterwards
|
||||
int jump = rom.ReadInt(address + 2);
|
||||
jump += address + 2;
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address].ToString("X2"));
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address + 1].ToString("X2"));
|
||||
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else if (code.BeginsWith(0x9D))
|
||||
{
|
||||
// Skip two bytes; single absolute address afterwards
|
||||
int jump = rom.ReadGbaPointer(address + 2);
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address].ToString("X2"));
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address + 1].ToString("X2"));
|
||||
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else if (code.BeginsWith(0xA2))
|
||||
{
|
||||
// Single absolute address at next byte
|
||||
int jump = rom.ReadGbaPointer(address);
|
||||
|
||||
context.LabelMap.Append(jump);
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
sb.Append(" _");
|
||||
sb.Append(context.LabelMap[jump]);
|
||||
sb.Append('_');
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Regular control code -- output the rest of the bytes
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
for (int i = 0; i < (code.Length - code.Identifier.Count); i++)
|
||||
{
|
||||
sb.Append(' ');
|
||||
sb.Append(rom[address + i].ToString("X2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the rest of the bytes
|
||||
address += code.Length - code.Identifier.Count;
|
||||
}
|
||||
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
// Output the end of the code block
|
||||
sb.Append(']');
|
||||
}
|
||||
|
||||
// End the block if necessary
|
||||
if (stopOnEnd && code.End)
|
||||
{
|
||||
ended = true;
|
||||
}
|
||||
|
||||
// Insert a newline after each end code for readibility
|
||||
if (newLines && (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce) && code.End)
|
||||
{
|
||||
sb.AppendLine();
|
||||
/*sb.Append('(');
|
||||
sb.Append(address.ToString("X"));
|
||||
sb.Append(')');*/
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatch)
|
||||
{
|
||||
// Bad!
|
||||
throw new Exception("Found unknown control code");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's not a control code -- just skip it
|
||||
if (mode == ScanMode.SecondPass || mode == ScanMode.ReadOnce)
|
||||
{
|
||||
if (!basicMode || (basicMode && (rom[address] != 0xFF)))
|
||||
sb.Append(CharLookup(rom[address]));
|
||||
}
|
||||
|
||||
address++;
|
||||
}
|
||||
|
||||
if ((endAddress != -1) && (address >= endAddress))
|
||||
ended = true;
|
||||
}
|
||||
|
||||
if (mode == ScanMode.SecondPass)
|
||||
context.Strings.Add(sb.ToString());
|
||||
|
||||
else if (mode == ScanMode.ReadOnce)
|
||||
return sb.ToString();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string CharLookup(byte value)
|
||||
{
|
||||
if ((value >= 83 && value <= 95) ||
|
||||
(value >= 180 && value <= 191) ||
|
||||
value == 255)
|
||||
{
|
||||
// Invalid
|
||||
throw new Exception("Invalid character");
|
||||
}
|
||||
|
||||
return charMap[value];
|
||||
}
|
||||
|
||||
private enum ScanMode
|
||||
{
|
||||
FirstPass,
|
||||
SecondPass,
|
||||
ReadOnce
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class M12TextTables
|
||||
{
|
||||
private static int[] StupidIndices =
|
||||
{
|
||||
0xB9, 0xBF, 0xC0, 0x164, 0x169,
|
||||
0x16D, 0x16F, 0x171, 0x1B0, 0x1B1,
|
||||
0x1B3, 0x1C1, 0x233, 0x239, 0x247,
|
||||
0x286, 0x2AD, 0x2AE, 0x2AF, 0x2E7,
|
||||
0x30A, 0x318, 0x3E1, 0x458, 0x45D,
|
||||
0x48C, 0x48D, 0x514, 0x515, 0x516,
|
||||
0x57D
|
||||
};
|
||||
|
||||
public static MainStringRef[] ReadTptRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<MainStringRef>();
|
||||
|
||||
int address = 0x8EB14;
|
||||
int entries = 1584;
|
||||
|
||||
for (int i = 0; i < entries; i++)
|
||||
{
|
||||
if (StupidIndices.Contains(i))
|
||||
{
|
||||
int firstPointer = rom.ReadGbaPointer(address + 9);
|
||||
if (firstPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 9, OldPointer = firstPointer });
|
||||
|
||||
byte type = rom[address];
|
||||
if (type != 2)
|
||||
{
|
||||
int secondPointer = rom.ReadGbaPointer(address + 13);
|
||||
if (secondPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 13, OldPointer = secondPointer });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int firstPointer = rom.ReadGbaPointer(address + 12);
|
||||
if (firstPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 12, OldPointer = firstPointer });
|
||||
|
||||
byte type = rom[address];
|
||||
if (type != 2)
|
||||
{
|
||||
int secondPointer = rom.ReadGbaPointer(address + 16);
|
||||
if (secondPointer != 0)
|
||||
refs.Add(new MainStringRef { Index = i, PointerLocation = address + 16, OldPointer = secondPointer });
|
||||
}
|
||||
}
|
||||
|
||||
address += 20;
|
||||
}
|
||||
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
/*public static StringRef[] ReadBattleActionRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x157B68;
|
||||
for (int i = 0; i < 318; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address + 4);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 4, OldPointer = pointer });
|
||||
address += 12;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static StringRef[] ReadPrayerRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x4A309;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address, OldPointer = pointer });
|
||||
address += 4;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static StringRef[] ReadItemHelpRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x155000;
|
||||
for (int i = 0; i < 254; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address + 0x23);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 0x23, OldPointer = pointer });
|
||||
address += 39;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static StringRef[] ReadPsiHelpRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x158A50;
|
||||
for (int i = 0; i < 53; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address + 11);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 11, OldPointer = pointer });
|
||||
address += 15;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static StringRef[] ReadPhoneRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x157AAE;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address + 0x1B);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 0x1B, OldPointer = pointer });
|
||||
address += 31;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
public static StringRef[] ReadEnemyTextRefs(byte[] rom)
|
||||
{
|
||||
var refs = new List<StringRef>();
|
||||
int address = 0x159589;
|
||||
for (int i = 0; i < 231; i++)
|
||||
{
|
||||
int pointer = rom.ReadPointer(address + 0x2D);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 0x2D, OldPointer = pointer });
|
||||
|
||||
pointer = rom.ReadPointer(address + 0x31);
|
||||
if (pointer != 0)
|
||||
refs.Add(new StringRef { Index = i, PointerLocation = address + 0x31, OldPointer = pointer });
|
||||
|
||||
address += 94;
|
||||
}
|
||||
return refs.ToArray();
|
||||
}*/
|
||||
|
||||
public static MiscStringCollection ReadPointerTable(byte[] rom, int tableAddress, int stringsAddress)
|
||||
{
|
||||
var refs = new List<MiscStringRef>();
|
||||
int entries = rom.ReadInt(tableAddress);
|
||||
|
||||
int currentTableAddress = tableAddress;
|
||||
currentTableAddress += 4;
|
||||
|
||||
for (int i = 0; i < entries; i++)
|
||||
{
|
||||
int offset = rom.ReadInt(currentTableAddress);
|
||||
refs.Add(new MiscStringRef
|
||||
{
|
||||
OffsetLocation = currentTableAddress,
|
||||
OldPointer = offset + stringsAddress,
|
||||
Index = i
|
||||
});
|
||||
currentTableAddress += 4;
|
||||
}
|
||||
|
||||
return new MiscStringCollection
|
||||
{
|
||||
OffsetTableLocation = tableAddress,
|
||||
StringsLocation = stringsAddress,
|
||||
StringRefs = refs
|
||||
};
|
||||
}
|
||||
|
||||
public static FixedStringCollection ReadFixedStringTable(byte[] rom, int stringsAddress, int numEntries, int entryLength)
|
||||
{
|
||||
var refs = new List<FixedStringRef>();
|
||||
int currentStringAddress = stringsAddress;
|
||||
|
||||
for(int i=0;i<numEntries;i++)
|
||||
{
|
||||
refs.Add(new FixedStringRef
|
||||
{
|
||||
OldPointer = currentStringAddress,
|
||||
Index = i
|
||||
});
|
||||
currentStringAddress += entryLength;
|
||||
}
|
||||
|
||||
return new FixedStringCollection
|
||||
{
|
||||
StringsLocation = stringsAddress,
|
||||
NumEntries = numEntries,
|
||||
EntryLength = entryLength,
|
||||
StringRefs = refs
|
||||
};
|
||||
}
|
||||
|
||||
public static MiscStringCollection ReadItemNames(byte[] rom)
|
||||
{
|
||||
return ReadPointerTable(rom, 0xB1AF94, 0xB1A694);
|
||||
}
|
||||
|
||||
public static MiscStringCollection ReadMenuChoices(byte[] rom)
|
||||
{
|
||||
return ReadPointerTable(rom, 0xB19A64, 0xB198B4);
|
||||
}
|
||||
|
||||
public static MiscStringCollection ReadMiscText(byte[] rom)
|
||||
{
|
||||
var miscStrings = ReadPointerTable(rom, 0xB17EE4, 0xB17424);
|
||||
|
||||
// Flag basic mode refs
|
||||
for (int i = 0x4A; i <= 0x55; i++)
|
||||
miscStrings.StringRefs[i].BasicMode = true;
|
||||
|
||||
return miscStrings;
|
||||
}
|
||||
|
||||
public static FixedStringCollection ReadPsiNames(byte[] rom)
|
||||
{
|
||||
return ReadFixedStringTable(rom, 0xB1B916, 0x12, 0xD);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
public class MainStringRef
|
||||
{
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int PointerLocation { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int OldPointer { get; set; }
|
||||
|
||||
public string Label { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class MiscStringCollection
|
||||
{
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int OffsetTableLocation { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int StringsLocation { get; set; }
|
||||
|
||||
public IList<MiscStringRef> StringRefs { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
public class MiscStringRef
|
||||
{
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int OffsetLocation { get; set; }
|
||||
|
||||
[JsonConverter(typeof(JsonHexConverter))]
|
||||
public int OldPointer { get; set; }
|
||||
|
||||
public bool BasicMode { get; set; }
|
||||
public string Old { get; set; }
|
||||
public string New { get; set; }
|
||||
|
||||
public bool ShouldSerializeBasicMode()
|
||||
{
|
||||
return BasicMode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ScriptTool
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static IList<ControlCode> EbControlCodes = new List<ControlCode>();
|
||||
static IList<ControlCode> M12ControlCodes = new List<ControlCode>();
|
||||
|
||||
// Decompiler setup
|
||||
static EbTextDecompiler ebDecompiler;
|
||||
static M12TextDecompiler m12Decompiler;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
CommandOptions options = ParseCommandLine(args);
|
||||
if (options == null)
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
|
||||
LoadControlCodes();
|
||||
|
||||
if (options.Command == CommandType.Decompile)
|
||||
{
|
||||
ebDecompiler = new EbTextDecompiler() { ControlCodes = EbControlCodes };
|
||||
m12Decompiler = new M12TextDecompiler() { ControlCodes = M12ControlCodes };
|
||||
|
||||
// Load ROMs
|
||||
byte[] ebRom = File.ReadAllBytes(options.EbRom);
|
||||
byte[] m12Rom = File.ReadAllBytes(options.M12Rom);
|
||||
|
||||
// Decompile misc string tables
|
||||
if (options.DoMiscText)
|
||||
{
|
||||
DecompileEbMisc(ebRom, options.WorkingDirectory);
|
||||
DecompileM12Misc(m12Rom, options.WorkingDirectory);
|
||||
}
|
||||
|
||||
// Decompile main string tables
|
||||
if (options.DoMainText)
|
||||
{
|
||||
DecompileEb(ebRom, options.WorkingDirectory);
|
||||
DecompileM12(m12Rom, options.WorkingDirectory);
|
||||
}
|
||||
}
|
||||
else if (options.Command == CommandType.Compile)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
}
|
||||
|
||||
static void Usage()
|
||||
{
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine(" ScriptTool.exe [-decompile or -compile] [-misc] [-main] workingdirectory [ebrom m12rom]");;
|
||||
}
|
||||
|
||||
static CommandOptions ParseCommandLine(string[] args)
|
||||
{
|
||||
var argList = new List<string>(args);
|
||||
|
||||
// Check for decompile switch
|
||||
CommandType command;
|
||||
if (argList.Contains("-decompile") && !argList.Contains("-compile"))
|
||||
{
|
||||
command = CommandType.Decompile;
|
||||
argList.Remove("-decompile");
|
||||
}
|
||||
else if (argList.Contains("-compile") && !argList.Contains("-decompile"))
|
||||
{
|
||||
command = CommandType.Compile;
|
||||
argList.Remove("-compile");
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for main and misc flags
|
||||
bool doMain = false;
|
||||
bool doMisc = false;
|
||||
if (argList.Contains("-main"))
|
||||
{
|
||||
doMain = true;
|
||||
argList.Remove("-main");
|
||||
}
|
||||
if (argList.Contains("-misc"))
|
||||
{
|
||||
doMisc = true;
|
||||
argList.Remove("-misc");
|
||||
}
|
||||
|
||||
// Check for working directory
|
||||
if (argList.Count < 1)
|
||||
return null;
|
||||
|
||||
string working = argList[0];
|
||||
if (!Directory.Exists(working))
|
||||
return null;
|
||||
|
||||
// Check for ROM paths
|
||||
string ebRom = null;
|
||||
string m12Rom = null;
|
||||
if (command == CommandType.Decompile && argList.Count == 3)
|
||||
{
|
||||
ebRom = argList[1];
|
||||
m12Rom = argList[2];
|
||||
if (!File.Exists(ebRom) || !File.Exists(m12Rom))
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CommandOptions
|
||||
{
|
||||
WorkingDirectory = working,
|
||||
EbRom = ebRom,
|
||||
M12Rom = m12Rom,
|
||||
Command = command,
|
||||
DoMainText = doMain,
|
||||
DoMiscText = doMisc
|
||||
};
|
||||
}
|
||||
|
||||
static void LoadControlCodes()
|
||||
{
|
||||
EbControlCodes = ControlCode.LoadEbControlCodes("eb-codelist.txt");
|
||||
M12ControlCodes = ControlCode.LoadM12ControlCodes("m12-codelist.txt");
|
||||
}
|
||||
|
||||
static void DecompileEb(byte[] ebRom, string workingDirectory)
|
||||
{
|
||||
var context = new DecompileContext();
|
||||
|
||||
// Pull all string refs from the ROM
|
||||
var allRefs = new List<Tuple<string, MainStringRef[]>>();
|
||||
allRefs.Add(Tuple.Create("eb-tpt", EbTextTables.ReadTptRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-battle-actions", EbTextTables.ReadBattleActionRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-prayers", EbTextTables.ReadPrayerRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-item-help", EbTextTables.ReadItemHelpRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-psi-help", EbTextTables.ReadPsiHelpRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-phone", EbTextTables.ReadPhoneRefs(ebRom)));
|
||||
allRefs.Add(Tuple.Create("eb-enemy-encounters", EbTextTables.ReadEnemyTextRefs(ebRom)));
|
||||
|
||||
// Decompile
|
||||
var allPointers = allRefs.SelectMany(rl => rl.Item2).Select(r => r.OldPointer).ToArray();
|
||||
ebDecompiler.Decompile(ebRom, allPointers, context);
|
||||
|
||||
// Update labels for all refs and write to JSON
|
||||
foreach (var refList in allRefs)
|
||||
{
|
||||
foreach (var stringRef in refList.Item2)
|
||||
stringRef.Label = context.LabelMap[stringRef.OldPointer];
|
||||
|
||||
File.WriteAllText(Path.Combine(workingDirectory, refList.Item1 + ".json"), JsonConvert.SerializeObject(refList.Item2, Formatting.Indented));
|
||||
}
|
||||
|
||||
// Write the strings
|
||||
File.WriteAllText(Path.Combine(workingDirectory, "eb-strings.txt"), String.Join(Environment.NewLine, context.Strings));
|
||||
}
|
||||
|
||||
static void DecompileEbMisc(byte[] ebRom, string workingDirectory)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void DecompileM12(byte[] m12Rom, string workingDirectory)
|
||||
{
|
||||
|
||||
var context = new DecompileContext();
|
||||
|
||||
// Pull all string refs from the ROM
|
||||
var allRefs = new List<Tuple<string, MainStringRef[]>>();
|
||||
allRefs.Add(Tuple.Create("m12-tpt", M12TextTables.ReadTptRefs(m12Rom)));
|
||||
|
||||
// Decompile
|
||||
var allPointers = allRefs.SelectMany(rl => rl.Item2).Select(r => r.OldPointer).ToArray();
|
||||
m12Decompiler.Decompile(m12Rom, allPointers, context);
|
||||
|
||||
// Update labels for all refs and write to JSON
|
||||
foreach (var refList in allRefs)
|
||||
{
|
||||
foreach (var stringRef in refList.Item2)
|
||||
stringRef.Label = context.LabelMap[stringRef.OldPointer];
|
||||
|
||||
File.WriteAllText(Path.Combine(workingDirectory, refList.Item1 + ".json"), JsonConvert.SerializeObject(refList.Item2, Formatting.Indented));
|
||||
}
|
||||
|
||||
// Write the strings
|
||||
File.WriteAllText(Path.Combine(workingDirectory, "m12-strings.txt"), String.Join(Environment.NewLine, context.Strings));
|
||||
}
|
||||
|
||||
static void DecompileM12Misc(byte[] m12Rom, string workingDirectory)
|
||||
{
|
||||
// Item names
|
||||
var itemNames = M12TextTables.ReadItemNames(m12Rom);
|
||||
DecompileM12MiscStringCollection(m12Rom, workingDirectory, "m12-itemnames", itemNames);
|
||||
|
||||
// Menu choices
|
||||
var menuChoices = M12TextTables.ReadMenuChoices(m12Rom);
|
||||
DecompileM12MiscStringCollection(m12Rom, workingDirectory, "m12-menuchoices", menuChoices);
|
||||
|
||||
// Misc text
|
||||
var miscText = M12TextTables.ReadMiscText(m12Rom);
|
||||
DecompileM12MiscStringCollection(m12Rom, workingDirectory, "m12-misctext", miscText);
|
||||
|
||||
// PSI names
|
||||
var psiNames = M12TextTables.ReadPsiNames(m12Rom);
|
||||
DecompileM12FixedStringCollection(m12Rom, workingDirectory, "m12-psinames", psiNames);
|
||||
}
|
||||
|
||||
static void DecompileM12MiscStringCollection(byte[] rom, string workingDirectory, string name, MiscStringCollection miscStringCollection)
|
||||
{
|
||||
// Decompile the strings
|
||||
foreach (var miscStringRef in miscStringCollection.StringRefs)
|
||||
{
|
||||
miscStringRef.Old =
|
||||
miscStringRef.New =
|
||||
m12Decompiler.ReadString(rom, miscStringRef.OldPointer, -1, miscStringRef.BasicMode);
|
||||
}
|
||||
|
||||
// Write JSON
|
||||
File.WriteAllText(Path.Combine(workingDirectory, name + ".json"), JsonConvert.SerializeObject(miscStringCollection, Formatting.Indented));
|
||||
}
|
||||
|
||||
static void DecompileM12FixedStringCollection(byte[] rom, string workingDirectory, string name, FixedStringCollection fixedStringCollection)
|
||||
{
|
||||
// Decompile the strings
|
||||
foreach (var fixedStringRef in fixedStringCollection.StringRefs)
|
||||
{
|
||||
fixedStringRef.Old =
|
||||
fixedStringRef.New =
|
||||
m12Decompiler.ReadString(rom, fixedStringRef.OldPointer,
|
||||
fixedStringRef.OldPointer + fixedStringCollection.EntryLength,
|
||||
false);
|
||||
}
|
||||
|
||||
// Write JSON
|
||||
File.WriteAllText(Path.Combine(workingDirectory, name + ".json"), JsonConvert.SerializeObject(fixedStringCollection, Formatting.Indented));
|
||||
}
|
||||
|
||||
//static void CompileM12Misc()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ScriptTool")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ScriptTool")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("04d88ce9-e4a3-457b-9f74-959ddf16f81d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CA5C95AE-2CD2-47E3-B5AE-FE6136808AC4}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ScriptTool</RootNamespace>
|
||||
<AssemblyName>ScriptTool</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandOptions.cs" />
|
||||
<Compile Include="ControlCode.cs" />
|
||||
<Compile Include="DecompileContext.cs" />
|
||||
<Compile Include="FixedStringCollection.cs" />
|
||||
<Compile Include="M12TextTables.cs" />
|
||||
<Compile Include="M12TextDecompiler.cs" />
|
||||
<Compile Include="EbTextDecompiler.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="JsonHexConverter.cs" />
|
||||
<Compile Include="LabelMap.cs" />
|
||||
<Compile Include="MiscStringCollection.cs" />
|
||||
<Compile Include="FixedStringRef.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="EbTextTables.cs" />
|
||||
<Compile Include="MiscStringRef.cs" />
|
||||
<Compile Include="MainStringRef.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="eb-codelist.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="eb-compressed-strings.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="m12-codelist.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="m12-text-table.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,216 @@
|
|||
00,"Line break";
|
||||
01,"Start on Blank Line";
|
||||
!02,"Signal end of block or string";
|
||||
03,"Wait with prompt, brief pause in battle";
|
||||
04 XX XX,"Toggle flag $XXXX on";
|
||||
05 XX XX,"Toggle flag $XXXX off";
|
||||
06 XX XX YY YY YY YY,"If flag $XXXX is set, jump to address $YYYYYYYY";
|
||||
07 XX XX,"Set binary flag with the status of flag $XXXX";
|
||||
08 XX XX XX XX,"Parse text at $XXXXXXXX and continue here";
|
||||
*09,"Multiple-entry pointer table (Jump to address)";
|
||||
!0A XX XX XX XX,"Jump to text at address $XXXXXXXX";
|
||||
0B XX,"Set binary flag to true if number in memory == $XX";
|
||||
0C XX,"Set binary flag to true if number in memory != $XX";
|
||||
0D XX,"Copy from memory $XX into argumentative memory";
|
||||
0E XX,"Input $XX into a memory bank";
|
||||
0F,"Secondary memory +1";
|
||||
10 XX,"Pause for ~0.02 sec. * $XX";
|
||||
11,"Treats text displayed by [1C (07|0C) XX] as a menu";
|
||||
12,"Clear current line of text";
|
||||
13,"Wait without prompt";
|
||||
14,"Wait with prompt in battle";
|
||||
18 00,"Closes most recently used text window";
|
||||
18 01 XX,"Open window";
|
||||
18 02,"UNKNOWN";
|
||||
18 03 XX,"Change parsing focus to window $XX";
|
||||
18 04,"Close all windows";
|
||||
18 05 XX YY,"Display text $XX pixels over and $YY lines down";
|
||||
18 06,"Clear contents from current window";
|
||||
18 07 XX XX XX XX YY,"Check for $XX inequality to memory";
|
||||
18 08 XX,"UNKNOWN";
|
||||
18 09 XX,"UNKNOWN";
|
||||
18 0A,"Open wallet window and display current cash on hand";
|
||||
18 0D XX YY,"Display Status window for Char$XX YY-01-parameter, 01,02 specific, 02 ?";
|
||||
19 02,"Load a text string into memory (end with [02])"
|
||||
19 04,"UNKNOWN";
|
||||
19 05 XX YY ZZ,"Inflict ailment YY YY on character $XX";
|
||||
19 10 XX,"Return the character number of the person in party position $XX"
|
||||
19 11 XX,"Return One Letter from a Character's Name (see lexicon.txt)";
|
||||
19 14,"UNKNOWN";
|
||||
19 16 XX YY,"Return Byte YY of Character XX Status";
|
||||
19 18 XX,"UNKNOWN";
|
||||
19 19 XX YY,"Sets $YY(01-0e) in item menu of Char$XX into working memory";
|
||||
19 1A XX,"UNKNOWN";
|
||||
19 1B XX,"UNKNOWN";
|
||||
19 1C XX YY,"UNKNOWN";
|
||||
19 1D XX YY,"UNKNOWN";
|
||||
19 1E,"UNKNOWN";
|
||||
19 1F,"UNKNOWN";
|
||||
19 20,"UNKNOWN";
|
||||
19 21 XX,"UNKNOWN";
|
||||
19 22 XX XX YY YY,"Store to memory the direction from character $XX to object $YY";
|
||||
19 23 XX XX YY YY ZZ,"Store to memory the direction from TPT entry $XX to object $YY (ZZ unknown)";
|
||||
19 24 XX XX YY YY ZZ,"Store to memory the direction from generated sprite $XX to object $YY (ZZ=00)";
|
||||
19 25 XX,"UNKNOWN";
|
||||
19 26 XX,"UNKNOWN";
|
||||
19 27 XX,"UNKNOWN";
|
||||
19 28 XX,"UNKNOWN";
|
||||
1A 00,"UNKNOWN INCOMPLETE";
|
||||
1A 01 WW WW WW WW XX XX XX XX YY YY YY YY ZZ ZZ ZZ ZZ,"Current Party Member Selection Menu";
|
||||
1A 04,"UNKNOWN INCOMPLETE";
|
||||
1A 05 XX YY,"Display the inventory of character YY in window XX";
|
||||
1A 06 XX,"Displays shop window $XX";
|
||||
1A 07,"Related to Escargo Express stored goods window";
|
||||
1A 08,"UNKNOWN INCOMPLETE";
|
||||
1A 09,"UNKNOWN INCOMPLETE";
|
||||
1A 0A,"Open non-working phone window";
|
||||
1A 0B,"Copy WRAM to Active Memory";
|
||||
1B 00,"Copy all memory to storage";
|
||||
1B 01,"Copy all storage to memory";
|
||||
1B 02 XX XX XX XX,"If binary flag is set 0, jump to $XXXXXXXX";
|
||||
1B 03 XX XX XX XX,"If binary flag is set 1, jump to $XXXXXXXX";
|
||||
1B 04,"Swap working and argumentary memory";
|
||||
1B 05,"Copy Active Memory to WRAM";
|
||||
1B 06,"Copy WRAM to Active Memory";
|
||||
1C 00 XX,"Text and window background color effects";
|
||||
1C 01 XX,"Display statistical data value $XX";
|
||||
1C 02 XX,"Display character name $XX";
|
||||
1C 03 XX,"Display Text Character XX; 00 as argument";
|
||||
1C 04,"Open party HP/PP status windows";
|
||||
1C 05 XX,"Display item name $XX";
|
||||
1C 06 XX,"Display teleport destination name $XX";
|
||||
1C 07 XX,"Display $XX strings centered horizontally (see [19 02])";
|
||||
1C 08 XX,"Display text graphic $XX";
|
||||
1C 09 XX,"UNKNOWN";
|
||||
1C 0A XX XX XX XX,"Displays $XXXXXXXX in decimal";
|
||||
1C 0B XX XX XX XX,"Displays $XXXXXXXX in decimal as money";
|
||||
1C 0C XX,"Display $XX strings vertically (see [19 02])";
|
||||
1C 0D,"Display action user name";
|
||||
1C 0E,"Display action target name";
|
||||
1C 0F,"UNKNOWN INCOMPLETE;IN PROGRESS (Relates to Level-Up stats editor)";
|
||||
1C 11 XX,"UNKNOWN";
|
||||
1C 12 XX,"Print PSI name $XX";
|
||||
1C 13 XX YY,"Display XX Amimation (YY is usually 00) See Animation code on forum";
|
||||
1C 14 XX,"Say $XX pronoun";
|
||||
1C 15 XX,"Say $XX pronoun";
|
||||
1D 00 XX XX,"Add item $YY to character $XX's inventory and return $YY if successful";
|
||||
1D 01 XX YY,"Remove item $YY from character $XX's inventory";
|
||||
1D 02 XX,"Set binary flag true if character $XX does not have free space in their inventory";
|
||||
1D 03 XX,"Set binary flag true if character $XX has free space in their inventory";
|
||||
1D 04 XX YY,"Sets binary flag true if char $XX does not have item $YY";
|
||||
1D 05 XX YY,"Sets binary flag true if char $XX has item $YY";
|
||||
1D 06 XX XX XX XX,"Add $XX dollars to ATM balance";
|
||||
1D 07 XX XX XX XX,"Remove $XX dollars from ATM balance";
|
||||
1D 08 XX XX,"Add $XX dollars to wallet balance";
|
||||
1D 09 XX XX,"Remove $XX dollars from wallet balance"
|
||||
1D 0A XX,"Return price of item";
|
||||
1D 0B XX,"Get one half of item $XX";
|
||||
1D 0C XX XX,"UNKNOWN";
|
||||
1D 0D XX YY YY,"Set binary flag true if character $XX has ailment YY YY";
|
||||
1D 0E XX YY,"Add item $YY to character $XX's inventory and return number of items held";
|
||||
1D 0F XX YY,"UNKNOWN";
|
||||
1D 10 XX XX,"UNKNOWN";
|
||||
1D 11 XX XX,"UNKNOWN";
|
||||
1D 12 XX XX,"UNKNOWN";
|
||||
1D 13 XX XX,"UNKNOWN";
|
||||
1D 14 XX XX XX XX,"Sets binary flag true if the player currently holds $XX in the wallet";
|
||||
1D 15 XX XX,"Multiply $XXXX by the number of characters in the party, and store in Working Memory";
|
||||
1D 17 XX XX XX XX,"Sets binary flag true if the player currently holds $XX in the ATM";
|
||||
1D 18 XX,"UNKNOWN";
|
||||
1D 19 XX,"Sets binary flag true if there are $XX party members";
|
||||
1D 20,"Check same user/target";
|
||||
1D 21 XX,"Generate random number from 0 to $XX";
|
||||
1D 22,"Set binary flag if current sector is Exit mouse-compatible";
|
||||
1D 23 XX,"UNKNOWN";
|
||||
1D 24 XX,"May relate to returning cash earned since last phone call to dad";
|
||||
1E 00 XX YY,"Character $XX recovers HP by YY% of max";
|
||||
1E 01 XX YY,"Character $XX loses HP by YY% of max";
|
||||
1E 02 XX YY,"Character $XX recovers $YY HP";
|
||||
1E 03 XX YY,"Character $XX loses $YY HP";
|
||||
1E 04 XX YY,"Character $XX recovers PP by YY% of max";
|
||||
1E 05 XX YY,"Character $XX loses PP by YY% of max";
|
||||
1E 06 XX YY,"Character $XX recovers $YY PP";
|
||||
1E 07 XX YY,"Character $XX loses $YY PP";
|
||||
1E 08 XX YY,"Character $XX becomes level $YY";
|
||||
1E 09 XX YY YY YY,"Character $XX gains $YYYYYY EXP";
|
||||
1E 0A XX YY,"Boost IQ in character $XX by $YY";
|
||||
1E 0B XX YY,"Boost Guts in character $XX by $YY";
|
||||
1E 0C XX YY,"Boost Speed in character $XX by $YY";
|
||||
1E 0D XX YY,"Boost Vitality in character $XX by $YY";
|
||||
1E 0E XX YY,"Boost Luck in character $XX by $YY";
|
||||
1F 00 XX YY,"Play music track $YY ($XX is unused)";
|
||||
1F 01 00,"Stops music";
|
||||
1F 02 XX,"Play sound effect $XX";
|
||||
1F 03,"Return music setting to sector default";
|
||||
1F 04 XX,"Toggles sound for text printing (?)";
|
||||
1F 05,"Disallow Sector Boundaries to Change Music";
|
||||
1F 06,"Allow Sector Boundaries to Change Music";
|
||||
1F 07 XX,"Apply audio effect $XX";
|
||||
1F 11 XX,"Add character $XX to party";
|
||||
1F 12 XX,"Remove character $XX from party";
|
||||
1F 13 XX YY,"Turn character $XX to direction $YY";
|
||||
1F 14 XX,"UNKNOWN";
|
||||
1F 15 XX XX YY YY ZZ,"Generate sprite $XXXX with movement pattern $YYYY using style $ZZ";
|
||||
1F 16 XX XX YY,"Turn TPT entry $XXXX to direction $YY";
|
||||
1F 17 XX XX YY YY ZZ,"Generate TPT entry $XXXX with movement pattern $YYYY using style $ZZ";
|
||||
1F 18 XX XX XX XX XX XX XX,"UNKNOWN";
|
||||
1F 19 XX XX XX XX XX XX XX,"UNKNOWN";
|
||||
1F 1A XX XX YY,"Generate sprite $YY near TPT entry $XXXX";
|
||||
1F 1B XX XX,"Delete 1F 1A sprite near TPT entry $XXXX";
|
||||
1F 1C XX YY,"Generate sprite $YY near character $XX";
|
||||
1F 1D XX,"Delete 1F 1C sprite near character $XX";
|
||||
1F 1E XX XX YY,"Make TPT entry $XXXX disappear via style $YY";
|
||||
1F 1F XX XX YY,"Delete 1F 15-generated sprite $XXXX via style $YY";
|
||||
1F 20 XX YY,"PSI Teleport to destination $XX using method $YY";
|
||||
1F 21 XX,"Teleport to 0x15EDAB teleport coordinate entry $XX";
|
||||
1F 23 XX XX,"Trigger battle with 0x10D74C enemy group entry $XXXX";
|
||||
1F 30,"Change to normal font";
|
||||
1F 31,"Change to Mr. Saturn font";
|
||||
1F 41 XX,"Call special event $XX";
|
||||
1F 50,"Disable controller input";
|
||||
1F 51,"Re-enable controller input";
|
||||
1F 52 XX,"Number selector with XX digits";
|
||||
1F 60 XX,"UNKNOWN";
|
||||
1F 61,"Simultaneously commences all prepared movements";
|
||||
1F 62 XX,"UNKNOWN";
|
||||
1F 63 XX XX XX XX,"Jump to $XXXXXXXX after the next screen refresh";
|
||||
1F 64,"Purge all NPCs from party";
|
||||
1F 65,"Purge first NPC from party";
|
||||
1F 66 XX YY ZZ ZZ ZZ ZZ,"Activate hotspot $XX with address $ZZZZZZZZ";
|
||||
1F 67 XX,"Deactivate hotspot $XX";
|
||||
1F 68,"Store current coordinates into memory";
|
||||
1F 69,"Teleport to coordinates stored by 1F 68";
|
||||
1F 71 XX YY,"Character $XX realizes special PSI $YY";
|
||||
1F 81 XX XX,"Check If Character Can Use Item";
|
||||
1F 83 XX XX,"Equip character XX with his or her YYth item";
|
||||
1F 90,"UNKNOWN";
|
||||
1F A0,"TPT entry being spoken to/checked faces downwards";
|
||||
1F A1,"Change Direction of Current TPT Entry to Down";
|
||||
1F A2,"UNKNOWN";
|
||||
1F B0,"Save the game in the slot selected at the beginning";
|
||||
*1F C0,"Multiple-entry pointer table (Reference address)";
|
||||
1F D0 XX,"Attempt to Fix Items";
|
||||
1F D1,"Returns a numeric value based on the proximity of a magic truffle TPT entry";
|
||||
1F D2 XX,"Summon photographer to location $XX";
|
||||
1F D3 XX,"Trigger timed event $XX from the 0x15F845 table";
|
||||
1F E1 XX YY ZZ,"Change map palette to that of tileset $XX, pallet $YY at speed $ZZ";
|
||||
1F E4 XX XX YY,"Change direction of 1F 15-generated sprite $XXXX to $YY";
|
||||
1F E5 XX,"Lock player movement";
|
||||
1F E6 XX XX,"Delay appearance of TPT entry $XXXX until end of text parsing";
|
||||
1F E7 XX XX,"UNKNOWN";
|
||||
1F E8 XX,"Restrict player movement if camera is focused on other sprite (XX is usually FF)";
|
||||
1F E9 XX XX,"Restrict player movement until end of text block (use 1F 61 after)";
|
||||
1F EA XX XX,"UNKNOWN";
|
||||
1F EB XX YY,"Make character $XX disappear via style $YY";
|
||||
1F EC XX YY,"Make character $XX appear via style $YY";
|
||||
1F ED,"Your party will be teleported (in a glitchy way) on top of some sprite that is nearby when the text block is over if the camera switched to another sprite in the block of text";
|
||||
1F EE XX XX,"UNKNOWN";
|
||||
1F EF XX XX,"Focuses the camera to where [1f 15]-generated sprite xxxx is but doesn't follow it";
|
||||
1F F0,"Activate bicycle";
|
||||
1F F1 XX XX YY YY,"Apply movement pattern $YYYY to TPT entry $XXXX";
|
||||
1F F2 XX XX YY YY,"Apply movement pattern $YYYY to sprite $XXXX";
|
||||
1F F3 XX XX YY,"Generate sprite $YY near sprite $XXXX";
|
||||
1F F4 XX XX,"Delete 1F F3 sprite near sprite $XXXX";
|
||||
15 XX,"Use compressed string $XX from bank 0";
|
||||
16 XX,"Use compressed string $XX from bank 1";
|
||||
17 XX,"Use compressed string $XX from bank 2";
|
|
@ -0,0 +1,768 @@
|
|||
|
||||
in the
|
||||
that
|
||||
...
|
||||
and
|
||||
this
|
||||
to the
|
||||
about
|
||||
just
|
||||
of the
|
||||
something
|
||||
going to
|
||||
to
|
||||
you have
|
||||
your
|
||||
for
|
||||
you're
|
||||
@You
|
||||
really
|
||||
don't
|
||||
@The
|
||||
e the
|
||||
e you
|
||||
...
|
||||
the
|
||||
will
|
||||
...Brick Road
|
||||
ing
|
||||
some
|
||||
|
||||
@Do you want to
|
||||
like
|
||||
ou don't have
|
||||
is
|
||||
you
|
||||
you
|
||||
anything else
|
||||
the
|
||||
you want to
|
||||
for the
|
||||
friend
|
||||
at the
|
||||
ould you like
|
||||
from
|
||||
would
|
||||
he Runaway Five
|
||||
with
|
||||
want to
|
||||
@If you
|
||||
you don't
|
||||
s the
|
||||
ed to
|
||||
e...
|
||||
something
|
||||
t the
|
||||
@...
|
||||
@Please
|
||||
's
|
||||
of your
|
||||
@It's
|
||||
@Thank you
|
||||
@I
|
||||
here.
|
||||
in
|
||||
@Do you
|
||||
I'll
|
||||
have
|
||||
e of
|
||||
d you
|
||||
@I'm
|
||||
me to
|
||||
@I don't
|
||||
@Well,
|
||||
@This is
|
||||
ed the
|
||||
@You're
|
||||
for a
|
||||
anything
|
||||
ing
|
||||
of
|
||||
you should
|
||||
I
|
||||
from the
|
||||
s...
|
||||
it's
|
||||
time
|
||||
e to
|
||||
ed
|
||||
e of the
|
||||
to you
|
||||
n't you
|
||||
again
|
||||
for you.
|
||||
other
|
||||
ation
|
||||
little
|
||||
ing to
|
||||
can't
|
||||
much
|
||||
someone
|
||||
on the
|
||||
looks like
|
||||
don't you
|
||||
very
|
||||
the
|
||||
can
|
||||
you
|
||||
that you
|
||||
it
|
||||
you want
|
||||
ou can't
|
||||
able to
|
||||
already
|
||||
give you
|
||||
understand
|
||||
|
||||
my
|
||||
you can
|
||||
that
|
||||
what
|
||||
here's
|
||||
there
|
||||
n the
|
||||
@What
|
||||
Thank you
|
||||
I can't
|
||||
one
|
||||
@The
|
||||
thought
|
||||
not
|
||||
You should
|
||||
ou know
|
||||
has
|
||||
back
|
||||
of
|
||||
ve been
|
||||
I'm
|
||||
there
|
||||
with you
|
||||
@I heard
|
||||
in
|
||||
here
|
||||
Fourside
|
||||
I wonder
|
||||
to
|
||||
could
|
||||
think
|
||||
out
|
||||
good
|
||||
the
|
||||
You
|
||||
too much
|
||||
ome back
|
||||
t...
|
||||
here
|
||||
thing
|
||||
come
|
||||
ly
|
||||
ent
|
||||
strong
|
||||
money.
|
||||
@I'll
|
||||
an
|
||||
ou must
|
||||
are you
|
||||
with the
|
||||
on your
|
||||
too many
|
||||
you.
|
||||
know
|
||||
to be
|
||||
around
|
||||
if you
|
||||
@Are you
|
||||
ome again
|
||||
e and
|
||||
more
|
||||
think
|
||||
e your
|
||||
@Don't
|
||||
nd the
|
||||
t to
|
||||
rea
|
||||
he
|
||||
me
|
||||
strange
|
||||
for you
|
||||
ight
|
||||
a
|
||||
be
|
||||
ther
|
||||
all
|
||||
cannot
|
||||
here is
|
||||
You have
|
||||
Monotoli
|
||||
was
|
||||
ll you
|
||||
hat
|
||||
, but
|
||||
stuff
|
||||
eep
|
||||
it
|
||||
didn't
|
||||
like th
|
||||
ll right
|
||||
should
|
||||
over
|
||||
@Oh,
|
||||
hear
|
||||
every
|
||||
I'm not
|
||||
about t
|
||||
zombies
|
||||
damage
|
||||
his is
|
||||
all
|
||||
some
|
||||
@It
|
||||
attack
|
||||
right
|
||||
ally
|
||||
orry
|
||||
ess
|
||||
er
|
||||
@That's
|
||||
carry it
|
||||
ake
|
||||
t was
|
||||
, the
|
||||
n you
|
||||
sn't
|
||||
help
|
||||
king
|
||||
ear
|
||||
ing the
|
||||
It's
|
||||
very
|
||||
talking
|
||||
ou've
|
||||
that's
|
||||
to me
|
||||
@Hello
|
||||
enemy
|
||||
you are
|
||||
by
|
||||
IBNT
|
||||
ight
|
||||
on't
|
||||
est
|
||||
ick
|
||||
power
|
||||
s that
|
||||
s are
|
||||
call
|
||||
t is
|
||||
is
|
||||
age
|
||||
, and
|
||||
great
|
||||
@Thanks
|
||||
people
|
||||
ter
|
||||
not
|
||||
ill
|
||||
ness
|
||||
@This
|
||||
into
|
||||
ha
|
||||
I can
|
||||
t your
|
||||
before
|
||||
things
|
||||
tion
|
||||
for
|
||||
be
|
||||
this
|
||||
Happy
|
||||
You
|
||||
out
|
||||
enough
|
||||
I'm
|
||||
@You
|
||||
go
|
||||
for
|
||||
all th
|
||||
though
|
||||
ing you
|
||||
e you
|
||||
ring
|
||||
one
|
||||
get
|
||||
t you
|
||||
@I'm s
|
||||
the s
|
||||
e's
|
||||
port
|
||||
d...
|
||||
out
|
||||
@What
|
||||
get
|
||||
I have
|
||||
looking
|
||||
n this
|
||||
of my
|
||||
have a
|
||||
ent
|
||||
do
|
||||
d of
|
||||
ting
|
||||
ncrease
|
||||
Twoson
|
||||
through
|
||||
s your
|
||||
ou'll
|
||||
place
|
||||
right
|
||||
Onett
|
||||
|
||||
our
|
||||
too
|
||||
ater
|
||||
be
|
||||
ain
|
||||
ing.
|
||||
take
|
||||
e is
|
||||
the
|
||||
please
|
||||
do you
|
||||
need
|
||||
use
|
||||
now.
|
||||
got
|
||||
|
||||
and
|
||||
ning
|
||||
sta
|
||||
the t
|
||||
I was
|
||||
y the
|
||||
his
|
||||
appe
|
||||
con
|
||||
ho
|
||||
hat's
|
||||
Threed
|
||||
get
|
||||
s of
|
||||
inter
|
||||
talk
|
||||
man
|
||||
day
|
||||
ove
|
||||
ha ha
|
||||
inally
|
||||
monkey
|
||||
s and
|
||||
ate
|
||||
see
|
||||
town
|
||||
side
|
||||
y to
|
||||
ever
|
||||
equip
|
||||
than
|
||||
who
|
||||
long
|
||||
care
|
||||
room
|
||||
e are
|
||||
ard
|
||||
end
|
||||
, you
|
||||
the b
|
||||
I know
|
||||
think
|
||||
s you
|
||||
time
|
||||
ment
|
||||
so
|
||||
!
|
||||
I've
|
||||
ell
|
||||
wa
|
||||
ious
|
||||
reat
|
||||
live
|
||||
ange
|
||||
we
|
||||
ble
|
||||
@.....
|
||||
ecover
|
||||
only
|
||||
thing
|
||||
er...
|
||||
Mr.
|
||||
ough
|
||||
now
|
||||
I
|
||||
wor
|
||||
to
|
||||
ed.
|
||||
I
|
||||
're
|
||||
give
|
||||
ing a
|
||||
return
|
||||
better
|
||||
ince
|
||||
well
|
||||
one
|
||||
still
|
||||
ying
|
||||
me...
|
||||
sta
|
||||
ust
|
||||
per
|
||||
lease
|
||||
ling
|
||||
point
|
||||
ect
|
||||
ast
|
||||
pretty
|
||||
Giygas
|
||||
ecause
|
||||
member
|
||||
carry
|
||||
used
|
||||
elieve
|
||||
money
|
||||
pres
|
||||
way
|
||||
di
|
||||
even
|
||||
ound
|
||||
s to
|
||||
ting
|
||||
ted
|
||||
oing
|
||||
and
|
||||
ine
|
||||
T
|
||||
sure
|
||||
on
|
||||
@...I
|
||||
while
|
||||
@but
|
||||
@We
|
||||
ice
|
||||
se
|
||||
ive
|
||||
rea
|
||||
com
|
||||
est
|
||||
have
|
||||
but
|
||||
away
|
||||
here
|
||||
must
|
||||
but
|
||||
want
|
||||
ready
|
||||
I'm
|
||||
carr
|
||||
my
|
||||
ay...
|
||||
are
|
||||
@Hey,
|
||||
world
|
||||
ing a
|
||||
happ
|
||||
seem
|
||||
his
|
||||
nder
|
||||
se
|
||||
ant
|
||||
item
|
||||
@But
|
||||
sho
|
||||
in a
|
||||
made
|
||||
night
|
||||
et's
|
||||
like
|
||||
The
|
||||
che
|
||||
de
|
||||
ful
|
||||
hat
|
||||
and
|
||||
self
|
||||
ould
|
||||
@No
|
||||
car
|
||||
tr
|
||||
good
|
||||
stor
|
||||
ombie
|
||||
@Oh
|
||||
@It
|
||||
s a
|
||||
vent
|
||||
ant
|
||||
so
|
||||
olla
|
||||
ree
|
||||
Your
|
||||
make
|
||||
work
|
||||
power
|
||||
home
|
||||
also
|
||||
ance
|
||||
@How
|
||||
h...
|
||||
@If
|
||||
ple
|
||||
buy
|
||||
e,
|
||||
n't
|
||||
oke
|
||||
n't
|
||||
more
|
||||
Good
|
||||
t a
|
||||
all
|
||||
take
|
||||
round
|
||||
when
|
||||
name
|
||||
being
|
||||
attle
|
||||
ite
|
||||
ack
|
||||
y...
|
||||
@Whe
|
||||
with
|
||||
al
|
||||
have
|
||||
look
|
||||
t of
|
||||
aster
|
||||
a lo
|
||||
feel
|
||||
here
|
||||
count
|
||||
monst
|
||||
now
|
||||
ark
|
||||
ous
|
||||
'll
|
||||
bus
|
||||
head
|
||||
any
|
||||
t you
|
||||
erson
|
||||
after
|
||||
ummer
|
||||
hard
|
||||
ful
|
||||
ever
|
||||
kid
|
||||
a b
|
||||
kay
|
||||
tra
|
||||
pla
|
||||
ook
|
||||
ome
|
||||
eat
|
||||
@Wel
|
||||
off
|
||||
turn
|
||||
I am
|
||||
oney
|
||||
any
|
||||
ave
|
||||
any
|
||||
enem
|
||||
con
|
||||
me
|
||||
red
|
||||
en
|
||||
bo
|
||||
re
|
||||
ell
|
||||
sell
|
||||
what
|
||||
next
|
||||
ure
|
||||
bu
|
||||
pro
|
||||
on
|
||||
res
|
||||
es
|
||||
lo
|
||||
our
|
||||
use
|
||||
iste
|
||||
ood
|
||||
no
|
||||
ope
|
||||
ock
|
||||
row
|
||||
@He
|
||||
how
|
||||
may
|
||||
as
|
||||
stor
|
||||
are
|
||||
ost
|
||||
mean
|
||||
We
|
||||
He
|
||||
@An
|
||||
it
|
||||
in
|
||||
ound
|
||||
one.
|
||||
come
|
||||
blue
|
||||
way,
|
||||
or
|
||||
mo
|
||||
.
|
||||
each
|
||||
some
|
||||
@(Th
|
||||
otel
|
||||
hand
|
||||
came
|
||||
ca
|
||||
ame
|
||||
@Hey
|
||||
een
|
||||
spec
|
||||
red
|
||||
ing!
|
||||
...
|
||||
hose
|
||||
ind
|
||||
ice
|
||||
ver
|
||||
W
|
||||
min
|
||||
et
|
||||
on
|
||||
ace
|
||||
er.
|
||||
are
|
||||
nter
|
||||
o...
|
||||
were
|
||||
help
|
||||
old
|
||||
it.
|
||||
hear
|
||||
stop
|
||||
look
|
||||
com
|
||||
@Do
|
||||
her
|
||||
pro
|
||||
chin
|
||||
ble
|
||||
e a
|
||||
girl
|
||||
luck
|
||||
B
|
||||
act
|
||||
ike
|
||||
down
|
||||
part
|
||||
see
|
||||
use
|
||||
uch
|
||||
from
|
||||
just
|
||||
llow
|
||||
@Her
|
||||
at
|
||||
@So,
|
||||
ye
|
||||
ser
|
||||
ying
|
||||
ring
|
||||
eave
|
||||
big
|
||||
ried
|
||||
was
|
||||
say
|
||||
su
|
||||
her
|
||||
it.
|
||||
Man
|
||||
kin
|
||||
up
|
||||
ers
|
||||
@Why
|
||||
p...
|
||||
cour
|
||||
him
|
||||
agic
|
||||
any
|
||||
fin
|
||||
eal
|
||||
he
|
||||
ide
|
||||
oor
|
||||
ity
|
||||
got
|
||||
ens
|
||||
ish
|
||||
ive
|
||||
sa
|
||||
oon
|
||||
fee
|
||||
s a
|
||||
nce
|
||||
D
|
||||
uck
|
||||
ass
|
||||
man
|
||||
a p
|
||||
@(I
|
||||
@Wh
|
||||
gu
|
||||
(
|
||||
bus
|
||||
los
|
||||
ts
|
||||
ba
|
||||
S
|
||||
if
|
||||
@Ha
|
||||
ma
|
||||
unn
|
||||
ay
|
||||
ner
|
||||
@A
|
||||
or
|
||||
stu
|
||||
ust
|
||||
kya
|
||||
shi
|
||||
pos
|
||||
A
|
||||
int
|
||||
le
|
||||
ary
|
||||
ven
|
||||
ch
|
||||
own
|
||||
hu
|
||||
@My
|
||||
@So
|
||||
sp
|
||||
sh
|
||||
wan
|
||||
ool
|
||||
Y
|
||||
old
|
||||
eas
|
||||
, I
|
||||
iki
|
||||
@Ky
|
||||
@Ye
|
||||
spi
|
|
@ -0,0 +1,198 @@
|
|||
!00 FF,End (02)
|
||||
01 FF,New line (00)
|
||||
02 FF,Prompt + new line (03 00)
|
||||
03 FF XX XX,Display menu string set {0:X}
|
||||
04 FF XX XX XX XX,Jump to offset {0:X} if first choice selected
|
||||
05 FF XX XX XX XX,Jump to offset {0:X} if second choice selected
|
||||
08 FF XX XX,Set flag {0:X} (04)
|
||||
09 FF XX XX,Unset flag {0:X} (05)
|
||||
0C FF,Party leader's name
|
||||
0D FF,Ness' name (1C 02 01 or 1C 01 08)
|
||||
0E FF,Paula's name (1C 02 02)
|
||||
0F FF,Jeff's name (1C 02 03)
|
||||
10 FF,Poo's name (1C 02 04)
|
||||
11 FF,Favorite food (1C 01 04)
|
||||
12 FF,Favorite thing (1C 01 05)
|
||||
14 FF XX XX,Teleport to entry {0:X} (1F 21)
|
||||
15 FF,King's name (1C 02 07)
|
||||
!18 FF XX XX,Unknown
|
||||
1A FF XX XX,Display string {0:X}? (Appears after 90 FF)
|
||||
1B FF XX XX,Pause for {0:X} frames (10)
|
||||
1C FF XX XX YY YY YY YY,If flag {0:X} is set, jump to offset {1:X} and return (06)
|
||||
1D FF,Wait without prompt (13)
|
||||
1E FF XX XX,Return one letter from a character's name (19 11)
|
||||
1F FF XX XX,Display text character {0:X} (1C 03)
|
||||
20 FF,Display SMAAASH!! graphics (1C 08 01)
|
||||
21 FF,Display YOU WIN! graphics (1C 08 02)
|
||||
22 FF,Unknown
|
||||
23 FF,Display cash in ATM (1C 01 07)
|
||||
24 FF,Display character 1 defense (1C 01 12)
|
||||
25 FF,Display character 2 defense (1C 01 28)
|
||||
26 FF,Display character 3 defense (1C 01 3E)
|
||||
27 FF,Display character 4 defense (1C 01 54)
|
||||
28 FF,Display character 1 offense (1C 01 11)
|
||||
29 FF,Display character 2 offense (1C 01 27)
|
||||
2A FF,Display character 3 offense (1C 01 3D)
|
||||
2B FF,Display character 4 offense (1C 01 53)
|
||||
2D FF,Display PSI name? (1C 12 00)
|
||||
2E FF,Show main text window (18 01 01)
|
||||
5F FF XX,Set the current rendering location to {0:X} (custom code)
|
||||
60 FF XX,Add {0:X} pixels to the current rendering location (custom code)
|
||||
61 FF XX XX,Toggles sound for text printing (?) (1F 04)
|
||||
62 FF,Display inventory? (?)
|
||||
63 FF,Display cash on hand (1C 01 06)
|
||||
64 FF,Call special event (value pushed with FC FF?) (1F 41)
|
||||
65 FF,Purge all NPCs from party (1F 64)
|
||||
66 FF,Unknown (19 1E)
|
||||
67 FF,Unknown (19 28)
|
||||
68 FF,Clear main text window (sometimes used in place of 18 01 01)
|
||||
69 FF,Open party HP/PP status windows (1C 04)
|
||||
6A FF XX XX,Set binary flag if number in memory != {0:X} (0C)
|
||||
6B FF XX XX,Apply audio effect {0:X} (1F 07)
|
||||
6C FF XX XX YY YY,Sets binary flag true if character {0:X} does not have item {1:X} (1D 04)
|
||||
6D FF XX XX YY YY,Remove item {1:X} from character {0:X}'s inventory (1D 01)
|
||||
6E FF XX XX,Deactivate hotspot {0:X} (1F 67)
|
||||
6F FF XX XX YY YY,Boost vitality in character {0:X} by {1:X} (1E 0D, values match)
|
||||
70 FF XX XX YY YY,Boost speed in character {0:X} by {1:X} (1E 0C, values match)
|
||||
71 FF XX XX YY YY,Boost guts in character {0:X} by {1:X} (1E 0B, values match)
|
||||
72 FF XX XX YY YY,Boost IQ in character {0:X} by {1:X} (1E 0A, values match)
|
||||
73 FF XX XX YY YY,Boost luck in character {0:X} by {1:X} (1E 0E, values match)
|
||||
74 FF,Stop music (1F 01 00)
|
||||
75 FF,Unknown (?)
|
||||
76 FF XX XX,Show window flavor menu? Argument seems to tell it which string to start with (so a value of 1 will skip the first flavor and show the remaining 6)
|
||||
77 FF XX XX,Unknown (1D 18, values match)
|
||||
78 FF XX XX YY YY,Unknown (19 1D, values match)
|
||||
79 FF XX XX YY YY,Unknown (19 1C, values match)
|
||||
7A FF XX XX,Unknown (19 1A, values match)
|
||||
7B FF,Change to Mr. Saturn font (1F 31)
|
||||
7C FF,Change to normal font (1F 30)
|
||||
7D FF,Activate bicycle (1F F0)
|
||||
7E FF XX XX,Unknown (19 26)
|
||||
7F FF,Save the game in the slot selected at the beginning (1F B0)
|
||||
!80 FF XX XX XX XX,Jump to offset {0:X} and don't return (0A)
|
||||
81 FF XX XX XX XX,If binary flag is set, jump to offset {0:X} and return (1B 03)
|
||||
82 FF XX XX XX XX,If binary flag is unset, jump to offset {0:X} and return (1B 02)
|
||||
83 FF XX XX,Set binary flag to status of flag {0:X} (07)
|
||||
84 FF XX XX YY YY ZZ ZZ,Generate TPT entry {0:X} with movement pattern {1:X} using style {2:X} (1F 17)
|
||||
85 FF XX XX YY YY,Make TPT entry {0:X} disappear via style {1:X} (1F 1E)
|
||||
86 FF XX XX XX XX,Jump to offset {0:X} and return (08)
|
||||
87 FF,Swap working and argumentary memory (1B 04)
|
||||
88 FF,Copy all memory to storage (1B 00)
|
||||
89 FF,Copy all storage to memory (1B 01)
|
||||
8A FF,Copy active memory to working memory (1B 05)
|
||||
8B FF,Copy working memory to active memory (1B 06)
|
||||
8C FF,Unknown (1F A2)
|
||||
8D FF XX XX,Load character number in party position {0:X} (19 10)
|
||||
8E FF,TPT entry being spoken to/checked faces downwards (1F A0)
|
||||
8F FF,Change direction of current TPT entry to down (1F A1)
|
||||
90 FF XX,Load character/item name {0:X} into memory (?)
|
||||
91 FF XX,Set binary flag if character {0:X} has free space in their inventory (1D 03)
|
||||
92 FF XX YY YY,Set binary flag true if character {0:X} has ailment {1:X} (corresponds exactly to 1D 0D XX YY YY)
|
||||
93 FF XX YY,Add item {1:X} to character {0:X}'s inventory and return number of items held (1D 0E)
|
||||
94 FF XX,Display shop window {0:X} (1A 06)
|
||||
*95 FF,Jump table with return (09)
|
||||
96 FF XX,Set binary flag if there are {0:X} party members (1D 19)
|
||||
97 FF XX,Set binary flag if character {0:X} does not have free space in their inventory (1D 02)
|
||||
98 FF XX,Return price of item {0:X} (1D 0A)
|
||||
99 FF XX XX XX XX,Sets binary flag if the player currently holds {0:X} in the wallet (1D 14)
|
||||
9A FF XX XX,Set binary flag if number in memory == {0:X} (0B)
|
||||
9B FF XX XX XX XX,Remove {0:X} dollars from wallet (1D 09)
|
||||
9C FF,Open wallet window and display current cash on hand (18 0A)
|
||||
9D FF XX YY ZZ ZZ ZZ ZZ,Activate hotspot {0:X} with address ${2:X} (1F 66)
|
||||
9E FF,Simultaneously commences all prepared movements (1F 61)
|
||||
9F FF,Display action user name (1C 0D)
|
||||
A0 FF XX XX YY YY ZZ ZZ,Generate sprite {0:X} with movement pattern {1:X} using style {2:X} (1F 15)
|
||||
A1 FF XX XX YY YY,Apply movement pattern {1:X} to TPT entry {0:X} (1F F1)
|
||||
A2 FF XX XX XX XX,After finishing this text block, close all other windows, jump to offset {0:X} and don't return (?)
|
||||
A3 FF XX XX,Restrict player movement until end of text block (1F E9, use 9E FF after)
|
||||
A4 FF XX XX,Delay appearance of TPT entry {0:X} until end of text parsing (1F E6)
|
||||
A5 FF XX XX YY YY,Delete A0 FF-generated sprite {0:X} via style {1:X} (1F 1F)
|
||||
A6 FF XX XX YY YY,Apply movement pattern {1:X} to sprite {0:X} (1F F2)
|
||||
A7 FF XX XX,Trigger battle with enemy group entry {0:X} (1F 23)
|
||||
A8 FF XX,Copy from memory {0:X} into argumentative memory (0D)
|
||||
A9 FF XX XX,Unknown (1F EA, values don't match)
|
||||
AA FF XX XX,Unknown (1F E7, values don't match)
|
||||
AB FF XX YY,Copies item {1:X} from character {0:X}'s inventory into working memory (19 19)
|
||||
AC FF,Unknown (1C 0F)
|
||||
AD FF,Display action target name (1C 0E)
|
||||
AE FF XX,Add character {0:X} to party (1F 11)
|
||||
AF FF XX,Remove character {0:X} from party (1F 12)
|
||||
B0 FF XX XX YY YY,Generate sprite {1:X} near TPT entry {0:X} (1F 1A)
|
||||
B1 FF XX XX YY YY,Generate sprite {1:X} near sprite {0:X} (1F F3)
|
||||
B2 FF XX XX YY YY,Generate sprite {1:X} near character {0:X} (1F 1C)
|
||||
B3 FF XX XX,Delete B0 FF sprite near TPT entry {0:X} (1F 1B)
|
||||
B4 FF XX XX,Delete B1 FF sprite near sprite {0:X} (1F F4)
|
||||
B5 FF XX XX,Delete B2 FF sprite near character {0:X} (1F 1D)
|
||||
B6 FF XX YY,Display the inventory of character {1:X} in window {0:X} (1A 05, values match)
|
||||
B7 FF XX,Return half-price of item {0:X} (1D 0B)
|
||||
B8 FF XX,Load {0:X} into memory as a decimal string (related to 1C 0A)
|
||||
B9 FF XX XX YY YY,Unknown (1D 0F)
|
||||
BA FF XX XX XX XX,Add {0:X} dollars to wallet (1D 08)
|
||||
BB FF XX,Multiply {0:X} by the number of characters in the party, and store in working memory (1D 15)
|
||||
BC FF XX XX,Input {0:X} into memory bank (0E)
|
||||
*BD FF,Jump table with return (1F C0)
|
||||
BE FF XX XX YY YY,Set binary flag if character {0:X} has item {1:X} (1D 05)
|
||||
BF FF,Unknown (19 20)
|
||||
C0 FF,Increment secondary memory (0F)
|
||||
C1 FF,Unknown (19 1F)
|
||||
C2 FF,Unknown, appears before 1A FF 05 00 (1C 11 69)
|
||||
C3 FF XX XX YY YY,Store to memory the direction from character {0:X} to object {1:X} (19 22)
|
||||
C4 FF XX YY,Play music {1:X} (1F 00)
|
||||
C5 FF,Return music to sector default (1F 03)
|
||||
C6 FF,Close all windows (18 04)
|
||||
C7 FF,Close most recently-used window (18 00)
|
||||
C8 FF XX XX,Number selector with {0:X} digits (1F 52)
|
||||
C9 FF XX XX,Focuses the camera to where A0 FF-generated sprite {0:X} is but doesn't follow it (1F EF)
|
||||
CA FF,Your party will be teleported (in a glitchy way) on top of some sprite that is nearby when the text block is over if the camera switched to another sprite in the block of text (1F ED)
|
||||
CB FF XX XX YY YY,Make character {0:X} disappear via style {1:X} (1F EB)
|
||||
CC FF XX XX YY YY,Make character {0:X} appear via style {1:X} (1F EC)
|
||||
CD FF XX XX YY YY ZZ ZZ,Change map palette to that of tileset {0:X}, palette {1:X} at speed {2:X} (1F E1)
|
||||
CE FF XX XX YY YY,Turn TPT entry {0:X} to direction {1:X} (1F 16)
|
||||
CF FF XX XX,Trigger timed event {0:X} (1F D3)
|
||||
D0 FF XX XX XX XX,Sets binary flag true if the player currently holds {0:X} in the ATM (1D 17)
|
||||
D1 FF XX XX XX XX,Add {0:X} dollars to ATM balance (1D 06)
|
||||
D3 FF XX XX,Remove {0:X} dollars from ATM balance? (1D 07)
|
||||
D4 FF XX XX,Play sound effect {0:X} (1F 02)
|
||||
D5 FF XX XX,Unknown (1D 23, value matches)
|
||||
D6 FF XX XX YY YY,Unknown (1D 11, value matches)
|
||||
D7 FF XX XX YY YY,Equip character {0:X} with their {1:X}'th item (1F 83)
|
||||
D8 FF XX XX YY YY,Turn character {0:X} to direction {1:X} (1F 13)
|
||||
D9 FF XX XX,Unknown (1F 14 XX)
|
||||
DA FF XX XX YY YY,Unknown (occurs after A0 FF and DC FF)
|
||||
DB FF XX XX YY YY ZZ ZZ,Store to memory the direction from TPT entry {0:X} to object {1:X} (ZZ unknown) (19 23)
|
||||
DC FF XX XX YY YY ZZ ZZ,Unknown (sandwiched between DA FF codes?)
|
||||
DD FF XX XX XX XX YY YY YY YY,Check for {0:X} inequality to memory (18 07)
|
||||
DE FF,Unknown (?)
|
||||
DF FF,Open non-working phone window (1A 0A)
|
||||
E0 FF XX XX,May relate to returning cash earned since last phone call to dad (1D 24, value matches)
|
||||
E1 FF XX XX,Unknown (19 18, value matches)
|
||||
E2 FF XX XX,Summon photographer to location {0:X} (1F D2)
|
||||
E3 FF,Unknown (19 21 00)
|
||||
E4 FF,Unknown (19 25 00)
|
||||
E5 FF,Check same user/target (1D 20)
|
||||
E6 FF XX XX,Unknown (1F EE, value matches)
|
||||
E7 FF XX XX,Show Mach Pizza window? Different arguments yield different menu strings (02 = full A menu, 03 = A menu sans PSI, and more)
|
||||
E8 FF XX XX YY YY,Character {0:X} realizes special PSI {1:X} (1F 71)
|
||||
E9 FF XX XX YY YY YY YY,Character {0:X} gains {1:X} EXP (1E 09)
|
||||
EA FF XX XX,Lock player movement (1F E5, value matches)
|
||||
EB FF XX XX,Restrict player movement if camera is focused on other sprite (XX is usually FF) (1F E8)
|
||||
EC FF,Display party select menu? (1A 01)
|
||||
ED FF XX XX YY YY,Return byte {1:X} of character {0:X} status (19 16, values match)
|
||||
EE FF XX XX YY YY ZZ ZZ,Inflict ailment {1:X} on character {0:X} (ZZ might possibly be the value to set? 0 for off, 1 for on) (YY and ZZ flipped w.r.t EB) (19 05)
|
||||
EF FF XX XX YY YY,PSI Teleport to destination {0:X} using method {1:X} (1F 20, values match)
|
||||
F0 FF XX XX YY YY,Display animation {0:X} (YY is usually 00) (1C 13)
|
||||
F1 FF,Show Escargo Express window? ([18 02][1A 07][18 03 0D][18 00][18 03 01][01])
|
||||
F2 FF XX XX XX XX,Unknown (1D 13, values match)
|
||||
F3 FF XX XX XX XX,Unknown (1D 12, values match)
|
||||
F4 FF XX XX YY YY,Unknown (1D 0C, values match)
|
||||
F5 FF,Unknown (19 14)
|
||||
F6 FF XX XX,Generate random number from 0 to {0:X} (1D 21)
|
||||
F7 FF XX XX YY YY,Character {0:X} recovers HP by {1:X} of max (1E 00)
|
||||
F8 FF XX XX YY YY,Character {0:X} recovers PP by {1:X} of max (1E 04)
|
||||
F9 FF XX XX YY YY,Character {0:X} recovers HP by {1:X} of max (not sure of the difference with F7 FF) (1E 00)
|
||||
FA FF XX XX YY YY,Character {0:X} recovers PP by {1:X} of max (not sure of the difference with F8 FF) (1E 04)
|
||||
FB FF XX XX,Attempt to fix items (1F D0)
|
||||
FC FF XX XX,Unknown; load some kind of value into memory? Observed: [FC FF 06 00] [64 FF] == [1F 41 06]
|
||||
FD FF,Set binary flag if current sector is Exit mouse-compatible (1D 22)
|
||||
FE FF,Store current coordinates into memory (1F 68)
|
||||
FF FF,Returns a numeric value based on the proximity of a magic truffle TPT entry (1F D1)
|
|
@ -0,0 +1,256 @@
|
|||
ぁ
|
||||
あ
|
||||
ぃ
|
||||
い
|
||||
ぅ
|
||||
う
|
||||
ぇ
|
||||
え
|
||||
ぉ
|
||||
お
|
||||
か
|
||||
が
|
||||
き
|
||||
ぎ
|
||||
く
|
||||
ぐ
|
||||
け
|
||||
げ
|
||||
こ
|
||||
ご
|
||||
さ
|
||||
ざ
|
||||
し
|
||||
じ
|
||||
す
|
||||
ず
|
||||
せ
|
||||
ぜ
|
||||
そ
|
||||
ぞ
|
||||
た
|
||||
だ
|
||||
ち
|
||||
ぢ
|
||||
っ
|
||||
つ
|
||||
づ
|
||||
て
|
||||
で
|
||||
と
|
||||
ど
|
||||
な
|
||||
に
|
||||
ぬ
|
||||
ね
|
||||
の
|
||||
は
|
||||
ば
|
||||
ぱ
|
||||
ひ
|
||||
び
|
||||
ぴ
|
||||
ふ
|
||||
ぶ
|
||||
ぷ
|
||||
へ
|
||||
べ
|
||||
ぺ
|
||||
ほ
|
||||
ぼ
|
||||
ぽ
|
||||
ま
|
||||
み
|
||||
む
|
||||
め
|
||||
も
|
||||
ゃ
|
||||
や
|
||||
ゅ
|
||||
ゆ
|
||||
ょ
|
||||
よ
|
||||
ら
|
||||
り
|
||||
る
|
||||
れ
|
||||
ろ
|
||||
|
||||
わ
|
||||
|
||||
|
||||
を
|
||||
ん
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
ァ
|
||||
ア
|
||||
ィ
|
||||
イ
|
||||
ゥ
|
||||
ウ
|
||||
ェ
|
||||
エ
|
||||
ォ
|
||||
オ
|
||||
カ
|
||||
ガ
|
||||
キ
|
||||
ギ
|
||||
ク
|
||||
グ
|
||||
ケ
|
||||
ゲ
|
||||
コ
|
||||
ゴ
|
||||
サ
|
||||
ザ
|
||||
シ
|
||||
ジ
|
||||
ス
|
||||
ズ
|
||||
セ
|
||||
ゼ
|
||||
ソ
|
||||
ゾ
|
||||
タ
|
||||
ダ
|
||||
チ
|
||||
ヂ
|
||||
ッ
|
||||
ツ
|
||||
ヅ
|
||||
テ
|
||||
デ
|
||||
ト
|
||||
ド
|
||||
ナ
|
||||
ニ
|
||||
ヌ
|
||||
ネ
|
||||
ノ
|
||||
ハ
|
||||
バ
|
||||
パ
|
||||
ヒ
|
||||
ビ
|
||||
ピ
|
||||
フ
|
||||
ブ
|
||||
プ
|
||||
ヘ
|
||||
ベ
|
||||
ペ
|
||||
ホ
|
||||
ボ
|
||||
ポ
|
||||
マ
|
||||
ミ
|
||||
.
|
||||
ム
|
||||
メ
|
||||
モ
|
||||
ャ
|
||||
ヤ
|
||||
ュ
|
||||
ユ
|
||||
ョ
|
||||
ヨ
|
||||
ラ
|
||||
リ
|
||||
ル
|
||||
レ
|
||||
ロ
|
||||
|
||||
ワ
|
||||
|
||||
|
||||
ヲ
|
||||
ン
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
INVALID
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
E
|
||||
F
|
||||
G
|
||||
H
|
||||
I
|
||||
J
|
||||
K
|
||||
L
|
||||
M
|
||||
N
|
||||
O
|
||||
P
|
||||
Q
|
||||
R
|
||||
S
|
||||
T
|
||||
U
|
||||
V
|
||||
W
|
||||
X
|
||||
Y
|
||||
Z
|
||||
α
|
||||
β
|
||||
γ
|
||||
Σ
|
||||
Ω
|
||||
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
#
|
||||
!
|
||||
?
|
||||
/
|
||||
:
|
||||
ー
|
||||
~
|
||||
·
|
||||
··
|
||||
。
|
||||
“
|
||||
”
|
||||
(
|
||||
)
|
||||
♪
|
||||
◯
|
||||
$
|
||||
"
|
||||
°
|
||||
◆
|
||||
(e)
|
||||
CONTROL CODE
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net451" />
|
||||
</packages>
|
Loading…
Reference in New Issue