74 lines
2.0 KiB
Python
74 lines
2.0 KiB
Python
#!/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()
|