libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.09k stars 1.81k forks source link

(CLI) Auto-detect Core when -L isn't present #746

Open BlackLotus opened 10 years ago

BlackLotus commented 10 years ago

When running retroarch "Mario.smc", have the core auto-detect and run.

Since -L is not there, it will do its best job to Load Content and Run.


Yeah the title pretty much explains it. It would be nice to not only have an auto detect function from within rgui, but from the command line as well. It could try to autodetect first and if nothing matches just use libretro_path or it could be something like -a/--auto-detect. The default behaviour could be also implemented in the retroarch.conf.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/2572018-feature-request-adding-a-command-line-option-or-a-default-auto-detect-function?utm_campaign=plugin&utm_content=tracker%2F296058&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F296058&utm_medium=issues&utm_source=github).
Earnestly commented 9 years ago

This used to work for a long time. I'm not sure when the commit that broke this landed but retroarch --appendconfig foo.conf game.rom used to work if you defined libretro_path when it was still designed to be a directory.

RobLoach commented 6 years ago

This exists in the Menu, would be nice to have it in the CLI....

c

When -L isn't provided, but content is, determine which core should be used and do it.

andres-asm commented 5 years ago

Auto detect and disambiguate from the cli seems pointless. One thing that could be done is:

If retroarch is launched with a filename as an argument do a lookup in the playlists including history looking for that, if that is found and has a core associated then use that

So:

retroarch mario.sfc would trigger a search in history, favorites and the other playlists, if an entry is found and the entry has an associated core then use that. If not, bail with an error.

Ferk commented 5 years ago

Why pointless?

