summaryrefslogtreecommitdiff
path: root/utils/ihx2tzx/tzxwriter.pas
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ihx2tzx/tzxwriter.pas')
-rw-r--r--utils/ihx2tzx/tzxwriter.pas132
1 files changed, 132 insertions, 0 deletions
diff --git a/utils/ihx2tzx/tzxwriter.pas b/utils/ihx2tzx/tzxwriter.pas
new file mode 100644
index 0000000000..b3be2abb10
--- /dev/null
+++ b/utils/ihx2tzx/tzxwriter.pas
@@ -0,0 +1,132 @@
+{ IHX (Intel Hex format) to TZX (ZX Spectrum tape file format) convertor tool.
+
+ This file contains the TZX writer code.
+
+ Copyright (C) 2020 Nikolay Nikolov <nickysn@users.sourceforg.net>
+
+ This source 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 2 of the License, or (at your option)
+ any later version.
+
+ This code 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.
+
+ A copy of the GNU General Public License is available on the World Wide Web
+ at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
+ to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1335, USA.
+}
+
+unit tzxwriter;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+
+ { TTZXWriter }
+
+ TTZXWriter = class
+ private
+ FOutStream: TStream;
+ public
+ constructor Create(OutStream : TStream);
+ procedure AppendStandardSpeedDataBlock(const Buffer; Count: Word);
+ procedure AppendHeader(FileType: Byte; const FileName: string; DataBlockLength, Parameter1, Parameter2: Word);
+ procedure AppendDataBlock(const Buffer; Count: Word);
+ procedure AppendProgramFile(const FileName: string; AutostartLine, VarAreaOffset: Word; const Buffer; Count: Word);
+ procedure AppendCodeFile(const FileName: string; StartAddress: Word; const Buffer; Count: Word);
+ end;
+
+implementation
+
+{ TTZXWriter }
+
+constructor TTZXWriter.Create(OutStream: TStream);
+const
+ Header: string = 'ZXTape!'#$1A#1#20;
+begin
+ FOutStream := OutStream;
+ FOutStream.Seek(0, soFromBeginning);
+ FOutStream.Write(Header[1], Length(Header));
+end;
+
+procedure TTZXWriter.AppendStandardSpeedDataBlock(const Buffer; Count: Word);
+const
+ PauseMilliseconds = 1000;
+begin
+ FOutStream.WriteByte($10);
+ FOutStream.WriteByte(Byte(PauseMilliseconds));
+ FOutStream.WriteByte(Byte(PauseMilliseconds shr 8));
+ FOutStream.WriteByte(Byte(Count));
+ FOutStream.WriteByte(Byte(Count shr 8));
+ FOutStream.Write(Buffer, Count);
+end;
+
+procedure TTZXWriter.AppendHeader(FileType: Byte; const FileName: string;
+ DataBlockLength, Parameter1, Parameter2: Word);
+var
+ HeaderBlock: array [0..18] of Byte;
+ I: Integer;
+ Checksum: Byte;
+begin
+ HeaderBlock[0] := 0; { header }
+ HeaderBlock[1] := FileType;
+ { file name }
+ for I := 1 to 10 do
+ if I <= Length(FileName) then
+ HeaderBlock[I + 1] := Ord(FileName[I])
+ else
+ HeaderBlock[I + 1] := Ord(' ');
+ HeaderBlock[12] := Byte(DataBlockLength);
+ HeaderBlock[13] := Byte(DataBlockLength shr 8);
+ HeaderBlock[14] := Byte(Parameter1);
+ HeaderBlock[15] := Byte(Parameter1 shr 8);
+ HeaderBlock[16] := Byte(Parameter2);
+ HeaderBlock[17] := Byte(Parameter2 shr 8);
+ Checksum := 0;
+ for I := 0 to 17 do
+ Checksum := Checksum xor HeaderBlock[I];
+ HeaderBlock[18] := Checksum;
+ AppendStandardSpeedDataBlock(HeaderBlock, SizeOf(HeaderBlock));
+end;
+
+procedure TTZXWriter.AppendDataBlock(const Buffer; Count: Word);
+var
+ I: Integer;
+ Checksum: Byte;
+ DataBlock: array of Byte;
+begin
+ SetLength(DataBlock, Count + 2);
+ Move(Buffer, DataBlock[1], Count);
+ DataBlock[0] := $FF; { data }
+ Checksum := 0;
+ for I := 0 to High(DataBlock) - 1 do
+ Checksum := Checksum xor DataBlock[I];
+ DataBlock[High(DataBlock)] := Checksum;
+ AppendStandardSpeedDataBlock(DataBlock[0], Length(DataBlock));
+end;
+
+procedure TTZXWriter.AppendProgramFile(const FileName: string; AutostartLine,
+ VarAreaOffset: Word; const Buffer; Count: Word);
+begin
+ AppendHeader(0, FileName, Count, AutostartLine, VarAreaOffset);
+ AppendDataBlock(Buffer, Count);
+end;
+
+procedure TTZXWriter.AppendCodeFile(const FileName: string; StartAddress: Word;
+ const Buffer; Count: Word);
+begin
+ AppendHeader(3, FileName, Count, StartAddress, 32768);
+ AppendDataBlock(Buffer, Count);
+end;
+
+end.
+