Commit e7c9e12a authored by jmcgrew@d9ba3f8c-9c8e-47e3-a892-eed549321d50's avatar jmcgrew@d9ba3f8c-9c8e-47e3-a892-eed549321d50
Browse files

Initial import of ZILF 0.3

parents
/* Copyright 2010 Jesse McGrew
*
* This file is part of DeZAPF.
*
* DeZAPF is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DeZAPF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeZAPF. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Dezapf
{
abstract class Chunk
{
public int PC { get; protected set; }
public int Length { get; protected set; }
public Chunk Parent;
protected Chunk(int pc, int length)
{
this.PC = pc;
this.Length = length;
}
public abstract void WriteTo(TextWriter writer, Context ctx);
public virtual bool WantNewParagraph(Chunk previous)
{
return true;
}
public virtual int GetAlignment(Context ctx)
{
return 1;
}
}
class DataChunk : Chunk
{
public byte[] Bytes { get; private set; }
private DataChunk(int pc, int length, byte[] data)
: base(pc, length)
{
this.Bytes = data;
}
public static DataChunk FromStream(Stream stream, int offset, int length)
{
stream.Seek(offset, SeekOrigin.Begin);
byte[] data = new byte[length];
stream.Read(data, 0, length);
return new DataChunk(offset, length, data);
}
public override void WriteTo(TextWriter writer, Context ctx)
{
ctx.OutputStyle.FormatData(writer, ctx, this);
}
}
class CompoundChunk : Chunk
{
protected readonly List<Chunk> contents = new List<Chunk>();
public static CompoundChunk Combine(Chunk first, Chunk second)
{
CompoundChunk cc = first as CompoundChunk;
if (cc != null)
{
cc.Add(second);
return cc;
}
return new CompoundChunk(first.PC, first.Length + second.Length, first, second);
}
public CompoundChunk(int pc, int length)
: base(pc, length)
{
}
public CompoundChunk(int pc, int length, Chunk first, Chunk second)
: this(pc, length)
{
contents.Add(first);
contents.Add(second);
}
public void Add(Chunk next)
{
next.Parent = this;
contents.Add(next);
Length += next.Length;
}
public override void WriteTo(TextWriter writer, Context ctx)
{
foreach (Chunk ch in contents)
ch.WriteTo(writer, ctx);
}
}
class FunctChunk : CompoundChunk
{
public FunctChunk(int pc, int length)
: base(pc, length)
{
}
public ushort[] Locals { get; set; }
public override void WriteTo(TextWriter writer, Context ctx)
{
ctx.OutputStyle.FormatFunctStart(writer, ctx, this);
base.WriteTo(writer, ctx);
ctx.OutputStyle.FormatFunctEnd(writer, ctx, this);
}
public override int GetAlignment(Context ctx)
{
return ctx.PackingFactor;
}
}
class GlobalsChunk : Chunk
{
public ushort[] Values { get; private set; }
private GlobalsChunk(int pc, ushort[] values)
: base(pc, values.Length * 2)
{
this.Values = values;
}
public static GlobalsChunk FromStream(Stream stream, int offset, int length)
{
stream.Seek(offset, SeekOrigin.Begin);
BinaryReader rdr = new BinaryReader(stream);
int count = length / 2;
ushort[] values = new ushort[count];
for (int i = 0; i < count; i++)
values[i] = rdr.ReadZWord();
return new GlobalsChunk(offset, values);
}
public override void WriteTo(TextWriter writer, Context ctx)
{
ctx.OutputStyle.FormatGlobalsStart(writer, ctx, Values.Length);
for (int i = 0; i < Values.Length; i++)
ctx.OutputStyle.FormatGlobal(writer, ctx, (ushort)(i + 16), Values[i]);
ctx.OutputStyle.FormatGlobalsEnd(writer, ctx);
}
}
}
/* Copyright 2010 Jesse McGrew
*
* This file is part of DeZAPF.
*
* DeZAPF is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DeZAPF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeZAPF. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zapf;
using System.Reflection;
namespace Dezapf
{
class Context
{
private int zversion;
private Header header;
private readonly RangeList<Chunk> chunks = new RangeList<Chunk>();
private readonly Dictionary<ushort, ZOpAttribute> opcodes = new Dictionary<ushort, ZOpAttribute>();
public Context()
{
zversion = 3;
LoadOpcodes();
}
public OutputStyle OutputStyle;
public int ZVersion
{
get
{
return zversion;
}
set
{
if (value < 3 || value > 8)
throw new ArgumentOutOfRangeException("Only versions 3-8 are supported");
zversion = value;
LoadOpcodes();
}
}
public int PackingFactor
{
get
{
switch (zversion)
{
case 1:
case 2:
case 3:
return 2;
case 4:
case 5:
case 6:
case 7:
return 4;
case 8:
return 8;
default:
throw new NotImplementedException();
}
}
}
public int SizeFactor
{
get
{
switch (zversion)
{
case 1:
case 2:
case 3:
return 2;
case 4:
case 5:
return 4;
default:
return 8;
}
}
}
public Header Header
{
get
{
return header;
}
set
{
ZVersion = value.ZVersion;
header = value;
}
}
public RangeList<Chunk> Chunks
{
get { return chunks; }
}
public int UnpackAddress(int packed, int hdrOffset)
{
if (zversion == 6 || zversion == 7)
return 4 * packed + 8 * hdrOffset;
return packed * PackingFactor;
}
public int PackAddress(int address, int hdrOffset)
{
if (zversion == 6 || zversion == 7)
return (address - 8 * hdrOffset) / 4;
return address / PackingFactor;
}
private void LoadOpcodes()
{
opcodes.Clear();
int effectiveVersion = zversion;
if (zversion == 7)
effectiveVersion = 6;
else if (zversion == 8)
effectiveVersion = 5;
foreach (FieldInfo fi in typeof(Zapf.Opcodes).GetFields(BindingFlags.Static | BindingFlags.Public))
{
if (fi.FieldType == typeof(Zapf.Opcodes))
{
ushort num = (ushort)(Zapf.Opcodes)fi.GetValue(null);
foreach (ZOpAttribute attr in fi.GetCustomAttributes(typeof(ZOpAttribute), false))
if (effectiveVersion >= attr.MinVer && effectiveVersion <= attr.MaxVer)
opcodes.Add(num, attr);
}
}
}
public ZOpAttribute GetOpcodeInfo(ushort op)
{
ZOpAttribute result;
opcodes.TryGetValue(op, out result);
return result;
}
private static readonly char[] defaultAlphabet0 =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
};
private static readonly char[] defaultAlphabet1 =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
};
private static readonly char[] defaultAlphabet2 =
{
' ', '\n', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.',
',', '!', '?', '_', '#', '\'', '"', '/', '\\', '-', ':', '(', ')',
};
public string DecodeText(ushort[] encodedText)
{
System.Diagnostics.Debug.Assert(zversion >= 3);
StringBuilder sb = new StringBuilder(encodedText.Length * 3);
int mode = 0; // 0/1/2 = alphabets, 3 = ASCII state 1, 4 = ASCII state 2
int pendingAscii = 0;
//XXX handle custom alphabets
char[] alphabet0 = defaultAlphabet0;
char[] alphabet1 = defaultAlphabet1;
char[] alphabet2 = defaultAlphabet2;
for (int i = 0; i < encodedText.Length; i++)
{
ushort w = encodedText[i];
for (int j = 0; j < 3; j++)
{
int code = (w & 0x7c00) >> 10;
w <<= 5;
switch (mode)
{
case 3:
pendingAscii = code << 5;
mode = 4;
break;
case 4:
sb.Append((char)(pendingAscii | code));
mode = 0;
break;
default:
switch (code)
{
case 0:
sb.Append(' ');
mode = 0;
break;
case 1:
case 2:
case 3:
// abbreviations
//XXX
mode = 0;
break;
case 4:
mode = 1;
break;
case 5:
mode = 2;
break;
case 6:
if (mode == 2)
{
mode = 3;
break;
}
goto default;
default:
code -= 6;
switch (mode)
{
case 0:
sb.Append(alphabet0[code]);
break;
case 1:
sb.Append(alphabet1[code]);
break;
case 2:
sb.Append(alphabet2[code]);
break;
}
mode = 0;
break;
}
break;
}
}
}
return sb.ToString();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EF94747E-F175-4AF5-8882-2FA99EB1505A}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dezapf</RootNamespace>
<AssemblyName>Dezapf</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Chunk.cs" />
<Compile Include="Context.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="Header.cs" />
<Compile Include="Instruction.cs" />
<Compile Include="OutputStyle.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RangeList.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Zapf\Zapf.csproj">
<Project>{C4379053-B0C7-4826-AC41-CEA59A743B15}</Project>
<Name>Zapf</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
/* Copyright 2010 Jesse McGrew
*
* This file is part of DeZAPF.
*
* DeZAPF is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DeZAPF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeZAPF. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Dezapf
{
static class ExtensionMethods
{
public static ushort ReadZWord(this BinaryReader rdr)
{
byte b1 = rdr.ReadByte();
byte b2 = rdr.ReadByte();
return (ushort)((b1 << 8) + b2);
}
}
}
/* Copyright 2010 Jesse McGrew
*
* This file is part of DeZAPF.
*
* DeZAPF is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DeZAPF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeZAPF. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Dezapf
{
[AttributeUsage(AttributeTargets.Field)]
class SetByTerpAttribute : Attribute
{
}
struct Header
{
// supplied in file...
public byte ZVersion;
public byte Flags1;
public ushort Release;
public ushort EndLod;
public ushort Start;
public ushort Vocab;
public ushort Objects;
public ushort Globals;
public ushort Impure;
public ushort Flags2;
public byte[] Serial;
public ushort Words;
public ushort Length;
public ushort Checksum;
// filled in by interpreter...
[SetByTerp]
public byte TerpNum;
[SetByTerp]
public byte TerpVersion;
[SetByTerp]
public byte ScreenRows;
[SetByTerp]
public byte ScreenColumns;
[SetByTerp]
public ushort ScreenWidth;
[SetByTerp]
public ushort ScreenHeight;
[SetByTerp]