"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.zzstatic2 = exports.DisplayOpcodes = void 0;
var DisplayOpcodes;
(function (DisplayOpcodes) {
    DisplayOpcodes[DisplayOpcodes["G_NOOP"] = 0] = "G_NOOP";
    DisplayOpcodes[DisplayOpcodes["G_VTX"] = 1] = "G_VTX";
    DisplayOpcodes[DisplayOpcodes["G_MODIFYVTX"] = 2] = "G_MODIFYVTX";
    DisplayOpcodes[DisplayOpcodes["G_CULLDL"] = 3] = "G_CULLDL";
    DisplayOpcodes[DisplayOpcodes["G_BRANCH_Z"] = 4] = "G_BRANCH_Z";
    DisplayOpcodes[DisplayOpcodes["G_TRI1"] = 5] = "G_TRI1";
    DisplayOpcodes[DisplayOpcodes["G_TRI2"] = 6] = "G_TRI2";
    DisplayOpcodes[DisplayOpcodes["G_QUAD"] = 7] = "G_QUAD";
    DisplayOpcodes[DisplayOpcodes["G_SPECIAL_3"] = 211] = "G_SPECIAL_3";
    DisplayOpcodes[DisplayOpcodes["G_SPECIAL_2"] = 212] = "G_SPECIAL_2";
    DisplayOpcodes[DisplayOpcodes["G_SPECIAL_1"] = 213] = "G_SPECIAL_1";
    DisplayOpcodes[DisplayOpcodes["G_DMA_IO"] = 214] = "G_DMA_IO";
    DisplayOpcodes[DisplayOpcodes["G_TEXTURE"] = 215] = "G_TEXTURE";
    DisplayOpcodes[DisplayOpcodes["G_POPMTX"] = 216] = "G_POPMTX";
    DisplayOpcodes[DisplayOpcodes["G_GEOMETRYMODE"] = 217] = "G_GEOMETRYMODE";
    DisplayOpcodes[DisplayOpcodes["G_MTX"] = 218] = "G_MTX";
    DisplayOpcodes[DisplayOpcodes["G_MOVEWORD"] = 219] = "G_MOVEWORD";
    DisplayOpcodes[DisplayOpcodes["G_MOVEMEM"] = 220] = "G_MOVEMEM";
    DisplayOpcodes[DisplayOpcodes["G_LOAD_UCODE"] = 221] = "G_LOAD_UCODE";
    DisplayOpcodes[DisplayOpcodes["G_DL"] = 222] = "G_DL";
    DisplayOpcodes[DisplayOpcodes["G_ENDDL"] = 223] = "G_ENDDL";
    DisplayOpcodes[DisplayOpcodes["G_SPNOOP"] = 224] = "G_SPNOOP";
    DisplayOpcodes[DisplayOpcodes["G_RDPHALF_1"] = 225] = "G_RDPHALF_1";
    DisplayOpcodes[DisplayOpcodes["G_SETOTHERMODE_L"] = 226] = "G_SETOTHERMODE_L";
    DisplayOpcodes[DisplayOpcodes["G_SETOTHERMODE_H"] = 227] = "G_SETOTHERMODE_H";
    DisplayOpcodes[DisplayOpcodes["G_TEXRECT"] = 228] = "G_TEXRECT";
    DisplayOpcodes[DisplayOpcodes["G_TEXRECTFLIP"] = 229] = "G_TEXRECTFLIP";
    DisplayOpcodes[DisplayOpcodes["G_RDPLOADSYNC"] = 230] = "G_RDPLOADSYNC";
    DisplayOpcodes[DisplayOpcodes["G_RDPPIPESYNC"] = 231] = "G_RDPPIPESYNC";
    DisplayOpcodes[DisplayOpcodes["G_RDPTILESYNC"] = 232] = "G_RDPTILESYNC";
    DisplayOpcodes[DisplayOpcodes["G_RDPFULLSYNC"] = 233] = "G_RDPFULLSYNC";
    DisplayOpcodes[DisplayOpcodes["G_SETKEYGB"] = 234] = "G_SETKEYGB";
    DisplayOpcodes[DisplayOpcodes["G_SETKEYR"] = 235] = "G_SETKEYR";
    DisplayOpcodes[DisplayOpcodes["G_SETCONVERT"] = 236] = "G_SETCONVERT";
    DisplayOpcodes[DisplayOpcodes["G_SETSCISSOR"] = 237] = "G_SETSCISSOR";
    DisplayOpcodes[DisplayOpcodes["G_SETPRIMDEPTH"] = 238] = "G_SETPRIMDEPTH";
    DisplayOpcodes[DisplayOpcodes["G_RDPSETOTHERMODE"] = 239] = "G_RDPSETOTHERMODE";
    DisplayOpcodes[DisplayOpcodes["G_LOADTLUT"] = 240] = "G_LOADTLUT";
    DisplayOpcodes[DisplayOpcodes["G_RDPHALF_2"] = 241] = "G_RDPHALF_2";
    DisplayOpcodes[DisplayOpcodes["G_SETTILESIZE"] = 242] = "G_SETTILESIZE";
    DisplayOpcodes[DisplayOpcodes["G_LOADBLOCK"] = 243] = "G_LOADBLOCK";
    DisplayOpcodes[DisplayOpcodes["G_LOADTILE"] = 244] = "G_LOADTILE";
    DisplayOpcodes[DisplayOpcodes["G_SETTILE"] = 245] = "G_SETTILE";
    DisplayOpcodes[DisplayOpcodes["G_FILLRECT"] = 246] = "G_FILLRECT";
    DisplayOpcodes[DisplayOpcodes["G_SETFILLCOLOR"] = 247] = "G_SETFILLCOLOR";
    DisplayOpcodes[DisplayOpcodes["G_SETFOGCOLOR"] = 248] = "G_SETFOGCOLOR";
    DisplayOpcodes[DisplayOpcodes["G_SETBLENDCOLOR"] = 249] = "G_SETBLENDCOLOR";
    DisplayOpcodes[DisplayOpcodes["G_SETPRIMCOLOR"] = 250] = "G_SETPRIMCOLOR";
    DisplayOpcodes[DisplayOpcodes["G_SETENVCOLOR"] = 251] = "G_SETENVCOLOR";
    DisplayOpcodes[DisplayOpcodes["G_SETCOMBINE"] = 252] = "G_SETCOMBINE";
    DisplayOpcodes[DisplayOpcodes["G_SETTIMG"] = 253] = "G_SETTIMG";
    DisplayOpcodes[DisplayOpcodes["G_SETZIMG"] = 254] = "G_SETZIMG";
    DisplayOpcodes[DisplayOpcodes["G_SETCIMG"] = 255] = "G_SETCIMG";
})(DisplayOpcodes = exports.DisplayOpcodes || (exports.DisplayOpcodes = {}));
class zzstatic2 {
    pointerSet = new Set();
    pointerList = [];
    displayListStarts = new Set();
    temp = Buffer.alloc(4);
    recurseSet = new Set();
    isValidOpCode(op) {
        return DisplayOpcodes[op] !== undefined;
    }
    isOpCodeEnd(op) {
        switch (op) {
            case DisplayOpcodes.G_ENDDL:
                return true;
        }
        return false;
    }
    isOpCodeNOP(op) {
        switch (op) {
            case DisplayOpcodes.G_NOOP:
                return true;
        }
        return false;
    }
    doesOpCodeHavePointer(op) {
        switch (op) {
            case DisplayOpcodes.G_VTX:
            case DisplayOpcodes.G_BRANCH_Z:
            case DisplayOpcodes.G_MTX:
            case DisplayOpcodes.G_DL:
            case DisplayOpcodes.G_SETTIMG:
            case DisplayOpcodes.G_SETZIMG:
            case DisplayOpcodes.G_SETCIMG:
            case DisplayOpcodes.G_MOVEWORD:
                return true;
        }
        return false;
    }
    readCommand(buf, offset) {
        return new Command(buf.readUInt8(offset), buf.readUInt32BE(offset) & 0x00FFFFFF);
    }
    readPointer(buf, offset) {
        return buf.readUInt32BE(offset) & 0x00FFFFFF;
    }
    findAllDisplayLists(buf) {
        for (let i = 0; i < buf.byteLength; i += 8) {
            let cmd = this.readCommand(buf, i);
            if (this.isOpCodeEnd(cmd.id) && buf.readUInt32BE(i) === 0xDF000000 && buf.readUInt32BE(i + 0x4) === 0) {
                let reverse = i;
                while (this.isValidOpCode(cmd.id)) {
                    if (this.doesOpCodeHavePointer(cmd.id)) {
                        this.pointerSet.add(reverse + 4);
                    }
                    reverse -= 8;
                    cmd = this.readCommand(buf, reverse);
                }
                this.displayListStarts.add(reverse);
            }
        }
        return this.displayListStarts;
    }
    scanList(buf, start) {
        let cur = start;
        let cmd = this.readCommand(buf, cur);
        let recurse = new Set();
        while (cmd.id !== DisplayOpcodes.G_ENDDL) {
            cmd = this.readCommand(buf, cur);
            if (this.doesOpCodeHavePointer(cmd.id)) {
                this.pointerSet.add(cur + 0x4);
                if (buf.readUInt32BE(cur) === 0xDE000000 && buf.readUInt8(cur + 4) === 0x06) {
                    recurse.add(buf.readUInt32BE(cur + 0x4) & 0x00FFFFFF);
                }
            }
            cur += 0x8;
        }
        let r = Array.from(recurse);
        while (r.length > 0) {
            let r1 = r.shift();
            this.scanList(buf, r1);
        }
    }
    repoint(buf, base) {
        this.pointerSet.clear();
        //this.findAllDisplayLists(buf);
        let start = buf.indexOf(Buffer.from("MODLOADER64"));
        let count = buf.readUInt32BE(start + 0xC);
        let cur = start + 0x20;
        while (count > 0) {
            let cmd = this.readCommand(buf, cur);
            if (this.doesOpCodeHavePointer(cmd.id)) {
                this.pointerSet.add(cur + 4);
                this.scanList(buf, buf.readUInt32BE(cur + 4) & 0x00FFFFFF);
            }
            else if (this.isOpCodeNOP(cmd.id)) {
                this.pointerSet.add(cur + 0x4);
            }
            cur += 8;
            count--;
        }
        if (buf.readUInt32BE(start + 0x17) > 0) {
            this.pointerSet.add(start + 0x17);
        }
        let skelsec = this.readPointer(buf, start + 0x1C);
        if (skelsec > 0) {
            this.pointerSet.add(start + 0x1C);
            for (let i = 0; i < 4; i++) {
                let bones = buf.readUInt8(skelsec + (i * 0x10) + 4);
                if (bones > 0) {
                    this.pointerSet.add(skelsec + (i * 0x10));
                    let skel = this.readPointer(buf, skelsec + (i * 0x10));
                    for (let j = 0; j < bones; j++) {
                        this.pointerSet.add(skel + (j * 4));
                        let bone = this.readPointer(buf, skel + (j * 4));
                        bone += 8;
                        let d1 = buf.readUInt32BE(bone);
                        this.temp.writeUInt32BE(d1);
                        if (this.temp.readUInt8(0) === 0x06) {
                            this.pointerSet.add(bone);
                            this.scanList(buf, d1 & 0x00FFFFFF);
                        }
                        bone += 4;
                        let d2 = buf.readUInt32BE(bone);
                        this.temp.writeUInt32BE(d2);
                        if (this.temp.readUInt8(0) === 0x06) {
                            this.pointerSet.add(bone);
                            this.scanList(buf, d2 & 0x00FFFFFF);
                        }
                    }
                }
            }
        }
        this.pointerList = Array.from(this.pointerSet);
        for (let i = 0; i < this.pointerList.length; i++) {
            this.temp.writeUInt32BE(buf.readUInt32BE(this.pointerList[i]));
            if (this.temp.readUInt8(0) !== 0x06)
                continue;
            let p = this.readPointer(buf, this.pointerList[i]);
            p += base;
            buf.writeUInt32BE(p, this.pointerList[i]);
        }
    }
}
exports.zzstatic2 = zzstatic2;
class Command {
    id;
    params;
    constructor(id, params) {
        this.id = id;
        this.params = params;
    }
    equals(cmd) {
        return cmd.id === this.id && cmd.params === this.params;
    }
    toString() {
        return `${this.id.toString(16).toUpperCase().padStart(2, '0')} | ${this.params.toString(16).toUpperCase().padStart(6, '0')}`;
    }
}
//# sourceMappingURL=zzstatic2.js.map