Skip to content

Commit

Permalink
Feature: no devices filter option (#476)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Jul 12, 2023
1 parent fbbe586 commit 51096a0
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 28 deletions.
8 changes: 8 additions & 0 deletions docs/rom-filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ This option is best used for collating all BIOS files across all consoles to one

Opposite of the above. This will filter out files that are not games.

### No MAME devices

```text
--no-device
```

Filters out [MAME devices](https://wiki.mamedev.org/index.php/MAME_Device_Basics). MAME devices typically represent physical devices, such as microcontrollers, video display controllers, sounds boards, and more. Many MAME devices don't have any associated ROM files.

### No unlicensed

```text
Expand Down
5 changes: 5 additions & 0 deletions src/modules/argumentsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ export default class ArgumentsParser {
type: 'boolean',
conflicts: ['only-bios'],
})
.option('no-device', {
group: groupRomFiltering,
description: 'Filter out MAME devices',
type: 'boolean',
})
.option('no-unlicensed', {
group: groupRomFiltering,
description: 'Filter out unlicensed ROMs',
Expand Down
1 change: 1 addition & 0 deletions src/modules/candidateFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export default class CandidateFilter extends Module {
this.regionNotAllowed(releaseCandidate),
this.options.getOnlyBios() && !game.isBios(),
this.options.getNoBios() && game.isBios(),
this.options.getNoDevice() && game.isDevice(),
this.options.getOnlyRetail() && !game.isRetail(),
this.options.getNoUnlicensed() && game.isUnlicensed(),
this.options.getNoDemo() && game.isDemo(),
Expand Down
9 changes: 9 additions & 0 deletions src/types/logiqx/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface GameProps {
readonly description?: string,
readonly sourceFile?: string,
readonly bios?: 'yes' | 'no',
readonly device?: 'yes' | 'no',
readonly cloneOf?: string,
readonly romOf?: string,
readonly sampleOf?: string,
Expand All @@ -58,6 +59,9 @@ export default class Game implements GameProps {
@Expose({ name: 'isbios' })
readonly bios: 'yes' | 'no' = 'no';

@Expose({ name: 'isdevice' })
readonly device: 'yes' | 'no' = 'no';

@Expose({ name: 'cloneof' })
readonly cloneOf?: string;

Expand All @@ -79,6 +83,7 @@ export default class Game implements GameProps {
this.name = options?.name || '';
this.description = options?.description || '';
this.bios = options?.bios || this.bios;
this.device = options?.device || this.device;
this.cloneOf = options?.cloneOf;
this.romOf = options?.romOf;
this.sampleOf = options?.sampleOf;
Expand Down Expand Up @@ -110,6 +115,10 @@ export default class Game implements GameProps {
return this.bios === 'yes' || this.name.match(/\[BIOS\]/i) !== null;
}

isDevice(): boolean {
return this.device === 'yes';
}

getReleases(): Release[] {
if (Array.isArray(this.release)) {
return this.release;
Expand Down
8 changes: 8 additions & 0 deletions src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export interface OptionsProps {
readonly regionFilter?: string[],
readonly onlyBios?: boolean,
readonly noBios?: boolean,
readonly noDevice?: boolean,
readonly noUnlicensed?: boolean,
readonly onlyRetail?: boolean,
readonly noDemo?: boolean,
Expand Down Expand Up @@ -147,6 +148,8 @@ export default class Options implements OptionsProps {

readonly noBios: boolean;

readonly noDevice: boolean;

readonly noUnlicensed: boolean;

readonly onlyRetail: boolean;
Expand Down Expand Up @@ -234,6 +237,7 @@ export default class Options implements OptionsProps {
this.regionFilter = options?.regionFilter || [];
this.onlyBios = options?.onlyBios || false;
this.noBios = options?.noBios || false;
this.noDevice = options?.noDevice || false;
this.noUnlicensed = options?.noUnlicensed || false;
this.onlyRetail = options?.onlyRetail || false;
this.noDemo = options?.noDemo || false;
Expand Down Expand Up @@ -804,6 +808,10 @@ export default class Options implements OptionsProps {
return this.noBios;
}

getNoDevice(): boolean {
return this.noDevice;
}

getNoUnlicensed(): boolean {
return this.noUnlicensed;
}
Expand Down
44 changes: 44 additions & 0 deletions test/fixtures/dats/one.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0"?>
<!DOCTYPE datafile PUBLIC "-//Logiqx//DTD ROM Management Datafile//EN" "http://www.logiqx.com/Dats/datafile.dtd">
<datafile>
<header>
<name>One</name>
<description>One</description>
<version>20220705</version>
<author>emmercm</author>
</header>
<machine name="Empty">
<description>Empty</description>
<rom name="Empty.rom" size="0" crc="00000000" md5="d41d8cd98f00b204e9800998ecf8427e" sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709" status="verified"/>
<rom name="Missing.rom" size="0" crc="ffffffff" md5="8ead518f69f2e6c4b92e68a89a056d68" sha1="d6487ef2e2c46d33cb46fdf891334331d6f6af1e" status="verified"/>
</machine>
<machine name="Foobar">
<description>Foobar</description>
<release name="Foobar" region="USA"/>
<rom name="Foobar.lnx" size="7" crc="b22c9747" md5="14758f1afd44c09b7992073ccf00b43d" sha1="988881adc9fc3655077dc2d4d757d480b5ea0e11" status="verified"/>
</machine>
<machine name="Fizzbuzz">
<description>Fizzbuzz</description>
<release name="Fizzbuzz" region="EUR"/>
<rom name="Fizzbuzz.nes" size="9" crc="370517b5" md5="cbe8410861130a91609295349918c2c2" sha1="5a316d9f0e06964d94cdd62a933803d7147ddadb" status="verified"/>
</machine>
<machine name="Lorem Ipsum">
<description>Lorem Ipsum</description>
<release name="Lorem Ipsum" region="JPN"/>
<rom name="Lorem Ipsum.rom" size="11" crc="70856527" md5="fffcb698d88fbc9425a636ba7e4712a3" sha1="1d913738eb363a4056c19e158aa81189a1eb7a55" status="verified"/>
</machine>
<machine name="One Three">
<description>One Three</description>
<rom name="One.rom" size="4" crc="f817a89f" md5="5bbf5a52328e7439ae6e719dfe712200" sha1="c7059bb19433cc3cabaa6236c83d56668a843dd2" status="verified"/>
<rom name="Three.rom" size="6" crc="ff46c5d8" md5="febe6995bad457991331348f7b9c85fa" sha1="1e7720a3460b8a84ac4ba27880d64526a3872f1c" status="verified"/>
</machine>
<machine name="Three Four Five">
<description>Three Four Five</description>
<rom name="Three.rom" size="6" crc="ff46c5d8" md5="febe6995bad457991331348f7b9c85fa" sha1="1e7720a3460b8a84ac4ba27880d64526a3872f1c" status="verified"/>
<rom name="Four.rom" size="5" crc="1cf3ca74" md5="75ffdb827341e578959bfcabde3789d8" sha1="4a4121ecd766ed16943a0c7b54c18f743e90c3f6" status="verified"/>
<rom name="Five.rom" size="5" crc="3e5daf67" md5="014835e36358e38c7f7897d6571e4529" sha1="4430bb02f6ed700d4408eb307b25f8b1a25d93de" status="verified"/>
</machine>
<machine name="Device" isdevice="yes">
<description>Device</description>
</machine>
</datafile>
Binary file removed test/fixtures/dats/one.zip
Binary file not shown.
36 changes: 18 additions & 18 deletions test/fixtures/dats/patchable.dat
Original file line number Diff line number Diff line change
Expand Up @@ -9,63 +9,63 @@
</header>

<!-- APS (GBA) -->
<machine name="92C85C9">
<game name="92C85C9">
<description>92C85C9</description>
<rom name="92C85C9.rom" size="65536" crc="06692159" md5="8e0caf88ba437cb7109c5642e06cfdb2" sha1="8335c4505380035c2fa94e2a1b9e69517e746905" status="verified"/>
<!-- After: size="65536" crc="b13eb478" -->
</machine>
</game>
<!-- APS (N64 SIMPLE) -->
<machine name="3708F2C">
<game name="3708F2C">
<description>3708F2C</description>
<rom name="3708F2C.rom" size="1025" crc="20891c9f" md5="b191e2d913681475ef6a579d4b40bb1f" sha1="181e0713260060fa7d6c64292902023ca7c88a06" status="verified"/>
<!-- After: size="1025" crc="caaaf550" -->
</machine>
</game>

<!-- IPS -->
<machine name="Before">
<game name="Before">
<description>Before</description>
<rom name="Before.rom" size="7" crc="0361b321" md5="ab8d71b3fdce92efd8bdf29cffd36116" sha1="7473def7220a59a6b4146e629064e1456542242d" status="verified"/>
<!-- After: size="7" crc="4c8e44d4" -->
</machine>
</game>
<!-- IPS32 -->
<machine name="65D1206">
<game name="65D1206">
<description>65D1206</description>
<rom name="65D1206.rom" size="1025" crc="20323455" md5="5ab0c664d1ed83757fbe49e99c509cb0" sha1="31306e0f014d3ac2c24d2abede5f9a67c097c5e7" status="verified"/>
<!-- After: size=1025" crc="8bb5cc63" -->
</machine>
</game>

<!-- BPS -->
<machine name="Best">
<game name="Best">
<description>Best</description>
<rom name="Best.rom" size="25" crc="1e3d78cf" md5="5212c8404bf1de024f9fb62289b68474" sha1="727d8db3dbfb5960057cb62e8b47d0e2842a4d55" status="verified"/>
<!-- After: size="26" crc="6ff9ef96" -->
</machine>
</game>

<!-- NINJA2 -->
<machine name="612644F">
<game name="612644F">
<description>612644F</description>
<rom name="612644F.rom" size="1025" crc="f7591b29" md5="92c62becd006bac8175304bb80dfb3aa" sha1="2bcd0216e1de4ee670ee4945d600beaf6acf8feb" status="verified"/>
<!-- After: size="1025" crc="922f5181" -->
</machine>
</game>

<!-- PPF -->
<machine name="C01173E">
<game name="C01173E">
<description>C01173E</description>
<rom name="C01173E.rom" size="1025" crc="dfaebe28" md5="c9e35aafaec606fcb16763200ce35b0f" sha1="2f185826482db2878663c0cd393d62d0c10814ae" status="verified"/>
<!-- After: size="1025" crc="95284ab4" -->
</machine>
</game>

<!-- UPS -->
<machine name="KDULVQN">
<game name="KDULVQN">
<description>KDULVQN</description>
<rom name="KDULVQN.rom" size="1025" crc="b1c303e4" md5="36109a5d2f9041b6ec00d7aea63379f3" sha1="6bc1e23ffaf5fafaf03fb10732b6be3b567b1417" status="verified"/>
<!-- After: size="1025" crc="e02c6dbb" -->
</machine>
</game>

<!-- vcdiff -->
<machine name="0F09A40">
<game name="0F09A40">
<description>0F09A40</description>
<rom name="0F09A40.rom" size="1025" crc="2f943e86" md5="02784c56583f4d82d11aec4c57f2859c" sha1="7b5b3998062b8338324b5f69ffcdcc22087ccbd5" status="verified"/>
<!-- After: size="1025" crc="1fb4f81f" -->
</machine>
</game>
</datafile>
6 changes: 0 additions & 6 deletions test/fixtures/dats/smdb.txt

This file was deleted.

Binary file added test/fixtures/dats/smdb.zip
Binary file not shown.
10 changes: 10 additions & 0 deletions test/modules/argumentsParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ describe('options', () => {
expect(options.getRegionFilter()).toHaveLength(0);
expect(options.getOnlyBios()).toEqual(false);
expect(options.getNoBios()).toEqual(false);
expect(options.getNoDevice()).toEqual(false);
expect(options.getNoUnlicensed()).toEqual(false);
expect(options.getOnlyRetail()).toEqual(false);
expect(options.getNoDemo()).toEqual(false);
Expand Down Expand Up @@ -499,6 +500,15 @@ describe('options', () => {
expect(() => argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-bios', '--only-bios'])).toThrow(/mutually exclusive/i);
});

it('should parse "no-device"', () => {
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device']).getNoDevice()).toEqual(true);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device', 'true']).getNoDevice()).toEqual(true);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device', 'false']).getNoDevice()).toEqual(false);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device', '--no-device']).getNoDevice()).toEqual(true);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device', 'false', '--no-device', 'true']).getNoDevice()).toEqual(true);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-device', 'true', '--no-device', 'false']).getNoDevice()).toEqual(false);
});

it('should parse "no-unlicensed"', () => {
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-unlicensed']).getNoUnlicensed()).toEqual(true);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--no-unlicensed', 'true']).getNoUnlicensed()).toEqual(true);
Expand Down
34 changes: 33 additions & 1 deletion test/modules/candidateFilter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ describe('preFilter', () => {
it('should return no candidates if none matching', async () => {
await expectFilteredCandidates({ noBios: true }, [
await buildReleaseCandidatesWithRegionLanguage('one', 'USA', 'EN', { bios: 'yes' }),
await buildReleaseCandidatesWithRegionLanguage('two', 'USA', 'EN', { bios: 'yes' }),
await buildReleaseCandidatesWithRegionLanguage('two [BIOS]', 'USA', 'EN', { bios: 'no' }),
], 0);
});

Expand All @@ -459,6 +459,38 @@ describe('preFilter', () => {
});
});

describe('no device', () => {
it('should return all candidates when option is false', async () => {
await expectFilteredCandidates({ noDevice: false }, [
await buildReleaseCandidatesWithRegionLanguage('one', 'USA', 'EN', { device: 'no' }),
await buildReleaseCandidatesWithRegionLanguage('two', 'USA', 'EN', { device: 'yes' }),
await buildReleaseCandidatesWithRegionLanguage('three', 'USA', 'EN', { device: 'no' }),
], 3);
});

it('should return no candidates if none matching', async () => {
await expectFilteredCandidates({ noDevice: true }, [
await buildReleaseCandidatesWithRegionLanguage('one', 'USA', 'EN', { device: 'yes' }),
await buildReleaseCandidatesWithRegionLanguage('two', 'USA', 'EN', { device: 'yes' }),
], 0);
});

it('should return some candidates if some matching', async () => {
await expectFilteredCandidates({ noDevice: true }, [
await buildReleaseCandidatesWithRegionLanguage('one', 'USA', 'EN', { device: 'no' }),
await buildReleaseCandidatesWithRegionLanguage('two', 'USA', 'EN', { device: 'yes' }),
await buildReleaseCandidatesWithRegionLanguage('three', 'USA', 'EN', { device: 'no' }),
], 2);
});

it('should return all candidates if all matching', async () => {
await expectFilteredCandidates({ noDevice: true }, [
await buildReleaseCandidatesWithRegionLanguage('one', 'USA', 'EN', { device: 'no' }),
await buildReleaseCandidatesWithRegionLanguage('two', 'USA', 'EN', { device: 'no' }),
], 2);
});
});

describe('no unlicensed', () => {
it('should return all candidates when option is false', async () => {
await expectFilteredCandidates({ noUnlicensed: false }, [
Expand Down
6 changes: 3 additions & 3 deletions test/modules/datScanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('multiple files', () => {
});

it('some files are path excluded', async () => {
await expect(createDatScanner(['test/fixtures/dats'], ['test/fixtures/**/*.dat']).scan()).resolves.toHaveLength(2);
await expect(createDatScanner(['test/fixtures/dats'], ['test/fixtures/**/*.dat']).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/dats'], ['test/fixtures/**/*.zip']).scan()).resolves.toHaveLength(4);
});

Expand Down Expand Up @@ -91,6 +91,6 @@ describe('multiple files', () => {
it('should scan single files', async () => {
await expect(createDatScanner([path.join(path.resolve(), 'test', 'fixtures', 'dats', 'one.*')]).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/dats/one.*']).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/*/one.zip']).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/dats/one.zip']).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/*/one.dat']).scan()).resolves.toHaveLength(1);
await expect(createDatScanner(['test/fixtures/dats/one.dat']).scan()).resolves.toHaveLength(1);
});

0 comments on commit 51096a0

Please sign in to comment.