Compare commits

...

11 commits
dev ... master

19 changed files with 781 additions and 58 deletions

3
.gitignore vendored
View file

@ -12,3 +12,6 @@ bin/
# generated types # generated types
generated/ generated/
# build
Makefile

BIN
lib/arookas.dll Normal file

Binary file not shown.

BIN
lib/arookas.pdb Normal file

Binary file not shown.

View file

@ -19,6 +19,20 @@ if not _OPTIONS["lib-dir"] then
_OPTIONS["lib-dir"] = "lib" _OPTIONS["lib-dir"] = "lib"
end end
-- clean
newaction {
trigger = "clean",
description = "clean the software",
execute = function ()
print("Clean the build...")
os.rmdir("./bin")
os.rmdir("./ssc/obj")
os.rmdir("./frontend/obj")
os.rmdir("./sbdump/obj")
print("Done.")
end
}
-- main workspace -- main workspace
workspace "ssc" workspace "ssc"
configurations { "Debug", "Release" } configurations { "Debug", "Release" }
@ -29,7 +43,7 @@ workspace "ssc"
filter "configurations:Debug" filter "configurations:Debug"
defines { "DEBUG" } defines { "DEBUG" }
flags { "Symbols" } flags { symbols "On" }
filter "configurations:Release" filter "configurations:Release"
defines { "RELEASE" } defines { "RELEASE" }
@ -42,7 +56,7 @@ workspace "ssc"
namespace "arookas" namespace "arookas"
location "ssc" location "ssc"
links { "System", "arookas", "grammatica-1.6" } links { "System.dll", "System.Core.dll", "arookas.dll", "grammatica-1.6.dll" }
-- apply options -- apply options
if _OPTIONS["clean-functions"] then if _OPTIONS["clean-functions"] then
@ -77,7 +91,8 @@ workspace "ssc"
namespace "arookas" namespace "arookas"
location "frontend" location "frontend"
links { "System", "arookas", "SSC" } libdirs { "$(TARGETDIR)" }
links { "System.dll", "System.Core.dll", "arookas.dll", "ssc.dll" }
files { files {
"frontend/**.cs", "frontend/**.cs",
@ -90,8 +105,14 @@ workspace "ssc"
postbuildcommands { postbuildcommands {
-- copy stdlib to frontend output so users can import the scripts -- copy stdlib to frontend output so users can import the scripts
'{RMDIR} "%{cfg.buildtarget.directory}ssc"', '{MKDIR} "%{cfg.buildtarget.directory}/ssc"',
'{COPY} "%{wks.location}stdlib" "%{cfg.buildtarget.directory}ssc"', '{RMDIR} "%{cfg.buildtarget.directory}/ssc"',
'{MKDIR} "%{cfg.buildtarget.directory}/ssc-sup39"',
'{RMDIR} "%{cfg.buildtarget.directory}/ssc-sup39"',
'{COPY} "%{wks.location}/stdlib" "%{cfg.buildtarget.directory}/ssc"',
'{COPY} "%{wks.location}/stdlib-sup39" "%{cfg.buildtarget.directory}/ssc-sup39"',
'{COPY} "%{wks.location}/lib/*.dll" "%{cfg.buildtarget.directory}/"',
'{COPY} "%{wks.location}/utils/*" "%{cfg.buildtarget.directory}/"',
} }
-- sbdump utility -- sbdump utility
@ -102,7 +123,7 @@ workspace "ssc"
namespace "arookas" namespace "arookas"
location "sbdump" location "sbdump"
links { "System", "arookas" } links { "System.dll", "System.Core.dll", "arookas.dll" }
files { files {
"sbdump/**.cs", "sbdump/**.cs",

172
sbdump/CodeGraph.cs Normal file
View file

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arookas
{
class CodeGraph
{
public List<CodeVertex> Graph;
public CodeGraph()
{
Graph = new List<CodeVertex>();
}
public void AddVertex(CodeVertex NewVertex)//Adds a vertex
{
Graph.Add(NewVertex);
}
private int IndexFromAddr(long Address)
{
for (int i = 0; i < Graph.Count; i++)
{
if (Graph[i].Addr < Address)
{
continue;
}
return i;
}
return -1;//-1 indicates end of the code
}
public string OutputCode(int IndentL)
{
for (int i = 0; i < Graph.Count; i++)
{
if(Graph[i].Type == VertexType.Branch)
{
int BranchIndex = IndexFromAddr(Graph[i].BranchTo);
if(BranchIndex == -1)
{
Graph[i].Code = "break " + Graph[i].BranchTo.ToString() + ";";//Branch to label
long EndAddr = Graph[Graph.Count - 1].Addr;
CodeVertex Label = new CodeVertex(VertexType.Label, -1, Graph[i].BranchTo.ToString() + ":", EndAddr+1);
Graph.Add(Label);
}
else
{
VertexType DestType = Graph[BranchIndex].Type;
if (DestType == VertexType.CodeBlock || DestType == VertexType.Branch)
{
Graph[i].Code = "break " + Graph[i].BranchTo.ToString() + ";";//Branch to label
CodeVertex NewLine = new CodeVertex(VertexType.Label, -1, Graph[i].BranchTo.ToString() + ":",Graph[i].BranchTo);
Graph.Insert(BranchIndex, NewLine);
if(BranchIndex <= i)
{
i++;
}
}
else if(DestType == VertexType.Label)
{
string LabelName = Graph[BranchIndex].Code.Replace(':',' ');
Graph[i].Code = "break " + LabelName + ";";//Branch to label
}
else if(DestType == VertexType.ConditionalBranch)
{
//While Loop Detected
Graph[BranchIndex].Code = "while(" + Graph[BranchIndex].Code + ")" + Environment.NewLine + "{";//Put while loop
int ClosingIndex = IndexFromAddr(Graph[BranchIndex].BranchTo);
if (ClosingIndex == -1)
{
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[BranchIndex].BranchTo);
Graph.Add(NewLine);
}
else
{
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[BranchIndex].BranchTo);
Graph.Insert(ClosingIndex, NewLine);
if (ClosingIndex <= i)
{
i++;
}
}
}
}
}
}
for (int i = 0; i < Graph.Count; i++)
{
if (Graph[i].Type == VertexType.ConditionalBranch && !Graph[i].Code.StartsWith("while"))
{
if (Graph[i].Addr < Graph[i].BranchTo)
{
//If Statement Detected
Graph[i].Code = "if(" + Graph[i].Code + ")" + Environment.NewLine + "{";//Put if
int ClosingIndex = IndexFromAddr(Graph[i].BranchTo);
if (ClosingIndex == -1)
{
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[i].BranchTo);
Graph.Add(NewLine);
}
else
{
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "}", Graph[i].BranchTo);
Graph.Insert(ClosingIndex, NewLine);
if (ClosingIndex <= i)
{
i++;
}
}
}
else
{
//Do loop detected
Graph[i].Code = "} while(" + Graph[i].Code + ")";//Put do loop
int ClosingIndex = IndexFromAddr(Graph[i].BranchTo);
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "do" + Environment.NewLine + "{", Graph[i].BranchTo);
Graph.Insert(ClosingIndex, NewLine);
if (ClosingIndex <= i)
{
i++;
}
}
}
}
string DecompiledCode = "";
for (int i = 0; i < Graph.Count; i++)
{
DecompiledCode = DecompiledCode + Environment.NewLine + Graph[i].Code;
}
string[] lines = DecompiledCode.Split(new[] { Environment.NewLine },StringSplitOptions.None);
DecompiledCode = "";
int IndentLevel = IndentL;
for (int i = 0; i < lines.Length; i++)
{
if (lines[i] == "")
continue;
string IndentedString = new String(' ', IndentLevel * 4) + lines[i];
if (lines[i].Contains("{"))
{
IndentLevel++;
}
else if (lines[i].Contains("}"))
{
IndentLevel = System.Math.Max(0, IndentLevel - 1);
IndentedString = new String(' ', IndentLevel * 4) + lines[i];
}
if(DecompiledCode == "")
{
DecompiledCode = IndentedString;
}
else
{
DecompiledCode = DecompiledCode + Environment.NewLine + IndentedString;
}
}
return DecompiledCode;
}
}
}

