From 74fc59f232a2cbd16708a510cb46551d08ef7a4f Mon Sep 17 00:00:00 2001 From: arookas Date: Sat, 15 Apr 2017 20:52:05 -0400 Subject: [PATCH] Clean up sunSpcBinary --- ssc/binary.cs | 260 +++++++++++++++++++++++++++----------------------- 1 file changed, 139 insertions(+), 121 deletions(-) diff --git a/ssc/binary.cs b/ssc/binary.cs index 3939b9d..ef570b0 100644 --- a/ssc/binary.cs +++ b/ssc/binary.cs @@ -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(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(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; } } }