inhabitor/mamelink/out2prg.js

55 lines
2.1 KiB
JavaScript

const fs = require('node:fs/promises');
const assert = require('node:assert/strict');
const die = (...message) => {
console.error(...message)
process.exit(1)
}
if (process.argv.length != 3) {
die("Usage: node out2prg.js FILE.out")
}
const replaceExtension = (filename, ext) => {
const idot = filename.lastIndexOf(".")
return `${idot < 0 ? filename : filename.substr(0, idot)}.${ext}`
}
(async () => {
const outfilename = process.argv[2]
const data = await fs.readFile(outfilename)
assert.equal(data.readUint16LE(0), 0xffff, `${outfilename} does not start with magic FFFF bytes`)
const prgfilename = replaceExtension(outfilename, "prg")
const prgfile = await fs.open(prgfilename, "w")
try {
let off = 2
let nextAddress = null
let bootAddr = null
while (off < data.length) {
const startAddr = data.readUint16LE(off)
const endAddr = data.readUint16LE(off + 2)
if (startAddr == endAddr && bootAddr == null) {
bootAddr = startAddr
console.log(`To start, type SYS${bootAddr}`)
console.log(`Skipping byte: ${data.readUint8(off + 4)}`)
off += 5
continue
}
assert.ok(endAddr >= startAddr, `Invalid address range ${startAddr}:${endAddr}`)
assert.ok(nextAddress == null || startAddr >= nextAddress, `Expected ${startAddr} to come after previous segment ending at ${nextAddress}`)
const paddingLength = nextAddress == null ? 0 : startAddr - nextAddress
const blobLength = endAddr - startAddr + 1
if (nextAddress == null) {
await fs.writeFile(prgfile, data.subarray(off, off + 2))
}
if (paddingLength > 0) {
await fs.writeFile(prgfile, Buffer.alloc(paddingLength))
}
off += 4
await fs.writeFile(prgfile, data.subarray(off, off + blobLength))
nextAddress = endAddr + 1
off += blobLength
}
} finally {
await prgfile.close()
}
})()