Commit 2bb25589 authored by Spencer Alves's avatar Spencer Alves

Support for unlisted strings in code

Not that I'd recommend it as it results in a different order, you can repack without a strings.json now.
parent 3fe0746f
......@@ -5,13 +5,14 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using static Altar.Repack.Deserialize;
namespace Altar.Recomp
{
public static class Assembler
{
public static CodeInfo DeserializeCodeFromFile(string filename, uint bcv,
IDictionary<string, uint> stringIndices, IDictionary<string, uint> objectIndices)
StringsListBuilder strings, IDictionary<string, uint> objectIndices)
{
IEnumerable<Instruction> instructions;
if (filename.ToLowerInvariant().EndsWith(SR.EXT_GML_ASM))
......@@ -28,7 +29,7 @@ namespace Altar.Recomp
throw new InvalidDataException("Unknown code format for '" + filename + "'");
}
return DeserializeAssembly(Path.GetFileNameWithoutExtension(filename), instructions, bcv,
stringIndices, objectIndices);
strings, objectIndices);
}
private static InstanceType GetInstanceType(InstanceType instanceType, string objName, IDictionary<string, uint> objectIndices)
......@@ -182,7 +183,7 @@ namespace Altar.Recomp
}
private static CodeInfo DeserializeAssembly(string name, IEnumerable<Instruction> instructions, uint bcv,
IDictionary<string, uint> stringIndices, IDictionary<string, uint> objectIndices)
StringsListBuilder strings, IDictionary<string, uint> objectIndices)
{
uint size = 0;
var labels = new Dictionary<string, uint>();
......@@ -275,7 +276,7 @@ namespace Altar.Recomp
bp.ValueRest = BitConverter.ToUInt64(BitConverter.GetBytes(unchecked((long)(p.Value))), 0);
break;
case DataType.String:
bp.ValueRest = stringIndices[(string)p.Value];
bp.ValueRest = strings.GetIndex((string)p.Value);
break;
}
}
......
......@@ -407,6 +407,51 @@ namespace Altar.Repack
private static JsonData LoadJson(string baseDir, string filename) => JsonMapper.ToObject(File.OpenText(Path.Combine(baseDir, filename)));
public class StringsListBuilder
{
IDictionary<string, int> stringIndices;
IList<string> stringList;
public StringsListBuilder()
{
stringIndices = new Dictionary<string, int>();
stringList = new List<string>();
}
public virtual int AddString(String s)
{
stringIndices[s] = stringList.Count;
stringList.Add(s);
return 0;
}
public void AddStrings(String[] strings)
{
foreach (var s in strings)
{
AddString(s);
}
}
public uint GetIndex(String s)
{
if (stringIndices.TryGetValue(s, out int idx))
{
return (uint)idx;
}
else
{
AddString(s);
return (uint)(stringList.Count - 1);
}
}
public string[] GetStrings()
{
return stringList.ToArray();
}
}
public static GMFile /* errors: different return type? */ ReadFile(string baseDir, JsonData projFile)
{
var f = new GMFile();
......@@ -665,8 +710,8 @@ namespace Altar.Repack
var code = projFile["code"].ToArray();
f.Code = new CodeInfo[code.Length];
IDictionary<string, uint> stringIndices = new Dictionary<string, uint>(f.Strings.Length);
for (uint i = 0; i < f.Strings.Length; i++) stringIndices[f.Strings[i]] = i;
var strings = new StringsListBuilder();
strings.AddStrings(f.Strings);
IDictionary<string, uint> objectIndices = new Dictionary<string, uint>(f.Objects.Length);
for (uint i = 0; i < f.Objects.Length; i++) objectIndices[f.Objects[i].Name] = i;
......@@ -676,7 +721,7 @@ namespace Altar.Repack
try
{
f.Code[i] = Assembler.DeserializeCodeFromFile(Path.Combine(baseDir, (string)(code[i])), f.General.BytecodeVersion,
stringIndices, objectIndices);
strings, objectIndices);
f.Code[i].Name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension((string)(code[i])));
f.Code[i].ArgumentCount = 1;
if (f.FunctionLocals != null)
......@@ -698,6 +743,8 @@ namespace Altar.Repack
Console.Error.WriteLine(e);
}
}
f.Strings = strings.GetStrings();
}
if (projFile.Has("sounds"))
{
......
......@@ -69,19 +69,17 @@ namespace Altar.Repack
}
}
public class StringsChunkBuilder
public class StringsChunkBuilder : Deserialize.StringsListBuilder
{
BBData stringsData;
IDictionary<string, int> stringOffsets;
IList<int> offsetList;
IDictionary<string, int> stringIndices;
public StringsChunkBuilder()
{
stringsData = new BBData(new BinBuffer(), new int[0]);
stringOffsets = new Dictionary<string, int>();
offsetList = new List<int>();
stringIndices = new Dictionary<string, int>();
}
private void WriteString(BBData data, String s)
......@@ -90,24 +88,16 @@ namespace Altar.Repack
data.Buffer.WriteByte(0);
}
public int AddString(String s)
public override int AddString(String s)
{
base.AddString(s);
int offset = stringsData.Buffer.Position;
WriteString(stringsData, s);
stringOffsets[s] = offset;
stringIndices[s] = offsetList.Count;
offsetList.Add(offset);
return offset;
}
public void AddStrings(String[] strings)
{
foreach (var s in strings)
{
AddString(s);
}
}
public uint GetOffset(String s)
{
if (stringOffsets.TryGetValue(s, out int offset))
......@@ -120,19 +110,6 @@ namespace Altar.Repack
}
}
public uint GetIndex(String s)
{
if (stringIndices.TryGetValue(s, out int idx))
{
return (uint)idx;
}
else
{
AddString(s);
return (uint)(offsetList.Count - 1);
}
}
public int[] WriteStringsChunk(BBData data)
{
var bb = data.Buffer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment