libretro / RetroArch

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

[Feature request] basic .sh scripting support at game launch and exit #8546

Open fzacchi opened 5 years ago

fzacchi commented 5 years ago

I’ve written a set of scripts for RetroPie on the Raspberry Pi that activate the correct nonstandard refresh rates for each game that needs them on LCD monitors, by parsing a refresh list. LCDs support integer rates only, so for example with R-Type and Mortal Kombat the monitor runs at 55 Hz, with Neo Geo games at 59, with Double Dragon at 57 and so on.

It’s called by runcommand-onstart.sh (when the frontend launches a game) and runcommand-onend.sh (when exiting the emulator back into the frontend), and I’d love to have the same functionality on RetroArch. Running the refresh rate switching commands from the command line via ssh (on Lakka) sort of works, but there’s no hook that I can find to do it when launching and then quitting a lr- core.

The only previous discussion I found is here: https://forums.libretro.com/t/custom-scripts-system/4776

i30817 commented 5 years ago

This btw, will never work on wayland because they explicitly determine that the only one program allowed to run changes is a blessed, 'user-only' (probably suid) program that has no cmdline interface. Probably pointless aside but just something to mention.

orbea commented 5 years ago

This doesn't seem like a very good idea and we have an issue template for a reason, please fill it out because I am not following you desired behavior...

fzacchi commented 5 years ago

Thanks for the Wayland info. My primary, if not only, use case would be Lakka on the Raspberry Pi, however. The refresh rate switch commands work, I've already tested it, I just have no way to invoke them automatically without dropping to the command line each time.

It's not an issue, it's a feature request for something that RetroArch-the-frontend currently lacks: the ability to call a bash script right before the frontend launches a libretro core, and call another one when the core quits back into the frontend. They're called runcommand-onstart.sh and runcommand-onend.sh in RetroPie, but they can be called anything and be stored anywhere, it doesn't matter. RetroPie had that forever, and I've made Recalbox support it as well. I think there's no way to do it in Lakka by scripting alone, the frontend app itself has to be modified (please correct me if I'm wrong).

Basically as it stands now the frontend just does:

retroarch *libretro.so romname

the sequence should become:

/path/to/script/onstart.sh corename romname retroarch *libretro.so romname /path/to/script/onend.sh

Where can I look to try to hack it in myself?

orbea commented 5 years ago

What would these scripts do?

@bparker06 What do you think of supporting shell scripting inside of RetroArch, is this supportable or worth adding?

fzacchi commented 5 years ago

Just to be clear, by default they should do nothing, in fact the .sh files shouldn't even be there.

You can check out my repos to get a good idea of what my script does, but in short it's the only way to get smooth scrolling at the right speed on PAL on nonstandard refresh rate games without using Freesync or G-Sync, on the Raspberry Pi (RasPi doesn't support Freesync or G-sync anyway).

Others have fancy arcade setups using LCDs as marquees and programmable LEDs, joysticks and buttons that need per-game initialization, others use them for launch videos.

It's also not about what you can do with it right now, but what possibilities open up once the feature is there, IMO.

Ferk commented 5 years ago

Wouldn't it make more sense to do that through a core? You could use lutro/chailove to write scripts in lua/chaiscript or for bash something like https://github.com/SwedishGojira/libretro-bash-launcher

fzacchi commented 5 years ago

Interesting, but it seems unneedlessly complicated. My script needs to be fed the name of the core and the rom to work properly, so you should pass those to the bash launcher (how?) that would then pass them to my script ... doesn't make much sense.

andres-asm commented 5 years ago

It could certainly be done... But should it? at some point you have to draw a line and start thinking about the big picture. Big picture being the common denominator.

Scripting is usually a last resort solution to something that can't be done through an API. The proper solution is to use an API to do modeline switching (which is implemented already even though it may not suit your usecase ideally)

fzacchi commented 5 years ago

I actually agree with that :)

Yet, fully automatic modeline switching on Lakka on the Raspberry Pi is far, far away from completion. As it is it's best suited to CRTs anyway, while my script is way simpler and meant for standard LCDs.

It's working on RetroPie and Recalbox, so only Lakka is missing now. It just seems like a case of something easy enough to implement that it would be worth the cost (also for other uses than refresh rate change). I would do it myself if I knew where to start ...

ghost commented 5 years ago

you dont have to change the modeline it has been said before the cores can handle this internally if they need to all you to fix your 57 and others bordeline all you have to do is adjust your audio skew setting to 0.01 not sure about pal would need to test 50hz

ghost commented 5 years ago

LCDs support integer rates only

This is incorrect.

Most LCD monitors do not support many different refresh rates anyway (especially in the higher resolutions) besides the standard 24/30/50/60 and their 1.001 equivalents.

I think that running a script on startup and exit should be left to, well, scripts. I see no reason to add this functionality directly into RetroArch... especially where "scripts" in general or the execution of separate processs does not even work on the majority of platforms we support.

ghost commented 5 years ago