I expect one of the use cases for this would be being able to associate retroarch with files in such a way that you can simply double click a rom from a file browser and have it open with retroarch (basically what's asked in #5614) without having to explicitly create playlists for it or having to set up wrappers to add the -L option trying to autodetect the core through the wrapper.

This is actually how most standalone emulators work. I would understand if it would seem hard (or maybe even impossible) to do it accurately in retroarch since the core cannot simply be guessed based on the extension, but I don't understand why would it seem pointless.

When using the "Select file and detect core" option you get a list of "Suggested cores" when there's more than one core that could be used. It'd be great if that choice was given when it cannot be determined which core to use.

geajack commented 5 years ago

Don't libretro cores have to declare a "supported extensions" field? You could use that to choose a default core, and add an option in the UI where the user can set cores for extensions.

ghost commented 5 years ago

Not all extensions are native to a particular system (e.g. bin/cue), and not everyone will always want to use the same core to launch a particular system's content.

Earnestly commented 5 years ago

Wouldn't those users have the option of using -L to specify a core explicitly?

geajack commented 5 years ago

I'm going to admit openly that this is a slightly tricky UX problem. Only slightly, but still not entirely trivial. So we should expect that any solution is going to be somewhat of a compromise and may not cover certain extreme edgecases perfectly.

(Opinionated feature rationale)

However, currently due to lacking this feature, Retroarch is... not exactly unusable, but I have the entire SNES and NES libraries in my filesystem. I don't want to have to scroll through all those files using the gamepad-oriented Retroarch UI. Yes, I can use page-up/down to scroll more quickly, or more library-navigation features could be added to Retroarch (like searching), but in the end the problem for me is that I just don't like media library apps. Stuff like iTunes that wants you to import your files into its own internal organizational system. I feel like I already have a great media library management app on my computer - the filesystem - which I know how to use and am comfortable with. The mere fact that I have to tell Retroarch to scan directories before I can run anything, for instance, is enough of a nuisance. In the old days I used to just fire up Snes9x and drag-and-drop a ROM in, you know? Most media-library management type apps that I've used in past have made those features optional and allowed more traditional "file-oriented" usage. Retroarch should do the same. I suspect the only reason it doesn't already is due to the "gamepad-oriented" design - no desktop-oriented software would leave out this sort of feature. But Retroarch is trying to be a solution for both dedicated gaming hardware and desktops.

The only real problem I foresee is the UI solution for when Retroarch really just doesn't know what core to use. The obvious solution is to just have it drop you to a "core select" screen, but the trouble is how to fit that into Retroarch's very "hierarchical", console-style UI. I mean, put it this way: if from that core select screen, I hit Backspace, where should I end up?

RobLoach commented 5 years ago

features could be added to Retroarch (like searching)

/ is the default hotkey to use search.

Most media-library management type apps that I've used in past have made those features optional and allowed more traditional "file-oriented" usage.

It's not that noone wants this implemented, it's just that noone has worked on it. It can be more difficult than what one would expect.

A work around I've done before is had a retroarch-snes.sh file that would launch RetroArch and pass the arguments with -L snes_libretro.so. Would love something better that came out-of-the-box with RA.

keithbowes commented 4 years ago

This used to work for a long time. I'm not sure when the commit that broke this landed but retroarch --appendconfig foo.conf game.rom used to work if you defined libretro_path when it was still designed to be a directory.

Yeah, the message to use libretro_path always confused me, as I could never get it to work, but I was testing out older versions. 1.0.0.3-beta is the oldest version I can get to work at all on my X-less Linux system and it detects the core and writes libretro_path. v1.2 to v1.3.2 wouldn't automatically detect the core, but they would respect libretro_path. v1.3.4 and higher don't respect libretro_path, but still gives the message RetroArch [ERROR] :: RetroArch is built for dynamic libretro cores, but libretro_path is not set. Cannot continue., even though libretro_path is set.

Still, libretro_path, even in the older versions in which it worked, seems quite limited, just picking the default core, without any apparent way of specifying various cores to try, let alone automatic detection.

seanocali commented 2 years ago

Why not just retroarch -A "myRom.zip"? Same behavior if you loaded content from the GUI. If it has a default core association it will launch the game. If not it will bring up the list of compatible cores in the GUI. Seems like no reason to not do this. It's not like launching RA from the CLI bypasses the GUI interface.

ssokolow commented 2 years ago

To be perfectly honest, the degree to which the lack of this complicates launching RetroArch from an external game browser is the number-one reason that I haven't yet tried switching from the RetroArch distributed in the Ubuntu repos to the Flatpak'd version.

It's bad enough when I'm more or less hard-coding /usr/lib/x86_64-linux-gnu/libretro/ and a known list of sonames that I can easily query with a directory listing from the outside.

...it's also one of the big reasons I prefer Mednafen over RetroArch for emulating any system that it supports. mednafen /path/to/rom.ext Just Works™. (Well, that and Mednafen's approach to configuring input devices is less frustrating when autodetection doesn't do the right thing.)

HardDiskDog commented 1 year ago

To be perfectly honest, the degree to which the lack of this complicates launching RetroArch from an external game browser is the number-one reason that I haven't yet tried switching from the RetroArch distributed in the Ubuntu repos to the Flatpak'd version.

It's bad enough when I'm more or less hard-coding /usr/lib/x86_64-linux-gnu/libretro/ and a known list of sonames that I can easily query with a directory listing from the outside.

...it's also one of the big reasons I prefer Mednafen over RetroArch for emulating any system that it supports. mednafen /path/to/rom.ext Just Works™. (Well, that and Mednafen's approach to configuring input devices is less frustrating when autodetection doesn't do the right thing.)

IKR? So many aspects of RetroArch make things completely unnecessarily time-consuming IMO; -This -Having to dig through the menu to edit playlists instead of the main screen where you're already browsing them -All the extra steps required for the "manual scan" option; your only option to import content that doesn't match the database -The frontend file browser for importing content defaulting to the same base directory every time, with the only option to remember your last directory being very temporary -Multiple features that could be done through the UI which you need to open an external file browser for (i.e. deleting shader presets)

I fail to understand any of it. So what if certain file types aren't core-specific, or certain games for the same system are preferable with different cores? If any of the workarounds suggested in this thread are viable and easy to implement enough, this should at least still be an option for the many people who want external browser launching and the like; for use case scenarios where these complications don't apply. I think many would agree that just File Explorer and command line launching are very useful, time-saving features in general, and I hope this is at least considered more.

i30817 commented 1 year ago

I added a bash linux auto completetion script for the -L command, to complete and list the possible installed cores.

If you don't know how to do this, you add a line like this to .bashrc

source /home/$USER/.bash_completions/retroarch.sh (where you put your script, has to be executable of course)

contents:

_retroarch_completion() {
    local cur_word prev_word type_list

    # COMP_WORDS is an array of words in the current command line.
    # COMP_CWORD is the index of the current word (the one the cursor is
    # in). So COMP_WORDS[COMP_CWORD] is the current word; we also record
    # the previous word here, although this specific script doesn't
    # use it yet.
    cur_word="${COMP_WORDS[COMP_CWORD]}"
    prev_word="${COMP_WORDS[COMP_CWORD-1]}"

    # Only perform completion if the current word starts with a dash ('-'),
    # meaning that the user is trying to complete an option.
    if [[ ${prev_word} == -L || ${prev_word} == --libretro ]] ; then

        VAR=$(find $HOME/.config/retroarch/cores/ -name "*_libretro.so" -execdir bash -c 'echo $(basename "$0" "_libretro.so")' "{}" \;)

        # COMPREPLY is the array of possible completions, generated with
        # the compgen builtin.
        COMPREPLY=( $(compgen -W "${VAR}" -- ${cur_word}) )
    elif [[ ${prev_word} == -M || ${prev_word} == --sram-mode ]] ; then

        VAR="
        noload-nosave
        noload-save
        load-nosave
        load-save
        "

        COMPREPLY=( $(compgen -W "${VAR}" -- ${cur_word}) )
    elif [[ ${cur_word} = -* ]]; then   
        VAR="-h --help -v --verbose --log-file --version --features --menu -c --config -L --libretro --appendconfig --subsystem -f --fullscreen --set-shader -N --nodevice -A --dualanalog -M --sram-mode -H --host -C --connect --port --nick --stateless --check-frames --command -P --bsvplay -R --bsvrecord --eof-exit -r --record --recordconfig --size -D --detach --max-frames -U --ups --bps --ips --no-patch --max-frames-ss --max-frames-ss-path --accessibility --load-menu-on-error -e --entryslot"

        COMPREPLY=( $(compgen -W "${VAR}" -- ${cur_word}) )
    fi

    return 0
}
complete -o default -F _retroarch_completion retroarch

I think it has a bug in some situations, but i don't recall the bug, or when it happens. I know, not very helpful. Frankly, i don't understand most of the script, i just added the branches that checks the '-L' and '-M' parts and copied the structure of another script i had from a library that adds such things automatically when a project using it is installed in another python project. And of course, this is useless in windows.

results in something like this when tab is pressed after -L:

$ retroarch -L 
bsnes_hd_beta        mame                 openlara
cannonball           mednafen_ngp         parallel_n64
citra                mednafen_pce         pcsx2
dolphin              mednafen_pce_fast    picodrive
dosbox_core          mednafen_psx_hw      ppsspp
dosbox_pure          mednafen_supergrafx  puae
easyrpg              mednafen_wswan       px68k
fbneo                melonds              reminiscence
fceumm               mesen                sameboy
flycast              mgba                 scummvm
genesis_plus_gx      mupen64plus_next     snes9x
gme                  neocd                swanstation
kronos               np2kai               vemulator

I also think there is a way to do the main switches (not the ones with arguments) without specifying them all for forward compatibility, but i really don't understand how that works, so i decided not to.

i30817 commented 1 year ago

I believe that in order to have auto-completion that reads from the executable themselves what the options are so we don't need to specify that list of options that can get out of date or create a script for one single cmd line terminal type, requires some standard i don't know how it works. Several programs in python just install something like this:

_retroarch_completion() {
    local IFS=$'
'
    COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \
                   COMP_CWORD=$COMP_CWORD \
                   _RETROARCH_COMPLETE=complete_bash $1 ) )
    return 0
}

