Leo III software preservation

Our project mostly happens on a small server which may not be up 24/7:

The main thrust of the project is the production of an environment within which original Leo III software can be experienced at verious levels, from a quick example run to detailed appreciation of the implementation.

Our original material was a box of lineprinter listings of systems software, and original manuals for the system. Via a separate source, we received a fairly mysterious box of paper tapes which are described here.

This project (including this document) is still a work-in-progress. A later version of the narrative below is in the course of preparation here.

History of the Project

David Holdsworth
This is an attempt to record the steps along the way, before memories become too unreliable.

I undertook this project in order to get a better appreciation of the issues that would face historians (archæologists) of the future faced with remnants of software from a long dead machine. I had the (unfair) advantage of living veterans, without which the project woul;d have been much more difficult.

The surviving material comprised printer listings and manuals, in various states of preservation.

Manuals — understanding Leo III

As a vital step, we made on-line manuals available. They can be seen here, on a server which may not be up 24/7. There remains some work to be done on editing, but what is there is very usable.

The decision was to try to reproduce the style of the originals using very simple HTML exploiting the <PRE> tag so that the material would be immune from sensitivity to browser versions. We have used this technique and it works well in almost every instance. The browsers in smartphones and smart TVs seem to lack a monospaced font. Even then the manuals read quite well, except for some of the tables.

Code — making it work

There does not seem to be any significant use of an assembly language for Leo III. Most of the system software was written in Intercode, and applications software both in Intercode and an early high-level language CLEO, which had some resemblance to COBOL. The machine language is called computer code, and seems only to exist in binary form, though individual computer code instructions can be written in Intercode.

From the several listings which survived we elected to work on the Intercode Translator (08000), the Master Rroutine (09001) and the generator programme for customising the master routine (08004). All of these are written in Intercode.

The ambition is to be able to execute the software, for which we clearly need an emulator for Leo III computer code, and to provide facilities for following the source text of the system in a current environment (i.e. a web browser).

Strategy — Intercode Translator

Ultimately, everything should run under an emulator which executes the Leo III machine code, but in order to get the that stage we need to be able to translate Intercode into machine code, which needs the Intercode Translator 08000, for which we did not have a binary program. The Intercode Translator has the capability to list the binary program at the end of its listing, but this part had been torn off our surviving listing. The decision was to develop in parallel an emulator for computer code, a translator for the minimum Intercode capability to translate 08000, and the digitised source code of 08000. We quickly realised that only copy-typing in duplicate had a chance of achieving the required accuracy for the source code listings, which were done on barrel printers. This image is the start of the Intercode Translator, and this is the start of the Master Routine.

At this point I (DH) was unaware that the listing produced 08000 was not the same as the input, and set things up to copy-type the parts of the listings that corresponded with the source code. In retrospect, this turned out well, probably better than if we had tried to type proper 08000 input from the print-outs.

This takes us to the point where we can execute the real 08000 which produces printout, and writes the binary program onto magnetic tape (emulated in a file). Our emulator (leo3.c) is running the user program and emulating both the computer code instructions and the calls to the master routine for operations such as reading and writing magnetic tapes. In order to execute the binary program produced by 08000, we need to load it from the mag tape into our emulator, which necessitates another program (getbin.c). This is because the input to leo3.c is a very simple text file with one instruction to a line. Leo III is an absolute memory machine (like the IBM360) so binary programs on mag tape need to have the addresses in instructions modified to address absolute memory locations.

This now take us to the point where we can take Intercode, translate it into computer code using the genuine 08000 and then load it into our emulator (leo3.c) and execute it, which is all we need for the bootstrap in which 08000 translates itself, and we have then re-created the binary program of 08000.

Strategy — Master Routine

In order to implement tha Master Routine we need both the generic Master Routine (09001) and the generator program 08004. Both programs were to be copy-typed and translated using the bootstrapped 08000.

The production of a Master Routine for an individual Leo III involved translation of the generic Master Routine to produce a mag tape that was then processed by 08004 with the actual machine’s configuration being described on paper tape. The result is a magnetic tape that can be loaded directly into a naked Leo III machine. Just as we needed getbin.c to take the output from 08000 and load it into our emulator we need our emulator to read the magnetic tape into the bottom of store and jump to address 0.

At this stage we have a working Leo III system capable of running real Leo III software. We still hope the find the CLEO compiler, perhaps only as a binary program on mag tape. Whatever we find, we can be confident of runing it if it is complete.

