Skip to content

Commit

Permalink
Update CascLib
Browse files Browse the repository at this point in the history
  • Loading branch information
olegbl committed Jul 27, 2024
1 parent 45015ef commit 9878b8b
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 28 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
"build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts",
"build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
"build:casclib": "\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe\" ./node_modules/CascLib/CascLib_dll.vcxproj /p:Configuration=Release /p:Platform=x64 && copy .\\node_modules\\CascLib\\bin\\CascLib_dll\\x64\\Release\\CascLib.dll .\\tools\\",
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
"lint": "cross-env NODE_ENV=development eslint ./src/ --ext .js,.jsx,.ts,.tsx --cache --cache-strategy metadata",
"package": "ts-node ./.erb/scripts/clean.js dist && npm run build --no-warnings && electron-builder build --publish never",
Expand Down Expand Up @@ -144,6 +145,7 @@
"@types/webpack-env": "^1.16.3",
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"CascLib": "https://github.com/ladislav-zezula/CascLib.git",
"browserslist-config-erb": "^0.0.3",
"chalk": "^4.1.2",
"concurrently": "^6.5.1",
Expand Down
40 changes: 22 additions & 18 deletions src/main/worker/BridgeAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ import {
import ts from 'typescript';
import packageManifest from '../../../release/app/package.json';
import { getAppPath, getHomePath } from './AppInfoAPI';
import { dwordPtr, getCascLib, processErrorCode, voidPtrPtr } from './CascLib';
import {
dwordPtr,
getCascLib,
getLastCascLibError,
voidPtrPtr,
} from './CascLib';
import { EventAPI } from './EventAPI';
import { provideAPI } from './IPC';
import { InstallationRuntime } from './InstallationRuntime';
Expand Down Expand Up @@ -133,14 +138,10 @@ function copyDirSync(src: string, dest: string) {
function createError(
method: string,
message: string,
errorCodeArg?: unknown,
errorCode?: unknown,
): Error {
const prefix = `${method}: ${message}`;
let errorCode = errorCodeArg;
if (errorCode != null) {
if (typeof errorCode === 'string' || typeof errorCode === 'number') {
errorCode = processErrorCode(errorCode) ?? errorCode;
}
return new Error(`${prefix}: ${String(errorCode)}`);
}
return new Error(prefix);
Expand Down Expand Up @@ -211,18 +212,21 @@ export const BridgeAPI: IBridgeAPI = {
openStorage: async (gamePath: string) => {
console.debug('BridgeAPI.openStorage', { gamePath });

// what do these mean? who knows!
const PATHS = [`${gamePath}:osi`, `${gamePath}:`, `${gamePath}`];

if (!cascStorageIsOpen) {
if (getCascLib().CascOpenStorage(`${gamePath}:osi`, 0, cascStoragePtr)) {
cascStorageIsOpen = true;
} else if (
getCascLib().CascOpenStorage(`${gamePath}:`, 0, cascStoragePtr)
) {
cascStorageIsOpen = true;
} else {
for (const path of PATHS) {
if (getCascLib().CascOpenStorage(path, 0, cascStoragePtr)) {
cascStorageIsOpen = true;
break;
}
}
if (!cascStorageIsOpen) {
throw createError(
'API.openStorage',
'Failed to open CASC storage',
`(CascLib Error Code: ${getCascLib().GetLastError()})`,
getLastCascLibError(),
);
}
}
Expand All @@ -241,7 +245,7 @@ export const BridgeAPI: IBridgeAPI = {
throw createError(
'API.closeStorage',
'Failed to close CASC storage',
`(CascLib Error Code: ${getCascLib().GetLastError()})`,
getLastCascLibError(),
);
}
}
Expand Down Expand Up @@ -310,7 +314,7 @@ export const BridgeAPI: IBridgeAPI = {
throw createError(
'API.extractFile',
`Failed to open file in CASC storage (${filePath})`,
`(CascLib Error Code: ${getCascLib().GetLastError()})`,
getLastCascLibError(),
);
}

Expand All @@ -333,15 +337,15 @@ export const BridgeAPI: IBridgeAPI = {
throw createError(
'API.extractFile',
`Failed to read file in CASC storage (${filePath})`,
`(CascLib Error Code: ${getCascLib().GetLastError()})`,
getLastCascLibError(),
);
}

if (!getCascLib().CascCloseFile(file)) {
throw createError(
'API.extractFile',
`Failed to close file in CASC storage (${filePath})`,
`(CascLib Error Code: ${getCascLib().GetLastError()})`,
getLastCascLibError(),
);
}
} catch (e) {
Expand Down
19 changes: 9 additions & 10 deletions src/main/worker/CascLib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ref from 'ref-napi';
import { getAppPath } from './AppInfoAPI';

// http://www.zezula.net/en/casc/casclib.html
// https://github.com/ladislav-zezula/CascLib/blob/master/src/CascLib.h
export type ICascLib = {
CascCloseFile: ffi.ForeignFunction<boolean, [ref.Pointer<void>]>;
CascCloseStorage: ffi.ForeignFunction<boolean, [ref.Pointer<void>]>;
Expand All @@ -19,7 +20,7 @@ export type ICascLib = {
boolean,
[ref.Pointer<void>, ref.Pointer<void>, number, ref.Pointer<number>]
>;
GetLastError: ffi.ForeignFunction<number, []>;
GetCascError: ffi.ForeignFunction<number, []>;
};

export const voidPtr = ref.refType(ref.types.void);
Expand All @@ -35,15 +36,15 @@ export async function initCascLib(): Promise<void> {
CascOpenFile: ['bool', [voidPtr, 'string', 'int', 'int', voidPtrPtr]],
CascOpenStorage: ['bool', ['string', 'int', voidPtrPtr]],
CascReadFile: ['bool', [voidPtr, voidPtr, 'int', dwordPtr]],
GetLastError: ['int', []],
GetCascError: ['int', []],
});
}

export function getCascLib(): ICascLib {
return CASC_LIB;
}

// CascLib Error Codes for GetLastError()
// CascLib Error Codes for GetCascError()
// https://github.com/ladislav-zezula/CascLib/blob/master/src/CascPort.h#L230
// https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
const KnownWindowsErrorCodes: { [code: number]: string } = {
Expand Down Expand Up @@ -293,14 +294,12 @@ const KnownWindowsErrorCodes: { [code: number]: string } = {
487: 'ERROR_INVALID_ADDRESS: Attempt to access invalid address.',
};

export function processErrorCode(errorCodeArg: string | number): string | null {
let errorCode = errorCodeArg;
export function getLastCascLibError(): string {
let errorCode = getCascLib().GetCascError();
if (typeof errorCode === 'string') {
errorCode = parseInt(errorCode, 10);
}
const knownCodeDescription = KnownWindowsErrorCodes[errorCode];
if (knownCodeDescription != null) {
return `${errorCode}: ${knownCodeDescription}`;
}
return null;

const message = KnownWindowsErrorCodes[errorCode] ?? `UNKNOWN ERROR`;
return `CascLib error code ${errorCode}: ${message}`;
}
1 change: 1 addition & 0 deletions src/renderer/react/modlist/hooks/useInstallMods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export default function useInstallMods(
}
return true;
} catch (error) {
setIsInstalling(false);
console.error(String(error));
showToast({
severity: 'error',
Expand Down
Binary file modified tools/CascLib.dll
Binary file not shown.
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2137,6 +2137,10 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==

"CascLib@https://github.com/ladislav-zezula/CascLib.git":
version "0.0.0"
resolved "https://github.com/ladislav-zezula/CascLib.git#f3714c3ee25ddfce5cf6e00b32390d1bb563767b"

abab@^2.0.3, abab@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
Expand Down

0 comments on commit 9878b8b

Please sign in to comment.