Code Monkey home page Code Monkey logo

romm's Introduction

romm logo

A beautiful, powerful, self-hosted rom manager.


license-badge release-badge docker-pulls-badge

discord-badge unraid-badge wiki-badge

Warning

Version 3.0 introduces exciting new fetures that require some changes to how RomM is setup and configured. If you're currently running a 2.x version, please review the migration guide before upgrading.

Overview

RomM (ROM Manager) allows you to scan, enrich, and browse your game collection with a clean and responsive interface. With support for multiple platforms, various naming schemes and custom tags, RomM is a must-have for anyone who plays on emulators.

Features

  • Scans your existing games library and enchances it with metadata from [IGDB][igdb] and [MobyGames][mobygames]
  • Supports a large number of platforms
  • Play games directly from the browser using EmulatorJS
  • Share your library with friend while limiting access and permissions
  • Supports MAME, Nintendo Switch, and Sony Playstation naming schemes
  • Detects and groups multifile games (e.g. PS1 games with multiple CDs)
  • Can parse tags in filenames (e.g. (E), (USA), (rev v1), etc.)
  • View, upload, update, and delete games from any modern web browser

Preview

๐Ÿ–ฅ Desktop ๐Ÿ“ฑ Mobile

Installation

Before running the image, ensure that Docker is installed and running on your system.

  1. Generate API keys for IGDB and/or MobyGames to fetch metadata.
  2. Verify that your library folder structure matches one of the options listed in the folder structure section.
  3. Create a docker-compose.yml file by referring to the example docker-compose.yml file for guidance, and customize it for your setup with the available environment variables.
  4. Launch the container(s) with docker-compose up -d.

Note

If you are having issues with RomM, please review the wiki page for troubleshooting steps and common issues.

Configuration

Folder Structure

As mentioned in the installation section, RomM requires a specific folder structure to work. The two supported structures are as follows:

Structure A (recommended) Structure B (fallback)
library/roms/gbc/rom_1.gbc library/gbc/roms/rom_1.gbc
        library/
        โ”œโ”€ roms/
        โ”‚  โ”œโ”€ gbc/
        โ”‚  โ”‚  โ”œโ”€ rom_1.gbc
        โ”‚  โ”‚  โ”œโ”€ rom_2.gbc
        โ”‚  โ”‚
        โ”‚  โ”œโ”€ gba/
        โ”‚  โ”‚  โ”œโ”€ rom_1.gba
        โ”‚  โ”‚  โ”œโ”€ rom_2.gba
        โ”‚  โ”‚
        โ”‚  โ”œโ”€ ps/
        โ”‚     โ”œโ”€ my_multifile_game/
        โ”‚     โ”‚   โ”œโ”€ my_game_cd1.iso
        โ”‚     โ”‚   โ”œโ”€ my_game_cd2.iso
        โ”‚     โ”‚
        โ”‚     โ”œโ”€ rom_1.iso
      
        library/
        โ”œโ”€ gbc/
        โ”‚  โ”œโ”€ roms/
        โ”‚     โ”œโ”€ rom_1.gbc
        โ”‚     โ”œโ”€ rom_2.gbc
        โ”‚
        โ”œโ”€ gba/
        โ”‚  โ”œโ”€ roms/
        โ”‚     โ”œโ”€ rom_1.gba
        โ”‚     โ”œโ”€ rom_2.gba
        โ”‚
        โ”œโ”€ ps/
        โ”‚  โ”œโ”€ roms/
        โ”‚     โ”œโ”€ my_multifile_game/
        โ”‚     โ”‚  โ”œโ”€ my_game_cd1.iso
        โ”‚     โ”‚  โ”œโ”€ my_game_cd2.iso
        โ”‚     โ”‚
        โ”‚     โ”œโ”€ rom_1.iso
      

Tip

For folder naming conventions, review the Platform Support section. To override default system names in the folder structure (if your directories are named differently), see the Configuration File section.

Configuration File

RomM's "understanding" of your library can be configured with a config.yaml file or through the config tab in the Control Panel under Settings section. Refer to the example config.yml file for guidance on how to configure it, and the example docker-compose.yml file on how to mount it into the container.

Scheduler

The scheduler allows you to scheduled async tasks that run in the Redis container at regular intervals. Jobs can be run at a specific time in the future, after a time delta, or at recurring internals using cron notation. The wiki page on the scheduler has more information on how which tasks are available and how to enable them.

Naming Convention

Platform Support

If you adhere to the RomM folder structure, RomM supports all platforms listed on the Supported Platforms page. The folder is is case sensitive and must be used exactly how it appears in the list. When scanning your library, RomM will use the folder name to determine the platform and fetch the appropriate game information, metadata, and cover art.

Additionally, some of these platforms have custom icons available (learn more about platform icons in our wiki).

Tag Support

Games can be tagged with region, revision, or other tags by using parentheses in the file name. Additionally, you can set the region and language by adding a prefix: (USA), [reg-J], (French), [De].

  • Revision tags must be prefixed with "rev " or "rev-" (e.g. (rev v1) or (rev-1))
  • Other tags will also be imported, for example: my_game [1.0001](HACK)[!].gba

Tags can be used to search for games in the search bar. For example, searching for (USA) will return all games with the USA tag.

Community