just to clarify above its maximum timing scew not audio skew setting my bad.

Load robocop with fba or any mame youll see it runs 60fps with an increased in pitch with sound as well with the default settings. Change it to 0.01 restart youll see it runs the right frame rate hope that clarifies any confusion

old post but pal is covered here

https://forums.libretro.com/t/perfect-audio-video-synchronization/12072

ghost commented 5 years ago

@grant2258 Please don't spread bad advice... it's absolutely required to be able to set modelines for proper operation in all circumstances... timing skew is not a solution to everything and won't fix larger framerate differences.

For example with MAME Mortal Kombat 1, on the scrolling page of all the fighters, the ONLY way to get this to be perfectly 100% smooth is either with a CRT+exact modeline, or a VRR display such as G-Sync/Freesync with the "sync content to exact framerate" option plus the frameskip core option disabled in MAME.

ghost commented 5 years ago

your entitled to your opinion 👍 from lcd to crt big jump just bear in mind sound effects timing as well. I know you have to agree with anything I say so ill agree to disagree

andres-asm commented 5 years ago

@grant2258 thing is this topic has nothing to do with your advice. Resolution switching is a valid request, this is why CRT switchres and VRR runloop were implemented.

The only thing you're achieving by lowering timing skew is you're disabling DRC, basically you're disabling vsync and running at the proper speed (with tearing for lower fps content and with tearing + skipping at higher fps content)

ghost commented 5 years ago

it has everything to do with this what this the usual team tag it the sound that takes the timing up on 57 fps games and that's why the timing skew fixes it. There is no tearing either

andres-asm commented 5 years ago

No it doesn't, the request is about basic scripting support for RetroArch so he can switch to the proper resolution + refresh rate combination.

You're claiming you can run 57hz content on a 60hz display with no tearing... RA is a lot of things but it's not magic.

Doesn't mean it will have horrible tearing, but there is gonna be a tear here and there. VSYNC exists for a reason.

ghost commented 5 years ago

lol there is no tearing set it and check i wont be wasting my breath on you and bparker last time you tagged team I got kicked because disagreed with him you fought his corner not intrested in in a tag team again we can agree do disagree not interested in arguing

fzacchi commented 5 years ago

LCDs support integer rates only This is incorrect.

CRU and the NVidia control panel on Windows, "vcgencmd hdmi_cvt "on the RasPi ... they let you change the refresh rate in 1hz increments only. Believe me, I've tried. It's not a big deal: it just means that any game is off by no more than 0.5 Hz in the worst case, so speed and music pitch aren't perfect, but very negligibly so. Scrolling however is just as smooth as the arcade was. No more horrid, choppy PAL scrollers. Transparency effects work.

Most LCD monitors do not support many different refresh rates anyway

Every single LCD monitor I tested is able to sync from 50 to 63 Hz in 1 Hz increments, which is the full range needed for 99.5% of games.

You're obviously right about audio timing skew not fixing the problem at all. Short of writing some kind of next gen, AI-powered, interpolating renderer, there's no way to have a 57 Hz game running on a 60 Hz screen without the speed being wrong or the scrolling being choppy.

For example with MAME Mortal Kombat 1, on the scrolling page of all the fighters, the ONLY way to get this to be perfectly 100% smooth is either with a CRT+exact modeline, or a VRR display such as G-Sync/Freesync with the "sync content to exact framerate" option plus the frameskip core option disabled in MAME.

Guess what: with my script MK is perfectly 100% smooth at the right speed on a lowly Raspberry Pi with any LCD monitor, old or new. In fact it's the main game I used for testing during development. That spinning fighters carousel doesn't lie.

basic scripting support for RetroArch so he can switch to the proper resolution + refresh rate combination.

Even simpler, the resolution always stays the same, the native LCD monitor one. Only the refresh rate changes.

especially where "scripts" in general or the execution of separate process does not even work on the majority of platforms we support.

This, sadly, is a strong argument against implementing .sh support.

I'm happy to have it working as well as it does on RetroPie, but it's clear that libretro is taking over, and Lakka is a much more elegant solution.

I can't stand choppy scrolling. The real solution is ubiquitous Freesync, but the Pi doesn't support it and it's not really needed anyhow (no on the fly changes during gameplay needed).

Another workable solution would be to simplify CRT Switchres and create LCD Switchrate: same resolution, per-game (or per-system) adaptive refresh. Groovymame has an LCD specific mode that works amazingly well, and was the main inspiration for me to create something similar for the Pi. Maybe that's what's worth pursuing for Lakka.

ghost commented 5 years ago

do me a favour leave your lcd at its default 60hz. Start ra goto setting audio machine timing skew set it to 0.01. Restart retroarch then play robocop on fba alpah. (dont touch dynamic audio)

Send me a link to your script ill see if there is any difference from this setting and what your script does.

ghost commented 5 years ago

i do agree one thing this shouldnt be such an issue mame has worked fine from the good old days. all you had to do was set your ini like this and t worked properly.

