Skip to content

Instantly share code, notes, and snippets.

@damieng
Last active December 2, 2021 18:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damieng/75f8dd42c8e01288e08c374fd4f62c5f to your computer and use it in GitHub Desktop.
Save damieng/75f8dd42c8e01288e08c374fd4f62c5f to your computer and use it in GitHub Desktop.
ZX Spectrum P-File decoder (incomplete)
using System;
using System.IO;
using System.Linq;
using System.Text;
internal class Program
{
static void Main(string[] args)
{
var pFileName = "EasyList.P";
using var reader = new BinaryReader(File.OpenRead(pFileName));
var version = reader.ReadByte();
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
var fileName = new String(reader.ReadChars(10)).TrimEnd();
var length = reader.ReadUInt16();
var param1 = reader.ReadUInt16();
var param2 = reader.ReadUInt16();
var unknown = reader.ReadBytes(3);
Console.WriteLine($"{fileName} length {length} ({param1}/{param2}/{String.Join("", unknown.Select(b => b.ToString("x2")).ToArray())})");
string text;
if (fileName.EndsWith("_T"))
text = GetFixedText(reader, length);
else
text = GetBasic(reader, length);
Console.WriteLine(text);
}
}
static readonly char[] textBuffer = new char[65536];
static readonly char[] noSpaceAfter = new char[] { ' ', '(', ')', ';', '=', '#', '<', '>', '*', '+', '/', '-' };
static string GetBasic(BinaryReader reader, int length)
{
var sb = new StringBuilder();
var endOfBasicPosition = reader.BaseStream.Position + length;
while (reader.BaseStream.Position < endOfBasicPosition)
{
var lineNumber = (reader.ReadByte() * 256) + reader.ReadByte();
if (lineNumber > 9999) break;
var lineLength = reader.ReadUInt16();
var endOfLinePosition = reader.BaseStream.Position + lineLength;
var line = lineNumber.ToString();
while (reader.BaseStream.Position < endOfLinePosition)
{
var b = reader.ReadByte();
var t = GetToken(b);
var lastChar = line[line.Length - 1];
if (noSpaceAfter.Contains(lastChar))
line += t.TrimStart();
else
line += t;
}
sb.AppendLine(line);
}
return sb.ToString();
}
static string GetFixedText(BinaryReader reader, int length)
{
int i = 0;
do
{
char c = reader.ReadChar();
switch (c)
{
case (char)0x0D:
textBuffer[i++] = '\n';
break;
default:
textBuffer[i++] = c;
break;
}
} while (i <= length);
return new String(textBuffer, 0, i);
}
static string GetToken(byte b)
{
return b switch
{
0x60 => "£",
127 => "©",
165 => " RND ",
166 => " INKEY$ ",
167 => " PI ",
168 => " FN ",
169 => " POINT ",
170 => " SCREEN$ ",
171 => " ATTR ",
172 => " AT ",
173 => " TAB ",
174 => " VAL$ ",
175 => " CODE ",
176 => " VAL ",
177 => " LEN ",
178 => " SIN ",
179 => " COS ",
180 => " TAN ",
181 => " ASN ",
182 => " ACS ",
183 => " ATN ",
184 => " LN ",
185 => " EXP ",
186 => " INT ",
187 => " SQR ",
188 => " SGN ",
189 => " ABS ",
190 => " PEEK ",
191 => " IN ",
192 => " USR ",
193 => " STR$ ",
194 => " CHR$ ",
195 => " NOT ",
196 => " BIN ",
197 => " OR ",
198 => " AND ",
199 => "<= ",
200 => ">= ",
201 => "<> ",
202 => " LINE ",
203 => " THEN ",
204 => " TO ",
205 => " STEP ",
206 => " DEF FN ",
207 => " CAT ",
208 => " FORMAT ",
209 => " MOVE ",
210 => " ERASE ",
211 => " OPEN #",
212 => " CLOSE #",
213 => " MERGE ",
214 => " VERIFY ",
215 => " BEEP ",
216 => " CIRCLE ",
217 => " INK ",
218 => " PAPER ",
219 => " FLASH ",
220 => " BRIGHT ",
221 => " INVERSE ",
222 => " OVER ",
223 => " OUT ",
224 => " LPRINT ",
225 => " LLIST ",
226 => " STOP ",
227 => " READ ",
228 => " DATA ",
229 => " RESTORE ",
230 => " NEW ",
231 => " BORDER ",
232 => " CONTINUE ",
233 => " DIM ",
234 => " REM ",
235 => " FOR ",
236 => " GO TO ",
237 => " GO SUB ",
238 => " INPUT ",
239 => " LOAD ",
240 => " LIST ",
241 => " LET ",
242 => " PAUSE ",
243 => " NEXT ",
244 => " POKE ",
245 => " PRINT ",
246 => " PLOT ",
247 => " RUN ",
248 => " SAVE ",
249 => " RANDOMIZE ",
250 => " IF ",
251 => " CLS ",
252 => " DRAW ",
253 => " CLEAR ",
254 => " RETURN ",
255 => " COPY ",
_ => new String((char)b, 1)
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment