From 6550d927d3fded9d308af81e139dfd2c75efe7d9 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Thu, 16 Nov 2017 14:16:39 -0800 Subject: [PATCH] Updated PC code to handle 12, 16, or 18 bit data from the PDP-8; added 12-bit dump program for PDP-8. (18-bit program is used for both 18 and 16-bit tapes). --- .../{DumpDT18.csproj => DumpDectape.csproj} | 7 +- DumpDT18/Program.cs | 744 +++++++++++++--- DumpDT18/Properties/AssemblyInfo.cs | 6 +- DumpDT18/dumpdt12.bin | Bin 0 -> 1158 bytes DumpDT18/dumpdt12.lst | 796 ++++++++++++++++++ DumpDT18/dumpdt12.pal | 689 +++++++++++++++ DumpDT18/dumpdt18-550.pal | 2 +- DumpDT18/dumpdt18.pal | 3 +- DumpDT18.sln => DumpDectape.sln | 2 +- 9 files changed, 2120 insertions(+), 129 deletions(-) rename DumpDT18/{DumpDT18.csproj => DumpDectape.csproj} (92%) create mode 100644 DumpDT18/dumpdt12.bin create mode 100644 DumpDT18/dumpdt12.lst create mode 100644 DumpDT18/dumpdt12.pal rename DumpDT18.sln => DumpDectape.sln (85%) diff --git a/DumpDT18/DumpDT18.csproj b/DumpDT18/DumpDectape.csproj similarity index 92% rename from DumpDT18/DumpDT18.csproj rename to DumpDT18/DumpDectape.csproj index 6b41dde..c1098fc 100644 --- a/DumpDT18/DumpDT18.csproj +++ b/DumpDT18/DumpDectape.csproj @@ -6,8 +6,8 @@ AnyCPU {88B646C3-54D8-4D63-BB8A-B391C996FE47} Exe - DumpDT18 - DumpDT18 + DumpDectape + DumpDectape v4.5.2 512 true @@ -47,6 +47,8 @@ + + PreserveNewest @@ -57,6 +59,7 @@ + diff --git a/DumpDT18/Program.cs b/DumpDT18/Program.cs index 216f902..c9a3cdc 100644 --- a/DumpDT18/Program.cs +++ b/DumpDT18/Program.cs @@ -2,15 +2,14 @@ using System.IO; using System.IO.Ports; -/* - * This program receives an 18-bit Dectape image from the serial port from the - PDP8 TD8E dump program. It is loosely based on David Gesswein's dumptd8e - program. +// +// This program receives an Dectape image in 12, 16, or 18b format from the serial port, from the +// appropriate PDP8 TD8E dump program. It is loosely based on David Gesswein's dumptd8e +// program. - This program should be running before the PDP8 end is started. +// This program should be running before the PDP8 end is started. -*/ -namespace DumpDT18 +namespace DumpDectape { class Program { @@ -24,42 +23,61 @@ namespace DumpDT18 static void Main(string[] args) { - if (args.Length < 3) + if (!ReadConfiguration(args)) { - Console.WriteLine("usage: DumpDT18 "); + // Just exit, configuration is invalid. return; } // // Open the serial port. Or try, anyway. // - SerialPort port = new SerialPort(args[0], int.Parse(args[1])); - port.StopBits = StopBits.One; - port.Handshake = Handshake.None; - port.Parity = Parity.None; + SerialPort port = new SerialPort(_configuration.PortName, _configuration.BaudRate, _configuration.Parity, 8, _configuration.StopBits); + port.Handshake = Handshake.None; port.Open(); - string tapeFileName = args[2]; + string tapeFileName = _configuration.FileName; string diagFileName = Path.Combine(Path.GetDirectoryName(tapeFileName), Path.GetFileNameWithoutExtension(tapeFileName) + ".log"); // Open the output file using (FileStream tapeOutput = new FileStream(tapeFileName, FileMode.Create, FileAccess.Write), diagOutput = new FileStream(diagFileName, FileMode.Create, FileAccess.Write)) { + IBlockProcessor blockProcessor = null; + int tapeBits = 0; + + switch (_configuration.TapeType) + { + case TapeType.Twelve: + blockProcessor = new BlockProcessor12(tapeOutput); + tapeBits = 12; + break; + + case TapeType.Sixteen: + blockProcessor = new BlockProcessor16(tapeOutput); + tapeBits = 16; + break; + + case TapeType.Eighteen: + blockProcessor = new BlockProcessor18(tapeOutput); + tapeBits = 18; + break; + + default: + throw new InvalidOperationException("Unexpected tape type."); + } + StreamWriter diagText = new StreamWriter(diagOutput); diagText.AutoFlush = true; - diagText.WriteLine("Summary log for 18-bit DECTape image {0} captured on {1}:", tapeFileName, DateTime.Now); + diagText.WriteLine("Summary log for {0}-bit DECTape image {1} captured on {2}:", tapeBits, tapeFileName, DateTime.Now); Console.WriteLine("Initialized, waiting for tape data."); ReadState readState = ReadState.BlockFlag; - int wordCount18 = 0; int blockNumber = 0; - int byteIndex36 = 0; - int byteIndex12 = 0; + int checksumByteIndex = 0; ushort temp = 0; int chksum12 = 0; - ulong thirtySix = 0; int badBlocks = 0; while (true) @@ -77,13 +95,12 @@ namespace DumpDT18 { case 0xff: case 0xfd: - wordCount18 = 0; - byteIndex36 = 0; + blockProcessor.StartBlock(); readState = ReadState.BlockData; if (b == 0xfd) { - Console.WriteLine("\nBlock {0} bad\n", blockNumber); + Console.Write(" {0} bad ", blockNumber); diagText.WriteLine("Block {0} bad.", blockNumber); badBlocks++; } @@ -91,7 +108,7 @@ namespace DumpDT18 case 0xfe: readState = ReadState.Checksum; - byteIndex12 = 0; + checksumByteIndex = 0; break; default: @@ -103,10 +120,10 @@ namespace DumpDT18 case ReadState.Checksum: // read first byte of checksum - if (byteIndex12 == 0) + if (checksumByteIndex == 0) { temp = (ushort)b; - byteIndex12 = 1; + checksumByteIndex = 1; } else { @@ -115,102 +132,25 @@ namespace DumpDT18 chksum12 = (temp + chksum12) & 0xfff; if (chksum12 != 0) { - Console.WriteLine("Read completed. Warning: Checksum error: {0}.", ToOctal(chksum12)); - diagText.WriteLine("Checksum error: {0}", ToOctal(chksum12)); - return; + Console.WriteLine("Warning: Checksum error during read: {0}.", ToOctal(chksum12)); + diagText.WriteLine("Warning: Checksum error during read: {0}.", ToOctal(chksum12)); } - Console.WriteLine("Read completed successfully. {0} blocks read, {1} bad blocks.", blockNumber, badBlocks); - diagText.WriteLine("Read successful. {0} blocks read, {1} bad blocks.", blockNumber, badBlocks); + Console.WriteLine("Read completed {0}. {1} blocks read, {2} bad blocks.", chksum12 == 0 ? "successfully" : "with checksum errors", blockNumber, badBlocks); + diagText.WriteLine("Read completed {0}. {1} blocks read, {2} bad blocks.", chksum12 == 0 ? "successfully" : "with checksum errors", blockNumber, badBlocks); return; } break; case ReadState.BlockData: + // + // Process the current byte. + // + blockProcessor.ProcessByte(b); // - // There are 384 12-bit words per block and each 12-bit word is - // transferred as 1.5 bytes. The 384 12-bit words in a block - // correspond to 256 18-bit words (1.5 12-bit words per 18-bit word) - // which we want to write out to an 18-bit SIMH dectape image. This - // is further complicated by the fact that due to the way the - // bits actually get written to the tape, reading 18-bit words - // as 1.5 12-bit words ends up transposing 6-bit segments inside - // a 36-bit segment: - // If the original 6-bit half-word ordering is: - // 5 4 3 2 1 0 - // When read back into sequential 12-bit words, these half-words get - // rearranged: - // 2 5 4 1 0 3 + // Deal with the 12-bit checksum. // - // To keep things somewhat easy to understand here (so as to preserve - // my own sanity) at the expense of slightly longer code, - // the state machine below parses 9 bytes (72 bits) at a time - // which corresponds to 2 36-bit words (4 18-bit words) and re-arranges the 6-bit - // half-words after each 36-bit word is read in. These re-arranged words are then - // pushed out to disk in standard SIMH 18b format. - // - // We do this while ALSO summing the 12-bit checksum used at the end of the transfer. - // - switch (byteIndex36++) - { - case 0: - thirtySix = b; - break; - - case 1: - thirtySix |= (ulong)(b << 8); - break; - - case 2: - thirtySix |= (ulong)(b << 16); - break; - - case 3: - thirtySix |= (ulong)(b << 24); - break; - - case 4: - thirtySix |= (ulong)((b & 0xf) << 32); - - // First 36-bit word finished. - WriteThirtySix(tapeOutput, MangleBits(thirtySix)); - wordCount18 += 2; - - // Start next 36-bit word - thirtySix = (ulong)((b & 0xf0) >> 4); - break; - - case 5: - thirtySix |= (ulong)(b << 4); - break; - - case 6: - thirtySix |= (ulong)(b << 12); - break; - - case 7: - thirtySix |= (ulong)(b << 20); - break; - - case 8: - thirtySix |= (ulong)(b << 28); - - // Second 36-bit word finished. - WriteThirtySix(tapeOutput, MangleBits(thirtySix)); - wordCount18 += 2; - - byteIndex36 = 0; - break; - - default: - throw new InvalidOperationException("Unexpected state when building 36-bit word."); - - } - - // - // Deal with the 12-bit checksum - // - switch (byteIndex12++) + switch (checksumByteIndex++) { case 0: temp = (ushort)b; @@ -225,7 +165,7 @@ namespace DumpDT18 case 2: temp = (ushort)((temp | (b << 4)) & 0xfff); chksum12 = chksum12 + temp; - byteIndex12 = 0; + checksumByteIndex = 0; break; default: @@ -235,11 +175,11 @@ namespace DumpDT18 // // Start next block when at end. // - if (wordCount18 == 256) + if (blockProcessor.BlockDone) { readState = ReadState.BlockFlag; blockNumber++; - byteIndex36 = 0; + checksumByteIndex = 0; if ((blockNumber % 5) == 0) { Console.Write("{0}", blockNumber); @@ -254,14 +194,14 @@ namespace DumpDT18 } } } - } + } - private static ulong MangleBits(ulong mangled) + public static ulong MangleBits(ulong mangled) { ulong unmangled; // - // Reading 18-bit DECTapes on a 12-bit PDP-8 presents an interesting + // Reading 18-bit or 16-bit DECTapes on a 12-bit PDP-8 presents an interesting // ordering of 6-bit half-words. // Effectively, each 36-bit sequence reorders 6-bit sequences as: // original: 5 4 3 2 1 0 @@ -277,6 +217,284 @@ namespace DumpDT18 ((mangled & 0xfc0000000) >> 6); return unmangled; + } + + public static string ToOctal(int i) + { + return Convert.ToString(i, 8); + } + + private static void PrintUsage() + { + Console.WriteLine("DumpDectape captures SIMH-compatible Dectape images from a PDP-8 system running the appropriate dump program."); + Console.WriteLine("usage: DumpDectape -port [-baud ] [-stop ] [-parity ] -type -file "); + Console.WriteLine(" specifies the serial port to use (e.g. 'com1')"); + Console.WriteLine(" specifies the baud rate to use (e.g. '9600')"); + Console.WriteLine(" specifies the number of stop bits (e.g. '1')"); + Console.WriteLine(" specifies the parity (e.g. 'Even')"); + Console.WriteLine(" If unspecified, DumpDectape defaults to 9600 baud, 1 stop bit, no parity."); + Console.WriteLine(" specifies the type of Dectape being dumped: 18b, 16b, or 12b."); + Console.WriteLine(" specifies the name of the SIMH image file to create."); + } + + private static bool ReadConfiguration(string[] args) + { + _configuration = new Configuration(); + + int index = 0; + while(index < args.Length) + { + try + { + switch (args[index++]) + { + case "-port": + _configuration.PortName = args[index++]; + break; + + case "-baud": + _configuration.BaudRate = int.Parse(args[index++]); + break; + + case "-stop": + switch(args[index++]) + { + case "1": + _configuration.StopBits = StopBits.One; + break; + + case "2": + _configuration.StopBits = StopBits.Two; + break; + + case "1.5": + _configuration.StopBits = StopBits.OnePointFive; + break; + + default: + throw new InvalidOperationException("Invalid Stop Bits specification."); + } + break; + + case "-parity": + _configuration.Parity = (Parity)Enum.Parse(typeof(Parity), args[index++]); + break; + + case "-type": + switch(args[index++]) + { + case "12b": + _configuration.TapeType = TapeType.Twelve; + break; + + case "16b": + _configuration.TapeType = TapeType.Sixteen; + break; + + case "18b": + _configuration.TapeType = TapeType.Eighteen; + break; + + default: + throw new InvalidOperationException("Invalid Tape Type specification."); + + } + break; + + case "-file": + _configuration.FileName = args[index++]; + break; + + default: + throw new InvalidOperationException("Invalid option."); + } + } + catch + { + // TODO: be more helpful about where the user screwed up. + PrintUsage(); + return false; + } + } + + // + // Ensure required options have been set, if not, print usage instructions. + if (_configuration.TapeType == TapeType.Unspecified || + string.IsNullOrWhiteSpace(_configuration.PortName) || + string.IsNullOrWhiteSpace(_configuration.FileName)) + { + PrintUsage(); + return false; + } + else + { + return true; + } + } + + private enum TapeType + { + Unspecified = 0, + Twelve, + Sixteen, + Eighteen, + } + + private class Configuration + { + public Configuration() + { + // Set things to defaults. + FileName = null; + PortName = null; + BaudRate = 9600; + Parity = Parity.None; + StopBits = StopBits.One; + TapeType = TapeType.Unspecified; + } + + public string FileName; + public string PortName; + public int BaudRate; + public Parity Parity; + public StopBits StopBits; + public TapeType TapeType; + } + + private static Configuration _configuration; + } + + public interface IBlockProcessor + { + void StartBlock(); + + void ProcessByte(ulong b); + + bool BlockDone { get; } + } + + public class BlockProcessor18 : IBlockProcessor + { + public BlockProcessor18(Stream outputStream) + { + _outStream = outputStream; + _byteIndex36 = 0; + _thirtySix = 0; + _wordCount18 = 0; + _blockDone = true; + } + + public bool BlockDone + { + get { return _blockDone; } + } + + public void StartBlock() + { + _blockDone = false; + _byteIndex36 = 0; + _wordCount18 = 0; + _thirtySix = 0; + } + + /// + /// Appends a new byte onto the output data. + /// + /// + /// true if the end of the block has been reached, false otherwise + public void ProcessByte(ulong b) + { + if (_blockDone) + { + throw new InvalidOperationException("Invalid state: ProcessByte called before StartBlock."); + } + + // + // For 18-bit tapes: + // There are 384 12-bit words per block and each 12-bit word is + // transferred as 1.5 bytes. The 384 12-bit words in a block + // correspond to 256 18-bit words (1.5 12-bit words per 18-bit word) + // which we want to write out to an 18-bit SIMH dectape image. This + // is further complicated by the fact that due to the way the + // bits actually get written to the tape, reading 18-bit words + // as 1.5 12-bit words ends up transposing 6-bit segments inside + // a 36-bit segment: + // If the original 6-bit half-word ordering is: + // 5 4 3 2 1 0 + // When read back into sequential 12-bit words, these half-words get + // rearranged: + // 2 5 4 1 0 3 + // + // To keep things somewhat easy to understand here (so as to preserve + // my own sanity) at the expense of slightly longer code, + // the state machine below parses 9 bytes (72 bits) at a time + // which corresponds to 2 36-bit words (4 18-bit words) and re-arranges the 6-bit + // half-words after each 36-bit word is read in. These re-arranged words are then + // pushed out to disk in standard SIMH 18b format. + // + switch (_byteIndex36++) + { + case 0: + _thirtySix = b; + break; + + case 1: + _thirtySix |= (ulong)(b << 8); + break; + + case 2: + _thirtySix |= (ulong)(b << 16); + break; + + case 3: + _thirtySix |= (ulong)(b << 24); + break; + + case 4: + _thirtySix |= (ulong)((b & 0xf) << 32); + + // First 36-bit word finished. + WriteThirtySix(_outStream, Program.MangleBits(_thirtySix)); + _wordCount18 += 2; + + // Start next 36-bit word + _thirtySix = (ulong)((b & 0xf0) >> 4); + break; + + case 5: + _thirtySix |= (ulong)(b << 4); + break; + + case 6: + _thirtySix |= (ulong)(b << 12); + break; + + case 7: + _thirtySix |= (ulong)(b << 20); + break; + + case 8: + _thirtySix |= (ulong)(b << 28); + + // Second 36-bit word finished. + WriteThirtySix(_outStream, Program.MangleBits(_thirtySix)); + _wordCount18 += 2; + + _byteIndex36 = 0; + break; + + default: + throw new InvalidOperationException("Unexpected state when building 36-bit word."); + + } + + if (_wordCount18 == 256) + { + // Finished with the current block, reset our word count + // and let the caller know we're done. + + _blockDone = true; + } } private static void WriteThirtySix(Stream outStream, ulong thirtySix) @@ -287,7 +505,7 @@ namespace DumpDT18 private static void WriteEighteen(Stream outStream, uint eighteen) { - outStream.WriteByte((byte) (eighteen & 0x000000ff)); + outStream.WriteByte((byte)(eighteen & 0x000000ff)); outStream.WriteByte((byte)((eighteen & 0x0000ff00) >> 8)); outStream.WriteByte((byte)((eighteen & 0x00ff0000) >> 16)); outStream.WriteByte((byte)((eighteen & 0xff000000) >> 24)); @@ -295,9 +513,293 @@ namespace DumpDT18 outStream.Flush(); } - public static string ToOctal(int i) + /// + /// The current byte index into the two 36-bit words we're building + /// + private int _byteIndex36; + + /// + /// The current 36-bit word we've built + /// + private ulong _thirtySix; + + /// + /// The number of 18-bit words we've read. + /// + private int _wordCount18; + + /// + /// Whether we've completed a block (and StartBlock must be called before processing more data) + /// + private bool _blockDone; + + /// + /// The stream we'll flush the data to. + /// + private Stream _outStream; + } + + public class BlockProcessor16 : IBlockProcessor + { + public BlockProcessor16(Stream outputStream) { - return Convert.ToString(i, 8); + _outStream = outputStream; + _byteIndex36 = 0; + _thirtySix = 0; + _wordCount16 = 0; + _blockDone = true; } + + public bool BlockDone + { + get { return _blockDone; } + } + + public void StartBlock() + { + _blockDone = false; + _byteIndex36 = 0; + _wordCount16 = 0; + _thirtySix = 0; + } + + /// + /// Appends a new byte onto the output data. + /// + /// + /// true if the end of the block has been reached, false otherwise + public void ProcessByte(ulong b) + { + if (_blockDone) + { + throw new InvalidOperationException("Invalid state: ProcessByte called before StartBlock."); + } + + // + // For 16-bit tapes: + // See the comments in BlockProcessor18.ProcessByte for the nitty-gritty. + // 16-bit tapes are handled nearly identically, since the format on tape is identical. + // The difference is that 16-bit dectapes do not use the upper 2 bits of each + // 18-bit word on tape. After the typical 18-bit processing and re-arrangement, we write out the data + // in the standard 16-bit SIMH format. + // Some of this code could technically be factored out. + // + switch (_byteIndex36++) + { + case 0: + _thirtySix = b; + break; + + case 1: + _thirtySix |= (ulong)(b << 8); + break; + + case 2: + _thirtySix |= (ulong)(b << 16); + break; + + case 3: + _thirtySix |= (ulong)(b << 24); + break; + + case 4: + _thirtySix |= (ulong)((b & 0xf) << 32); + + // First 36-bit word finished. + WriteThirtySix(_outStream, Program.MangleBits(_thirtySix)); + _wordCount16 += 2; + + // Start next 36-bit word + _thirtySix = (ulong)((b & 0xf0) >> 4); + break; + + case 5: + _thirtySix |= (ulong)(b << 4); + break; + + case 6: + _thirtySix |= (ulong)(b << 12); + break; + + case 7: + _thirtySix |= (ulong)(b << 20); + break; + + case 8: + _thirtySix |= (ulong)(b << 28); + + // Second 36-bit word finished. + WriteThirtySix(_outStream, Program.MangleBits(_thirtySix)); + _wordCount16 += 2; + + _byteIndex36 = 0; + break; + + default: + throw new InvalidOperationException("Unexpected state when building 36-bit word."); + + } + + if (_wordCount16 == 256) + { + // Finished with the current block, reset our word count + // and let the caller know we're done. + + _blockDone = true; + } + } + + private static void WriteThirtySix(Stream outStream, ulong thirtySix) + { + WriteSixteen(outStream, (uint)(thirtySix & 0xffff)); + + // TODO: verify this is correct. + WriteSixteen(outStream, (uint)((thirtySix & 0x3fffc0000) >> 18)); + } + + private static void WriteSixteen(Stream outStream, uint sixteen) + { + outStream.WriteByte((byte) (sixteen & 0x00ff)); + outStream.WriteByte((byte)((sixteen & 0xff00) >> 8)); + outStream.Flush(); + } + + /// + /// The current byte index into the two 36-bit words we're building + /// + private int _byteIndex36; + + /// + /// The current 36-bit word we've built + /// + private ulong _thirtySix; + + /// + /// The number of 18-bit words we've read. + /// + private int _wordCount16; + + /// + /// Whether we've completed a block (and StartBlock must be called before processing more data) + /// + private bool _blockDone; + + /// + /// The stream we'll flush the data to. + /// + private Stream _outStream; + } + + public class BlockProcessor12 : IBlockProcessor + { + public BlockProcessor12(Stream outputStream) + { + _outStream = outputStream; + _byteIndex12 = 0; + _twelve = 0; + _wordCount12 = 0; + _blockDone = true; + } + + public bool BlockDone + { + get { return _blockDone; } + } + + public void StartBlock() + { + _blockDone = false; + _byteIndex12 = 0; + _twelve = 0; + _wordCount12 = 0; + } + + /// + /// Appends a new byte onto the output data. + /// + /// + /// true if the end of the block has been reached, false otherwise + public void ProcessByte(ulong b) + { + if (_blockDone) + { + throw new InvalidOperationException("Invalid state: ProcessByte called before StartBlock."); + } + + // + // For 12-bit tapes: + // There are 129 12-bit words per block and each 12-bit word is + // transferred as 1.5 bytes. The reassembled 12-bit words are then + // pushed out to disk in standard SIMH 12b format. + // + switch (_byteIndex12++) + { + case 0: + _twelve = b; + break; + + case 1: + _twelve |= (ulong)(b << 8); + + // First 12-bit word finished. + WriteTwelve(_outStream, _twelve); + _wordCount12++; + + // Start next 12-bit word. + _twelve = (ulong)(b >> 4); + break; + + case 2: + // Second 12-bit word finished. + _twelve |= (ulong)((b << 4)); + WriteTwelve(_outStream, _twelve); + _wordCount12++; + + // Start over. + _byteIndex12 = 0; + break; + + default: + throw new InvalidOperationException("Unexpected state when building 12-bit word."); + } + + if (_wordCount12 == 129) + { + // Finished with the current block. + _blockDone = true; + } + } + + private static void WriteTwelve(Stream outStream, ulong twelve) + { + outStream.WriteByte((byte) (twelve & 0x0ff)); + outStream.WriteByte((byte)((twelve & 0xf00) >> 8)); + outStream.Flush(); + } + + /// + /// The current byte index into the two 36-bit words we're building + /// + private int _byteIndex12; + + /// + /// The current 36-bit word we've built + /// + private ulong _twelve; + + /// + /// The number of 18-bit words we've read. + /// + private int _wordCount12; + + /// + /// Whether we've completed a block (and StartBlock must be called before processing more data) + /// + private bool _blockDone; + + /// + /// The stream we'll flush the data to. + /// + private Stream _outStream; } } diff --git a/DumpDT18/Properties/AssemblyInfo.cs b/DumpDT18/Properties/AssemblyInfo.cs index 8de24cf..8cf56dc 100644 --- a/DumpDT18/Properties/AssemblyInfo.cs +++ b/DumpDT18/Properties/AssemblyInfo.cs @@ -5,12 +5,12 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("DumpPDP7")] +[assembly: AssemblyTitle("DumpDectape")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("DumpPDP7")] -[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyProduct("DumpDectape")] +[assembly: AssemblyCopyright("Copyright © 2017 LCM+L")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/DumpDT18/dumpdt12.bin b/DumpDT18/dumpdt12.bin new file mode 100644 index 0000000000000000000000000000000000000000..9c9f272e9aa16584995e78a0f4a553aa47f31b2a GIT binary patch literal 1158 zcmd^94RfL}5M7DYV7!__)d;o%TG4Q$6wgV(K(4*-f7PFUi`MDfZ@A4237fa?ZFVzx zd;7oa6@CJMNQ)uM!`&^Yx&rD6--BDwvDmh=Se?IX4+^3zY1nhHrKvKA5@}-Hg zt+I;)_2*LAk{U-IRE6G{Zw<{hd|mP?V8{2Ul~|(QbC{$>S~Q@_3{+G0;EDNWlg(&` zk)W&*%<71)b%frk(HB$&$c^Ym$OBy?GLwf2G|;73@r^uW(u0zFaMlvW*>FVqNCjr zpaSOWsO)JR$??RQ?~L|NU-mKpyB;FT#s1jB{mQLb*xI7!@#+U4?f=C_1hpVc-DF&pDxzsDk>_k1izVj`v@#tu*DRLAtL#vJLy zY@`mJ=rl;_EUmGeXWN_1XD1PyK!k%QWO*puwBl3#Ad8|S$9TFj)hD2_j;}MSo(C*a zjm#IePD`iTUMAb9a9h5!`dY_$1D4{URk<){3#Q)JNvrWqk^06ZP1hr~3q627biTts z9C(ZN7C9ObB;Gl@VbR%R-B8~ba~dpBaTwBA#KZ8i{>V~1@=$)pj@Ln^fzR<)_paEs zYY@@LkC>&)!;G}(&}q?9?7Vh==Kp(EPzCC{ds<+~^ literal 0 HcmV?d00001 diff --git a/DumpDT18/dumpdt12.lst b/DumpDT18/dumpdt12.lst new file mode 100644 index 0000000..585043e --- /dev/null +++ b/DumpDT18/dumpdt12.lst @@ -0,0 +1,796 @@ + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 1 + + + 1 / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code from D. Gesswein + 2 / (see ftp://ftp.pdp8online.com/software/dumprest). + 3 / Modified to handle arbitrary-length tapes by J. Dersch + 4 / + 5 / This program will send a DECtape image out the console port. + 6 / The format of the data sent is 0xff (0377) or 0xfd if read error + 7 / followed by 129 12-bit words of data for each block. + 8 / After the last block a 0xfe (0376) is sent + 9 / with a two byte checksum, low 8 bits first then upper 4. + 10 / The words in a block are sent as three bytes for each 2 words. + 11 / 1 = low 8 bits first word + 12 / 2 = upper 4 bits first and lower 4 bits second + 13 / 3 = upper 8 bits second word + 14 / + 15 / The program (PC) receiving the data should be started before this program. + 16 / + 17 / To run, start at 0200. + 18 / SR 11 should be drive, only 0 and 1 supported without reassembling + 19 / SR 6-8 should be maximum memory field in computer, needs 8k minimum + 20 / + 21 / The receiving program should be running first. + 22 / At normal exit hitting cont will restart the program. + 23 / + 24 / Should halt at label finish (140) with number of recoverable errors in AC + 25 / The current block being read will be displayed in the AC + 26 / while running. + 27 / + 28 / The PC program will print out the bad location if an error occurs. + 29 / + 30 / We will retry each read up to four times on error. + 31 / + 32 / This transfers the standard 129 word by 1474 blocks used by 12-bit DEC hardware, + 33 / using standard checksums (as used by the PDP-9 and later machines). + 34 / It will read as many blocks are present up to the forward end-zone, so it will + 35 / handle tapes that vary from the standard block length. + 36 / + 37 0030 INAD=030 / Address of serial input, 30 for console + 38 6030 KCF2=6000 INAD + 39 6031 KSF2=6001 INAD + 40 6032 KCC2=6002 INAD + 41 6034 KRS2=6004 INAD + 42 6035 KIE2=6005 INAD + 43 6036 KRB2=6006 INAD + 44 + 45 0040 OUTAD=040 / Address of serial output, 40 for console + 46 6040 TFL2=6000 OUTAD + 47 6041 TSF2=6001 OUTAD + 48 6042 TCF2=6002 OUTAD + 49 6044 TPC2=6004 OUTAD + 50 6045 TSK2=6005 OUTAD + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 2 + + + 51 6046 TLS2=6006 OUTAD + 52 + 53 + 54 /CODE BASED ON: + 55 /2 TD8E INITIALIZER PROGRAM, V7A + 56 / + 57 /COPYRIGHT (C) 1975, 1977 + 58 /DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. + 59 / + 60 / + 61 / + 62 /THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A + 63 /SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE INCLU- + 64 /SION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ANT OTHER + 65 /COPIES THEREOF, MAY NOT BR PROVIDED OR OTHERWISE MADE AVAILABLE + 66 /TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO + 67 /AGREES TO THESE LICENSE TERMS. TITLE TO AND OWNERSHIP OF THE + 68 /SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC. + 69 / + 70 / + 71 /THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT + 72 /NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL + 73 /EQUIPMRNT COROPATION. + 74 / + 75 /DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS + 76 /SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. + 77 / + 78 / + 79 / + 80 / + 81 / + 82 / + 83 + 84 /DECEMBER 21, 1973 GB/RL/EF/SR + 85 + 86 /ABSTRACT-- + 87 / THE ROUTINE DESCRIBED AND LISTED HERE IS A GENERAL + 88 /DATA HANDLER FOR THE TD8E DECTAPE SYSTEM. THE ROUTINE + 89 /CONTAINS SEARCH, READ, AND WRITE FUNCTIONS IN A FORMAT + 90 /WHICH IS COMPATIBLE WITH OS/8 DEVICE HANDLER CALLING + 91 /SEQUENCES. + 92 + 93 /FIXES SINCE FIELD-TEST RELEASE: + 94 + 95 /1. FIXED BUG RE CLA ON RETRY AFTER ERROR + 96 /2. ALLOWED FINAL BOOTSTRAP TO BE INTO A WRITE-LOCKED DEVICE + 97 + 98 /OS/8 V3D CHANGES: + 99 + 100 /3. FIXED BUG RE TD8E BUILD (V6B PATCH) + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 3 + + + 101 + 102 /THIS ROUTINE CAN BE RE-EDITED AND ASSEMBLED TO PRODUCE + 103 /VARIATIONS ON THE BASIC TD8E SYSTEM. ASSEMBLY PARAMETERS + 104 /CONTROL: + 105 /A) WHAT DRIVES (UNITS 0-7) WILL BE USED + 106 /B) THE ORIGIN OF THE TWO PAGE ROUTINE + 107 /C) WHAT MEMORY FIELD THE ROUTINE WILL RUN IN + 108 /D) THE SIZE OF THE DECTAPE BLOCK TO BE READ/WRITTEN + 109 + 110 /FOLLOWING ARE THE PARAMETERS SET UP FOR THE STANDARD + 111 /DEC VERSION OF THIS ROUTINE: + 112 + 113 0010 DRIVE=10 /UNITS 0 AND 1 SELECTED + 114 0600 ORIGIN=600 /ENTER AT ORIGIN, ORIGIN+4 + 115 0000 AFIELD=0 /INITIAL FIELD SETTING + 116 0000 MFIELD=00 /AFIELD*10=MFIELD + 117 0201 WDSBLK=201 /129 12-BIT WORDS PER BLOCK + 118 + 119 /THE USE OF THE PARAMETERS IS AS FOLLOWS: + 120 + 121 / DRIVE: DRIVE DETERMINES WHICH UNITS WILL BE SELECTED + 122 / DRIVE=10 IMPLIES UNITS 0 &1 + 123 / DRIVE=20 IMPLIES UNITS 2&3 + 124 / DRIVE=30 IMPLIES UNITS 4&5 + 125 / DRIVE=40 IMPLIES UNITS 6&7 + 126 + 127 /ORIGIN: ALTERING ORIGIN CAUSES ASSEMBLY IN A DIFFERENT + 128 / MEMORY LOCATION. WHEN CHANGING ORIGIN KEEP IN MIND + 129 /THAT THIS IS A TWO PAGE ROUTINE. + 130 + 131 /AFIELD: AFIELD DETERMINES THE INITIAL FIELD SETTING FOR THE + 132 / LOADER. PERMISSIBLE VALUES FOR AFIELD ARE 0 TO 7. + 133 + 134 /MFIELD: MFIELD IS USED IN A CIF CDF MFIELD INSTRUCTION. + 135 / THE VALUE INSERTED FOR MFIELD SHOULD BE 10(8) TIMES + 136 / THE VALUE FOR AFIELD. THE PERMISSIBLE VALUES ARE 00-70. + 137 + 138 /WDSBLK: WDSBLK GOVERNS HOW MANY WORDS THE ROUTINE THINKS ARE + 139 / IN A DECTAPE BLOCK. THE STANDARD VALUE IS 201(8) OR + 140 / 128 DECIMAL. NOTE THAT THE FUNCTION WORD BIT 10 CAN + 141 / 129 DECIMAL ??? (DJG) + 142 / BE USED TO SUBTRACT ONE FROM WDSBLK. THE VALUE USED + 143 / FOR WDSBLK SHOULD BE THE NUMBER OF WORDS THE TAPE WAS + 144 / FORMATTED TO CONTAIN. + 145 + 146 /IF WE WANT A HANDLER FOR UNITS 2&3 TO RESIDE IN + 147 /FIELD 2 AT LOCATION 3000 AND READ/WRITE 256(10) WORDS + 148 /PER BLOCK, THE PARAMETERS WOULD BE: + 149 / DRIVE=20 + 150 / ORIGIN=3000 + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 4 + + + 151 / AFIELD=2 + 152 / MFIELD=20 + 153 / WDSBLK=400 + 154 /THE CALL TO THE SUBROUTINE FOLLOWS BASICALLY THE + 155 /CALLING SEQUENCE FOR OS/8 DEVICE HANDLERS. + 156 /THE CALLING SEQUENCE IS: + 157 + 158 / CDF CURRENT + 159 / CIF MFIELD /MFIELD=FIELD ASSEMBLED IN + 160 / JMS ENTRY /ENTRY=ORIGIN (EVEN NUMBERED DRIVE + 161 /AND ORIGIN+4 FOR ODD NUMBERED DRIVE. + 162 / ARG1 + 163 / ARG1B (DJG) + 164 / ARG2 + 165 / ARG3 + 166 / ERROR RETURN + 167 / NORMAL RETURN + 168 + 169 /THE ARGUMENTS ARE: + 170 + 171 /ARG1: FUNCTION WORD BIT0: 0=READ, 1=WRITE + 172 / BITS 1-5: UNUSED, WAS # BLOCKS IN OPERATION (DJG) + 173 / BITS 6-8: FIELD OF BUFFER AREA + 174 / BIT 9: UNUSED + 175 / BIT 10: # OF WORDS/BLOCK. + 176 / 0= WDSBLK, 1=WDSBLK-1 + 177 / BIT 11: 1=START FORWARD, 0=REVERSE + 178 /ARG1A: # OF BLOCKS IN OPERATIONA (DJG) + 179 /ARG2: BUFFER ADDRESS FOR OPERATION + 180 /ARG3: STARTING BLOCK FOR OPERATION + 181 + 182 /ERRORS: THE HANDLER DETECTS TWO TYPES OF ERRORS: + 183 /A) FATAL ERRORS- PARITY ERROR, TIMING ERROR, + 184 / TOO GREAT A BLOCK NUMBER + 185 / FATAL ERRORS TAKE ERROR RETURN WITH THE + 186 / AC=4000. + 187 /B) NON-FATAL- SELECT ERROR. + 188 / IF NO PROPER UNIT IS SELECTED, THE ERROR + 189 / RETURN IS TAKEN WITH CLEAR AC. + 190 /FATAL ERRORS TRY THREE TIMES BEFORE TAKING ERROR RETURN. + 191 /THE NORMAL RETURN IS TAKEN AFTER ALL INDICATED + 192 /BLOCKS HAVE BEEN TRANSFERRED. THE AC IS CLEAR. + 193 + 194 /THE TD8E IOT'S ARE: + 195 6771 SDSS=7001-DRIVE /SKIP ON SINGLE LINE FLAG + 196 6772 SDST=7002-DRIVE /SKIP ON TIMING ERROR + 197 6773 SDSQ=7003-DRIVE /SKIP ON QUAD LINE FLAG + 198 6774 SDLC=7004-DRIVE /LOAD COMMAND REGISTER + 199 6775 SDLD=7005-DRIVE /LOAD DATA REGISTER + 200 6776 SDRC=7006-DRIVE /READ COMMAND REGISTER + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 5 + + + 201 6777 SDRD=7007-DRIVE /READ DATA REGISTER + 202 + 203 /THE IOT'S IN GENERAL ARE 677X,676X,675X,AND 674X. + 204 /THE OTHERS CONTROL UNITS 2-7. + 205 + 206 / THIS HANDLER USES DECTAPE BLOCKS NOT OS/8 BLOCKS ! + 207 + 208 0600 *ORIGIN + 209 + 210 / MODIFIED SO BIT 0 ON ENTRY IS UNIT 1 + 211 00600 0000 DTA0, 0 + 212 00601 3047 DCA UNIT /SAVE UNIT POSITION + 213 00602 6214 RDF + 214 00603 1360 TAD C6203 /GET DATA FIELD AND SETUP RETURN + 215 00604 3356 DCA LEAVE + 216 00605 1600 TAD I DTA0 /GET FUNCTION WORD + 217 00606 6775 SDLD /PUT FUNCTION INTO DATA REGISTER + 218 00607 7200 CLA + 219 00610 1022 TAD MWORDS + 220 00611 3023 DCA WCOUNT /STORE MASTER WORD COUNT + 221 00612 2200 ISZ DTA0 /TO BLOCK COUNT (DJG) + 222 00613 1600 TAD I DTA0 / (DJG) + 223 00614 7041 CIA / (DJG) + 224 00615 3051 DCA PGCT / (DJG) + 225 00616 2200 ISZ DTA0 /TO BUFFER + 226 00617 1600 TAD I DTA0 + 227 00620 3044 DCA XBUFF /SAVE ADDRESS (DJG) + 228 00621 2200 ISZ DTA0 /TO BLOCK NUMBER + 229 00622 1600 TAD I DTA0 + 230 00623 3046 DCA BLOCK + 231 00624 2200 ISZ DTA0 /POINT TO ERROR EXIT + 232 00625 6203 CIF CDF MFIELD /TO ROUTINES DATA FIELD + 233 00626 6777 SDRD + 234 00627 0376 AND C70 /GET FIELD FOR XFER + 235 00630 1361 TAD C6201 /FORM CDF N + 236 00631 3251 DCA XFIELD /IF=0 AND DF=N AT XFER. + 237 00632 1047 TAD UNIT /TEST FOR SELECT ERROR + 238 00633 6774 SDLC + 239 00634 7200 CLA / Moved here because my drive 1 is slow selecting + 240 00635 1020 TAD RETRY + 241 00636 3050 DCA TRYCNT /3 ERROR TRIES + 242 00637 6776 SDRC + 243 00640 0364 AND C100 + 244 00641 7640 SZA CLA + 245 00642 5351 JMP FATAL-1 + 246 00643 6777 SDRD /PUT FUNCT INTO XFUNCT IN SECOND PG. + 247 00644 3763 DCA I CXFUN + 248 00645 1023 TAD WCOUNT + 249 00646 3452 DCA I CXWCT + 250 00647 6777 SDRD /GET MOTION BIT TO LINK + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 6 + + + 251 00650 7110 CLL RAR + 252 00651 7402 XFIELD, HLT /INTO NEXT PAGE + 253 00652 5263 JMP GO /AND START THE MOTION. + 254 00653 6772 RWCOM, SDST /ANY CHECKSUM ERRORS? + 255 00654 7640 SZA CLA /OR CHECKSUM ERRORS? + 256 00655 5341 JMP TRY3 /PLEASE NOTE THAT THE LINK IS ALWAYS + 257 /SET AT RWCOM. GETCHK SETS IT. + 258 00656 2051 ISZ PGCT / (DJG) + 259 00657 7410 SKP / (DJG) + 260 00660 5350 JMP EXIT /ALL DONE. GET OUT + 261 00661 2046 ISZ BLOCK /NEXT BLOCK TO XFER + 262 00662 7120 CLL CML /FORCES MOTION FORWARD + 263 00663 7232 GO, CLA CML RTR /LINK BECOMES MOTION BIT + 264 00664 1365 TAD C1000 + 265 00665 1047 TAD UNIT /PUT IN 'GO' AND UNIT # + 266 00666 6774 SDLC /LOOK FOR BLOCK NO. + 267 00667 7200 CLA + 268 00670 1044 TAD XBUFF + 269 00671 3043 DCA OLDBUF + 270 00672 6214 RDF + 271 00673 1361 TAD C6201 + 272 00674 3342 DCA OLDFLD + 273 00675 4762 JMS I CRDQUD /WAIT AT LEAST 6 LINES TO LOOK + 274 00676 4762 JMS I CRDQUD + 275 00677 7600 CM200, 7600 /COULD HAVE SAVED A LOC. HERE + 276 00700 6771 SRCH, SDSS + 277 00701 5300 JMP .-1 /WAIT FOR SINGLE LINE FLAG + 278 00702 6776 SDRC + 279 00703 7106 CLL RTL /DIRECTION TO LINK. INFO BITS + 280 /ARE SHIFTED. + 281 00704 0045 AND C374 /ISOLATE MARK TRACK BITS + 282 00705 1323 TAD M110 /IS IT END ZONE? + 283 00706 7450 SNA /THE LINK STAYS SAME THRU THIS + 284 00707 5331 JMP ENDZ + 285 00710 1053 TAD M20 /CHECK FOR BLOCK MARK + 286 00711 7640 SZA CLA + 287 00712 5300 JMP SRCH + 288 00713 6777 SDRD /GET THE BLOCK NUMBER + 289 00714 7430 SZL /IF WE ARE IN REVERSE, LOOK FOR 3 + 290 /BLOCKS BEFORE TARGET BLOCK. THIS + 291 /ALLOWS TURNAROUND AND UP TO SPEED. + 292 00715 1377 TAD C3 /REVERSE + 293 00716 7040 CMA + 294 00717 1046 TAD BLOCK + 295 00720 7040 CMA /IS IT RIGHT BLOCK? + 296 00721 7450 SNA + 297 00722 5372 JMP FOUND /YES..HOORAY! + 298 00723 7670 M110, SZL SNA CLA /NO, BUT ARE WE HEADED FOR IT? + 299 /ABOVE SNA IS SUPERFLUOUS. + 300 00724 5300 JMP SRCH /YES + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 7 + + + 301 00725 6776 SDRC /NO, TURN US AROUND. + 302 00726 7106 CLL RTL /DIRECTION TO LINK + 303 00727 7200 CLA /THIS CODE USED TO BE SHARED WITH ENDZ, + 304 00730 5263 JMP GO /BUT NOW ENDZ HANDLES END OF TAPE CASES ONLY. + 305 00731 6776 ENDZ, SDRC /WE ARE IN THE END ZONE + 306 00732 7106 CLL RTL /DIRECTION TO LINK + 307 00733 7630 SZL CLA /ARE WE IN REVERSE? + 308 00734 5263 JMP GO /YES..TURN US AROUND + 309 00735 1046 TAD BLOCK /IF WE ARE ON BLOCK ZERO, IT IS POSSIBLE FOR US TO BE AT THE + 310 /REVERSE ENDZONE GOING FORWARD, EITHER DUE TO A RETRY OR BECAUSE + 311 /THE TAPE WAS STARTED IN A POSITION BEFORE THE END ZONE. + 312 /THESE CASES SHOULD NOT BE TREATED AS END-OF-TAPE. + 313 00736 7640 SZA CLA + 314 00737 5353 JMP ENDEX /END OF TAPE. STOP THE UNIT AND TAKE THE END EXIT. + 315 00740 5263 JMP GO + 316 + 317 00741 7200 TRY3, CLA + 318 00742 7000 OLDFLD, NOP + 319 00743 1043 TAD OLDBUF + 320 00744 3044 DCA XBUFF + 321 00745 2050 ISZ TRYCNT + 322 00746 5263 JMP GO /TRY 3 TIMES + 323 00747 5352 JMP FATAL /LINK OFF MEANS AC=4000 ON RETURN + 324 00750 2200 EXIT, ISZ DTA0 /TAKE THE NORMAL RETURN + 325 00751 7120 CLL CML /AC=0 ON NORMAL RETURN + 326 00752 2200 FATAL, ISZ DTA0 /TAKE THE ERROR RETURN + 327 00753 1047 ENDEX, TAD UNIT + 328 00754 6774 SDLC /STOP THE UNIT + 329 00755 7230 CLA CML RAR + 330 00756 7402 LEAVE, HLT + 331 00757 5600 JMP I DTA0 + 332 + 333 + 334 00760 6203 C6203, 6203 + 335 00761 6201 C6201, 6201 + 336 00762 1060 CRDQUD, RDQUAD + 337 00763 1120 CXFUN, XFUNCT + 338 00764 0100 C100, 100 + 339 00765 1000 C1000, 1000 + 340 + 341 + 342 / NOTE THAT THE ABOVE CODE SEGMENT COMES VERY CLOSE TO TOUCHING + 343 / THIS ONE, AND THIS ONE MUST RESIDE AT THE END OF THIS PAGE. + 344 / BE CAREFUL ADDING NEW CODE TO THE ABOVE PAGE. + 345 0772 *ORIGIN+172 + 346 00772 7630 FOUND, SZL CLA /RIGHT BLOCK. HOW ABOUT DIRECTION? + 347 00773 5263 JMP GO /WRONG..TURN AROUND + 348 00774 1047 TAD UNIT /PUT UNIT INTO LINK + 349 00775 7104 CLL RAL /AC IS NOW 0 + 350 00776 0070 C70, 70 /********DON'T MOVE THIS!!!!****** + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 8 + + + 351 00777 0003 C3, 3 + 352 /INTO NEXT PAGE + 353 1000 *ORIGIN+200 + 354 01000 6202 CIF MFIELD + 355 01001 7010 RAR /NOW GET UNIT # + 356 01002 3265 DCA XUNIT + 357 01003 6776 SDRC + 358 01004 6774 SDLC + 359 01005 6771 REVGRD, SDSS + 360 01006 5205 JMP .-1 /LOOK FOR REVERSE GUARD + 361 01007 6776 SDRC + 362 01010 0222 AND K77 + 363 01011 1321 TAD CM32 /IS IT REVERSE GUARD? + 364 01012 7640 SZA CLA + 365 01013 5205 JMP REVGRD /NO.KEEP LOOKING + 366 01014 1325 TAD XWCT + 367 01015 3324 DCA WORDS /WORD COUNTER + 368 01016 1320 TAD XFUNCT /GET FUNCTION READ OR WRITE + 369 01017 7700 K7700, SMA CLA + 370 01020 5223 JMP READ /NEG. IS WRITE + 371 01021 7402 WRITE, HLT /WRITE CODE REMOVED + 372 01022 0077 K77, 77 /ABOVE MAY SKIP (NOT ANYMORE DJG) + 373 01023 4260 READ, JMS RDQUAD + 374 01024 4260 JMS RDQUAD + 375 01025 4260 JMS RDQUAD /SKIP CONTROL WORDS + 376 01026 0222 AND K77 + 377 01027 1217 TAD K7700 /TACK 7700 ONTO CHECKSUM. + 378 01030 3323 DCA CHKSUM /CHECKSUM ONLY LOW 6 BITS ANYWAY + 379 01031 4260 RDLP, JMS RDQUAD + 380 01032 4265 JMS EQUFUN /COMPUT CHECKSUM AS WE GO + 381 01033 3444 DCA I XBUFF /IT GETS CONDENSED LATER + 382 01034 2044 ISZ XBUFF /AT END OF FIELD? + 383 01035 5242 JMP STFLD2+1 /NOT AT END OF FIELD (DJG) + 384 01036 6214 RDF + 385 01037 1377 TAD (6211 + 386 01040 3241 DCA STFLD2 + 387 01041 7000 STFLD2, NOP + 388 01042 2324 ISZ WORDS /DONE THIS OP? + 389 01043 5231 JMP RDLP /NO SUCH LUCK + 390 01044 1320 TAD XFUNCT /IF OP WAS FOR WDSBLK-1, READ AND + 391 01045 7112 CLL RTR /CHECKSUM THE LAST TAPE WORD + 392 01046 7620 SNL CLA + 393 01047 5252 JMP RDLP2 + 394 01050 4260 JMS RDQUAD /NOT NEEDED FOR WDSBLK/BLOCK + 395 01051 4265 JMS EQUFUN /CHECKSUM IT + 396 01052 4260 RDLP2, JMS RDQUAD /READ CHECKSUM + 397 01053 0217 AND K7700 + 398 01054 4265 JMS EQUFUN + 399 01055 4302 JMS GETCHK /GET SIX BIT CHECKSUM + 400 01056 5717 JMP I CRWCOM + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 9 + + + 401 01057 0300 C300, 300 /PROTECTION (NOT ANYMORE DJG) + 402 + 403 01060 0000 RDQUAD, 0 /READ A 12 BIT WORD + 404 01061 6773 SDSQ + 405 01062 5261 JMP .-1 + 406 01063 6777 SDRD /READ DATA + 407 01064 5660 JMP I RDQUAD + 408 + 409 XUNIT, + 410 01065 0000 EQUFUN, 0 /COMPUTE EQUIVALENCE CHECKSUM + 411 01066 7040 CMA + 412 01067 3326 DCA EQUTMP /ACTUALLY CHECKSUMS ON DECTAPE ARE + 413 01070 1326 TAD EQUTMP /EQUIVALENCE OF ALL WORDS IN A RECORD + 414 01071 0323 AND CHKSUM /SIX BITS AT A TIME. BUT SINCE EQUIVALENCE + 415 01072 7041 CIA /IS ASSOCIATIVE, WE CAN DO IT 12 + 416 01073 7104 CLL RAL /BITS AT A TIME AND CONDENSE LATER. + 417 01074 1326 TAD EQUTMP /THIS ROUTINE USES THESE IDENTITIES: + 418 01075 1323 TAD CHKSUM /A+B=(A.XOR.B)+2*(A.AND.B) + 419 01076 3323 DCA CHKSUM /A.EQU.B=.NOT.(A.XOR.B)=A.XOR.(.NOT.B) + 420 01077 1326 TAD EQUTMP /A.EQU.B=(A+(.NOT.B))-2*(A.AND.(.NOT.B)) + 421 01100 7040 CMA + 422 01101 5665 JMP I EQUFUN + 423 + 424 01102 0000 GETCHK, 0 /FORM 6 BIT CHECKSUM + 425 01103 7200 CLA + 426 01104 1323 TAD CHKSUM + 427 01105 7040 CMA + 428 01106 7106 CLL RTL + 429 01107 7006 RTL + 430 01110 7006 RTL + 431 01111 4265 JMS EQUFUN + 432 01112 7320 CLA CLL CML /FORCES LINK ON AT RWCOM + 433 01113 1323 TAD CHKSUM + 434 01114 0217 AND K7700 + 435 01115 5702 JMP I GETCHK + 436 + 437 01116 0752 CFATAL, FATAL + 438 01117 0653 CRWCOM, RWCOM + 439 01120 0000 XFUNCT, 0 + 440 01121 7746 CM32, -32 + 441 01122 1400 C1400, 1400 + 442 01123 0000 CHKSUM, 0 + 443 01124 0000 WORDS, 0 + 444 01125 0000 XWCT, 0 + 445 01126 0000 EQUTMP, 0 + 446 + 01177 6211 + 447 0020 *20 + 448 00020 7774 RETRY, 7774 / RETRY UP TO 4 TIME + 449 00021 3777 NUMBLK, 3777 / MAX NUMBER OF BLOCKS TO ATTEMPT READING. BY DEFAULT THIS PROGRAM WILL READ UNTIL + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 10 + + + 450 / IT HITS THE END OF THE TAPE (FORWARD ENDZONE). IF YOU NEED TO LIMIT THE NUMBER OF BLOCKS + 451 / READ, MODIFY THIS VALUE. + 452 00022 7577 MWORDS, -WDSBLK / WORDS PER BLOCK + 453 00023 0000 WCOUNT, 0 + 454 00024 0036 BLKFLD, 36 / 30 129 WORD BLOCKS OF 12-BIT WORDS + 455 / WRAPPING PAST END OF LAST FIELD DOESN'T WORK + 456 00025 0000 FIELDS, 0 + 457 00026 0000 RDSIZE, 0 / NUMBER BLOCKS PER READ + 458 00027 0000 CBLOCK, 0 / CURRENT BLOCK TO XFER + 459 00030 0000 CLKSUM, 0 + 460 00031 0000 DRVSEL, 0 + 461 00032 0377 READST, 377 + 462 00033 0000 LOC, 0 + 463 00034 0000 LEN, 0 + 464 00035 0000 BCNT, 0 / BLOCKS TO SEND TO PC + 465 00036 0000 TEMP, 0 + 466 00037 0017 C17, 17 + 467 00040 0360 C360, 360 + 468 00041 0000 CHKSM, 0 + 469 00042 0000 ERRCN2, 0 + 470 00043 0000 OLDBUF, 0 / BELOW ARE USED BY DTA0 ROUTINE + 471 00044 0000 XBUFF, 0 + 472 00045 0374 C374, 374 + 473 00046 0000 BLOCK, 0 + 474 00047 0000 UNIT, 0 + 475 00050 7775 TRYCNT, -3 + 476 00051 0000 PGCT, 0 + 477 00052 1125 CXWCT, XWCT + 478 00053 7760 M20, -20 + 479 + 480 0140 *140 + 481 00140 7402 FINISH, HLT / Normal good halt + 482 00141 5777@ JMP START + 483 + 484 0200 *200 + 485 00200 6201 START, CDF 0 + 486 00201 6007 CAF + 487 00202 7704 CLA CLL OSR / Get drive + 488 00203 0377 AND (1 + 489 00204 7012 RTR + 490 00205 3031 DCA DRVSEL + 491 00206 7704 CLA CLL OSR / Get max field + 492 00207 7012 RTR + 493 00210 7010 RAR + 494 00211 0376 AND (7 + 495 00212 7450 SNA + 496 00213 7402 HLT / Must have at least 1 field for buffer + 497 00214 7041 CIA + 498 00215 3025 DCA FIELDS + 499 00216 3042 DCA ERRCN2 + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 11 + + + 500 00217 1024 RDSZLP, TAD BLKFLD / Multiply by number of fields available + 501 00220 2025 ISZ FIELDS + 502 00221 5217 JMP RDSZLP + 503 00222 3026 DCA RDSIZE / NUMBER BLOCK PER READ + 504 00223 3027 DCA CBLOCK + 505 00224 3041 DCA CHKSM + 506 + 507 00225 7200 DUMPLP, CLA + 508 00226 1026 TAD RDSIZE + 509 00227 1027 TAD CBLOCK + 510 00230 7041 CIA + 511 00231 1021 TAD NUMBLK / MORE BLOCKS LEFT THAN READSIZE? + 512 00232 7500 SMA / NO, READ NUMBER LEFT + 513 00233 7200 CLA / YES, ONLY READ RDSIZE + 514 00234 1026 TAD RDSIZE + 515 00235 7450 SNA / ANY MORE BLOCKS? + 516 00236 5270 JMP DONE / NO, DO FINISH STUFF + 517 00237 3245 DCA ARGSZ + 518 00240 1027 TAD CBLOCK + 519 00241 3247 DCA ARGBK + 520 00242 1031 TAD DRVSEL + 521 00243 4775@ JMS DTA0 + 522 00244 0010 0010 / READ STARTING IN FIELD 1 + 523 00245 0000 ARGSZ, 0 + 524 00246 0000 0 + 525 00247 0000 ARGBK, 0 + 526 00250 5774@ JMP ENDRET / TAKEN WHEN END OF TAPE IS HIT + 527 00251 5323 JMP ERRRET / TAKEN WHEN AN ERROR IS ENCOUNTERED + 528 00252 1373 TAD (377 / All blocks good + 529 00253 3032 DCA READST + 530 / Send data, each block starts with FF + 531 00254 7300 CLA CLL / then 2 12 bit words in 3 bytes + 532 00255 3033 DCA LOC / ERRRET DUPLICATES SOME OF THIS + 533 00256 1245 TAD ARGSZ + 534 00257 7041 CIA + 535 00260 3035 DCA BCNT / Setup loop counter with number blocks read + 536 00261 6211 CDF 10 + 537 00262 4772@ OUTBL1, JMS OUTBLK / Send a block + 538 00263 2027 ISZ CBLOCK + 539 00264 2035 ISZ BCNT / Send all read? + 540 00265 5262 JMP OUTBL1 / No + 541 00266 6201 CDF 0 + 542 00267 5225 JMP DUMPLP / Go read next batch + 543 + 544 + 545 00270 7200 DONE, CLA / Send FE and -checksum of all words + 546 00271 1371 TAD (376 + 547 00272 4770@ JMS PUN + 548 00273 7300 CLA CLL + 549 00274 1041 TAD CHKSM / Send checksum in two bytes, low bits first + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 12 + + + 550 00275 7041 CIA + 551 00276 4770@ JMS PUN + 552 00277 7300 CLA CLL + 553 00300 1041 TAD CHKSM + 554 00301 7041 CIA + 555 00302 7012 RTR + 556 00303 7012 RTR + 557 00304 7012 RTR + 558 00305 7012 RTR + 559 00306 0037 AND C17 + 560 00307 4770@ JMS PUN + 561 00310 7200 CLA + 562 00311 1031 TAD DRVSEL + 563 00312 4775@ JMS DTA0 / REWIND TAPE + 564 00313 0010 0010 + 565 00314 0001 1 + 566 00315 0000 0 + 567 00316 0000 0 + 568 00317 7000 NOP + 569 00320 7000 NOP + 570 00321 1042 TAD ERRCN2 / Leave AC with # of errors + 571 00322 5140 JMP FINISH + 572 + 573 /SEND GOOD BLOCKS READ WITH GOOD BLOCK FLAG + 574 /THEN BAD WITH BAD BLOCK FLAG. + 575 ERRRET, + 576 / HLT / ****** If we want to stop on error + 577 00323 6211 CDF 10 + 578 00324 7300 CLA CLL + 579 00325 3033 DCA LOC + 580 00326 1027 TAD CBLOCK + 581 00327 7041 CIA + 582 00330 1046 TAD BLOCK /Get - number good blocks read + 583 00331 7041 CIA /Last was bad + 584 00332 7450 SNA + 585 00333 5343 JMP FSTBAD /First block is bad, no good to send + 586 00334 3035 DCA BCNT + 587 00335 1373 TAD (377 + 588 00336 3032 DCA READST + 589 00337 4772@ OUTBL2, JMS OUTBLK /Send good blocks + 590 00340 2027 ISZ CBLOCK + 591 00341 2035 ISZ BCNT + 592 00342 5337 JMP OUTBL2 + 593 00343 1367 FSTBAD, TAD (375 /NOW SEND BAD BLOCK + 594 00344 3032 DCA READST + 595 00345 4772@ JMS OUTBLK + 596 00346 2027 ISZ CBLOCK + 597 00347 2042 ISZ ERRCN2 + 598 00350 6201 CDF 0 + 599 00351 5225 JMP DUMPLP /And read from here on + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 13 + + + 600 + 00367 0375 + 00370 0511 + 00371 0376 + 00372 0422 + 00373 0377 + 00374 0400 + 00375 0600 + 00376 0007 + 00377 0001 + 601 PAGE + 602 ENDRET, /SEND LAST SET OF BLOCKS READ BEFORE END OF TAPE AND FINISH. + 603 00400 6211 CDF 10 + 604 00401 7300 CLA CLL + 605 00402 3033 DCA LOC + 606 00403 1027 TAD CBLOCK + 607 00404 7041 CIA + 608 00405 1046 TAD BLOCK / GET NUMBER OF BLOCKS READ IN LAST BATCH + 609 00406 7040 CMA / +1 to -BCNT SO WE SEND ALL BLOCKS + 610 00407 7450 SNA + 611 00410 5777@ JMP DONE / READ ZERO BLOCKS IN LAST BATCH, WE ARE DONE + 612 00411 3035 DCA BCNT + 613 00412 1376 TAD (377 + 614 00413 3032 DCA READST + 615 00414 4222 OUTBL3, JMS OUTBLK / SEND ALL BLOCKS + 616 00415 2027 ISZ CBLOCK + 617 00416 2035 ISZ BCNT + 618 00417 5214 JMP OUTBL3 + 619 00420 6201 CDF 0 + 620 00421 5777@ JMP DONE / NO MORE BLOCKS, DONE. + 621 + 622 00422 0000 OUTBLK, 0 /Send a block of data out serial port + 623 00423 7200 CLA + 624 00424 1023 TAD WCOUNT + 625 00425 3034 DCA LEN + 626 00426 1032 TAD READST /Send good/bad flag + 627 00427 4311 JMS PUN + 628 00430 7300 OUT, CLA CLL + 629 00431 1433 TAD I LOC + 630 00432 1041 TAD CHKSM / Keep checksum of all words sent + 631 00433 3041 DCA CHKSM + 632 00434 1433 TAD I LOC / Send 2 words as 3 bytes + 633 00435 4311 JMS PUN + 634 00436 7300 CLA CLL + 635 00437 1433 TAD I LOC + 636 00440 7012 RTR / Shift top 4 bits to low 4 + 637 00441 7012 RTR + 638 00442 7012 RTR + 639 00443 7012 RTR + 640 00444 0037 AND C17 + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 14 + + + 641 00445 3036 DCA TEMP + 642 00446 2033 ISZ LOC + 643 00447 5254 JMP STFLD3+1 /NOT AT END OF FIELD (DJG) + 644 00450 6214 RDF /At end, inc to next field + 645 00451 1375 TAD (6211 /BUILD CDF + 646 00452 3253 DCA STFLD3 + 647 00453 7000 STFLD3, NOP + 648 00454 2034 ISZ LEN /END OF BUFFER? + 649 00455 7410 SKP /NO + 650 00456 5306 JMP ENDBK /YES + 651 00457 1433 TAD I LOC + 652 00460 1041 TAD CHKSM + 653 00461 3041 DCA CHKSM + 654 00462 1433 TAD I LOC + 655 00463 7006 RTL + 656 00464 7006 RTL + 657 00465 0040 AND C360 + 658 00466 1036 TAD TEMP + 659 00467 4311 JMS PUN + 660 00470 7300 CLA CLL + 661 00471 1433 TAD I LOC + 662 00472 7012 RTR + 663 00473 7012 RTR + 664 00474 4311 JMS PUN + 665 00475 2033 ISZ LOC + 666 00476 5303 JMP STFLD4+1 /NOT AT END OF FIELD (DJG) + 667 00477 6214 RDF + 668 00500 1375 TAD (6211 /BUILD CDF + 669 00501 3302 DCA STFLD4 + 670 00502 7000 STFLD4, NOP + 671 00503 2034 ISZ LEN + 672 00504 5230 JMP OUT + 673 00505 5622 JMP I OUTBLK + 674 00506 1036 ENDBK, TAD TEMP /SEND LAST PART OF WORD + 675 00507 4311 JMS PUN + 676 00510 5622 JMP I OUTBLK + 677 + 678 00511 0000 PUN, 0 / Send byte out serial port + 679 / PLS / Punch for testing with emulator + 680 00512 6046 TLS2 / Send out console + 681 00513 7300 CLA CLL + 682 00514 1027 TAD CBLOCK + 683 / PSF + 684 00515 6041 TSF2 /Wait until character sent + 685 00516 5315 JMP .-1 + 686 00517 7200 CLA + 687 00520 5711 JMP I PUN + 688 + 00575 6211 + 00576 0377 + + + + / TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code fro Page 15 + + + 00577 0270 + 00177 0200 + 689 $ + + No detected errors + 12 links generated diff --git a/DumpDT18/dumpdt12.pal b/DumpDT18/dumpdt12.pal new file mode 100644 index 0000000..14207c6 --- /dev/null +++ b/DumpDT18/dumpdt12.pal @@ -0,0 +1,689 @@ +/ TD8E 12-bit DECtape DUMP Program. Based on DUMPREST code from D. Gesswein +/ (see ftp://ftp.pdp8online.com/software/dumprest). +/ Modified to handle arbitrary-length tapes by J. Dersch +/ +/ This program will send a DECtape image out the console port. +/ The format of the data sent is 0xff (0377) or 0xfd if read error +/ followed by 129 12-bit words of data for each block. +/ After the last block a 0xfe (0376) is sent +/ with a two byte checksum, low 8 bits first then upper 4. +/ The words in a block are sent as three bytes for each 2 words. +/ 1 = low 8 bits first word +/ 2 = upper 4 bits first and lower 4 bits second +/ 3 = upper 8 bits second word +/ +/ The program (PC) receiving the data should be started before this program. +/ +/ To run, start at 0200. +/ SR 11 should be drive, only 0 and 1 supported without reassembling +/ SR 6-8 should be maximum memory field in computer, needs 8k minimum +/ +/ The receiving program should be running first. +/ At normal exit hitting cont will restart the program. +/ +/ Should halt at label finish (140) with number of recoverable errors in AC +/ The current block being read will be displayed in the AC +/ while running. +/ +/ The PC program will print out the bad location if an error occurs. +/ +/ We will retry each read up to four times on error. +/ +/ This transfers the standard 129 word by 1474 blocks used by 12-bit DEC hardware, +/ using standard checksums (as used by the PDP-9 and later machines). +/ It will read as many blocks are present up to the forward end-zone, so it will +/ handle tapes that vary from the standard block length. +/ + INAD=030 / Address of serial input, 30 for console + KCF2=6000 INAD + KSF2=6001 INAD + KCC2=6002 INAD + KRS2=6004 INAD + KIE2=6005 INAD + KRB2=6006 INAD + + OUTAD=040 / Address of serial output, 40 for console + TFL2=6000 OUTAD + TSF2=6001 OUTAD + TCF2=6002 OUTAD + TPC2=6004 OUTAD + TSK2=6005 OUTAD + TLS2=6006 OUTAD + + +/CODE BASED ON: +/2 TD8E INITIALIZER PROGRAM, V7A +/ +/COPYRIGHT (C) 1975, 1977 +/DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. +/ +/ +/ +/THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A +/SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE INCLU- +/SION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ANT OTHER +/COPIES THEREOF, MAY NOT BR PROVIDED OR OTHERWISE MADE AVAILABLE +/TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO +/AGREES TO THESE LICENSE TERMS. TITLE TO AND OWNERSHIP OF THE +/SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC. +/ +/ +/THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT +/NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL +/EQUIPMRNT COROPATION. +/ +/DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS +/SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. +/ +/ +/ +/ +/ +/ + +/DECEMBER 21, 1973 GB/RL/EF/SR + +/ABSTRACT-- +/ THE ROUTINE DESCRIBED AND LISTED HERE IS A GENERAL +/DATA HANDLER FOR THE TD8E DECTAPE SYSTEM. THE ROUTINE +/CONTAINS SEARCH, READ, AND WRITE FUNCTIONS IN A FORMAT +/WHICH IS COMPATIBLE WITH OS/8 DEVICE HANDLER CALLING +/SEQUENCES. + +/FIXES SINCE FIELD-TEST RELEASE: + +/1. FIXED BUG RE CLA ON RETRY AFTER ERROR +/2. ALLOWED FINAL BOOTSTRAP TO BE INTO A WRITE-LOCKED DEVICE + +/OS/8 V3D CHANGES: + +/3. FIXED BUG RE TD8E BUILD (V6B PATCH) + +/THIS ROUTINE CAN BE RE-EDITED AND ASSEMBLED TO PRODUCE +/VARIATIONS ON THE BASIC TD8E SYSTEM. ASSEMBLY PARAMETERS +/CONTROL: +/A) WHAT DRIVES (UNITS 0-7) WILL BE USED +/B) THE ORIGIN OF THE TWO PAGE ROUTINE +/C) WHAT MEMORY FIELD THE ROUTINE WILL RUN IN +/D) THE SIZE OF THE DECTAPE BLOCK TO BE READ/WRITTEN + +/FOLLOWING ARE THE PARAMETERS SET UP FOR THE STANDARD +/DEC VERSION OF THIS ROUTINE: + + DRIVE=10 /UNITS 0 AND 1 SELECTED + ORIGIN=600 /ENTER AT ORIGIN, ORIGIN+4 + AFIELD=0 /INITIAL FIELD SETTING + MFIELD=00 /AFIELD*10=MFIELD + WDSBLK=201 /129 12-BIT WORDS PER BLOCK + +/THE USE OF THE PARAMETERS IS AS FOLLOWS: + +/ DRIVE: DRIVE DETERMINES WHICH UNITS WILL BE SELECTED +/ DRIVE=10 IMPLIES UNITS 0 &1 +/ DRIVE=20 IMPLIES UNITS 2&3 +/ DRIVE=30 IMPLIES UNITS 4&5 +/ DRIVE=40 IMPLIES UNITS 6&7 + +/ORIGIN: ALTERING ORIGIN CAUSES ASSEMBLY IN A DIFFERENT +/ MEMORY LOCATION. WHEN CHANGING ORIGIN KEEP IN MIND +/THAT THIS IS A TWO PAGE ROUTINE. + +/AFIELD: AFIELD DETERMINES THE INITIAL FIELD SETTING FOR THE +/ LOADER. PERMISSIBLE VALUES FOR AFIELD ARE 0 TO 7. + +/MFIELD: MFIELD IS USED IN A CIF CDF MFIELD INSTRUCTION. +/ THE VALUE INSERTED FOR MFIELD SHOULD BE 10(8) TIMES +/ THE VALUE FOR AFIELD. THE PERMISSIBLE VALUES ARE 00-70. + +/WDSBLK: WDSBLK GOVERNS HOW MANY WORDS THE ROUTINE THINKS ARE +/ IN A DECTAPE BLOCK. THE STANDARD VALUE IS 201(8) OR +/ 128 DECIMAL. NOTE THAT THE FUNCTION WORD BIT 10 CAN +/ 129 DECIMAL ??? (DJG) +/ BE USED TO SUBTRACT ONE FROM WDSBLK. THE VALUE USED +/ FOR WDSBLK SHOULD BE THE NUMBER OF WORDS THE TAPE WAS +/ FORMATTED TO CONTAIN. + +/IF WE WANT A HANDLER FOR UNITS 2&3 TO RESIDE IN +/FIELD 2 AT LOCATION 3000 AND READ/WRITE 256(10) WORDS +/PER BLOCK, THE PARAMETERS WOULD BE: +/ DRIVE=20 +/ ORIGIN=3000 +/ AFIELD=2 +/ MFIELD=20 +/ WDSBLK=400 + /THE CALL TO THE SUBROUTINE FOLLOWS BASICALLY THE +/CALLING SEQUENCE FOR OS/8 DEVICE HANDLERS. +/THE CALLING SEQUENCE IS: + +/ CDF CURRENT +/ CIF MFIELD /MFIELD=FIELD ASSEMBLED IN +/ JMS ENTRY /ENTRY=ORIGIN (EVEN NUMBERED DRIVE + /AND ORIGIN+4 FOR ODD NUMBERED DRIVE. +/ ARG1 +/ ARG1B (DJG) +/ ARG2 +/ ARG3 +/ ERROR RETURN +/ NORMAL RETURN + +/THE ARGUMENTS ARE: + +/ARG1: FUNCTION WORD BIT0: 0=READ, 1=WRITE +/ BITS 1-5: UNUSED, WAS # BLOCKS IN OPERATION (DJG) +/ BITS 6-8: FIELD OF BUFFER AREA +/ BIT 9: UNUSED +/ BIT 10: # OF WORDS/BLOCK. +/ 0= WDSBLK, 1=WDSBLK-1 +/ BIT 11: 1=START FORWARD, 0=REVERSE +/ARG1A: # OF BLOCKS IN OPERATIONA (DJG) +/ARG2: BUFFER ADDRESS FOR OPERATION +/ARG3: STARTING BLOCK FOR OPERATION + +/ERRORS: THE HANDLER DETECTS TWO TYPES OF ERRORS: +/A) FATAL ERRORS- PARITY ERROR, TIMING ERROR, +/ TOO GREAT A BLOCK NUMBER +/ FATAL ERRORS TAKE ERROR RETURN WITH THE +/ AC=4000. +/B) NON-FATAL- SELECT ERROR. +/ IF NO PROPER UNIT IS SELECTED, THE ERROR +/ RETURN IS TAKEN WITH CLEAR AC. +/FATAL ERRORS TRY THREE TIMES BEFORE TAKING ERROR RETURN. +/THE NORMAL RETURN IS TAKEN AFTER ALL INDICATED +/BLOCKS HAVE BEEN TRANSFERRED. THE AC IS CLEAR. + +/THE TD8E IOT'S ARE: + SDSS=7001-DRIVE /SKIP ON SINGLE LINE FLAG + SDST=7002-DRIVE /SKIP ON TIMING ERROR + SDSQ=7003-DRIVE /SKIP ON QUAD LINE FLAG + SDLC=7004-DRIVE /LOAD COMMAND REGISTER + SDLD=7005-DRIVE /LOAD DATA REGISTER + SDRC=7006-DRIVE /READ COMMAND REGISTER + SDRD=7007-DRIVE /READ DATA REGISTER + +/THE IOT'S IN GENERAL ARE 677X,676X,675X,AND 674X. +/THE OTHERS CONTROL UNITS 2-7. + +/ THIS HANDLER USES DECTAPE BLOCKS NOT OS/8 BLOCKS ! + + *ORIGIN + +/ MODIFIED SO BIT 0 ON ENTRY IS UNIT 1 +DTA0, 0 + DCA UNIT /SAVE UNIT POSITION + RDF + TAD C6203 /GET DATA FIELD AND SETUP RETURN + DCA LEAVE + TAD I DTA0 /GET FUNCTION WORD + SDLD /PUT FUNCTION INTO DATA REGISTER + CLA + TAD MWORDS + DCA WCOUNT /STORE MASTER WORD COUNT + ISZ DTA0 /TO BLOCK COUNT (DJG) + TAD I DTA0 / (DJG) + CIA / (DJG) + DCA PGCT / (DJG) + ISZ DTA0 /TO BUFFER + TAD I DTA0 + DCA XBUFF /SAVE ADDRESS (DJG) + ISZ DTA0 /TO BLOCK NUMBER + TAD I DTA0 + DCA BLOCK + ISZ DTA0 /POINT TO ERROR EXIT + CIF CDF MFIELD /TO ROUTINES DATA FIELD + SDRD + AND C70 /GET FIELD FOR XFER + TAD C6201 /FORM CDF N + DCA XFIELD /IF=0 AND DF=N AT XFER. + TAD UNIT /TEST FOR SELECT ERROR + SDLC + CLA / Moved here because my drive 1 is slow selecting + TAD RETRY + DCA TRYCNT /3 ERROR TRIES + SDRC + AND C100 + SZA CLA + JMP FATAL-1 + SDRD /PUT FUNCT INTO XFUNCT IN SECOND PG. + DCA I CXFUN + TAD WCOUNT + DCA I CXWCT + SDRD /GET MOTION BIT TO LINK + CLL RAR +XFIELD, HLT /INTO NEXT PAGE + JMP GO /AND START THE MOTION. +RWCOM, SDST /ANY CHECKSUM ERRORS? + SZA CLA /OR CHECKSUM ERRORS? + JMP TRY3 /PLEASE NOTE THAT THE LINK IS ALWAYS + /SET AT RWCOM. GETCHK SETS IT. + ISZ PGCT / (DJG) + SKP / (DJG) + JMP EXIT /ALL DONE. GET OUT + ISZ BLOCK /NEXT BLOCK TO XFER + CLL CML /FORCES MOTION FORWARD +GO, CLA CML RTR /LINK BECOMES MOTION BIT + TAD C1000 + TAD UNIT /PUT IN 'GO' AND UNIT # + SDLC /LOOK FOR BLOCK NO. + CLA + TAD XBUFF + DCA OLDBUF + RDF + TAD C6201 + DCA OLDFLD + JMS I CRDQUD /WAIT AT LEAST 6 LINES TO LOOK + JMS I CRDQUD +CM200, 7600 /COULD HAVE SAVED A LOC. HERE +SRCH, SDSS + JMP .-1 /WAIT FOR SINGLE LINE FLAG + SDRC + CLL RTL /DIRECTION TO LINK. INFO BITS + /ARE SHIFTED. + AND C374 /ISOLATE MARK TRACK BITS + TAD M110 /IS IT END ZONE? + SNA /THE LINK STAYS SAME THRU THIS + JMP ENDZ + TAD M20 /CHECK FOR BLOCK MARK + SZA CLA + JMP SRCH + SDRD /GET THE BLOCK NUMBER + SZL /IF WE ARE IN REVERSE, LOOK FOR 3 + /BLOCKS BEFORE TARGET BLOCK. THIS + /ALLOWS TURNAROUND AND UP TO SPEED. + TAD C3 /REVERSE + CMA + TAD BLOCK + CMA /IS IT RIGHT BLOCK? + SNA + JMP FOUND /YES..HOORAY! +M110, SZL SNA CLA /NO, BUT ARE WE HEADED FOR IT? + /ABOVE SNA IS SUPERFLUOUS. + JMP SRCH /YES + SDRC /NO, TURN US AROUND. + CLL RTL /DIRECTION TO LINK + CLA /THIS CODE USED TO BE SHARED WITH ENDZ, + JMP GO /BUT NOW ENDZ HANDLES END OF TAPE CASES ONLY. +ENDZ, SDRC /WE ARE IN THE END ZONE + CLL RTL /DIRECTION TO LINK + SZL CLA /ARE WE IN REVERSE? + JMP GO /YES..TURN US AROUND + TAD BLOCK /IF WE ARE ON BLOCK ZERO, IT IS POSSIBLE FOR US TO BE AT THE + /REVERSE ENDZONE GOING FORWARD, EITHER DUE TO A RETRY OR BECAUSE + /THE TAPE WAS STARTED IN A POSITION BEFORE THE END ZONE. + /THESE CASES SHOULD NOT BE TREATED AS END-OF-TAPE. + SZA CLA + JMP ENDEX /END OF TAPE. STOP THE UNIT AND TAKE THE END EXIT. + JMP GO + +TRY3, CLA +OLDFLD, NOP + TAD OLDBUF + DCA XBUFF + ISZ TRYCNT + JMP GO /TRY 3 TIMES + JMP FATAL /LINK OFF MEANS AC=4000 ON RETURN +EXIT, ISZ DTA0 /TAKE THE NORMAL RETURN + CLL CML /AC=0 ON NORMAL RETURN +FATAL, ISZ DTA0 /TAKE THE ERROR RETURN +ENDEX, TAD UNIT + SDLC /STOP THE UNIT + CLA CML RAR +LEAVE, HLT + JMP I DTA0 + + +C6203, 6203 +C6201, 6201 +CRDQUD, RDQUAD +CXFUN, XFUNCT +C100, 100 +C1000, 1000 + + + / NOTE THAT THE ABOVE CODE SEGMENT COMES VERY CLOSE TO TOUCHING + / THIS ONE, AND THIS ONE MUST RESIDE AT THE END OF THIS PAGE. + / BE CAREFUL ADDING NEW CODE TO THE ABOVE PAGE. + *ORIGIN+172 +FOUND, SZL CLA /RIGHT BLOCK. HOW ABOUT DIRECTION? + JMP GO /WRONG..TURN AROUND + TAD UNIT /PUT UNIT INTO LINK + CLL RAL /AC IS NOW 0 +C70, 70 /********DON'T MOVE THIS!!!!****** +C3, 3 + /INTO NEXT PAGE + *ORIGIN+200 + CIF MFIELD + RAR /NOW GET UNIT # + DCA XUNIT + SDRC + SDLC +REVGRD, SDSS + JMP .-1 /LOOK FOR REVERSE GUARD + SDRC + AND K77 + TAD CM32 /IS IT REVERSE GUARD? + SZA CLA + JMP REVGRD /NO.KEEP LOOKING + TAD XWCT + DCA WORDS /WORD COUNTER + TAD XFUNCT /GET FUNCTION READ OR WRITE +K7700, SMA CLA + JMP READ /NEG. IS WRITE +WRITE, HLT /WRITE CODE REMOVED +K77, 77 /ABOVE MAY SKIP (NOT ANYMORE DJG) +READ, JMS RDQUAD + JMS RDQUAD + JMS RDQUAD /SKIP CONTROL WORDS + AND K77 + TAD K7700 /TACK 7700 ONTO CHECKSUM. + DCA CHKSUM /CHECKSUM ONLY LOW 6 BITS ANYWAY +RDLP, JMS RDQUAD + JMS EQUFUN /COMPUT CHECKSUM AS WE GO + DCA I XBUFF /IT GETS CONDENSED LATER + ISZ XBUFF /AT END OF FIELD? + JMP STFLD2+1 /NOT AT END OF FIELD (DJG) + RDF + TAD (6211 + DCA STFLD2 +STFLD2, NOP + ISZ WORDS /DONE THIS OP? + JMP RDLP /NO SUCH LUCK + TAD XFUNCT /IF OP WAS FOR WDSBLK-1, READ AND + CLL RTR /CHECKSUM THE LAST TAPE WORD + SNL CLA + JMP RDLP2 + JMS RDQUAD /NOT NEEDED FOR WDSBLK/BLOCK + JMS EQUFUN /CHECKSUM IT +RDLP2, JMS RDQUAD /READ CHECKSUM + AND K7700 + JMS EQUFUN + JMS GETCHK /GET SIX BIT CHECKSUM + JMP I CRWCOM +C300, 300 /PROTECTION (NOT ANYMORE DJG) + +RDQUAD, 0 /READ A 12 BIT WORD + SDSQ + JMP .-1 + SDRD /READ DATA + JMP I RDQUAD + +XUNIT, +EQUFUN, 0 /COMPUTE EQUIVALENCE CHECKSUM + CMA + DCA EQUTMP /ACTUALLY CHECKSUMS ON DECTAPE ARE + TAD EQUTMP /EQUIVALENCE OF ALL WORDS IN A RECORD + AND CHKSUM /SIX BITS AT A TIME. BUT SINCE EQUIVALENCE + CIA /IS ASSOCIATIVE, WE CAN DO IT 12 + CLL RAL /BITS AT A TIME AND CONDENSE LATER. + TAD EQUTMP /THIS ROUTINE USES THESE IDENTITIES: + TAD CHKSUM /A+B=(A.XOR.B)+2*(A.AND.B) + DCA CHKSUM /A.EQU.B=.NOT.(A.XOR.B)=A.XOR.(.NOT.B) + TAD EQUTMP /A.EQU.B=(A+(.NOT.B))-2*(A.AND.(.NOT.B)) + CMA + JMP I EQUFUN + +GETCHK, 0 /FORM 6 BIT CHECKSUM + CLA + TAD CHKSUM + CMA + CLL RTL + RTL + RTL + JMS EQUFUN + CLA CLL CML /FORCES LINK ON AT RWCOM + TAD CHKSUM + AND K7700 + JMP I GETCHK + +CFATAL, FATAL +CRWCOM, RWCOM +XFUNCT, 0 +CM32, -32 +C1400, 1400 +CHKSUM, 0 +WORDS, 0 +XWCT, 0 +EQUTMP, 0 + + *20 +RETRY, 7774 / RETRY UP TO 4 TIME +NUMBLK, 3777 / MAX NUMBER OF BLOCKS TO ATTEMPT READING. BY DEFAULT THIS PROGRAM WILL READ UNTIL + / IT HITS THE END OF THE TAPE (FORWARD ENDZONE). IF YOU NEED TO LIMIT THE NUMBER OF BLOCKS + / READ, MODIFY THIS VALUE. +MWORDS, -WDSBLK / WORDS PER BLOCK +WCOUNT, 0 +BLKFLD, 36 / 30 129 WORD BLOCKS OF 12-BIT WORDS + / WRAPPING PAST END OF LAST FIELD DOESN'T WORK +FIELDS, 0 +RDSIZE, 0 / NUMBER BLOCKS PER READ +CBLOCK, 0 / CURRENT BLOCK TO XFER +CLKSUM, 0 +DRVSEL, 0 +READST, 377 +LOC, 0 +LEN, 0 +BCNT, 0 / BLOCKS TO SEND TO PC +TEMP, 0 +C17, 17 +C360, 360 +CHKSM, 0 +ERRCN2, 0 +OLDBUF, 0 / BELOW ARE USED BY DTA0 ROUTINE +XBUFF, 0 +C374, 374 +BLOCK, 0 +UNIT, 0 +TRYCNT, -3 +PGCT, 0 +CXWCT, XWCT +M20, -20 + + *140 +FINISH, HLT / Normal good halt + JMP START + + *200 +START, CDF 0 + CAF + CLA CLL OSR / Get drive + AND (1 + RTR + DCA DRVSEL + CLA CLL OSR / Get max field + RTR + RAR + AND (7 + SNA + HLT / Must have at least 1 field for buffer + CIA + DCA FIELDS + DCA ERRCN2 +RDSZLP, TAD BLKFLD / Multiply by number of fields available + ISZ FIELDS + JMP RDSZLP + DCA RDSIZE / NUMBER BLOCK PER READ + DCA CBLOCK + DCA CHKSM + +DUMPLP, CLA + TAD RDSIZE + TAD CBLOCK + CIA + TAD NUMBLK / MORE BLOCKS LEFT THAN READSIZE? + SMA / NO, READ NUMBER LEFT + CLA / YES, ONLY READ RDSIZE + TAD RDSIZE + SNA / ANY MORE BLOCKS? + JMP DONE / NO, DO FINISH STUFF + DCA ARGSZ + TAD CBLOCK + DCA ARGBK + TAD DRVSEL + JMS DTA0 + 0010 / READ STARTING IN FIELD 1 +ARGSZ, 0 + 0 +ARGBK, 0 + JMP ENDRET / TAKEN WHEN END OF TAPE IS HIT + JMP ERRRET / TAKEN WHEN AN ERROR IS ENCOUNTERED + TAD (377 / All blocks good + DCA READST + / Send data, each block starts with FF + CLA CLL / then 2 12 bit words in 3 bytes + DCA LOC / ERRRET DUPLICATES SOME OF THIS + TAD ARGSZ + CIA + DCA BCNT / Setup loop counter with number blocks read + CDF 10 +OUTBL1, JMS OUTBLK / Send a block + ISZ CBLOCK + ISZ BCNT / Send all read? + JMP OUTBL1 / No + CDF 0 + JMP DUMPLP / Go read next batch + + +DONE, CLA / Send FE and -checksum of all words + TAD (376 + JMS PUN + CLA CLL + TAD CHKSM / Send checksum in two bytes, low bits first + CIA + JMS PUN + CLA CLL + TAD CHKSM + CIA + RTR + RTR + RTR + RTR + AND C17 + JMS PUN + CLA + TAD DRVSEL + JMS DTA0 / REWIND TAPE + 0010 + 1 + 0 + 0 + NOP + NOP + TAD ERRCN2 / Leave AC with # of errors + JMP FINISH + + /SEND GOOD BLOCKS READ WITH GOOD BLOCK FLAG + /THEN BAD WITH BAD BLOCK FLAG. +ERRRET, +/ HLT / ****** If we want to stop on error + CDF 10 + CLA CLL + DCA LOC + TAD CBLOCK + CIA + TAD BLOCK /Get - number good blocks read + CIA /Last was bad + SNA + JMP FSTBAD /First block is bad, no good to send + DCA BCNT + TAD (377 + DCA READST +OUTBL2, JMS OUTBLK /Send good blocks + ISZ CBLOCK + ISZ BCNT + JMP OUTBL2 +FSTBAD, TAD (375 /NOW SEND BAD BLOCK + DCA READST + JMS OUTBLK + ISZ CBLOCK + ISZ ERRCN2 + CDF 0 + JMP DUMPLP /And read from here on + + PAGE +ENDRET, /SEND LAST SET OF BLOCKS READ BEFORE END OF TAPE AND FINISH. + CDF 10 + CLA CLL + DCA LOC + TAD CBLOCK + CIA + TAD BLOCK / GET NUMBER OF BLOCKS READ IN LAST BATCH + CMA / +1 to -BCNT SO WE SEND ALL BLOCKS + SNA + JMP DONE / READ ZERO BLOCKS IN LAST BATCH, WE ARE DONE + DCA BCNT + TAD (377 + DCA READST +OUTBL3, JMS OUTBLK / SEND ALL BLOCKS + ISZ CBLOCK + ISZ BCNT + JMP OUTBL3 + CDF 0 + JMP DONE / NO MORE BLOCKS, DONE. + +OUTBLK, 0 /Send a block of data out serial port + CLA + TAD WCOUNT + DCA LEN + TAD READST /Send good/bad flag + JMS PUN +OUT, CLA CLL + TAD I LOC + TAD CHKSM / Keep checksum of all words sent + DCA CHKSM + TAD I LOC / Send 2 words as 3 bytes + JMS PUN + CLA CLL + TAD I LOC + RTR / Shift top 4 bits to low 4 + RTR + RTR + RTR + AND C17 + DCA TEMP + ISZ LOC + JMP STFLD3+1 /NOT AT END OF FIELD (DJG) + RDF /At end, inc to next field + TAD (6211 /BUILD CDF + DCA STFLD3 +STFLD3, NOP + ISZ LEN /END OF BUFFER? + SKP /NO + JMP ENDBK /YES + TAD I LOC + TAD CHKSM + DCA CHKSM + TAD I LOC + RTL + RTL + AND C360 + TAD TEMP + JMS PUN + CLA CLL + TAD I LOC + RTR + RTR + JMS PUN + ISZ LOC + JMP STFLD4+1 /NOT AT END OF FIELD (DJG) + RDF + TAD (6211 /BUILD CDF + DCA STFLD4 +STFLD4, NOP + ISZ LEN + JMP OUT + JMP I OUTBLK +ENDBK, TAD TEMP /SEND LAST PART OF WORD + JMS PUN + JMP I OUTBLK + +PUN, 0 / Send byte out serial port +/ PLS / Punch for testing with emulator + TLS2 / Send out console + CLA CLL + TAD CBLOCK +/ PSF + TSF2 /Wait until character sent + JMP .-1 + CLA + JMP I PUN + + $ diff --git a/DumpDT18/dumpdt18-550.pal b/DumpDT18/dumpdt18-550.pal index e9d79d4..ad668f7 100644 --- a/DumpDT18/dumpdt18-550.pal +++ b/DumpDT18/dumpdt18-550.pal @@ -1,6 +1,6 @@ / TD8E 18-bit DECtape DUMP Program. Based on DUMPREST code from D. Gesswein / (see ftp://ftp.pdp8online.com/software/dumprest). -/ Modified for 18-bit PDP-7 550 DECtape imaging by J. Dersch +/ Modified for 18-bit PDP-7 550 DECtape imaging and arbitrary-lengths by J. Dersch / / This program will send a DECtape image out the console port. / The format of the data sent is 0xff (0377) or 0xfd if read error diff --git a/DumpDT18/dumpdt18.pal b/DumpDT18/dumpdt18.pal index a3148c1..b4b59b2 100644 --- a/DumpDT18/dumpdt18.pal +++ b/DumpDT18/dumpdt18.pal @@ -1,6 +1,7 @@ / TD8E 18-bit DECtape DUMP Program. Based on DUMPREST code from D. Gesswein / (see ftp://ftp.pdp8online.com/software/dumprest). -/ Modified for 18-bit DECtape w/standard checksum imaging by J. Dersch +/ Modified for 18-bit DECtape w/standard checksum imaging and arbitrary-lengths +/ by J. Dersch / / This program will send a DECtape image out the console port. / The format of the data sent is 0xff (0377) or 0xfd if read error diff --git a/DumpDT18.sln b/DumpDectape.sln similarity index 85% rename from DumpDT18.sln rename to DumpDectape.sln index de48c9b..eff7b19 100644 --- a/DumpDT18.sln +++ b/DumpDectape.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26403.7 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DumpDT18", "DumpDT18\DumpDT18.csproj", "{88B646C3-54D8-4D63-BB8A-B391C996FE47}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DumpDectape", "DumpDT18\DumpDectape.csproj", "{88B646C3-54D8-4D63-BB8A-B391C996FE47}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution