Improve console handling, fixes 40 column width issue, implements scroll window
authorNick Downing <nick@ndcode.org>
Thu, 19 May 2022 15:22:38 +0000 (01:22 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 19 May 2022 15:49:33 +0000 (01:49 +1000)
apple_io.py

index 0c89d20..6582b9b 100755 (executable)
@@ -174,6 +174,10 @@ fd_out = sys.stdout.fileno()
 poll_in = select.poll()
 poll_in.register(fd_in, select.POLLIN)
 mem = {
+  ZP_WNDLFT: 0,
+  ZP_WNDWTH: 40,
+  ZP_WNDTOP: 0,
+  ZP_WNDBTM: 24,
   ZP_CH: 0,
   ZP_CV: 0,
   0x300: 0, # tone period
@@ -240,6 +244,7 @@ def _print(data):
       elif mem[ZP_CH] < 39:
         mem[ZP_CH] += 1
       else:
+        write('\r\n')
         if mem[ZP_CV] < 23:
           mem[ZP_CV] += 1
         mem[ZP_CH] = 0
@@ -259,26 +264,25 @@ def input():
   line = ''
   while True:
     ch = get()
-    _print(ch)
-    if ch == '\r':
-      write('\x1b[?25l') # hide cursor
-      return line
     if ch == '\b':
       if len(line):
-        _print(' \b')
+        _print('\b \b')
         line = line[:-1]
-      else:
-        # strictly, apple only does this if cursor not at left, maybe
-        # because it knows the echoed backspace has no effect at left
+      elif mem[ZP_CH]:
         _print('\r')
     else:
-      if len(line) >= 247:
-        _print('\a')
-        if len(line) >= 255:
-          _print('\r')
-          line = ''
-          continue
-      line += ch
+      _print(ch)
+      if ch == '\r':
+        write('\x1b[?25l') # hide cursor
+        return line
+      else:
+        if len(line) >= 247:
+          _print('\a')
+          if len(line) >= 255:
+            _print('\r')
+            line = ''
+            continue
+        line += ch
 
 def htab(x):
   write(f'\x1b[{x:d}G')
@@ -330,10 +334,16 @@ def lomem(addr):
   pass
 
 def peek(addr):
-  return mem.get(addr & 0xffff, 0)
+  addr &= 0xffff
+  return mem.get(addr, 0)
 
 def poke(addr, data):
-  mem[addr & 0xffff] = data & 0xff
+  addr &= 0xffff
+  data &= 0xff
+  mem[addr] = data
+  if addr == ZP_WNDTOP or addr == ZP_WNDBTM:
+    # save cursor, set scrolling region, restore cursor
+    write(f'\x1b[s\x1b{mem[ZP_WNDTOP + 1]:d};{mem[ZP_WNDBTM]:d}24r\x1b[u')
 
 def call(addr):
   addr &= 0xffff
@@ -357,10 +367,19 @@ def call(addr):
     raise Exception(f'call {addr:04x}')
 
 def text():
-  pass
+  # save cursor, set scrolling region, restore cursor
+  write('\x1b[s\x1b1;24r\x1b[u')
+  mem[ZP_WNDLFT] = 0
+  mem[ZP_WNDWTH] = 40
+  mem[ZP_WNDTOP] = 0
+  mem[ZP_WNDBTM] = 24
 
 def gr():
-  write('\x1b[2J\x1b[21H')
+  # clear screen, set scrolling region (homes cursor)
+  mem[ZP_WNDLFT] = 0
+  mem[ZP_WNDWTH] = 40
+  mem[ZP_WNDTOP] = 20
+  mem[ZP_WNDBTM] = 24
   mem[ZP_CH] = 0
   mem[ZP_CV] = 20
   for i in range(40):