Running the master routine requires not only emulation of the machine’s computer code instructions, but also there are times when it is necessary to emulate the operators’ actions, e.g. loading paper tapes, cards, mag tapes, feeding in commands via the indicator keys. This is currently at a very rudimentary stage, and the strategy is to improve it as the need arises.


We also have ambitions to make the appreciation of usage of Leo III accessible to a 21st century audience. We have packaged our emulator as a web facility for submitting an Intercode program, and for running the resulting binary program, all using the genuine Leo III software, currently available here.

The listings produced by 08000 were on fanfold printer paper and probably perused by kneeling on the floor upon which the listing was spread out. Our modernise.c progam takes the listing file, and turns all the references into hot links to the relevant routine, this making it much easier to follow executions paths that was ever the case in real life.

The documentaiton has been similarly modernised with hot links in its contents pages.


Parallel Implementation

The parellel implementation of the emulator (leo3.c), the copy-typing and the interim translator (called it.c) for generating abinary program from 08000 enabled the emerging the C code to be tested against known valid Leo III Intercode. To see the rationale for programming in a aubset of C, please look here.


Each line in the Intercode listing represent on Intercode instruaction, which may result in more than one computer code instruction. The layout is in columns, with a serial number in the left-hand column. Although the listing should be read line-by-line, it seems easier to copy-type in columns, using the spread capabilities to generate the serial numbers, and to copy down the often repeated zeros. The spreadsheet is then saved as comma-separated data and this is what is read by the interim intercode translator (it.c), which only needs to work on those parts of the language that are used in those parts of the real Intercode Translator that are needed for translating itself.

Each page of listing was photographed, and the photos were put on a webserver. The pages were copy-typed by volunteer Leo III veterans, each one in duplicate by different people. We had an on-line booking system for people to volunteer to claim a page for either typing the primary copy (comments included) or the secondary copy (no comments). The two copies were then brought together and compared to produce a comparison file that shows which lines did not compare, and picked out where the mis-match happened within the line. At the foot of the page is a link to the original photograph in a separate tab, giving rapid comparison. It has to be admitted that this comparison system developed over several months.

Fancy characters that do not appear on modern keyboards were represented by lower case letters in the typescript, and eventually emerged in listings as Unicode near equivalents.
Leo IIItypescript 
£ppound sign
>gright arrow

Interim Intercode Translator

The interim intercode translator uses 2 pases, and takes as input the CSV file from the copy-typing. The first pass allocates addresses for all the instructions and constants, and the second one generates the code. The translator is generated from a file that defines the Intercode instructions, which is then merged with a wrapper to produce the translator.

When our interim translator processed the copy-typed listing of the real Intercode Translator, this was the result.

As a by product the generator program also makes an HTML file for use as a cross reference into the documentation.

Initial Leo III emulation

Our original emulation was made from the Leo III page in Our Computer Heritage.

This was done by:
  1. Open the Leo III page in Acrobat Reader.
  2. Select the text of the table listing the instruction set.
  3. Paste it into a plain text file.
  4. Write a small generator program to read this file and generate a giant case statement
  5. Write a skeletal framework into which the case statement can sit
  6. Modify the generator program to merge the two together.
  7. Test it with a very crude input file.
So then it just remained to populate the individual elements of the case statement, leading eventually to leo3.c.

To see how KDF9 lineprinter listings have been turned into working software, please look here.

Running the translated programs

When we run the output from our interim translator under our emulator, the translated binary program ends up on an emulated magnetic tape. It is not absolute binary, but relocatable as Leo III did not have address translation. This relocation process is part of the Master Routine which we cannot yet run, so a program (getbin.c) was written to read the emulated tape and generate a memory image for loading into our emulator (leo3.c).

Once a few test programs had been run, including the ubiquitous Hello World!, attention switched to 08000 itself. It was at this point that I discovered that the input to 08000 differed non-trivially from the listing that 08000 produced, and yet another program (mkpt.c) was need to make a paper tape for input to our newly generated 08000. Of course this was an emulated paper tape. A real one would have been about a mile long.

At last we have a mag tape which holds the binary version of 08000. This can be run with the aid of getbin.c and leo3.c. This is spelt out in more detail below.

We can now take Intercode source text and execute it on our emulator, so long as it does not contain instructions that we have not met yet. A vital part of the strategy is only to implement those instructions for which we have known examples from historic code.

Master Routine

