Skip to content

Commit

Permalink
Cart loader (#309)
Browse files Browse the repository at this point in the history
* wip

* various fixes, first working version

* rename script from cart-loader to chimera-cart-loader

* detect and use rom name to be able to use saves

* add monitor service for automatically loading games from carts

* whitespace fix

* update setup to package new files

* add artwork

* prevent rewriting of system shortcuts

* put binaries in the correct place

* attempt to fix test failures
  • Loading branch information
alkazar authored May 6, 2024
1 parent 776b923 commit 489e344
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 10 deletions.
15 changes: 15 additions & 0 deletions bin/chimera-cart-monitor
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#! /bin/bash

hascart=false

while true; do
chimera-cart-loader --check
result=$?
if [ "$result" == "0" ] && [ $hascart == false ]; then
chimera-cart-loader --trigger
hascart=true
elif [ "$result" != "0" ] && [ $hascart == true ]; then
hascart=false
fi
sleep 3
done
11 changes: 11 additions & 0 deletions chimera-cart-monitor.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
Description=Chimera Cart Monitor - Automatically launch games from physical cartridges
Requires=dev-gboperator.device
After=dev-gboperator.device

[Service]
ExecStart=/usr/share/chimera/bin/chimera-cart-monitor
Restart=always

[Install]
WantedBy=default.target
1 change: 0 additions & 1 deletion chimera_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def merge_single_level(src1, src2):
if not os.path.isdir(BIN_PATH):
BIN_PATH = "/usr/share/chimera/bin"

SHORTCUT_DIR = context.SHORTCUT_DIRS
BANNER_DIR = context.DATA_HOME + '/chimera/images'
DATA_DIR = context.DATA_HOME + '/chimera/data'
CONTENT_DIR = context.DATA_HOME + '/chimera/content'
Expand Down
5 changes: 3 additions & 2 deletions chimera_app/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ def __get_steam_user_dirs(steam_dir):
CACHE_HOME = os.path.expanduser('~/.cache')
CONFIG_HOME = os.path.expanduser('~/.config')
DATA_HOME = os.path.expanduser('~/.local/share')
COMPAT_DATA_FILE = os.path.join(CACHE_HOME, 'steam-shortcuts-compat.yaml')
SHORTCUT_DIRS = os.path.join(DATA_HOME, 'chimera/shortcuts')
USER_SHORTCUT_DIR = os.path.join(DATA_HOME, 'chimera/shortcuts')
SYSTEM_SHORTCUT_DIR = '/usr/share/chimera/shortcuts'
SHORTCUT_DIRS = [ USER_SHORTCUT_DIR, SYSTEM_SHORTCUT_DIR ]
TOOLS_DIR = os.path.join(DATA_HOME, 'chimera/data/compat/tools')
TOOLS_TEMPLATE_FILE = os.path.join(DATA_HOME, 'chimera/data/compat/tool-stub.tpl')
PATCH_DIR = os.path.join(DATA_HOME, 'chimera/data/patch')
Expand Down
28 changes: 21 additions & 7 deletions chimera_app/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@

def create_all_shortcuts():
"""Convenience function to create all shortcuts with default parameters"""
if not os.path.isdir(context.SHORTCUT_DIRS):
print(f'Shortcuts directory does not exist ({context.SHORTCUT_DIRS})')
return
for shortcut_dir in context.SHORTCUT_DIRS:
if not os.path.isdir(shortcut_dir):
print(f'Shortcuts directory does not exist ({shortcut_dir})')
return

manager = ShortcutsManager()
for user_dir in context.STEAM_USER_DIRS:
# Should change the STEAM_USER_DIRS into USER_IDS
manager.add_steam_file_for_user(os.path.basename(user_dir))

for file in os.scandir(context.SHORTCUT_DIRS):
if file.is_file():
manager.add_shortcuts_file_from_path(file.path)
for shortcut_dir in context.SHORTCUT_DIRS:
for file in os.scandir(shortcut_dir):
if file.is_file():
manager.add_shortcuts_file_from_path(file.path)

manager.load_shortcut_entries()
manager.create_shortcuts()
Expand Down Expand Up @@ -210,6 +212,15 @@ def add_shortcut(self, entry: dict):
self.current_data.pop(index)
return

if 'condition' in entry and entry['condition']:
# drop the shortcut if the condition command returns an error code
code = os.system(entry['condition'])
if code != 0:
if shortcut:
self.current_data.pop(index)
return


shortcut['appid'] = shortcut_id
shortcut['AppName'] = entry['name']
shortcut['Exe'] = entry['cmd']
Expand Down Expand Up @@ -362,7 +373,7 @@ class PlatformShortcutsFile(ShortcutsFile):

def __init__(self, platform: str, auto_load: bool = True):
self.platform = platform
path = os.path.join(context.SHORTCUT_DIRS, f'chimera.{platform}.yaml')
path = os.path.join(context.USER_SHORTCUT_DIR, f'chimera.{platform}.yaml')
super().__init__(path, auto_load)


Expand Down Expand Up @@ -414,6 +425,9 @@ def load_shortcut_entries(self) -> None:
def prune_deleted_shortcuts(self) -> None:
"""Drop shortcuts marked as deleted from all YAML files"""
for f in self.shortcut_files:
if context.SYSTEM_SHORTCUT_DIR in f.path and f.path.index(context.SYSTEM_SHORTCUT_DIR) == 0:
# system shortcuts are read-only
continue
f.load_data()
f.prune_deleted()
f.save()
Expand Down
Binary file added images/cart-loader/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/cart-loader/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/cart-loader/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/cart-loader/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/cart-loader/poster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions launchers/chimera-cart-loader
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash

DUMP_DIR=/tmp/chimera-cart-loader

function check {
if ! lsusb | grep "1d50:6018" &> /dev/null; then
# gboperator not connected
return 1
fi

cart_name=$(gbopyrator 2> /dev/null | grep "Detected game:" | cut -d":" -f2- | awk '{$1=$1;print}')

if echo $cart_name | grep ".gb$" &> /dev/null; then
# Game Boy cart detected
echo "gb:::$cart_name"
return 0
elif echo $cart_name | grep ".gbc$" &> /dev/null; then
# Game Boy Color cart detected
echo "gbc:::$cart_name"
return 0
else
# No valid cart detected
return 2
fi
}

function load {
launcher=$1
cart=$2

ROM="$DUMP_DIR/$cart"

mkdir -p "$DUMP_DIR"
trap "rm -rf $DUMP_DIR" EXIT
gbopyrator --dump-rom "$ROM"
$launcher "$ROM"
}

result=$(check)
code=$?
cart_type=$(echo $result | cut -d":" -f1)
cart_name=$(echo $result | cut -d":" -f4-)

if [ "$1" == "--check" ]; then
echo "Detected: [$cart_type] $cart_name"
exit $code
elif [ "$1" == "--trigger" ] && [ "$code" == "0" ] && [ ! -e $DUMP_DIR ]; then
# cart detected, trigger cart launch through Steam if not already triggered
steam steam://rungameid/12273638796687310848
elif [ -z "$1" ] && [ -n "$cart_type" ] && [ -n "$cart_name" ]; then
# no parameters means this script has been called from Steam, launch the cart directly if one is detected
load "$cart_type" "$cart_name"
fi
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
('share/chimera/images', glob('images/*.png')),
('share/chimera/images/flathub', glob('images/flathub/*.png')),
('share/chimera/images/splash', glob('images/splash/*.png')),
('share/chimera/images/cart-loader', glob('images/cart-loader/*.png')),
('share/chimera/shortcuts', glob('shortcuts/*.yaml')),
('share/chimera/views', glob('views/*.tpl')),
('share/chimera/public', glob('public/*.js')),
('share/chimera/public', glob('public/*.css')),
Expand Down
9 changes: 9 additions & 0 deletions shortcuts/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- name: Cart Loader
cmd: chimera-cart-loader
condition: lsusb | grep 1d50:6018
hidden: false
poster: /usr/share/chimera/images/cart-loader/poster.png
banner: /usr/share/chimera/images/cart-loader/banner.png
background: /usr/share/chimera/images/cart-loader/background.png
logo: /usr/share/chimera/images/cart-loader/logo.png
icon: /usr/share/chimera/images/cart-loader/icon.png
1 change: 1 addition & 0 deletions tests/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def fake_data(fs,
monkeypatch):
files_path = os.path.join(os.path.dirname(__file__), 'files')

fs.create_dir("/usr/share/chimera/shortcuts")
fs.create_dir(os.path.expanduser('~/.cache'))
fs.create_dir(os.path.expanduser('~/.local/share/chimera'))
fs.create_dir(os.path.expanduser('~/.local/share/Steam/config'))
Expand Down

0 comments on commit 489e344

Please sign in to comment.