BEEP_STYLE_VT100 = 1
beep_style = BEEP_STYLE_ALSA
-gr_width = 1
# global state
termios_attr = None
addr = bascalc(i)
low_mem[addr:addr + 40] = [0] * 40
+# takes memory encoded with upper pixel in bits 0-3, lower in bits 4-7
+# returns a stream of unicode characters with attribute-setting escapes
+# attribute-setting can be optimized by passing in a previous attribute
+def gr_encode(_in, attr = (-1, -1, -1)):
+ out = []
+ for i in _in:
+ background = colors[i & 0xf]
+ foreground = colors[i >> 4]
+ # we cannot draw two different intense colours in same block,
+ # so just do the best we can (the greater colour gets priority)
+ if background < foreground:
+ ch = '▄'
+ elif background > foreground:
+ background, foreground = foreground, background
+ ch = '▀'
+ elif background < 8:
+ # we try to draw not-intense pixels using background, it
+ # might play nicer with terminals that use black-on-white
+ foreground = 0
+ ch = ' '
+ else:
+ background = 0
+ ch = '█'
+ new_attr = (background & 7, foreground & 7, foreground >> 3)
+ if new_attr != attr:
+ out.append(
+ '\x1b[0;{0:d};{1:d}{2:s}m'.format(
+ new_attr[0] + 40,
+ new_attr[1] + 30,
+ ';1' if new_attr[2] else ''
+ )
+ )
+ attr = new_attr
+ out.append(ch)
+ return ''.join(out), attr
+
def gr_update(x0, y0, x1, y1):
write('\x1b[s') # save cursor
- bg = -1
- fg = -1
- br = -1
+ attr = (-1, -1, -1)
for i in range(y0, y1):
- write(f'\x1b[{i + 1:d};{x0 * gr_width + 1:d}H')
addr = bascalc(i)
- for j in range(x0, x1):
- new_bg = colors[low_mem[addr + j] & 0xf]
- new_fg = colors[low_mem[addr + j] >> 4]
- # we cannot draw two different intense colours in same block,
- # so just do the best we can (the greater colour gets priority)
- if new_bg < new_fg:
- ch = '▄'
- elif new_bg > new_fg:
- new_bg, new_fg = new_fg, new_bg
- ch = '▀'
- elif new_bg < 8:
- # we try to draw not-intense pixels using background, it
- # might play nicer with terminals that use black-on-white
- new_fg = 0
- ch = ' '
- else:
- new_bg = 0
- ch = '█'
- new_br = new_fg >= 8
- new_bg &= 7
- new_fg &= 7
- if new_bg != bg or new_fg != fg or new_br != br:
- write(
- '\x1b[0{0:s}{1:s}{2:s}m'.format(
- f';4{new_bg:d}' if new_bg else '',
- f';3{new_fg:d}' if new_fg else '',
- ';1' if new_br else ''
- )
- )
- bg = new_bg
- fg = new_fg
- br = new_br
- write(ch * gr_width)
+ data, attr = gr_encode(low_mem[addr + x0:addr + x1], attr)
+ write(f'\x1b[{i + 1:d};{x0 + 1:d}H{data:s}')
write('\x1b[u') # restore cursor
invflg() # restore normal/inverse/flash
while len(sys.argv) >= 2:
if sys.argv[1][:7] == '--beep-style=':
apple_io.beep_style = beep_styles[sys.arg[1][7:]]
- elif sys.argv[1][:11] == '--gr-width=':
- apple_io.gr_width = int(sys.argv[1][11:])
elif sys.argv[1][:11] == '--joystick=':
apple_joystick.input_path = sys.argv[1][11:]
else:
break
del sys.argv[1]
if len(sys.argv) < 2:
- print(f'usage: {sys.argv[0]:s} [--beep-style=alsa|vt100] [--gr-width=n] [--joystick=/dev/input/eventNN] program.tok')
+ print(f'usage: {sys.argv[0]:s} [--beep-style=alsa|vt100] [--joystick=/dev/input/eventNN] program.tok')
sys.exit(EXIT_FAILURE)
program_bas = sys.argv[1]