initial upload

This commit is contained in:
Luxferre
2026-06-29 20:09:40 +03:00
commit b491b1f100
10 changed files with 4619 additions and 0 deletions
+79
View File
@@ -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 <input_bin_file> [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()
+116
View File
@@ -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 <input_octaddr_file> [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()
Executable
+8
View File
@@ -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"
+73
View File
@@ -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 <input_rim_file> [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()