PCM_RATE = 44100
PCM_PERIODSIZE = 441
+# target will yield this much time whenever it polls HW_IOADR
+POLL_TIMEOUT_MS = 1
+
# see https://www.tinaja.com/ebooks/tearing_rework.pdf
ZP_WNDLFT = 0x20 # Left side of scroll window
ZP_WNDWTH = 0x21 # Width of scroll window
NICK_DURH: 0,
NICK_FREQL: 0,
NICK_FREQH: 0,
+ HW_IOADR: 0,
+ HW_PB0: 0,
+ HW_PB1: 0,
+ HW_PB2: 0,
}
gr_mem = [[0 for j in range(40)] for i in range(40)]
+pdl_value = [255 for i in range(4)]
def init():
global termios_attr, pcm
def in_hash(n):
pass
-def read_ready():
- return len(poll_in.poll(1)) != 0
-
def read(n):
return str(os.read(fd_in, 1), 'utf-8')
crlf()
def get():
+ # if there is a lookahead from PEEK of HW_IOADR, cancel and return it
+ if mem[HW_IOADR] >= 0x80:
+ mem[HW_IOADR] &= 0x7f
+ return chr(HW_IOADR)
ch = read(1)
if len(ch) == 0:
raise Exception('end of input') # due to piping or input redirection
def peek(addr):
addr &= 0xffff
+ if addr == HW_IOADR:
+ if mem[HW_IOADR] < 0x80 and len(poll_in.poll(POLL_TIMEOUT_MS)):
+ mem[HW_IOADR] = ord(read(1)) | 0x80
return mem.get(addr, 0)
def poke(addr, data):
return gr_mem[y][x]
def pdl(n):
- return 127
+ return pdl_value[n]
def pos():
return mem[ZP_CH]
--- /dev/null
+import apple_io
+import evdev
+import select
+import sys
+import threading
+
+POLL_TIMEOUT_MS = 1 # program will take this long to exit
+
+input_path = None
+input_device = None
+input_thread = None
+
+thread = None
+stop = False
+poll = select.poll()
+
+def init():
+ global input_device, poll, stop, thread
+ assert input_device is None
+ if input_path is not None:
+ # we will not update these until we get some movement,
+ # so start with a reasonable value (not timeout value)
+ apple_io.pdl_value[:3] = [128, 128, 128]
+
+ input_device = evdev.InputDevice(input_path)
+
+ poll = select.poll()
+ poll.register(input_device.fd, select.POLLIN)
+
+ stop = False
+ thread = threading.Thread(target = run, daemon = True)
+ thread.start()
+
+def deinit():
+ global input_device, poll, stop, thread
+ if thread is not None:
+ stop = True
+ thread.join()
+ thread = None
+
+ poll = None
+
+ input_device.close()
+ input_device = None
+
+ # the timeout value generally indicates no joystick present
+ apple_io.pdl_value[:3] = [255, 255, 255]
+
+def run():
+ while not stop:
+ if len(poll.poll(POLL_TIMEOUT_MS)):
+ for event in input_device.read():
+ # the below event codes were determined by experiment using my
+ # Mad Catz, Inc. Mad Catz V.1 Stick (USB ID 0738:2237), I don't
+ # know whether other joysticks use consistent axis/button codes
+ if event.type == evdev.ecodes.EV_ABS:
+ #sys.stderr.write(f'abs code {event.code:d} value {event.value:d}\r\n')
+ if event.code == 0:
+ apple_io.pdl_value[0] = event.value & 0xff
+ elif event.code == 1:
+ apple_io.pdl_value[1] = event.value & 0xff
+ elif event.code == 5:
+ apple_io.pdl_value[2] = event.value & 0xff
+ elif event.type == evdev.ecodes.EV_KEY:
+ #sys.stderr.write(f'key code {event.code:d} value {event.value:d}\r\n')
+ if event.code == 288:
+ apple_io.mem[apple_io.HW_PB0] = 0x80 if event.value else 0
+ if event.code == 290:
+ apple_io.mem[apple_io.HW_PB1] = 0x80 if event.value else 0
+ if event.code == 291:
+ apple_io.mem[apple_io.HW_PB2] = 0x80 if event.value else 0
import apple_io
import element
import lex_yy
+import apple_joystick
import sys
import t_def
import y_tab
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] program.tok')
+ print(f'usage: {sys.argv[0]:s} [--beep-style=alsa|vt100] [--gr-width=n] [--joystick=/dev/input/eventNN] program.tok')
sys.exit(EXIT_FAILURE)
program_bas = sys.argv[1]
with open(program_bas) as fin:
- #print('y_tab.yyparse()')
lex_yy.yyin = fin
program = y_tab.yyparse(t_def.Program)
-
-#print('element.serialize()')
#element.serialize(program, sys.stdout)
-#print('program.post_process()')
program.post_process(program)
-
-#print('element.serialize()')
#element.serialize(program, sys.stdout)
-#print('apple_io.init()')
apple_io.init()
try:
+ apple_joystick.init()
#print('context.run()')
context = t_def.Context(program)
context.run()
finally:
#print('apple_io.deinit()')
apple_io.deinit()
+ apple_joystick.deinit()
@method(RValuePdl)
def get(self, context):
value = self.children[0].get_int(context)
+ if value < 0 or value >= 4:
+ raise Exception(
+ f'?ILLEGAL QUANTITY ERROR IN {context.line_number():d}'
+ )
return float(apple_io.pdl(value))
@method(RValuePos)
def get(self, context):
--- /dev/null
+10PRINTPDL(0);" ";PDL(1);" ";PDL(2);" ";PEEK(-16287)>=128;" ";PEEK(-16286)>=128;" ";PEEK(-16285)>=128
+20IFPEEK(-16384)<128THEN10
+30GETI$