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_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_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_sgn(ins): """ SGN: get sign. """ inp = vartypes.pass_number(parse_bracket(ins)) if inp[0] == '%': inp_int = vartypes.integer_to_int_signed(inp) return vartypes.int_to_integer_signed(0 if inp_int==0 else (1 if inp_int > 0 else -1)) else: return vartypes.int_to_integer_signed(fp.unpack(inp).sign())
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_sgn(ins): """ SGN: get sign. """ inp = vartypes.pass_number(parse_bracket(ins)) if inp[0] == '%': inp_int = vartypes.integer_to_int_signed(inp) return vartypes.int_to_integer_signed(0 if inp_int == 0 else ( 1 if inp_int > 0 else -1)) else: return vartypes.int_to_integer_signed(fp.unpack(inp).sign())
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 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 number_sgn(inp): """ Return the sign of a number. """ if inp[0] == '%': i = vartypes.integer_to_int_signed(inp) if i > 0: return vartypes.int_to_integer_signed(1) elif i < 0: return vartypes.int_to_integer_signed(-1) else: return vartypes.int_to_integer_signed(0) elif inp[0] in ('!', '#'): return vartypes.int_to_integer_signed(fp.unpack(inp).sign()) return inp
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_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_pos(ins): """ POS: get the current screen column. """ # parse the dummy argument, doesnt matter what it is as long as it's a legal expression parse_bracket(ins) col = state.console_state.col if col == state.console_state.screen.mode.width and state.console_state.overflow: # in overflow position, return column 1. col = 1 return vartypes.int_to_integer_signed(col)
def value_csrlin(ins): """ CSRLIN: get the current screen row. """ row, col = state.console_state.row, state.console_state.col if (col == state.console_state.screen.mode.width and state.console_state.overflow and row < state.console_state.scroll_height): # in overflow position, return row+1 except on the last row row += 1 return vartypes.int_to_integer_signed(row)
def value_csrlin(ins): """ CSRLIN: get the current screen row. """ row, col = state.console_state.row, state.console_state.col if (col == state.console_state.screen.mode.width and state.console_state.overflow and row < state.console_state.scroll_height): # in overflow position, return row+1 except on the last row row += 1 return vartypes.int_to_integer_signed(row)
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_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_pos(ins): """ POS: get the current screen column. """ # parse the dummy argument, doesnt matter what it is as long as it's a legal expression parse_bracket(ins) col = state.console_state.col if col == state.console_state.screen.mode.width and state.console_state.overflow: # in overflow position, return column 1. col = 1 return vartypes.int_to_integer_signed(col)
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_inc_gt(typechar, loopvar, stop, step, sgn): """ Increase number and check if it exceeds a limit. """ if sgn == 0: return False if typechar in ('#', '!'): fp_left = fp.from_bytes(loopvar).iadd(step) loopvar[:] = fp_left.to_bytes() return fp_left.gt(stop) if sgn > 0 else stop.gt(fp_left) else: int_left = vartypes.integer_to_int_signed(vartypes.bytes_to_integer(loopvar)) + step loopvar[:] = vartypes.integer_to_bytes(vartypes.int_to_integer_signed(int_left)) return int_left > stop if sgn > 0 else stop > int_left
def ml_parse_const(gmls): """ Parse and return a constant value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) if c and c in string.digits: numstr = '' while c and c in string.digits: gmls.read(1) numstr += c c = util.skip(gmls, ml_whitepace) return vartypes.int_to_integer_signed(int(numstr)) else: raise error.RunError(error.IFC)
def ml_parse_const(gmls): """ Parse and return a constant value in a macro-language string. """ c = util.skip(gmls, ml_whitepace) if c and c in string.digits: numstr = '' while c and c in string.digits: gmls.read(1) numstr += c c = util.skip(gmls, ml_whitepace) return vartypes.int_to_integer_signed(int(numstr)) else: raise error.RunError(error.IFC)
def number_abs(inp): """ Return the absolute value of a number. """ if inp[0] == '%': val = abs(vartypes.integer_to_int_signed(inp)) if val == 32768: return fp.pack(fp.Single.from_int(val)) else: return vartypes.int_to_integer_signed(val) elif inp[0] in ('!', '#'): out = (inp[0], inp[1][:]) out[1][-2] &= 0x7F return out return inp
def number_inc_gt(typechar, loopvar, stop, step, sgn): """ Increase number and check if it exceeds a limit. """ if sgn == 0: return False if typechar in ('#', '!'): fp_left = fp.from_bytes(loopvar).iadd(step) loopvar[:] = fp_left.to_bytes() return fp_left.gt(stop) if sgn > 0 else stop.gt(fp_left) else: int_left = vartypes.integer_to_int_signed( vartypes.bytes_to_integer(loopvar)) + step loopvar[:] = vartypes.integer_to_bytes( vartypes.int_to_integer_signed(int_left)) return int_left > stop if sgn > 0 else stop > int_left
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 number_neg(inp): """ Return the negation of a number. """ inp = vartypes.pass_number(inp) if inp[0] == '%': val = -vartypes.integer_to_int_signed(inp) if val == 32768: return fp.pack(fp.Single.from_int(val)) else: return vartypes.int_to_integer_signed(val) elif inp[0] in ('!', '#'): out = (inp[0], inp[1][:]) out[1][-2] ^= 0x80 return out # pass strings on, let error happen somewhere else. return inp
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_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_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_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 value_err(ins): """ ERR: get error code of last error. """ return vartypes.int_to_integer_signed(state.basic_state.errn)
def value_err(ins): """ ERR: get error code of last error. """ return vartypes.int_to_integer_signed(state.basic_state.errn)
def value_len(ins): """ LEN: length of string. """ return vartypes.int_to_integer_signed( vartypes.string_length(vartypes.pass_string(parse_bracket(ins))))
def tokenise_dec(ins, outs): """ Convert decimal expression in Python string to number token. """ have_exp = False have_point = False word = '' kill = False while True: c = ins.read(1).upper() if not c: break elif c in '\x1c\x1d\x1f': # ASCII separator chars invariably lead to zero result kill = True elif c == '.' and not have_point and not have_exp: have_point = True word += c elif c in 'ED' and not have_exp: # there's a special exception for number followed by EL or EQ # presumably meant to protect ELSE and maybe EQV ? if c == 'E' and util.peek(ins).upper() in ('L', 'Q'): ins.seek(-1, 1) break else: have_exp = True word += c elif c in '-+' and (not word or word[-1] in 'ED'): # must be first token or in exponent word += c elif c in string.digits: word += c elif c in number_whitespace: # we'll remove this later but need to keep it for now # so we can reposition the stream on removing trailing whitespace word += c elif c in '!#' and not have_exp: word += c break elif c == '%': # swallow a %, but break parsing break else: ins.seek(-1, 1) break # ascii separators encountered: zero output if kill: word = '0' # don't claim trailing whitespace while len(word) > 0 and (word[-1] in number_whitespace): word = word[:-1] ins.seek(-1, 1) # even if c=='' # remove all internal whitespace trimword = '' for c in word: if c not in number_whitespace: trimword += c word = trimword # write out the numbers if len(word) == 1 and word in string.digits: # digit outs.write(chr(0x11 + str_to_int(word))) elif (not (have_exp or have_point or word[-1] in '!#') and str_to_int(word) <= 0x7fff and str_to_int(word) >= -0x8000): if str_to_int(word) <= 0xff and str_to_int(word) >= 0: # one-byte constant outs.write(tk.T_BYTE + chr(str_to_int(word))) else: # two-byte constant outs.write(tk.T_INT + str( vartypes.integer_to_bytes( vartypes.int_to_integer_signed(str_to_int(word))))) else: mbf = str(str_to_float(word).to_bytes()) if len(mbf) == 4: outs.write(tk.T_SINGLE + mbf) else: outs.write(tk.T_DOUBLE + mbf)
def value_asc(ins): """ ASC: ordinal ASCII value of a character. """ s = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if not s: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed(ord(s[0]))
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 tokenise_dec(ins, outs): """ Convert decimal expression in Python string to number token. """ have_exp = False have_point = False word = '' kill = False while True: c = ins.read(1).upper() if not c: break elif c in '\x1c\x1d\x1f': # ASCII separator chars invariably lead to zero result kill = True elif c == '.' and not have_point and not have_exp: have_point = True word += c elif c in 'ED' and not have_exp: # there's a special exception for number followed by EL or EQ # presumably meant to protect ELSE and maybe EQV ? if c == 'E' and util.peek(ins).upper() in ('L', 'Q'): ins.seek(-1, 1) break else: have_exp = True word += c elif c in '-+' and (not word or word[-1] in 'ED'): # must be first token or in exponent word += c elif c in string.digits: word += c elif c in number_whitespace: # we'll remove this later but need to keep it for now # so we can reposition the stream on removing trailing whitespace word += c elif c in '!#' and not have_exp: word += c break elif c == '%': # swallow a %, but break parsing break else: ins.seek(-1, 1) break # ascii separators encountered: zero output if kill: word = '0' # don't claim trailing whitespace while len(word)>0 and (word[-1] in number_whitespace): word = word[:-1] ins.seek(-1,1) # even if c=='' # remove all internal whitespace trimword = '' for c in word: if c not in number_whitespace: trimword += c word = trimword # write out the numbers if len(word) == 1 and word in string.digits: # digit outs.write(chr(0x11+str_to_int(word))) elif (not (have_exp or have_point or word[-1] in '!#') and str_to_int(word) <= 0x7fff and str_to_int(word) >= -0x8000): if str_to_int(word) <= 0xff and str_to_int(word) >= 0: # one-byte constant outs.write(tk.T_BYTE + chr(str_to_int(word))) else: # two-byte constant outs.write(tk.T_INT + str(vartypes.integer_to_bytes(vartypes.int_to_integer_signed(str_to_int(word))))) else: mbf = str(str_to_float(word).to_bytes()) if len(mbf) == 4: outs.write(tk.T_SINGLE + mbf) else: outs.write(tk.T_DOUBLE + mbf)
def number_not(right): """ Bitwise NOT, -x-1. """ return vartypes.int_to_integer_signed(-vartypes.pass_int_unpack(right)-1)
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 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_asc(ins): """ ASC: ordinal ASCII value of a character. """ s = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if not s: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed(ord(s[0]))
def draw(self, gml): """ DRAW: Execute a Graphics Macro Language string. """ # don't convert to uppercase as VARPTR$ elements are case sensitive gmls = StringIO(gml) plot, goback = True, False while True: c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == '': break elif c == ';': continue elif c == 'B': # do not draw plot = False elif c == 'N': # return to postiton after move goback = True elif c == 'X': # execute substring sub = draw_and_play.ml_parse_string(gmls) self.draw(str(sub)) elif c == 'C': # set foreground colour # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.last_attr = 0 else: self.last_attr = draw_and_play.ml_parse_number(gmls) elif c == 'S': # set scale self.draw_scale = draw_and_play.ml_parse_number(gmls) elif c == 'A': # set angle # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = 90 * draw_and_play.ml_parse_number(gmls) elif c == 'T': # 'turn angle' - set (don't turn) the angle to any value if gmls.read(1).upper() != 'A': raise error.RunError(error.IFC) # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = draw_and_play.ml_parse_number(gmls) # one-variable movement commands: elif c in ('U', 'D', 'L', 'R', 'E', 'F', 'G', 'H'): step = draw_and_play.ml_parse_number(gmls, default=vartypes.int_to_integer_signed(1)) x0, y0 = self.last_point x1, y1 = 0, 0 if c in ('U', 'E', 'H'): y1 -= step elif c in ('D', 'F', 'G'): y1 += step if c in ('L', 'G', 'H'): x1 -= step elif c in ('R', 'E', 'F'): x1 += step self.draw_step(x0, y0, x1, y1, plot, goback) plot = True goback = False # two-variable movement command elif c == 'M': relative = util.skip(gmls, draw_and_play.ml_whitepace) in ('+','-') x = draw_and_play.ml_parse_number(gmls) if util.skip(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) else: gmls.read(1) y = draw_and_play.ml_parse_number(gmls) x0, y0 = self.last_point if relative: self.draw_step(x0, y0, x, y, plot, goback) else: if plot: self.draw_line(x0, y0, x, y, self.last_attr) self.last_point = x, y if goback: self.last_point = x0, y0 plot = True goback = False elif c =='P': # paint - flood fill colour = draw_and_play.ml_parse_number(gmls) if util.skip_read(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) bound = draw_and_play.ml_parse_number(gmls) x, y = self.get_window_logical(*self.last_point) self.paint((x, y, False), None, colour, bound, None)
def value_len(ins): """ LEN: length of string. """ return vartypes.int_to_integer_signed( vartypes.string_length(vartypes.pass_string(parse_bracket(ins))))
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_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))