MOS paper tape format

MOS paper tape format

I built the world's worst paper tape reader some weeks ago. It works pretty okay on anything with a USR-style port like a KIM-1 clone or a VIC-20.

It at least attempts to live up to the world's worst name.

Paper tape was (and is) an interesting medium. Sure it's hard to work with and fragile, but it also has the advantage of being slow. I mean, what's not to like??!!!

Did you know that sometimes the CIA still uses paper tape to exchange encryption keys? Look it up, fascinating.

MOS Format

From a previous article, let's look at an example of a paper tape file in "MOS" format.


Let's break down the first line:


Each line begins with a semicolon, followed by the number of hex bytes in the line:

;18  (24 in decimal)

Next is the starting address for that line in 2 bytes:


The next 24 ($18) bytes are the actual byte codes to be loaded:


And we end the line with a simple checksum which is just all 24 bytes added. The result is two bytes:


If you think better in code, here's a little python to help wrap our minds around this checksum:

line = ";180200D8A9FF8D03168D0116A2FF8604201D02A604CA8604D0F6A9" 

def checksumKim(line):
    checksum = 0
    data = [line[i:i+2] for i in range(1, len(line), 2)] #chomp ; and split to bytes
    for byte in data:
        checksum += int(byte, 16)
    checksum = hex(checksum)[2:] #formatting 
    if len(checksum)<4:
        return line+'0'+checksum #need this in two bytes
    return line + checksum


KIM-1 Load from file

Many modern serial terminals make it easy to load these paper tapes onto a KIM-1: XModem transfer or just a simple cut and paste. Move to the start address and press L. Then upload or paste into the window.


KIM-1 Save

Let's look at the program already in memory.

Set $17F7 and $17F8 to the end location of what you want to save. Move to the start and press Q.



What would an ASCII message look like on paper tape? This depends on the type of encoding used, but a popular one looks like this:

for byte in message:
    bytestring = str(bin(ord(byte)))
    print('0'+ bytestring[2:6]+"."+bytestring[6:], ":", byte)
01000.001 : A
01010.010 : R
01000.101 : E
01011.001 : Y
01001.111 : O
01010.101 : U
01001.011 : K
01000.101 : E
01000.101 : E
01010.000 : P
01001.001 : I
01001.110 : N
01000.111 : G
01010.101 : U
01010.000 : P

Have Fun!