示例#1
0
def main():
    gtasa = gta3sc.read_config("gtasa/commands.xml")
    gtavc = gta3sc.read_config("gtavc/commands.xml")
    gta3 = gta3sc.read_config("gta3/commands.xml")

    gtasa_commands = {c.id: c for c in gtasa.commands}
    gtavc_commands = {c.id: c for c in gtavc.commands}
    gta3_commands = {c.id: c for c in gta3.commands}

    discover_properties_from_description(gtasa_commands)

    gtasa.save_config("gtasa/commands.xml")
示例#2
0
def main(xmlfile, clear_useless_data):
    config = gta3sc.read_config(xmlfile)
    commands = config.commands

    # Remove description from where Entity and Enum information is enough.
    for cmd in commands:
        for arg in cmd.args:
            amb_entity = AMBIGOUS_DESCRIPTION_ENTITY.get(arg.desc)
            amb_enum   = AMBIGOUS_DESCRIPTION_ENUM.get(arg.desc)
            if amb_entity and arg.entity and arg.entity in amb_entity:
                arg.desc = ""
            if amb_enum and len(arg.enums) > 0 and arg.enums[0] in amb_enum:
                arg.desc = ""

    if clear_useless_data:
        new_commands = []
        for cmd in commands:
            if cmd.supported == False:
                continue
            for a in cmd.args:
                a.desc   = ""
                a.entity = None
                a.enums  = []
                a.allow_const = True
                a.allow_gvar = True
                a.allow_lvar = True
            new_commands.append(cmd)
    else:
        # Simply rewriting the XML will simplify it.
        new_commands = commands

    config.commands = new_commands
    config.save_config(xmlfile, pretty_print=(not clear_useless_data))
示例#3
0
def main(xmlfile):
    config = gta3sc.read_config(xmlfile)

    for cmd in config.commands:
        cmd.hash = one_at_a_time(cmd.name)

    config.save_config(xmlfile)
def main(ir2file, xmlfile):
    config = gta3sc.read_config(xmlfile)
    ir2 = gta3sc.read_ir2(ir2file)

    commands = {cmd.name: cmd for cmd in config.commands}

    for off, data in ir2:
        if data.is_command():
            if not data.name in commands:
                print("Missing command %s" % data.name)
            else:
                cmd = commands[data.name]
                if not cmd.supported:
                    cmd.supported = True
                    print("Command %s is actually supported" % data.name)

    config.save_config(xmlfile)
示例#5
0
def main(xmlname, ininame):
    commands = gta3sc.read_config(xmlname).commands
    inidata = read_scmini(ininame)

    commands_dict = {c.id: c for c in commands}
    inidata_dict = {d[0]: d for d in inidata}

    count_bad = 0

    for entry in inidata:
        xcmd = commands_dict.get(entry[0])
        if xcmd is None:
            if not entry[0] in [0x416]:  # Ignore NOPy LOAD_AND_LAUNCH_MISSION
                print("Missing opcode %.4X on XML." % (entry[0]))
                count_bad += 1
            continue

        if len(xcmd.args) != entry[1]:
            if not xcmd.name in ["SAVE_STRING_TO_DEBUG_FILE"]:
                if entry[1] != -1 or not xcmd.has_optional():
                    print(
                        "Mismatch on the number of arguments (%.4X:%s): INI %d != XML %d"
                        % (entry[0], xcmd.name, entry[1], len(xcmd.args)))
                    count_bad += 1
                continue

    if False:  # III/VC SCM.INI are too old for those checks
        for xcmd in commands:
            if xcmd.supported:
                if inidata_dict.get(xcmd.id) == None:
                    print(
                        "Found a possibly unsupported opcode (%.4X:%s) as it's not present on INI."
                        % (xcmd.id, xcmd.name))
                    count_bad += 1

    if count_bad == 0:
        print("Everything correct.")
    else:
        sys.exit(1)