Here are a few projects maintained by members of our community. As they are not regularly reviewed by the RomM team, we recommend you closely review them before use.

Join us on discord, where you can ask questions, submit ideas, get help, showcase your collection, and discuss RomM with other users.

discord-invite

Support

If you like this project, consider buying me a coffee!

coffee-donate

Our Friends

Here are a few projects that we think you might like:

  • EmulatorJS: An embeddable, browser-based emulator
  • RetroDECK: Retro gaming on SteamOS and Linux
  • ES-DE Frontend: Emulator frontend for Linux, macOS and Windows
  • Gaseous: Another self-hosted ROM manager

romm's People

Contributors

2600box avatar alexkalopsia avatar bfenty avatar calebsmithdev avatar casuallynoted avatar dependabot[bot] avatar duhow avatar gantoine avatar jacksaur avatar jiannazzone avatar jinorex avatar jmberesford avatar justinforlenza avatar malev avatar moyer34 avatar psych0d0g avatar rursache avatar sondregronas avatar therobbiedavis avatar xargonwan avatar zurdi15 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

romm's Issues

[Feature] make games with multiple regions and revisions appear under one entry

It would be cool if the program was able to put different regions and revisions under one game entry. Currently games with multiple regions and revisions have multiple game entries. Some examples of different regions and revisions could be:
-Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1).gb
-Zelda no Densetsu - Yume o Miru Shima (Japan).gb
-The Legend of Zelda: Link's Awakening (Europe).gb
I think these should be under the same game entry and then when you click on the game you should be able to choose which revision and region you would like to download. Maybe there should also be a "default" download button, where it chooses a prechosen region (that you can set in the settings) and the latest revision.

[Feature] Figured out how to add RomM to iPhone homescreen with custom icon

in case there are any other apple users out out there, i just worked out to make RomM act like an app.
Originally, I just added a safari link to 192.168.1.XXX:4044 but the icon it created from the site was a bit ugly and incoherent.

IMG_4FEF6BB4ECDA-1

But if you

  1. open the shortcuts app
  2. tap + in top right corner
  3. add action
  4. tap web option and in the search bar at the top type "URL"
  5. select the option in the list below that with the safari icon named "open URLs
  6. in the panel that appears again with a safari icon that says 'Open URL' tap the word URL and enter the url to your RomM instance
  7. enter a name for the shortcut at the very top of the screen and press 'done' at the bottom
  8. click the blue slider icon top right of the screen
  9. choose 'add to home screen'
  10. choose a new icon by clicking the lower option halfway down the screen
  11. click 'add' and you're done

now you have a nice app-looking link to your game library

Screenshot 2023-04-01 at 18 46 08

[Bug] UI freezes up with huge/massive collection

RomM version
V1.5

Describe the bug
When attempting to load a platform with a large number of entries, there is a huge lag.
700 entries: takes 1-5 seconds, loads smoothly
8500 entires: takes 60+ seconds, sometimes Chrome will prompt to terminate the tab. Scrolling down quickly seems to lazy load the image for each game (in this case, 'cover missing' for most of them).

To Reproduce

  1. Have two folders, folder 'ds' has 1 file and folder 'gba' 8500 files. Scan the files.
  2. After the scan, click on the 'ds' section. Then click on the 'gba' section and wait for the lag.

Expected behavior
It would be nice if large collections could be loaded lazily, instead of the page trying to fetch every game at once. Actually, the implementation doesn't really matter - I'd just like the page to load faster, even if the cover images load in later.

Desktop (please complete the following information):
Windows 10, Chrome v109.0.5414.75

[Bug] Compose

Describe the bug
When I start romm via docker compose in sqlite mode I get this errors:

[+] Running 1/1
 โ ฟ Container romm  Recreated                                                                                                                                 0.5s
Attaching to romm
romm  | INFO:     Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
romm  | INFO:     Started parent process [10]
romm  | Process SpawnProcess-3:
romm  | Traceback (most recent call last):
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm  |     self.run()
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm  |     self._target(*self._args, **self._kwargs)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm  |     target(sockets=sockets)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm  |     return asyncio.run(self.serve(sockets=sockets))
romm  |   File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm  |     return loop.run_until_complete(main)
romm  |   File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm  |     return future.result()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm  |     config.load()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm  |     self.loaded_app = import_from_string(self.app)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm  |     module = importlib.import_module(module_str)
romm  |   File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm  |     return _bootstrap._gcd_import(name[level:], package, level)
romm  |   File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm  |   File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm  |   File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm  |   File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm  |   File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm  |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm  |   File "/back/./main.py", line 5, in <module>
romm  |     from handler.igdb_handler import IGDBHandler
romm  |   File "/back/./handler/igdb_handler.py", line 8, in <module>
romm  |     from config.config import CLIENT_ID, CLIENT_SECRET
romm  |   File "/back/./config/config.py", line 28, in <module>
romm  |     DB_PORT: int = int(os.getenv('DB_PORT'))
romm  | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm  | Process SpawnProcess-1:
romm  | Traceback (most recent call last):
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm  |     self.run()
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm  |     self._target(*self._args, **self._kwargs)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm  |     target(sockets=sockets)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm  |     return asyncio.run(self.serve(sockets=sockets))
romm  |   File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm  |     return loop.run_until_complete(main)
romm  |   File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm  |     return future.result()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm  |     config.load()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm  |     self.loaded_app = import_from_string(self.app)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm  |     module = importlib.import_module(module_str)
romm  |   File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm  |     return _bootstrap._gcd_import(name[level:], package, level)
romm  |   File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm  |   File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm  |   File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm  |   File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm  |   File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm  |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm  |   File "/back/./main.py", line 5, in <module>
romm  |     from handler.igdb_handler import IGDBHandler
romm  |   File "/back/./handler/igdb_handler.py", line 8, in <module>
romm  |     from config.config import CLIENT_ID, CLIENT_SECRET
romm  |   File "/back/./config/config.py", line 28, in <module>
romm  |     DB_PORT: int = int(os.getenv('DB_PORT'))
romm  | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm  | Process SpawnProcess-4:
romm  | Traceback (most recent call last):
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm  |     self.run()
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm  |     self._target(*self._args, **self._kwargs)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm  |     target(sockets=sockets)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm  |     return asyncio.run(self.serve(sockets=sockets))
romm  |   File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm  |     return loop.run_until_complete(main)
romm  |   File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm  |     return future.result()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm  |     config.load()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm  |     self.loaded_app = import_from_string(self.app)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm  |     module = importlib.import_module(module_str)
romm  |   File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm  |     return _bootstrap._gcd_import(name[level:], package, level)
romm  |   File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm  |   File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm  |   File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm  |   File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm  |   File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm  |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm  |   File "/back/./main.py", line 5, in <module>
romm  |     from handler.igdb_handler import IGDBHandler
romm  |   File "/back/./handler/igdb_handler.py", line 8, in <module>
romm  |     from config.config import CLIENT_ID, CLIENT_SECRET
romm  |   File "/back/./config/config.py", line 28, in <module>
romm  |     DB_PORT: int = int(os.getenv('DB_PORT'))
romm  | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm  | Process SpawnProcess-2:
romm  | Traceback (most recent call last):
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm  |     self.run()
romm  |   File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm  |     self._target(*self._args, **self._kwargs)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm  |     target(sockets=sockets)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm  |     return asyncio.run(self.serve(sockets=sockets))
romm  |   File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm  |     return loop.run_until_complete(main)
romm  |   File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm  |     return future.result()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm  |     config.load()
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm  |     self.loaded_app = import_from_string(self.app)
romm  |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm  |     module = importlib.import_module(module_str)
romm  |   File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm  |     return _bootstrap._gcd_import(name[level:], package, level)
romm  |   File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm  |   File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm  |   File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm  |   File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm  |   File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm  |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm  |   File "/back/./main.py", line 5, in <module>
romm  |     from handler.igdb_handler import IGDBHandler
romm  |   File "/back/./handler/igdb_handler.py", line 8, in <module>
romm  |     from config.config import CLIENT_ID, CLIENT_SECRET
romm  |   File "/back/./config/config.py", line 28, in <module>
romm  |     DB_PORT: int = int(os.getenv('DB_PORT'))
romm  | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'

If I try to scan me roms folder I get " Couldn't complete scan. Something went wrong...".

To Reproduce
Steps to reproduce the behavior:

  1. set client_id and _secret
  2. set the volume on the right rom library location
  3. changed the forwarded port from 80 to 45107 (tried multiple)

Desktop (please complete the following information):

  • OS: Raspberry Pi OS (Linux Debian)
  • Browser Vivaldi, Chrome
  • Version latest on 29/03/2023

[Bug] Downloads are broken

Sorry, it's me again :)

RomM version
docker:1.5

Describe the bug
Download of a roms always stops at 411kb

To Reproduce
Steps to reproduce the behavior:

  1. Select a game (GBA in my case)
  2. Click on Download button
  3. The file is downloaded but the size is 411kb

Expected behavior
The file is downloaded in its full size.

Desktop (please complete the following information):

  • OS: Raspberry Pi OS (Linux Debian)
  • Browser Vivaldi, Chrome
  • Version latest on 29/03/2023

[Other] Better App Name?

I know you can come up with a better name for this than 'ROM Manager'. C'mon man, this is a really great app and you need a better name to go with it :)

Maybe we can brainstorm it in this thread.

[Feature] Custom game covers

Is your feature request related to a problem? Please describe.
Posibility to use a custom cover for each game

[Feature] Choose IGDB entry manually

Some Games do not get recognized even when they have an entry in the IGDB Database.
The 'Search IGDB' button returns no results and therefore i can not link an IGDB entry to my game.

It would be nice if you could manually pick the IGDB entry.
There could be an additional field in the 'Edit' Section of a game.
(See mock image)
This field would contain just the IGDB ID.
After editing the IGDB ID and applying the new data/cover should be fetched and saved.

Alternatively the 'Search IGDB' button could be improved to allow more filters then just the file name.

Add any other context or screenshots about the feature request here.
I made a quick Mock of how the menu could look like:
image

Loving the project so far. Thanks for the hard work.

[Feature] PS2 icon too dark

this is a tiny, cosmetic point, but anyway - the PS2 icon is pretty invisible when using the dark theme. Would be nice to have a more visible one at some point in the future

Screenshot 2023-03-28 at 18 38 57

[Feature] Bulk edit/rescan option

request to have a bulk edit option so you can, for example, delete or edit a bunch of games at once rather than clicking into each one individually. Audiobookshelf here as an example..

Screenshot 2023-03-28 at 11 22 51

[Bug] Prune Empty Platform Headings

RomM version
1.6

Describe the bug
RomM doesn't automatically prune headings / directories which are empty. Instead, it leaves it intact with a "0" next to it. Clicking on the empty heading loads a page that says "Feels cold here :( ". I encountered this because initially I created a directory for PlayStation called "ps1" instead of "ps". When I renamed the directory from "ps1" to "ps" then scanned in RomM, it correctly created the PlayStation heading but also left the "ps1" heading as empty.

To Reproduce
Steps to reproduce the behavior:

  1. Create a directory for roms (it can either follow the official directory guide, or not), put some files here
  2. Scan that directory with RomM, it will be added to the application
  3. Delete all of the files in that directory
  4. Scan again with RomM, the heading will now be empty but still present

Expected behavior
If RomM encounters a directory or heading with no roms in it, or cannot find a directory it previously scanned, delete that heading in the application. RomM already deletes the individual rom entries when they're deleted, so this should be extended to headings as well. Currently, there is no way in the UI to remove these empty headings.

Screenshots
Screenshot

[Feature] Gamecube rom support

Is your feature request related to a problem? Please describe.
Unfortunately it doesn't appear gamecube roms are compatible with romM. At least as far as grabbing metadata from IGDB goes.

Describe the solution you'd like
Support for GC roms. It should be possible since the platform is on IGDB.

Describe alternatives you've considered
N/A

Thanks!

SQLite Support

Would love to run this without having to deploy a full mariadb container to run it.

Wanted to just put in a quick request for SQLite support, will also look into the code and see if I can just PR it.

Thanks!

[Feature] Option to search a game by its IGDB id

Plex has the useful ability to fix occasions when a movie will stubbornly refused to find its match on IMDB by letting you search by the IMDB id instead of the movie name, like so:

Screenshot 2023-03-29 at 11 50 48

I have several roms which, for reasons I can't work out, refuse to be matched on IGDB so it would be useful to be able to do the same here. I see the search already drags in the IGDB id when matching.

Screenshot 2023-03-29 at 11 50 58

[Feature] User configure of folder structure

Is your feature request related to a problem? Please describe.
It would be nice if we could set our own folder structure. Allowing some sort of mapping schema would allow for more people to easily use this project without having to modify their existing folder structure. For example, I personally don't use a 'rom' folder like you do. I think someone mentioned something similar on the reddit thread, but I didn't see a github issue.

Personally I use the following structure:

library/
โ”œโ”€ gbc/
โ”‚     โ”œโ”€ rom_1.gbc
โ”‚     โ”œโ”€ rom_1.sav
โ”‚     โ”œโ”€ rom_1.sav1
โ”‚     โ”œโ”€ rom_2.gbc
|
โ”œโ”€ switch/
โ”‚     โ”œโ”€ rom_1
โ”‚           โ”œโ”€ rom_1.xci
โ”‚           โ”œโ”€ rom_1.nsp
โ”‚     โ”œโ”€ rom_2.xci
|
โ”œโ”€ pc/
โ”‚     โ”œโ”€ game_1/
โ”‚           โ”œโ”€ game_1.iso
โ”‚           โ”œโ”€ game_1_patch.exe
โ”‚     โ”œโ”€ game_2/
โ”‚           โ”œโ”€ soundtrack/
โ”‚                  โ”œโ”€ song_1.mp3
โ”‚                  โ”œโ”€ song_2.mp3
โ”‚           โ”œโ”€ game_2.iso
โ”‚           โ”œโ”€ game_2_patch.exe
โ”‚     โ”œโ”€ random1_game.iso
โ”‚     โ”œโ”€ random2_game.7z
โ”‚     โ”œโ”€ random3_game.rar

Describe the solution you'd like
I'd like to have a more dynamic method of linking folders/files to game entries. Additionally it could be useful to exclude certain files/folders (eg: the 'soundtrack' folder in my example above)

Appreciate you making this app and sharing it with us!

[Feature] Unzip files on the fly

Hi Zurdi,
You asked me to open an issue on unzipping files. I think this can both be done on the server side or in the browser. I think it is worth noting that this will cause a delay in the download process (especially for large files).

[Other] Collaboration proposal

Greetings,

I'm Xargon, the founder of RetroDECK and before of that developer on 351ELEC/AmberELEC.

With another developer I recently started a project named RetroMan (https://github.com/RetroMan-project).
Our project just started and we noticed your RomM project and we are interested in it as I found it somehow similar to ours.

RetroMan stands for "Retro Manager", it amis to be a fully pluginable core for managing user's rom libraries.
RetroMan, is focusing on recognizing and syncing the roms on different devices, let's say that you have a miyoo mini and a game boy flahs cart, you can decide which roms (and saves/states) to keep synced in the various devices by having one (or more) main library.
So there will be a "server mode" and a "client" mode to allow the user to use it to catalogue their roms and to manage their physical devices.

Basically every device got two templates: the device template and the physical device file that they are linked together to instruct RetroMan about the device's features, supported systems, folder locations, etc.
These files are yaml that they can always be updated.

Then it can generate gameslists.xml that suits the devices frontend, such as EmulationStation or Onion for example.

It seems like we have similar goals, at least for the server side, so I would like to discuss the evenutality to unify the projects and join our forces to do a single better software and avoid fragmentation.

Feel free to check our page and ask any questions :)

