Skip to content

Instantly share code, notes, and snippets.

@shawly
Last active April 21, 2020 23:36
Show Gist options
  • Save shawly/f071ee74b2982beb3d8bb543e06817e4 to your computer and use it in GitHub Desktop.
Save shawly/f071ee74b2982beb3d8bb543e06817e4 to your computer and use it in GitHub Desktop.
Batch script for creating emulator shortcuts with commandline options within GeForce Experience for game streaming. (usage examples in the comment section)
@echo off
title GeForce Experience Shortcut generator
setlocal EnableExtensions EnableDelayedExpansion
if %1.==. goto usage
set executable=%1
if not exist %executable% goto :exenotfound
for %%A in (%executable%) do (
set exefullpath=%%~fA
set exeworkingdirectory=%%~dA%%~pA
)
if %2.==. goto usage
set scanpath=%2
if %3.==. goto usage
if not %3.==. (
set _input=%*
call set _reduce1=%%_input:%1 =%%
call set _args=%%_reduce1:%2 =%%
)
if exist %scanpath%\* (goto createShortcutForDir)
if exist %scanpath% (set recursive=false & goto createShortcutForFile)
goto scanpathnotfound
:exenotfound
echo Could not find executable %executable%
exit /B 1
:scanpathnotfound
echo Could not find file or directory %scanpath%
exit /B 1
:usage
echo Usage: createGFEShortcuts.bat "^<X:\path\to\executable.exe^>" "^<X:\path\to\romfolder\^|X:\path\to\romfile.ext^>" ^<-arg1 {rom} -arg2 {romdir}^>
echo Placeholders: {rom}=path to rom; {romdir}=path to rom folder
echo Note: Execute "set recursive=true" beforehand if your roms are located in separate subfolders e.g. X:\path\to\romfolder\rom name\romfile.ext
exit /B 1
:createShortcutForDir
call:cleanpath scanpath
for %%A in ("%scanpath%") do (
set romdir=%%~fA
)
if not defined recursive (set recursive=false)
echo Creating shortcuts for directory %romdir% ^(recursive=%recursive%^)
if /I %recursive% == true (
set recurseParam=/D
)
for %recurseParam% %%i in ("%romdir%\*") do (
set scanpath="%%i"
call:createShortcutForFile
if %errorlevel% neq 0 goto eof
)
goto eof
:createShortcutForFile
for %%A in (%scanpath%) do (
set rom=%%~fA
set romname=%%~nA
if /I %recursive% == true (
for %%B in ("%%~fA\*") do (
set rom=%%~fB
)
set romname=%%~nxA
)
set romdir=%%~dA%%~pA
set romshort=%%~sA
)
echo Creating shortcuts for file "%rom%"
call:createShortcut
goto eof
:eof
if %errorlevel% neq 0 echo Script exited with an error (%errorlevel%)
exit /B %errorlevel%
::Functions
:createShortcut
set shieldAppsPath=NVIDIA Corporation\Shield Apps
set shortcutPath=%LOCALAPPDATA%\%shieldAppsPath%
set shortcutName="%romname%"
set shortcutFullpath=%shortcutPath%\\%shortcutName%.lnk
set shortcutFullpath=%shortcutFullpath:'=''%
set shortcutTarget=%exefullpath%
set shortcutWorkingDirectory=%exeworkingdirectory%
set _tmp=%_args%
call set _tmp=%%_tmp:{rom}=\"%rom%\"%%
call set _tmp=%%_tmp:{romdir}=\"%romdir%\"%%
call set _tmp=%_tmp:'=''%
set shortcutArguments=%_tmp%
set streamingAssetsPath=%shieldAppsPath%\StreamingAssets
set assetsPath=%LOCALAPPDATA%\%streamingAssetsPath%
set boxartFullpath=%assetsPath%\%romname%\
if not exist "%boxartFullpath%\box-art.png" (
if not defined usecustomboxart (set usecustomboxart=false)
echo Adding box-art.png for shortcut... ^(usecustomboxart=%usecustomboxart%^)
if not exist "%boxartFullpath%\*" (
echo Creating directory "%boxartFullpath%"
mkdir "%boxartFullpath%"
)
echo Adding box-art.png...
if /I %usecustomboxart% == true (call:copyboxart) else (call:generateboxart)
)
echo Creating shortcut %shortcutFullpath%
powershell $s=(New-Object -COM WScript.Shell).CreateShortcut('%shortcutFullpath%');$s.TargetPath='%shortcutTarget%';$s.WorkingDirectory='%shortcutWorkingDirectory%';$s.Arguments='%shortcutArguments%';$s.Save();echo $s;
if %errorlevel% neq 0 exit /B %errorlevel%
goto eof
:copyboxart
echo Copying custom %~dp0box-art.png to %boxartFullpath%
copy /Y "%~dp0box-art.png" "%boxartFullpath%"
if %errorlevel% neq 0 exit /B %errorlevel%
goto eof
:generateboxart
echo Generating %boxartFullpath%box-art.png
powershell Add-Type -AssemblyName System.Drawing;$filename='%boxartFullpath%\box-art.png';$bmp=new-object System.Drawing.Bitmap 628,888;$font=new-object System.Drawing.Font Consolas,24;$brushBg=New-Object Drawing.SolidBrush([System.Drawing.Color]::FromArgb(254, 29, 29, 29));$graphics=[System.Drawing.Graphics]::FromImage($bmp);$graphics.FillRectangle($brushBg,0,0,$bmp.Width,$bmp.Height);$graphics.Dispose();$bmp.Save($filename)
if %errorlevel% neq 0 exit /B %errorlevel%
goto eof
:cleanpath var
setlocal enableextensions enabledelayedexpansion
set "_varName=%~1"
set "_tmp=!%~1!"
set "_tmp=%_tmp:"=%"
if not defined _tmp set "_tmp=."
if "%_tmp:~-1%"=="\" set "_tmp=%_tmp%."
for %%# in ("%_tmp%") do set "_tmp=%%~f#"
endlocal & set "%~1=%_tmp%"
goto eof
@shawly
Copy link
Author

