ponydos/process_wallpaper.py

122 lines
3.3 KiB
Python

import sys
from collections import namedtuple
Attribute = namedtuple('Attribute', ['fg', 'bg', 'bold'])
WIDTH = 80
HEIGHT = 25
# ANSI orders the colours black, red, green, yellow, blue, magenta, cyan, white
# VGA orders them black, blue, green, cyan, red, magenta, yellow, white
color_map = [0, 4, 2, 6, 1, 5, 3, 7]
if len(sys.argv) != 7:
print("Usage: {sys.argv[0]} outfile infile default_fgcolor default_bgcolor origin_x origin_y", file=sys.stderr)
sys.exit(1)
outfile = sys.argv[1]
infile = sys.argv[2]
default_fgcolor = int(sys.argv[3])
assert 0 <= default_fgcolor <= 15
default_bgcolor = int(sys.argv[4])
assert 0 <= default_bgcolor <= 15
origin_x = int(sys.argv[5])
assert 0 <= origin_x < WIDTH
origin_y = int(sys.argv[6])
assert 0 <= origin_y < HEIGHT
chars = [bytearray([0]*HEIGHT) for _ in range(WIDTH)]
attributes = [[(Attribute(default_fgcolor, default_bgcolor, False))]*HEIGHT for _ in range(WIDTH)]
with open(infile, 'rb') as f:
ansitext = f.read()
x = origin_x
y = origin_y
fgcolor = default_fgcolor
bgcolor = default_bgcolor
bold = False
error = False
line = 1
line_start = 0
index = 0
while index < len(ansitext):
if ansitext[index:].startswith(b'\x1b['):
index += len(b'\x1b[')
escape_start = index
while index < len(ansitext) and ansitext[index] not in b'CDHJhm':
index += 1
escape_params = ansitext[escape_start:index]
escape_type = ansitext[index:index+1]
index += 1
if escape_type == b'C':
x += int(escape_params)
elif escape_type == b'D':
x -= int(escape_params)
elif escape_type == b'H':
row, column = escape_params.split(b';')
y = int(row) - 1
x = int(column) - 1
elif escape_type == b'J':
# Erase display
# We just ignore this, because why would you have
# erase command anywhere but at the start
pass
elif escape_type == b'h':
# Something nonstandard, ignore
pass
elif escape_type == b'm':
for color_parameter in escape_params.split(b';'):
color_parameter = int(color_parameter)
if color_parameter == 0:
bold = False
elif color_parameter == 1:
bold = True
elif color_parameter == 39:
fgcolor = default_fgcolor
elif color_parameter == 49:
bgcolor = default_bgcolor
elif 30 <= color_parameter <= 37:
fgcolor = color_map[color_parameter - 30]
elif 40 <= color_parameter <= 47:
bgcolor = color_map[color_parameter - 40]
elif 90 <= color_parameter <= 97:
fgcolor = color_map[color_parameter - 90] + 8
elif 100 <= color_parameter <= 107:
bgcolor = color_map[color_parameter - 100] + 8
else:
print(f'{line},{escape_start-line_start+1}: Unknown colour escape {color_parameter}')
error = True
else:
print(f'{line},{escape_start-line_start+1}: Unknown escape ^[[{escape_params.decode()}{escape_type.decode()}')
error = True
elif ansitext[index] == 13:
x = origin_x
index += 1
elif ansitext[index] == 10:
for i in range(x, WIDTH):
attributes[i][y] = Attribute(fgcolor, bgcolor, bold)
x = origin_x
y += 1
index += 1
line += 1
line_start = index
else:
chars[x][y] = ansitext[index]
attributes[x][y] = Attribute(fgcolor, bgcolor, bold)
index += 1
x += 1
if error:
sys.exit(1)
with open(outfile, 'wb') as f:
for y in range(HEIGHT):
for x in range(WIDTH):
fgcolor, bgcolor, bold = attributes[x][y]
char = chars[x][y]
f.write(bytes([char, (bgcolor<<4) | fgcolor | (8 if bold else 0)]))