diff options
Diffstat (limited to 'tools/armips_gen.py')
| -rw-r--r-- | tools/armips_gen.py | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/tools/armips_gen.py b/tools/armips_gen.py new file mode 100644 index 000000000..cbdd5bec6 --- /dev/null +++ b/tools/armips_gen.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# SPDX-FileCopyrightText: © 2026 ZeldaRET +# SPDX-License-Identifier: CC0-1.0 +# +# Create a single-file armips assembler from an upstream commit, for MIPS only. +# Changing the target commit may require updating +# - armips.diff +# - the included file list +# - the line filters in filter_lines +# + +import contextlib, io, os + + +ARMIPS_URL = "https://github.com/kingcom/armips" +ARMIPS_COMMIT = "9029577f6448c78dadcffbc876d2b8cbcfc6da9b" +ARMIPS_MAJOR_VER = "v0.11" +ARMIPS_PATCH = "armips.diff" +ARMIPS_OUTPUT = "armips.cpp" + + +file_list = ( + "Util/FileSystem.h", + "ext/tinyformat/tinyformat.h", + "Core/Types.h", + "Core/Types.cpp", + "Commands/CAssemblerCommand.h", + "Core/Expression.h", + "Parser/Tokenizer.h", + "Core/ExpressionFunctionHandler.h", + "Core/ExpressionFunctions.h", + "Core/SymbolData.h", + "Util/Util.h", + "Util/FileClasses.h", + "Util/ByteArray.h", + "Core/FileManager.h", + "Core/ELF/ElfTypes.h", + "Core/ELF/ElfFile.h", + "Core/ELF/ElfRelocator.h", + "Archs/Architecture.h", + "Archs/MIPS/Mips.h", + "Archs/MIPS/MipsOpcodes.h", + "Archs/MIPS/CMipsInstruction.h", + "Util/EncodingTable.h", + "Core/Misc.h", + "Core/Assembler.h", + "Core/SymbolTable.h", + "Core/Common.h", + "Core/Allocations.h", + "Core/Allocations.cpp", + "Parser/DirectivesParser.h", + "Archs/MIPS/MipsMacros.h", + "Archs/MIPS/MipsParser.h", + "Archs/MIPS/CMipsInstruction.cpp", + "Archs/MIPS/MipsExpressionFunctions.h", + "Archs/MIPS/MipsElfRelocator.h", + "Archs/MIPS/Mips.cpp", + "Archs/MIPS/MipsElfFile.h", + "Util/CRC.h", + "Archs/MIPS/MipsElfFile.cpp", + "Commands/CommandSequence.h", + "Parser/Parser.h", + "Archs/MIPS/MipsElfRelocator.cpp", + "Archs/MIPS/MipsExpressionFunctions.cpp", + "Archs/MIPS/MipsMacros.cpp", + "Archs/MIPS/MipsOpcodes.cpp", + "Parser/ExpressionParser.h", + "Core/ExpressionFunctionHandler.cpp", + "Archs/MIPS/PsxRelocator.h", + "Commands/CDirectiveFile.h", + "Archs/MIPS/MipsParser.cpp", + "Archs/MIPS/PsxRelocator.cpp", + "Archs/Architecture.cpp", + "Commands/CAssemblerCommand.cpp", + "Commands/CAssemblerLabel.h", + "Commands/CAssemblerLabel.cpp", + "Commands/CDirectiveArea.h", + "Commands/CDirectiveArea.cpp", + "Commands/CDirectiveConditional.h", + "Commands/CDirectiveConditional.cpp", + "Commands/CDirectiveData.h", + "Commands/CDirectiveData.cpp", + "Commands/CDirectiveFile.cpp", + "Commands/CDirectiveMessage.h", + "Commands/CDirectiveMessage.cpp", + "Commands/CommandSequence.cpp", + "Parser/DirectivesParser.cpp", + "Parser/ExpressionParser.cpp", + "Parser/Parser.cpp", + "Parser/Tokenizer.cpp", + "Util/ByteArray.cpp", + "Util/CRC.cpp", + "Util/EncodingTable.cpp", + "Util/FileClasses.cpp", + "Util/Util.cpp", + "Main/CommandLineInterface.h", + "Main/CommandLineInterface.cpp", + "Core/ELF/ElfFile.cpp", + "Core/ELF/ElfRelocator.cpp", + "Core/Assembler.cpp", + "Core/Common.cpp", + "Core/Expression.cpp", + "Core/ExpressionFunctions.cpp", + "Core/FileManager.cpp", + "Core/Misc.cpp", + "Core/SymbolData.cpp", + "Core/SymbolTable.cpp", + "Main/main.cpp", +) + + +file_header = \ +f"""// == AUTOMATICALLY GENERATED by armips_gen.py, do not edit directly == +// armips assembler {ARMIPS_MAJOR_VER} (commit {ARMIPS_COMMIT}) +// {ARMIPS_URL} +// To simplify compilation, all files have been concatenated into one. +// MIPS only, other architectures not included.\n\n""" + + +@contextlib.contextmanager +def working_dir(x: str): + old = os.getcwd() + os.chdir(x) + try: + yield + finally: + os.chdir(old) + + +def filter_lines(line: str): + blacklist = ( + "#pragma once", + "#include \"", + "#include <tinyformat.h>" + ) + return not any(s in line for s in blacklist) + + +def cat_file(fout: io.TextIOBase, fin_name: str): + with open(fin_name) as fin: + lines = fin.readlines() + lines = map(str.rstrip, filter(filter_lines, lines)) + fout.write("\n".join(lines) + "\n") + + +def combine_armips(fout_name: str, armips_path: str): + with open(fout_name, "w") as fout: + fout.write(file_header) + fout.write("/*\n") + cat_file(fout, os.path.join(armips_path, "LICENSE.txt")) + fout.write("*/\n\n") + fout.write("#define ARMIPS_USE_STD_FILESYSTEM\n") + for f in file_list: + fout.write(f"\n#pragma region \"File: {f}\"\n") + cat_file(fout, os.path.join(armips_path, f)) + + +def main(): + with working_dir(os.path.dirname(os.path.realpath(__file__))): + temp_dir = "armips_clone" + # Acquire the base armips commit + os.system(f"rm -rf {temp_dir}") + os.system(f"git init {temp_dir} 2>/dev/null") + with working_dir(temp_dir): + os.system(f"git remote add origin {ARMIPS_URL}.git") + os.system(f"git fetch origin --depth 1 {ARMIPS_COMMIT}") + os.system(f"git checkout FETCH_HEAD 2>/dev/null") + # Apply patch + os.system(f"git apply ../{ARMIPS_PATCH}") + # Concat all included files + print(f"Creating {ARMIPS_OUTPUT}") + combine_armips(ARMIPS_OUTPUT, os.path.expanduser(temp_dir)) + os.system(f"rm -rf {temp_dir}") + + +if __name__ == "__main__": + main() |