complete -o default -F _retroarch_completion retroarch

And it works... for them... i think because they're using some kind of framework that can extract the option list from '--help' in 'complete_bash' or something (this doesn't actually seem to be a built-in from bash because i can't call it from there). If you try to use this directly, you'll see a nice env error, so it's worthless.

Still, you can 'just' implement the original request, this was just a aside from the problems of this alternative. I wouldn't mind that functionality either.

edit:

Ah... i think the env error might be because my 'retroarch' is a alias, because i'm not installing it, just compiling from source and adding a alias. Replacing $1 in that script above by the path to the retroarch executable.... still doesn't work (it starts retroarch instead of decomposing the options).

Which is probably not that strange, maybe it only works on python 'executables' (scripts) made with Typer which is the framework i use on my python projects that adds that bash completion script style.

I also found a interesting bug - or maybe feature - with starting retroarch while a wine game is running alt-tabbed - it prevents retroarch from starting up because:

[INFO] [Wayland]: Compositor doesn't support zwp_idle_inhibit_manager_v1 protocol
[INFO] [Wayland]: Compositor doesn't support zxdg_decoration_manager_v1 protocol
^C[ERROR] [Wayland]: libdecor failed to dispatch

Error comes after ctrl-c, so it was hanging on libdecor i guess. It seems like wayland doesn't want you running two fullscreen applications I guess.

Quit the game and it started again. Kind of cool, kind of annoying. Regardless, this is out of topic, and i'm stopping now, this was just to clarify the other comment.