The copy-typing of the generic master (09001) and the generator program (08004) produced CSV files, which are easily converted to emulated paper tapes using mkpt.c. The translation of 09001 produced a listing that compared most convincingly with the photos, and also a magnet tape on its file A2, which is then used as input file A1 by 08004. At this point we hit a snag. When we ran 08004 it read the tape and complained that it could not find 09002. Clearly we have an incompatibility here. We patched the binary 08004 program to accept 09001 instead, and after another couple of patches it processed the tape, and transformed itself into a Master Routine executing in our emulator, which soon complained that various master mode instructions were not implemented.

Implementation of the missing instructions soon led to the generation of a master boot tape suitable for use with mag tape start (Leo-speak for intial bootstrap from mag tape). The simplest way to implement the mag tape start is to write a program (MT-start.bin) in the simple loader format of our leo3.c emulator.
          Mag tape start programme
          When it asks for indicator type m00 MT-start.leo
          where MT-start.leo is the tape that you wish to load
          Note: Thre are no second chances.
                You must get it right first time, with just the one space
L999 initial bootstrap loaded at word 999
19/1/2 24    unload paper tape to set done19 flag
25/1/2 7     read indicators to allow tape to be mounted
19/0/1 0     read initial block on tape
26/1/0 0     test route
0/0/0 0      halt not available
24/1/0 1002  loop until transfer finished
0/0/0 0      doubtful block
0/0/0 0      warning of end
25/1/2 0     A := 0
2/0/0 258    store[129] will become 0 rather than 0x80
24/1/0 0     enter bootstrap
E999  entering at address 999
There was some little understood problem which was solved by altering one word in the bootstrap code on the tape (see above), and we can load our Master Routine and it runs programs, including 08000 with then produces binary programs that we can also run.

A facility for generating a Leo III Master Routine on your own machine is here.


This 21st century exploration of Leo III has been been possible because of the dedicated efforts of several Leo III veterans, and the goodwill of the Leo Society. John Daines, Ray Smith, Geoff Cooper and Ken Kemp have stuck with the enterprise and continue to do so. Valuable work continues in improving our on-line documentation. Chuck Knowles, Tony Jackson and Dave Jones also made invaluable contributions to the laborious and painstaking process of copy-typing the surviving line-printer listings. Helpful nuggets of information have been provided from time by other members of the Leo Society.

Translator Bootstrap

The current state of play can be accessed via the link in the status section above, but our first major milestone was the creation of an executable Intercode Translator which successfully translates itself. We now have considerable experience of using this on the master routine and its generator program and it has proven very reliable.

