示例#1
0
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)))
示例#2
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_keep(coord)), fp.Single.zero)
        return vartypes.pack_int(value)
    elif mode == 1:
        _, value = screen.drawing.get_window_physical(
            fp.Single.zero, fp.unpack(vartypes.pass_single_keep(coord)))
        return vartypes.pack_int(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)
示例#3
0
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)))
示例#4
0
def value_sgn(ins):
    """ SGN: get sign. """
    inp = vartypes.pass_number_keep(parse_bracket(ins))
    if inp[0] == '%':
        inp_int = vartypes.unpack_int(inp)
        return vartypes.pack_int(0 if inp_int==0 else (1 if inp_int > 0 else -1))
    else:
        return vartypes.pack_int(fp.unpack(inp).sign() )
示例#5
0
def value_sgn(ins):
    """ SGN: get sign. """
    inp = vartypes.pass_number_keep(parse_bracket(ins))
    if inp[0] == '%':
        inp_int = vartypes.unpack_int(inp)
        return vartypes.pack_int(0 if inp_int == 0 else (
            1 if inp_int > 0 else -1))
    else:
        return vartypes.pack_int(fp.unpack(inp).sign())
示例#6
0
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.pack_int(printer.device_file.col)
    else:
        return vartypes.pack_int(1)
示例#7
0
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.pack_int(printer.device_file.col)
    else:
        return vartypes.pack_int(1)
示例#8
0
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 vartypes.pack_int(the_file.lof() )
示例#9
0
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))
示例#10
0
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))
示例#11
0
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 = iolayer.get_file(num)
    return vartypes.pack_int(the_file.loc())
示例#12
0
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 vartypes.pack_int(the_file.lof())
示例#13
0
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)
示例#14
0
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.pack_int(row)
示例#15
0
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.pack_int(col)
示例#16
0
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.pack_int(pen)
示例#17
0
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.pack_int(pen)
示例#18
0
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.pack_int(col)
示例#19
0
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.pack_int(row)
示例#20
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_keep(coord)), fp.Single.zero)
        return vartypes.pack_int(value)
    elif mode == 1:
        _, value = screen.drawing.get_window_physical(fp.Single.zero, fp.unpack(vartypes.pass_single_keep(coord)))
        return vartypes.pack_int(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)
示例#21
0
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)
示例#22
0
def value_varptr(ins):
    """ VARPTR, VARPTR$: get memory address for variable or FCB. """
    dollar = util.skip_white_read_if(ins, ('$',))
    util.require_read(ins, ('(',))
    if (not dollar) and util.skip_white(ins) == '#':
        filenum = parse_file_number_opthash(ins)
        var_ptr = machine.varptr_file(filenum)
    else:
        name, indices = get_var_or_array_name(ins)
        var_ptr = machine.varptr(name, indices)
    util.require_read(ins, (')',))
    if var_ptr < 0:
        raise error.RunError(error.IFC)
    if dollar:
        return vartypes.pack_string(bytearray(chr(var.byte_size[name[-1]])) + vartypes.value_to_uint(var_ptr))
    else:
        return vartypes.pack_int(var_ptr)
示例#23
0
def value_varptr(ins):
    """ VARPTR, VARPTR$: get memory address for variable or FCB. """
    dollar = util.skip_white_read_if(ins, ('$', ))
    util.require_read(ins, ('(', ))
    if (not dollar) and util.skip_white(ins) == '#':
        filenum = parse_file_number_opthash(ins)
        var_ptr = machine.varptr_file(filenum)
    else:
        name, indices = get_var_or_array_name(ins)
        var_ptr = machine.varptr(name, indices)
    util.require_read(ins, (')', ))
    if var_ptr < 0:
        raise error.RunError(error.IFC)
    if dollar:
        return vartypes.pack_string(
            bytearray(chr(var.byte_size[name[-1]])) +
            vartypes.value_to_uint(var_ptr))
    else:
        return vartypes.pack_int(var_ptr)
