Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: CHD support #1006

Merged
merged 94 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
c63d8eb
Draft
emmercm Mar 15, 2024
8b2a452
Update
emmercm Mar 15, 2024
5fb170d
Update
emmercm Mar 15, 2024
2635740
Update
emmercm Mar 15, 2024
59203a8
Update
emmercm Mar 16, 2024
4529420
Update
emmercm Mar 16, 2024
83d5b2d
Fix
emmercm Mar 16, 2024
c115554
Update
emmercm Mar 17, 2024
9a18709
Merge remote-tracking branch 'origin/main' into emmercm/file-factory-…
emmercm Mar 17, 2024
81ad036
Use timer
emmercm Mar 17, 2024
4e6f5e5
Feature: CHD support
emmercm Mar 18, 2024
0916ce2
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Mar 21, 2024
93a74f2
Merge fix
emmercm Mar 21, 2024
6515e72
Package only the needed chdman
emmercm Mar 21, 2024
d042d3f
Docs
emmercm Mar 23, 2024
a7bcf8b
Update
emmercm Mar 24, 2024
ac955c8
Update
emmercm Mar 24, 2024
65693f7
.gitignore
emmercm Mar 24, 2024
cd4db0d
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Mar 24, 2024
3b9854c
Parse GD-ROMs
emmercm Mar 24, 2024
b81a3b9
Fixes
emmercm Mar 25, 2024
a5d18d1
Tests
emmercm Mar 25, 2024
4f87ce4
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Mar 27, 2024
9b8785b
Merge fix
emmercm Mar 27, 2024
80c0e2c
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Apr 7, 2024
8ad88b1
Merge fix
emmercm Apr 7, 2024
de00e22
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Apr 7, 2024
df479c3
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Apr 7, 2024
1d1d256
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Apr 7, 2024
bd3d7fc
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Apr 13, 2024
ac4619a
Docs
emmercm May 8, 2024
3741230
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm May 9, 2024
2d5221f
Merge fix
emmercm May 9, 2024
7606d0e
Chd.SUPPORTED_FILES
emmercm May 9, 2024
40ad4d0
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Jul 21, 2024
9c13f14
Merge fix
emmercm Jul 21, 2024
00eae05
npm i
emmercm Jul 21, 2024
f2c06dc
Merge remote-tracking branch 'origin/main' into emmercm/chd
emmercm Jul 22, 2024
4fc6c1c
Test fixes
emmercm Jul 22, 2024
d211548
Merge branch 'emmercm/3.0.0-feature' into emmercm/chd
emmercm Jul 22, 2024
badc671
Test update
emmercm Jul 22, 2024
44b7b02
Bump chdman
emmercm Jul 22, 2024
f92de72
Update
emmercm Jul 22, 2024
c837805
.gitattributes?
emmercm Jul 23, 2024
58f4603
.gitattributes?
emmercm Jul 23, 2024
f90585b
.gitattributes
emmercm Jul 23, 2024
173d60c
GD-ROM.gdi
emmercm Jul 23, 2024
9556acb
Debug
emmercm Jul 23, 2024
9b14fa7
Debug
emmercm Jul 23, 2024
2df57cc
Debug
emmercm Jul 23, 2024
ed07510
Debug
emmercm Jul 23, 2024
4bef50e
Debug
emmercm Jul 23, 2024
6e3e2ec
macOS SDL2
emmercm Jul 23, 2024
c1c62ee
DEBUG
emmercm Jul 23, 2024
379b966
Debug
emmercm Jul 23, 2024
45ae97a
Ubuntu SDL2
emmercm Jul 23, 2024
e3a5092
Downgrade chdman
emmercm Jul 23, 2024
53a11f3
path.resolve
emmercm Jul 23, 2024
2aa1513
fail-fast: false
emmercm Jul 23, 2024
d909be6
Debug
emmercm Jul 23, 2024
d8d929e
Debug
emmercm Jul 23, 2024
b3cc613
Mutex
emmercm Jul 23, 2024
2e195b5
Mutex fix
emmercm Jul 23, 2024
0d0c95f
Debug
emmercm Jul 23, 2024
b771fc5
Test timeout 60sec
emmercm Jul 23, 2024
0be4a28
mkdir
emmercm Jul 23, 2024
bda9c36
Debug
emmercm Jul 23, 2024
83f15a3
Info mutex
emmercm Jul 23, 2024
b00f793
Debug
emmercm Jul 23, 2024
842513c
Debug
emmercm Jul 23, 2024
10e75bd
Debug
emmercm Jul 23, 2024
1d1fbde
Debug
emmercm Jul 23, 2024
6414474
Debug
emmercm Jul 23, 2024
fbb8913
Debug
emmercm Jul 23, 2024
f95aeca
Fix?
emmercm Jul 23, 2024
58b8d4a
Fix
emmercm Jul 23, 2024
bb1b40c
Reverts
emmercm Jul 23, 2024
d89c1b7
Revert
emmercm Jul 23, 2024
ca3b96f
Test fix
emmercm Jul 23, 2024
382a337
fail-fast: false
emmercm Jul 23, 2024
30bfcda
Icon update
emmercm Jul 23, 2024
eee2dc2
Debug
emmercm Jul 23, 2024
ad66b24
Debug
emmercm Jul 23, 2024
554b6e9
Debug
emmercm Jul 23, 2024
ec54606
Fix?
emmercm Jul 23, 2024
32318af
Debug
emmercm Jul 23, 2024
39850db
Debug
emmercm Jul 23, 2024
5aaaa30
Fix?
emmercm Jul 23, 2024
63d860d
Fix?
emmercm Jul 23, 2024
76468d8
Reverts
emmercm Jul 23, 2024
046e29d
Windows fix?
emmercm Jul 23, 2024
6a88d98
Update
emmercm Jul 25, 2024
8bed768
Windows test fix
emmercm Jul 26, 2024
fd9254c
Update
emmercm Jul 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Stop `core.autocrlf true`
*.lnx binary
*.nes binary
*.rom binary
test/fixtures/roms/** binary
*.cue text eol=lf
*.gdi text eol=crlf
3 changes: 3 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
- uses: actions/checkout@v4
- uses: volta-cli/action@v4
- run: npm ci
- run: |
sudo apt-get update
sudo apt-get install -y libsdl2-2.0-0 libsdl2-ttf-2.0-0
# Run test coverage
- run: npm run test:coverage
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/node-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- if: ${{ matrix.os == 'macos' }}
run: brew install --overwrite sdl2
- if: ${{ matrix.os == 'ubuntu' }}
run: |
sudo apt-get update
sudo apt-get install -y libsdl2-2.0-0 libsdl2-ttf-2.0-0
# Test the source files
- run: npm run test:unit

Expand All @@ -102,6 +109,9 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: |
sudo apt-get update
sudo apt-get install -y libsdl2-2.0-0 libsdl2-ttf-2.0-0
# Test the built files
- run: npm run build
- run: ./test/endToEndTest.sh
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ site/
*.bin
*.cd1
*.cd2
*.chd
*.col
*.cue
*.dvd
Expand All @@ -144,6 +145,7 @@ site/
*.pce
*.pk3
*.pup
*.raw
*.rom
*.rvz
*.sfc
Expand Down
2 changes: 1 addition & 1 deletion docs/alternatives.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ There are a few different popular ROM managers that have similar features:
| DATs: fixdat creation |[Fixdat docs](dats/fixdats.md) ||||
| DATs: combine multiple |||||
| Archives: extraction formats | ✅ many formats ([reading archives docs](input/reading-archives.md)) |`.zip`, `.7z`, `.rar` | ⚠️ `.zip`, `.7z` | ⚠️ `.zip`, `.7z` |
| Archives: `.chd` support | | ⚠️ via chdman | ✅ v1-5 natively | ⚠️ v1-4 natively |
| Archives: `.chd` support | ⚠️ via chdman (bundled) | ⚠️ via chdman | ✅ v1-5 natively | ⚠️ v1-4 natively |
| Archives: `.nkit.iso` support | ⚠️ matching but no extraction [GameCube docs](usage/console/gamecube.md#nkit) ||||
| Archives: creation formats |`.zip` only by design ([writing archives docs](output/writing-archives.md)) |`.zip`, `.7z`, `.rar` | ⚠️ `.zip` (TorrentZip), `.7z` | ⚠️ `.zip`, `.7z` |
| Archives: automatic extension correction |||||
Expand Down
25 changes: 13 additions & 12 deletions docs/input/reading-archives.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@

`igir` supports most common archive formats:

| Extension | Contains file CRC32s | `igir` can extract without a third-party binary | `igir` can checksum without temporary files |
|--------------------------------------------------------------|----------------------|-------------------------------------------------|---------------------------------------------|
| `.7z` ||||
| `.gz`, `.gzip` | ❌ CRC16 |||
| `.nkit` ([GameCube docs](../usage/console/gamecube.md#nkit)) || ❌ no extraction support ||
| `.rar` ||||
| `.tar` ||| ✅ ≤64MiB |
| `.tar.gz`, `.tgz` ||| ✅ ≤64MiB |
| `.z01` ||||
| `.zip` (including zip64) ||| ✅ ≤64MiB |
| `.zip.001` ||||
| `.zipx` ||||
| Extension | Contains file CRC32s | `igir` can extract without a third-party binary | `igir` can checksum without temporary files |
|------------------------------------------------------------------|----------------------|-------------------------------------------------|---------------------------------------------|
| `.7z` ||`7za` ||
| `.chd` | ❌ SHA1 |`chdman` ||
| `.gz`, `.gzip` | ❌ CRC16 |`7za` ||
| `.nkit.iso` ([GameCube docs](../usage/console/gamecube.md#nkit)) || ❌ no extraction support ||
| `.rar` ||||
| `.tar` ||| ✅ ≤64MiB |
| `.tar.gz`, `.tgz` ||| ✅ ≤64MiB |
| `.z01` ||`7za` ||
| `.zip` (including zip64) ||| ✅ ≤64MiB |
| `.zip.001` ||`7za` ||
| `.zipx` ||`7za` ||

**You should prefer archive formats that have CRC32 checksum information for each file.**

Expand Down
20 changes: 20 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
import fs from 'node:fs';
import path from 'node:path';

import { JestConfigWithTsJest } from 'ts-jest';

// Fix some bad package.json files that don't play well with ts-jest
[
// https://github.com/g-plane/cue/issues/1
'@gplane/cue',
].forEach((moduleName) => {
const modulePath = path.join('node_modules', moduleName);
const packagePath = path.join(modulePath, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packagePath).toString());

packageJson.main = packageJson.main
?? packageJson.exports['.'].import;
delete packageJson.exports;

fs.writeFileSync(packagePath, JSON.stringify(packageJson, undefined, 2));
});

const jestConfig: JestConfigWithTsJest = {
preset: 'ts-jest',
testEnvironment: 'node',

setupFilesAfterEnv: ['jest-extended/all'],
Expand Down
26 changes: 24 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@
"dependencies": {
"@fast-csv/format": "5.0.0",
"@fast-csv/parse": "5.0.0",
"@gplane/cue": "0.2.0",
"@node-rs/crc32": "1.10.3",
"7zip-min": "1.4.4",
"archiver": "7.0.1",
"async": "3.2.5",
"async-mutex": "0.5.0",
"chalk": "5.3.0",
"chdman": "0.267.2",
"class-transformer": "0.5.1",
"cli-progress": "3.12.0",
"fast-glob": "3.3.2",
Expand Down
3 changes: 3 additions & 0 deletions package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
return results;
};

(async (): Promise<void> => {

Check warning on line 45 in package.ts

View workflow job for this annotation

GitHub Actions / node-lint

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
const logger = new Logger(LogLevel.TRACE);

const argv = await yargs(process.argv.slice(2))
Expand Down Expand Up @@ -86,6 +86,9 @@
// Only include the exact 7zip-bin we need
{ exclude: 'node_modules/{**/,}7zip-bin/**/7z*' },
{ include: path7za },
// Only include the exact chdman bin we need
{ exclude: 'node_modules/{**/,}chdman/bin/*/*/chdman*' },
{ include: `node_modules/{**/,}chdman/bin/${process.platform}/${process.arch}/chdman*` },
]));
const includeSize = (await Promise.all([...include].map(async (file) => {
if (await FsPoly.isDirectory(file)) {
Expand Down
1 change: 1 addition & 0 deletions src/console/progressBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const ProgressBarSymbol = {
// Candidates
GENERATING: chalk.cyan('Σ'),
FILTERING: chalk.cyan('∆'),
EXTENSION_CORRECTION: chalk.cyan('.'),
HASHING: chalk.cyan('#'),
VALIDATING: chalk.cyan(process.platform === 'win32' ? '?' : '≟'),
COMBINING_ALL: chalk.cyan(process.platform === 'win32' ? 'U' : '∪'),
Expand Down
41 changes: 26 additions & 15 deletions src/modules/candidateExtensionCorrector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import DAT from '../types/dats/dat.js';
import Parent from '../types/dats/parent.js';
import ROM from '../types/dats/rom.js';
import ArchiveEntry from '../types/files/archives/archiveEntry.js';
import Chd from '../types/files/archives/chd/chd.js';
import FileSignature from '../types/files/fileSignature.js';
import Options, { FixExtension } from '../types/options.js';
import OutputFactory from '../types/outputFactory.js';
Expand Down Expand Up @@ -52,7 +53,7 @@ export default class CandidateExtensionCorrector extends Module {
.filter((romWithFiles) => this.romNeedsCorrecting(romWithFiles))
.length;
this.progressBar.logTrace(`${dat.getNameShort()}: correcting ${romsThatNeedCorrecting.toLocaleString()} output file extension${romsThatNeedCorrecting !== 1 ? 's' : ''}`);
await this.progressBar.setSymbol(ProgressBarSymbol.HASHING);
await this.progressBar.setSymbol(ProgressBarSymbol.EXTENSION_CORRECTION);
await this.progressBar.reset(romsThatNeedCorrecting);

const correctedParentsToCandidates = await this.correctExtensions(dat, parentsToCandidates);
Expand All @@ -62,6 +63,12 @@ export default class CandidateExtensionCorrector extends Module {
}

private romNeedsCorrecting(romWithFiles: ROMWithFiles): boolean {
const inputFile = romWithFiles.getInputFile();
if (inputFile instanceof ArchiveEntry && inputFile.getArchive() instanceof Chd) {
// Files within CHDs never need extension correction
return false;
}

return this.options.getFixExtension() === FixExtension.ALWAYS
|| (this.options.getFixExtension() === FixExtension.AUTO && (
!this.options.usingDats()
Expand Down Expand Up @@ -148,21 +155,25 @@ export default class CandidateExtensionCorrector extends Module {
this.progressBar.logTrace(`${dat.getNameShort()}: ${parent.getName()}: correcting extension for: ${romWithFiles.getInputFile()
.toString()}`);

await romWithFiles.getInputFile().createReadStream(async (stream) => {
const romSignature = await FileSignature.signatureFromFileStream(stream);
if (!romSignature) {
// No signature was found, so we can't perform any correction
return;
}

// ROM file signature found, use the appropriate extension
const { dir, name } = path.parse(correctedRom.getName());
const correctedRomName = path.format({
dir,
name: name + romSignature.getExtension(),
try {
await romWithFiles.getInputFile().createReadStream(async (stream) => {
const romSignature = await FileSignature.signatureFromFileStream(stream);
if (!romSignature) {
// No signature was found, so we can't perform any correction
return;
}

// ROM file signature found, use the appropriate extension
const { dir, name } = path.parse(correctedRom.getName());
const correctedRomName = path.format({
dir,
name: name + romSignature.getExtension(),
});
correctedRom = correctedRom.withName(correctedRomName);
});
correctedRom = correctedRom.withName(correctedRomName);
});
} catch (error) {
this.progressBar.logError(`${dat.getNameShort()}: failed to correct file extension for '${romWithFiles.getInputFile()}': ${error}`);
}

this.progressBar.removeWaitingMessage(waitingMessage);
await this.progressBar.incrementDone();
Expand Down
Loading
Loading