mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-23 01:57:29 +00:00
186 lines
4.3 KiB
JavaScript
186 lines
4.3 KiB
JavaScript
const { COMMANDS } = require("./constants");
|
|
const MAGIC = "FG";
|
|
const ENCODING = "utf8";
|
|
|
|
class Parser {
|
|
_readMagic() {
|
|
const magic = this._readStringOfLength(MAGIC.length);
|
|
if (magic !== MAGIC) {
|
|
throw new Error("Magic number does not mach. Is this a maki file?");
|
|
}
|
|
return magic;
|
|
}
|
|
|
|
_readVersion() {
|
|
// No idea what we're actually expecting here.
|
|
this._i += 2;
|
|
}
|
|
|
|
_readTypes() {
|
|
let count = this._readUInt32LE();
|
|
const types = [];
|
|
while (count--) {
|
|
let identifier = "";
|
|
let chunks = 4;
|
|
while (chunks--) {
|
|
identifier += this._readUInt32LE().toString(16);
|
|
}
|
|
types.push(identifier.padStart(32, "0"));
|
|
}
|
|
return types;
|
|
}
|
|
|
|
_readFunctionsNames() {
|
|
let count = this._readUInt32LE();
|
|
const functionNames = [];
|
|
while (count--) {
|
|
const func = {};
|
|
func.classCode = this._readUInt16LE();
|
|
// Offset into our parsed types
|
|
func.classType = func.classCode & 0xff;
|
|
func.dummy2 = this._readUInt16LE();
|
|
func.name = this._readString();
|
|
functionNames.push(func);
|
|
}
|
|
return functionNames;
|
|
}
|
|
|
|
_readVariables() {
|
|
let count = this._readUInt32LE();
|
|
const variables = [];
|
|
while (count--) {
|
|
const type = this._readUInt8();
|
|
const object = this._readUInt8();
|
|
const subClass = this._readUInt16LE();
|
|
const uinit1 = this._readUInt16LE();
|
|
const uinit2 = this._readUInt16LE();
|
|
const uinit3 = this._readUInt16LE();
|
|
const uinit4 = this._readUInt16LE();
|
|
const global = this._readUInt8();
|
|
const system = this._readUInt8();
|
|
const variable = {
|
|
type,
|
|
object,
|
|
subClass,
|
|
uinit1,
|
|
uinit2,
|
|
uinit3,
|
|
uinit4,
|
|
global,
|
|
system
|
|
};
|
|
variables.push(variable);
|
|
}
|
|
return variables;
|
|
}
|
|
|
|
_readConstants() {
|
|
let count = this._readUInt32LE();
|
|
const constants = [];
|
|
while (count--) {
|
|
const varNum = this._readUInt32LE();
|
|
const value = this._readString();
|
|
constants.push({ varNum, value });
|
|
}
|
|
return constants;
|
|
}
|
|
|
|
_readFunctions() {
|
|
let count = this._readUInt32LE();
|
|
const functions = [];
|
|
while (count--) {
|
|
const varNum = this._readUInt32LE();
|
|
const funcNum = this._readUInt32LE();
|
|
const offset = this._readUInt32LE();
|
|
functions.push({ varNum, offset, funcNum });
|
|
}
|
|
return functions;
|
|
}
|
|
|
|
_readCommands(code) {
|
|
let i = 0;
|
|
while (i < code.length) {
|
|
const opCode = code.charCodeAt(i);
|
|
const command = COMMANDS[opCode];
|
|
if (command.arg == null) {
|
|
i++;
|
|
continue;
|
|
}
|
|
switch (command.arg) {
|
|
case "var":
|
|
// This is the index into this._debug.variables
|
|
// this._readUInt32LE();
|
|
i += 5;
|
|
break;
|
|
default:
|
|
i += 5;
|
|
}
|
|
// console.log({ command });
|
|
}
|
|
}
|
|
|
|
_readFunctionsCode() {
|
|
const code = this._readStringOfLength(this._readUInt32LE());
|
|
return code;
|
|
}
|
|
|
|
_readUInt32LE() {
|
|
const int = this._buffer.readUInt32LE(this._i);
|
|
this._i += 4;
|
|
return int;
|
|
}
|
|
|
|
_readUInt16LE() {
|
|
const int = this._buffer.readUInt16LE(this._i);
|
|
this._i += 2;
|
|
return int;
|
|
}
|
|
|
|
_readUInt8() {
|
|
const int = this._buffer.readUInt8(this._i);
|
|
this._i++;
|
|
return int;
|
|
}
|
|
|
|
_readStringOfLength(length) {
|
|
const str = this._buffer.toString(ENCODING, this._i, this._i + length);
|
|
this._i += length;
|
|
return str;
|
|
}
|
|
|
|
_readString() {
|
|
return this._readStringOfLength(this._readUInt16LE());
|
|
}
|
|
|
|
parse(buffer) {
|
|
this._buffer = buffer;
|
|
this._i = 0;
|
|
|
|
const magic = this._readMagic();
|
|
this._readVersion();
|
|
this._readUInt32LE(); // Not sure what we are skipping over here. Just some UInt 32.
|
|
const types = this._readTypes();
|
|
const functionNames = this._readFunctionsNames();
|
|
const variables = this._readVariables();
|
|
const constants = this._readConstants();
|
|
const functions = this._readFunctions();
|
|
const functionsCode = this._readFunctionsCode();
|
|
this._readCommands(functionsCode);
|
|
return {
|
|
magic,
|
|
types,
|
|
functionNames,
|
|
variables,
|
|
constants,
|
|
functionsCode,
|
|
functions
|
|
};
|
|
}
|
|
}
|
|
|
|
function parse(buffer) {
|
|
const parser = new Parser();
|
|
return parser.parse(buffer);
|
|
}
|
|
|
|
module.exports = { parse };
|