Table of Contents
There are various file formats used with the pymlac machine:
All papertape files readable by the pymlac machine have a *.ptp filename.
Source Code File Format
Papertape files containing program source code are 8-bit tapes encoded in ASCII, with a zero byte leader and trailer, as usual.
For example, this simple text file:
; a simple 'smoke-test' file
org 0100
start nop
hlt
end start
might have this form in a papertape file:
$ octdump test.asm
0000000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 |................|
0000010 073 040 141 040 163 151 155 160 154 145 040 047 163 155 157 153 |; a simple 'smok|
0000020 145 055 164 145 163 164 047 040 146 151 154 145 012 040 040 040 |e-test' file. |
0000030 040 040 040 040 040 157 162 147 040 040 040 040 040 060 061 060 | org 010|
0000040 060 012 012 163 164 141 162 164 040 040 040 156 157 160 012 040 |0..start nop. |
0000050 040 040 040 040 040 040 040 150 154 164 012 012 040 040 040 040 | hlt.. |
0000060 040 040 040 040 145 156 144 040 040 040 040 040 163 164 141 162 | end star|
0000070 164 012 000 000 000 000 000 000 000 000 000 000 000 000 000 000 |t...............|
0000100 000 000 |.|
Note that a papertape file has 16 or more zero bytes of leader and trailer. This is true for all papertape files as the physical medium needs a leader and trailer for ease of handling. On a real papertape these leaders may be much longer.
Executable File Format
All executable papertape files have a zero byte leader followed by blockloader data and then executable block data.
The ROM bootstrap loader reads the first 040 non-zero words in the file into the last 040 addresses of memory and then jumps to the start address (the first word loaded). This blockloader then loads the remainder of the tape.
There are two basic forms of executable PTP files. They are called c8lds and lc16sd formats.
##c8lds format executables
This older format file has an overall format of:
- a zero byte leader
- 040 words of blockloader, loaded into the last 040 bytes of memory
- one or more blocks of data
- an End-Of-Tape block
- a zero byte trailer
Each c8lds data block has the following format:
- data count (8 bits)
- load address (16 bits)
- data word 1 (16 bits)
- ...
- data word N (16 bits)
- checksum (16 bits)
The checksum word must be the value calculated by summing all data words only modulo 0177777.
The End-Of-Tape block has this format:
- any non-zero count (8 bits)
- a load address of 0177777 (16 bits)
###c8lds Example
As an example, here is the source listing for a small test file, test.asm:
$ more test.lst
0001: ; a simple 'smoke-test' file
00100 0002: org 0100
0003:
0100000 00100 0004: start nop
0000000 00101 0005: hlt
0006:
00100 0007: end start
and here is the corresponding test.ptp file assembled to an c8lds format tape:
$ octdump test.ptp
0000000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 |................|
0000010 002 032 027 340 047 277 077 360 204 001 027 303 200 006 047 377 |....'.?.......'.|
0000020 077 350 047 376 177 330 027 315 000 000 077 350 247 376 077 331 |?.'.......?...?.|
0000030 067 376 067 377 027 315 077 350 167 277 204 001 027 346 000 000 |7.7...?.w.......|
0000040 377 377 037 320 200 010 157 277 004 004 200 004 047 277 227 331 |......o.....'...|
0000050 002 061 147 374 047 361 012 032 377 375 047 361 200 011 027 302 |.1g.'.....'.....|
0000060 037 311 200 011 077 360 006 003 006 003 006 002 077 360 227 350 |....?.......?...|
0000070 037 357 002 032 205 000 027 362 005 000 027 364 002 051 227 360 |.............)..|
0000100 004 040 027 370 002 033 227 360 027 370 000 044 000 000 000 000 |. .........$....|
0000110 002 000 100 200 000 000 000 200 000 377 200 100 000 000 000 000 |..@.............|
0000120 000 000 000 000 000 000 000 000 000 000 000 000 000 000 |..............|
The first 16 bytes are the zero leader. The blockloader code is from 010 to 0107. Starting at offset 0110 we have the lone data block:
002 data word count (2)
000 100 block load address (0100)
200 000 first data word (NOP)
000 000 second data word (HLT)
200 000 checksum
Adding the two data words gets a sum of 0100000, which is the checksum value.
The next block is a start block:
377 data word (0377 here, but any value will do)
200 100 start address (0100) with the high bit set
000 000 AC is loaded with 000000 before start
The load address with the high bit set signifies that this is the end of the tape and the start address is 0100. The next word is the value put into AC before the loaded program starts.
If the load address is 0177777 then there is no auto-start and the block loader just stops.
The last bytes of the file are the zero byte trailer.
##lc16sd format executables
This newer format file has an overall format of:
- a zero byte leader
- 040 words of blockloader, loaded in the last 040 bytes of memory
- one or more blocks of data
- an End-Of-Tape block
- a zero byte trailer
Each lc16sd data block has the following format:
- one word of load address (16bits)
- a word of data word count (16bits, complemented)
- a checksum word (16bits)
- data word 1 (16 bits)
- ...
- data word N (16 bits)
The checksum is computed such that the sum of the load address, complemented word count, the checksum itself and all data words will be zero, modulo 0177777.
The End-Of-Tape block has this format:
- a start address with the high bit set (16 bits)
- a value that is put into the AC register on start (16 bits)
###lc16sd Example
As an example, here is the source listing for a small test file, test.asm:
$ more test.lst
0001: ; a simple 'smoke-test' file
00100 0002: org 0100
0003:
0100000 00100 0004: start nop
0000000 00101 0005: hlt
0006:
00100 0007: end start
and here is the corresponding test.ptp file assembled to an lc16sd format tape:
$ octdump test.ptp
0000000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 |................|
0000010 002 032 027 340 047 277 077 360 204 001 027 303 200 006 047 377 |....'.?.......'.|
0000020 077 350 047 376 177 330 027 315 000 000 077 350 247 376 077 331 |?.'.......?...?.|
0000030 067 376 067 377 027 315 077 350 167 277 204 001 027 346 000 000 |7.7...?.w.......|
0000040 377 377 037 320 200 010 157 277 004 004 200 004 047 277 227 331 |......o.....'...|
0000050 002 061 147 374 047 361 012 032 377 375 047 361 200 011 027 302 |.1g.'.....'.....|
0000060 037 311 200 011 077 360 006 003 006 003 006 002 077 360 227 350 |....?.......?...|
0000070 037 357 002 032 205 000 027 362 005 000 027 364 002 051 227 360 |.............)..|
0000100 004 040 027 370 002 033 227 360 027 370 000 044 000 000 000 000 |. .........$....|
0000110 002 000 100 200 000 000 000 200 000 001 377 377 000 000 000 000 |..@.............|
0000120 000 000 000 000 000 000 000 000 000 000 000 000 |............|
The first 16 bytes are the zero leader. The blockloader code is from 010 to 0107. Starting at offset 0110 we have the lone data block:
002 data word count (2)
000 100 block load address (0100)
200 000 first data word (NOP)
000 000 second data word (HLT)
200 000 checksum
Adding the two data words gets a sum of 0100000, which is the checksum value.
The next block is a start block:
001 data word (1, but any non-zero value will do)
200 100 start address (0100) with high bit set
000 000 AC is loaded with 000000 before start
The load address with the high bit set signifies that this is the end of the tape and the start address id 0100. The next word is the value put into AC before the loaded program starts.
If the load address is 0177777 then there is no auto-start and the block loader just stops.
The last bytes of the file are the zero byte trailer.
Different File Formats
Note that the executable tape formats described here are not the only ones possible.
An executable tape can have a different blockloader that reads data blocks of a format different from that described here. This is acceptable since the blockloader and the data blocks are all punched onto one piece of tape. As long as the blockloader code recognizes the following data blocks then all is well. Indeed, if you look at various historical papertape images you will see different data block formats. The executable tape formats described here is that used by all pymlac software.
All that is necessary for a blockloader is that the ROM boot code reads the first 040 non-zero words on tape into high memory and execution goes to the lowest addressed word in the loaded code. After that, anything is allowed!