diff --git a/.editorconfig b/.editorconfig index 604cc306..c6a6539f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*.{py,txt,editorconfig}] indent_style = space -indent_size = 2 +indent_size = 4 insert_final_newline = true trim_trailing_whitespace = true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8434d906..58cce4dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,10 @@ jobs: # Use minimum supported version cmake-version: '3.13.x' + - name: Patch MSVC 4.2 + run: | + python tools/patch_c2.py msvc420/bin/C2.EXE + - name: Build shell: cmd run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 18a7b052..2cb1798c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,17 +276,12 @@ if (ISLE_BUILD_APP) endif() if (MSVC) - # Remove "identifier was truncated to '255' characters" warnings from output. - # Impossible to avoid this if using STL map or set. - # Unfortunately, MSVC4 has a bug that makes it impossible - # to get rid of this warning by using the standard #pragma directive. - configure_file("compile.cmd" "compile.cmd") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "compile.cmd < NUL") - # These flags have been taken from the defaults for a Visual C++ 4.20 project (the compiler the # game was originally built with) and tweaked slightly to produce more debugging info for reccmp. # They ensure a recompilation that can be byte/instruction accurate to the original binaries. - target_compile_options(isle PRIVATE "/ML$<$:d>") + if (ISLE_BUILD_APP) + target_compile_options(isle PRIVATE "/ML$<$:d>") + endif() target_compile_options(lego1 PRIVATE "/MT$<$:d>") set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"") diff --git a/tools/patch_c2.py b/tools/patch_c2.py new file mode 100644 index 00000000..7933c7ef --- /dev/null +++ b/tools/patch_c2.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +import argparse +import hashlib +import pathlib +import shutil + +ORIGINAL_C2_MD5 = "dcd69f1dd28b02dd03dd7ed02984299a" # original C2.EXE + +C2_MD5 = ( + ORIGINAL_C2_MD5, + "e70acde41802ddec06c4263bb357ac30", # patched C2.EXE +) + +C2_SIZE = 549888 + + +def main(): + parser = argparse.ArgumentParser(allow_abbrev=False, description="Patch C2.EXE of Micrisoft Visual Studio 4.2.0 to disable C4786 warning") + parser.add_argument("path", type=pathlib.Path, help="Path of C2.EXE") + parser.add_argument("-f", dest="force", default=False, action="store_true", help="force") + args = parser.parse_args() + + if not args.path.is_file(): + parser.error("Input is not a file") + + binary = bytearray(args.path.open("rb").read()) + md5 = hashlib.md5(binary).hexdigest() + print(md5, C2_MD5) + + msg_cb = parser.error if not args.force else print + if len(binary) != C2_SIZE: + msg_cb("file size is not correct") + if md5 not in C2_MD5: + msg_cb("md5 checksum does not match") + + if md5 == ORIGINAL_C2_MD5: + backup = f"{args.path}.BAK" + print(f"Creating backup \"{backup}\"") + shutil.copyfile(args.path, backup) + + def nop_patch(start, count, expected=None): + replacement = [0x90] * count + if expected: + current = list(binary[start:start + count]) + assert len(expected) == count + assert current in (expected, replacement) + print(f"Nopping {count} bytes at 0x{start:08x}") + binary[start:start + count] = replacement + + # Disable C4786 warning ('%Fs' : identifier was truncated to '%d' characters in the debug information) + nop_patch(0x52f07, 5, [0xe8, 0x4f, 0xb3, 0xfe, 0xff]) # 0x00453b07 + nop_patch(0x74832, 5, [0xe8, 0x24, 0x9a, 0xfc, 0xff]) # 0x00475432 + + args.path.open("wb").write(binary) + print("done") + + +if __name__ == "__main__": + raise SystemExit(main())