def value_pmap(ins): """ PMAP: convert between logical and physical coordinates. """ util.require_read(ins, ('(', )) coord = parse_expression(ins) util.require_read(ins, (',', )) mode = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')', )) util.range_check(0, 3, mode) screen = state.console_state.screen if screen.mode.is_text_mode: return vartypes.null('%') if mode == 0: value, _ = screen.drawing.get_window_physical( fp.unpack(vartypes.pass_single(coord)), fp.Single.zero) return vartypes.int_to_integer_signed(value) elif mode == 1: _, value = screen.drawing.get_window_physical( fp.Single.zero, fp.unpack(vartypes.pass_single(coord))) return vartypes.int_to_integer_signed(value) elif mode == 2: value, _ = screen.drawing.get_window_logical( vartypes.pass_int_unpack(coord), 0) return fp.pack(value) elif mode == 3: _, value = screen.drawing.get_window_logical( 0, vartypes.pass_int_unpack(coord)) return fp.pack(value)
def value_operator(op, left, right): """ Get value of binary operator expression. """ if op == tk.O_CARET: return vcaret(left, right) elif op == tk.O_TIMES: return vtimes(left, right) elif op == tk.O_DIV: return vdiv(left, right) elif op == tk.O_INTDIV: return fp.pack( fp.div( fp.unpack(vartypes.pass_single_keep(left)).ifloor(), fp.unpack(vartypes.pass_single_keep( right)).ifloor()).apply_carry().ifloor()) elif op == tk.MOD: numerator = vartypes.pass_int_unpack(right) if numerator == 0: # simulate division by zero return fp.pack( fp.div( fp.unpack(vartypes.pass_single_keep(left)).ifloor(), fp.unpack( vartypes.pass_single_keep(right)).ifloor()).ifloor()) return vartypes.pack_int(vartypes.pass_int_unpack(left) % numerator) elif op == tk.O_PLUS: return vplus(left, right) elif op == tk.O_MINUS: return vartypes.number_add(left, vartypes.number_neg(right)) elif op == tk.O_GT: return vartypes.bool_to_int_keep(vartypes.gt(left, right)) elif op == tk.O_EQ: return vartypes.bool_to_int_keep(vartypes.equals(left, right)) elif op == tk.O_LT: return vartypes.bool_to_int_keep(not ( vartypes.gt(left, right) or vartypes.equals(left, right))) elif op == tk.O_GT + tk.O_EQ: return vartypes.bool_to_int_keep( vartypes.gt(left, right) or vartypes.equals(left, right)) elif op == tk.O_LT + tk.O_EQ: return vartypes.bool_to_int_keep(not vartypes.gt(left, right)) elif op == tk.O_LT + tk.O_GT: return vartypes.bool_to_int_keep(not vartypes.equals(left, right)) elif op == tk.AND: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) & vartypes.pass_twoscomp(right)) elif op == tk.OR: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) | vartypes.pass_twoscomp(right)) elif op == tk.XOR: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right)) elif op == tk.EQV: return vartypes.twoscomp_to_int(~(vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right))) elif op == tk.IMP: return vartypes.twoscomp_to_int((~vartypes.pass_twoscomp(left)) | vartypes.pass_twoscomp(right)) else: raise error.RunError(error.STX)
def number_modulo(left, right): """ Left MOD right. """ divisor = vartypes.pass_int_unpack(right) dividend = vartypes.pass_int_unpack(left) if divisor == 0: # division by zero, return single-precision maximum raise ZeroDivisionError(fp.Single(dividend<0, fp.Single.max.man, fp.Single.max.exp)) mod = dividend % divisor if dividend < 0 or mod < 0: mod -= divisor return vartypes.int_to_integer_signed(mod)
def number_intdiv(left, right): """ Left\\right. """ dividend = vartypes.pass_int_unpack(left) divisor = vartypes.pass_int_unpack(right) if divisor == 0: # division by zero, return single-precision maximum raise ZeroDivisionError(fp.Single(dividend<0, fp.Single.max.man, fp.Single.max.exp)) if (dividend >= 0) == (divisor >= 0): return vartypes.int_to_integer_signed(dividend / divisor) else: return vartypes.int_to_integer_signed(-(abs(dividend) / abs(divisor)))
def value_string(ins): """ STRING$: repeat characters. """ util.require_read(ins, ('(',)) n, j = parse_expr_list(ins, 2) n = vartypes.pass_int_unpack(n) util.range_check(0, 255, n) if j[0] == '$': j = vartypes.unpack_string(j) util.range_check(1, 255, len(j)) j = j[0] else: j = vartypes.pass_int_unpack(j) util.range_check(0, 255, j) util.require_read(ins, (')',)) return vartypes.pack_string(bytearray(chr(j)*n))
def value_string(ins): """ STRING$: repeat characters. """ util.require_read(ins, ('(', )) n, j = parse_expr_list(ins, 2) n = vartypes.pass_int_unpack(n) util.range_check(0, 255, n) if j[0] == '$': j = vartypes.unpack_string(j) util.range_check(1, 255, len(j)) j = j[0] else: j = vartypes.pass_int_unpack(j) util.range_check(0, 255, j) util.require_read(ins, (')', )) return vartypes.pack_string(bytearray(chr(j) * n))
def value_point(ins): """ POINT: get pixel attribute at screen location. """ util.require_read(ins, ('(',)) lst = parse_expr_list(ins, 2, err=error.STX) util.require_read(ins, (')',)) if not lst[0]: raise error.RunError(error.STX) screen = state.console_state.screen if not lst[1]: # single-argument version try: x, y = screen.drawing.last_point fn = vartypes.pass_int_unpack(lst[0]) if fn == 0: return vartypes.pack_int(x) elif fn == 1: return vartypes.pack_int(y) elif fn == 2: fx, _ = screen.drawing.get_window_logical(x, y) return fp.pack(fx) elif fn == 3: _, fy = screen.drawing.get_window_logical(x, y) return fp.pack(fy) except AttributeError: return vartypes.null['%'] else: # two-argument mode if screen.mode.is_text_mode: raise error.RunError(error.IFC) return vartypes.pack_int(screen.drawing.point( (fp.unpack(vartypes.pass_single_keep(lst[0])), fp.unpack(vartypes.pass_single_keep(lst[1])), False)))
def value_point(ins): """ POINT: get pixel attribute at screen location. """ util.require_read(ins, ('(', )) arg0 = parse_expression(ins) screen = state.console_state.screen if util.skip_white_read_if(ins, (',', )): # two-argument mode arg1 = parse_expression(ins) util.require_read(ins, (')', )) if screen.mode.is_text_mode: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed( screen.drawing.point( (fp.unpack(vartypes.pass_single(arg0)), fp.unpack(vartypes.pass_single(arg1)), False))) else: # single-argument mode util.require_read(ins, (')', )) try: x, y = screen.drawing.last_point fn = vartypes.pass_int_unpack(arg0) if fn == 0: return vartypes.int_to_integer_signed(x) elif fn == 1: return vartypes.int_to_integer_signed(y) elif fn == 2: fx, _ = screen.drawing.get_window_logical(x, y) return fp.pack(fx) elif fn == 3: _, fy = screen.drawing.get_window_logical(x, y) return fp.pack(fy) except AttributeError: return vartypes.null('%')
def value_lof(ins): """ LOF: get length of file. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) util.range_check(0, 255, num) the_file = devices.get_file(num) return fp.pack(fp.Single.from_int(the_file.lof()))
def value_strig(ins): """ STRIG: poll the joystick fire button. """ fn = vartypes.pass_int_unpack(parse_bracket(ins)) # 0,1 -> [0][0] 2,3 -> [0][1] 4,5-> [1][0] 6,7 -> [1][1] util.range_check(0, 7, fn) return vartypes.bool_to_int_keep( state.console_state.stick.poll_trigger(fn))
def value_play(ins): """ PLAY: get length of music queue. """ voice = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 255, voice) if not (is_pcjr_syntax and voice in (1, 2)): voice = 0 return vartypes.pack_int(state.console_state.sound.queue_length(voice))
def value_point(ins): """ POINT: get pixel attribute at screen location. """ util.require_read(ins, ('(', )) lst = parse_expr_list(ins, 2, err=error.STX) util.require_read(ins, (')', )) if not lst[0]: raise error.RunError(error.STX) screen = state.console_state.screen if not lst[1]: # single-argument version try: x, y = screen.drawing.last_point fn = vartypes.pass_int_unpack(lst[0]) if fn == 0: return vartypes.pack_int(x) elif fn == 1: return vartypes.pack_int(y) elif fn == 2: fx, _ = screen.drawing.get_window_logical(x, y) return fp.pack(fx) elif fn == 3: _, fy = screen.drawing.get_window_logical(x, y) return fp.pack(fy) except AttributeError: return vartypes.null['%'] else: # two-argument mode if screen.mode.is_text_mode: raise error.RunError(error.IFC) return vartypes.pack_int( screen.drawing.point( (fp.unpack(vartypes.pass_single_keep(lst[0])), fp.unpack(vartypes.pass_single_keep(lst[1])), False)))
def value_loc(ins): """ LOC: get file pointer. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) util.range_check(0, 255, num) the_file = devices.get_file(num) return vartypes.pack_int(the_file.loc())
def value_point(ins): """ POINT: get pixel attribute at screen location. """ util.require_read(ins, ('(',)) arg0 = parse_expression(ins) screen = state.console_state.screen if util.skip_white_read_if(ins, (',',)): # two-argument mode arg1 = parse_expression(ins) util.require_read(ins, (')',)) if screen.mode.is_text_mode: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed(screen.drawing.point( (fp.unpack(vartypes.pass_single(arg0)), fp.unpack(vartypes.pass_single(arg1)), False))) else: # single-argument mode util.require_read(ins, (')',)) try: x, y = screen.drawing.last_point fn = vartypes.pass_int_unpack(arg0) if fn == 0: return vartypes.int_to_integer_signed(x) elif fn == 1: return vartypes.int_to_integer_signed(y) elif fn == 2: fx, _ = screen.drawing.get_window_logical(x, y) return fp.pack(fx) elif fn == 3: _, fy = screen.drawing.get_window_logical(x, y) return fp.pack(fy) except AttributeError: return vartypes.null('%')
def value_play(ins): """ PLAY: get length of music queue. """ voice = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 255, voice) if not(is_pcjr_syntax and voice in (1, 2)): voice = 0 return vartypes.int_to_integer_signed(state.console_state.sound.queue_length(voice))
def value_loc(ins): """ LOC: get file pointer. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) util.range_check(0, 255, num) the_file = devices.get_file(num) return vartypes.pack_int(the_file.loc())
def value_lof(ins): """ LOF: get length of file. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) util.range_check(0, 255, num) the_file = devices.get_file(num) return fp.pack(fp.Single.from_int(the_file.lof()))
def value_string(ins): """ STRING$: repeat characters. """ util.require_read(ins, ('(', )) n = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(0, 255, n) util.require_read(ins, (',', )) j = parse_expression(ins) if j[0] == '$': j = var.copy_str(j) util.range_check(1, 255, len(j)) j = ord(j[0]) else: j = vartypes.pass_int_unpack(j) util.range_check(0, 255, j) util.require_read(ins, (')', )) return state.basic_state.strings.store(chr(j) * n)
def value_string(ins): """ STRING$: repeat characters. """ util.require_read(ins, ('(',)) n = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(0, 255, n) util.require_read(ins, (',',)) j = parse_expression(ins) if j[0] == '$': j = var.copy_str(j) util.range_check(1, 255, len(j)) j = ord(j[0]) else: j = vartypes.pass_int_unpack(j) util.range_check(0, 255, j) util.require_read(ins, (')',)) return state.basic_state.strings.store(chr(j)*n)
def value_operator(op, left, right): """ Get value of binary operator expression. """ if op == tk.O_CARET: return vcaret(left, right) elif op == tk.O_TIMES: return vtimes(left, right) elif op == tk.O_DIV: return vdiv(left, right) elif op == tk.O_INTDIV: return fp.pack(fp.div(fp.unpack(vartypes.pass_single_keep(left)).ifloor(), fp.unpack(vartypes.pass_single_keep(right)).ifloor()).apply_carry().ifloor()) elif op == tk.MOD: numerator = vartypes.pass_int_unpack(right) if numerator == 0: # simulate division by zero return fp.pack(fp.div(fp.unpack(vartypes.pass_single_keep(left)).ifloor(), fp.unpack(vartypes.pass_single_keep(right)).ifloor()).ifloor()) return vartypes.pack_int(vartypes.pass_int_unpack(left) % numerator) elif op == tk.O_PLUS: return vplus(left, right) elif op == tk.O_MINUS: return vartypes.number_add(left, vartypes.number_neg(right)) elif op == tk.O_GT: return vartypes.bool_to_int_keep(vartypes.gt(left,right)) elif op == tk.O_EQ: return vartypes.bool_to_int_keep(vartypes.equals(left, right)) elif op == tk.O_LT: return vartypes.bool_to_int_keep(not(vartypes.gt(left,right) or vartypes.equals(left, right))) elif op == tk.O_GT + tk.O_EQ: return vartypes.bool_to_int_keep(vartypes.gt(left,right) or vartypes.equals(left, right)) elif op == tk.O_LT + tk.O_EQ: return vartypes.bool_to_int_keep(not vartypes.gt(left,right)) elif op == tk.O_LT + tk.O_GT: return vartypes.bool_to_int_keep(not vartypes.equals(left, right)) elif op == tk.AND: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) & vartypes.pass_twoscomp(right) ) elif op == tk.OR: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) | vartypes.pass_twoscomp(right) ) elif op == tk.XOR: return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right) ) elif op == tk.EQV: return vartypes.twoscomp_to_int( ~(vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right)) ) elif op == tk.IMP: return vartypes.twoscomp_to_int( (~vartypes.pass_twoscomp(left)) | vartypes.pass_twoscomp(right) ) else: raise error.RunError(error.STX)
def parse_int_list(ins, size, err=error.IFC, allow_last_empty=False): """ Helper function: parse a list of integers. """ exprlist = parse_expr_list(ins, size, err, allow_last_empty=allow_last_empty) return [(vartypes.pass_int_unpack(expr) if expr else None) for expr in exprlist]
def value_eof(ins): """ EOF: get end-of-file. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) if num == 0: return vartypes.null('%') util.range_check(0, 255, num) the_file = devices.get_file(num, 'IR') return vartypes.bool_to_integer(the_file.eof())
def value_lpos(ins): """ LPOS: get the current printer column. """ num = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 3, num) printer = state.io_state.devices['LPT' + max(1, num) + ':'] if printer.device_file: return vartypes.int_to_integer_signed(printer.device_file.col) else: return vartypes.int_to_integer_signed(1)
def parse_file_number(ins, file_mode='IOAR'): """ Helper function: parse a file number and retrieve the file object. """ screen = None if util.skip_white_read_if(ins, ('#', )): number = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(0, 255, number) screen = devices.get_file(number, file_mode) util.require_read(ins, (',', )) return screen
def value_pen(ins): """ PEN: poll the light pen. """ fn = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 9, fn) pen = state.console_state.pen.poll(fn) if pen is None or not state.basic_state.events.pen.enabled: # should return 0 or char pos 1 if PEN not ON pen = 1 if fn >= 6 else 0 return vartypes.int_to_integer_signed(pen)
def parse_file_number(ins, file_mode='IOAR'): """ Helper function: parse a file number and retrieve the file object. """ screen = None if util.skip_white_read_if(ins, ('#',)): number = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(0, 255, number) screen = devices.get_file(number, file_mode) util.require_read(ins, (',',)) return screen
def value_pen(ins): """ PEN: poll the light pen. """ fn = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 9, fn) pen = state.console_state.pen.poll(fn) if pen is None or not state.basic_state.events.pen.enabled: # should return 0 or char pos 1 if PEN not ON pen = 1 if fn >= 6 else 0 return vartypes.int_to_integer_signed(pen)
def value_lpos(ins): """ LPOS: get the current printer column. """ num = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 3, num) printer = state.io_state.devices['LPT' + max(1, num) + ':'] if printer.device_file: return vartypes.int_to_integer_signed(printer.device_file.col) else: return vartypes.int_to_integer_signed(1)
def value_eof(ins): """ EOF: get end-of-file. """ util.skip_white(ins) num = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) if num == 0: return vartypes.null('%') util.range_check(0, 255, num) the_file = devices.get_file(num, 'IR') return vartypes.bool_to_integer(the_file.eof())
def value_mid(ins): """ MID$: get substring. """ util.require_read(ins, ('(',)) s = var.copy_str(vartypes.pass_string(parse_expression(ins))) util.require_read(ins, (',',)) start = vartypes.pass_int_unpack(parse_expression(ins)) if util.skip_white_read_if(ins, (',',)): num = vartypes.pass_int_unpack(parse_expression(ins)) else: num = len(s) util.require_read(ins, (')',)) util.range_check(1, 255, start) util.range_check(0, 255, num) if num == 0 or start > len(s): return vartypes.null('$') start -= 1 stop = start + num stop = min(stop, len(s)) return state.basic_state.strings.store(s[start:stop])
def value_mid(ins): """ MID$: get substring. """ util.require_read(ins, ('(', )) s = var.copy_str(vartypes.pass_string(parse_expression(ins))) util.require_read(ins, (',', )) start = vartypes.pass_int_unpack(parse_expression(ins)) if util.skip_white_read_if(ins, (',', )): num = vartypes.pass_int_unpack(parse_expression(ins)) else: num = len(s) util.require_read(ins, (')', )) util.range_check(1, 255, start) util.range_check(0, 255, num) if num == 0 or start > len(s): return vartypes.null('$') start -= 1 stop = start + num stop = min(stop, len(s)) return state.basic_state.strings.store(s[start:stop])
def value_environ(ins): """ ENVIRON$: get environment string. """ util.require_read(ins, ('$',)) expr = parse_bracket(ins) if expr[0] == '$': return state.basic_state.strings.store(shell.get_env(var.copy_str(expr))) else: expr = vartypes.pass_int_unpack(expr) util.range_check(1, 255, expr) return state.basic_state.strings.store(shell.get_env_entry(expr))
def type_converter(self, v_val): if (v_val[0] == '%'): return vartypes.pass_int_unpack(v_val) elif (v_val[0] == '!'): return fp.Single.from_bytes(v_val[1]).to_value() elif (v_val[0] == '#'): return fp.Double.from_bytes(v_val[1]).to_value() elif (v_val[0] == '$'): return str(vartypes.pass_string_unpack(v_val)) else: raise error.RunError(error.TYPE_MISMATCH)
def value_screen(ins): """ SCREEN: get char or attribute at a location. """ util.require_read(ins, ('(',)) row = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (',',), err=error.IFC) col = vartypes.pass_int_unpack(parse_expression(ins)) z = 0 if util.skip_white_read_if(ins, (',',)): z = vartypes.pass_int_unpack(parse_expression(ins)) cmode = state.console_state.screen.mode util.range_check(1, cmode.height, row) if state.console_state.view_set: util.range_check(state.console_state.view_start, state.console_state.scroll_height, row) util.range_check(1, cmode.width, col) util.range_check(0, 255, z) util.require_read(ins, (')',)) if z and not cmode.is_text_mode: return vartypes.null('%') else: return vartypes.int_to_integer_signed(state.console_state.screen.apage.get_char_attr(row, col, z!=0))
def value_environ(ins): """ ENVIRON$: get environment string. """ util.require_read(ins, ('$', )) expr = parse_bracket(ins) if expr[0] == '$': return state.basic_state.strings.store( shell.get_env(var.copy_str(expr))) else: expr = vartypes.pass_int_unpack(expr) util.range_check(1, 255, expr) return state.basic_state.strings.store(shell.get_env_entry(expr))
def parse_variable(ins): """ Helper function: parse a variable or array element. """ name = util.parse_scalar(ins) indices = [] if util.skip_white_read_if(ins, ('[', '(')): # it's an array, read indices while True: indices.append(vartypes.pass_int_unpack(parse_expression(ins))) if not util.skip_white_read_if(ins, (',', )): break util.require_read(ins, (']', ')')) return name, indices
def value_right(ins): """ RIGHT$: get substring at the end of string. """ util.require_read(ins, ('(', )) s = var.copy_str(vartypes.pass_string(parse_expression(ins))) util.require_read(ins, (',', )) stop = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')', )) util.range_check(0, 255, stop) if stop == 0: return vartypes.null('$') stop = min(stop, len(s)) return state.basic_state.strings.store(s[-stop:])
def value_left(ins): """ LEFT$: get substring at the start of string. """ util.require_read(ins, ('(',)) s = vartypes.pass_string_unpack(parse_expression(ins)) util.require_read(ins, (',',)) stop = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')',)) util.range_check(0, 255, stop) if stop == 0: return vartypes.null['$'] stop = min(stop, len(s)) return vartypes.pack_string(s[:stop])
def parse_variable(ins): """ Helper function: parse a variable or array element. """ name = util.parse_scalar(ins) indices = [] if util.skip_white_read_if(ins, ('[', '(')): # it's an array, read indices while True: indices.append(vartypes.pass_int_unpack(parse_expression(ins))) if not util.skip_white_read_if(ins, (',',)): break util.require_read(ins, (']', ')')) return name, indices
def value_right(ins): """ RIGHT$: get substring at the end of string. """ util.require_read(ins, ('(',)) s = var.copy_str(vartypes.pass_string(parse_expression(ins))) util.require_read(ins, (',',)) stop = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')',)) util.range_check(0, 255, stop) if stop == 0: return vartypes.null('$') stop = min(stop, len(s)) return state.basic_state.strings.store(s[-stop:])
def value_left(ins): """ LEFT$: get substring at the start of string. """ util.require_read(ins, ('(', )) s = vartypes.pass_string_unpack(parse_expression(ins)) util.require_read(ins, (',', )) stop = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')', )) util.range_check(0, 255, stop) if stop == 0: return vartypes.null['$'] stop = min(stop, len(s)) return vartypes.pack_string(s[:stop])
def value_screen(ins): """ SCREEN: get char or attribute at a location. """ util.require_read(ins, ('(', )) row = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (',', ), err=error.IFC) col = vartypes.pass_int_unpack(parse_expression(ins)) z = 0 if util.skip_white_read_if(ins, (',', )): z = vartypes.pass_int_unpack(parse_expression(ins)) cmode = state.console_state.screen.mode util.range_check(1, cmode.height, row) if state.console_state.view_set: util.range_check(state.console_state.view_start, state.console_state.scroll_height, row) util.range_check(1, cmode.width, col) util.range_check(0, 255, z) util.require_read(ins, (')', )) if z and not cmode.is_text_mode: return vartypes.null('%') else: return vartypes.int_to_integer_signed( state.console_state.screen.apage.get_char_attr(row, col, z != 0))
def value_pmap(ins): """ PMAP: convert between logical and physical coordinates. """ util.require_read(ins, ('(',)) coord = parse_expression(ins) util.require_read(ins, (',',)) mode = vartypes.pass_int_unpack(parse_expression(ins)) util.require_read(ins, (')',)) util.range_check(0, 3, mode) screen = state.console_state.screen if screen.mode.is_text_mode: return vartypes.null('%') if mode == 0: value, _ = screen.drawing.get_window_physical(fp.unpack(vartypes.pass_single(coord)), fp.Single.zero) return vartypes.int_to_integer_signed(value) elif mode == 1: _, value = screen.drawing.get_window_physical(fp.Single.zero, fp.unpack(vartypes.pass_single(coord))) return vartypes.int_to_integer_signed(value) elif mode == 2: value, _ = screen.drawing.get_window_logical(vartypes.pass_int_unpack(coord), 0) return fp.pack(value) elif mode == 3: _, value = screen.drawing.get_window_logical(0, vartypes.pass_int_unpack(coord)) return fp.pack(value)
def value_input(ins): """ INPUT$: get characters from the keyboard or a file. """ util.require_read(ins, ('$',)) util.require_read(ins, ('(',)) num = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(1, 255, num) infile = backend.kybd_file if util.skip_white_read_if(ins, (',',)): infile = iolayer.get_file(parse_file_number_opthash(ins)) util.require_read(ins, (')',)) word = vartypes.pack_string(bytearray(infile.read_raw(num))) if len(word) < num: # input past end raise error.RunError(62) return word
def value_input(ins): """ INPUT$: get characters from the keyboard or a file. """ util.require_read(ins, ('$',)) util.require_read(ins, ('(',)) num = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(1, 255, num) infile = state.io_state.kybd_file if util.skip_white_read_if(ins, (',',)): infile = devices.get_file(parse_file_number_opthash(ins)) util.require_read(ins, (')',)) word = bytearray(infile.read_raw(num)) if len(word) < num: # input past end raise error.RunError(error.INPUT_PAST_END) return state.basic_state.strings.store(word)
def value_input(ins): """ INPUT$: get characters from the keyboard or a file. """ util.require_read(ins, ('$', )) util.require_read(ins, ('(', )) num = vartypes.pass_int_unpack(parse_expression(ins)) util.range_check(1, 255, num) infile = state.io_state.kybd_file if util.skip_white_read_if(ins, (',', )): infile = devices.get_file(parse_file_number_opthash(ins)) util.require_read(ins, (')', )) word = bytearray(infile.read_raw(num)) if len(word) < num: # input past end raise error.RunError(error.INPUT_PAST_END) return state.basic_state.strings.store(word)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(',)) big, small, n = '', '', 1 s = parse_expression(ins, empty_err=error.STX) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',',)) big = vartypes.pass_string_unpack(parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string_unpack(s) util.require_read(ins, (',',)) small = vartypes.pass_string_unpack(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')',)) return vartypes.str_instr(big, small, n)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(', )) big, small, n = '', '', 1 s = parse_expression(ins, empty_err=error.STX) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',', )) big = vartypes.pass_string_unpack( parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string_unpack(s) util.require_read(ins, (',', )) small = vartypes.pass_string_unpack(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')', )) return vartypes.str_instr(big, small, n)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(', )) big, small, n = '', '', 1 # followed by coma so empty will raise STX s = parse_expression(ins) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',', )) big = vartypes.pass_string(parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string(s) util.require_read(ins, (',', )) small = vartypes.pass_string(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')', )) big, small = var.copy_str(big), var.copy_str(small) if big == '' or n > len(big): return vartypes.null('%') # BASIC counts string positions from 1 find = big[n - 1:].find(small) if find == -1: return vartypes.null('%') return vartypes.int_to_integer_signed(n + find)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(',)) big, small, n = '', '', 1 # followed by coma so empty will raise STX s = parse_expression(ins) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',',)) big = vartypes.pass_string(parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string(s) util.require_read(ins, (',',)) small = vartypes.pass_string(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')',)) big, small = var.copy_str(big), var.copy_str(small) if big == '' or n > len(big): return vartypes.null('%') # BASIC counts string positions from 1 find = big[n-1:].find(small) if find == -1: return vartypes.null('%') return vartypes.int_to_integer_signed(n + find)
def value_inp(ins): """ INP: get value from machine port. """ port = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) return vartypes.int_to_integer_signed(machine.inp(port))
def value_exterr(ins): """ EXTERR: device error information; not implemented. """ x = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 3, x) logging.warning("EXTERR() function not implemented.") return vartypes.null('%')
def ml_parse_number(gmls, default=None): """ Parse and return a number value in a macro-language string. """ return vartypes.pass_int_unpack(ml_parse_value(gmls, default), err=error.IFC)
def ml_parse_number(gmls, default=None): """ Parse and return a number value in a macro-language string. """ return vartypes.pass_int_unpack(ml_parse_value(gmls, default), err=error.IFC)
def value_exterr(ins): """ EXTERR: device error information; not implemented. """ x = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 3, x) logging.warning("EXTERR() function not implemented.") return vartypes.null('%')
def value_stick(ins): """ STICK: poll the joystick. """ fn = vartypes.pass_int_unpack(parse_bracket(ins)) util.range_check(0, 3, fn) return vartypes.int_to_integer_signed(state.console_state.stick.poll(fn))
def ml_parse_const_int(gmls): """ Parse a constant value in a macro-language string, return Python int. """ return vartypes.pass_int_unpack(ml_parse_const(gmls), err=error.IFC)
def value_peek(ins): """ PEEK: read memory location. """ addr = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) if state.basic_state.protected and not state.basic_state.run_mode: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed(machine.peek(addr))
def ml_parse_const_int(gmls): """ Parse a constant value in a macro-language string, return Python int. """ return vartypes.pass_int_unpack(ml_parse_const(gmls), err=error.IFC)
def value_inp(ins): """ INP: get value from machine port. """ port = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff) return vartypes.int_to_integer_signed(machine.inp(port))