Skip to content

Commit

Permalink
Feature: Output token funkeyos (#786)
Browse files Browse the repository at this point in the history
Co-authored-by: Julia Mono Brunenberg <[email protected]>
Co-authored-by: Christian Emmer <[email protected]>
  • Loading branch information
3 people authored Oct 28, 2023
1 parent 57577b8 commit df19a61
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ Advanced usage:
{onion} The ROM's emulator-specific /Roms/* directory for OnionOS/GarlicOS (e.g. "GB")
{batocera} The ROM's emulator-specific /roms/* directory for Batocera (e.g. "gb")
{jelos} The ROM's emulator-specific /roms/* directory for JELOS (e.g. "gb")
{funkeyos} The ROM's emulator-specific /* directory for FunKey OS (e.g. "Game Boy")
Example use cases:
Expand Down
1 change: 1 addition & 0 deletions docs/output/tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ To help sort ROMs into unique file structures for popular frontends & hardware,
- `{mister}` the [MiSTer FPGA](../usage/hardware/mister.md) core's directory for the ROM
- `{onion}` the [OnionOS / GarlicOS](../usage/handheld/onionos.md) emulator's directory for the ROM
- `{batocera}` the [Batocera](../usage/desktop/batocera.md) emulator's directory for the ROM
- `{funkeyos}` the [FunKey OS](../usage/handheld/funkeyos.md) emulator's directory for the ROM

!!! tip

Expand Down
59 changes: 59 additions & 0 deletions docs/usage/handheld/funkeyos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# FunKey OS

!!! info

[FunKey OS](https://github.com/FunKey-Project/FunKey-OS) is a Retro Emulation OS for the [FunKey S](https://www.funkey-project.com/) handheld. It is also used on the [Anbernic RG Nano](https://anbernic.com/products/rg-nano). It is not very well documented which consoles are supported on which device. The `funkeyos` tag should handle systems supported by either of those handhelds.

[FunKey OS](https://github.com/FunKey-Project/FunKey-OS) is a minimalistic buildroot based Linux distribution originally designed for the tiny ARM based [FunKey S](https://www.funkey-project.com/) handheld. It is also used on the [Anbernic RG Nano](https://anbernic.com/products/rg-nano) with a few modifications.

## BIOS

FunKey OS ships with most emulators not needing BIOS files. Two notable exceptions are the GBA BIOS as well as the PS1 BIOS. These can be [installed manually](https://doc.funkey-project.com/user_manual/tutorials/software/gba_bios/). Only two files are needed, so automating the task might be more work than copying them across.

To sum up the documentation, two files need to be copied:

* `gba_bios.bin` (MD5 hash `a860e8c0b6d573d191e4ec7db1b1e4f6`) to `<sdcard>/Game Boy Advance` for the GBA BIOS
* `SCPH1001.BIN` (512kib in size) to `<sdcard>/PS1` of the card for the PS1 BIOS

## ROMs

Funkey OS uses its own proprietary [ROM folder structure](https://github.com/FunKey-Project/FunKey-OS/tree/master/FunKey/board/funkey/rootfs-overlay/usr/games/collections) based in the root of the SD card, so `igir` has a replaceable `{funkeyos}` token to sort ROMs into the right place. See the [replaceable tokens page](../../output/tokens.md) for more information.

=== ":simple-windowsxp: Windows"

Replace the `E:\` drive letter with wherever your SD card is:

```batch
igir copy extract test clean ^
--dat "No-Intro*.zip" ^
--input ROMs\ ^
--output "E:\{funkeyos}" ^
--dir-letter ^
--no-bios
```

=== ":simple-apple: macOS"

Replace the `/Volumes/FunKeyS` drive name with whatever your SD card is named:

```shell
igir copy extract test clean \
--dat "No-Intro*.zip" \
--input ROMs/ \
--output "/Volumes/FunKeyS/{funkeyos}" \
--dir-letter \
--no-bios
```

=== ":simple-linux: Linux"

Replace the `/media/FunKeyS` path with wherever your SD card is mounted:

```shell
igir copy extract test clean \
--dat "No-Intro*.zip" \
--input ROMs/ \
--output "/media/FunKeyS/{funkeyos}" \
--dir-letter \
--no-bios
```
1 change: 1 addition & 0 deletions src/modules/argumentsParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@ Advanced usage:
{onion} The ROM's emulator-specific /Roms/* directory for OnionOS/GarlicOS (e.g. "GB")
{batocera} The ROM's emulator-specific /roms/* directory for Batocera (e.g. "gb")
{jelos} The ROM's emulator-specific /roms/* directory for JELOS (e.g. "gb")
{funkeyos} The ROM's emulator-specific /Roms* directory for FunKey OS (e.g. "Game Boy")
Example use cases:
Expand Down
27 changes: 27 additions & 0 deletions src/types/gameConsole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ interface OutputTokens {
// JELOS ROMs go in the ??? directory:
// @see https://github.com/JustEnoughLinuxOS/distribution/blob/main/documentation/PER_DEVICE_DOCUMENTATION/AMD64/SUPPORTED_EMULATORS_AND_CORES.md
jelos?: string,

// FunKey S ROMs go into the subfolder of / for the console:
// @see https://github.com/FunKey-Project/FunKey-OS/tree/master/FunKey/board/funkey/rootfs-overlay/usr/games/collections
funkeyos?: string,
}

/**
Expand Down Expand Up @@ -102,6 +106,7 @@ export default class GameConsole {
onion: 'LYNX',
batocera: 'lynx',
jelos: 'atarilynx',
funkeyos: 'Atari lynx',
}),
new GameConsole(/Atari.*ST/i, ['.msa', '.st', '.stx'], {
mister: 'AtariST',
Expand All @@ -127,13 +132,15 @@ export default class GameConsole {
onion: 'WS',
batocera: 'wswan',
jelos: 'wonderswan',
funkeyos: 'WonderSwan',
}),
new GameConsole(/WonderSwan Color/i, ['.wsc'], {
pocket: 'wonderswan',
mister: 'WonderSwan',
onion: 'WS',
batocera: 'wswanc',
jelos: 'wonderswancolor',
funkeyos: 'WonderSwan',
}),
// Bit Corporation
new GameConsole(/Gamate/i, [/* '.bin' */], {
Expand Down Expand Up @@ -286,6 +293,7 @@ export default class GameConsole {
onion: 'PCE',
batocera: 'pcengine',
jelos: 'tg16',
funkeyos: 'PCE-TurboGrafx',
}),
new GameConsole(/(PC Engine|TurboGrafx) CD/i, [/* '.bin', '.cue' */], {
pocket: 'pcecd',
Expand Down Expand Up @@ -319,6 +327,7 @@ export default class GameConsole {
onion: 'FDS',
batocera: 'fds',
jelos: 'fds',
funkeyos: 'NES',
}),
new GameConsole(/Game (and|&) Watch/i, ['.mgw'], {
mister: 'GameNWatch',
Expand All @@ -336,20 +345,23 @@ export default class GameConsole {
onion: 'GB',
batocera: 'gb',
jelos: 'gb',
funkeyos: 'Game Boy',
}), // pocket:sgb for spiritualized1997
new GameConsole(/GBA|Game ?Boy Advance/i, ['.gba', '.srl'], {
pocket: 'gba',
mister: 'GBA',
onion: 'GBA',
batocera: 'gba',
jelos: 'gba',
funkeyos: 'Game Boy Advance',
}),
new GameConsole(/GBC|Game ?Boy Color/i, ['.gbc'], {
pocket: 'gbc',
mister: 'Gameboy',
onion: 'GBC',
batocera: 'gbc',
jelos: 'gbc',
funkeyos: 'Game Boy Color',
}),
new GameConsole(/Nintendo 64|N64/i, ['.n64', '.v64', '.z64'], {
mister: 'N64',
Expand All @@ -373,13 +385,15 @@ export default class GameConsole {
onion: 'FC',
batocera: 'nes',
jelos: 'nes',
funkeyos: 'NES',
}),
new GameConsole(/Pokemon Mini/i, ['.min'], {
pocket: 'poke_mini',
mister: 'PokemonMini',
onion: 'POKE',
batocera: 'pokemini',
jelos: 'pokemini',
funkeyos: 'Pokemini',
}),
new GameConsole(/Satellaview/i, ['.bs'], {
pocket: 'snes',
Expand All @@ -399,11 +413,13 @@ export default class GameConsole {
onion: 'SFC',
batocera: 'snes',
jelos: 'snes',
funkeyos: 'SNES',
}),
new GameConsole(/Virtual Boy/i, ['.vb', '.vboy'], {
onion: 'VB',
batocera: 'virtualboy',
jelos: 'virtualboy',
funkeyos: 'Virtualboy',
}),
new GameConsole(/Wii/i, [/* '.iso' */], {
batocera: 'wii',
Expand Down Expand Up @@ -450,13 +466,15 @@ export default class GameConsole {
onion: 'GG',
batocera: 'gamegear',
jelos: 'gamegear',
funkeyos: 'Game Gear',
}),
new GameConsole(/Master System/i, ['.sms'], {
pocket: 'sms',
mister: 'SMS',
onion: 'MS',
batocera: 'mastersystem',
jelos: 'mastersystem',
funkeyos: 'Sega Master System',
}),
new GameConsole(/(Mega|Sega) CD/i, [/* '.bin', '.cue' */], {
mister: 'MegaCD',
Expand All @@ -470,6 +488,7 @@ export default class GameConsole {
onion: 'MD',
batocera: 'megadrive',
jelos: 'genesis',
funkeyos: 'Sega Genesis',
}),
new GameConsole(/Saturn/i, [/* '.bin', '.cue' */], {
batocera: 'saturn',
Expand Down Expand Up @@ -519,6 +538,7 @@ export default class GameConsole {
onion: 'NEOGEO',
batocera: 'neogeo',
jelos: 'neogeo',
funkeyos: 'Neo Geo Pocket',
}),
new GameConsole(/Neo ?Geo CD/i, [/* '.bin', '.cue' */], {
onion: 'NEOCD',
Expand All @@ -529,18 +549,21 @@ export default class GameConsole {
onion: 'NGP',
batocera: 'ngp',
jelos: 'ngp',
funkeyos: 'Neo Geo Pocket',
}),
new GameConsole(/Neo ?Geo Pocket Color/i, ['.ngc'], {
onion: 'NGP',
batocera: 'ngpc',
jelos: 'ngpc',
funkeyos: 'Neo Geo Pocket',
}),
// Sony
new GameConsole(/PlayStation|psx/i, [/* '.bin', '.cue' */], {
mister: 'PSX',
onion: 'PS',
batocera: 'psx',
jelos: 'psx',
funkeyos: 'PS1',
}),
new GameConsole(/PlayStation 2|ps2/i, [/* '.bin', '.cue' */], {
batocera: 'ps2',
Expand Down Expand Up @@ -636,4 +659,8 @@ export default class GameConsole {
getJelos(): string | undefined {
return this.outputTokens.jelos;
}

getFunkeyOS(): string | undefined {
return this.outputTokens.funkeyos;
}
}
5 changes: 5 additions & 0 deletions src/types/outputFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ export default class OutputFactory {
if (jelos) {
output = output.replace('{jelos}', jelos);
}

const funkeyos = gameConsole.getFunkeyOS();
if (funkeyos) {
output = output.replace('{funkeyos}', funkeyos);
}
return output;
}

Expand Down
65 changes: 65 additions & 0 deletions test/outputFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,71 @@ describe('token replacement', () => {
)).rejects.toThrow(/failed to replace/);
},
);

test.each([
['game.lnx', path.join('', 'Atari lynx', 'game.lnx')],
['game.ws', path.join('', 'WonderSwan', 'game.ws')],
['game.wsc', path.join('', 'WonderSwan', 'game.wsc')],
['game.pce', path.join('', 'PCE-TurboGrafx', 'game.pce')],
['game.fds', path.join('', 'NES', 'game.fds')],
['game.gb', path.join('', 'Game Boy', 'game.gb')],
['game.gba', path.join('', 'Game Boy Advance', 'game.gba')],
['game.gbc', path.join('', 'Game Boy Color', 'game.gbc')],
['game.nes', path.join('', 'NES', 'game.nes')],
['game.nez', path.join('', 'NES', 'game.nez')],
['game.min', path.join('', 'Pokemini', 'game.min')],
['game.sfc', path.join('', 'SNES', 'game.sfc')],
['game.smc', path.join('', 'SNES', 'game.smc')],
['game.vb', path.join('', 'Virtualboy', 'game.vb')],
['game.gg', path.join('', 'Game Gear', 'game.gg')],
['game.sms', path.join('', 'Sega Master System', 'game.sms')],
['game.gen', path.join('', 'Sega Genesis', 'game.gen')],
['game.md', path.join('', 'Sega Genesis', 'game.md')],
['game.mdx', path.join('', 'Sega Genesis', 'game.mdx')],
['game.sgd', path.join('', 'Sega Genesis', 'game.sgd')],
['game.smd', path.join('', 'Sega Genesis', 'game.smd')],
['game.ngp', path.join('', 'Neo Geo Pocket', 'game.ngp')],
['game.ngc', path.join('', 'Neo Geo Pocket', 'game.ngc')],
])(
'should replace {funkeyos} for known extension: %s',
async (outputRomFilename, expectedPath) => {
const options = new Options({ commands: ['copy'], output: '{funkeyos}' });
const rom = new ROM({ name: outputRomFilename, size: 0, crc: '' });

const outputPath = OutputFactory.getPath(
options,
dummyDat,
dummyGame,
dummyRelease,
rom,
await rom.toFile(),
);
expect(outputPath.format()).toEqual(expectedPath);
},
);

test.each([
'game.bin',
'game.rom',
// satellaview is not supported by https://github.com/FunKey-Project/FunKey-OS/blob/master/FunKey/board/funkey/rootfs-overlay/usr/games/collections/SNES/settings.conf
'game.bs',
])(
'should throw on {funkeyos} for unknown extension: %s',
async (outputRomFilename) => {
const options = new Options({ commands: ['copy'], output: 'roms/{funkeyos}' });

const rom = new ROM({ name: outputRomFilename, size: 0, crc: '' });

await expect(async () => OutputFactory.getPath(
options,
dummyDat,
dummyGame,
dummyRelease,
rom,
await rom.toFile(),
)).rejects.toThrow(/failed to replace/);
},
);
});

describe('should respect "--dir-mirror"', () => {
Expand Down

0 comments on commit df19a61

Please sign in to comment.