示例#24
0
def value_screen(ins):
    """ SCREEN: get char or attribute at a location. """
    util.require_read(ins, ('(',))
    row, col, z = parse_int_list(ins, 3, 5)
    if row is None or col is None:
        raise error.RunError(error.IFC)
    if z is None:
        z = 0
    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.pack_int(state.console_state.screen.apage.get_char_attr(row, col, z!=0))
示例#25
0
def value_screen(ins):
    """ SCREEN: get char or attribute at a location. """
    util.require_read(ins, ('(', ))
    row, col, z = parse_int_list(ins, 3, 5)
    if row is None or col is None:
        raise error.RunError(error.IFC)
    if z is None:
        z = 0
    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.pack_int(
            state.console_state.screen.apage.get_char_attr(row, col, z != 0))
示例#26
0
def value_err(ins):
    """ ERR: get error code of last error. """
    return vartypes.pack_int(state.basic_state.errn)
示例#27
0
def value_asc(ins):
    """ ASC: ordinal ASCII value of a character. """
    s = vartypes.pass_string_unpack(parse_bracket(ins))
    if not s:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(s[0])
示例#28
0
def value_err(ins):
    """ ERR: get error code of last error. """
    return vartypes.pack_int(state.basic_state.errn)
示例#29
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(5)
             # 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.pack_int(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(5)
             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(5)
             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)
示例#30
0
def value_not(ins):
    """ NOT: get two's complement NOT, -x-1. """
    return vartypes.pack_int(~vartypes.pass_int_unpack(parse_expr_unit(ins)))
示例#31
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.pack_int(machine.peek(addr))
示例#32
0
def value_inp(ins):
    """ INP: get value from machine port. """
    port = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff)
    return vartypes.pack_int(machine.inp(port))
示例#33
0
def value_len(ins):
    """ LEN: length of string. """
    return vartypes.pack_int(len(vartypes.pass_string_unpack(parse_bracket(ins))) )
示例#34
0
def value_asc(ins):
    """ ASC: ordinal ASCII value of a character. """
    s = vartypes.pass_string_unpack(parse_bracket(ins))
    if not s:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(s[0])
示例#35
0
def value_cvi(ins):
    """ CVI: return the int value of a byte representation. """
    cstr =  vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 2:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(vartypes.sint_to_value(cstr[:2]))
