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")
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))
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)
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)
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)
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()
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]))
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))