waitvsync               0
triplebuffer            1
matchrefresh         1
andres-asm commented 5 years ago

@fzacchi right, changing modes will always work better than what grant proposed here (disabling vsync and running 57hz content at 60hz).

Only ways I know to get proper scrolling and speed is mode switching or VRR.

ghost commented 5 years ago

im talking about stand alone mame you can get it looking good without all this messing about not perfect but has options to make everything presentable easily.

The biggest problem with RA is it messes the audio pitch up thats as bad as screen tearing Id love to hear a suggestion that actually works without setting per game that makes odd ball frame rates more presentable.

also how are you setting your modelines in windows 10 if this solution is better for you

andres-asm commented 5 years ago

You can't get 57hz content at proper speed and no tearing on a display that is set at 60hz, that's all I have been saying.

ghost commented 5 years ago

I just tested VVR scrolling in robocop is jerky works better with machine timing skew looks smooth to the eye. I know how to set modes in linux but not sure about windows setting per game seems a very odd way to deal with it. I guess there is no real solution but to tinker the machine timing does work well with 57 and up if you change it. I really cant notice any tearing in it with machine timing when you go below that you do notice it

ghost commented 5 years ago

@fzacchi Whether a monitor or video encoder can support those rates is still not a universal given... I routinely work with devices that only accept a single specific set of timings for either input or output. But anyway, most of the time you'll be stopped by the OS refusing to use timings outside the device's EDID, which won't have all those 1Hz increments in it... but sure if you force it, there's a chance it might work. Also the MAME dat shows the refresh rate for MK1 is 53.204948Hz.

Anyway, all of this is way off-topic for this thread I think. The topic is about running scripts on startup/exit, and that just doesn't belong in RetroArch IMO.

@twinaphex Care to chime in?

inactive123 commented 5 years ago

I really don't think this is the thread to be launching into direct MAME vs. RetroArch comparisons.

Let's try to de-escalate this and let's keep to the subject matter.

The subject should just be about scripting support in RA.

There still remains the issue that scripting pulls in a ton of dependencies and RA is already growing rather big as-is. It's a hard sell IMHO.

ghost commented 5 years ago

This isint about mame vs RA its about games 57.x-59.x fps running at 60mhz with the default timing skew running too fast and how to improve it or at least make it more presentable on a lcd running at the correct speed. Scripting isint available on all platforms like has been said before.

orbea commented 5 years ago

There still remains the issue that scripting pulls in a ton of dependencies and RA is already growing rather big as-is. It's a hard sell IMHO.

I think this is the bottom line, implementing and maintaining it could likely be extra burden with only limited benefit.

fzacchi commented 5 years ago

Whether a monitor or video encoder can support those rates is still not a universal given...

Well, no one's asking to make LCD refresh rate switching mandatory :)

But anyway, most of the time you'll be stopped by the OS refusing to use timings outside the device's EDID, which won't have all those 1Hz increments in it... but sure if you force it, there's a chance it might work.

In my real world testing it works 100% of the time on the Pi ... I was pretty surprised myself.

Also the MAME dat shows the refresh rate for MK1 is 53.204948Hz.

Yes, what do you mean exactly by that? The LCD runs at 53.0 Hz (rounded to the nearest integer), and the RA core makes up the 0.2 Hz difference by slowing the game down by 0.4% or so, just like it does for all those "60-but-not-quite" Hz NTSC or arcade systems when running on a 60 Hz LCD. Scrolling is perfectly smooth, the speed difference is negligible, the experience is night and day.

There still remains the issue that scripting pulls in a ton of dependencies and RA is already growing rather big as-is. It's a hard sell IMHO.

I understand wanting to keep RA feature parity across platforms, and I agree it's not worth pursuing it if the goal is full-fledged scripting support across every system RA runs on. It seemed to me that Lakka on the Pi support would be simple enough - just two hooks before and after launching the core.

Now I have to pester Alphanu for LCD support for CRT Switchres :)

DeadlySurgeon commented 2 years ago

My usage is to have a way to backup and retrieve my saves, to ensure my games are always synced cross platform. Right now I'm hacking this together with inotify for saving, and there is a place in RetroArch that you can add scripting before a ROM is loaded, however this feature is still nice.

alecov commented 9 months ago

Sorry to necro, but I also believe this would be a good addition. It doesn't seem complicated to implement and gives a lot of flexibility for a variety of different setups.

Setting refresh rates might or might not be a use case but discussing this particular functionality here is a red herring. The feature of custom hooks itself is useful much beyond this. These hooks can be used not only for specific functionality on a specific setup but also to work around things RetroArch still doesn't do.

Out of my head, I would use it for:

And likely more things related to ROM management or general ricing.

@inactive123 Why does this feature require lots of dependencies? It looks like a simple fork()+exec()+wait() in a few places and some support for custom menus.

sharmashivanand commented 2 months ago

I think this should be implemented. Hooking into Retroarch would be immensely helpful. It's just like WordPress has action and filter hooks (and JS has event observers).