Kindly,
Xargon

[Feature] Manage multiple disk games

how should we handle games with more than one disk?
e.g,. Alone in the Dark has two disks

i tried

> games
>> dc
>>> roms
>>>> Alone in the Dark
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 1).chd
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 2).chd

but nothing showed up after scanning the folder from the front end. So i tried taking them out of the subfolder and put both disks in the roms folder, thus...

> games
>> dc
>>> roms
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 1).chd
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 2).chd

...but now I have two entries for one game in the front end.
What's the correct way to handle these?

Screenshot 2023-03-28 at 16 02 41

Download Notification

At the moment, it is only possible to see if a download has started via the dev-tools of the browser.

This isn't a problem with small files like GBA games or similar ones where it pops up relatively fast in the browser downloads, but when it goes to PS2 or Switch Games for instance, it would be nice to see a notification that the Download started.

Scan fails using mariaDB as db driver

After encountering the issue from #41, I removed the long titled file from the folder and now the application cannot complete any scans.

Running via Docker with MariaDB using the repo docker-compose.

2023-03-28T15:11:06.144462222Z INFO:	  [ROMM] complete scaning... 2023-03-28 15:11:06

2023-03-28T15:11:09.402536345Z INFO:     192.168.3.20:0 - "PUT /scan?overwrite=false HTTP/1.0" 500 Internal Server Error

2023-03-28T15:11:09.403992018Z ERROR:    Exception in ASGI application

2023-03-28T15:11:09.404010984Z Traceback (most recent call last):

2023-03-28T15:11:09.404017252Z   File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi

2023-03-28T15:11:09.404024262Z     result = await app(  # type: ignore[func-returns-value]

2023-03-28T15:11:09.404029798Z   File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__

2023-03-28T15:11:09.404035526Z     return await self.app(scope, receive, send)

2023-03-28T15:11:09.404041126Z   File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__

2023-03-28T15:11:09.404046971Z     await super().__call__(scope, receive, send)

2023-03-28T15:11:09.404052379Z   File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__

2023-03-28T15:11:09.404058346Z     await self.middleware_stack(scope, receive, send)

2023-03-28T15:11:09.404063790Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__

2023-03-28T15:11:09.404070074Z     raise exc

2023-03-28T15:11:09.404075548Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__

2023-03-28T15:11:09.404081245Z     await self.app(scope, receive, _send)

2023-03-28T15:11:09.404086719Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__

2023-03-28T15:11:09.404092452Z     await self.simple_response(scope, receive, send, request_headers=headers)

2023-03-28T15:11:09.404097926Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response

2023-03-28T15:11:09.404103644Z     await self.app(scope, receive, send)

2023-03-28T15:11:09.404109017Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__

2023-03-28T15:11:09.404114703Z     raise exc

2023-03-28T15:11:09.404139975Z   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__

2023-03-28T15:11:09.404146086Z     await self.app(scope, receive, sender)

2023-03-28T15:11:09.404151377Z   File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__

2023-03-28T15:11:09.404156983Z     raise e

2023-03-28T15:11:09.404162013Z   File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__

2023-03-28T15:11:09.404167773Z     await self.app(scope, receive, send)

2023-03-28T15:11:09.404173233Z   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__

2023-03-28T15:11:09.404178907Z     await route.handle(scope, receive, send)

2023-03-28T15:11:09.404185167Z   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle

2023-03-28T15:11:09.404190749Z     await self.app(scope, receive, send)

2023-03-28T15:11:09.404196111Z   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app

2023-03-28T15:11:09.404201606Z     response = await func(request)

2023-03-28T15:11:09.404206835Z   File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app

2023-03-28T15:11:09.404212453Z     raw_response = await run_endpoint_function(

2023-03-28T15:11:09.404217743Z   File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function

2023-03-28T15:11:09.404223411Z     return await dependant.call(**values)

2023-03-28T15:11:09.404228612Z   File "/back/./main.py", line 82, in scan

2023-03-28T15:11:09.404233924Z     platforms = data['platforms'] if data['platforms'] else fs.get_platforms()

2023-03-28T15:11:09.404239531Z   File "/back/./utils/fs.py", line 76, in get_platforms

2023-03-28T15:11:09.404245018Z     [platforms.remove(reserved) for reserved in RESERVED_FOLDERS]

2023-03-28T15:11:09.404250402Z   File "/back/./utils/fs.py", line 76, in <listcomp>

2023-03-28T15:11:09.404257271Z     [platforms.remove(reserved) for reserved in RESERVED_FOLDERS]

2023-03-28T15:11:09.404262638Z ValueError: list.remove(x): x not in list

Arcade - platform not found in igdb

Was attempting to scan my EmulatorJS library, and after Sega 32X got this error:

romm     | WARNING:  [ROMM] platform not found in igdb 2023-03-27 20:07:30
romm     | INFO:          [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm     | INFO:          [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm     | INFO:          [ROMM] Purge sega32x 2023-03-27 20:07:30
romm     | INFO:          [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm     | INFO:          [ROMM] Getting arcade details 2023-03-27 20:07:30
romm     | INFO:     10.0.2.4:0 - "PUT /scan?overwrite=false HTTP/1.0" 500 Internal Server Error
romm     | ERROR:    Exception in ASGI application
romm     | Traceback (most recent call last):
romm     |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
romm     |     result = await app(  # type: ignore[func-returns-value]
romm     |   File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
romm     |     return await self.app(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__
romm     |     await super().__call__(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__
romm     |     await self.middleware_stack(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__
romm     |     raise exc
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__
romm     |     await self.app(scope, receive, _send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__
romm     |     await self.simple_response(scope, receive, send, request_headers=headers)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response
romm     |     await self.app(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
romm     |     raise exc
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
romm     |     await self.app(scope, receive, sender)
romm     |   File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
romm     |     raise e
romm     |   File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
romm     |     await self.app(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__
romm     |     await route.handle(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle
romm     |     await self.app(scope, receive, send)
romm     |   File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app
romm     |     response = await func(request)
romm     |   File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app
romm     |     raw_response = await run_endpoint_function(
romm     |   File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function
romm     |     return await dependant.call(**values)
romm     |   File "/back/./main.py", line 84, in scan
romm     |     p_igdb_id: str = fastapi.scan_platform(overwrite, p_slug, igdbh, dbh)
romm     |   File "/back/./utils/fastapi.py", line 24, in scan_platform
romm     |     p_igdb_id, p_name, url_logo = igdbh.get_platform_details(p_slug)
romm     |   File "/back/./handler/igdb_handler.py", line 26, in wrapper
romm     |     return func(*args)
romm     |   File "/back/./handler/igdb_handler.py", line 40, in get_platform_details
romm     |     id_logo = res_details['platform_logo']
romm     | KeyError: 'platform_logo'

Weird thing is, there are no arcade roms in the arcade/roms dir.

(Edited, i thought sega32x was causing the error, but it's what comes AFTEE sega32x)

[Other] error bind mount using example compose file

I tried running the example compose file and keep getting an error related to a missing bind mount.

failed to deploy a stack: time="2023-03-28T13:30:15Z" level=warning msg="The "Vi" variable is not set. Defaulting to a blank string." Network romm_default Creating Network romm_default Created Container romm_db Creating Container romm_db Created Container romm Creating Container romm Created Container romm_db Starting Error response from daemon: Bind mount failed: '/data/compose/56/config' does not exists

I am guessing this is related to the following:
Also not sure what the undefined Vi variable is

volumes:
  - ./config:/config

I tried changing this to

volumes:
  - ./volume1/docker/romm:/config

failed to deploy a stack: time="2023-03-28T13:34:24Z" level=warning msg="The "Vi" variable is not set. Defaulting to a blank string." Network romm_default Creating Network romm_default Created Container romm_db Creating Container romm_db Created Container romm Creating Container romm Created Container romm_db Starting Error response from daemon: Bind mount failed: '/data/compose/58/volume1/docker/romm' does not exists

Should I create a config folder inside the data folder? I'd rather have config files in volume1/docker/romm and roms in volume1/data/media/roms

I can see it did actually try to create the database

image
image

currently compose file without the sensitive info

`version: '3'
services:
romm:
image: 'zurdi15/romm:latest'
container_name: romm
network_mode: bridge0
environment:
- ROMM_DB_DRIVER="mariadb" # This variable can be set as: mariadb | sqlite. If it is not defined, sqlite will be the database by default
- DB_HOST=romm_db # Only if ROMM_DB_DRIVER='mariadb'
- DB_PORT=3306 # Only if ROMM_DB_DRIVER='mariadb'
- DB_USER=romm-user # Only if ROMM_DB_DRIVER='mariadb'
- DB_PASSWD=alreadychangedthis # Only if ROMM_DB_DRIVER='mariadb'
- CLIENT_ID=gottheclientid
- CLIENT_SECRET=gotthesecretaswell
- STEAMGRIDDB_API_KEY=WIP
volumes:
- ./volume1/data/media/roms:/library
ports:
- '82:80' #80 was in use by pihole. Changed this to 82 on host
depends_on:
- romm_db
restart: "unless-stopped"

romm_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: romm_db
environment:
- MYSQL_ROOT_PASSWORD=changedthisone
- MYSQL_DATABASE=romm
- MYSQL_USER=romm-user
- MYSQL_PASSWORD=alsochangedthisone
volumes:
- ./config:/config #did not change this bind
ports:
- 3306:3306
restart: "unless-stopped"
`

[Bug] IGDB Scraper not working

Hi,

I looked a round in the issues but couldn't find anything related to my problem.
I played around with romm the last couple of days but I couldn't get the IGDB scraper to work. For every title I search get no results and the logs show this error:

 INFO:     [ROMM] getting Arkanoid.d64 roms from  igdb ... 2023-04-01 13:38:03
INFO:     [ROMM] Matched roms for Arkanoid.d64: [{'title': 'Syntax Error', 'status': 400, 'cause': "Expecting a STRING as input, surround your input with quotes starting at ']' expecting {'{', 'f', '(', '[', 'true', 't', 'false', 'null', 'n'"}] 2023-04-01 13:38:03
INFO:     192.168.0.6:0 - "PUT /search/roms/igdb HTTP/1.0" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app
    response = await func(request)
  File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app
    raw_response = await run_endpoint_function(
  File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function
    return await dependant.call(**values)
  File "/back/./main.py", line 101, in search_rom_igdb
    return {'data': igdbh.get_matched_roms(data['file_name'], data['p_igdb_id'])}
  File "/back/./handler/igdb_handler.py", line 28, in wrapper
    return func(*args)
  File "/back/./handler/igdb_handler.py", line 125, in get_matched_roms
    data=f"fields url; where game={rom['id']};").json()[0]
KeyError: 'id'

The IGDB client_id and secret are working when call in the API with powershell. I'm running version 1.6 in Docker.

Thanks

Faba

[Feature] Support read-only library

Is your feature request related to a problem? Please describe.
I keep my library read-only, mainly so apps such as this cannot accidentally delete files (either because of an app bug, or my own user error). Currently the docker mounts /library for games and /library/resources for image resources related to each game. When mounting the former as RO and the latter as RW, docker will throw an error similar to error mounting to rootfs at read-only file system: unknown. This is due to adding the RW folder as a subfolder of a RO mount. This can be overcome by adding a folder called "resources" within my game library (but I'd rather not have this empty folder in my host's library mount folder).

Describe the solution you'd like
It would be useful to separate the location of the game library and the downloaded resources. Entirely separate directories would be ideal. Or maybe some setting/config to set the location?

Describe alternatives you've considered
The image assets could also be stored in the DB. Though it could result in DB bloat, and may require some implementation of sqlite VACUUM for deleted/removed games.

Additional context
Great app! Very glad you've shared this with all of us~!

[Bug] MariaDB filename data too long for column

When scanning /library/gb/roms/ I encountered the below error and it halted any further scanning:

2023-03-28T15:07:22.973406594Z sqlalchemy.exc.DataError: (mariadb.DataError) Data too long for column 'name' at row 1

2023-03-28T15:07:22.973412167Z [SQL: INSERT INTO roms (filename, filename_no_ext, r_igdb_id, p_igdb_id, r_sgdb_id, p_sgdb_id, name, r_slug, p_slug, summary, path_cover_s, path_cover_l, has_cover, size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]

2023-03-28T15:07:22.973418529Z [parameters: ('Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja).zip', 'Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja)', '', 33, '', '', 'Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja)', '', 'gb', '', '/assets/library/resources/default/cover_s.png', '/assets/library/resources/default/cover_l.png', 0, '0.21')]

Running via docker with mariadb as defined from the docker-compose in the repo.

[Bug] Scan is broken after latest update

RomM version
docker:latest

Describe the bug
Scan is broken after the systems update

To Reproduce
Steps to reproduce the behavior:

  1. docker compose up -d
  2. Click on 'Scan'

Expected behavior
Roms are scanned

Desktop (please complete the following information):

  • OS: Raspberry Pi OS (Linux Debian)
  • Browser Vivaldi, Chrome
  • Version latest on 29/03/2023

romm.log

[Feature] Play games in browser

I wonder if it would be possible to play games directly in the browser. Could be coupled with EmulatorJS.

This would make it awesome for parents with their kids, where they can just add a shortcut to RomM somehwere on their systems and they can just open it, pick a game an play.

[Other] iPhone rendering issue

not sure why this would be the case, but my Romm instance renders perfectly on iphone in chrome, but is totally blank when opening with safari

Chrome

IMG_63A22AC015CA-1

Safari

IMG_0EB4471A9861-1

[Bug] Database not Supported Error

Describe the bug
On a fresh container stood up using a lightly modified version of the provided docker-compose.yml (see below for the docker compose I'm using), I'm seeing an error and RomM isn't able to find the roms I've put in the library directory.

Error from the container logs:
image

Error shown by RomM:
image

To Reproduce
The error in the container logs seems to only show up on boot/reboot of the RomM container, while the error in the RomM webpage shows up anytime I click the "Scan" button.

Expected behavior
The roms that I've placed in the library directory should be showing up in the RomM web console (web page?).

Additional context
The library directory structure is following the exact requirements shown in the instructions. For example, I have one rom loaded as this: /library/gbc/roms/Pokemon_YellowVersion.gbc

The docker-compose.yml (only passwords and api keys omitted)

version: '3'
services:
romm:
image: 'zurdi15/romm:latest'
container_name: romm
environment:
- ROMM_DB_DRIVER="mariadb"
- DB_HOST=romm_db
- DB_PORT=3306
- DB_USER=romm-user
- DB_NAME=romm
- DB_PASSWD=
- CLIENT_ID=
- CLIENT_SECRET=
volumes:
- '/host/path/to/romm:/library'
ports:
- 8080:80
depends_on:
- romm_db
restart: 'unless-stopped'
romm_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: romm_db
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_DATABASE=romm
- MYSQL_USER=romm-user
- MYSQL_PASSWORD=
volumes:
- ./config:/config
ports:
- 3306:3306
restart: 'unless-stopped'

Missing LICENSE

I see you have no LICENSE file for this project. The default is copyright.

I would suggest releasing the code under the GPL-3.0-or-later or AGPL-3.0-or-later license so that others are encouraged to contribute changes back to your project.

[Feature] Change zoom level for games grid

is there a way of having an adjustable zoom level for the games grid? it looks fine on my laptop, but when on my desktop the covers are massive and you can only see a few at a time.

Screenshot 2023-03-28 at 14 20 23

Example zoom adjustment, with the contol bottom-right of the screen

Screenshot 2023-03-28 at 14 18 38
Screenshot 2023-03-28 at 14 18 56
Screenshot 2023-03-28 at 14 19 25

[Feature] Savefiles/states management

Is your feature request related to a problem? Please describe.
Posibility to manage (download and upload) different savefiles/states for each game

[Feature] Authentication and user management

i open up some of my services (like overseer / audiobookshelf / calibre-web / komga etc) via cloudflare tunnels, but all these have username / password and user management or some other authentication to help prevent bad actors.

Any plans for something similar here so we can open up to the internet relatively safely?

[Feature] the ROM Management Datafile aka dat files

Wow for only three weeks since first commit the progress here is nothing short of impressive, well done!

I hate to be the one to add yet another feature request, but this is more of a requirement. You need to be informed about this (if you don't already know), sooner rather than later.

tl;dr dat files you must start from here

The ROM Management Datafile, is a fairly basic specification, which provides you with everything you need to identify a ROM, like file names, sizes and hashes. The definition also include a name, description and usually also language, region, etc. all the information you need which is difficult or impossible to find from the file name alone. It is also what is traditionally expected from a ROM Manager, by your target audience and competition.

The tool you use to organize your ROMs, the ROM Manager. To rebuild a working ROM set from other collections or unknown files, while ensuring completeness, no corruption, modification, or manipulation. Which is also why it is championed by the preservation community, wanting to ensure every bit and original byte is accounted for. But it also enables you to compile a collection of known working ROMs, in the structure and layout as expected by different emulators.

MAME is particularly tricky, and as time progress more and more systems and their ROMs are being encapsulated by the project. It has already become the de-facto set for PSX ROMs only in a matter months. The problem is not only that their naming convention is obscure, using only a few lower case characters and numbers as file names, with no spaces, but they have three different types of ROMs for the same game(s). The ROMs can be zipped as split, full merged, or non-merged files, which may include one game, or multiple games of separate releases of the same game, or different games of the same type (hardware speaking). They also may or may not include the required BIOS dumps necessary to play the game which means these also need to be managed.

Not only are the dat files necessary to identify the actual game, but it is also required from a ROM Manager to be able to unzip and compile one type from another, as may be needed, to mitigate having to keep duplicates. I have been praying for a web manager, all the others are desktop clients which makes it difficult to combine into any sensible workflow automation, and they are singular in purpose. There is a disconnect between organizing files, and the identifying data contained therein, which is required to source the additional meta data needed to actually manage a library of media content.

These two worlds of organization vs manageability has remained in disconnect, which impairs the archivability of retro games into a singular source library by any definition. Hopefully RomM is here to finally make sense of all the chaos.

Sources

Logiqx actually came up with the dat file specification which most projects are using, there is of course always that one, no-intro has a slightly different schema but the content is similar and also well documented. Since it's all XML the data is self explaining anyway. This is not an exhaustive list...

http://www.logiqx.com/Dats/ - legacy sets
https://pleasuredome.github.io/pleasuredome/ - mame sets and others
https://github.com/danmons/datfiles - Mister set

The preservationists each with their own focus and peculiarities but each in their own right indispensable for their work cataloging our history.
http://redump.org - optical discs
https://no-intro.org - cartridges
https://www.tosecdev.org/downloads/category/22-datfiles
There is another one, trurip being rebranded as emuarc, but I am still unable to find their actual dat files, moving on...

Should probably be considered out of scope, more applicable to a lister project for sourcing roms, but for interest sake. The first, catalogs the scene releases of split archive files, the other has defined a specification called srr which catalogs the metadata required to "rescene" the extracted content back to identical split archives again.
https://dats.site
https://www.srrdb.com/

Documentation

...and other useful technical information to assist with the implementation of dat files.
https://pleasuredome.miraheze.org/wiki/DAT_File
http://www.logiqx.com/DatFAQs/DatCreation.php
https://wiki.no-intro.org/index.php?title=DAT-o-MATIC_Guide
https://www.oreilly.com/library/view/gaming-hacks/0596007140/ch01s13.html

The missing link which ties ROM files to their meta data, countless hours by a vast community capturing and cataloging this information, a saving grace unavailable to any other type of media.

Unable to pull artwork from IGDB

So I've followed the example docker compose and deployed it with my Client ID/Secret but for some reason when I try to pull the artwork for a game, it says no results found. Here are my logs from startup to when I get that error:

image

I'm running the docker container on a server running OMV, and deployed the compose through Portainer if that helps.

[Bug] Unable to delete rom

RomM version
v1.5

Describe the bug
Unable to delete rom when using structure folder 1. RomM doesn't find the file

To Reproduce

  1. Go to game details
  2. Delete it from filesystem
  3. RomM unable to delete it

Expected behavior
RomM should be able to delete the file from the system

Dreamcast support

please may we have dreamcast in the supported systems so we get a pretty icon in the system list?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.