示例#36
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in tk.end_line + ('"',):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d in string.ascii_uppercase:
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d in string.digits:
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return representation.parse_value(outs)
    # number literals
    elif d in tk.number:
        return representation.parse_value(ins)
    # gw-basic allows adding line numbers to numbers
    elif d == tk.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens
    else:
        ins.read(1)
        if d == tk.INPUT:         return value_input(ins)
        elif d == tk.SCREEN:      return value_screen(ins)
        elif d == tk.USR:         return value_usr(ins)
        elif d == tk.FN:          return value_fn(ins)
        elif d == tk.NOT:         return value_not(ins)
        elif d == tk.ERL:         return value_erl(ins)
        elif d == tk.ERR:         return value_err(ins)
        elif d == tk.STRING:      return value_string(ins)
        elif d == tk.INSTR:       return value_instr(ins)
        elif d == tk.VARPTR:      return value_varptr(ins)
        elif d == tk.CSRLIN:      return value_csrlin(ins)
        elif d == tk.POINT:       return value_point(ins)
        elif d == tk.INKEY:       return value_inkey(ins)
        elif d == tk.O_PLUS:      return parse_expr_unit(ins)
        elif d == tk.O_MINUS:     return value_neg(ins)
        # two-byte tokens
        elif d == '\xFD':
            d += ins.read(1)
            if d == tk.CVI:       return value_cvi(ins)
            elif d == tk.CVS:     return value_cvs(ins)
            elif d == tk.CVD:     return value_cvd(ins)
            elif d == tk.MKI:     return value_mki(ins)
            elif d == tk.MKS:     return value_mks(ins)
            elif d == tk.MKD:     return value_mkd(ins)
            elif d == tk.EXTERR:  return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d += ins.read(1)
            if d == tk.DATE:      return value_date(ins)
            elif d == tk.TIME:    return value_time(ins)
            elif d == tk.PLAY:    return value_play(ins)
            elif d == tk.TIMER:   return value_timer(ins)
            elif d == tk.ERDEV:   return value_erdev(ins)
            elif d == tk.IOCTL:   return value_ioctl(ins)
            elif d == tk.ENVIRON: return value_environ(ins)
            elif d == tk.PMAP:    return value_pmap(ins)
        # two-byte tokens
        elif d == '\xFF':
            d += ins.read(1)
            if d == tk.LEFT:    return value_left(ins)
            elif d == tk.RIGHT: return value_right(ins)
            elif d == tk.MID:   return value_mid(ins)
            elif d == tk.SGN:   return value_sgn(ins)
            elif d == tk.INT:   return value_int(ins)
            elif d == tk.ABS:   return value_abs(ins)
            elif d == tk.SQR:   return value_sqr(ins)
            elif d == tk.RND:   return value_rnd(ins)
            elif d == tk.SIN:   return value_sin(ins)
            elif d == tk.LOG:   return value_log(ins)
            elif d == tk.EXP:   return value_exp(ins)
            elif d == tk.COS:   return value_cos(ins)
            elif d == tk.TAN:   return value_tan(ins)
            elif d == tk.ATN:   return value_atn(ins)
            elif d == tk.FRE:   return value_fre(ins)
            elif d == tk.INP:   return value_inp(ins)
            elif d == tk.POS:   return value_pos(ins)
            elif d == tk.LEN:   return value_len(ins)
            elif d == tk.STR:   return value_str(ins)
            elif d == tk.VAL:   return value_val(ins)
            elif d == tk.ASC:   return value_asc(ins)
            elif d == tk.CHR:   return value_chr(ins)
            elif d == tk.PEEK:  return value_peek(ins)
            elif d == tk.SPACE: return value_space(ins)
            elif d == tk.OCT:   return value_oct(ins)
            elif d == tk.HEX:   return value_hex(ins)
            elif d == tk.LPOS:  return value_lpos(ins)
            elif d == tk.CINT:  return value_cint(ins)
            elif d == tk.CSNG:  return value_csng(ins)
            elif d == tk.CDBL:  return value_cdbl(ins)
            elif d == tk.FIX:   return value_fix(ins)
            elif d == tk.PEN:   return value_pen(ins)
            elif d == tk.STICK: return value_stick(ins)
            elif d == tk.STRIG: return value_strig(ins)
            elif d == tk.EOF:   return value_eof(ins)
            elif d == tk.LOC:   return value_loc(ins)
            elif d == tk.LOF:   return value_lof(ins)
        else:
            return None
示例#37
0
    def set_gwbasic_vars(self, dictionary):
        """ Retrieve variables from Python script """
        for new_var_name, new_var_value in dictionary.iteritems():
            var_name = self.name_recover(new_var_name)

            if type(new_var_value) == str:
                if var_name[-1] != '$':
                    raise Exception("Type mismatch. Variable name is %s, but a string value was received (%s)" %
                                    (new_var_name , new_var_value))

                ins = cStringIO.StringIO(var_name)
                var_name = util.get_var_name(ins)
                var.set_var(var_name, vartypes.pack_string(bytearray(new_var_value + "\0")))
            elif type(new_var_value) == int:
                if var_name[-1] != '%':
                    raise Exception("Type mismatch. Variable name is %s, but a integer value was received (%d)" %
                                    (new_var_name , new_var_value))

                ins = cStringIO.StringIO(var_name)
                var_name = util.get_var_name(ins)
                var.set_var(var_name, vartypes.pack_int(new_var_value))
            elif type(new_var_value) == float:
                if var_name[-1] == '!':
                    ins = cStringIO.StringIO(var_name)
                    var_name = util.get_var_name(ins)
                    bytearray_val = fp.Single.from_value(new_var_value).to_bytes()
                    var.set_var(var_name, ('!', bytearray_val))
                elif var_name[-1] == '#':
                    ins = cStringIO.StringIO(var_name)
                    var_name = util.get_var_name(ins)
                    bytearray_val = fp.Double.from_value(new_var_value).to_bytes()
                    var.set_var(var_name, ('#', bytearray_val))
                else:
                    raise Exception("Type mismatch. Variable name is %s, but a floating-point value was received (%f)" %
                                    (new_var_name , new_var_value))
            elif type(new_var_value) == list:
                matrix = np.array(new_var_value)

                dimensions = matrix.shape

                if var_name in state.basic_state.arrays.keys():
                    var.erase_array(var_name)
                dimensions = [x for x in dimensions]
                var.dim_array(var_name, dimensions)

                indexes = [list(xrange(d)) for d in dimensions]
                indexes = list(itertools.product(*indexes))

                for index in indexes:
                    item_value = new_var_value
                    for coord in index:
                        item_value = item_value[coord]

                    if var_name[-1] == '$':
                        matrix_element = vartypes.pack_string(bytearray(item_value + "\0"))
                    elif var_name[-1] == '%':
                        matrix_element = vartypes.pack_int(item_value)
                    elif var_name[-1] == '!':
                        matrix_element = ( '!', fp.Single.from_value(item_value).to_bytes())
                    elif var_name[-1] == '#':
                        matrix_element = ('#', fp.Double.from_value(item_value).to_bytes())
                    else:
                        raise Exception("Array type unknown for variable %s" % new_var_name)

                    try:
                        var.set_var_or_array(var_name, index, matrix_element)
                    except:
                        import traceback
                        traceback.print_exc()

            else:
                logging.debug('Received variable was not processed: %s.', new_var_name)
