UNPKG

@shockpkg/dir-projector

Version:

Package for creating Shockwave Director projectors

348 lines (276 loc) 7.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectorWindows = void 0; var _path = require("path"); var _archiveFiles = require("@shockpkg/archive-files"); var _patcher = require("../patcher"); var _projector = require("../projector"); var _util = require("../util"); /** * ProjectorWindows constructor. * * @param options Options object. */ class ProjectorWindows extends _projector.Projector { /** * Patch the Shockave 3D Xtra to have a larger buffer to avoid a crash. * The buffer for resolving InstalledDisplayDrivers to a path is small. * Changes to the values stored in InstalledDisplayDrivers cause issues. * The value is now supposed to hold full paths on modern Windows. * In particular, Nvidia drivers which do this need this patch. * * @default false */ /** * Icon file, requires Windows or Wine. * * @default null */ /** * Version strings, requires Windows or Wine. * * @default null */ /** * Product version, requires Windows or Wine. * * @default null */ /** * Version strings, requires Windows or Wine. * * @default null */ constructor(options) { super(options); this.patchShockwave3dInstalledDisplayDriversSize = void 0; this.iconFile = void 0; this.fileVersion = void 0; this.productVersion = void 0; this.versionStrings = void 0; this.iconFile = (0, _util.defaultNull)(options.iconFile); this.fileVersion = (0, _util.defaultNull)(options.fileVersion); this.productVersion = (0, _util.defaultNull)(options.productVersion); this.versionStrings = (0, _util.defaultNull)(options.versionStrings); this.patchShockwave3dInstalledDisplayDriversSize = (0, _util.defaultFalse)(options.patchShockwave3dInstalledDisplayDriversSize); } /** * Projector file extension. * * @returns File extension. */ get projectorExtension() { return '.exe'; } /** * Config file newline characters. * * @returns Newline characters. */ get configNewline() { return '\r\n'; } /** * Config file newline characters. * * @returns Newline characters. */ get lingoNewline() { return '\r\n'; } /** * Newline characters. * * @returns Newline characters. */ get newline() { return '\r\n'; } /** * Splash image file extension. * * @returns File extension. */ get splashImageExtension() { return '.BMP'; } /** * Get the SKL name. * * @returns File name. */ get sklName() { return 'Projec32.skl'; } /** * Write out the projector. * * @param path Save path. * @param name Save name. */ async write(path, name) { await super.write(path, name); await this._patch(path, name); await this._updateResources(path, name); } /** * Write the projector skeleton from archive. * * @param path Save path. * @param name Save name. */ async _writeSkeleton(path, name) { const { shockwave, sklName, xtrasDirectoryName } = this; const xtrasPath = this.getXtrasPath(name); const xtrasMappings = this.getIncludeXtrasMappings(); let foundProjectorSkl = false; let foundXtras = false; const xtrasHandler = async entry => { // Check if Xtras path. const xtrasRel = (0, _util.pathRelativeBase)(entry.volumePath, xtrasDirectoryName, true); if (xtrasRel === null) { return false; } foundXtras = true; // Find output path if being included, else skip. const dest = this.includeXtrasMappingsDest(xtrasMappings, xtrasRel); if (!dest) { return true; } await entry.extract((0, _path.join)(path, xtrasPath, dest)); return true; }; const projectorSklHandler = async entry => { const entryPath = entry.volumePath; // Should not be in sub directory. if (entryPath.includes('/')) { return false; } // Check if skl path. if (!(0, _util.pathRelativeBaseMatch)(entryPath, sklName, true)) { return false; } foundProjectorSkl = true; await entry.extract((0, _path.join)(path, name)); return true; }; const projectorDllHandler = async entry => { const entryPath = entry.volumePath; // Should not be in sub directory. if (entryPath.includes('/')) { return false; } // Check if dll path. if (!/\.dll$/i.test(entryPath)) { return false; } // Exclude if shockwave projector. if (shockwave) { return true; } await entry.extract((0, _path.join)(path, entryPath)); return true; }; const archive = await this.getSkeletonArchive(); await archive.read(async entry => { // Skip empty resource forks (every file in DMG). if ((0, _util.entryIsEmptyResourceFork)(entry)) { return; } if (await xtrasHandler(entry)) { return; } if (await projectorSklHandler(entry)) { return; } if (await projectorDllHandler(entry)) { return; } }); if (!foundProjectorSkl) { throw new Error(`Failed to locate: ${sklName}`); } if (!foundXtras) { throw new Error(`Failed to locate: ${xtrasDirectoryName}`); } } /** * Patch projector. * * @param path Save path. * @param name Save name. */ async _patch(path, name) { await this._patchShockwave3dInstalledDisplayDriversSize(path, name); } /** * Patch projector, Shockwave 3D InstalledDisplayDrivers size. * * @param path Save path. * @param name Save name. */ async _patchShockwave3dInstalledDisplayDriversSize(path, name) { if (!this.patchShockwave3dInstalledDisplayDriversSize) { return; } const xtrasDir = (0, _path.join)(path, this.getXtrasPath(name)); const search = 'Shockwave 3D Asset.x32'; const searchLower = search.toLowerCase(); let found = false; await (0, _archiveFiles.fsWalk)(xtrasDir, async (path, stat) => { if (!stat.isFile()) { return; } const fn = (0, _path.basename)(path); if (fn.toLowerCase() !== searchLower) { return; } found = true; await (0, _patcher.patchWindowsS3dInstalledDisplayDriversSize)((0, _path.join)(xtrasDir, path)); }, { ignoreUnreadableDirectories: true }); if (!found) { throw new Error(`Failed to locate for patching: ${search}`); } } /** * Update projector Windows resources. * * @param path Save path. * @param name Save name. */ async _updateResources(path, name) { const { iconFile, fileVersion, productVersion, versionStrings } = this; const options = {}; let optionsSet = false; if (iconFile) { options.iconPath = iconFile; optionsSet = true; } if (fileVersion !== null) { options.fileVersion = fileVersion; optionsSet = true; } if (productVersion !== null) { options.productVersion = productVersion; optionsSet = true; } if (versionStrings !== null) { options.versionStrings = versionStrings; optionsSet = true; } // Do not update if no changes are specified. if (!optionsSet) { return; } const file = (0, _path.join)(path, name); await (0, _util.rcedit)(file, options); } } exports.ProjectorWindows = ProjectorWindows; //# sourceMappingURL=windows.js.map