示例#6
0
def main(xmlfile, clear_useless_data):
    config = gta3sc.read_config(xmlfile)
    commands = config.commands

    myset = set()
    for cmd in commands:
        for arg in cmd.args:
            if arg.desc:
                if arg.desc[0] in ['X', 'Y', 'Z'] or arg.desc in [
                        "Radius", "Angle", "Rotation"
                ]:
                    arg.desc = arg.desc
                elif arg.desc.startswith("Script ID"):
                    arg.desc = "Streamed Script"
                elif arg.desc.startswith("Time"):
                    arg.desc = "Time"
                elif arg.desc.startswith("Boolean"):
                    arg.desc = "Bool"
                elif arg.desc.startswith("Width"):
                    arg.desc = "Width"
                elif arg.desc.startswith("Height"):
                    arg.desc = "Height"
                elif arg.desc == "Red (0-255)":
                    arg.desc = "Red"
                elif arg.desc == "Green (0-255)":
                    arg.desc = "Green"
                elif arg.desc == "Blue (0-255)":
                    arg.desc = "Blue"
                elif arg.desc == "Alpha (0-255)":
                    arg.desc = "Alpha"
                elif arg.desc == "2D Pixel X":
                    arg.desc = "2D Pixel X"
                elif arg.desc == "2D Pixel Y":
                    arg.desc = "2D Pixel Y"
                else:
                    arg.desc = ""

    config.save_config(xmlfile)