示例#38
0
def value_len(ins):
    """ LEN: length of string. """
    return vartypes.pack_int(
        len(vartypes.pass_string_unpack(parse_bracket(ins))))
示例#39
0
def value_inp(ins):
    """ INP: get value from machine port. """
    port = vartypes.pass_int_unpack(parse_bracket(ins), maxint=0xffff)
    return vartypes.pack_int(machine.inp(port))
示例#40
0
def value_stick(ins):
    """ STICK: poll the joystick. """
    fn = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 3, fn)
    return vartypes.pack_int(state.console_state.stick.poll(fn))
示例#41
0
def value_not(ins):
    """ NOT: get two's complement NOT, -x-1. """
    return vartypes.pack_int(~vartypes.pass_int_unpack(parse_expr_unit(ins)))
示例#42
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.pack_int(machine.peek(addr))
示例#43
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in tk.end_line + ('"', ):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d in string.ascii_uppercase:
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d in string.digits:
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return representation.parse_value(outs)
    # number literals
    elif d in tk.number:
        return representation.parse_value(ins)
    # gw-basic allows adding line numbers to numbers
    elif d == tk.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens
    else:
        ins.read(1)
        if d == tk.INPUT: return value_input(ins)
        elif d == tk.SCREEN: return value_screen(ins)
        elif d == tk.USR: return value_usr(ins)
        elif d == tk.FN: return value_fn(ins)
        elif d == tk.NOT: return value_not(ins)
        elif d == tk.ERL: return value_erl(ins)
        elif d == tk.ERR: return value_err(ins)
        elif d == tk.STRING: return value_string(ins)
        elif d == tk.INSTR: return value_instr(ins)
        elif d == tk.VARPTR: return value_varptr(ins)
        elif d == tk.CSRLIN: return value_csrlin(ins)
        elif d == tk.POINT: return value_point(ins)
        elif d == tk.INKEY: return value_inkey(ins)
        elif d == tk.O_PLUS: return parse_expr_unit(ins)
        elif d == tk.O_MINUS:
            return value_neg(ins)
            # two-byte tokens
        elif d == '\xFD':
            d += ins.read(1)
            if d == tk.CVI: return value_cvi(ins)
            elif d == tk.CVS: return value_cvs(ins)
            elif d == tk.CVD: return value_cvd(ins)
            elif d == tk.MKI: return value_mki(ins)
            elif d == tk.MKS: return value_mks(ins)
            elif d == tk.MKD: return value_mkd(ins)
            elif d == tk.EXTERR: return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d += ins.read(1)
            if d == tk.DATE: return value_date(ins)
            elif d == tk.TIME: return value_time(ins)
            elif d == tk.PLAY: return value_play(ins)
            elif d == tk.TIMER: return value_timer(ins)
            elif d == tk.ERDEV: return value_erdev(ins)
            elif d == tk.IOCTL: return value_ioctl(ins)
            elif d == tk.ENVIRON: return value_environ(ins)
            elif d == tk.PMAP: return value_pmap(ins)
        # two-byte tokens
        elif d == '\xFF':
            d += ins.read(1)
            if d == tk.LEFT: return value_left(ins)
            elif d == tk.RIGHT: return value_right(ins)
            elif d == tk.MID: return value_mid(ins)
            elif d == tk.SGN: return value_sgn(ins)
            elif d == tk.INT: return value_int(ins)
            elif d == tk.ABS: return value_abs(ins)
            elif d == tk.SQR: return value_sqr(ins)
            elif d == tk.RND: return value_rnd(ins)
            elif d == tk.SIN: return value_sin(ins)
            elif d == tk.LOG: return value_log(ins)
            elif d == tk.EXP: return value_exp(ins)
            elif d == tk.COS: return value_cos(ins)
            elif d == tk.TAN: return value_tan(ins)
            elif d == tk.ATN: return value_atn(ins)
            elif d == tk.FRE: return value_fre(ins)
            elif d == tk.INP: return value_inp(ins)
            elif d == tk.POS: return value_pos(ins)
            elif d == tk.LEN: return value_len(ins)
            elif d == tk.STR: return value_str(ins)
            elif d == tk.VAL: return value_val(ins)
            elif d == tk.ASC: return value_asc(ins)
            elif d == tk.CHR: return value_chr(ins)
            elif d == tk.PEEK: return value_peek(ins)
            elif d == tk.SPACE: return value_space(ins)
            elif d == tk.OCT: return value_oct(ins)
            elif d == tk.HEX: return value_hex(ins)
            elif d == tk.LPOS: return value_lpos(ins)
            elif d == tk.CINT: return value_cint(ins)
            elif d == tk.CSNG: return value_csng(ins)
            elif d == tk.CDBL: return value_cdbl(ins)
            elif d == tk.FIX: return value_fix(ins)
            elif d == tk.PEN: return value_pen(ins)
            elif d == tk.STICK: return value_stick(ins)
            elif d == tk.STRIG: return value_strig(ins)
            elif d == tk.EOF: return value_eof(ins)
            elif d == tk.LOC: return value_loc(ins)
            elif d == tk.LOF: return value_lof(ins)
        else:
            return None