Here is the story of the steps in this generation process (which is part of the example accessed from the status section above):
  1. Raw material is the line printer output saved by Colin Tully. This is the output listing produced by the Intercode Translator translating itself.
  2. This was photographed, and then copy-typed using spreadsheets to produce 08000.csv.
  3. This can be processed using a specially written translator (it.c) to produce a listing that is also a binary program: demo.htm.
    This can be run with the emulator (leo3.c) to translate Intercode programs in paper tape initial translation format, such as hello.txt:
                  leo3 -d demo.htm hello.txt
  4. The binary program generated by the Intercode Translator is on the output tape MT-A2.leo. This is in a form ready for the Master Routine’s loading process. We have yet to implement the Master Routine, but the program getbin.c extracts the program from this output tape and generates a binary program in a form suitable for our emulator (leo3.c). E.G. after translating hello.txt as above, it can be executed using the sequence:
                  getbin MT-A2.leo t.bin
                  leo3 -d t.bin
    The getbin program involves reading a tape for which we have only partial documentation, in effect reverse engineering the loading proess of the Master Routine that we have yet to implement. Consequently, it produces quite a lot of diagnostic commentary on the contents of the tape.
    The -d switch used with leo3.c sends its diagnostics to a file log.txt. If you omit this switch there is some extra output on your screen. Details of the diagnostic facilities are in a comment at the head of leo3.c.
  5. The Intercode Translator can be translated using the demo.htm version of itself. The original raw material (08000.csv) is first converted to paper tape initial translation format (08000.txt) using a program mkpt.c, before running demo.htm with the emulator:
                  leo3 -d demo.htm 08000.txt
    The Intercode Translator works slightly differently in translating itself, and as a result the binary program ends up on tape MT-A6.leo. Although the binary program is also on MT-A2.leo it seems to be in a slightly different format. The suspicion is that this is something to do with the overlay mechanism. A binary version of the self-translated Translator can be generated by
                  getbin -b5000 -b8192 -b160 MT-A6.leo t.bin
    The -b5000 -b8192 -b160 switches define the location in memory of chapters 1, 2 and 3 respectively. Chapter 3 is the extra chapter generated by the translator. Chapters 4 onwards are overlaid over chapter 2. Chapter 4 in the binary program corresponds to chapter 3 in the source code.
  6. The Intercode Translator is aware of its own issue number and its behaviour depends on this number, which is always zero for an initial translation from paper tape. So we have to rename the output file as the input file and do a null amendment to enable us to set the issue number to 8 using file NullAmend.txt:
                  move MT-A2.leo MT-A1.leo
                  leo3 -d demo.htm NullAmend.txt
  7. The result of this translation is a properly functioning issue 8 Intercode Translator (probably) written on MT-A6.leo. We can extract a binary program suitable for our emulator from this by
                  getbin -b5000 -b8192 -b160 MT-A6.leo ITi.bin
  8. We can substitute ITi.bin for demo.htm in the commands above, and even have it regenerate itself, see below:
    F:\dh\leo>leo3 -d ITi.bin 08000.txt
     8257 LOG: 08000 PROG OUT  08000      0   +PTS
    11450 LOG:   08000 MAKES PASS3 COPY ON  8000
    ALARM *06 for operator
    PROGRAMME UNLOADED: ADDRESS = 11616 after 31505788 instructions
    F:\dh\leo>move MT-A2.leo MT-A1.leo
    F:\DH\LEO\MT-A2.leo => F:\DH\LEO\MT-A1.leo [ok]
    F:\dh\leo>leo3 -d ITi.bin NullAmend.txt
     8940 LOG: 08000  AMEND  08000     0
     8257 LOG: 08000 PROG OUT  08000    801
    11450 LOG:   08000 MAKES PASS3 COPY ON  8000
    ALARM *06 for operator
    PROGRAMME UNLOADED: ADDRESS = 11616 after 22861490 instructions
    F:\dh\leo>getbin -b5000 -b8192 -b160 MT-A6.leo t.bin
    File: MT-A6.leo
        3 PASS3 marker for program 08000 found
       73 ALLOC block found
       Total chaps = 11 (init 3)  files(R) = 5  Transit Areas = 5
       Enter at address 41 in chapter 2
      112 File details block (5 routes)
       File D1 type 14 -- chap 6 annex at 598 length 394
        Annex 0 is in chapter 6 - reallocated to 3
       File B1 type 15 -- chap 4 annex at 6810 length 58
       File A1 type 7 -- chap 4 annex at 6868 length 154
       File A2 type 8 -- chap 4 annex at 7022 length 154
       File A6 type 7 -- chap 4 annex at 7176 length 154
    Transit area 0 is in chapter 6 - reallocated to 3
      235 CHAPTer 1 start at 5000 (progid = 08000)
      242 CHAPTer 2 start at 8192 (progid = 08000)
      454 CHAPTer 3 start at 160 (progid = 08000)
    Extra chapter 3 located at 361 (param = 3840)
      456 CHAPTer 4 start at 8192 (progid = 08000)
    Overlaying chapter 2 by 4
      893 CHAPTer 5 start at 8192 (progid = 08000)
    Overlaying chapter 4 by 5
     1329 CHAPTer 6 start at 8192 (progid = 08000)
    Overlaying chapter 5 by 6
     1687 CHAPTer 7 start at 8192 (progid = 08000)
    Overlaying chapter 6 by 7
     1942 CHAPTer 8 start at 8192 (progid = 08000)
    Overlaying chapter 7 by 8
     2356 CHAPTer 9 start at 8192 (progid = 08000)
    Overlaying chapter 8 by 9
     2538 CHAPTer 10 start at 8192 (progid = 08000)
    Overlaying chapter 9 by 10
     2544 CHAPTer 11 start at 8192 (progid = 08000)
    Overlaying chapter 10 by 11
    Overlaying last chapter 11
    F:\dh\leo>leo3 -d t.bin NullAmend.txt
     8940 LOG: 08000  AMEND  08000     0
     8257 LOG: 08000 PROG OUT  08000    801
    11450 LOG:   08000 MAKES PASS3 COPY ON  8000
    ALARM *06 for operator
    PROGRAMME UNLOADED: ADDRESS = 11616 after 22861490 instructions