|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | +# Madeira Converter Exception: see LICENSE-EXCEPTION.md |
| 4 | +"""Compile the production IL2CPP detector and launch-path mapping on temporary games.""" |
| 5 | +from pathlib import Path |
| 6 | +import subprocess |
| 7 | +import tempfile |
| 8 | + |
| 9 | +root = Path(__file__).resolve().parents[2] |
| 10 | +bcd = (root / 'app/Madeira/LibraryBCD.swift').read_text() |
| 11 | +library = (root / 'app/Madeira/Library.swift').read_text() |
| 12 | + |
| 13 | + |
| 14 | +def block(source, header): |
| 15 | + start = source.index(header) |
| 16 | + opening = source.index('{', start) |
| 17 | + depth, end = 1, opening + 1 |
| 18 | + while depth: |
| 19 | + depth += (source[end] == '{') - (source[end] == '}') |
| 20 | + end += 1 |
| 21 | + return source[start:end] |
| 22 | + |
| 23 | + |
| 24 | +swift = '''import Foundation |
| 25 | +struct LibraryEntry { |
| 26 | + var relativePath: String |
| 27 | + var steamAppID: Int? = nil |
| 28 | + var steamStart: String? = nil |
| 29 | + var steamProgram: String? = nil |
| 30 | + var epicAppName: String? = nil |
| 31 | + var epicAntiCheatOff: Bool? = nil |
| 32 | + static let epicAntiCheatOffProgram: [String: String] = [:] |
| 33 | + static let hostDrive = URL(fileURLWithPath: CommandLine.arguments[1], isDirectory: true) |
| 34 | +''' |
| 35 | +for header in [' var windowsPath:', ' var startsSteamGameDirectly:', |
| 36 | + ' var launchRelativePath:', ' var launchWindowsPath:', |
| 37 | + ' static func hostURL(ofWindowsPath']: |
| 38 | + swift += block(library, header) + '\n' |
| 39 | +swift += '}\nenum BCDLaunch {\n' + block(bcd, ' static func isUnityIL2CPP(') + '\n}\n' |
| 40 | +swift += r''' |
| 41 | +let fm = FileManager.default |
| 42 | +let drive = LibraryEntry.hostDrive |
| 43 | +func create(_ path: String) throws { |
| 44 | + let file = drive.appendingPathComponent(path) |
| 45 | + try fm.createDirectory(at: file.deletingLastPathComponent(), withIntermediateDirectories: true) |
| 46 | + try Data().write(to: file) |
| 47 | +} |
| 48 | +for path in ["Nested/bin/game.exe", "Nested/bin/GameAssembly.dll", "Root/game.exe", |
| 49 | + "Root/GameAssembly.dll", "Plain/game.exe", "Other/game.exe", "Other/GameAssembly.dll"] { |
| 50 | + try create(path) |
| 51 | +} |
| 52 | +try fm.createSymbolicLink(at: drive.appendingPathComponent("Plain/escape"), |
| 53 | + withDestinationURL: drive.appendingPathComponent("Other")) |
| 54 | +var failed = 0 |
| 55 | +func expect(_ value: Bool, _ label: String) { |
| 56 | + print((value ? "PASS: " : "FAIL: ") + label) |
| 57 | + if !value { failed += 1 } |
| 58 | +} |
| 59 | +let directSteam = LibraryEntry(relativePath: "Nested", steamAppID: 1, steamStart: "game", steamProgram: "bin/game.exe") |
| 60 | +expect(BCDLaunch.isUnityIL2CPP(directSteam), "known nested Steam executable is detected") |
| 61 | +expect(BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Nested/bin/game.exe")), "local nested executable is detected") |
| 62 | +expect(BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Root", steamAppID: 2)), "root-level Steam DLL is still detected") |
| 63 | +expect(BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Root/game.exe")), "local root-level DLL is still detected") |
| 64 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Plain/game.exe")), "non-IL2CPP game is not detected") |
| 65 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Plain", steamAppID: 3, steamStart: "game", steamProgram: "../Other/game.exe")), "parent traversal cannot select another game's assembly") |
| 66 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Plain", steamAppID: 3, steamStart: "game", steamProgram: "escape/game.exe")), "launch symlink cannot select another game's assembly") |
| 67 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "../Other/game.exe")), "invalid entry path is rejected") |
| 68 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Nested", steamAppID: 1)), "unknown Dock program does not scan arbitrary subdirectories") |
| 69 | +expect(!BCDLaunch.isUnityIL2CPP(LibraryEntry(relativePath: "Nested", steamAppID: 1, steamProgram: "bin/game.exe")), "a dormant direct-start choice does not change a Dock launch") |
| 70 | +exit(failed == 0 ? 0 : 1) |
| 71 | +''' |
| 72 | +with tempfile.TemporaryDirectory(prefix='madeira-il2cpp-detection-') as tmp: |
| 73 | + directory = Path(tmp) |
| 74 | + program = directory / 'detect.swift' |
| 75 | + program.write_text(swift) |
| 76 | + subprocess.run(['swift', str(program), str(directory / 'drive_c')], check=True) |
| 77 | +print('check-il2cpp-detection: PASS') |
0 commit comments