24
sbdump/CodeVertex.cs Normal file
View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arookas
{
class CodeVertex
{
public VertexType Type;
public long BranchTo = -1;
public string Code;
public long Addr;
public CodeVertex(VertexType Typ, long BrTo,string Cde,long Adr)
{
Type = Typ;
BranchTo = BrTo;
Code = Cde;
Addr = Adr;
}
}
}

16
sbdump/Enums.cs Normal file
View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arookas
{
enum VertexType
{
CodeBlock = 0,
Branch = 1,
ConditionalBranch = 2,
Label = 3,
}
}

View file

@ -3,6 +3,7 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Collections.Generic;
namespace arookas { namespace arookas {
class sbdump { class sbdump {
@ -22,38 +23,52 @@ namespace arookas {
"ret", "ret0", "jne", "jmp", "pop", "int0", "int1", "end", "ret", "ret0", "jne", "jmp", "pop", "int0", "int1", "end",
}; };
static int Main(string[] args) { static int Main(string[] args) {
#if !DEBUG #if !DEBUG
try { try {
#endif #endif
Console.WriteLine(cTitle); Console.WriteLine(cTitle);
ReadCommandLine(args); ReadCommandLine(args);
Console.WriteLine("Opening input file..."); Console.WriteLine("Opening input file...");
using (var sb = File.OpenRead(sSettings.Input)) { using (var sb = File.OpenRead(sSettings.Input))
CreateReader(sb); {
Console.WriteLine("Creating output file..."); CreateReader(sb);
using (sWriter = File.CreateText(sSettings.Output)) { Console.WriteLine("Creating output file...");
ReadHeader(); using (sWriter = File.CreateText(sSettings.Output))
WritePreamble(); {
if (sSettings.OutputHeader) { ReadHeader();
WriteHeader(); if (sSettings.OutputSun)
} {
if (sSettings.OutputText) { WriteSun();
WriteText(); }
} else
if (sSettings.OutputData) { {
WriteData(); WritePreamble();
} if (sSettings.OutputHeader)
if (sSettings.OutputSym) { {
WriteSym(); WriteHeader();
} }
if (sSettings.OutputVars) { if (sSettings.OutputText)
WriteVars(); {
} WriteText();
Console.WriteLine("Closing output file..."); }
} if (sSettings.OutputData)
Console.WriteLine("Closing input file..."); {
} WriteData();
}
if (sSettings.OutputSym)
{
WriteSym();
}
if (sSettings.OutputVars)
{
WriteVars();
}
}
Console.WriteLine("Closing output file...");
}
Console.WriteLine("Closing input file...");
}
Console.WriteLine("Done."); Console.WriteLine("Done.");
#if !DEBUG #if !DEBUG
} }
@ -65,7 +80,8 @@ namespace arookas {
return 0; return 0;
} }
static void ReadCommandLine(string[] args) { static void ReadCommandLine(string[] args)
{
Console.WriteLine("Reading command line..."); Console.WriteLine("Reading command line...");
sSettings = new CommandLineSettings(new aCommandLine(args)); sSettings = new CommandLineSettings(new aCommandLine(args));
} }
@ -92,7 +108,8 @@ namespace arookas {
sSymCount = sReader.ReadS32(); sSymCount = sReader.ReadS32();
sVarCount = sReader.ReadS32(); sVarCount = sReader.ReadS32();
} }
static void WriteHeader() { static void WriteHeader()
{
Console.WriteLine("Outputting header..."); Console.WriteLine("Outputting header...");
sWriter.WriteLine("# Header information"); sWriter.WriteLine("# Header information");
sWriter.WriteLine("# .text offset : {0:X8}", sTextOffset); sWriter.WriteLine("# .text offset : {0:X8}", sTextOffset);
@ -103,15 +120,19 @@ namespace arookas {
sWriter.WriteLine("# var count : {0}", sVarCount); sWriter.WriteLine("# var count : {0}", sVarCount);
sWriter.WriteLine(); sWriter.WriteLine();
} }
static void WriteText() { static void WriteText()
{
Console.WriteLine("Outputting .text..."); Console.WriteLine("Outputting .text...");
sWriter.WriteLine(".text"); sWriter.WriteLine(".text");
WriteText(0u); WriteText(0u);
var symbols = new Symbol[sSymCount]; var symbols = new Symbol[sSymCount];
for (var i = 0; i < sSymCount; ++i) { for (var i = 0; i < sSymCount; ++i)
{
symbols[i] = FetchSymbol(i); symbols[i] = FetchSymbol(i);
} }
foreach (var symbol in symbols.Where(i => i.Type == SymbolType.Function).OrderBy(i => i.Data)) {
foreach (var symbol in symbols.Where(i => i.Type == SymbolType.Function).OrderBy(i => i.Data))
{
sWriter.WriteLine("{0}: ", FetchSymbolName(symbol)); sWriter.WriteLine("{0}: ", FetchSymbolName(symbol));
WriteText(symbol.Data); WriteText(symbol.Data);
} }
@ -132,13 +153,13 @@ namespace arookas {
case 0x02: { case 0x02: {
var data = sReader.ReadS32(); var data = sReader.ReadS32();
var value = FetchDataValue(data); var value = FetchDataValue(data);
sWriter.Write(" {0} # \"{1}\"", data, value); sWriter.Write(" {0} # \"{1}\"", data, value.Replace("\n", "\\n"));
break; break;
} }
case 0x03: sWriter.Write(" ${0:X8}", sReader.Read32()); break; case 0x03: sWriter.Write(" ${0:X8}", sReader.Read32()); break;
case 0x04: WriteVar(); break; case 0x04: WriteVar(); break;
case 0x06: WriteVar(); break; case 0x06: break;
case 0x07: WriteVar(); break; case 0x07: break;
case 0x0D: { case 0x0D: {
sReader.Read8(); // TSpcInterp skips this byte sReader.Read8(); // TSpcInterp skips this byte
WriteVar(); WriteVar();
@ -198,7 +219,7 @@ namespace arookas {
for (var i = 0; i < sDataCount; ++i) { for (var i = 0; i < sDataCount; ++i) {
var ofs = sReader.Read32(); var ofs = sReader.Read32();
var data = FetchDataValue(ofs); var data = FetchDataValue(ofs);
sWriter.WriteLine(" .string \"{0}\"", data); sWriter.WriteLine(" .string \"{0}\"", data.Replace("\n", "\\n"));
} }
sWriter.WriteLine(); sWriter.WriteLine();
} }
@ -228,7 +249,380 @@ namespace arookas {
sWriter.WriteLine(); sWriter.WriteLine();
} }
static uint FetchData(int i) { static void WriteSun()
{
Console.WriteLine("Decompiling sb file...");
var symbols = new Symbol[sSymCount];
for (var i = 0; i < sSymCount; ++i)
{
symbols[i] = FetchSymbol(i);
}
foreach (var symbol in symbols.Where(i => i.Type == SymbolType.Function).OrderBy(i => i.Data))
{
sWriter.WriteLine();
sWriter.WriteLine("function "+ FetchSymbolName(symbol)+ "(...)" + Environment.NewLine+ "{");
DecompFunction(symbol.Data, 1);
sWriter.WriteLine("}");
sWriter.WriteLine();
}
DecompFunction(0u, 0);//Decompile main part.
}
static void DecompFunction(uint ofs, int IndentL)
{
byte command;
sReader.Keep();
sReader.Goto(sTextOffset + ofs);
var maxofs = 0u;
Stack<string> Stack = new Stack<string>();
CodeGraph FuncCodeGraph = new CodeGraph();
HashSet<string> DeclaredTable = new HashSet<string>();
do
{
var pos = sReader.Position - sTextOffset;
command = sReader.Read8();
var nextofs = 0u;
switch (command)
{
case 0x00: //int
{
Stack.Push(sReader.ReadS32().ToString());
break;
}
case 0x01: //flt
{
Stack.Push(sReader.ReadF32().ToString("0.0###############"));
break;
}
case 0x02: //str
{
var data = sReader.ReadS32();
var value = FetchDataValue(data);
Stack.Push("\"" + value.Replace("\n", "\\n") +"\"");
break;
}
case 0x03: //adr
{
Stack.Push("$" + sReader.ReadS32().ToString("X8"));
break;
}
case 0x04: //var
{
var display = sReader.ReadS32();
var data = sReader.ReadS32();
switch (display)
{
case 0: Stack.Push(FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data))); break;
case 1: Stack.Push("local " + data.ToString()); break;
}
break;
}
case 0x06: //inc
{
sReader.ReadS8(); // Ignore inline var
var display = sReader.ReadS32();
var data = sReader.ReadS32();
switch (display)
{
case 0: Stack.Push("++" + FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data))); break;
case 1: Stack.Push("++" + data.ToString()); break;
}
break;
}
case 0x07: //dec
{
sReader.ReadS8(); // Ignore inline var
var display = sReader.ReadS32();
var data = sReader.ReadS32();
switch (display)
{
case 0: Stack.Push("--" + FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data))); break;
case 1: Stack.Push("--" + data.ToString()); break;
}
break;
}
case 0x08: //add
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " + " + Op2 + ")");
break;
}
case 0x09: //sub
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " - " + Op2 + ")");
break;
}
case 0x0A: //mul
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " * " + Op2 + ")");
break;
}
case 0x0B: //div
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " / " + Op2 + ")");
break;
}
case 0x0C: //mod
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " % " + Op2 + ")");
break;
}
case 0x0D: //ass
{
sReader.Read8(); //Ignore this byte
var display = sReader.ReadS32();
var data = sReader.ReadS32();
string VariableName = "";
switch (display)
{
case 0:
{
VariableName = FetchSymbolName(FetchSymbol(i => i.Type == SymbolType.Variable && i.Data == data));
if (!DeclaredTable.Contains(VariableName))
{
DeclaredTable.Add(VariableName);
VariableName = "var " + VariableName;
}
break;
}
case 1:
{
VariableName = data.ToString();
if (!DeclaredTable.Contains(VariableName))
{
DeclaredTable.Add(VariableName);
VariableName = "var local " + VariableName;
}
break;
}
}
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock , -1, VariableName + " = " + Stack.Pop() + ";", pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x0E: //eq
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " == " + Op2 + ")");
break;
}
case 0x0F: //ne
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " != " + Op2 + ")");
break;
}
case 0x10: //gt
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " > " + Op2 + ")");
break;
}
case 0x11: //lt
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " < " + Op2 + ")");
break;
}
case 0x12: //ge
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " >= " + Op2 + ")");
break;
}
case 0x13: //le
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " <= " + Op2 + ")");
break;
}
case 0x14: //neg
{
string Op1 = Stack.Pop();
Stack.Push("-(" + Op1 + ")");
break;
}
case 0x15: //not
{
string Op1 = Stack.Pop();
Stack.Push("!(" + Op1 + ")");
break;
}
case 0x16: //and
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " && " + Op2 + ")");
break;
}
case 0x17: //or
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " || " + Op2 + ")");
break;
}
case 0x18: //band
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " & " + Op2 + ")");
break;
}
case 0x19: //bor
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " ^ " + Op2 + ")");
break;
}
case 0x1A: //shl
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " << " + Op2 + ")");
break;
}
case 0x1B: //shr
{
string Op2 = Stack.Pop();
string Op1 = Stack.Pop();
Stack.Push("(" + Op1 + " >> " + Op2 + ")");
break;
}
case 0x1C: //call
{
var dest = sReader.Read32();
var args = sReader.ReadS32();
var symbol = FetchSymbol(i => i.Data == dest);
string FuncName = "";
if (symbol != null)
{
FuncName = FetchSymbolName(symbol);
}
else
{
FuncName = dest.ToString("X8");
}
string FuncInput = "";
for(int i = 0; i < args; i++)
{
string Op = Stack.Pop();
if (i != 0)
FuncInput = Op + "," + FuncInput;
else
FuncInput = Op;
}
Stack.Push(FuncName + "(" + FuncInput + ")");
break;
}
case 0x1D: //func
{
string FuncName = FetchSymbolName(FetchSymbol(sReader.ReadS32()));
var args = sReader.ReadS32();
string FuncInput = "";
for (int i = 0; i < args; i++)
{
string Op = Stack.Pop();
if (i != 0)
FuncInput = Op + "," + FuncInput;
else
FuncInput = Op;
}
Stack.Push(FuncName + "(" + FuncInput + ")");
break;
}
case 0x1E: sReader.ReadS32(); break;
case 0x1F: sReader.ReadS32(); break;
case 0x20: //ret
{
string Op = Stack.Pop();
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock , -1, "return " + Op + ";", pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x21: //ret0
{
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, "return 0;", pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x22: //jne
{
var dest = sReader.Read32();
nextofs = dest;
string Op = Stack.Pop();
CodeVertex NewLine = new CodeVertex(VertexType.ConditionalBranch, dest, Op, pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x23: //jmp
{
var dest = sReader.Read32();
nextofs = dest;
CodeVertex NewLine = new CodeVertex(VertexType.Branch, dest, "", pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x24: //pop
{
string Op = Stack.Pop();
CodeVertex NewLine = new CodeVertex(VertexType.CodeBlock, -1, Op + ";", pos);
FuncCodeGraph.AddVertex(NewLine);
break;
}
case 0x25: //int0
{
Stack.Push("0");
break;
}
case 0x26: //int1
{
Stack.Push("1");
break;
}
}
if (nextofs > maxofs)
{
maxofs = nextofs;
}
} while (!IsReturnCommand(command) || sReader.Position <= sTextOffset + maxofs);
WriteCode(FuncCodeGraph, IndentL);
sWriter.WriteLine();
sReader.Back();
}
static void WriteCode(CodeGraph FuncCodeGraph, int Indent)
{
sWriter.Write(FuncCodeGraph.OutputCode(Indent));
}
static uint FetchData(int i) {
sReader.Keep(); sReader.Keep();
sReader.Goto(sDataOffset + (4 * i)); sReader.Goto(sDataOffset + (4 * i));
var data = sReader.Read32(); var data = sReader.Read32();

View file

@ -2,9 +2,10 @@
using System.IO; using System.IO;
namespace arookas { namespace arookas {
class CommandLineSettings { class CommandLineSettings
{
string mInput, mOutput; string mInput, mOutput;
bool mOutputHeader, mOutputText, mOutputData, mOutputSym, mOutputVars; bool mOutputHeader, mOutputText, mOutputData, mOutputSym, mOutputVars, mDecomp;
public string Input { get { return mInput; } } public string Input { get { return mInput; } }
public string Output { get { return mOutput; } } public string Output { get { return mOutput; } }
@ -13,11 +14,13 @@ namespace arookas {
public bool OutputData { get { return mOutputData; } } public bool OutputData { get { return mOutputData; } }
public bool OutputSym { get { return mOutputSym; } } public bool OutputSym { get { return mOutputSym; } }
public bool OutputVars { get { return mOutputVars; } } public bool OutputVars { get { return mOutputVars; } }
public bool OutputSun { get { return mDecomp; } }
public CommandLineSettings(aCommandLine cmd) { public CommandLineSettings(aCommandLine cmd) {
if (cmd == null) { if (cmd == null) {
throw new ArgumentNullException("cmd"); throw new ArgumentNullException("cmd");
} }
mDecomp = false;
foreach (var param in cmd) { foreach (var param in cmd) {
switch (param.Name) { switch (param.Name) {
case "-in": mInput = param[0]; continue; case "-in": mInput = param[0]; continue;
@ -32,6 +35,7 @@ namespace arookas {
case "-s": mOutputSym = false; continue; case "-s": mOutputSym = false; continue;
case "-V": mOutputVars = true; continue; case "-V": mOutputVars = true; continue;
case "-v": mOutputVars = false; continue; case "-v": mOutputVars = false; continue;
case "-sun": mDecomp = true; continue;
} }
} }
if (mInput == null) { if (mInput == null) {
@ -41,5 +45,5 @@ namespace arookas {
mOutput = Path.ChangeExtension(mInput, ".txt"); mOutput = Path.ChangeExtension(mInput, ".txt");
} }
} }
} }
} }

View file

@ -189,7 +189,7 @@ namespace arookas {
public override void Compile(sunCompiler compiler, sunStorableSymbol symbol) { public override void Compile(sunCompiler compiler, sunStorableSymbol symbol) {
symbol.CompileInc(compiler); symbol.CompileInc(compiler);
symbol.CompileSet(compiler); symbol.CompilePop(compiler);
} }
} }
@ -199,7 +199,7 @@ namespace arookas {
public override void Compile(sunCompiler compiler, sunStorableSymbol symbol) { public override void Compile(sunCompiler compiler, sunStorableSymbol symbol) {
symbol.CompileDec(compiler); symbol.CompileDec(compiler);
symbol.CompileSet(compiler); symbol.CompilePop(compiler);
} }
} }
} }

View file

@ -184,16 +184,14 @@ namespace arookas {
TraceInstruction("inc {0} {1}", display, index); TraceInstruction("inc {0} {1}", display, index);
#endif #endif
mText.Writer.Write8(0x06); mText.Writer.Write8(0x06);
mText.Writer.WriteS32(display); WriteVAR(display, index);
mText.Writer.WriteS32(index);
} }
public override void WriteDEC(int display, int index) { public override void WriteDEC(int display, int index) {
#if DEBUG #if DEBUG
TraceInstruction("dec {0} {1}", display, index); TraceInstruction("dec {0} {1}", display, index);
#endif #endif
mText.Writer.Write8(0x07); mText.Writer.Write8(0x07);
mText.Writer.WriteS32(display); WriteVAR(display, index);
mText.Writer.WriteS32(index);
} }
public override void WriteADD() { public override void WriteADD() {
#if DEBUG #if DEBUG

View file

@ -21,7 +21,6 @@ namespace arookas {
public sunCallableSymbol Unlock { get; private set; } public sunCallableSymbol Unlock { get; private set; }
// system variables // system variables
public sunStorableSymbol Switch { get; private set; }
public sunContext() { public sunContext() {
DataTable = new sunDataTable(); DataTable = new sunDataTable();
@ -196,9 +195,6 @@ namespace arookas {
Exit = AddSystemBuiltin("exit"); Exit = AddSystemBuiltin("exit");
Lock = AddSystemBuiltin("lock"); Lock = AddSystemBuiltin("lock");
Unlock = AddSystemBuiltin("unlock"); Unlock = AddSystemBuiltin("unlock");
// add system variables
Switch = AddSystemVariable("switch"); // storage for switch statements
} }
sunCallableSymbol AddSystemBuiltin(string name) { sunCallableSymbol AddSystemBuiltin(string name) {
var symbol = new sunBuiltinSymbol(name, SymbolTable.Count); var symbol = new sunBuiltinSymbol(name, SymbolTable.Count);

View file

@ -90,6 +90,20 @@ namespace arookas {
} }
} }
class sunVariablePopSite : sunSymbolRelocation<sunVariableSymbol> {
public sunVariablePopSite(sunBinary binary, sunVariableSymbol symbol)
: base(binary, symbol) {
mBinary.WritePOP();
}
public override void Relocate() {
mBinary.Keep();
mBinary.Goto(mPoint);
mBinary.WritePOP();
mBinary.Back();
}
}
class sunVariableIncSite : sunSymbolRelocation<sunVariableSymbol> { class sunVariableIncSite : sunSymbolRelocation<sunVariableSymbol> {
public sunVariableIncSite(sunBinary binary, sunVariableSymbol symbol) public sunVariableIncSite(sunBinary binary, sunVariableSymbol symbol)
: base(binary, symbol) { : base(binary, symbol) {

View file

@ -255,6 +255,7 @@ namespace arookas {
} }
public abstract void CompileGet(sunCompiler compiler); public abstract void CompileGet(sunCompiler compiler);
public abstract void CompileSet(sunCompiler compiler); public abstract void CompileSet(sunCompiler compiler);
public abstract void CompilePop(sunCompiler compiler);
public virtual void CompileInc(sunCompiler compiler) { public virtual void CompileInc(sunCompiler compiler) {
CompileGet(compiler); CompileGet(compiler);
compiler.Binary.WriteINT(1); compiler.Binary.WriteINT(1);
@ -305,6 +306,9 @@ namespace arookas {
public override void CompileDec(sunCompiler compiler) { public override void CompileDec(sunCompiler compiler) {
OpenRelocation(new sunVariableDecSite(compiler.Binary, this)); OpenRelocation(new sunVariableDecSite(compiler.Binary, this));
} }
public override void CompilePop(sunCompiler compiler) {
OpenRelocation(new sunVariablePopSite(compiler.Binary, this));
}
} }
class sunConstantSymbol : sunStorableSymbol { class sunConstantSymbol : sunStorableSymbol {
@ -329,10 +333,16 @@ namespace arookas {
public override void CompileGet(sunCompiler compiler) { public override void CompileGet(sunCompiler compiler) {
mExpression.Compile(compiler); mExpression.Compile(compiler);
} }
public override void CompileSet(sunCompiler compiler) { public override void CompileSet(sunCompiler compiler) {
// checks against this have to be implemented at a higher level // checks against this have to be implemented at a higher level
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
public override void CompilePop(sunCompiler compiler)
{
throw new InvalidOperationException();
}
} }
public enum sunSymbolType { public enum sunSymbolType {

2
stdlib-sup39/common.sun Normal file
View file

@ -0,0 +1,2 @@
import "./ram.sun";
import "./input.sun";

View file

@ -0,0 +1,2 @@
builtin drawText(x, y, fontSize, colorTop, colorBot, fmt, ...);
builtin drawRect(fill, x0, y0, x1, y1);

22
stdlib-sup39/draw.sun Normal file
View file

@ -0,0 +1,22 @@
builtin drawText(x, y, size, colorTop, colorBot, fmt, ...);
// drawNgon(fill, stroke, n, angle=0)
builtin drawNgon(fill, stroke, n, ...);
// setMTX(dst)
// setMTX(dst, src)
// setMTX(dst, src, dx, dy)
// setMTX(dst, src, SS, dx, dy)
// setMTX(dst, src, xx, yy, dx, dy)
// setMTX(dst, src, xx, xy, yx, yy, dx, dy)
builtin setMTX(dst, ...);
var const MTX_LOADIMM = 0;
var const MTX_NEW = 0;
// drawRect(fill, x0, y0, x1, y1)
// drawRect(fill, stroke, x0, y0, x1, y1, resetMtx=true)
builtin drawRect(fill, x0, y0, x1, y1, ...);
var const FILL_NONE = 0;
var const STROKE_NONE = 0;
builtin setLineWidth(lw);

20
stdlib-sup39/input.sun Normal file
View file

@ -0,0 +1,20 @@
var const addrButton = $80400D50;
var const PRESS_S = 0x1000;
var const PRESS_B = 0x0200;
var const PRESS_A = 0x0100;
var const PRESS_Z = 0x0010;
var const PRESS_X = 0x0400;
var const PRESS_Y = 0x0800;
var const PRESS_DU = 0x0008;
var const PRESS_DD = 0x0004;
var const PRESS_DL = 0x0001;
var const PRESS_DR = 0x0002;
var const PRESS_L = 0x0040;
var const PRESS_R = 0x0020;
var const addrLTrig = $80400D90;
var const addrRTrig = $80400D94;
var const addrMStickX = $80400E40;
var const addrMStickY = $80400E44;
var const addrCStickX = $80400E80;
var const addrCStickY = $80400E84;

25
stdlib-sup39/ram.sun Normal file
View file

@ -0,0 +1,25 @@
builtin readRAM(addr, ...);
builtin writeRAM(addr, value, ...);
builtin memcpy(dst, src, count);
/* https://docs.google.com/spreadsheets/d/1ElTW-akaTUF9OC2pIFR9-7aVPwpJ54AdEVJyJ_jvg0E/edit#gid=1727422135 */
var const gpApplication = $803E6000;
var const addrRand = $80408CF0;
var const addrFlagManager = $8040A290;
var const gpMarDirector = $8040A2A8;
var const gpCardManager = $8040A2B4;
var const gpMarioOriginal = $8040A378;
var const gpMarioAddress = $8040A398;
var const gpMarioPos = $8040A39C;
var const gpMarioAngleX = $8040A3A0;
var const gpMarioAngleY = $8040A3A4;
var const gpMarioAngleZ = $8040A3A8;
var const gpMarioSpeedX = $8040A3AC;
var const gpMarioSpeedY = $8040A3B0;
var const gpMarioSpeedZ = $8040A3B4;
var const gpItemManager = $8040A4D8;
var const gpMap = $8040A570;
var const gpBeamManager = $8040AEB0;
var const gpCamera = $8040B370;
var const gpCameraMario = $8040B378;
var const gpCameraShake = $8040B380;