Skip to content

Commit 54703b1

Browse files
committed
Add POK file format and public comments
1 parent 9e3978e commit 54703b1

23 files changed

Lines changed: 1201 additions & 3 deletions

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ jobs:
1313

1414
steps:
1515
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
1618

1719
- name: Setup .NET
1820
uses: actions/setup-dotnet@v4

Spectron.Files.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IY/@EntryIndexedValue">IY</s:String>
99
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PC/@EntryIndexedValue">PC</s:String>
1010
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SP/@EntryIndexedValue">SP</s:String>
11+
<s:Boolean x:Key="/Default/UserDictionary/Words/=amstrad/@EntryIndexedValue">True</s:Boolean>
1112
<s:Boolean x:Key="/Default/UserDictionary/Words/=covox/@EntryIndexedValue">True</s:Boolean>
1213
<s:Boolean x:Key="/Default/UserDictionary/Words/=currah/@EntryIndexedValue">True</s:Boolean>
1314
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kempston/@EntryIndexedValue">True</s:Boolean>

src/Spectron.Files/Extensions/TapFileExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
namespace OldBit.Spectron.Files.Extensions;
77

8+
/// <summary>
9+
/// Extensions for converting between TapFile and TzxFile.
10+
/// </summary>
811
public static class TapFileExtensions
912
{
1013
/// <summary>

src/Spectron.Files/Pok/PokeFile.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
namespace OldBit.Spectron.Files.Pok;
2+
3+
/// <summary>
4+
/// Represents a poke that needs to be applied to a game.
5+
/// </summary>
6+
/// <param name="MemoryBank">Bits 0-2 specify a memory bank for 128K games or bit 3
7+
/// is always set for 48K games</param>
8+
/// <param name="Address">The address (16384-65535).</param>
9+
/// <param name="Value">Poke value (0-255). If it is 256, a requester should pop up where the user can enter a value</param>
10+
/// <param name="OriginalValue">Original value at the address.</param>
11+
public record Poke(int MemoryBank, Word Address, int Value, byte OriginalValue);
12+
13+
/// <summary>
14+
/// Represents a trainer that contains a list of pokes.
15+
/// </summary>
16+
/// <param name="Name">The name of the trainer.</param>
17+
/// <param name="Pokes">A list of pokes.</param>
18+
public record Trainer(string Name, List<Poke> Pokes);
19+
20+
/// <summary>
21+
/// Represents a POKE file.
22+
/// </summary>
23+
public sealed class PokeFile
24+
{
25+
/// <summary>
26+
/// Gets the list of trainers in the POKE file.
27+
/// </summary>
28+
public List<Trainer> Trainers { get; } = [];
29+
30+
private PokeFile()
31+
{
32+
}
33+
34+
/// <summary>
35+
/// Loads a POKE file from the specified file and parses its contents into a PokeFile object.
36+
/// </summary>
37+
/// <param name="fileName">The path to the POKE file to be loaded.</param>
38+
/// <returns>A <see cref="PokeFile"/> instance containing the trainers and pokes parsed from the file.</returns>
39+
public static PokeFile Load(string fileName)
40+
{
41+
var lines = File.ReadAllLines(fileName);
42+
43+
var pokeFile = new PokeFile();
44+
Trainer? trainer = null;
45+
46+
foreach (var line in lines)
47+
{
48+
if (IsNextTrainer(line))
49+
{
50+
trainer = new Trainer(line[1..], []);
51+
}
52+
53+
if (line.StartsWith('M'))
54+
{
55+
var poke = ParsePoke(line);
56+
57+
if (poke != null)
58+
{
59+
trainer?.Pokes.Add(poke);
60+
}
61+
}
62+
63+
if (line.StartsWith('Z'))
64+
{
65+
var poke = ParsePoke(line);
66+
67+
if (poke != null && trainer != null)
68+
{
69+
trainer.Pokes.Add(poke);
70+
pokeFile.Trainers.Add(trainer);
71+
72+
trainer = null;
73+
}
74+
}
75+
76+
if (IsLastLine(line))
77+
{
78+
break;
79+
}
80+
}
81+
82+
return pokeFile;
83+
}
84+
85+
private static Poke? ParsePoke(string line)
86+
{
87+
var parts = line.Split(' ');
88+
89+
if (parts.Length != 5)
90+
{
91+
return null;
92+
}
93+
94+
if (!int.TryParse(parts[1].Trim(), out var memoryBank))
95+
{
96+
return null;
97+
}
98+
99+
if (!Word.TryParse(parts[2].Trim(), out var address))
100+
{
101+
return null;
102+
}
103+
104+
if (!int.TryParse(parts[3].Trim(), out var value))
105+
{
106+
return null;
107+
}
108+
109+
if (!byte.TryParse(parts[4].Trim(), out var originalValue))
110+
{
111+
return null;
112+
}
113+
114+
return new Poke(memoryBank, address, value, originalValue);
115+
}
116+
117+
private static bool IsNextTrainer(string line) => line.StartsWith('N');
118+
119+
private static bool IsLastLine(string line) => line.StartsWith('Y');
120+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace OldBit.Spectron.Files.Serialization;
22

3-
public interface IDataSerializer
3+
internal interface IDataSerializer
44
{
55
byte[] Serialize();
66
}

src/Spectron.Files/Spectron.Files.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
<Version>0.9.2</Version>
1010
<Title>ZX Spectrum emulator files parser</Title>
1111
<Authors>Wojciech Sobieszek</Authors>
12-
<Description>This package allows reading and writing files used by ZX Spectrum emulators such as TAP, TZX, SNA, SZX and Z80.</Description>
12+
<Description>This package allows reading and writing files used by ZX Spectrum emulators such as TAP, TZX, SNA, SZX, POK and Z80.</Description>
1313
<PackageProjectUrl>https://github.com/oldbit-com/Spectron.Files</PackageProjectUrl>
14-
<PackageTags>TAP TZX SNA SZX Z80</PackageTags>
14+
<PackageTags>TAP TZX SNA SZX Z80 POK</PackageTags>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageIcon>icon.png</PackageIcon>
1717
<PackageReadmeFile>README.md</PackageReadmeFile>
18+
<GenerateDocumentationFile>True</GenerateDocumentationFile>
19+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1820
</PropertyGroup>
1921

2022
<ItemGroup>

src/Spectron.Files/Szx/SzxHeader.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,94 @@ namespace OldBit.Spectron.Files.Szx;
88
/// </summary>
99
public sealed class SzxHeader
1010
{
11+
/// <summary>
12+
/// ZX Spectrum 16K.
13+
/// </summary>
1114
public const byte MachineId16K = 0;
15+
16+
/// <summary>
17+
/// ZX Spectrum 48K.
18+
/// </summary>
1219
public const byte MachineId48K = 1;
20+
21+
/// <summary>
22+
/// ZX Spectrum 128K.
23+
/// </summary>
1324
public const byte MachineId128K = 2;
25+
26+
/// <summary>
27+
/// ZX Spectrum +2.
28+
/// </summary>
1429
public const byte MachineIdPlus2 = 3;
30+
31+
/// <summary>
32+
/// ZX Spectrum +2A.
33+
/// </summary>
1534
public const byte MachineIdPlus2A = 4;
35+
36+
/// <summary>
37+
/// ZX Spectrum +3.
38+
/// </summary>
1639
public const byte MachineIdPlus3 = 5;
40+
41+
/// <summary>
42+
/// ZX Spectrum +3E.
43+
/// </summary>
1744
public const byte MachineIdPlus3E = 6;
45+
46+
/// <summary>
47+
/// Pentagon 128.
48+
/// </summary>
1849
public const byte MachineIdPentagon128 = 7;
50+
51+
/// <summary>
52+
/// Timex TC2048.
53+
/// </summary>
1954
public const byte MachineIdTc2048 = 8;
55+
56+
/// <summary>
57+
/// Timex TC2068.
58+
/// </summary>
2059
public const byte MachineIdTc2068 = 9;
60+
61+
/// <summary>
62+
/// Scorpion.
63+
/// </summary>
2164
public const byte MachineIdScorpion = 10;
65+
66+
/// <summary>
67+
/// ZX Spectrum SE.
68+
/// </summary>
2269
public const byte MachineIdSe = 11;
70+
71+
/// <summary>
72+
/// Timex TS2068.
73+
/// </summary>
2374
public const byte MachineIdTs2068 = 12;
75+
76+
/// <summary>
77+
/// Pentagon 512K.
78+
/// </summary>
2479
public const byte MachineIdPentagon512 = 13;
80+
81+
/// <summary>
82+
/// Pentagon 1024K.
83+
/// </summary>
2584
public const byte MachineIdPentagon1024 = 14;
85+
86+
/// <summary>
87+
/// ZX Spectrum 48K NTSC.
88+
/// </summary>
2689
public const byte MachineIdNtsc48K = 15;
90+
91+
/// <summary>
92+
/// ZX Spectrum 128 KE.
93+
/// </summary>
2794
public const byte MachineId128Ke = 16;
2895

96+
/// <summary>
97+
/// Alternate timings.
98+
/// </summary>
2999
public const byte FlagsAlternateTimings = 1;
30100

31101
/// <summary>

src/Spectron.Files/Tap/Extensions/TapeHeaderExtensions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
namespace OldBit.Spectron.Files.Tap.Extensions;
22

3+
/// <summary>
4+
/// Extensions for the TapHeader class.
5+
/// </summary>
36
public static class TapeHeaderExtensions
47
{
8+
/// <summary>
9+
/// Retrieves the name of the data type based on the header's data type.
10+
/// </summary>
11+
/// <param name="header">The TapHeader instance containing the data type information.</param>
12+
/// <returns>A string representing the name of the data type, such as "Program", "Number Array", "Character Array", "Bytes", or "Unknown" if the data type is unrecognized.</returns>
513
public static string GetDataTypeName(this TapHeader header)
614
{
715
return header.DataType switch

src/Spectron.Files/Tzx/ArchiveInfo.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
11
namespace OldBit.Spectron.Files.Tzx;
22

3+
/// <summary>
4+
/// Represents a utility class for handling archive information properties in the TZX file format.
5+
/// </summary>
36
public static class ArchiveInfo
47
{
8+
/// <summary>
9+
/// Represents the identifier for the "Title" property in the archive information section of a TZX file.
10+
/// </summary>
511
public const byte Title = 0x00;
12+
13+
/// <summary>
14+
/// Represents the identifier for the "Publisher" property in the archive information section of a TZX file.
15+
/// </summary>
616
public const byte Publisher = 0x01;
17+
18+
/// <summary>
19+
/// Represents the identifier for the "Author" property in the archive information section of a TZX file.
20+
/// </summary>
721
public const byte Author = 0x02;
22+
23+
/// <summary>
24+
/// Represents the identifier for the "Year" property in the archive information section of a TZX file.
25+
/// </summary>
826
public const byte Year = 0x03;
27+
28+
/// <summary>
29+
/// Represents the identifier for the "Language" property in the archive information section of a TZX file.
30+
/// </summary>
931
public const byte Language = 0x04;
32+
33+
/// <summary>
34+
/// Represents the identifier for the "Type" property in the archive information section of a TZX file.
35+
/// </summary>
1036
public const byte Type = 0x05;
37+
38+
/// <summary>
39+
/// Represents the identifier for the "Price" property in the archive information section of a TZX file.
40+
/// </summary>
1141
public const byte Price = 0x06;
42+
43+
/// <summary>
44+
/// Represents the identifier for the "Protection" property in the archive information section of a TZX file.
45+
/// </summary>
1246
public const byte Protection = 0x07;
47+
48+
/// <summary>
49+
/// Represents the identifier for the "Origin" property in the archive information section of a TZX file.
50+
/// </summary>
1351
public const byte Origin = 0x08;
52+
53+
/// <summary>
54+
/// Represents the identifier for the "Comments" property in the archive information section of a TZX file.
55+
/// </summary>
1456
public const byte Comments = 0xFF;
1557

1658
/// <summary>

src/Spectron.Files/Tzx/BlockCode.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
namespace OldBit.Spectron.Files.Tzx;
22

3+
/// <summary>
4+
/// Contains constant values representing different types of TZX block codes used in the system.
5+
/// </summary>
6+
/// <remarks>
7+
/// These block codes correspond to various data types and operations defined in the TZX file format.
8+
/// They are used to identify the type of block in TZX-related operations and processes.
9+
/// </remarks>
310
public static class BlockCode
411
{
512
/// <summary>

0 commit comments

Comments
 (0)