diff --git a/src/data/cast_roll_arrangement.bin b/src/data/cast_roll_arrangement.bin
new file mode 100644
index 0000000..8a11a19
Binary files /dev/null and b/src/data/cast_roll_arrangement.bin differ
diff --git a/src/data/cast_roll_graphics.bin b/src/data/cast_roll_graphics.bin
new file mode 100644
index 0000000..0df41dd
Binary files /dev/null and b/src/data/cast_roll_graphics.bin differ
diff --git a/src/data/cast_sign_arrangements.bin b/src/data/cast_sign_arrangements.bin
new file mode 100644
index 0000000..68d86ee
Binary files /dev/null and b/src/data/cast_sign_arrangements.bin differ
diff --git a/src/data/cast_sign_graphics.bin b/src/data/cast_sign_graphics.bin
new file mode 100644
index 0000000..a7a25eb
Binary files /dev/null and b/src/data/cast_sign_graphics.bin differ
diff --git a/test.json b/test.json
new file mode 100644
index 0000000..1679dce
--- /dev/null
+++ b/test.json
@@ -0,0 +1,22 @@
+{
+ "Renders":[
+ {
+ "Y":10,
+ "Center_X":10,
+ "Text":"This is a test...",
+ "Font": 0
+ },
+ {
+ "Y":12,
+ "Center_X":10,
+ "Text":"This is a test2...",
+ "Font": 0
+ },
+ {
+ "Y":16,
+ "Center_X":30,
+ "Text":"\"",
+ "Font": 0
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tools/M12Tools.sln b/tools/M12Tools.sln
index b2e3474..62fcd10 100644
--- a/tools/M12Tools.sln
+++ b/tools/M12Tools.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.28407.52
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.168
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptTool", "ScriptTool\ScriptTool.csproj", "{29AB41A8-6405-4C4B-A374-BF1BD7AF1A27}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptToolGui", "ScriptToolGui\ScriptToolGui.csproj", "{BAE5CBBF-D0B3-4F82-A80A-957CEC379238}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderCastRoll", "RenderCastRoll\RenderCastRoll.csproj", "{DD1C607C-5A74-4921-81A4-6BF530A191D7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
{BAE5CBBF-D0B3-4F82-A80A-957CEC379238}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAE5CBBF-D0B3-4F82-A80A-957CEC379238}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAE5CBBF-D0B3-4F82-A80A-957CEC379238}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DD1C607C-5A74-4921-81A4-6BF530A191D7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/tools/RenderCastRoll/App.config b/tools/RenderCastRoll/App.config
new file mode 100644
index 0000000..731f6de
--- /dev/null
+++ b/tools/RenderCastRoll/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/RenderCastRoll/Asset.cs b/tools/RenderCastRoll/Asset.cs
new file mode 100644
index 0000000..21fba14
--- /dev/null
+++ b/tools/RenderCastRoll/Asset.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace RenderCastRoll
+{
+ public static class Asset
+ {
+ public static readonly string AssetPath;
+
+ static Asset()
+ {
+ AssetPath = AppDomain.CurrentDomain.BaseDirectory;
+ }
+
+ public static string GetFullPath(string path)
+ => Path.Combine(AssetPath, path);
+
+ public static string ReadAllText(string path)
+ => File.ReadAllText(GetFullPath(path));
+
+ public static byte[] ReadAllBytes(string path)
+ => File.ReadAllBytes(GetFullPath(path));
+
+ public static string[] ReadAllLines(string path)
+ => File.ReadAllLines(GetFullPath(path));
+
+ public static void WriteAllText(string path, string text)
+ => File.WriteAllText(GetFullPath(path), text);
+ }
+}
diff --git a/tools/RenderCastRoll/Program.cs b/tools/RenderCastRoll/Program.cs
new file mode 100644
index 0000000..a34eec9
--- /dev/null
+++ b/tools/RenderCastRoll/Program.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace RenderCastRoll
+{
+ class Program
+ {
+ static IDictionary m12CharByteLookup;
+ static byte[] BitsToNybbleLookup;
+ static readonly ushort Palette = 0xF000;
+ static RenderFont[] Fonts;
+ static byte[] Graphics;
+ static _1bppTile emptyTile = new _1bppTile();
+ static _1bppTile[] _1bppGraphics;
+ static _1bppTile[] _1bppGraphics_RotX;
+ static _1bppTile[] _1bppGraphics_RotY;
+ static _1bppTile[] _1bppGraphics_RotXY;
+ static ushort[] Arrangements;
+ static readonly ushort arrStart = 0x100;
+
+ static void Main(string[] args)
+ {
+ if (args.Length != 2)
+ return;
+
+ //Initialization
+ string rendersJson = File.ReadAllText(args[0]);
+ string dataFolder = args[1] + Path.DirectorySeparatorChar;
+ Fonts = new RenderFont[2];
+ Fonts[0] = new RenderFont(dataFolder, "main");
+ Fonts[1] = new RenderFont(dataFolder, "saturn");
+ byte[] CastGraphics = File.ReadAllBytes(dataFolder + "cast_sign_graphics.bin");
+ byte[] CastArrangements = File.ReadAllBytes(dataFolder + "cast_sign_arrangements.bin");
+ List renders = JsonConvert.DeserializeObject(rendersJson).Renders;
+ BitsToNybbleLookup = Asset.ReadAllBytes("bits_to_nybbles.bin");
+ m12CharByteLookup = JsonConvert.DeserializeObject>(Asset.ReadAllText("m12-byte-lookup.json"));
+ Graphics = new byte[0x6000];
+ Arrangements = new ushort[0x4E80];
+
+ for (int i = 0; i < Arrangements.Length; i++)
+ Arrangements[i] = 0x3FF; //Empty tile
+
+ for (int i = 0; i < CastGraphics.Length; i++)
+ Graphics[0x6000 - CastGraphics.Length + i] = CastGraphics[i]; //Put the CAST graphics in
+
+ int castArrPos = readIntLE(CastArrangements, 0); //First 4 bytes are the position of the CAST arrangements
+ for (int i = 0; i < ((CastArrangements.Length - 4) >> 1); i++) //Put the CAST arrangements in
+ {
+ Arrangements[(castArrPos / 2) + i] = readUShortLE(CastArrangements, (i * 2) + 4);
+ }
+
+ int maxTiles = 0x300 - (CastGraphics.Length / 0x20);
+ _1bppGraphics = new _1bppTile[maxTiles];
+ _1bppGraphics_RotX = new _1bppTile[maxTiles];
+ _1bppGraphics_RotY = new _1bppTile[maxTiles];
+ _1bppGraphics_RotXY = new _1bppTile[maxTiles];
+ int UsedTiles = 0;
+ WritingBuffer[] buffers = new WritingBuffer[renders.Count];
+
+ //Render the text as 1bpp
+ for (int i = 0; i < renders.Count; i++)
+ buffers[i] = renderText(renders[i]);
+
+ for (int i = 0; i < buffers.Length; i++)
+ UsedTiles = insertInGraphics(buffers[i], UsedTiles);
+
+ //Put the arrangements in
+ for (int i = 0; i < renders.Count; i++)
+ {
+ int pos = buffers[i].startPos + 1 + (renders[i].Y * 0x20); //The + 1 is here because the scene's map starts from tile 1. Not tile 0
+ for (int j = 0; j < buffers[i].used; j++)
+ {
+ Arrangements[pos + j] = buffers[i].arrangements[0, j];
+ Arrangements[pos + 0x20 + j] = buffers[i].arrangements[1, j];
+ }
+ }
+
+ //Convert the 1bpp tiles to 4bpp
+ for (int tile = 0; tile < UsedTiles; tile++)
+ {
+ int basePos = tile * 0x20;
+ _1bppTile pre_converted_tile = _1bppGraphics[tile];
+ for (int i = 0; i < 8; i++)
+ {
+ int row = BitsToNybbleLookup[pre_converted_tile.getRow(i)];
+ for (int j = 0; j < 4; j++)
+ Graphics[basePos + (i * 4) + j] = (byte)((row >> (j * 8)) & 0xFF);
+ }
+ }
+
+ File.WriteAllBytes(dataFolder + "cast_roll_graphics.bin", Graphics);
+ File.WriteAllBytes(dataFolder + "cast_roll_arrangement.bin", convertUShortArrToByteLE(Arrangements));
+ }
+
+ static int readIntLE(byte[] arr, int pos)
+ {
+ return arr[pos] + (arr[pos + 1] << 8) + (arr[pos + 2] << 16) + (arr[pos + 3] << 24);
+ }
+
+ static ushort readUShortLE(byte[] arr, int pos)
+ {
+ return (ushort)(arr[pos] + (arr[pos + 1] << 8));
+ }
+
+ static byte[] convertUShortArrToByteLE(ushort[] arr)
+ {
+ byte[] newArr = new byte[arr.Length * 2];
+ for (int i = 0; i < arr.Length; i++)
+ {
+ newArr[(i * 2)] = (byte)((arr[i]) & 0xFF);
+ newArr[(i * 2) + 1] = (byte)((arr[i] >> 8) & 0xFF);
+ }
+ return newArr;
+ }
+
+ static int insertInGraphics(WritingBuffer buf, int usedInGraphics)
+ {
+ //Optimally inserts the graphics inside the final product
+ int total = usedInGraphics;
+
+ for (int i = 0; i < buf.used; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ _1bppTile tile = buf.tiles[j, i];
+ _1bppTile rotatedXTile = null;
+ _1bppTile rotatedYTile = null;
+ _1bppTile rotatedXYTile = null;
+
+ int rot = 0;
+ int pos = -1;
+ if (emptyTile.Equals(tile))
+ pos = 0x2FF; //Empty tile
+ else
+ pos = getPosInFinal(tile, total, _1bppGraphics);
+
+ if (pos == -1)
+ {
+ rot = 1;
+ rotatedXTile = tile.rotateX();
+ pos = getPosInFinal(rotatedXTile, total, _1bppGraphics_RotX);
+
+ if (pos == -1)
+ {
+ rot = 2;
+ rotatedYTile = tile.rotateY();
+ pos = getPosInFinal(rotatedYTile, total, _1bppGraphics_RotY);
+
+ if (pos == -1)
+ {
+ rotatedXYTile = rotatedXTile.rotateY();
+ rot = 3;
+ pos = getPosInFinal(rotatedXYTile, total, _1bppGraphics_RotXY);
+ }
+ }
+ }
+
+ if (pos == -1) //Hasn't been found in any of the ways the buffer can be looked at
+ {
+ rot = 0;
+ pos = total++;
+ _1bppGraphics[pos] = tile; //If we're here, we already calculated all four of them
+ _1bppGraphics_RotX[pos] = rotatedXTile;
+ _1bppGraphics_RotY[pos] = rotatedYTile;
+ _1bppGraphics_RotXY[pos] = rotatedXYTile;
+ }
+
+ buf.arrangements[j, i] = (ushort)(Palette | (pos + arrStart) | (rot << 0xA));
+ }
+ }
+
+ return total;
+ }
+
+ static int getPosInFinal(_1bppTile tile, int total, _1bppTile[] finalProd)
+ {
+ int pos = -1;
+ for (int k = 0; k < total; k++)
+ if (finalProd[k].Equals(tile))
+ {
+ pos = k;
+ break;
+ }
+ return pos;
+ }
+
+ static WritingBuffer renderText(Render r)
+ {
+ WritingBuffer a = new WritingBuffer();
+ byte[] text = getTextBytes(r.Text);
+ int len = getTextLength(text, r.Font);
+ int x = r.Center_X - (len / 2);
+ if (x < 0)
+ x = 0;
+ a.startPos = (x >> 3);
+ int bufferPos = x & 7;
+
+ for (int i = 0; i < text.Length; i++)
+ bufferPos += _1bppRenderChar(text[i], bufferPos, r.Font, a);
+
+ a.used = (bufferPos + 7) >> 3;
+ return a;
+ }
+
+ static byte _1bppRenderChar(byte chr, int x, int font, WritingBuffer buf)
+ {
+ //Renders a character
+ int tileHeight = 2;
+ int tileWidth = 2;
+ int tileX = x >> 3;
+ int chrPos = chr * tileWidth * tileHeight * 8;
+ int offsetX = x & 7;
+ byte vWidth = Fonts[font].fontWidth[chr * 2];
+ byte rWidth = Fonts[font].fontWidth[(chr * 2) + 1];
+ for(int dTileY = 0; dTileY < tileHeight; dTileY++)
+ {
+ int dTileX = 0;
+ int renderedWidth = rWidth;
+ while (renderedWidth > 0)
+ {
+ int tileIndexX = tileX + dTileX;
+ _1bppTile leftTile = buf.tiles[dTileY, tileIndexX];
+ _1bppTile rightTile = buf.tiles[dTileY, tileIndexX + 1];
+
+ for (int row = 0; row < 8; row++)
+ {
+ ushort canvasRow = (ushort)(leftTile.getRow(row) | (rightTile.getRow(row) << 8));
+ ushort glyphRow = (ushort)(Fonts[font].font[chrPos + row + (((dTileY * tileWidth) + dTileX) * 8)] << offsetX);
+
+ canvasRow |= glyphRow;
+ leftTile.setRow(row, (byte)(canvasRow & 0xFF));
+ rightTile.setRow(row, (byte)((canvasRow >> 8) & 0xFF));
+ }
+
+ renderedWidth -= 8;
+ dTileX++;
+ }
+ }
+ return vWidth;
+ }
+
+ static byte[] getTextBytes(String str)
+ {
+ //Reads a string and converts it to bytes
+ List tokens = new List();
+ for (int i = 0; str.Length > 0; i++)
+ {
+ string token = str[0].ToString();
+ str = str.Substring(1);
+ if (token == "[")
+ while (str.Length > 0 && !token.EndsWith("]"))
+ {
+ token += str[0].ToString();
+ str = str.Substring(1);
+ }
+ if (m12CharByteLookup.ContainsKey(token))
+ tokens.Add(m12CharByteLookup[token]);
+ }
+ return tokens.ToArray();
+ }
+
+ static int getTextLength(byte[] text, int Font)
+ {
+ int len = 0;
+ for (int i = 0; i < text.Length; i++)
+ len += Fonts[Font].fontWidth[2 * text[i]];
+ return len;
+ }
+ }
+}
diff --git a/tools/RenderCastRoll/Properties/AssemblyInfo.cs b/tools/RenderCastRoll/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..662d477
--- /dev/null
+++ b/tools/RenderCastRoll/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Le informazioni generali relative a un assembly sono controllate dal seguente
+// set di attributi. Modificare i valori di questi attributi per modificare le informazioni
+// associate a un assembly.
+[assembly: AssemblyTitle("RenderCastRoll")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("HP Inc.")]
+[assembly: AssemblyProduct("RenderCastRoll")]
+[assembly: AssemblyCopyright("Copyright © HP Inc. 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili
+// ai componenti COM. Se è necessario accedere a un tipo in questo assembly da
+// COM, impostare su true l'attributo ComVisible per tale tipo.
+[assembly: ComVisible(false)]
+
+// Se il progetto viene esposto a COM, il GUID seguente verrà utilizzato come ID della libreria dei tipi
+[assembly: Guid("dd1c607c-5a74-4921-81a4-6bf530a191d7")]
+
+// Le informazioni sulla versione di un assembly sono costituite dai seguenti quattro valori:
+//
+// Versione principale
+// Versione secondaria
+// Numero di build
+// Revisione
+//
+// È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build
+// usando l'asterisco '*' come illustrato di seguito:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tools/RenderCastRoll/RenderCastRoll.csproj b/tools/RenderCastRoll/RenderCastRoll.csproj
new file mode 100644
index 0000000..9daf848
--- /dev/null
+++ b/tools/RenderCastRoll/RenderCastRoll.csproj
@@ -0,0 +1,65 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {DD1C607C-5A74-4921-81A4-6BF530A191D7}
+ Exe
+ RenderCastRoll
+ RenderCastRoll
+ v4.6.1
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/RenderCastRoll/RenderTools.cs b/tools/RenderCastRoll/RenderTools.cs
new file mode 100644
index 0000000..5be027d
--- /dev/null
+++ b/tools/RenderCastRoll/RenderTools.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RenderCastRoll
+{
+ public class Render
+ {
+ public int Y { get; set; }
+ public int Center_X { get; set; }
+ public string Text { get; set; }
+ public int Font { get; set; }
+ }
+
+ public class RenderRoot
+ {
+ public List Renders { get; set; }
+ }
+
+ public class RenderFont
+ {
+ public byte[] font;
+ public byte[] fontWidth;
+
+ public RenderFont(string folder, string fontName)
+ {
+ font = File.ReadAllBytes(folder + "m2-font-" + fontName + ".bin");
+ fontWidth = File.ReadAllBytes(folder + "m2-widths-" + fontName + ".bin");
+ }
+ }
+
+ public class _1bppTile
+ {
+ UInt64 tile;
+
+ public _1bppTile() : this(0) { }
+
+ public _1bppTile(UInt64 val)
+ {
+ tile = val;
+ }
+
+ public byte getRow(int i)
+ {
+ return (byte)((tile >> i) & 0xFF);
+ }
+
+ public void setRow(int i, byte val)
+ {
+ UInt64 mask = ~((UInt64)(0xFF) << i);
+ tile = (tile & mask) | ((UInt64)val << i);
+ }
+
+ public UInt64 getColumn(int i)
+ {
+ UInt64 mask = (UInt64)(0x0101010101010101 << i);
+ return mask & tile;
+ }
+
+ public void setColumn(int i, UInt64 val)
+ {
+ UInt64 mask = ~(UInt64)(0x0101010101010101 << i);
+ tile = (tile & mask) | val;
+ }
+
+ public bool Equals(_1bppTile t)
+ {
+ return this.tile == t.tile;
+ }
+
+ public _1bppTile rotateX()
+ {
+ _1bppTile newTile = new _1bppTile(tile);
+ for (int row = 0; row < 8; row++)
+ {
+ byte val = newTile.getRow(row);
+ byte newVal = 0;
+ for (int i = 0; i < 8; i++)
+ newVal |= (byte)(((val >> i) & 1) << (7 - i));
+ newTile.setRow(row, newVal);
+ }
+ return newTile;
+ }
+
+ public _1bppTile rotateY()
+ {
+ _1bppTile newTile = new _1bppTile(tile);
+ for (int column = 0; column < 8; column++)
+ {
+ UInt64 val = newTile.getColumn(column);
+ UInt64 newVal = 0;
+ for (int i = 0; i < 8; i++)
+ newVal |= ((val >> (i * 8)) & 0xFF) << ((7 - i) * 8);
+ newTile.setColumn(column, newVal);
+ }
+ return newTile;
+ }
+ }
+
+ public class WritingBuffer
+ {
+ public _1bppTile[,] tiles;
+ public ushort[,] arrangements;
+ public int used;
+ public int startPos;
+
+ public WritingBuffer()
+ {
+ used = 0;
+ startPos = 0;
+ tiles = new _1bppTile[2, 0x20];
+ arrangements = new ushort[2, 0x20];
+ for (int i = 0; i < 2; i++)
+ for (int j = 0; j < 0x20; j++)
+ {
+ tiles[i, j] = new _1bppTile();
+ arrangements[i, j] = 0x3FF; //Empty tile
+ }
+ }
+ }
+}
diff --git a/tools/RenderCastRoll/bits_to_nybbles.bin b/tools/RenderCastRoll/bits_to_nybbles.bin
new file mode 100644
index 0000000..3508803
Binary files /dev/null and b/tools/RenderCastRoll/bits_to_nybbles.bin differ
diff --git a/tools/RenderCastRoll/m12-byte-lookup.json b/tools/RenderCastRoll/m12-byte-lookup.json
new file mode 100644
index 0000000..bc39cdc
--- /dev/null
+++ b/tools/RenderCastRoll/m12-byte-lookup.json
@@ -0,0 +1,98 @@
+{
+ " ": 0,
+ "!": 1,
+ "\"": 2,
+ "#": 3,
+ "$": 4,
+ "%": 5,
+ "&": 6,
+ "'": 7,
+ "(": 8,
+ ")": 9,
+ "*": 10,
+ "+": 11,
+ ",": 12,
+ "-": 13,
+ ".": 14,
+ "/": 15,
+ "0": 16,
+ "1": 17,
+ "2": 18,
+ "3": 19,
+ "4": 20,
+ "5": 21,
+ "6": 22,
+ "7": 23,
+ "8": 24,
+ "9": 25,
+ ":": 26,
+ ";": 27,
+ "<": 28,
+ "=": 29,
+ ">": 30,
+ "?": 31,
+ "@": 32,
+ "A": 33,
+ "B": 34,
+ "C": 35,
+ "D": 36,
+ "E": 37,
+ "F": 38,
+ "G": 39,
+ "H": 40,
+ "I": 41,
+ "J": 42,
+ "K": 43,
+ "L": 44,
+ "M": 45,
+ "N": 46,
+ "O": 47,
+ "P": 47,
+ "Q": 49,
+ "R": 50,
+ "S": 51,
+ "T": 52,
+ "U": 53,
+ "V": 54,
+ "W": 55,
+ "X": 56,
+ "Y": 57,
+ "Z": 58,
+ "[8B]": 59,
+ "[8C]": 60,
+ "[8D]": 61,
+ "[8E]": 62,
+ "[8F]": 63,
+ "`": 64,
+ "a": 65,
+ "b": 66,
+ "c": 67,
+ "d": 68,
+ "e": 69,
+ "f": 70,
+ "g": 71,
+ "h": 72,
+ "i": 73,
+ "j": 74,
+ "k": 75,
+ "l": 76,
+ "m": 77,
+ "n": 78,
+ "o": 79,
+ "p": 80,
+ "q": 81,
+ "r": 82,
+ "s": 83,
+ "t": 84,
+ "u": 85,
+ "v": 86,
+ "w": 87,
+ "x": 88,
+ "y": 89,
+ "z": 90,
+ "{": 91,
+ "|": 92,
+ "}": 93,
+ "~": 94,
+ "[AF]": 95
+}
\ No newline at end of file
diff --git a/tools/RenderCastRoll/packages.config b/tools/RenderCastRoll/packages.config
new file mode 100644
index 0000000..8ab13a9
--- /dev/null
+++ b/tools/RenderCastRoll/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file