Lo-res graphics sort of working (needs some modifications to LEMONADE source)
authorNick Downing <nick@ndcode.org>
Wed, 18 May 2022 01:53:44 +0000 (11:53 +1000)
committerNick Downing <nick@ndcode.org>
Wed, 18 May 2022 01:53:44 +0000 (11:53 +1000)
apple_io.py
applesoft_basic.py
test_io.bas

index 267ddcf..978bd84 100755 (executable)
@@ -5,6 +5,7 @@ import os
 import select
 import sys
 import termios
+import time
 import tty
 
 # see https://www.tinaja.com/ebooks/tearing_rework.pdf
@@ -141,6 +142,26 @@ ROM_IOSAVE = 0xFF4A # Save all working registers
 ROM_OLDRST = 0xFF59 # Old reset entry, no autostart
 ROM_MON = 0xFF65 # Enter monitor and beep spkr
 
+# colors (map 15 apple colors to 16 VT100 colours, some duplicate or unused)
+colors = [
+  0x0, # black -> black
+  0x5, # dark pink -> magenta
+  0x1, # dark blue -> blue
+  0x5, # dark purple -> magenta
+  0x2, # dark green -> green
+  0x7, # grey 1 -> white
+  0x9, # light blue -> intense blue
+  0xd, # light purple -> intense magenta
+  0x6, # dark yellow -> yellow
+  0xe, # orange -> intense yellow
+  0x7, # grey 2 -> white
+  0xc, # pink -> intense red
+  0xa, # light green -> intense green
+  0xe, # light yellow -> intense yellow
+  0xb, # light cyan -> intense cyan
+  0xf, # white -> intense white
+]
+
 # global state
 attr = None
 fd_in = sys.stdin.fileno()
@@ -153,6 +174,8 @@ mem = {
   0x300: 0, # tone freq
   0x301: 0, # tone dur
 }
+gr_color = 0
+gr_mem = [[0 for j in range(40)] for i in range(40)]
 
 def init():
   global attr
@@ -180,10 +203,10 @@ def read_ready():
   return len(poll_in.poll(1)) != 0
 
 def read(n):
-  return str(os.read(fd_in, 1), 'ascii')
+  return str(os.read(fd_in, 1), 'utf-8')
 
 def write(data):
-  os.write(fd_out, bytes(data, 'ascii'))
+  os.write(fd_out, bytes(data, 'utf-8'))
 
 def _print(data):
   for ch in data:
@@ -251,7 +274,7 @@ def clreop():
   write('\x1b[J')
 
 def home():
-  write('\x1b[H\x1b[2J')
+  write('\x1b[2J\x1b[H')
   mem[ZP_CH] = 0
   mem[ZP_CV] = 0
 
@@ -266,7 +289,8 @@ def flash():
 
 def tone(freq, dur): # Hz, ms
   # doesn't seem to work on any linux console on my laptop
-  write(f'\x1b7\x1b[10;{freq:d}]\x1b[11;{dur:d}]\x07\x1b8')
+  #write(f'\x1b7\x1b[10;{freq:d}]\x1b[11;{dur:d}]\x07\x1b8')
+  time.sleep(dur * .001)
 
 def himem(addr):
   pass
@@ -299,25 +323,84 @@ def text():
   pass
 
 def gr():
-  pass
+  write('\x1b[2J\x1b[21H')
+  mem[ZP_CH] = 0
+  mem[ZP_CV] = 20
+  for i in range(40):
+    gr_mem[i][:] = [0 for j in range(40)]
+
+def gr_update(x0, y0, x1, y1):
+  write('\x1b[s') # save cursor
+  bg = -1
+  fg = -1
+  br = -1
+  for i in range(y0, y1):
+    write(f'\x1b[{i + 1:d};{x0 * 2 + 1:d}H')
+    for j in range(x0, x1):
+      new_bg = colors[gr_mem[i * 2][j]]
+      new_fg = colors[gr_mem[i * 2 + 1][j]]
+      # 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 * 2)
+  write('\x1b[u\x1b[0m') # restore cursor and attrs
+  time.sleep(.1)
 
 def color(n):
-  pass
+  global gr_color
+  gr_color = n
 
 def plot(x, y):
-  pass
+  gr_mem[y][x] = gr_color
+  y >>= 1
+  gr_update(x, y, x + 1, y + 1)
 
 def hlin(x0, x1, y):
-  pass
+  if x1 < x0:
+    x0, x1 = x1, x0
+  for x in range(x0, x1 + 1):
+    gr_mem[y][x] = gr_color
+  y >>= 1
+  gr_update(x0, y, x1 + 1, y + 1)
 
 def vlin(y0, y1, x):
-  pass
+  if y1 < y0:
+    y0, y1 = y1, y0
+  for y in range(y0, y1 + 1):
+    gr_mem[y][x] = gr_color
+  gr_update(x, y0 >> 1, x + 1, (y1 >> 1) + 1)
 
 def usr(n):
   return 0
 
 def scrn(x, y):
-  return 0
+  return gr_mem[y][x]
 
 def pdl(n):
   return 127
index 4f1347b..fcb7956 100755 (executable)
@@ -47,7 +47,7 @@ with open(program_bas) as fin:
 program.post_process(program)
 
 #print('element.serialize()')
-element.serialize(program, sys.stdout)
+#element.serialize(program, sys.stdout)
 
 #print('apple_io.init()')
 apple_io.init()
index bba54ea..cbec8ac 100644 (file)
 150 FLASH
 160 PRINT "GOODBYE"
 170 NORMAL
+180 GR
+190 COLOR=4
+200 PLOT 20,10
+210 COLOR=6
+220 VLIN 10,30 AT 15
+230 COLOR=13
+240 HLIN 10,30 AT 15
+250 TEXT