use a proper logger

This commit is contained in:
beerpsi
2024-10-27 03:17:55 +07:00
parent cadee776ea
commit ecaec6d942
4 changed files with 40 additions and 13 deletions
+1
View File
@@ -1 +1,2 @@
.ruff_cache .ruff_cache
*.log
+2 -2
View File
@@ -9,10 +9,10 @@ disk image.
## Patchers ## Patchers
- `patchers/b2spatch.ts`: Convert from BemaniPatcher to Spice2x JSON - `patchers/b2spatch.ts`: Convert from BemaniPatcher to Spice2x JSON
- Use Deno: `deno run -WNE b2spatch.ts ...` - Use Deno: `deno run -A b2spatch.ts ...`
- You will need to rename the resulting JSON manually so that they match the - You will need to rename the resulting JSON manually so that they match the
`{gameCode}-{timestamp}_{entrypoint}` format expected by Spice2x. `{gameCode}-{timestamp}_{entrypoint}` format expected by Spice2x.
- `patchers/b2mpatch.ts`: Convert from BemaniPatcher to [mempatch-hook](https://github.com/djhackersdev/bemanitools/blob/master/doc/tools/mempatch-hook.md) - `patchers/b2mpatch.ts`: Convert from BemaniPatcher to [mempatch-hook](https://github.com/djhackersdev/bemanitools/blob/master/doc/tools/mempatch-hook.md)/[mempatcher](https://github.com/aixxe/mempatcher)
- Use Deno: `deno run -A b2mpatch.ts ...` - Use Deno: `deno run -A b2mpatch.ts ...`
- You need to setup a folder of executables or DLLs you want to patch. They - You need to setup a folder of executables or DLLs you want to patch. They
can be named the patcher's description, or the patcher's filename. can be named the patcher's description, or the patcher's filename.
+32 -9
View File
@@ -1,11 +1,15 @@
import { Buffer } from "node:buffer";
import { existsSync, readFileSync, writeFileSync } from "node:fs"; import { existsSync, readFileSync, writeFileSync } from "node:fs";
import process from "node:process"; import process from "node:process";
import path from "node:path"; import path from "node:path";
import { CreateLogger } from "npm:mei-logger";
import PE from "npm:pe-parser"; import PE from "npm:pe-parser";
import type { PEFile } from "npm:pe-parser/parser"; import type { PEFile } from "npm:pe-parser/parser";
import sanitize from "npm:sanitize-filename"; import sanitize from "npm:sanitize-filename";
import { bytesToHex, parsePatcherHtml } from "./_parser.ts"; import { bytesToHex, parsePatcherHtml } from "./_parser.ts";
const logger = CreateLogger("b2mpatch");
function fileOffsetToRVA(pe: PEFile, offset: number) { function fileOffsetToRVA(pe: PEFile, offset: number) {
for (const section of pe.sections) { for (const section of pe.sections) {
if ( if (
@@ -45,32 +49,46 @@ async function main() {
executableDir, executableDir,
sanitize(patcher.description) + path.extname(patcher.fname), sanitize(patcher.description) + path.extname(patcher.fname),
); );
let useFileOffsets = false;
if (!existsSync(exePath)) { if (!existsSync(exePath)) {
console.warn( logger.warn(
`Target file ${exePath} does not exist, falling back to ${patcher.fname}.`, `Target file ${exePath} does not exist, falling back to ${patcher.fname}.`,
); );
exePath = path.join(executableDir, patcher.fname); exePath = path.join(executableDir, patcher.fname);
} }
if (!existsSync(exePath)) { if (!existsSync(exePath)) {
console.warn(`Target file ${exePath} does not exist, skipping.`); logger.warn(`Target file ${exePath} does not exist, using file offsets instead (requires gh:aixxe/mempatcher).`);
continue; useFileOffsets = true;
}
let data: Buffer | null = null;
let pe: PEFile | null = null;
if (!useFileOffsets) {
data = readFileSync(exePath);
pe = await PE.Parse(data);
} }
const data = readFileSync(exePath);
const pe = await PE.Parse(data);
let mempatch = `# ${patcher.fname} ${patcher.description}\n\n`; let mempatch = `# ${patcher.fname} ${patcher.description}\n\n`;
for (const patch of patcher.patches) { for (const patch of patcher.patches) {
if (patch.type !== undefined && patch.type !== "union") { if (patch.type !== undefined && patch.type !== "union") {
console.warn( logger.warn(
`Unsupported BemaniPatcher patch type ${patch.type}`, `Unsupported BemaniPatcher patch type ${patch.type}`,
patch, patch,
); );
continue; continue;
} }
if (patch.type === "union" && !data) {
logger.warn(
`Union patch requires file data, skipping.`, patch,
);
continue;
}
mempatch += `# ${patch.name}\n`; mempatch += `# ${patch.name}\n`;
if (patch.tooltip) { if (patch.tooltip) {
@@ -90,7 +108,7 @@ async function main() {
const up = p as { name: string; patch: number[] }; const up = p as { name: string; patch: number[] };
on = bytesToHex(up.patch); on = bytesToHex(up.patch);
off = data off = data!
.subarray( .subarray(
patch.offset, patch.offset,
patch.offset + up.patch.length, patch.offset + up.patch.length,
@@ -111,8 +129,13 @@ async function main() {
on = bytesToHex(sp.on); on = bytesToHex(sp.on);
off = bytesToHex(sp.off); off = bytesToHex(sp.off);
offset = fileOffsetToRVA(pe, sp.offset).toString(16)
.toUpperCase(); if (useFileOffsets) {
offset = "F+" + sp.offset.toString(16).toUpperCase();
} else {
offset = fileOffsetToRVA(pe, sp.offset).toString(16)
.toUpperCase();
}
} }
if (patch.type === "union" && on === off) { if (patch.type === "union" && on === off) {
+5 -2
View File
@@ -8,6 +8,7 @@
import { readFileSync, writeFileSync } from "node:fs"; import { readFileSync, writeFileSync } from "node:fs";
import path from "node:path"; import path from "node:path";
import process from "node:process"; import process from "node:process";
import { CreateLogger } from "npm:mei-logger";
import { bytesToHex, parsePatcherHtml } from "./_parser.ts"; import { bytesToHex, parsePatcherHtml } from "./_parser.ts";
import type { import type {
BemaniPatch, BemaniPatch,
@@ -19,6 +20,8 @@ import type {
SpiceUnionPatch, SpiceUnionPatch,
} from "./_types.ts"; } from "./_types.ts";
const logger = CreateLogger("b2spatch");
function convertToSpicePatch( function convertToSpicePatch(
bmPatch: BemaniPatch, bmPatch: BemaniPatch,
gameCode: string, gameCode: string,
@@ -69,7 +72,7 @@ function convertToSpicePatch(
// Technically you can match BemaniPatcher's DynamicPatch type to // Technically you can match BemaniPatcher's DynamicPatch type to
// Spice's signature patch, but one DynamicPatch can have multiple signatures, // Spice's signature patch, but one DynamicPatch can have multiple signatures,
// while Spice only supports one signature per patch. // while Spice only supports one signature per patch.
console.warn( logger.warn(
`Unsupported BemaniPatcher patch type ${bmPatch.type}`, `Unsupported BemaniPatcher patch type ${bmPatch.type}`,
bmPatch, bmPatch,
); );
@@ -90,7 +93,7 @@ function convertToSpicePatch(
async function main() { async function main() {
if (process.argv.length < 4) { if (process.argv.length < 4) {
console.log( console.log(
"Usage: deno run -WNE b2spatch.ts <patcher URL | local patcher HTML> <gameCode> [output dir]", "Usage: deno run -A b2spatch.ts <patcher URL | local patcher HTML> <gameCode> [output dir]",
); );
process.exit(1); process.exit(1);
} }