Clean up sunSpcBinary

This commit is contained in:
arookas 2017-04-15 20:52:05 -04:00
parent c556939972
commit 74fc59f232

View file

@ -87,301 +87,319 @@ namespace arookas {
sealed class sunSpcBinary : sunBinary {
aBinaryWriter mWriter;
sunSpcBinarySection mText, mData, mDataString, mSymbol, mSymbolString;
sunSpcStringTable mStringTable;
uint mTextOffset, mDataOffset, mSymbolOffset;
int mDataCount, mSymbolCount, mVarCount;
public override uint Offset {
get { return mText.Offset; }
get { return (uint)mWriter.Position; }
}
public sunSpcBinary(Stream output) {
mWriter = new aBinaryWriter(output, Endianness.Big, Encoding.GetEncoding(932));
mText = new sunSpcBinarySection();
mData = new sunSpcBinarySection();
mDataString = new sunSpcBinarySection();
mSymbol = new sunSpcBinarySection();
mSymbolString = new sunSpcBinarySection();
mWriter.PushAnchor();
mStringTable = new sunSpcStringTable(Encoding.GetEncoding(932));
}
public override void Open() {
mWriter.PushAnchor();
WriteHeader();
}
public override void Close() {
// header
mWriter.WriteString("SPCB");
mWriter.Write32(0x1C);
mWriter.Write32(0x1C + mText.Size);
WriteHeader();
mWriter.PopAnchor();
}
void WriteHeader() {
mWriter.Goto(0);
mWriter.Write8(0x53); // 'S'
mWriter.Write8(0x50); // 'P'
mWriter.Write8(0x43); // 'C'
mWriter.Write8(0x42); // 'B'
mWriter.Write32(mTextOffset);
mWriter.Write32(mDataOffset);
mWriter.WriteS32(mDataCount);
mWriter.Write32(0x1C + mText.Size + mData.Size + mDataString.Size);
mWriter.Write32(mSymbolOffset);
mWriter.WriteS32(mSymbolCount);
mWriter.WriteS32(mVarCount);
// sections
mText.Copy(mWriter);
mData.Copy(mWriter);
mDataString.Copy(mWriter);
mSymbol.Copy(mWriter);
mSymbolString.Copy(mWriter);
}
// text
public override void Keep() {
mText.Writer.Keep();
mWriter.Keep();
}
public override void Back() {
mText.Writer.Back();
mWriter.Back();
}
public override void Goto(uint offset) {
mText.Writer.Goto(offset);
mWriter.Goto(offset);
}
public override void BeginText() {
mTextOffset = Offset;
mWriter.PushAnchor();
}
public override void WriteINT(int value) {
switch (value) { // shortcut commands
case 0: WriteINT0(); return;
case 1: WriteINT1(); return;
}
TraceInstruction("int {0} # ${0:X}", value);
mText.Writer.Write8(0x00);
mText.Writer.WriteS32(value);
mWriter.Write8(0x00);
mWriter.WriteS32(value);
}
public override void WriteFLT(float value) {
TraceInstruction("flt {0}", value);
mText.Writer.Write8(0x01);
mText.Writer.WriteF32(value);
mWriter.Write8(0x01);
mWriter.WriteF32(value);
}
public override void WriteSTR(int index) {
TraceInstruction("str {0}", index);
mText.Writer.Write8(0x02);
mText.Writer.WriteS32(index);
mWriter.Write8(0x02);
mWriter.WriteS32(index);
}
public override void WriteADR(uint value) {
TraceInstruction("adr ${0:X8}", value);
mText.Writer.Write8(0x03);
mText.Writer.Write32(value);
mWriter.Write8(0x03);
mWriter.Write32(value);
}
public override void WriteVAR(int display, int index) {
TraceInstruction("var {0} {1}", display, index);
mText.Writer.Write8(0x04);
mText.Writer.WriteS32(display);
mText.Writer.WriteS32(index);
mWriter.Write8(0x04);
mWriter.WriteS32(display);
mWriter.WriteS32(index);
}
public override void WriteNOP() {
TraceInstruction("nop");
mText.Writer.Write8(0x05);
mWriter.Write8(0x05);
}
public override void WriteINC(int display, int index) {
TraceInstruction("inc {0} {1}", display, index);
mText.Writer.Write8(0x06);
mText.Writer.WriteS32(display);
mText.Writer.WriteS32(index);
mWriter.Write8(0x06);
mWriter.WriteS32(display);
mWriter.WriteS32(index);
}
public override void WriteDEC(int display, int index) {
TraceInstruction("dec {0} {1}", display, index);
mText.Writer.Write8(0x07);
mText.Writer.WriteS32(display);
mText.Writer.WriteS32(index);
mWriter.Write8(0x07);
mWriter.WriteS32(display);
mWriter.WriteS32(index);
}
public override void WriteADD() {
TraceInstruction("add");
mText.Writer.Write8(0x08);
mWriter.Write8(0x08);
}
public override void WriteSUB() {
TraceInstruction("sub");
mText.Writer.Write8(0x09);
mWriter.Write8(0x09);
}
public override void WriteMUL() {
TraceInstruction("mul");
mText.Writer.Write8(0x0A);
mWriter.Write8(0x0A);
}
public override void WriteDIV() {
TraceInstruction("div");
mText.Writer.Write8(0x0B);
mWriter.Write8(0x0B);
}
public override void WriteMOD() {
TraceInstruction("mod");
mText.Writer.Write8(0x0C);
mWriter.Write8(0x0C);
}
public override void WriteASS(int display, int index) {
TraceInstruction("ass {0} {1}", display, index);
mText.Writer.Write8(0x0D);
mText.Writer.Write8(0x04); // unused (skipped over by TSpcInterp)
mText.Writer.WriteS32(display);
mText.Writer.WriteS32(index);
mWriter.Write8(0x0D);
mWriter.Write8(0x04); // unused (skipped over by TSpcInterp)
mWriter.WriteS32(display);
mWriter.WriteS32(index);
}
public override void WriteEQ() {
TraceInstruction("eq");
mText.Writer.Write8(0x0E);
mWriter.Write8(0x0E);
}
public override void WriteNE() {
TraceInstruction("ne");
mText.Writer.Write8(0x0F);
mWriter.Write8(0x0F);
}
public override void WriteGT() {
TraceInstruction("gt");
mText.Writer.Write8(0x10);
mWriter.Write8(0x10);
}
public override void WriteLT() {
TraceInstruction("lt");
mText.Writer.Write8(0x11);
mWriter.Write8(0x11);
}
public override void WriteGE() {
TraceInstruction("ge");
mText.Writer.Write8(0x12);
mWriter.Write8(0x12);
}
public override void WriteLE() {
TraceInstruction("le");
mText.Writer.Write8(0x13);
mWriter.Write8(0x13);
}
public override void WriteNEG() {
TraceInstruction("neg");
mText.Writer.Write8(0x14);
mWriter.Write8(0x14);
}
public override void WriteNOT() {
TraceInstruction("not");
mText.Writer.Write8(0x15);
mWriter.Write8(0x15);
}
public override void WriteAND() {
TraceInstruction("and");
mText.Writer.Write8(0x16);
mWriter.Write8(0x16);
}
public override void WriteOR() {
TraceInstruction("or");
mText.Writer.Write8(0x17);
mWriter.Write8(0x17);
}
public override void WriteBAND() {
TraceInstruction("band");
mText.Writer.Write8(0x18);
mWriter.Write8(0x18);
}
public override void WriteBOR() {
TraceInstruction("bor");
mText.Writer.Write8(0x19);
mWriter.Write8(0x19);
}
public override void WriteSHL() {
TraceInstruction("shl");
mText.Writer.Write8(0x1A);
mWriter.Write8(0x1A);
}
public override void WriteSHR() {
TraceInstruction("shr");
mText.Writer.Write8(0x1B);
mWriter.Write8(0x1B);
}
public override void WriteCALL(uint offset, int count) {
TraceInstruction("call ${0:X8} {1}", offset, count);
mText.Writer.Write8(0x1C);
mText.Writer.Write32(offset);
mText.Writer.WriteS32(count);
mWriter.Write8(0x1C);
mWriter.Write32(offset);
mWriter.WriteS32(count);
}
public override void WriteFUNC(int index, int count) {
TraceInstruction("func {0} {1}", index, count);
mText.Writer.Write8(0x1D);
mText.Writer.WriteS32(index);
mText.Writer.WriteS32(count);
mWriter.Write8(0x1D);
mWriter.WriteS32(index);
mWriter.WriteS32(count);
}
public override void WriteMKFR(int count) {
#if DEBUG
TraceInstruction("mkfr {0}", count);
#endif
mText.Writer.Write8(0x1E);
mText.Writer.WriteS32(count);
mWriter.Write8(0x1E);
mWriter.WriteS32(count);
}
public override void WriteMKDS(int display) {
TraceInstruction("mkds {0}", display);
mText.Writer.Write8(0x1F);
mText.Writer.WriteS32(display);
mWriter.Write8(0x1F);
mWriter.WriteS32(display);
}
public override void WriteRET() {
TraceInstruction("ret");
mText.Writer.Write8(0x20);
mWriter.Write8(0x20);
}
public override void WriteRET0() {
TraceInstruction("ret0");
mText.Writer.Write8(0x21);
mWriter.Write8(0x21);
}
public override void WriteJNE(uint offset) {
TraceInstruction("jne ${0:X8}", offset);
mText.Writer.Write8(0x22);
mText.Writer.Write32(offset);
mWriter.Write8(0x22);
mWriter.Write32(offset);
}
public override void WriteJMP(uint offset) {
TraceInstruction("jmp ${0:X8}", offset);
mText.Writer.Write8(0x23);
mText.Writer.Write32(offset);
mWriter.Write8(0x23);
mWriter.Write32(offset);
}
public override void WritePOP() {
TraceInstruction("pop");
mText.Writer.Write8(0x24);
mWriter.Write8(0x24);
}
public override void WriteINT0() {
TraceInstruction("int0");
mText.Writer.Write8(0x25);
mWriter.Write8(0x25);
}
public override void WriteINT1() {
TraceInstruction("int1");
mText.Writer.Write8(0x26);
mWriter.Write8(0x26);
}
public override void WriteEND() {
TraceInstruction("end");
mText.Writer.Write8(0x27);
mWriter.Write8(0x27);
}
public override void EndText() {
mWriter.PopAnchor();
}
[Conditional("DEBUG")]
void TraceInstruction(string format, params object[] args) {
var instruction = String.Format(format, args);
Debug.WriteLine("{0:X8} {1}", mText.Size, instruction);
Debug.WriteLine("{0:X8} {1}", mWriter.Position, instruction);
}
// data
public override void BeginData() {
mDataCount = 0;
mDataOffset = Offset;
mWriter.PushAnchor();
mStringTable.Clear();
}
public override void WriteData(string data) {
if (data == null) {
throw new ArgumentNullException("data");
}
mData.Writer.Write32(mDataString.Size);
mDataString.Writer.WriteString<aZSTR>(data);
mWriter.Write32(mStringTable.Add(data));
++mDataCount;
}
public override void EndData() {
mWriter.WriteString(mStringTable.ToString());
mWriter.PopAnchor();
mStringTable.Clear();
}
// symbol
public override void BeginSymbol() {
mSymbolCount = 0;
mSymbolOffset = Offset;
mWriter.PushAnchor();
mStringTable.Clear();
}
public override void WriteSymbol(sunSymbolType type, string name, uint data) {
mSymbol.Writer.WriteS32((int)type);
mSymbol.Writer.Write32(mSymbolString.Size);
mSymbol.Writer.Write32(data);
mSymbol.Writer.Write32(0u); // runtime field (hash)
mSymbol.Writer.Write32(0u); // runtime field (funcptr)
mSymbolString.Writer.WriteString<aZSTR>(name);
mWriter.WriteS32((int)type);
mWriter.Write32(mStringTable.Add(name));
mWriter.Write32(data);
mWriter.Write32(0u); // runtime field (hash)
mWriter.Write32(0u); // runtime field (funcptr)
++mSymbolCount;
if (type == sunSymbolType.Variable) {
++mVarCount;
}
}
public override void EndSymbol() {
mWriter.WriteString(mStringTable.ToString());
mWriter.PopAnchor();
mStringTable.Clear();
}
class sunSpcBinarySection : IDisposable {
readonly aBinaryWriter mWriter;
readonly MemoryStream mStream;
class sunSpcStringTable {
StringBuilder mBuilder;
Encoding mEncoding;
uint mSize;
public aBinaryWriter Writer {
get { return mWriter; }
}
public MemoryStream Stream {
get { return mStream; }
public sunSpcStringTable(Encoding encoding) {
mBuilder = new StringBuilder(1024);
mEncoding = encoding;
}
public uint Offset {
get { return (uint)mWriter.Position; }
public uint Add(string value) {
var size = mSize;
mBuilder.Append(value);
mBuilder.Append('\0');
mSize += (uint)mEncoding.GetByteCount(value) + 1u; // + null terminator
return size;
}
public uint Size {
get { return (uint)mWriter.Length; }
public override string ToString() {
return mBuilder.ToString();
}
public sunSpcBinarySection() {
mStream = new MemoryStream(1024);
mWriter = new aBinaryWriter(mStream, Endianness.Big, Encoding.GetEncoding(932));
}
public void Dispose() {
mStream.Dispose();
}
public void Copy(aBinaryWriter writer) {
if (writer == null) {
throw new ArgumentNullException("writer");
}
writer.Write8s(mStream.GetBuffer(), (int)Size);
public void Clear() {
mBuilder.Clear();
mSize = 0;
}
}
}