示例#7
0
def main(ir2file, configpath, output_dir):

    cmdline = dict(gta3sc.read_commandline(configpath))
    config = gta3sc.read_config(configpath)
    ir2 = gta3sc.read_ir2(ir2file)

    scopes_before_label = bool(cmdline["-fscope-then-label"])
    timer_index = int(cmdline["-ftimer-index"])
    farrays = bool(cmdline["-farrays"])
    global TIMER_INDICES  # HACK!!!!!!!!!!!
    global MISSION_LVAR_BEGIN  #
    TIMER_INDICES = (timer_index + 0, timer_index + 1)
    MISSION_LVAR_BEGIN = max(0, int(cmdline["-fmission-var-begin"]))

    commands = {cmd.name: cmd for cmd in config.commands}
    alternators = defaultdict(
        set, {alt.name: set(alt.alters)
              for alt in config.alternators})
    enums = {
        enum.name: {v: k
                    for k, v in enum.constants.iteritems()}
        for enum in config.enums
    }

    scopes = ir2.discover_scopes()
    filename_by_offset = dict()
    subscripts = dict()
    gosubfiles = dict()
    current_scope = None
    first_scope = scopes[0] if len(scopes) > 0 else None
    current_scope_name = None

    for i in range(len(ir2.mission_blocks)):
        script_offset = ir2.offset_from_mission(i)
        script_name = Scope.from_offset(script_offset,
                                        scopes).find_script_name(ir2)
        filename_by_offset[
            script_offset] = "missions/%s.sc" % script_name.lower()

    for i in range(len(ir2.streamed_blocks)):
        script_offset = ir2.offset_from_streamed(i)
        stream_name = ir2.get_stream_name(i)
        filename_by_offset[
            script_offset] = "streams/%s.sc" % stream_name.lower()

    for off, data in ir2:
        if data.is_command() and data.name == "LAUNCH_MISSION":
            assert data.args[0].is_label()
            script_offset = ir2.offset_from_label(data.args[0].value)
            script_name = Scope.from_offset(script_offset,
                                            scopes).find_script_name(ir2)
            filename = "%s.sc" % script_name.lower(
            ) if script_name else "subscript%d.sc" % len(subscripts)
            filename_by_offset[script_offset] = filename
            subscripts[script_offset] = filename
        elif data.is_command() and data.name == "GOSUB_FILE":
            assert data.args[1].is_label()
            filename = "gosub%d.sc" % len(gosubs)
            script_offset = ir2.offset_from_label(data.args[1].value)
            filename_by_offset[script_offset] = filename
            gosubfiles[script_offset] = filename

    if farrays:
        more_info = [v for (s, v) in SA_VAR_ARRAYS if s == None]
    else:
        more_info = None

    global_vars = ir2.discover_global_vars(config=config, more_info=more_info)
    local_vars = None

    print("//--------------------------")

    try:
        os.makedirs(os.path.join(output_dir, "main"))
        os.makedirs(os.path.join(output_dir, "main", "missions"))
        os.makedirs(os.path.join(output_dir, "main", "streams"))
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    stream = open(os.path.join(output_dir, "main.sc"), 'w')

    got_mission_terminate = [None]  # hack
    is_mission = False
    print_script_terminate_for = None

    print_vars(stream, global_vars, False, False)

    for off, data in ir2:

        if print_script_terminate_for != None:
            if print_script_terminate_for.type != BYTECODE_OFFSET_STREAMED or print_script_terminate_for.block != off.block:
                if print_script_terminate_for.type == BYTECODE_OFFSET_STREAMED:
                    stream.write("}\n")
                stream.write("%s\n" %
                             ("MISSION_END", "MISSION_END",
                              "SCRIPT_END")[print_script_terminate_for.type])
                got_mission_terminate[0] = True
            else:
                stream.write("    TERMINATE_THIS_SCRIPT\n")
            print_script_terminate_for = None

        def on_scope_begin(old_scope, new_scope):
            print("Converting %s" % current_scope_name)
            if new_scope.start in subscripts or (
                    old_scope.start.type != new_scope.start.type
                    or old_scope.start.block != new_scope.start.block):
                if new_scope.start.type != BYTECODE_OFFSET_MAIN or new_scope.start in subscripts:
                    stream.write("%s\n" %
                                 ("MISSION_START", "MISSION_START",
                                  "SCRIPT_START")[new_scope.start.type])
                    got_mission_terminate[0] = False

        def on_scope_end(old_scope, new_scope):
            if old_scope.start in subscripts or (
                    old_scope.start.type != new_scope.start.type
                    or old_scope.start.block != new_scope.start.block):
                if old_scope.start.type != BYTECODE_OFFSET_MAIN or old_scope.start in subscripts:
                    #stream.write("%s\n" % ("MISSION_END", "MISSION_END", "SCRIPT_END")[old_scope.start.type])
                    got_mission_terminate[0] = None

        def write_data(tab=0):
            tabing = ' ' * (tab * 4)
            if data.is_label(): stream.write("\n")
            line = converted_data(ir2,
                                  data,
                                  commands,
                                  alternators,
                                  enums,
                                  global_vars,
                                  local_vars,
                                  filename_by_offset=filename_by_offset)
            stream.write("%s%s\n" % (tabing, line))

        if current_scope == None:
            if first_scope != None and off >= first_scope.start:
                current_scope = Scope.from_offset(off, scopes)
                assert current_scope != None
        elif not current_scope.owns_offset(off):
            previous_scope = current_scope
            if current_scope != first_scope and previous_scope.start.type != BYTECODE_OFFSET_STREAMED:
                stream.write("}\n")
            current_scope = Scope.from_offset(off, scopes)
            assert current_scope != None

            current_scope_name = current_scope.find_script_name(ir2)
            if current_scope_name is None:
                current_scope_name = "??"

            on_scope_end(previous_scope, current_scope)

            if off.type != BYTECODE_OFFSET_MAIN:
                stream.close()
                stream = open(
                    os.path.join(output_dir, "main", filename_by_offset[off]),
                    'w')
            elif off in subscripts or off in gosubfiles:
                filename = subscripts.get(off) or gosubfiles.get(off)
                stream.close()
                stream = open(os.path.join(output_dir, "main", filename), 'w')

            on_scope_begin(previous_scope, current_scope)

            if farrays and current_scope_name != None:
                more_info = [
                    v for (s, v) in SA_VAR_ARRAYS if s == current_scope_name
                ]
            else:
                more_info = None

            local_vars = ir2.discover_local_vars(current_scope,
                                                 config=config,
                                                 more_info=more_info)

            is_mission = (current_scope.start.type == BYTECODE_OFFSET_MISSION)
            is_stream = (current_scope.start.type == BYTECODE_OFFSET_STREAMED)

            if data.is_label():
                if scopes_before_label:
                    stream.write("\n{")
                    write_data(tab=1)
                    print_vars(stream, local_vars, True, is_mission, tab=1)
                    continue
                else:
                    write_data(tab=0)
                    stream.write("{\n")
                    print_vars(stream, local_vars, True, is_mission, tab=1)
                    continue
            else:
                stream.write("{\n")
                print_vars(stream, local_vars, True, is_mission, tab=1)

        if got_mission_terminate[0] == False and\
           data.is_command() and data.name == "TERMINATE_THIS_SCRIPT":
            print_script_terminate_for = off
        else:
            tab = int(current_scope != None and current_scope != first_scope)
            if got_mission_terminate[0] == False and not is_stream:
                tab += 1
            write_data(tab=tab)

    if current_scope != None and current_scope != first_scope:
        stream.write("}\n")

    if print_script_terminate_for != None:
        stream.write("%s\n" % ("MISSION_END", "MISSION_END",
                               "SCRIPT_END")[print_script_terminate_for.type])

    if stream != sys.stdout:
        stream.close()
示例#8
0
def main(ir2file, xmlfile):
    config = gta3sc.read_config(xmlfile)
    ir2 = gta3sc.read_ir2(ir2file)

    scopes = ir2.discover_scopes()
    current_scope = None
    first_scope = scopes[0] if len(scopes) > 0 else None

    commands = {cmd.name: cmd for cmd in config.commands}
    cmds_set = set(config.get_alternator("SET"))
    cmds_is_thing_equal_to_thing = set(
        config.get_alternator("IS_THING_EQUAL_TO_THING"))
    cmds_all_alternatives = set(
        chain.from_iterable(map(lambda x: x.alters, config.alternators)))

    varinfo = VariableInfo(ir2, scopes)
    commands_to_tweak = defaultdict(set)

    print("--------------------------")

    for off, data in ir2:

        if current_scope == None:
            if first_scope != None and off >= first_scope.start:
                current_scope = Scope.from_offset(off, scopes)
                assert current_scope != None
        elif not current_scope.owns_offset(off):
            current_scope = Scope.from_offset(off, scopes)
            assert current_scope != None

        if data.is_command() and data.name in ("START_NEW_SCRIPT",
                                               "START_NEW_STREAMED_SCRIPT"):
            if data.name == "START_NEW_SCRIPT":
                assert data.args[0].is_label()
                script_offset = ir2.offset_from_label(data.args[0].value)
                script_scope = Scope.from_offset(script_offset, scopes)
            else:  # START_NEW_STREAMED_SCRIPT
                assert data.args[0].is_number()
                script_offset = ir2.offset_from_streamed(data.args[0].value)
                script_scope = Scope.from_offset(script_offset, scopes)
            assert script_scope != None
            for i, arg in enumerate(data.args[1:]):
                if arg.is_var():
                    entity_type = varinfo.get_entity_type(arg, current_scope)
                    if entity_type:
                        varinfo.register_local_in_scope(
                            script_scope, i, entity_type)
        elif data.is_command() and data.name in cmds_set:
            assert data.args[0].is_var()
            if data.args[1].is_var():
                rhs_entity = varinfo.get_entity_type(data.args[1],
                                                     current_scope)
                if rhs_entity:
                    varinfo.register_var(data.args[0], rhs_entity,
                                         current_scope)
        elif data.is_command() and data.name in cmds_all_alternatives:
            # ignore commands which are part of alternators
            pass
        elif data.is_command():
            cmd = commands.get(data.name)
            for i, arg in enumerate(data.args):
                cmdarg = cmd.get_arg(i)
                if cmdarg.out and cmdarg.entity:
                    varinfo.register_var(arg, cmdarg.entity, current_scope)
                elif arg.is_var():
                    var_entity_type = varinfo.get_entity_type(
                        arg, current_scope)
                    if var_entity_type != None and cmdarg.entity != var_entity_type:
                        commands_to_tweak[cmd.name].add((i, var_entity_type))
                    elif var_entity_type == None and cmdarg.entity != None:
                        # this check does not work as intended since we don't have enough information
                        # about the source code (e.g. arrays always indexed by a literal)
                        #print(str(data), i, cmdarg.entity, varinfo.get_var_base(arg, current_scope),
                        #        current_scope.find_script_name(ir2), off, current_scope)
                        pass

    # Prone to mistakes,so not going to update the XML automatically.
    for cmdname, args in commands_to_tweak.iteritems():
        for info in args:
            print("Command %s argument %d is missing entity %s" %
                  (cmdname, info[0], info[1]))
