Skip to content

Commit

Permalink
Feature: {gameType} output token (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmercm authored Jul 27, 2023
1 parent a5bad6a commit 6f842c3
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/modules/argumentsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ Advanced usage:
{datName} The name of the DAT that contains the ROM (e.g. "Nintendo - Game Boy")
{datReleaseRegion} The region of the ROM release (e.g. "USA"), each ROM can have multiple
{datReleaseLanguage} The language of the ROM release (e.g. "En"), each ROM can have multiple
{gameType} The type of the game (e.g. "Retail", "Demo", "Prototype")
{inputDirname} The input file's dirname
{outputBasename} Equivalent to "{outputName}.{outputExt}"
Expand Down
72 changes: 72 additions & 0 deletions src/types/logiqx/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@ import Release from './release.js';
import ROM from './rom.js';
import Sample from './sample.js';

enum GameType {
AFTERMARKET = 'Aftermarket',
ALPHA = 'Alpha',
BAD = 'Bad',
BETA = 'Beta',
BIOS = 'BIOS',
DEMO = 'Demo',
DEVICE = 'Device',
FIXED = 'Fixed',
HACKED = 'Hacked',
HOMEBREW = 'Homebrew',
OVERDUMP = 'Overdump',
PENDING_DUMP = 'Pending Dump',
PIRATED = 'Pirated',
PROTOTYPE = 'Prototype',
RETAIL = 'Retail',
SAMPLE = 'Sample',
TEST = 'Test',
TRAINED = 'Trained',
TRANSLATED = 'Translated',
UNLICENSED = 'Unlicensed',
}

/**
* "There are two 'semi-optional' fields that can be included for each game;
* 'year' and 'manufacturer'. However, CMPro displays the manufacturer in the
Expand Down Expand Up @@ -254,6 +277,55 @@ export default class Game implements GameProps {
&& !this.hasTrainer();
}

getGameType(): GameType {
// NOTE(cemmer): priority here matters!
if (this.isBios()) {
return GameType.BIOS;
} if (this.isVerified()) {
return GameType.RETAIL;
}

if (this.isAftermarket()) {
return GameType.AFTERMARKET;
} if (this.isAlpha()) {
return GameType.ALPHA;
} if (this.isBad()) {
return GameType.BAD;
} if (this.isBeta()) {
return GameType.BETA;
} if (this.isDemo()) {
return GameType.DEMO;
} if (this.isDevice()) {
return GameType.DEVICE;
} if (this.isFixed()) {
return GameType.FIXED;
} if (this.hasHack()) {
return GameType.HACKED;
} if (this.isHomebrew()) {
return GameType.HOMEBREW;
} if (this.isOverdump()) {
return GameType.OVERDUMP;
} if (this.isPendingDump()) {
return GameType.PENDING_DUMP;
} if (this.isPirated()) {
return GameType.PIRATED;
} if (this.isPrototype()) {
return GameType.PROTOTYPE;
} if (this.isSample()) {
return GameType.SAMPLE;
} if (this.isTest()) {
return GameType.TEST;
} if (this.hasTrainer()) {
return GameType.TRAINED;
} if (this.isTranslated()) {
return GameType.TRANSLATED;
} if (this.isUnlicensed()) {
return GameType.UNLICENSED;
}

return GameType.RETAIL;
}

isParent(): boolean {
return !this.isClone();
}
Expand Down
13 changes: 13 additions & 0 deletions src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export default class Options implements OptionsProps {
output,
dat,
inputRomPath,
game,
release,
romFilenameSanitized,
);
Expand Down Expand Up @@ -703,11 +704,13 @@ export default class Options implements OptionsProps {
outputPath: string,
dat: DAT,
inputRomPath?: string,
game?: Game,
release?: Release,
outputRomFilename?: string,
): string {
let result = outputPath;
result = this.replaceDatTokens(result, dat);
result = this.replaceGameTokens(result, game);
result = this.replaceReleaseTokens(result, release);
result = this.replaceInputTokens(result, inputRomPath);
result = this.replaceOutputTokens(result, outputRomFilename);
Expand All @@ -725,6 +728,16 @@ export default class Options implements OptionsProps {
return input.replace('{datName}', dat.getName().replace(/[\\/]/g, '_'));
}

private static replaceGameTokens(input: string, game?: Game): string {
if (!game) {
return input;
}

let output = input;
output = output.replace('{gameType}', game.getGameType());
return output;
}

private static replaceReleaseTokens(input: string, release?: Release): string {
if (!release) {
return input;
Expand Down
33 changes: 33 additions & 0 deletions test/types/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,39 @@ describe('getOutputFileParsed', () => {
expect(new Options({ commands: ['copy'], output }).getOutputFileParsed(dat, dummyInputRomPath, dummyGame, release, 'game.rom')).toEqual(expectedPath);
});

test.each([
// Highest priority
['Game [BIOS]', 'BIOS'],
['Game [!]', 'Retail'],
// No particular priority
['Game (Aftermarket)', 'Aftermarket'],
['Game (Alpha)', 'Alpha'],
['Game [b]', 'Bad'],
['Game (Beta)', 'Beta'],
['Game (Demo)', 'Demo'],
['Game [f]', 'Fixed'],
['Game (Hack)', 'Hacked'],
['Game [h]', 'Hacked'],
['Game (Homebrew)', 'Homebrew'],
['Game [o]', 'Overdump'],
['Game [!p]', 'Pending Dump'],
['Game [p]', 'Pirated'],
['Game (Pirate)', 'Pirated'],
['Game (Proto)', 'Prototype'],
['Game (Sample)', 'Sample'],
['Game (Test)', 'Test'],
['Game [t]', 'Trained'],
['Game [T+Eng]', 'Translated'],
['Game (Unl)', 'Unlicensed'],
// Default
['Game', 'Retail'],
])('should replace {gameType}: %s', (gameName, expectedPath) => {
const game = new Game({ name: gameName });
const outputFileParsed = new Options({ commands: ['copy'], output: '{gameType}' }).getOutputFileParsed(dummyDat, dummyInputRomPath, game, dummyRelease, 'dummy.rom');
const outputDirname = path.dirname(outputFileParsed);
expect(outputDirname).toEqual(expectedPath);
});

test.each([
['{inputDirname}', path.join('path', 'to', 'game.rom')],
])('should replace {input*}: %s', (output, expectedPath) => {
Expand Down

0 comments on commit 6f842c3

Please sign in to comment.