commit b491b1f100f60b67147d330186dcc0cd70b7562d Author: Luxferre Date: Mon Jun 29 20:09:40 2026 +0300 initial upload diff --git a/README.md b/README.md new file mode 100644 index 0000000..0967b61 --- /dev/null +++ b/README.md @@ -0,0 +1,199 @@ +# ILDEC: a highly portable minimal DEC PDP-8/L emulator + +## About + +ILDEC (pronounced roughly like _ill-deck_) is a project aimed at creating a working and practical PDP-8 platform emulator in as little amount of code as possible for as many popular programming runtimes as possible. + +The name itself doesn't have an official meaning. Common interpretations include but are not limited to: + +- "Import, Load, Deposit, Examine, Continue" (5 most commonly used interactive commands in the emulator) +- "Interpreted/Interactive Land of DEC/Loader for DEC" +- "Inexpensive, Lazy DEC" +- "In Lieu of [DeCastro](https://en.wikipedia.org/wiki/Edson_de_Castro)" (PDP-8/L was the last of his designs before leaving for Data General) +- "It Lives through Digital Environmental Collapses" (see the FAQ section) +- "Instruction Logic to Ditch Extra Complexity" +- "Inefficient Luxferre's Decision to Educate Consumers" +- ... and so on. + +## Supported PDP-8 implementations + +ILDEC is most closely emulating the **unextended** version of PDP-8/L (and, to some extent, PDP-8/S), as it implements the absolute minimum required to run OS-less PDP-8 software packages like FOCAL-69. As a deliberate design decision, it **does not** support extensions like memory bank switching, EAE (Extended Arithmetic Element) with MQ (Multiplier/Quotient) register, or any device controls other than interrupts, teleprinter and keyboard. + +See the [ISA documentation](pdp8_isa_ildec.md) for all the details about the supported registers, memory and instruction set. This document may also be very helpful if you want to design your own PDP-8 emulator from scratch or just port ILDEC to a new runtime. + +## Implementations + +This is the list of all known implementations of the ILDEC specification, both the author's and third-party. + +The list is divided into four categories: CLI, GUI (including Web), embedded and library-only implementations. In case an implementation can be used in several niches, it may appear in several categories. + +Forks and mods are allowed and even encouraged! + +### Official Python implementation: [ildec.py](python/ildec.py) + +- Categories: CLI, Embedded, Library +- Compatible with: CPython, MicroPython, CircuitPython (only tested on a LilyGO T-Deck Plus in the [T-DeckARD](https://codeberg.org/luxferre/t-deckard) environment, see below for installation details), Brython (as a library) + +## Usage + +Depending on the implementation, the way to interact with ILDEC may differ, but generally all implementations that aren't library-only must expose the same set of commands. + +### CLI implementations + +In case of CLI, the emulator must accept the following optional command-line parameters (in this very order): + +- preloaded tape file name (string, default `` (empty)) in the `.oct` format (see below) +- starting PC (program counter) address (4 digits, octal, default `0200`) +- starting SR (switch register) state (4 digits, octal, default `0000`) + +Upon starting, the emulator must present an optional welcome banner, then the initial machine state (see below), then a DOS-like prompt (`> `), and accept either a single 4-digit octal number as a command (and update the machine state by changing the SR (switch register) value) or any of the following (case-insensitive) single-character commands: + +- `l`: load the SR value into the PC register +- `d`: deposit the value in SR under the memory address which is in PC, then run the examine command (which auto-increments PC) +- `e`: examine (display) the value at the current address in PC, then increment PC +- `c`: continue/start running the program starting at the address in PC +- `s`: step through one instruction at a time (execute it and then increment PC) +- `r`: reset the machine (clear every internal state and register except the memory contents, then restore the initial PC and SR values if they were provided upon emulator start) +- `n`: (new, nuke) fully clear the memory contents, effectively reinitializing the emulator from scratch +- `i`: import a tape in the `.oct` format into the machine memory +- `x`: export current machine memory into the `.oct` format (zero-valued locations are not exported) +- `q`: quit the emulator. + +Additionally, you may press Ctrl+D (or Shift+Vol on the T-Deck) to halt execution at any time and return to the emulator command interface. + +After running any command and/or halting execution, the emulator must print a new machine state before printing the prompt. The state looks like this: +``` +PC: [PC] | L AC: [L] [AC] | SR: [switches] +``` + +As an example, this is the initial state that gets displayed when starting a CLI implementation of ILDEC with no parameters: +``` +PC: 0200 | L AC: 0 0000 | SR: 0000 +``` + +And this is how the state should change after successfully running the bundled [test routine](soft/test.oct) which prints 31 dots when all tests pass: +``` +> i +File path: soft/test.oct +Memory imported from soft/test.oct + +PC: 0200 | L AC: 0 0000 | SR: 0000 + +> c +............................... +PC: 1376 | L AC: 0 0000 | SR: 0000 + +>``` + +### GUI/Web implementations + +While there's no unified way of doing this, any GUI implementation of ILDEC, including Web-based ones, must fully provide functional equivalents of all interactive commands, parameters and displays mentioned in the CLI section. + +The designs may vary from just embedding the same CLI into a web page to full graphical simulation with switches and blinkenlights. + +### Embedded implementations + +In case the embedded target platform provides any sort of serial terminal interface, the emulator must implement the same UI as for the CLI applications, with the exception of preloading the initial state from command-line parameters. + +Here's how to install and run ILDEC as an applet on the [T-DeckARD](https://codeberg.org/luxferre/t-deckard) CircuitPython-based environment for LilyGO T-Deck (Plus): + +1. Mount your CircuitPython device volume. +2. Create a directory for your PDP-8 tapes in the device volume root, `data/ildec` is the recommended name but you're free to choose any other. +3. Copy `python/ildec.py` from this repo into the `app/` directory on the device. +4. Copy all the `soft/*.oct` files from this repo into the directory you created on step 2 (e.f. `data/ildec`). +5. Unmount and eject the volume. + +Now, from the T-DeckARD REPL, you can import the emulator with `from app.ildec import ildec` and then run it by typing `ildec()`, optionally passing the parameters in the form `(filename, PC, SR)`, e.g. `ildec("data/ildec/test.oct", 0o200, 0o1234)` to preload the tape, specify the starting PC and switch register state. + +From the interpreter, you can use all the same commands as the usual CLI, including `i` for import and `x` for export. + +### Library-only implementations + +A non-UI implementation of ILDEC must offer the user a way to inspect and customize the emulator state (memory, PC, AC, L, SR) on the fly and expose methods for continuous running, stepping through and resetting the machine. Also, if possible, a method to load `.oct` tape images is recommended to implement. + +## Tape format (`.oct`) + +To load (and save) memory images, ILDEC uses an extremely simple `.oct` format that is purely ASCII plain text and resembles old `.lst` listing formats. Each line contains a pair of two 4-digit octal values, `[address]` and `[content]`, separated by a colon and (optional) whitespace: `[address]: [content]`. Everything after the `[content]` value up to the next newline must be ignored by the reader. + +Here's a short example of a program starting from the address 0000 in the `.oct` format: +``` +0000: 7301 +0001: 7001 +0002: 7430 +0003: 7402 +0004: 5001 +``` + +To facilitate converting from popular `.bin` and `.rim` DEC tape formats into ILDEC's `.oct`, the `conv` directory of this repository contains two Python scripts: [bin2oct.py](conv/bin2oct.py) and [rim2oct.py](conv/rim2oct.py). It also contains a script called [oct2rim.py](conv/oct2rim.py) in case you need to export an `.oct` tape into other PDP-8 emulation environments as a `.rim` image. + +## Bundled programs + +ILDEC repo contains a few examples of PDP-8 software that you can try running on the emulator. For now, the following programs are bundled: + +- [Test program](soft/test.oct): the one you should run first. Tests the entire emulation logic. Loads at the (default) address 0200. If the tests are successful, it must print 31 dots and halt at the PC address 1376. +- [Hellorld](soft/hellorld.oct): a program that just prints `HELLORLD!` and then halts. Tribute to [Usagi Electric](https://www.youtube.com/@UsagiElectric) (David Lovett). +- [FOCAL-69 interpreter](soft/focal69.oct): probably the most complete FOCAL programming language version that can run on an unextended PDP-8/L. + +## FAQ + +### Why bother with PDP-8 emulation in 2026? + +Among the mass-produced, non-"esoteric" architectures, PDP-8 was stucturally one of the simplest. For instance, the bit-serial version, PDP-8/S, was made just with 519 logic gates. As a result, 1) this architecture, while being mainstream enough, is one of the easiest to rebuild from scratch in an event of technological collapse, 2) its instruction set (including all the essential IOT and OPR combos) is still smaller than the modern RISC-V (which is considered minimalist on its own). Combined with fixed instruction length (just like in RISC-V, by the way) and clean instruction bit layout (just unlike RISC-V, see e.g. the bit order for its `JAL` instruction), all this makes PDP-8 a perfect target for studying and emulation. ILDEC is a project of mine that serves both of these purposes: studying and emulation. + +### What is the rationale behind this project then? Don't we already have [SIMH](https://github.com/simh/simh) / [OpenSIMH](https://opensimh.org/) and other good, accurate and well-documented emulators? Why only emulate the unextended (4K) PDP-8/L with the bare minimum of peripherals? + +Most existing PDP-8 emulators are good enough for the purpose of historical software preservation, because they not only support all existing extensions and peripherals to run all the advanced stuff that was ever written for this hardware, but also replicate the full machine logic down to the original clock speeds if you want. And I think that's really cool and something that true retro fans will really appreciate, especially considering that the Open SIMH project is led by a former DEC engineer. + +However, all that comes at a cost of increased complexity. SIMH code may be clean but it's just a lot to grasp. One of the main ILDEC's goals is to give you a **practical** (not necessarily historically accurate) recreation of the simplest commercially successful architecture of the past in the smallest possible amount of code while being as portable as possible. For example, the first ILDEC implementation was [written in Python](python/ildec.py) and contains just 191 SLOC, and that includes all the CLI interaction and some compatibility tweaks for MicroPython and CircuitPython + T-DeckARD runtimes. The core CPU logic (all supported instruction groups, indirection, autoincrements, interrupts, I/O etc) is well under 90 SLOC, and the code is very straightforward and understandable. In fact, using any implementation hosted in this repo as a reference, especially in combination with the [ISA document](pdp8_isa_ildec.md), is enough for anyone to recreate their own virtual PDP-8/L from scratch in a very short amount of time in their favorite programming language. + +### Why isn't FORTRAN-4K compiler bundled? + +While it says FORTRAN-4K, it doesn't make a lot of sense to run it on a 4K system. From the official documentation: + +> Compiler and symbol table requires locations 0003-7577 (7574(8) locations) + +So, you'll be only left with 0200 (128) words of memory. What will you compile with that? + +Meanwhile, in FOCAL-69, if we believe the same official docs, you already have about 700 words free with all math functions enabled, but can unload logarithms, exponents and trigonometry if you don't need them and get up to 1100 words for the (tokenized) program, which is quite a lot. + +### Where can I find more software for PDP-8/L? + +The main problem with software collections for retro machines is that they don't always specify which exact models any particular program works on. Some trusted sources are: + +- Mike Douglas's [DeRamp](https://deramp.com/downloads/mfe_archive/011-Digital%20Equipment%20Corporation/01%20DEC%20PDP-8%20Family%20Software/): contains a lot of relevant software and other useful materials for all PDP-8 generations. +- Vince Slyngstad's [so-much-stuff](https://so-much-stuff.com/pdp8/papertape/papertape.php): download the TAR archive from the link at the bottom, then use `labels.txt` file(s) for navigating through them. A lot of stuff there though either seems to be corrupted or requires more advanced hardware than PDP-8/L. +- [BitSavers](https://bitsavers.org/bits/DEC/pdp8/): not a lot, and most stuff also requires more advanced hardware, but still something. + +### How do I write my own software for PDP-8/L? + +Since this machine doesn't have any technical means of running an OS like DMS, TSS/8 or OS/8, your most viable options for writing programs for it are either FOCAL-69 (bundled in the repo) on the emulated machine itself, or some kind of PAL-III or MACRO-8 symbolic assemblers on the host side. I recommend two assembler options available nowadays. + +The first (and mostly recommended) option is the `pal.c` single-file assembler, which you can download, build and install like this: + +```sh +curl https://homepage.divms.uiowa.edu/~jones/pdp8/pal.txt > pal.c +cc -O2 -s -o pal pal.c +sudo cp pal /usr/local/bin/ # optional step +``` + +This assembler outputs `.lst` and `.bin` files. The latter can be fed into `conv/bin2oct.py` script to produce the `.oct` file loadable by ILDEC. Alternatively, you can generate a `.oct` file directly from the `.lst` file using AWK: + +```awk +awk '$2~/^[0-7]+/{printf "%04d: %04d\n",$2,$3}' input.lst > output.oct +``` + +The second option is [pdpnasm](https://people.csail.mit.edu/ebakke/pdp8/), but it's so minimal that it might not understand some I/O-specific mnemonics and you might have to use direct octal notation for them instead. + +To convert pdpnasm's output `.po` files into ILDEC's `.oct` files, you can use a small helper shell script called [po2oct.sh](conv/po2oct.sh) in this repo. Since both formats are plaintext, the conversion is fairly trivial. + +### What do I need to do if I want to port ILDEC to a yet unsupported platform? + +Simple: first, implement the emulation core according to [the ISA document](pdp8_isa_ildec.md), then implement the UI and `.oct` format support according to the above guidelines. Once your emulator is compatible with ILDEC on the ISA, command and format levels, you may fully call it an ILDEC port. + +## Credits + +Created by Luxferre in 2026, released into the public domain with no warranties. + +In memoriam Edson DeCastro (1938 – 2024). + +Special thanks to [Nino Ivanov](https://github.com/KedalionDaimon) for sharing a complete FOCAL-69 tape image. diff --git a/conv/bin2oct.py b/conv/bin2oct.py new file mode 100755 index 0000000..4163bc3 --- /dev/null +++ b/conv/bin2oct.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# Convert PDP-8 .bin format files to ILDEC .oct format +# Created by Luxferre in 2026, released into the public domain + +import sys + +def print_error(msg): + sys.stderr.write(f"Error: {msg}\n") + +def convert_bin_to_oct(input_path, output_path): + # Initialize memory to 0 + memory = [0] * 4096 + + try: + with open(input_path, "rb") as f: + bytes_data = f.read() + except Exception as e: + print_error(f"Failed to read input file '{input_path}': {e}") + return False + + current_address, data_frames = 0, [] + for b in bytes_data: + if b != 0xFF: + if b & 0x80 and not (b & 0x40) and len(data_frames) > 1: + break + if not (b & 0x80): + data_frames.append(b) + + if len(data_frames) < 2: + print_error("No valid binary data frames found in the input file.") + return False + + words_loaded = 0 + for i in range(0, len(data_frames) - 2, 2): + word = ((data_frames[i] & 0x3F) << 6) | (data_frames[i+1] & 0x3F) + if data_frames[i] & 0x40: + current_address = word + else: + memory[current_address] = word + words_loaded += 1 + current_address = (current_address + 1) & 0xFFF + + # Output to .oct format + try: + with open(output_path, 'w') as f: + for addr in range(4096): + if memory[addr] != 0: + f.write(f"{addr:04o}: {memory[addr]:04o}\n") + except Exception as e: + print_error(f"Failed to write output file: {e}") + return False + + print(f"Successfully converted '{input_path}' to '{output_path}' ({words_loaded} words loaded).") + return True + +def main(): + args = sys.argv if hasattr(sys, 'argv') else [] + if len(args) < 2 or len(args) > 3: + print("Usage: python3 bin2oct.py [output_oct_file]") + sys.exit(1) + + input_path = args[1] + if len(args) == 3: + output_path = args[2] + else: + # Generate default output name by replacing extension with .oct + dot_idx = input_path.rfind('.') + slash_idx = max(input_path.rfind('/'), input_path.rfind('\\')) + if dot_idx > slash_idx: + output_path = input_path[:dot_idx] + ".oct" + else: + output_path = input_path + ".oct" + + success = convert_bin_to_oct(input_path, output_path) + if not success: + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/conv/oct2rim.py b/conv/oct2rim.py new file mode 100755 index 0000000..8b0937f --- /dev/null +++ b/conv/oct2rim.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# Convert ILDEC .oct format files to PDP-8 .rim format +# Created by Luxferre in 2026, released into the public domain + +import sys + +def print_error(msg): + sys.stderr.write(f"Error: {msg}\n") + +def convert_octaddr_to_rim(input_path, output_path): + pairs = [] + line_num = 0 + try: + with open(input_path, 'r') as f: + for line in f: + line_num += 1 + # Strip comments starting with /, #, ; + clean_line = line + for comment_char in ('/', '#', ';'): + if comment_char in clean_line: + clean_line = clean_line.split(comment_char, 1)[0] + + clean_line = clean_line.strip() + if not clean_line: + continue + + if ':' not in clean_line: + print_error(f"Line {line_num}: Missing colon separator (format is 'addr: data').") + return False + + parts = clean_line.split(':', 1) + addr_str = parts[0].strip() + data_str = parts[1].strip() + + try: + addr = int(addr_str, 8) + except ValueError: + print_error(f"Line {line_num}: Invalid octal address '{addr_str}'.") + return False + + try: + data = int(data_str, 8) + except ValueError: + print_error(f"Line {line_num}: Invalid octal data '{data_str}'.") + return False + + if not (0 <= addr <= 0o7777): + print_error(f"Line {line_num}: Address '{addr_str}' ({oct(addr)}) out of 12-bit range (0-7777).") + return False + + if not (0 <= data <= 0o7777): + print_error(f"Line {line_num}: Data '{data_str}' ({oct(data)}) out of 12-bit range (0-7777).") + return False + + pairs.append((addr, data)) + except Exception as e: + print_error(f"Failed to read input file '{input_path}': {e}") + return False + + if not pairs: + print_error("No valid address:data pairs found in the input file.") + return False + + # Write RIM format + # Leader: 2 bytes of 0xFF + # For each pair: + # addr high: ((addr >> 6) & 0x3F) | 0x40 + # addr low: addr & 0x3F + # data high: (data >> 6) & 0x3F + # data low: data & 0x3F + # Trailer: 2 bytes of 0xFF + try: + with open(output_path, 'wb') as f: + # Write leader + f.write(bytes([0xFF] * 2)) + + for addr, data in pairs: + addr_hi = ((addr >> 6) & 0x3F) | 0x40 + addr_lo = addr & 0x3F + data_hi = (data >> 6) & 0x3F + data_lo = data & 0x3F + f.write(bytes([addr_hi, addr_lo, data_hi, data_lo])) + + # Write trailer + f.write(bytes([0xFF] * 2)) + except Exception as e: + print_error(f"Failed to write output file: {e}") + return False + + print(f"Successfully converted '{input_path}' to '{output_path}' ({len(pairs)} words).") + return True + +def main(): + args = sys.argv if hasattr(sys, 'argv') else [] + if len(args) < 2 or len(args) > 3: + print("Usage: python3 oct2rim.py [output_rim_file]") + sys.exit(1) + + input_path = args[1] + if len(args) == 3: + output_path = args[2] + else: + # Generate default output name by replacing extension with .rim + dot_idx = input_path.rfind('.') + slash_idx = max(input_path.rfind('/'), input_path.rfind('\\')) + if dot_idx > slash_idx: + output_path = input_path[:dot_idx] + ".rim" + else: + output_path = input_path + ".rim" + + success = convert_octaddr_to_rim(input_path, output_path) + if not success: + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/conv/po2oct.sh b/conv/po2oct.sh new file mode 100755 index 0000000..319b0e0 --- /dev/null +++ b/conv/po2oct.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# A small shell script (using POSIX AWK) to convert pdpnasm .po files into ILDEC .oct files +# Usage: po2oct.sh input.po output.oct +# Created by Luxferre in 2026, released into the public domain + +for l in $(cat "$1"); do + printf '%d\n' "0$l" +done | awk 'BEGIN{a=0}/[0-9]+/{if($1>4096)a=$1%4096;else{if($1)printf("%04o: %04o\n",a,$1);a++}}' > "$2" diff --git a/conv/rim2oct.py b/conv/rim2oct.py new file mode 100755 index 0000000..5a457be --- /dev/null +++ b/conv/rim2oct.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# Convert PDP-8 .rim format files to ILDEC .oct format +# Created by Luxferre in 2026, released into the public domain + +import sys + +def print_error(msg): + sys.stderr.write(f"Error: {msg}\n") + +def convert_rim_to_oct(input_path, output_path): + # Initialize memory to 0 + memory = [0] * 4096 + + try: + with open(input_path, "rb") as f: + raw_data = f.read() + except Exception as e: + print_error(f"Failed to read input file '{input_path}': {e}") + return False + + # Filter out bytes with MSB set (bit 7) + data = [b for b in raw_data if not (b & 0x80)] + + i = 0 + words_loaded = 0 + while i < len(data) - 1: + word = ((data[i] & 0x3F) << 6) | (data[i+1] & 0x3F) + if data[i] & 0x40 and i + 3 < len(data): + addr = word + val = ((data[i+2] & 0x3F) << 6) | (data[i+3] & 0x3F) + memory[addr] = val + words_loaded += 1 + i += 4 + else: + i += 2 + + # Output to .oct format + try: + with open(output_path, 'w') as f: + for addr in range(4096): + if memory[addr] != 0: + f.write(f"{addr:04o}: {memory[addr]:04o}\n") + except Exception as e: + print_error(f"Failed to write output file: {e}") + return False + + print(f"Successfully converted '{input_path}' to '{output_path}' ({words_loaded} words loaded).") + return True + +def main(): + args = sys.argv if hasattr(sys, 'argv') else [] + if len(args) < 2 or len(args) > 3: + print("Usage: python3 rim2oct.py [output_oct_file]") + sys.exit(1) + + input_path = args[1] + if len(args) == 3: + output_path = args[2] + else: + # Generate default output name by replacing extension with .oct + dot_idx = input_path.rfind('.') + slash_idx = max(input_path.rfind('/'), input_path.rfind('\\')) + if dot_idx > slash_idx: + output_path = input_path[:dot_idx] + ".oct" + else: + output_path = input_path + ".oct" + + success = convert_rim_to_oct(input_path, output_path) + if not success: + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/pdp8_isa_ildec.md b/pdp8_isa_ildec.md new file mode 100644 index 0000000..8b4dec5 --- /dev/null +++ b/pdp8_isa_ildec.md @@ -0,0 +1,262 @@ +# DEC PDP-8/L Emulation Core Instruction Set Architecture + +This document provides a detailed reference of the PDP-8/L instruction set implemented in the ILDEC emulation core. + +--- + +## 1. Architectural Overview & State + +The emulator models a simplified 12-bit DEC PDP-8/L processor. CPU registers and state are defined as follows: + +* **`memory`**: An array of 4,096 12-bit words (a single 4K memory field). +* **`pc` (Program Counter)**: 12-bit register holding the address offset of the next instruction. +* **`ac` (Accumulator)**: 12-bit register used for arithmetic, logic, and I/O. +* **`link` (Link Register)**: 1-bit register functioning as a carry/overflow indicator, logically positioned to the left of the Accumulator for shifts. +* **sr` (Switch Register)**: 12-bit register representing front panel switches, queried via operate instructions. +* **Program Interrupt Registers**: + * `ie` (Interrupt Enable Flag): 1-bit register controlling the interrupt system. + * `ion_delay` (Interrupt On Delay): Counter managing the 1-instruction latency for enabling interrupts. +* **Peripheral Buffers & Flags**: + * `kbb` (Keyboard Buffer) & `kbf` (Keyboard Flag) + * `chb` (Character Buffer) & `chf` (Character Flag) + +--- + +## 2. Memory Addressing System + +Memory is organized into **32 pages of 128 words each** (4,096 words total). + +Memory Reference Instructions (MRIs) contain a 9-bit address specification block. The bits are mapped as follows: + +``` + 3 4 5 6 7 8 9 10 11 ++---+---+---+---+---+---+---+---+---+ +| I | Z | 7-bit Page Offset | ++---+---+---+---+---+---+---+---+---+ +``` + +* **Bit 3 (`I` - Indirect Address Bit)**: + * `0`: Direct addressing. + * `1`: Indirect addressing. +* **Bit 4 (`Z` - Sector/Page Select Bit)**: + * `0`: Page 0 (addresses `0o0000` to `0o0177`). + * `1`: Current Page (the page containing the instruction being executed). +* **Bits 5–11 (Page Offset)**: 7-bit relative address (`0` to `127`). + +### Target Address Resolution Flow + +1. **Base Address Offset Calculation**: + * If `Z = 1`: The 5 high-bits of the current `PC` are combined with the 7-bit offset: + $$\text{Base Target} = (\text{PC} \ \& \ \text{0xF80}) \ | \ \text{Offset}$$ + * If `Z = 0`: The base target is within Page 0: + $$\text{Base Target} = \text{Offset}$$ +2. **Effective Address Calculation**: + * **Direct Addressing (`I = 0`)**: + $$\text{Effective Address} = \text{Base Target}$$ + * **Indirect Addressing (`I = 1`)**: + * The pointer address is the base target: + $$\text{Pointer Address} = \text{Base Target}$$ + * **Auto-Indexing**: If the base target is in the range `8` to `15` (`0o0010` to `0o0017` in octal), the pointer word is incremented by 1 (modulo 4096) and written back to memory: + $$\text{Memory}[\text{Pointer Address}] = (\text{Memory}[\text{Pointer Address}] + 1) \ \& \ \text{0xFFF}$$ + * The 12-bit target pointer offset is read from the pointer address: + $$\text{Effective Address} = \text{Memory}[\text{Pointer Address}]$$ + +--- + +## 3. Instruction Set Details + +Every instruction is 12 bits wide. The top 3 bits (bits 0–2) specify the opcode. + +``` + 0 1 2 3 4 5 6 7 8 9 10 11 ++---+---+---+---+---+---+---+---+---+---+---+---+ +| Opcode | Rest of Instruction | ++---+---+---+---+---+---+---+---+---+---+---+---+ +``` + +--- + +### 3.1. Memory Reference Instructions (Opcodes 0–5) + +These instructions perform operations involving memory locations. + +| Opcode | Octal | Mnemonic | Description | Py-8-S Emulation Core Logic | +| :---: | :---: | :--- | :--- | :--- | +| `0` | `0o0` | **AND** | Logical AND | `self.ac &= self.memory[target_addr]` | +| `1` | `0o1` | **TAD** | Two's Complement Add | `val = self.ac + self.memory[target_addr]`
`self.ac = val & 0xFFF`
`self.link ^= (val >> 12)` *(Carry toggles Link)* | +| `2` | `0o2` | **ISZ** | Increment and Skip if Zero | `self.memory[target_addr] = (self.memory[target_addr] + 1) & 0xFFF`
`if self.memory[target_addr] == 0: PC = (PC + 1) & 0xFFF` | +| `3` | `0o3` | **DCA** | Deposit and Clear AC | `self.memory[target_addr] = self.ac`
`self.ac = 0` | +| `4` | `0o4` | **JMS** | Jump to Subroutine | `self.memory[target_addr] = self.pc`
`self.pc = (target_addr + 1) & 0xFFF` | +| `5` | `0o5` | **JMP** | Jump | `self.pc = target_addr & 0xFFF` | + +--- + +### 3.2. Input/Output Transfer (IOT) Instructions (Opcode 6) + +IOT instructions control and transfer data to/from peripheral devices. The instruction format is: +* **Device Code (`dev`)**: Bits 3–8 (6 bits, range 0–63). +* **Sub-operation (`op`)**: Bits 9–11 (3 bits, range 0–7). + +#### Device 0: Interrupt Control (Program Interrupt System) +Manages the CPU's Program Interrupt (PI) system. + +* **`6001` (ION - Interrupt Turn On)**: Enables the program interrupt system. The interrupt system is enabled after the execution of the instruction following ION. +* **`6002` (IOF - Interrupt Turn Off)**: Disables the program interrupt system immediately. +* **`6003` (SRQ - Skip on Interrupt Request)**: Skips the next instruction if a device interrupt request is pending: + `if self.kbf or self.chf: PC = PC + 1` +* **`6004` (GTF - Get Flags)**: Loads various processor flags into the Accumulator: + * AC Bit 0: Link Register (`self.link`) + * AC Bit 2: Interrupt Request (`self.kbf or self.chf`) + * AC Bit 4: Interrupt Enable Flip-Flop (`self.ie`) + * All other bits are cleared to `0`. +* **`6005` (RTF - Restore Flags)**: Restores flags from the Accumulator: + * Link is restored from AC Bit 0: `self.link = (self.ac >> 11) & 1` + * Enables interrupts with a one-instruction delay (equivalent to `ION`). +* **`6007` (CAF - Clear All Flags)**: Resets the processor and I/O status: + * Clears Accumulator and Link: `self.ac = self.link = 0` + * Clears I/O device buffers/flags: `self.kbf = self.kbb = self.chf = self.chb = 0` + * Disables the program interrupt system: `self.ie = self.ion_delay = 0` + +#### Device 3: Keyboard / Reader +Interfaces with the standard keyboard/character input. + +* **Micro-programmed Keyboard Operations (bits 9, 10, 11)**: + * **Bit 11** (`op & 1`): Skip on Keyboard Flag. + * **Bit 10** (`(op >> 1) & 1`): Clear Accumulator and Keyboard Flag. + * **Bit 9** (`op >> 2`): OR Keyboard Buffer into the Accumulator. + + Combined, these bits form the standard Keyboard instructions: + * **`6031` (KSF - Keyboard Skip on Flag)**: `if self.kbf: PC = PC + 1` + * **`6032` (KCC - Keyboard Clear Flag)**: `self.ac = self.kbf = 0` + * **`6034` (KRS - Keyboard Read Static)**: `self.ac |= self.kbb` + * **`6036` (KRB - Keyboard Read Buffer)**: `self.ac = self.kbf = 0` followed by `self.ac |= self.kbb` + +#### Device 4: Teleprinter / Punch +Interfaces with the standard teleprinter/character output. + +* **`6040` (Custom IOT: Force Teleprinter Flag)**: + Forces the teleprinter flag to high (`chf = 1`). +* **Micro-programmed Teleprinter Operations (bits 9, 10, 11)**: + * **Bit 11** (`op & 1`): Skip on Teleprinter Flag. + * **Bit 10** (`(op >> 1) & 1`): Clear Teleprinter Flag. + * **Bit 9** (`op >> 2`): Load Accumulator into Character Buffer, trigger write callback, and set Teleprinter Flag. + + Combined, these bits form the standard Teleprinter instructions: + * **`6041` (TSF - Teleprinter Skip on Flag)**: `if self.chf: PC = PC + 1` + * **`6042` (TCF - Teleprinter Clear Flag)**: `self.chf = 0` + * **`6044` (TPC - Teleprinter Print Character)**: `self.chb = self.ac; self.chf = 1; self.outc(self.ac)` + * **`6046` (TLS - Teleprinter Load Sequence)**: `self.chf = 0; self.chb = self.ac; self.chf = 1; self.outc(self.ac)` + +--- + +### 3.3. Operate Instructions (Opcode 7) + +Operate (OPR) instructions are register manipulation commands. They do not reference memory addresses. The lower 9 bits function as micro-programmed instruction controls. + +> [!NOTE] +> If the lower 9 bits are `0` (`7000`) or `0o401` (`7401`), the instruction is treated as a `NOP` (No Operation) and returns immediately. + +#### Sub-group Determination +* **Bit 3** (MSB of the instruction's lower 9 bits): + * If `0`: **Group 1** (Register manipulation, complements, and shifts). + * If `1`: **Group 2** (Status testing, skips, and halt). + * *Note: Group 3 (EAE/MQ register operations) is not supported.* + +--- + +#### Group 1 Operate Instructions (Bit 3 = 0) + +Used for bitwise operations, clearing registers, incrementing, and rotations. + +``` + 3 4 5 6 7 8 9 10 11 ++---+---+---+---+---+---+---+---+---+ +| 0 |CLA|CLL|CMA|CML|RAR|RAL|BSW|IAC| ++---+---+---+---+---+---+---+---+---+ +``` + +##### Bit Mapping & Function +* **Bit 4 (`CLA`)**: Clear Accumulator. +* **Bit 5 (`CLL` / `b5`)**: Clear Link. +* **Bit 6 (`CMA` / `b6`)**: Complement Accumulator. +* **Bit 7 (`CML` / `b7`)**: Complement Link. +* **Bit 8 (`RAR` / `b8`)**: Rotate Accumulator and Link Right. +* **Bit 9 (`RAL` / `b9`)**: Rotate Accumulator and Link Left. +* **Bit 10 (`BSW` / `b10`)**: Byte Swap / Rotate Command Modifier. + * If `RAR` or `RAL` is active: Specifies double rotation (rotate 2 positions). + * If neither `RAR` nor `RAL` is active: Swaps the high and low 6-bit halves of `AC`: + `self.ac = ((self.ac << 6) | (self.ac >> 6)) & 0xFFF` +* **Bit 11 (`IAC` / `b11`)**: Increment Accumulator. + +##### Execution Order +Group 1 micro-operations are executed sequentially in the following order: + +1. **Clear**: + * If `CLA` is `1`: `self.ac = 0` + * If `CLL` is `1`: `self.link = 0` +2. **Complement**: + * If `CMA` is `1`: `self.ac ^= 0xFFF` + * If `CML` is `1`: `self.link ^= 1` +3. **Increment**: + * If `IAC` is `1`: + `self.ac, self.link = (self.ac + 1) & 0xFFF, self.link ^ ((self.ac + 1) >> 12)` *(Carry toggles Link)* +4. **Rotation / Swap**: + * If `RAR` is `1`: Circular right rotate `b10 + 1` times of the 13-bit combined register `[Link, AC]`. + * If `RAL` is `1`: Circular left rotate `b10 + 1` times of the 13-bit combined register `[Link, AC]`. + * If `BSW` is `1` and neither `RAR` nor `RAL` is active: Swaps the high and low 6-bit halves of `AC`: + `self.ac = ((self.ac << 6) | (self.ac >> 6)) & 0xFFF` + +--- + +#### Group 2 Operate Instructions (Bit 3 = 1, Bit 11 = 0) + +Used for conditional skips, input register integration, and program termination. + +``` + 3 4 5 6 7 8 9 10 11 ++---+---+---+---+---+---+---+---+---+ +| 1 |CLA|SMA|SZA|SNL|REV|OSR|HLT| 0 | ++---+---+---+---+---+---+---+---+---+ +``` + +##### Bit Mapping & Function +* **Bit 4 (`CLA`)**: Clear Accumulator. +* **Bit 5 (`SMA` / `b5`)**: Skip on Minus Accumulator (`AC & 0x800` is set / `AC > 0x7FF`). +* **Bit 6 (`SZA` / `b6`)**: Skip on Zero Accumulator (`AC == 0`). +* **Bit 7 (`SNL` / `b7`)**: Skip on Non-Zero Link (`Link == 1`). +* **Bit 8 (`REV` / `b8`)**: Reverse skip condition sense (OR group if `0`, AND group if `1`). +* **Bit 9 (`OSR` / `b9`)**: OR AC with Switch Register. +* **Bit 10 (`HLT` / `b10`)**: Halt processor execution. + +##### Condition Evaluation & Skip Logic +1. **Or Group (`REV = 0`)**: + Skips the next instruction if *any* of the enabled conditions are true: + $$\text{Skip} \iff (\text{SMA} \land \text{AC} < 0) \lor (\text{SZA} \land \text{AC} == 0) \lor (\text{SNL} \land \text{Link} \ne 0)$$ +2. **And Group (`REV = 1`)**: + Skips the next instruction if *none* of the enabled conditions are true. This evaluates to: + $$\text{Skip} \iff (\neg\text{SMA} \lor \text{AC} \ge 0) \land (\neg\text{SZA} \lor \text{AC} \ne 0) \land (\neg\text{SNL} \lor \text{Link} == 0)$$ + +##### Execution Order +Group 2 micro-operations execute sequentially in the following order: + +1. **Skip Condition**: Evaluate conditions and increment `PC` if met: + `if any_cond != b8: self.pc = (self.pc + 1) & 0xFFF` +2. **Clear**: + * If `CLA` is `1`: `self.ac = 0` +3. **OR Switch Register**: + * If `OSR` is `1`: `self.ac |= self.sr` +4. **Halt**: + * If `HLT` is `1`: `self.halted = True` + +--- + +## 4. Emulation & Support Control Mechanisms + +### 4.1. Loader format +Octal tape images are loaded with the `load_oct` function. The loader parses files containing lines of `addr: value` configurations, storing values directly in standard memory locations. In this simplified core, all loaded addresses are masked with `0xFFF` to restrict them to the 4K word field limit. + +### 4.2. Program Interrupt Mechanism +When the program interrupt system is enabled (`self.ie == 1`) and a device interrupt request is active (either `self.kbf == 1` or `self.chf == 1`), the CPU executes the interrupt sequence at the start of an instruction step: +1. Interrupts are disabled: `self.ie = 0` +2. The current Program Counter (`self.pc`) is saved to memory location `0`. +3. The Program Counter is set to `1` (`self.pc = 1`), branching control to the interrupt handler. diff --git a/python/ildec.py b/python/ildec.py new file mode 100755 index 0000000..8850897 --- /dev/null +++ b/python/ildec.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +# ILDEC: a minimalistic DEC PDP-8/L emulation core in (Micro)Python +# See README.md for the usage guide +# Created by Luxferre in 2026, released into the public domain + +import sys +try: + import select +except ImportError: + select = None +from array import array + +try: # T-DeckARD workaround + from deck.input import input + from repl.tdeck_repl import Pydos_ui + def default_keyboard_check(pdp8): + if pdp8.kbd_delay <= 0: + pdp8.kbd_delay = 1000 + if Pydos_ui.serial_bytes_available(): + c = Pydos_ui.read_keyboard(1) + b = ord(c) if c else None + if b == 4 or c == "": + pdp8.halted = True + return + if b is not None: + pdp8.kbb, pdp8.kbf, pdp8.kbd_delay = (13 if b == 10 else b) | 0x80, 1, 500 +except: + def default_keyboard_check(pdp8): + try: + if pdp8.kbd_delay <= 0: + pdp8.kbd_delay = 1000 + try: + import supervisor + has_bytes = supervisor.runtime.serial_bytes_available + except (ImportError, AttributeError): + has_bytes = pdp8.poller.poll(0) if pdp8.poller else (select.select([sys.stdin], [], [], 0)[0] if select else False) + if has_bytes: + try: + import os; b, c = os.read(0, 1)[0], None + except Exception: + c = sys.stdin.read(1) + b = ord(c) if c else None + if b == 4 or c == "": + pdp8.halted = True + return + if b is not None: + pdp8.kbb, pdp8.kbf, pdp8.kbd_delay = (13 if b == 10 else b) | 0x80, 1, 500 + except Exception: pass + +def set_cbreak(enable): + try: + import termios + fd = sys.stdin.fileno() + if enable: + import tty; tty.setcbreak(fd) + else: + attr = termios.tcgetattr(fd) + attr[3] |= (termios.ICANON | termios.ECHO) + termios.tcsetattr(fd, termios.TCSADRAIN, attr) + except Exception: pass + +def char_output(c): + sys.stdout.write(chr(c & 0x7F)) + if hasattr(sys.stdout, 'flush'): sys.stdout.flush() + +class ILDEC_PDP8: + def __init__(self, init_pc=0, init_sr=0, keyboard_check = None, outchar_cb = None): + self.memory = array('H', [0] * 4096) + self.kbdcheck, self.outc = keyboard_check or default_keyboard_check, outchar_cb or char_output + self.reset(init_pc, init_sr) + self.poller = None + try: + import supervisor + except ImportError: + try: + if select: + self.poller = select.poll() + self.poller.register(sys.stdin, select.POLLIN) + except Exception: pass + + def reset(self, pcval=0, srval=0): + self.link = self.ac = self.kbb = self.kbf = self.chb = self.chf = self.kbd_delay = 0 + self.ie = self.ion_delay = 0 + self.pc, self.sr, self.halted = pcval, srval, False + + def start(self, start_addr=0o200): + self.pc, self.halted = start_addr, False + set_cbreak(True) + try: + while not self.halted: self.step() + finally: set_cbreak(False) + + def rotate_ac_link(self, dir, times): + for _ in range(times): + if dir > 0: self.ac, self.link = (self.ac >> 1) | (self.link << 11), self.ac & 1 + else: self.ac, self.link = ((self.ac << 1) | self.link) & 0xFFF, self.ac >> 11 + + def step(self): + if self.halted: return + if not self.kbf: self.kbdcheck(self) + if self.halted: return + if self.kbd_delay > 0: self.kbd_delay -= 1 + if self.ion_delay > 0: + self.ion_delay -= 1 + if self.ion_delay == 0: self.ie = 1 + if self.ie and (self.kbf or self.chf): + self.ie, self.memory[0], self.pc = 0, self.pc, 1 + instruction, current_pc = self.memory[self.pc], self.pc + self.pc = (current_pc + 1) & 0xFFF + opcode, rest = (instruction >> 9) & 7, instruction & 511 + if opcode < 6: + target = (current_pc & 0xF80 if rest & 0x80 else 0) | (rest & 0x7F) + if rest & 0x100: + if 8 <= target <= 15: self.memory[target] = (self.memory[target] + 1) & 0xFFF + target = self.memory[target] + if opcode == 0: self.ac &= self.memory[target] + elif opcode == 1: + self.ac, self.link = (self.ac + self.memory[target]) & 0xFFF, self.link ^ ((self.ac + self.memory[target]) >> 12) + elif opcode == 2: + self.memory[target] = (self.memory[target] + 1) & 0xFFF + if not self.memory[target]: self.pc = (self.pc + 1) & 0xFFF + elif opcode == 3: self.memory[target], self.ac = self.ac, 0 + elif opcode == 4: self.memory[target], self.pc = self.pc, (target + 1) & 0xFFF + elif opcode == 5: self.pc = target & 0xFFF + elif opcode == 6: self.execute_iot(rest) + elif opcode == 7: self.execute_opr(rest) + + def execute_opr(self, opr): + if opr in (0, 0o401): return + group = 1 if not (opr & 0x100) else (3 if (opr & 1) else 2) + b10 = (opr >> 1) & 1 + if group == 1: + if opr & 0x80: self.ac = 0 + if opr & 0x40: self.link = 0 + if opr & 0x20: self.ac ^= 0xFFF + if opr & 0x10: self.link ^= 1 + if opr & 1: self.ac, self.link = (self.ac + 1) & 0xFFF, self.link ^ ((self.ac + 1) >> 12) + if opr & 0x08: self.rotate_ac_link(1, b10 + 1) + if opr & 0x04: self.rotate_ac_link(-1, b10 + 1) + if b10 and not (opr & 0x0C): self.ac = ((self.ac << 6) | (self.ac >> 6)) & 0xFFF + elif group == 2: + if bool(((opr & 0x40) and self.ac > 0x7FF) or ((opr & 0x20) and not self.ac) or ((opr & 0x10) and self.link)) != bool(opr & 0x08): self.pc = (self.pc + 1) & 0xFFF + if opr & 0x80: self.ac = 0 + if opr & 0x04: self.ac |= self.sr + if b10: self.halted = True + + def execute_iot(self, cmd): + dev, op = (cmd >> 3) & 63, cmd & 7 + if dev == 0: + if op == 1: self.ion_delay = 2 + elif op == 2: self.ie = self.ion_delay = 0 + elif op == 3 and (self.kbf or self.chf): self.pc = (self.pc + 1) & 0xFFF + elif op == 4: self.ac = (self.link << 11) | ((1 if (self.kbf or self.chf) else 0) << 9) | (self.ie << 7) + elif op == 5: self.link, self.ion_delay = (self.ac >> 11) & 1, 2 + elif op == 7: + self.ac = self.link = self.kbf = self.kbb = self.chf = self.chb = self.ie = self.ion_delay = 0 + elif dev == 3 and op != 5: + if (op & 1) and self.kbf: self.pc = (self.pc + 1) & 0xFFF + if op & 2: self.ac = self.kbf = 0 + if op & 4: self.ac |= self.kbb + elif dev == 4 and op != 5: + if op == 0: self.chf = 1 + else: + if (op & 1) and self.chf: self.pc = (self.pc + 1) & 0xFFF + if op & 2: self.chf = 0 + if op & 4: self.chb, self.chf = self.ac, 1; self.outc(self.ac) + + def load_oct(self, filepath): + with open(filepath, 'r') as f: + for line in f: + try: + p = line.split(':') + self.memory[int(p[0], 8) & 0xFFF] = int(p[1].strip().split()[0], 8) + except Exception: pass + +# entry point (for ildec.py to be usable as a module) +def ildec(fname='', init_pc=0o200, init_sr=0): + print('\n ===== ILDEC PDP-8/L ONLINE =====') + emu = ILDEC_PDP8(init_pc, init_sr) + if fname: emu.load_oct(fname) + while True: + print(f"\nPC: {emu.pc:04o} | L AC: {emu.link} {emu.ac:04o} | SR: {emu.sr:04o}\n") + cmd = input('> ').strip().lower() + if cmd == 'q': break + elif cmd == 'r': emu.reset(init_pc, init_sr) + elif cmd == 'n': emu.__init__(init_pc, init_sr), print('All memory cleared!') + elif cmd == 'c': emu.start(emu.pc) + elif cmd == 'l': emu.pc = emu.sr + elif cmd == 's': emu.step() + elif cmd in ('e', 'd'): + if cmd == 'd': emu.memory[emu.pc] = emu.sr + print(f"{emu.pc:04o}: {emu.memory[emu.pc]:04o}") + emu.pc = (emu.pc + 1) & 0xFFF + elif cmd == 'i': + fname = input('File path: ').strip() + if fname: emu.load_oct(fname); print(f'Memory imported from {fname}') + elif cmd == 'x': + fname = input('File path: ').strip() + if fname: + with open(fname, 'w') as f: + for i, val in enumerate(emu.memory): + if val: f.write(f"{i:04o}: {val:04o}\n") + print(f'Memory exported to {fname}') + else: + try: emu.sr = int(cmd, 8) + except Exception: print('Invalid action!') + +# Run it standalone +if __name__ == '__main__': + a = sys.argv if hasattr(sys, 'argv') else [] + ildec(a[1] if len(a) > 1 else '', int(a[2], 8) if len(a) > 2 else 0o200, int(a[3], 8) if len(a) > 3 else 0) diff --git a/soft/focal69.oct b/soft/focal69.oct new file mode 100644 index 0000000..9452d37 --- /dev/null +++ b/soft/focal69.oct @@ -0,0 +1,3338 @@ +0001: 5403 +0002: 5403 +0003: 2603 +0004: 0004 +0005: 0013 +0006: 0100 +0007: 6400 +0013: 4370 +0014: 3117 +0016: 7402 +0017: 3215 +0022: 2407 +0026: 0001 +0031: 3760 +0035: 4370 +0051: 6603 +0052: 2004 +0053: 6724 +0057: 7760 +0060: 3760 +0061: 1354 +0062: 2414 +0063: 2676 +0064: 2666 +0065: 0001 +0066: 0215 +0070: 0005 +0072: 0214 +0073: 0207 +0074: 0203 +0075: 0337 +0076: 0212 +0077: 0215 +0100: 7402 +0101: 7700 +0102: 0256 +0103: 7701 +0104: 7600 +0105: 7760 +0106: 0177 +0107: 0017 +0110: 0277 +0111: 7776 +0112: 7477 +0113: 0260 +0114: 7540 +0115: 7522 +0116: 7563 +0117: 7775 +0120: 7773 +0121: 7767 +0122: 0077 +0123: 0200 +0124: 4000 +0125: 2030 +0126: 2155 +0127: 5715 +0130: 6000 +0131: 6200 +0132: 3140 +0133: 3206 +0134: 3140 +0135: 3217 +0136: 2017 +0137: 2407 +0140: 0521 +0141: 1565 +0142: 0477 +0143: 0534 +0144: 0554 +0145: 2274 +0146: 2502 +0147: 1314 +0150: 0721 +0151: 2465 +0152: 2155 +0153: 2425 +0154: 0302 +0155: 2242 +0156: 2360 +0157: 0413 +0160: 1517 +0161: 1533 +0162: 2035 +0163: 0744 +0164: 0700 +0165: 2062 +0166: 2726 +0176: 4371 +0177: 7610 +0200: 5576 +0201: 1137 +0202: 3022 +0203: 7001 +0204: 3100 +0205: 3026 +0206: 1226 +0207: 3013 +0210: 1225 +0211: 4551 +0212: 1132 +0213: 3010 +0214: 3062 +0215: 1132 +0216: 3027 +0217: 4552 +0220: 4547 +0221: 0073 +0222: 0474 +0223: 4546 +0224: 5217 +0225: 0252 +0226: 3220 +0227: 4546 +0230: 4546 +0231: 1132 +0232: 3017 +0233: 3020 +0234: 4545 +0235: 1035 +0236: 3013 +0237: 4560 +0240: 4561 +0241: 5362 +0242: 5271 +0243: 2026 +0244: 4554 +0245: 1124 +0246: 1065 +0247: 7640 +0250: 4566 +0251: 1060 +0252: 3010 +0253: 3062 +0254: 1067 +0255: 3410 +0256: 4560 +0257: 7410 +0260: 4545 +0261: 4546 +0262: 1066 +0263: 1116 +0264: 7640 +0265: 5260 +0266: 4565 +0267: 4556 +0270: 5177 +0271: 4540 +0272: 0611 +0273: 1422 +0274: 7450 +0275: 5177 +0276: 3022 +0277: 1022 +0300: 7001 +0301: 5232 +0303: 4560 +0304: 1066 +0305: 1112 +0306: 7650 +0307: 5322 +0310: 3036 +0311: 4771 +0312: 1047 +0313: 0372 +0314: 1046 +0315: 7640 +0316: 4566 +0317: 1047 +0320: 4557 +0321: 7004 +0322: 3067 +0323: 4561 +0324: 4545 +0325: 4561 +0326: 5340 +0327: 5352 +0330: 1054 +0331: 7106 +0332: 1054 +0333: 7004 +0334: 1067 +0335: 3067 +0336: 4545 +0337: 4561 +0340: 4566 +0341: 5352 +0342: 1054 +0343: 1067 +0344: 3067 +0345: 4545 +0346: 4561 +0347: 5340 +0350: 7410 +0351: 4566 +0352: 7100 +0353: 1067 +0354: 0104 +0355: 7640 +0356: 7020 +0357: 1067 +0360: 0106 +0361: 7460 +0362: 4566 +0363: 7640 +0364: 1373 +0365: 7020 +0366: 7004 +0367: 3065 +0370: 5702 +0371: 5600 +0372: 7740 +0373: 2000 +0374: 2014 +0375: 2010 +0376: 1160 +0377: 1142 +0400: 1553 +0401: 1343 +0402: 5000 +0403: 4620 +0404: 5040 +0405: 5205 +0406: 5200 +0407: 7400 +0410: 2725 +0411: 2725 +0412: 2725 +0414: 7106 +0415: 7006 +0416: 7006 +0417: 5613 +0420: 4554 +0421: 1022 +0422: 4542 +0423: 4543 +0424: 0017 +0425: 4543 +0426: 0065 +0427: 1065 +0430: 7710 +0431: 5263 +0432: 4555 +0433: 7000 +0434: 1023 +0435: 3011 +0436: 1411 +0437: 4563 +0440: 4566 +0441: 4540 +0442: 0606 +0443: 4544 +0444: 0065 +0445: 1422 +0446: 7450 +0447: 5271 +0450: 7001 +0451: 3030 +0452: 1065 +0453: 7740 +0454: 5260 +0455: 1430 +0456: 4563 +0457: 5271 +0460: 1430 +0461: 3067 +0462: 5225 +0463: 4555 +0464: 4566 +0465: 4540 +0466: 0610 +0467: 4544 +0470: 0065 +0471: 4544 +0472: 0017 +0473: 1413 +0474: 3022 +0475: 5676 +0476: 0611 +0500: 3071 +0501: 7040 +0502: 4310 +0503: 1071 +0504: 3413 +0505: 7040 +0506: 4310 +0507: 5677 +0511: 1013 +0512: 3013 +0513: 1013 +0514: 7141 +0515: 1031 +0516: 7630 +0517: 4566 +0520: 5710 +0522: 1721 +0523: 3071 +0524: 7040 +0525: 4310 +0526: 1321 +0527: 7001 +0530: 3413 +0531: 7040 +0532: 4310 +0533: 5471 +0535: 7240 +0536: 1734 +0537: 3011 +0540: 2334 +0541: 1117 +0542: 4310 +0543: 1117 +0544: 3071 +0545: 1411 +0546: 3413 +0547: 2071 +0550: 5345 +0551: 1117 +0552: 4310 +0553: 5734 +0555: 7240 +0556: 1754 +0557: 2354 +0560: 3011 +0561: 1117 +0562: 3071 +0563: 1413 +0564: 3411 +0565: 2071 +0566: 5363 +0567: 5754 +0570: 2740 +0571: 0212 +0572: 0217 +0573: 0227 +0574: 1075 +0575: 1137 +0576: 2725 +0577: 1065 +0600: 0610 +0601: 0614 +0602: 7472 +0603: 4554 +0604: 4555 +0605: 4566 +0606: 1023 +0607: 3022 +0610: 4545 +0611: 1066 +0612: 1116 +0613: 7650 +0614: 5541 +0615: 4550 +0616: 1376 +0617: 5210 +0620: 1066 +0621: 0075 +0622: 4542 +0623: 4545 +0624: 4550 +0625: 1376 +0626: 7410 +0627: 5223 +0630: 1413 +0631: 4547 +0632: 0773 +0633: 0167 +0634: 4566 +0635: 4554 +0636: 2026 +0637: 4555 +0640: 5267 +0641: 1067 +0642: 7640 +0643: 4553 +0644: 4545 +0645: 4551 +0646: 1066 +0647: 1116 +0650: 7640 +0651: 5244 +0652: 1423 +0653: 7450 +0654: 5271 +0655: 7001 +0656: 3030 +0657: 1065 +0660: 7700 +0661: 1430 +0662: 4563 +0663: 5273 +0664: 1430 +0665: 3067 +0666: 5237 +0667: 1023 +0670: 5253 +0671: 3026 +0672: 5541 +0673: 1065 +0674: 7750 +0675: 5271 +0676: 4551 +0677: 5264 +0701: 4560 +0702: 4550 +0703: 1767 +0704: 5700 +0705: 1066 +0706: 2300 +0707: 1202 +0710: 7650 +0711: 5317 +0712: 4561 +0713: 5700 +0714: 7410 +0715: 5700 +0716: 2300 +0717: 2300 +0720: 5700 +0722: 1721 +0723: 3012 +0724: 1412 +0725: 7510 +0726: 5340 +0727: 7041 +0730: 1066 +0731: 7640 +0732: 5324 +0733: 1721 +0734: 7040 +0735: 1012 +0736: 3054 +0737: 7410 +0740: 2321 +0741: 2321 +0742: 7300 +0743: 5721 +0745: 0104 +0746: 7041 +0747: 3071 +0750: 1067 +0751: 0104 +0752: 1071 +0753: 7650 +0754: 2344 +0755: 5744 +0757: 1036 +0760: 7640 +0761: 5364 +0762: 4545 +0763: 5756 +0764: 4552 +0765: 4547 +0766: 6776 +0767: 3402 +0770: 5756 +0771: 1035 +0772: 0610 +0773: 0614 +0774: 0323 +0775: 0306 +0776: 0311 +0777: 0304 +1000: 0307 +1001: 0303 +1002: 0301 +1003: 0324 +1004: 0314 +1005: 0305 +1006: 0327 +1007: 0315 +1010: 0321 +1011: 0322 +1012: 0212 +1013: 4564 +1014: 4637 +1015: 2013 +1016: 4640 +1017: 1111 +1020: 3032 +1021: 1045 +1022: 7510 +1023: 2032 +1024: 7750 +1025: 2032 +1026: 7410 +1027: 5767 +1030: 4547 +1031: 1377 +1032: 7371 +1033: 4545 +1034: 5230 +1035: 4545 +1036: 5225 +1037: 1601 +1040: 2047 +1041: 4540 +1042: 1403 +1043: 4560 +1044: 1066 +1045: 1335 +1046: 7440 +1047: 4566 +1050: 1030 +1051: 4542 +1052: 4540 +1053: 1612 +1054: 1413 +1055: 3030 +1056: 4407 +1057: 6430 +1061: 4547 +1062: 1377 +1063: 7177 +1064: 4566 +1065: 1030 +1066: 4542 +1067: 4540 +1070: 1612 +1071: 4547 +1072: 1377 +1073: 7174 +1074: 4566 +1075: 4543 +1076: 2030 +1077: 4540 +1100: 1612 +1101: 4543 +1102: 2030 +1103: 4543 +1104: 0017 +1105: 4540 +1106: 0610 +1107: 4544 +1110: 0017 +1111: 4544 +1112: 2030 +1113: 4544 +1114: 7470 +1115: 1413 +1116: 3030 +1117: 4407 +1120: 0430 +1121: 1733 +1122: 6430 +1123: 2525 +1125: 1045 +1126: 7740 +1127: 5541 +1130: 1030 +1131: 4542 +1132: 4543 +1133: 7470 +1134: 5301 +1135: 7503 +1136: 7524 +1137: 4543 +1140: 2405 +1141: 5301 +1142: 4453 +1143: 4542 +1144: 1066 +1145: 1336 +1146: 7640 +1147: 4566 +1150: 4540 +1151: 1612 +1152: 4453 +1153: 6063 +1154: 7200 +1155: 1413 +1156: 6057 +1157: 7410 +1160: 4453 +1161: 7200 +1162: 5536 +1163: 1041 +1164: 1041 +1165: 1013 +1166: 0420 +1167: 0603 +1170: 0614 +1171: 1202 +1172: 1203 +1173: 7503 +1174: 2204 +1175: 0635 +1176: 1256 +1177: 0177 +1200: 1563 +1201: 6361 +1202: 7240 +1203: 3056 +1204: 3026 +1205: 4547 +1206: 1371 +1207: 0176 +1210: 2056 +1211: 5226 +1212: 4540 +1213: 1403 +1214: 1066 +1215: 4542 +1216: 1255 +1217: 4551 +1220: 2036 +1221: 7001 +1222: 4531 +1223: 1413 +1224: 3066 +1225: 5202 +1226: 4540 +1227: 1613 +1230: 4530 +1231: 5203 +1232: 2026 +1233: 4545 +1234: 4547 +1235: 1403 +1236: 0773 +1237: 4551 +1240: 5233 +1241: 4545 +1242: 4554 +1243: 1067 +1244: 3052 +1245: 5204 +1246: 1077 +1247: 4463 +1250: 7040 +1251: 1077 +1252: 4551 +1253: 4545 +1254: 5204 +1255: 0272 +1256: 4554 +1257: 4555 +1260: 4566 +1261: 1060 +1262: 3010 +1263: 3062 +1264: 1067 +1265: 3410 +1266: 1010 +1267: 3027 +1270: 4464 +1271: 3100 +1272: 2026 +1273: 4545 +1274: 4551 +1275: 4547 +1276: 0076 +1277: 1271 +1300: 4546 +1301: 5273 +1302: 1060 +1303: 7001 +1304: 3010 +1305: 3062 +1306: 4552 +1307: 4547 +1310: 0071 +1311: 1271 +1312: 4546 +1313: 5306 +1315: 7450 +1316: 1066 +1317: 7041 +1320: 3071 +1321: 1714 +1322: 2314 +1323: 3012 +1324: 1412 +1325: 7510 +1326: 5340 +1327: 1071 +1330: 7640 +1331: 5324 +1332: 1012 +1333: 1714 +1334: 3071 +1335: 1471 +1336: 3071 +1337: 5471 +1340: 2314 +1341: 7300 +1342: 5714 +1343: 4453 +1344: 7000 +1345: 6375 +1346: 6332 +1347: 5346 +1350: 6362 +1351: 3046 +1352: 6001 +1353: 5536 +1355: 6046 +1356: 6026 +1357: 6041 +1360: 5357 +1361: 7200 +1362: 5754 +1363: 1273 +1364: 1270 +1365: 2740 +1366: 1302 +1367: 1271 +1370: 0261 +1371: 1312 +1372: 0245 +1373: 0242 +1374: 0241 +1375: 0243 +1376: 0244 +1377: 0240 +1400: 0254 +1401: 0273 +1402: 0215 +1403: 4564 +1404: 0242 +1405: 0215 +1406: 4566 +1407: 3062 +1410: 4546 +1411: 4545 +1412: 4550 +1413: 1767 +1414: 5226 +1415: 1066 +1416: 0122 +1417: 1061 +1420: 3061 +1421: 4545 +1422: 4550 +1423: 1767 +1424: 5226 +1425: 5221 +1426: 4562 +1427: 5237 +1430: 1061 +1431: 3056 +1432: 4660 +1433: 1413 +1434: 3061 +1435: 4657 +1436: 4453 +1437: 3317 +1440: 1060 +1441: 3030 +1442: 1030 +1443: 7041 +1444: 1031 +1445: 7750 +1446: 5261 +1447: 1430 +1450: 7041 +1451: 1061 +1452: 7650 +1453: 5305 +1454: 1030 +1455: 1070 +1456: 5241 +1457: 2047 +1460: 1601 +1461: 1031 +1462: 1005 +1463: 7141 +1464: 1013 +1465: 7620 +1466: 4566 +1467: 1031 +1470: 1070 +1471: 3031 +1472: 1061 +1473: 3430 +1474: 2030 +1475: 1317 +1476: 3430 +1477: 2030 +1500: 4407 +1501: 0537 +1502: 6430 +1504: 5541 +1505: 1030 +1506: 3011 +1507: 1411 +1510: 7041 +1511: 1317 +1512: 7640 +1513: 5254 +1514: 2030 +1515: 2030 +1516: 5541 +1520: 1066 +1521: 1114 +1522: 7640 +1523: 5717 +1524: 4545 +1525: 5320 +1526: 7520 +1527: 7507 +1531: 2000 +1534: 1066 +1535: 1115 +1536: 7640 +1537: 2333 +1540: 1066 +1541: 1326 +1542: 3054 +1543: 1054 +1544: 7710 +1545: 5733 +1546: 1066 +1547: 1327 +1550: 7750 +1551: 2333 +1552: 5733 +1553: 4407 +1554: 1330 +1555: 4350 +1556: 6330 +1560: 3330 +1561: 3044 +1562: 5536 +1563: 1137 +1564: 3022 +1565: 1413 +1566: 3071 +1567: 5471 +1570: 1241 +1571: 1232 +1572: 1251 +1573: 1246 +1574: 3052 +1575: 1253 +1576: 1253 +1577: 0610 +1600: 0614 +1602: 1054 +1603: 4542 +1604: 1055 +1605: 4542 +1606: 1056 +1607: 4542 +1610: 1201 +1611: 4542 +1612: 4545 +1613: 3055 +1614: 4564 +1615: 5227 +1616: 5332 +1617: 5343 +1620: 4540 +1621: 1407 +1622: 4564 +1623: 5244 +1624: 0212 +1625: 0377 +1626: 4566 +1627: 1137 +1630: 3030 +1631: 1111 +1632: 1054 +1633: 7450 +1634: 5247 +1635: 7001 +1636: 7650 +1637: 5323 +1640: 1054 +1641: 1121 +1642: 7710 +1643: 5363 +1644: 4562 +1645: 7410 +1646: 4566 +1647: 1054 +1650: 3024 +1651: 1024 +1652: 1121 +1653: 7700 +1654: 3024 +1655: 1024 +1656: 7041 +1657: 1055 +1660: 7710 +1661: 5310 +1662: 1055 +1663: 7112 +1664: 7012 +1665: 1331 +1666: 3274 +1667: 1055 +1670: 7640 +1671: 4544 +1672: 0044 +1673: 4407 +1675: 6525 +1677: 1125 +1700: 3030 +1701: 1024 +1702: 1055 +1703: 7650 +1704: 5541 +1705: 1413 +1706: 3055 +1707: 5255 +1710: 4562 +1711: 7410 +1712: 5365 +1713: 1055 +1714: 4542 +1715: 1030 +1716: 3320 +1717: 4543 +1721: 1024 +1722: 3055 +1723: 4545 +1724: 4564 +1725: 5363 +1726: 5332 +1727: 5343 +1730: 5220 +1731: 0430 +1732: 4543 +1733: 0044 +1734: 1125 +1735: 3030 +1736: 3036 +1737: 4531 +1740: 4544 +1741: 0044 +1742: 5222 +1743: 3056 +1744: 4545 +1745: 4550 +1746: 1767 +1747: 5354 +1750: 1056 +1751: 7104 +1752: 1066 +1753: 5343 +1754: 4562 +1755: 4566 +1756: 4201 +1757: 1413 +1760: 4547 +1761: 2164 +1762: 6207 +1763: 4562 +1764: 4566 +1765: 4201 +1766: 2013 +1767: 5536 +1770: 0240 +1771: 0253 +1772: 0255 +1773: 0257 +1774: 0252 +1775: 0336 +1776: 0250 +1777: 0333 +2000: 0274 +2001: 0251 +2002: 0335 +2003: 0276 +2004: 0254 +2005: 0273 +2006: 0215 +2007: 0275 +2010: 4543 +2011: 2405 +2012: 4544 +2013: 0044 +2014: 1231 +2015: 7710 +2016: 4451 +2017: 4407 +2020: 7000 +2021: 6230 +2023: 1125 +2024: 3030 +2025: 4247 +2026: 5627 +2027: 1622 +2034: 0003 +2036: 1054 +2037: 1121 +2040: 7700 +2041: 5635 +2042: 1054 +2043: 1120 +2044: 7740 +2045: 2235 +2046: 5635 +2050: 1413 +2051: 3055 +2052: 1234 +2053: 1413 +2054: 7041 +2055: 1054 +2056: 7640 +2057: 4566 +2060: 4545 +2061: 5647 +2063: 6002 +2064: 4555 +2065: 5662 +2066: 2026 +2067: 4545 +2070: 1066 +2071: 1116 +2072: 7640 +2073: 5267 +2074: 1017 +2075: 7040 +2076: 1023 +2077: 3057 +2100: 1133 +2101: 7041 +2102: 1023 +2103: 7650 +2104: 5177 +2105: 7000 +2106: 1423 +2107: 3425 +2110: 1133 +2111: 3071 +2112: 1471 +2113: 7450 +2114: 5327 +2115: 3032 +2116: 1023 +2117: 7141 +2120: 1032 +2121: 7630 +2122: 1057 +2123: 1032 +2124: 3471 +2125: 1032 +2126: 5311 +2127: 7040 +2130: 1023 +2131: 3011 +2132: 1057 +2133: 7040 +2134: 1023 +2135: 3012 +2136: 1057 +2137: 1060 +2140: 3060 +2141: 1010 +2142: 7040 +2143: 1012 +2144: 3032 +2145: 1010 +2146: 1057 +2147: 3010 +2150: 1412 +2151: 3411 +2152: 2032 +2153: 5350 +2154: 5263 +2156: 4464 +2157: 3066 +2160: 4550 +2161: 1623 +2162: 5755 +2163: 4551 +2164: 5755 +2165: 2533 +2166: 2650 +2167: 2636 +2170: 2565 +2171: 2630 +2172: 2517 +2173: 2572 +2174: 2624 +2175: 2625 +2176: 2654 +2177: 2575 +2200: 2702 +2201: 2631 +2202: 2567 +2203: 0330 +2204: 4564 +2205: 5237 +2206: 5222 +2207: 5213 +2210: 1066 +2211: 1112 +2212: 7440 +2213: 4566 +2214: 1135 +2215: 3060 +2216: 3533 +2217: 1060 +2220: 3031 +2221: 5177 +2222: 4554 +2223: 1060 +2224: 3010 +2225: 4565 +2226: 2023 +2227: 1065 +2230: 7700 +2231: 1423 +2232: 4563 +2233: 5217 +2234: 1423 +2235: 3067 +2236: 5225 +2237: 1060 +2240: 3031 +2241: 5541 +2243: 1133 +2244: 3025 +2245: 1133 +2246: 3023 +2247: 1023 +2250: 3011 +2251: 1067 +2252: 7141 +2253: 1411 +2254: 7450 +2255: 5266 +2256: 7630 +2257: 5267 +2260: 1023 +2261: 3025 +2262: 1423 +2263: 7440 +2264: 5246 +2265: 7410 +2266: 2242 +2267: 1023 +2270: 7001 +2271: 3017 +2272: 3020 +2273: 5642 +2275: 4330 +2276: 7710 +2277: 1006 +2300: 1357 +2301: 1066 +2302: 7450 +2303: 5316 +2304: 1075 +2305: 3066 +2306: 1026 +2307: 1100 +2310: 7650 +2311: 4551 +2312: 5674 +2313: 4330 +2314: 7040 +2315: 5276 +2316: 1026 +2317: 7640 +2320: 5326 +2321: 1100 +2322: 7650 +2323: 7001 +2324: 3100 +2325: 5275 +2326: 1110 +2327: 5305 +2331: 2020 +2332: 5345 +2333: 1021 +2334: 0122 +2335: 3066 +2336: 1066 +2337: 1103 +2340: 7650 +2341: 5313 +2342: 1066 +2343: 1356 +2344: 5730 +2345: 1417 +2346: 3021 +2347: 7040 +2350: 3020 +2351: 1021 +2352: 7112 +2353: 7012 +2354: 7012 +2355: 5334 +2356: 7740 +2357: 7641 +2361: 7000 +2362: 1425 +2363: 3460 +2364: 1060 +2365: 3425 +2366: 1061 +2367: 7440 +2370: 3410 +2371: 1010 +2372: 7001 +2373: 3060 +2374: 1060 +2375: 3031 +2376: 5760 +2377: 1253 +2400: 0614 +2401: 6202 +2402: 0757 +2403: 0757 +2404: 6250 +2405: 0001 +2406: 2000 +2413: 7766 +2415: 6031 +2416: 5215 +2417: 6036 +2420: 0106 +2421: 7450 +2422: 5215 +2423: 1123 +2424: 5614 +2426: 1067 +2427: 4557 +2430: 0122 +2431: 4242 +2432: 1102 +2433: 4551 +2434: 1067 +2435: 4242 +2436: 1356 +2437: 3066 +2440: 4551 +2441: 5625 +2443: 0106 +2444: 3032 +2445: 1113 +2446: 3033 +2447: 5252 +2450: 2033 +2451: 3032 +2452: 1032 +2453: 1213 +2454: 7500 +2455: 5250 +2456: 7200 +2457: 1033 +2460: 4551 +2461: 1032 +2462: 1113 +2463: 4551 +2464: 5642 +2466: 7450 +2467: 1066 +2470: 1116 +2471: 7450 +2472: 5276 +2473: 1077 +2474: 4463 +2475: 5665 +2476: 1077 +2477: 4463 +2500: 1076 +2501: 5274 +2503: 1110 +2504: 7041 +2505: 1066 +2506: 7450 +2507: 1352 +2510: 1101 +2511: 7450 +2512: 5755 +2513: 1353 +2514: 3071 +2515: 1071 +2516: 0354 +2517: 1356 +2520: 7440 +2521: 1354 +2522: 7650 +2523: 5332 +2524: 1071 +2525: 0122 +2526: 7440 +2527: 4335 +2530: 7000 +2531: 5702 +2532: 1122 +2533: 4335 +2534: 5324 +2536: 2062 +2537: 5357 +2540: 1061 +2541: 3410 +2542: 3061 +2543: 1013 +2544: 7141 +2545: 1005 +2546: 1010 +2547: 7620 +2550: 5735 +2551: 4566 +2552: 0040 +2553: 0377 +2554: 0140 +2555: 3004 +2556: 7640 +2557: 4557 +2560: 3061 +2561: 7040 +2562: 3062 +2563: 5735 +2602: 7575 +2603: 3200 +2604: 7010 +2605: 3201 +2606: 6041 +2607: 5225 +2610: 6042 +2611: 3016 +2612: 1665 +2613: 7450 +2614: 5225 +2615: 6044 +2616: 3016 +2617: 3665 +2620: 1265 +2621: 7001 +2622: 0107 +2623: 1263 +2624: 3265 +2625: 6031 +2626: 5246 +2627: 6036 +2630: 0106 +2631: 7450 +2632: 5246 +2633: 1123 +2634: 3262 +2635: 1262 +2636: 1202 +2637: 7650 +2640: 5340 +2641: 1034 +2642: 7640 +2643: 4566 +2644: 1262 +2645: 3034 +2646: 6011 +2647: 5252 +2650: 6012 +2651: 3037 +2652: 6244 +2653: 6101 +2654: 7000 +2655: 1201 +2656: 7104 +2657: 1200 +2660: 6001 +2661: 5400 +2663: 3120 +2664: 3120 +2665: 3120 +2667: 1034 +2670: 7550 +2671: 5267 +2672: 3276 +2673: 3034 +2674: 1276 +2675: 5666 +2677: 3266 +2700: 6001 +2701: 1664 +2702: 7640 +2703: 5301 +2704: 6002 +2705: 1016 +2706: 7640 +2707: 5314 +2710: 1266 +2711: 6046 +2712: 3016 +2713: 5323 +2714: 1266 +2715: 3664 +2716: 1264 +2717: 7001 +2720: 0107 +2721: 1263 +2722: 3264 +2723: 6001 +2724: 5676 +2725: 3326 +2727: 7240 +2730: 1326 +2731: 3067 +2732: 6001 +2733: 1016 +2734: 7640 +2735: 5333 +2736: 6002 +2737: 5342 +2740: 1123 +2741: 3067 +2742: 2016 +2743: 1105 +2744: 3057 +2745: 7040 +2746: 1263 +2747: 3010 +2750: 7000 +2751: 3410 +2752: 2057 +2753: 5351 +2754: 3034 +2755: 1263 +2756: 3265 +2757: 1263 +2760: 3264 +2761: 7040 +2762: 6046 +2763: 1101 +2764: 4551 +2765: 4553 +2766: 2022 +2767: 1422 +2770: 7450 +2771: 5377 +2772: 3067 +2773: 1101 +2774: 4551 +2775: 4551 +2776: 4553 +2777: 1077 +3000: 4551 +3001: 1126 +3002: 3152 +3003: 5177 +3004: 1062 +3005: 7640 +3006: 5214 +3007: 1010 +3010: 7041 +3011: 1027 +3012: 7700 +3013: 5641 +3014: 1251 +3015: 4551 +3016: 1010 +3017: 3071 +3020: 7000 +3021: 2062 +3022: 5242 +3023: 1471 +3024: 0122 +3025: 1103 +3026: 7640 +3027: 5237 +3030: 7040 +3031: 3062 +3032: 7040 +3033: 1010 +3034: 3010 +3035: 1471 +3036: 0101 +3037: 3061 +3040: 5641 +3041: 2530 +3042: 1471 +3043: 0101 +3044: 1006 +3045: 7640 +3046: 5230 +3047: 3471 +3050: 5231 +3051: 0334 +3052: 1060 +3053: 3030 +3054: 1031 +3055: 7041 +3056: 1030 +3057: 7650 +3060: 5541 +3061: 1430 +3062: 3316 +3063: 1315 +3064: 3017 +3065: 3020 +3066: 4545 +3067: 4551 +3070: 4545 +3071: 4551 +3072: 4545 +3073: 4551 +3074: 2030 +3075: 1430 +3076: 4714 +3077: 4545 +3100: 4551 +3101: 2030 +3102: 4407 +3103: 0430 +3105: 4530 +3106: 1077 +3107: 4551 +3110: 1070 +3111: 1111 +3112: 1030 +3113: 5253 +3114: 2442 +3115: 3115 +3117: 5051 +3206: 3217 +3210: 0355 +3211: 0617 +3212: 0301 +3213: 1454 +3214: 6171 +3215: 6671 +3216: 7715 +3217: 3235 +3220: 0212 +3221: 2440 +3222: 4142 +3223: 0317 +3224: 1607 +3225: 2201 +3226: 2425 +3227: 1401 +3230: 2411 +3231: 1716 +3232: 2341 +3233: 4142 +3234: 7715 +3235: 3272 +3236: 0224 +3237: 2440 +3240: 4041 +3241: 4231 +3242: 1725 +3243: 4010 +3244: 0126 +3245: 0540 +3246: 2325 +3247: 0303 +3250: 0523 +3251: 2306 +3252: 2514 +3253: 1431 +3254: 4014 +3255: 1701 +3256: 0405 +3257: 0440 +3260: 4706 +3261: 1703 +3262: 0114 +3263: 5461 +3264: 7166 +3265: 7147 +3266: 4017 +3267: 1640 +3270: 0140 +3271: 7715 +3272: 3330 +3273: 0231 +3274: 2305 +3275: 2440 +3276: 2004 +3277: 2075 +3300: 2004 +3301: 2052 +3302: 6236 +3303: 6161 +3304: 7304 +3305: 4061 +3306: 5662 +3307: 6673 +3310: 0417 +3311: 4061 +3312: 5671 +3313: 7304 +3314: 1740 +3315: 6273 +3316: 4024 +3317: 4041 +3320: 4220 +3321: 2217 +3322: 0305 +3323: 0504 +3324: 5642 +3325: 4141 +3326: 7322 +3327: 7715 +3330: 3354 +3331: 0232 +3332: 1106 +3333: 4050 +3334: 2004 +3335: 2055 +3336: 6651 +3337: 4061 +3340: 5663 +3341: 6054 +3342: 6156 +3343: 6267 +3344: 7324 +3345: 4042 +3346: 2004 +3347: 2055 +3350: 7057 +3351: 1442 +3352: 7322 +3353: 7715 +3354: 3365 +3355: 0233 +3356: 2440 +3357: 4220 +3360: 0420 +3361: 5561 +3362: 6242 +3363: 7322 +3364: 7715 +3365: 3403 +3366: 0236 +3367: 1140 +3370: 5020 +3371: 0420 +3372: 5565 +3373: 5161 +3374: 5664 +3375: 7324 +3376: 4042 +3377: 1401 +3400: 0255 +3401: 7042 +3402: 7715 +3403: 3421 +3404: 0250 +3405: 1140 +3406: 5020 +3407: 0420 +3410: 5564 +3411: 5161 +3412: 5665 +3413: 7324 +3414: 4042 +3415: 1411 +3416: 1603 +3417: 5570 +3420: 7715 +3421: 3443 +3422: 0262 +3423: 2440 +3424: 4220 +3425: 0420 +3426: 5542 +3427: 7311 +3430: 0640 +3431: 5020 +3432: 0420 +3433: 5563 +3434: 5161 +3435: 5666 +3436: 7324 +3437: 4042 +3440: 7057 +3441: 1142 +3442: 7715 +3443: 3457 +3444: 0274 +3445: 1106 +3446: 4050 +3447: 2004 +3450: 2055 +3451: 6251 +3452: 6156 +3453: 6773 +3454: 2440 +3455: 4270 +3456: 7715 +3457: 3474 +3460: 0306 +3461: 1106 +3462: 4050 +3463: 2004 +3464: 2055 +3465: 6151 +3466: 6156 +3467: 7073 +3470: 2440 +3471: 4270 +3472: 5723 +3473: 7715 +3474: 3507 +3475: 0320 +3476: 1106 +3477: 4050 +3500: 2004 +3501: 2051 +3502: 6156 +3503: 7173 +3504: 2440 +3505: 4265 +3506: 7715 +3507: 3522 +3510: 0332 +3511: 2440 +3512: 4240 +3513: 0317 +3514: 1520 +3515: 2524 +3516: 0522 +3517: 5642 +3520: 4141 +3521: 7715 +3522: 3531 +3523: 0417 +3524: 2305 +3525: 2440 +3526: 3006 +3527: 7561 +3530: 7715 +3531: 3546 +3532: 0424 +3533: 2440 +3534: 4142 +3535: 2310 +3536: 0114 +3537: 1440 +3540: 1140 +3541: 2205 +3542: 2401 +3543: 1116 +3544: 4042 +3545: 7715 +3546: 3562 +3547: 0431 +3550: 2440 +3551: 4214 +3552: 1707 +3553: 5440 +3554: 0530 +3555: 2054 +3556: 4001 +3557: 2416 +3560: 4037 +3561: 7715 +3562: 3601 +3563: 0436 +3564: 0417 +3565: 4061 +3566: 6073 +3567: 1106 +3570: 4050 +3571: 2205 +3572: 5162 +3573: 5671 +3574: 5462 +3575: 5664 +3576: 5462 +3577: 5664 +3600: 7715 +3601: 3632 +3602: 0450 +3603: 0417 +3604: 4062 +3605: 5662 +3606: 7324 +3607: 4042 +3610: 2311 +3611: 1605 +3612: 5440 +3613: 0317 +3614: 2311 +3615: 1605 +3616: 4037 +3617: 4273 +3620: 0417 +3621: 4061 +3622: 6073 +3623: 1106 +3624: 4050 +3625: 2205 +3626: 5162 +3627: 5665 +3630: 7322 +3631: 7715 +3632: 3642 +3633: 0462 +3634: 2340 +3635: 3006 +3636: 7555 +3637: 6173 +3640: 4022 +3641: 7715 +3642: 3650 +3643: 0532 +3644: 2340 +3645: 3006 +3646: 7560 +3647: 7715 +3650: 3673 +3651: 2450 +3652: 0140 +3653: 2205 +3654: 7311 +3655: 4050 +3656: 2205 +3657: 5560 +3660: 3105 +3661: 2351 +3662: 4061 +3663: 6056 +3664: 6554 +3665: 6160 +3666: 5664 +3667: 6554 +3670: 6160 +3671: 5665 +3672: 7715 +3673: 3704 +3674: 2455 +3675: 4023 +3676: 0524 +3677: 4022 +3700: 0575 +3701: 5561 +3702: 7322 +3703: 7715 +3704: 3721 +3705: 2462 +3706: 1106 +3707: 4050 +3710: 2205 +3711: 5560 +3712: 1617 +3713: 5161 +3714: 6056 +3715: 6654 +3716: 6160 +3717: 5670 +3720: 7715 +3721: 3750 +3722: 2474 +3723: 2440 +3724: 4142 +3725: 2014 +3726: 0501 +3727: 2305 +3730: 4001 +3731: 1623 +3732: 2705 +3733: 2240 +3734: 4731 +3735: 0523 +3736: 4740 +3737: 1722 +3740: 4047 +3741: 1617 +3742: 4740 +3743: 4273 +3744: 0740 +3745: 6160 +3746: 5664 +3747: 7715 +3751: 2520 +3752: 2305 +3753: 2440 +3754: 2205 +3755: 7561 +3756: 7322 +3757: 7715 +4370: 2741 +4371: 1370 +4372: 3176 +4373: 6142 +4374: 6077 +4375: 6152 +4376: 6762 +4377: 6012 +4400: 6346 +4401: 6772 +4402: 7300 +4403: 3414 +4404: 2057 +4405: 5203 +4406: 1362 +4407: 4371 +4410: 1370 +4411: 3000 +4412: 7040 +4413: 6167 +4414: 7200 +4415: 6171 +4416: 7650 +4417: 5226 +4420: 1365 +4421: 6141 +4422: 1366 +4423: 6141 +4424: 7200 +4425: 5310 +4426: 6141 +4427: 0017 +4430: 0002 +4431: 7001 +4432: 7650 +4433: 5306 +4434: 7101 +4435: 6344 +4436: 6331 +4437: 7700 +4440: 5246 +4441: 1350 +4442: 3752 +4443: 1351 +4444: 3753 +4445: 5307 +4446: 7354 +4447: 1367 +4450: 7650 +4451: 5265 +4452: 7344 +4453: 1366 +4454: 7650 +4455: 5312 +4456: 1100 +4457: 3764 +4460: 1212 +4461: 3763 +4462: 5313 +4463: 2761 +4464: 5314 +4465: 6046 +4466: 6000 +4467: 6000 +4470: 6000 +4471: 6000 +4472: 6000 +4473: 6000 +4474: 6000 +4475: 6000 +4476: 2057 +4477: 6041 +4500: 5266 +4501: 1057 +4502: 1130 +4503: 7710 +4504: 5311 +4505: 2430 +4506: 2430 +4507: 2430 +4510: 2430 +4511: 2430 +4512: 2430 +4513: 2430 +4514: 6046 +4515: 6001 +4516: 4540 +4517: 0421 +4520: 6002 +4521: 1360 +4522: 4371 +4523: 7450 +4524: 5344 +4525: 7710 +4526: 1366 +4527: 1120 +4530: 3057 +4531: 1354 +4532: 3011 +4533: 1355 +4534: 3411 +4535: 2057 +4536: 5333 +4537: 1360 +4540: 4371 +4541: 7710 +4542: 1104 +4543: 1356 +4544: 1357 +4545: 3035 +4546: 5747 +4547: 2214 +4550: 6313 +4551: 6307 +4552: 1153 +4553: 1156 +4554: 0401 +4555: 2725 +4556: 0560 +4557: 4617 +4560: 3006 +4561: 2661 +4562: 2004 +4563: 6322 +4564: 2654 +4565: 0007 +4566: 0002 +4567: 4002 +4570: 4462 +4571: 2344 +4572: 3061 +4573: 4540 +4574: 1437 +4575: 2030 +4576: 1430 +4577: 5771 +4620: 1045 +4621: 7710 +4622: 4724 +4623: 3033 +4624: 4407 +4625: 4313 +4626: 6675 +4630: 4453 +4631: 3325 +4632: 4407 +4633: 7000 +4634: 6676 +4635: 0675 +4636: 2676 +4637: 6675 +4640: 4675 +4641: 6676 +4642: 1310 +4643: 6326 +4644: 0305 +4645: 3326 +4646: 2675 +4647: 1277 +4650: 6326 +4651: 0302 +4652: 4676 +4653: 1326 +4654: 6326 +4655: 0675 +4656: 3326 +4657: 4321 +4660: 1316 +4662: 1325 +4663: 1044 +4664: 3044 +4665: 2033 +4666: 5536 +4667: 4407 +4670: 6675 +4671: 0316 +4672: 3675 +4674: 5536 +4675: 5322 +4676: 5326 +4677: 0004 +4700: 2372 +4701: 1402 +4702: 7774 +4703: 2157 +4704: 5157 +4705: 0012 +4706: 5454 +4707: 0343 +4710: 0007 +4711: 2566 +4712: 5341 +4713: 0001 +4714: 2705 +4715: 2435 +4716: 0001 +4717: 2000 +4721: 0002 +4722: 2000 +4724: 5163 +4732: 4407 +4733: 0675 +4734: 4675 +4735: 6676 +4736: 4374 +4737: 1371 +4740: 4676 +4741: 1366 +4742: 6326 +4743: 0363 +4744: 4676 +4745: 1360 +4746: 4676 +4747: 1355 +4750: 4675 +4751: 3326 +4753: 5754 +4754: 5024 +4756: 2437 +4757: 1643 +4760: 7777 +4761: 3304 +4762: 4434 +4763: 7773 +4764: 3306 +4765: 5454 +4767: 2437 +4770: 1646 +4772: 2427 +4773: 2323 +4774: 7775 +4775: 3427 +4776: 7052 +5000: 1045 +5001: 7710 +5002: 4363 +5003: 3033 +5004: 4407 +5005: 6635 +5006: 2637 +5010: 1045 +5011: 7710 +5012: 5221 +5013: 4407 +5014: 0637 +5015: 3635 +5016: 6635 +5020: 7240 +5021: 3362 +5022: 5623 +5023: 4732 +5024: 2362 +5025: 5634 +5026: 4407 +5027: 6635 +5030: 0636 +5031: 2635 +5033: 5634 +5034: 5302 +5035: 5322 +5036: 5316 +5037: 4716 +5040: 1045 +5041: 7450 +5042: 4566 +5043: 7710 +5044: 4451 +5045: 4407 +5046: 6756 +5047: 2637 +5051: 1045 +5052: 7450 +5053: 5536 +5054: 7700 +5055: 5264 +5056: 4407 +5057: 0637 +5060: 3756 +5061: 6756 +5063: 7240 +5064: 3033 +5065: 1005 +5066: 3044 +5067: 7040 +5070: 1756 +5071: 3045 +5072: 3046 +5073: 3047 +5074: 7001 +5075: 3756 +5076: 4407 +5077: 4357 +5100: 6635 +5101: 0756 +5102: 2637 +5103: 6756 +5104: 4353 +5105: 1350 +5106: 4756 +5107: 1345 +5110: 4756 +5111: 1342 +5112: 4756 +5113: 1337 +5114: 4756 +5115: 1334 +5116: 4756 +5117: 1331 +5120: 4756 +5121: 1326 +5122: 4756 +5123: 1635 +5125: 5634 +5127: 3777 +5130: 7742 +5131: 7777 +5132: 4000 +5133: 4100 +5134: 7777 +5135: 2517 +5136: 0307 +5137: 7776 +5140: 4113 +5141: 7211 +5142: 7776 +5143: 2535 +5144: 3301 +5145: 7775 +5146: 4746 +5147: 0771 +5150: 7774 +5151: 2236 +5152: 4304 +5153: 7771 +5154: 4544 +5155: 1735 +5156: 4726 +5160: 2613 +5161: 4414 +5164: 4451 +5165: 7240 +5166: 5763 +5200: 4407 +5201: 6322 +5202: 0316 +5203: 2322 +5205: 1045 +5206: 7740 +5207: 5215 +5210: 1045 +5211: 7700 +5212: 5536 +5213: 4451 +5214: 7040 +5215: 3033 +5216: 4407 +5217: 3306 +5220: 6326 +5222: 4453 +5223: 4407 +5224: 7000 +5225: 6322 +5226: 0326 +5227: 2322 +5230: 4306 +5231: 6322 +5232: 2312 +5234: 1045 +5235: 7710 +5236: 5245 +5237: 4407 +5240: 6322 +5242: 1033 +5243: 7040 +5244: 3033 +5245: 4407 +5246: 0322 +5247: 2316 +5251: 1045 +5252: 7710 +5253: 5261 +5254: 4407 +5255: 0312 +5256: 2322 +5257: 6322 +5261: 4407 +5262: 0322 +5263: 3316 +5264: 6322 +5265: 4322 +5266: 6326 +5267: 0332 +5270: 4326 +5271: 1336 +5272: 4326 +5273: 1342 +5274: 4326 +5275: 1346 +5276: 4326 +5277: 1316 +5300: 4322 +5302: 2033 +5303: 5536 +5304: 4451 +5305: 5536 +5306: 0003 +5307: 3110 +5310: 3756 +5311: 3235 +5312: 0002 +5313: 3110 +5314: 3756 +5315: 3235 +5316: 0001 +5317: 3110 +5320: 3756 +5321: 3235 +5332: 7764 +5333: 2401 +5334: 7015 +5335: 1042 +5336: 7771 +5337: 5464 +5340: 5514 +5341: 6150 +5342: 7775 +5343: 2431 +5344: 5361 +5345: 4736 +5347: 5325 +5350: 0414 +5351: 3167 +5401: 3334 +5402: 1052 +5403: 4557 +5404: 0122 +5405: 3032 +5406: 1032 +5407: 7041 +5410: 7450 +5411: 1326 +5412: 3335 +5413: 1052 +5414: 7450 +5415: 5241 +5416: 0122 +5417: 3333 +5420: 1335 +5421: 1333 +5422: 7510 +5423: 5230 +5424: 7240 +5425: 1032 +5426: 3333 +5427: 7040 +5430: 1033 +5431: 7500 +5432: 7200 +5433: 1032 +5434: 7510 +5435: 5263 +5436: 1326 +5437: 7500 +5440: 7200 +5441: 1327 +5442: 3071 +5443: 1731 +5444: 1071 +5445: 3336 +5446: 1071 +5447: 7041 +5450: 3071 +5451: 1325 +5452: 2736 +5453: 1736 +5454: 1330 +5455: 7710 +5456: 5265 +5457: 3736 +5460: 2071 +5461: 5321 +5462: 2736 +5463: 2033 +5464: 7200 +5465: 1052 +5466: 7650 +5467: 5356 +5470: 1335 +5471: 1033 +5472: 7540 +5473: 5355 +5474: 1333 +5475: 7500 +5476: 7200 +5477: 7041 +5500: 1033 +5501: 7041 +5502: 3032 +5503: 1033 +5504: 1032 +5505: 7650 +5506: 5343 +5507: 1032 +5510: 7001 +5511: 7710 +5512: 1105 +5513: 4336 +5514: 2032 +5515: 5303 +5516: 1102 +5517: 4551 +5520: 5303 +5521: 7040 +5522: 1336 +5523: 3336 +5524: 5252 +5525: 0005 +5526: 7772 +5527: 0007 +5530: 7766 +5531: 6150 +5532: 6154 +5537: 4732 +5540: 2335 +5541: 5736 +5542: 5600 +5543: 7040 +5544: 1033 +5545: 3033 +5546: 2334 +5547: 5353 +5550: 7040 +5551: 3334 +5552: 5313 +5553: 1414 +5554: 5313 +5555: 7200 +5556: 4732 +5557: 1102 +5560: 4551 +5561: 2200 +5562: 1414 +5563: 4336 +5564: 2334 +5565: 5362 +5566: 7040 +5567: 3334 +5570: 5363 +5572: 1045 +5573: 3050 +5574: 1045 +5575: 7710 +5576: 4451 +5577: 5771 +5601: 3046 +5602: 3044 +5603: 3045 +5604: 3047 +5605: 3314 +5606: 3050 +5607: 1066 +5610: 1264 +5611: 7450 +5612: 5220 +5613: 1111 +5614: 7640 +5615: 5221 +5616: 7040 +5617: 3050 +5620: 4666 +5621: 1066 +5622: 1265 +5623: 7650 +5624: 5220 +5625: 4227 +5626: 5600 +5630: 1066 +5631: 1262 +5632: 7650 +5633: 5627 +5634: 4561 +5635: 5627 +5636: 5247 +5637: 1054 +5640: 3313 +5641: 4267 +5642: 2314 +5643: 7640 +5644: 4566 +5645: 4666 +5646: 5230 +5647: 1066 +5650: 1112 +5651: 7710 +5652: 5627 +5653: 1066 +5654: 1263 +5655: 7740 +5656: 5627 +5657: 1066 +5660: 0122 +5661: 5240 +5662: 7473 +5663: 7446 +5664: 7525 +5665: 7540 +5666: 0756 +5670: 1047 +5671: 3043 +5672: 1046 +5673: 3042 +5674: 1045 +5675: 3041 +5676: 3312 +5677: 4315 +5700: 4315 +5701: 4333 +5702: 4315 +5703: 1313 +5704: 3043 +5705: 3042 +5706: 3041 +5707: 4333 +5710: 1312 +5711: 5667 +5716: 1047 +5717: 7104 +5720: 3047 +5721: 1046 +5722: 7004 +5723: 3046 +5724: 1045 +5725: 7004 +5726: 3045 +5727: 1312 +5730: 7004 +5731: 3312 +5732: 5715 +5734: 7300 +5735: 1047 +5736: 1043 +5737: 3047 +5740: 7004 +5741: 1046 +5742: 1042 +5743: 3046 +5744: 7004 +5745: 1045 +5746: 1041 +5747: 3045 +5750: 7004 +5751: 1312 +5752: 3312 +5753: 5733 +5755: 7300 +5756: 1041 +5757: 7510 +5760: 7120 +5761: 7010 +5762: 3041 +5763: 1042 +5764: 7010 +5765: 3042 +5766: 1043 +5767: 7010 +5770: 3043 +5771: 2040 +5772: 5754 +5773: 5754 +6001: 1335 +6002: 4551 +6003: 1045 +6004: 7700 +6005: 1334 +6006: 1336 +6007: 4551 +6010: 4753 +6011: 3033 +6012: 1044 +6013: 7510 +6014: 5227 +6015: 7440 +6016: 1341 +6017: 7750 +6020: 5234 +6021: 4407 +6022: 4744 +6024: 7001 +6025: 1033 +6026: 5211 +6027: 4407 +6030: 4752 +6032: 7040 +6033: 5225 +6034: 3745 +6035: 3746 +6036: 1350 +6037: 3014 +6040: 1044 +6041: 7140 +6042: 3354 +6043: 1343 +6044: 3044 +6045: 4527 +6046: 2354 +6047: 5245 +6050: 1746 +6051: 7450 +6052: 5270 +6053: 1342 +6054: 7710 +6055: 5264 +6056: 7001 +6057: 3414 +6060: 2044 +6061: 1342 +6062: 2033 +6063: 7000 +6064: 1746 +6065: 2033 +6066: 7000 +6067: 7410 +6070: 4747 +6071: 3414 +6072: 2044 +6073: 5270 +6074: 1350 +6075: 3014 +6076: 1343 +6077: 4751 +6100: 5600 +6101: 1333 +6102: 4551 +6103: 1033 +6104: 7510 +6105: 7041 +6106: 3045 +6107: 1033 +6110: 7700 +6111: 1111 +6112: 1336 +6113: 4551 +6114: 1045 +6115: 2044 +6116: 1337 +6117: 7500 +6120: 5315 +6121: 1340 +6122: 3045 +6123: 7040 +6124: 1044 +6125: 7440 +6126: 4354 +6127: 1045 +6130: 4732 +6131: 5600 +6132: 2442 +6133: 0305 +6134: 7763 +6135: 0275 +6136: 0255 +6137: 7634 +6140: 0144 +6141: 7774 +6142: 7766 +6143: 7771 +6144: 6275 +6145: 5713 +6146: 5712 +6147: 5667 +6150: 7467 +6151: 5400 +6152: 6271 +6153: 5571 +6155: 1113 +6156: 4551 +6157: 5754 +6201: 7640 +6202: 4706 +6203: 1066 +6204: 1114 +6205: 7650 +6206: 5202 +6207: 4702 +6210: 1066 +6211: 1115 +6212: 7640 +6213: 5221 +6214: 4706 +6215: 3705 +6216: 4703 +6217: 1705 +6220: 7041 +6221: 3033 +6222: 1310 +6223: 3044 +6224: 4704 +6225: 4707 +6226: 4407 +6227: 6430 +6231: 1066 +6232: 1301 +6233: 7640 +6234: 5246 +6235: 4706 +6236: 4702 +6237: 4704 +6240: 1047 +6241: 1033 +6242: 3033 +6243: 4407 +6244: 0430 +6246: 1033 +6247: 7450 +6250: 5600 +6251: 7700 +6252: 5261 +6253: 4407 +6254: 4275 +6255: 6430 +6257: 7001 +6260: 5266 +6261: 4407 +6262: 4271 +6263: 6430 +6265: 7040 +6266: 1033 +6267: 3033 +6270: 5246 +6271: 0004 +6272: 2400 +6275: 7775 +6276: 3146 +6277: 3147 +6300: 3150 +6301: 7473 +6302: 5600 +6303: 5627 +6304: 7173 +6305: 5714 +6306: 0756 +6307: 7335 +6310: 0043 +6322: 1105 +6323: 3343 +6324: 1037 +6325: 7700 +6326: 5364 +6327: 2032 +6330: 5324 +6331: 2343 +6332: 5324 +6333: 4343 +6334: 1013 +6335: 1376 +6336: 7620 +6337: 5742 +6340: 2013 +6341: 5541 +6342: 0212 +6344: 1375 +6345: 7040 +6346: 3375 +6347: 7140 +6350: 3037 +6351: 1375 +6352: 7440 +6353: 6014 +6354: 7640 +6355: 1377 +6356: 1126 +6357: 3152 +6360: 5743 +6361: 4343 +6362: 5763 +6363: 0611 +6364: 7040 +6365: 3037 +6366: 6016 +6367: 0106 +6370: 7450 +6371: 5322 +6372: 1123 +6373: 3066 +6374: 5721 +6376: 4557 +6377: 4144 +6401: 7300 +6402: 3047 +6403: 3043 +6404: 1600 +6405: 7450 +6406: 5600 +6407: 3262 +6410: 1262 +6411: 0123 +6412: 7650 +6413: 5216 +6414: 1104 +6415: 0200 +6416: 3040 +6417: 1106 +6420: 0262 +6421: 1040 +6422: 3040 +6423: 1263 +6424: 0262 +6425: 7650 +6426: 5231 +6427: 1440 +6430: 3040 +6431: 2200 +6432: 7040 +6433: 1040 +6434: 3015 +6435: 1262 +6436: 7106 +6437: 7006 +6440: 0107 +6441: 7450 +6442: 5267 +6443: 1264 +6444: 3262 +6445: 1662 +6446: 7450 +6447: 5265 +6450: 3262 +6451: 1304 +6452: 3014 +6453: 1117 +6454: 3057 +6455: 1415 +6456: 3414 +6457: 2057 +6460: 5255 +6461: 5662 +6463: 0400 +6464: 6573 +6465: 1303 +6466: 5273 +6467: 1303 +6470: 3015 +6471: 7040 +6472: 1040 +6473: 3014 +6474: 1117 +6475: 3057 +6476: 1414 +6477: 3415 +6500: 2057 +6501: 5276 +6502: 5201 +6503: 0043 +6504: 0037 +6505: 4765 +6506: 4770 +6507: 5201 +6510: 4772 +6511: 4771 +6512: 4773 +6513: 4767 +6514: 5201 +6515: 1045 +6516: 7640 +6517: 5325 +6520: 3044 +6521: 3045 +6522: 3046 +6523: 3047 +6524: 5201 +6525: 4543 +6526: 0044 +6527: 4543 +6530: 0040 +6531: 4544 +6532: 0044 +6533: 4453 +6534: 7510 +6535: 5342 +6536: 7040 +6537: 3262 +6540: 3043 +6541: 1045 +6542: 7640 +6543: 4566 +6544: 4543 +6545: 2405 +6546: 4544 +6547: 0044 +6550: 4544 +6551: 7470 +6552: 5360 +6553: 4543 +6554: 7470 +6555: 4544 +6556: 0040 +6557: 4766 +6560: 2262 +6561: 5353 +6562: 5201 +6563: 4766 +6564: 5201 +6565: 7153 +6566: 7004 +6567: 7335 +6570: 6623 +6571: 5754 +6572: 6757 +6573: 5733 +6574: 6506 +6575: 6505 +6576: 7107 +6577: 6563 +6600: 6515 +6602: 6513 +6604: 7300 +6605: 1047 +6606: 7041 +6607: 3047 +6610: 1046 +6611: 7040 +6612: 7430 +6613: 7101 +6614: 3046 +6615: 1045 +6616: 7040 +6617: 7430 +6620: 7101 +6621: 3045 +6622: 5603 +6624: 1045 +6625: 7450 +6626: 1046 +6627: 7650 +6630: 5311 +6631: 1041 +6632: 7450 +6633: 1042 +6634: 7450 +6635: 1043 +6636: 7650 +6637: 5623 +6640: 1040 +6641: 7041 +6642: 1044 +6643: 7450 +6644: 5273 +6645: 3203 +6646: 1203 +6647: 7500 +6650: 7041 +6651: 3322 +6652: 1322 +6653: 1336 +6654: 7710 +6655: 5275 +6656: 1203 +6657: 7700 +6660: 5265 +6661: 4357 +6662: 2322 +6663: 5261 +6664: 5273 +6665: 7040 +6666: 1040 +6667: 3040 +6670: 4723 +6671: 2322 +6672: 5270 +6673: 2223 +6674: 5623 +6675: 1040 +6676: 7700 +6677: 5304 +6700: 1044 +6701: 7700 +6702: 5623 +6703: 5306 +6704: 1044 +6705: 7700 +6706: 1203 +6707: 7740 +6710: 5623 +6711: 1040 +6712: 3044 +6713: 1041 +6714: 3045 +6715: 1042 +6716: 3046 +6717: 1043 +6720: 3047 +6721: 5623 +6723: 5754 +6725: 4751 +6726: 1044 +6727: 7750 +6730: 5353 +6731: 7001 +6732: 3043 +6733: 1350 +6734: 3040 +6735: 4223 +6736: 0027 +6737: 2047 +6740: 5344 +6741: 2046 +6742: 7410 +6743: 2045 +6744: 3047 +6745: 4752 +6746: 1046 +6747: 5724 +6750: 0027 +6751: 5571 +6752: 7173 +6753: 3044 +6754: 3045 +6755: 3046 +6756: 5344 +6760: 7300 +6761: 1045 +6762: 7510 +6763: 7020 +6764: 7010 +6765: 3045 +6766: 1046 +6767: 7010 +6770: 3046 +6771: 1047 +6772: 7010 +6773: 3047 +6774: 2044 +6775: 5757 +6776: 5757 +6777: 0337 +7000: 0377 +7001: 0212 +7002: 0375 +7003: 7777 +7005: 7001 +7006: 1040 +7007: 4324 +7010: 7710 +7011: 4353 +7012: 3301 +7013: 3300 +7014: 3277 +7015: 3276 +7016: 1045 +7017: 3751 +7020: 1041 +7021: 4752 +7022: 0002 +7023: 1042 +7024: 4752 +7025: 0003 +7026: 1046 +7027: 3751 +7030: 1041 +7031: 4752 +7032: 0003 +7033: 1042 +7034: 4752 +7035: 0004 +7036: 5263 +7037: 3274 +7040: 1043 +7041: 3751 +7042: 1045 +7043: 4752 +7044: 0004 +7045: 1046 +7046: 4752 +7047: 0005 +7050: 1047 +7051: 3751 +7052: 1041 +7053: 4752 +7054: 0004 +7055: 1042 +7056: 4752 +7057: 0005 +7060: 1043 +7061: 4752 +7062: 0006 +7063: 1301 +7064: 3045 +7065: 1300 +7066: 3046 +7067: 1277 +7070: 3047 +7071: 4301 +7072: 3047 +7073: 5604 +7102: 2050 +7103: 4451 +7104: 4747 +7105: 2047 +7106: 5701 +7107: 1041 +7110: 7650 +7111: 4566 +7112: 1040 +7113: 7041 +7114: 7001 +7115: 4324 +7116: 7700 +7117: 4353 +7120: 4750 +7121: 4301 +7122: 5723 +7123: 6401 +7125: 1044 +7126: 3044 +7127: 1124 +7130: 0045 +7131: 1041 +7132: 7700 +7133: 7040 +7134: 3050 +7135: 1045 +7136: 7450 +7137: 5746 +7140: 7710 +7141: 4451 +7142: 1041 +7143: 7450 +7144: 5746 +7145: 5724 +7146: 6520 +7147: 7335 +7150: 7261 +7151: 7256 +7152: 7200 +7154: 7300 +7155: 1043 +7156: 7041 +7157: 3043 +7160: 1042 +7161: 7040 +7162: 7430 +7163: 7101 +7164: 3042 +7165: 1041 +7166: 7040 +7167: 7430 +7170: 7101 +7171: 3041 +7172: 5753 +7174: 1050 +7175: 7710 +7176: 4451 +7177: 5773 +7201: 7450 +7202: 5600 +7203: 3254 +7204: 3253 +7205: 1257 +7206: 3255 +7207: 7100 +7210: 1254 +7211: 7010 +7212: 3254 +7213: 1253 +7214: 7420 +7215: 5220 +7216: 7100 +7217: 1256 +7220: 7010 +7221: 3253 +7222: 2255 +7223: 5210 +7224: 1254 +7225: 7010 +7226: 3255 +7227: 1600 +7230: 7041 +7231: 1252 +7232: 3254 +7233: 1255 +7234: 7100 +7235: 1654 +7236: 3654 +7237: 2254 +7240: 7004 +7241: 1253 +7242: 1654 +7243: 3654 +7244: 7420 +7245: 5600 +7246: 2254 +7247: 2654 +7250: 5600 +7251: 5246 +7252: 7102 +7257: 7764 +7260: 7751 +7262: 3200 +7263: 3254 +7264: 1260 +7265: 3255 +7266: 7410 +7267: 4527 +7270: 7100 +7271: 1042 +7272: 1046 +7273: 3256 +7274: 7004 +7275: 1045 +7276: 1041 +7277: 7420 +7300: 5304 +7301: 3045 +7302: 1256 +7303: 3046 +7304: 7200 +7305: 1254 +7306: 7004 +7307: 3254 +7310: 1200 +7311: 7004 +7312: 3200 +7313: 2255 +7314: 5267 +7315: 1254 +7316: 3046 +7317: 1200 +7320: 3045 +7321: 5661 +7322: 7004 +7323: 3335 +7324: 2255 +7325: 5267 +7326: 1335 +7327: 3045 +7330: 1200 +7331: 3046 +7332: 1254 +7333: 3047 +7334: 5661 +7336: 4775 +7337: 4366 +7340: 1045 +7341: 7450 +7342: 1047 +7343: 7450 +7344: 1046 +7345: 7650 +7346: 5363 +7347: 1045 +7350: 7104 +7351: 7710 +7352: 5360 +7353: 4527 +7354: 7140 +7355: 1044 +7356: 3044 +7357: 5347 +7360: 4776 +7361: 4366 +7362: 5735 +7363: 3044 +7364: 5735 +7365: 6757 +7367: 1045 +7370: 7510 +7371: 7041 +7372: 7710 +7373: 4765 +7374: 5766 +7375: 5571 +7376: 7173 +7400: 4407 +7401: 6274 +7403: 1045 +7404: 7710 +7405: 4566 +7406: 1044 +7407: 7510 +7410: 7020 +7411: 7010 +7412: 3270 +7413: 7430 +7414: 2270 +7415: 7000 +7416: 1267 +7417: 3271 +7420: 3272 +7421: 3273 +7422: 1275 +7423: 7450 +7424: 1276 +7425: 7650 +7426: 5265 +7427: 4407 +7430: 0274 +7431: 3270 +7432: 1270 +7434: 7240 +7435: 1044 +7436: 3044 +7437: 1044 +7440: 7041 +7441: 1270 +7442: 7640 +7443: 5261 +7444: 1045 +7445: 7041 +7446: 1271 +7447: 7640 +7450: 5261 +7451: 1046 +7452: 7041 +7453: 1272 +7454: 7500 +7455: 7041 +7456: 7001 +7457: 7700 +7460: 5536 +7461: 4407 +7462: 6270 +7464: 5227 +7465: 3044 +7466: 5536 +7467: 3015 +7477: 7503 +7503: 1133 +7504: 4327 +7505: 1060 +7506: 4327 +7507: 1031 +7510: 4327 +7511: 1035 +7512: 4327 +7513: 5316 +7514: 4545 +7515: 4551 +7516: 1066 +7517: 1116 +7520: 7640 +7521: 5314 +7522: 1016 +7523: 7640 +7524: 5322 +7525: 6002 +7526: 5504 +7530: 3032 +7531: 1032 +7532: 7006 +7533: 7006 +7534: 4350 +7535: 4557 +7536: 7004 +7537: 4350 +7540: 7012 +7541: 7010 +7542: 4350 +7543: 4350 +7544: 7200 +7545: 1077 +7546: 4551 +7547: 5727 +7551: 0356 +7552: 1113 +7553: 4551 +7554: 1032 +7555: 5750 +7556: 0007 diff --git a/soft/hellorld.oct b/soft/hellorld.oct new file mode 100644 index 0000000..b515e05 --- /dev/null +++ b/soft/hellorld.oct @@ -0,0 +1,25 @@ +0200: 7200 +0201: 7100 +0202: 1220 +0203: 3010 +0204: 7000 +0205: 1410 +0206: 7450 +0207: 7402 +0210: 4212 +0211: 5204 +0213: 6046 +0214: 6041 +0215: 5214 +0216: 7200 +0217: 5612 +0220: 0220 +0221: 0110 +0222: 0105 +0223: 0114 +0224: 0114 +0225: 0117 +0226: 0122 +0227: 0114 +0230: 0104 +0231: 0041 diff --git a/soft/test.oct b/soft/test.oct new file mode 100644 index 0000000..0e0cfa0 --- /dev/null +++ b/soft/test.oct @@ -0,0 +1,308 @@ +0001: 5003 +0003: 7001 +0004: 5600 +0020: 0000 +0021: 7200 +0022: 1026 +0023: 6046 +0024: 7200 +0025: 5620 +0026: 0056 +0031: 7777 +0032: 0001 + +0200: 7200 +0201: 1031 +0202: 1032 +0203: 7001 +0204: 4020 + +0220: 2211 +0221: 5223 +0222: 7001 +0223: 7001 +0224: 4020 +0011: 7777 + +0240: 1410 +0241: 1410 +0242: 7001 +0010: 0243 +0243: 0001 +0244: 0002 +0245: 4020 + +0260: 4265 +0261: 7001 +0262: 5270 +0265: 7200 +0266: 7001 +0267: 5665 +0270: 4020 +0271: 5300 + +0300: 7200 +0301: 7041 +0302: 7001 +0303: 4020 + +0320: 7200 +0321: 7001 +0322: 7010 +0323: 7001 +0324: 4020 + +0340: 1211 +0341: 7001 +0011: 0342 +0342: 0005 +0343: 4020 + +0360: 5361 +0361: 1261 +0362: 7001 +0361: 0005 +0363: 4020 + +0400: 1211 +0401: 7200 +0402: 7200 +0403: 1211 +0404: 7001 +0011: 0003 +0401: 0005 +0405: 4020 + +0420: 7200 +0421: 7440 +0422: 7440 +0423: 7001 +0424: 7001 +0425: 4020 + +0440: 3211 +0441: 5242 +0442: 7001 +0443: 4020 + +0460: 1211 +0461: 7001 +0461: 0470 +0470: 0007 +0462: 4020 +0463: 5300 + +0500: 7200 +0501: 2110 +0502: 7402 +0503: 7001 +0504: 4020 +0505: 5320 +0110: 7777 + +0520: 7200 +0521: 7001 +0522: 3730 +0523: 7200 +0524: 1730 +0525: 4020 +0526: 5340 +0530: 0531 +0531: 0000 + +0540: 7200 +0541: 7020 +0542: 7100 +0543: 7020 +0544: 4020 +0545: 5360 + +0560: 7200 +0561: 7001 +0562: 7004 +0563: 7006 +0564: 4020 +0565: 5766 +0566: 0600 + +0600: 7200 +0601: 1610 +0602: 7002 +0603: 4020 +0604: 5220 +0610: 0007 + +0620: 7200 +0621: 7020 +0622: 7420 +0623: 7402 +0624: 7100 +0625: 7430 +0626: 7402 +0627: 4020 +0630: 5240 + +0640: 7200 +0641: 7040 +0642: 7500 +0643: 7402 +0644: 7200 +0645: 7001 +0646: 7510 +0647: 7402 +0650: 4020 +0651: 5260 + +0660: 7200 +0661: 7001 +0662: 7450 +0663: 7402 +0664: 4020 +0665: 5330 + + +0730: 7200 +0731: 7404 +0732: 7440 +0733: 5336 +0734: 5342 +0736: 1345 +0737: 7440 +0740: 7402 +0742: 4020 +0743: 5746 +0745: 6544 +0746: 1000 + +1000: 7200 +1001: 6040 +1002: 6041 +1003: 7402 +1004: 6042 +1005: 6041 +1006: 5210 +1007: 7402 +1010: 4020 +1011: 5240 + + +1040: 7200 +1041: 7001 +1042: 7001 +1043: 7100 +1044: 7012 +1045: 7420 +1046: 7402 +1047: 7440 +1050: 7402 +1051: 4020 +1052: 5260 + +1060: 7200 +1061: 7540 +1062: 7402 +1063: 7040 +1064: 7540 +1065: 7402 +1066: 7200 +1067: 7001 +1070: 7550 +1071: 7402 +1072: 7200 +1073: 7550 +1074: 5276 +1075: 7402 +1076: 4020 +1077: 5700 + +1100: 1220 + + + + + +1220: 7300 +1221: 1237 +1222: 7006 +1223: 7440 +1224: 7402 +1225: 7420 +1226: 7402 +1227: 4020 +1230: 5240 +1237: 2000 + +1240: 6042 +1241: 7200 +1242: 6001 +1243: 7000 +1244: 6040 +1245: 6042 +1246: 7001 +1247: 1255 +1250: 7440 +1251: 7402 +1252: 6002 +1253: 4020 +1254: 5260 +1255: 7776 + +1260: 6042 +1261: 7200 +1262: 6001 +1263: 7000 +1264: 6002 +1265: 6040 +1266: 7440 +1267: 7402 +1270: 4020 +1271: 5300 + +1300: 7300 +1301: 7020 +1302: 6040 +1303: 6004 +1304: 1320 +1305: 7440 +1306: 7402 +1307: 4020 +1310: 5330 +1320: 3000 + +1330: 7200 +1331: 6042 +1332: 6003 +1333: 5335 +1334: 7402 +1335: 6040 +1336: 6003 +1337: 7402 +1340: 4020 +1341: 5350 + +1350: 6042 +1351: 7200 +1352: 1376 +1353: 6005 +1354: 7000 +1355: 6040 +1356: 7420 +1357: 7402 +1360: 4020 +1361: 5362 + +1362: 7300 +1363: 7001 +1364: 7020 +1365: 6040 +1366: 6007 +1367: 7440 +1368: 7402 +1369: 7430 +1370: 7402 +1371: 6003 +1372: 5374 +1373: 7402 +1374: 4020 +1375: 7402 +1376: 4000