示例#9
0
def main(ir2file, xmlfile):
    config = gta3sc.read_config(xmlfile)
    ir2 = gta3sc.read_ir2(ir2file)

    commands    = {cmd.name: cmd for cmd in config.commands}
    alternators = defaultdict(set, {alt.name: set(alt.alters) for alt in config.alternators})
    enums       = {enum.name: {v: k for k,v in enum.constants.iteritems()} for enum in config.enums}

    scopes = ir2.discover_scopes()
    current_scope = None
    first_scope = scopes[0] if len(scopes) > 0 else None

    global_vars = ir2.discover_global_vars(config=config)
    local_vars = None

    commands = {cmd.name: cmd for cmd in config.commands}
    cmds_all_alternatives = set(chain.from_iterable(map(lambda x: x.alters, config.alternators)))

    enum_args = defaultdict(set)   # All values used for a enum that exists
    unknown_values = set()          # Values without a matching enum
    commands_enum = set()           # Commands missing enum info

    highest_default_id = max(enums["DEFAULTMODEL"].iterkeys())

    print("--------------------------")

    for off, data in ir2:

        if current_scope == None:
            if first_scope != None and off >= first_scope.start:
                current_scope = Scope.from_offset(off, scopes)
                assert current_scope != None
        elif not current_scope.owns_offset(off):
            current_scope = Scope.from_offset(off, scopes)
            assert current_scope != None
            local_vars = ir2.discover_local_vars(current_scope, config=config)

        if data.is_command() and data.name in CONST_COMMANDS:
            argvar   = data.args[0] if not data.name.startswith("IS_CONSTANT_") else data.args[1]
            argconst = data.args[1] if not data.name.startswith("IS_CONSTANT_") else data.args[0]
            assert argvar.is_var()
            assert argconst.is_number()
            varlist  = local_vars if argvar.is_local() else global_vars
            var = VarInfo.from_offset(argvar.get_offset(), varlist)
            if len(var.enums) > 0:
                for ve in var.enums:
                    enum_args[ve].add(argconst.value)
            else:
                print("Unknown value %d at %s" % (argconst.value, str(data)))
        elif data.is_command() and data.name in cmds_all_alternatives:
            pass
        elif data.is_command():
            cmdinfo = commands[data.name]
            for i, arg in enumerate(data.args):
                arginfo = cmdinfo.get_arg(i)
                if len(arginfo.enums) > 0:
                    assert len(arginfo.enums) == 1
                    enum_name = arginfo.enums[0]
                    if arg.is_number():
                        enum_args[enum_name].add(arg.value)
                        pass
                    else:
                        pass # TODO
                elif not arginfo.out:
                    if arg.is_var():
                        varlist = local_vars if arg.is_local() else global_vars
                        var = VarInfo.from_offset(arg.get_offset(), varlist)
                        if len(var.enums) > 0:
                            for enum_name in var.enums:
                                commands_enum.add((cmdinfo.name, i, enum_name))

    for info in commands_enum:
        print("Command %s has enum %s at argument %d" % (info[0], info[2], info[1]))

    for name, values in enum_args.iteritems():
        
        if name == "MODEL":
            missing = sorted(v for v in values if v > highest_default_id)
        elif name == "DEFAULTMODEL":
            enum = enums[name]
            missing = sorted(v for v in values if v >= 0 and v not in enum)
        else:
            enum = enums.get(name, {})
            missing = sorted(v for v in values if v not in enum)
        
        if len(missing) > 0:
            print("Values missing from enum %s: %s" % (name, missing))