示例#44
0
def value_cvi(ins):
    """ CVI: return the int value of a byte representation. """
    cstr = vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 2:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(vartypes.sint_to_value(cstr[:2]))
示例#45
0
def value_stick(ins):
    """ STICK: poll the joystick. """
    fn = vartypes.pass_int_unpack(parse_bracket(ins))
    util.range_check(0, 3, fn)
    return vartypes.pack_int(state.console_state.stick.poll(fn))
示例#46
0
def parse_expr_unit(ins):
    """ Compute the value of the expression unit at the current code pointer. """
    d = util.skip_white(ins)
    # string literal
    if d == '"':
        ins.read(1)
        output = bytearray()
        # while tokenised nmbers inside a string literal will be printed as tokenised numbers, they don't actually execute as such:
        # a \00 character, even if inside a tokenised number, will break a string literal (and make the parser expect a 
        # line number afterwards, etc. We follow this.
        d = ins.read(1)
        while d not in util.end_line + ('"',):
            output += d
            d = ins.read(1)
        if d == '\0':
            ins.seek(-1, 1)
        return vartypes.pack_string(output)
    # variable name
    elif d >= 'A' and d <= 'Z':
        name, indices = get_var_or_array_name(ins)
        return var.get_var_or_array(name, indices)
    # number literals as ASCII are accepted in tokenised streams. only if they start with a figure (not & or .)
    # this happens e.g. after non-keywords like AS. They are not acceptable as line numbers.
    elif d >= '0' and d <= '9':
        outs = StringIO()
        representation.tokenise_number(ins, outs)
        outs.seek(0)
        return util.parse_value(outs)
    # number literals
    elif d in token.number:
        return util.parse_value(ins)   
    # gw-basic allows adding line numbers to numbers     
    elif d == token.T_UINT:
        return vartypes.pack_int(util.parse_jumpnum(ins))
    # brackets
    elif d == '(':
        return parse_bracket(ins)
    # single-byte tokens 
    else:
        ins.read(1)       
        if d == '\x85':         return value_input(ins)
        elif d == '\xC8':       return value_screen(ins)
        elif d == '\xD0':       return value_usr(ins)
        elif d == '\xD1':       return value_fn(ins)
        elif d == '\xD3':       return value_not(ins)
        elif d == '\xD4':       return value_erl(ins)
        elif d == '\xD5':       return value_err(ins)
        elif d == '\xD6':       return value_string(ins)
        elif d == '\xD8':       return value_instr(ins)    
        elif d == '\xDA':       return value_varptr(ins)
        elif d == '\xDB':       return value_csrlin(ins)
        elif d == '\xDC':       return value_point(ins)
        elif d == '\xDE':       return value_inkey(ins)
        elif d == '\xE9':       return parse_expr_unit(ins)
        elif d == '\xEA':       return value_neg(ins)     
        # two-byte tokens
        elif d == '\xFD':
            d = ins.read(1)
            if d == '\x81':      return value_cvi(ins)
            elif d =='\x82':     return value_cvs(ins)
            elif d =='\x83':     return value_cvd(ins)
            elif d =='\x84':     return value_mki(ins)
            elif d =='\x85':     return value_mks(ins)
            elif d =='\x86':     return value_mkd(ins)
            elif d == '\x8b':    return value_exterr(ins)
        # two-byte tokens
        elif d == '\xFE':
            d = ins.read(1)        
            if d == '\x8D':      return value_date(ins)
            elif d == '\x8E':    return value_time(ins)
            elif d == '\x93':    return value_play(ins)
            elif d == '\x94':    return value_timer(ins)
            elif d == '\x95':    return value_erdev(ins)
            elif d == '\x96':    return value_ioctl(ins)
            elif d == '\x9B':    return value_environ(ins)
            elif d == '\x9E':    return value_pmap(ins)
        # two-byte tokens                    
        elif d == '\xFF':
            d = ins.read(1)
            if d == '\x81':     return value_left(ins)
            elif d == '\x82':   return value_right(ins)
            elif d == '\x83':   return value_mid(ins)
            elif d == '\x84':   return value_sgn(ins)
            elif d == '\x85':   return value_int(ins)
            elif d == '\x86':   return value_abs(ins)
            elif d == '\x87':   return value_sqrt(ins)
            elif d == '\x88':   return value_rnd(ins)
            elif d == '\x89':   return value_sin(ins)
            elif d == '\x8a':   return value_log(ins)
            elif d == '\x8b':   return value_exp(ins)
            elif d == '\x8c':   return value_cos(ins)
            elif d == '\x8D':   return value_tan(ins)
            elif d == '\x8E':   return value_atn(ins)
            elif d == '\x8F':   return value_fre(ins)
            elif d == '\x90':   return value_inp(ins)
            elif d == '\x91':   return value_pos(ins)
            elif d == '\x92':   return value_len(ins)
            elif d == '\x93':   return value_str(ins)
            elif d == '\x94':   return value_val(ins)
            elif d == '\x95':   return value_asc(ins)
            elif d == '\x96':   return value_chr(ins)
            elif d == '\x97':   return value_peek(ins)
            elif d == '\x98':   return value_space(ins)
            elif d == '\x99':   return value_oct(ins)
            elif d == '\x9A':   return value_hex(ins)
            elif d == '\x9B':   return value_lpos(ins)
            elif d == '\x9C':   return value_cint(ins)
            elif d == '\x9D':   return value_csng(ins)
            elif d == '\x9E':   return value_cdbl(ins)
            elif d == '\x9F':   return value_fix(ins)    
            elif d == '\xA0':   return value_pen(ins)
            elif d == '\xA1':   return value_stick(ins)
            elif d == '\xA2':   return value_strig(ins)
            elif d == '\xA3':   return value_eof(ins)
            elif d == '\xA4':   return value_loc(ins)
            elif d == '\xA5':   return value_lof(ins)
        else:
            return None
示例#47
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.pack_int(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)