shawly commented Mar 18, 2019

FYI: I probably won't support this any further, since I figured out, that I preferred Steams BigPicture mode and rather use Ice to add my games. I still wanted to finish this little project since I started it and it might be of use for people that don't want to use BigPicture.

Save the script as batch and execute it via cmd once to see how to use it. Right now it is currently not fully compatible with CEMU since the executable lies within GAMEFOLDER\code*.prx, so for CEMU only single file mode is usable.

Usage:

Usage: createGFEShortcuts.bat "<X:\path\to\executable.exe>" "<X:\path\to\romfolder\|X:\path\to\romfile.ext>" <-arg1 {rom} -arg2 {romdir}>
Placeholders: {rom}=path to rom; {romdir}=path to rom folder

Make sure to put quotes on paths but also make sure to not put quotes around your arugments themselves.
It's robust enough to handle relative paths aswell, as it generates absolute paths, but your mileage may vary.
The parameters are fixed, the first parameter has to be the path to the executable you want to add, the second is the path to the rom or romfolder and everything AFTER parameter 1 and 2 is used for arguments, if you don't put quotes on your paths and those paths have spaces this script will fail, as spaces are used to split parameters within batch!

Usage example for single files ({rom} is a placeholder used for arguments to supply the absolute path to the rom file):

createGFEShortcuts "D:\emulators\CEMU\cemu.exe" "D:\roms\wiiu\Breath of the Wild\code\U-King.rpx" -g {rom}

Usage for rom folders:

createGFEShortcuts "D:\emulators\RetroArch\retroarch.exe" "D:\roms\nes" -L "D:\emulators\RetroArch\cores\nestopia_libretro.dll" {rom}

Usage for rom folders where roms lie in subdirectories (e.g. D:\roms\gcn<gamename>\game.iso), you have to set the variable recursive to true:

set recursive=true
createGFEShortcuts "D:\emulators\Dolphin\Dolphin.exe" "D:\roms\gcn" --batch --exec={rom}

Network shares also work.

createGFEShortcuts "D:\emulators\mGBA\mgba.exe" "\\HOST\roms\gba\anygbarom.gba" {rom}

Normally the script generates a blank box-art.png for every shortcut, but you can replace this with your own default box-art, for single files you can use a cover from your game, rename it to box-art.png (make sure it's a PNG). For multi rom generation you should probably use a more generic image as box-art.png. The box-art.png file has to be in the same folder as the script (not the working directory but actually where the script is located)

set usecustomboxart=true
set recursive=true
createGFEShortcuts "D:\emulators\Dolphin\Dolphin.exe" "D:\roms\gcn" --batch --exec={rom}

To turn off recursiveness and custom box arts you have to reset the variables or set them to false:

set usecustomboxart=
set recursive=

Technically this can be used for more than just roms and emulators, since it's more or less just a shortcut generator for GFE. You can use any executable and file, so you could even add Notepad++ to GFE (if anyone might want such a thing):

createGFEShortcuts "C:\Program Files\Notepad++\notepad++.exe" "D:\textfiles\My Awesome GFE Texteditor.txt" -nosession {rom}

{rom} represents the path to "D:\textfiles\My Awesome GFE Texteditor.txt" and the name of the file is used as name for your shortcut, so in your game streaming client it will be called "My Awesome GFE Texteditor".
You could also add Chrome and open up a specific homepage or whatever you want to do with it, feel free.

If you want to delete masses of shortcuts within GFE because you have a lot or accidentally provided the wrong path in recursive mode, there is an easy trick, just delete the folders for the shortcuts you don't want within "C:\Users%username%\AppData\Local\NVIDIA Corporation\Shield Apps\StreamingAssets" and then open up the game stream settings within GFE (where you can add shortcuts), GFE will then delete any shortcut that doesn't have a box-art.png within StreamingAssets.

@lulle2007200
Copy link

Very useful script.
Do you, by any chance, know, whre nvidia stores the landscape box arts that are displayed when you open the nvidia app?

@shawly
Copy link
Author

shawly commented Apr 21, 2020

@lulle2007200
Thanks! I'm not sure which landscape box arts you mean, do you mean the box arts on the home tab in GFE?
If so I'd have to tell you that they probably aren't stored locally as it seems, I've scrawled through the NVIDIA folders within AppData but couldn't find anything that relates to the covers.

@lulle2007200
Copy link

When you open the gamestream app on an nvidia shield device, it displays some of the available games with landscape boxart. When you click on "my library" (or whatever its called), it displays all of the available games with portrait boxarts.
Almost thought so as i didnt find any sign of the landscape boxarts while digging through the nvidia files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment