Getting started with SteamDeck development
Project: SteamDeck
Introduction
I'm aiming at developing a simple game for the SteamDeck. I've started out by just proving it is possible to get something running on the ‘deck, utilising its built-in controls.
To start with I've created a simple OpenGL project that rotates a diamond with a single point light, casting a shadow onto a 2D plane below:
Setting up the code
The open-gl basics of this small demo are founded on the work of Joey de Vries, on his excellent website. All my development has been done on Windows, using Visual Studio 2022. A lot of the code will work on Mac and Linux, but I have not yet gotten around to testing those platforms.
First off, clone or otherwise download the code from the repo where it lives. Then either follow the first pages from the learnopengl website to install glad, GLFW and glm, or follow these steps:
Installing Prequisites
GLFW is a windowing library to use with OpenGL. It deals with all platform-specific windowing and input code. Download it here.
You can download pre-built libraries or the source code and cmake it. cmake can be downloaded from here and build GLFW from powershell by typing cmake . whilst in its directory.
However, using the UI tool to general a cmake configuration failed for me - possibly due to using VS 2022 and not 2019. No matter - the configuration included in GLFW worked fine.
Once you've ran cmake, open the GLFW .sln file and build the project.
Move the library files from glfw-<version>\src\debug to a library folder you can point the VS project at. Move the include files to somewhere nearby you can point the VS project at too.
The Diamond project already has a dependency on glfw.lib in its 'additional dependencies', however it won't be able to find it until you tell it where you put it - via 'project settings' => 'VC++ directories' => 'Library directories'.
Point the project at the include files via 'project settings' => 'VC++ directories' => 'Include directories'.
Next you will need GLAD - an interface to opengl. This was generated here and exists as the glad.c file inside the solution.
I am using OpenGl 4.2, Core, for C++ - however if you want to use a different version of OpenGL, you will need to regenerate this.
The Open GL Maths library will need downloading from here, the header files need to be added to the include file, ensuring it maintains the directory structure glm/ - do not copy the header files out of this structure as this is how they are referenced.
Finally, download the Steam SDK from Steam - you will need to be registered with Steam to do this. Also recommended is downloading the reference code - the SteamWorks Example application SpaceWar.
The app SpaceWar has app-id 480, and developers are allowed to re-use this id without paying for an id of their own - you can do this before publication if that is your intention.
Copy the header files to your include directory that you previously set up the project to reference, maintaining the /steam directory structure.
Also you will need to add the steam_api64.dll to sit alongside your source code.
Post-build events will copy all shader files (*.glsl), the steam_api64 dll, the steam_appid file and all VDF files (SteamInput files) to the debug or release directory.
The IGA file (see here for more information), game_actions_480.vdf, needs to be stored at C:\Program Files (x86)\Steam\Controller_Config\ (create that last directory if it is not there already).
Running the code
Once all this is set up, you should run it locally on your computer. Ensure you are targeting debug/x64 and run the program. The diamond will stay green if you have no controller plugged in, or turn a beautiful red colour if your controller is found. I have an Xbox controller, and that is what is configured for the app’. You may need to reconfigure the controls for a different controller.The rendering is simple Phong shading, there is no Phyics-Based Rendering yet. Ultimately I would like the diamond to be scratched plastic, but that would (probably) involve textures and I want it all to be self-created for the moment. An actual translucent diamond would be amazing, and maybe I’ll revisit it someday, but for now I wanted to keep the shadows simple.
Controls are configured for the left joystick to look around, the right joystick to move the camera. Pressing 'A' currently is configured for fire, 'B' for pause and right bumper for accelerate. These are the controls to be used ultimately in the demo game, however for now they are mapped like this:
- Fire: lock camera on diamond
- Pause: Show depth map from light's point of view
- Accelerate: Show Steam control binding menu
When the camera is locked, it can be unlocked by pressing fire again. During lock, the left joystick rotates the camera around the diamond, the right one rotates the light around the diamond (and alters it’s y-coordinate).
Note also that ASDW keys are configured to move around, with the CF keys moving vertically.
Running on the SteamDeck
First, find the SpaceWar app in the Steam Library. Install and run it on your 'deck.
To run your code, the windows debug runtime will need to be in your debug folder, before you deploy to the 'deck. Details on this can be found on the Steam API section of 'Bundling the Windows runtime'
Using the SteamOs DevKit client, connect to your Steamdeck and select 'Title Upload'. Set local folder to your x64Debug folder, type the start command of 'diamond.exe', and tick 'This title requires Steam Play'. After uploading you should be able to run it from 'Non-steam' games.
If the diamond does not turn red from green, it means that it has failed to connect properly to the controller via SteamInput. This seems to happen on first install - it is possibly something to do with sharing the App Id with SpaceWar, or the cloud sync on the vdf files (that configure the control bindings). Press the steam button and exit the app and retry - though sometimes just pressing the steam button and hit 'B' to go back makes it all work. Steam Input can be problematic - more on that in an upcoming article on getting SteamInput working!
The next article is About the Diamond Demo Code.
Further note: the issues with the Controller were found to be due to the incorrect use of an Action Manifest file. This has been commented out - though when first running an app on the 'deck, it might be necessary to uncomment it to let Steam know which files to use, and then re-comment it to get it working every time without pressing the Steam button. The line in question is at the end of EngineInput::Initialise(). The manifest files are really for when you have your own app-id.