import assert from 'node:assert/strict'; import { parseLocalPkg } from '../src/utils/parseLocalPkg.js'; const bytes = new Uint8Array(0x140000); const view = new DataView(bytes.buffer); const encode = new TextEncoder(); bytes.set([0x7f, 0x43, 0x4e, 0x54], 0); view.setUint32(0x10, 2, false); view.setUint32(0x18, 0x100, false); bytes.set(encode.encode('UP0000-GAME12345_00-1234567890123456'), 0x40); const json = encode.encode('{"titleId":"GAME12345","titleName":"Beyond Header","category":"gp","appVersion":"1.02"}'); view.setUint32(0x100, 0x2000, false); view.setUint32(0x110, 0x120000, false); view.setUint32(0x114, json.length, false); bytes.set(json, 0x120000); view.setUint32(0x120, 0x1200, false); view.setUint32(0x130, 0x130000, false); view.setUint32(0x134, 9, false); bytes.set([0x89, 0x50, 0x4e, 0x47, 13, 10, 26, 10, 0], 0x130000); const file = new Blob([bytes]); file.name = 'beyond.pkg'; const details = await parseLocalPkg(file); assert.equal(details.title_name, 'Beyond Header'); assert.equal(details.title_id, 'GAME12345'); assert.equal(details.app_version, 'v1.02'); assert.equal(details.pkg_type, 'update'); assert.equal(details.icon_offset, 0x130000); assert.equal(details.icon_size, 9); console.log('parseLocalPkg: metadata and icon beyond first 1 MB passed'); const ps4 = new Uint8Array(0x120000); const p4 = new DataView(ps4.buffer); ps4.set([0x7f, 0x43, 0x4e, 0x54], 0); p4.setUint32(0x10, 1, false); p4.setUint32(0x18, 0x100, false); p4.setUint32(0x100, 0x1000, false); p4.setUint32(0x110, 0x110000, false); const sfo = new Uint8Array(160); const sv = new DataView(sfo.buffer); sv.setUint32(0, 0x46535000, true); sv.setUint32(8, 68, true); sv.setUint32(12, 104, true); sv.setUint32(16, 3, true); sfo.set(encode.encode('TITLE\0TITLE_ID\0CATEGORY\0'), 68); const ps4Title = encode.encode('PS4 Package\0'); const ps4Id = encode.encode('CUSA12345\0'); sv.setUint32(24, ps4Title.length, true); sv.setUint32(32, 0, true); sv.setUint16(36, 6, true); sv.setUint32(40, ps4Id.length, true); sv.setUint32(48, 20, true); sv.setUint16(52, 15, true); sv.setUint32(56, 3, true); sv.setUint32(64, 36, true); sfo.set(ps4Title, 104); sfo.set(ps4Id, 124); sfo.set(encode.encode('gd\0'), 140); p4.setUint32(0x04, 1, false); p4.setUint32(0x114, sfo.length, false); ps4.set(sfo, 0x110000); const ps4File = new Blob([ps4]); ps4File.name = 'ps4.pkg'; const ps4Details = await parseLocalPkg(ps4File); assert.equal(ps4Details.title_name, 'PS4 Package'); assert.equal(ps4Details.title_id, 'CUSA12345'); assert.equal(ps4Details.pkg_type, 'base'); console.log('parseLocalPkg: PS4 CATEGORY=gd overrides CNT type 1'); const dlcBytes = new Uint8Array(0x120000); const dv = new DataView(dlcBytes.buffer); dlcBytes.set([0x7f, 0x43, 0x4e, 0x54], 0); dv.setUint32(0x04, 0x00020001, false); dv.setUint32(0x10, 1, false); dv.setUint32(0x18, 0x100, false); dlcBytes.set(encode.encode('TEST00-TEST00000_00-DLCMETADATA0001'), 0x40); dv.setUint32(0x100, 0x2000, false); dv.setUint32(0x110, 0x110000, false); const dlcJson = encode.encode('{"titleId":"TEST00000","titleName":"DLC Package","contentVersion":"01.000.000"}'); dv.setUint32(0x114, dlcJson.length, false); dlcBytes.set(dlcJson, 0x110000); const dlcFile = new Blob([dlcBytes]); dlcFile.name = 'dlc-package.pkg'; const dlcDetails = await parseLocalPkg(dlcFile); assert.equal(dlcDetails.pkg_type, 'dlc'); assert.equal(dlcDetails.title_id, 'TEST00000'); console.log('parseLocalPkg: CNT type 0x00020001 DLC detection passed'); const baseBytes = new Uint8Array(dlcBytes); const baseView = new DataView(baseBytes.buffer); const baseJson = encode.encode('{"titleId":"TEST00000","titleName":"Base Package","applicationDrmType":"standard","contentVersion":"01.000.000"}'); baseView.setUint32(0x114, baseJson.length, false); baseBytes.set(baseJson, 0x110000); const baseDetails = await parseLocalPkg(new Blob([baseBytes])); assert.equal(baseDetails.pkg_type, 'base'); console.log('parseLocalPkg: base application metadata overrides shared CNT low byte');