How I turn my pc into a gaming console in a click of a button

Why do I need that?

Well simply put I got a tv a year ago, and being mostly a console gamer I had neglected my PC in favor of my steam deck, but now that I had a tv bigscreen gaming made more sense.

I did upgrade my graphics card at the end of 2024 I think after year of rocking an AMD RX 580 to a Radeon RX 7800 XT I believe?

But sitting at my desk to play games after having spend the rest of my day at it didn’t fell right.

I didn’t have the money nor space to build a dedicated console PC, and I live in a single room appartment, so what made the most sense was to use a long HDMI cable route it behind furnitures in an attempt to hide it.

To make switching from my desk to my tv setup, I wanted to have steam big picture running at all time, on a separate display. No big deal I could just have steam running under GNOME, but I would miss the benefits of running steam under gamescope.

I looked up a way to have two separate graphical session at the same time on two separte display, the idea would have been to have a separte TTY per display and run GNOME on one and steam on the other.

I couldn’t find a way of doing just this.

The following setup is the solution I ended up on by following this idea

The solution

Having two tty and running GNOME on one and Steam on the other is what I ended up with, but not at the same time.

I just needed a way to effortlessly switch between the two, I don’t really need my Desktop when I play on the TV, and vice versa.

So good old ALT+F something it is, and it works but there is two issues:

The second one is not entierly fixed, but going back to gdm and logging in there unlocks GNOME. And we will make so that exiting steam bigpicture get us back to GNOME and stop steam itself.

Scripting the launch of steam bigpicture

The first element we need is setting up a script that will launch steam bigpicture inside of gamescope. I followed a few article and looked at how various distro that ship with bigpicture do it.

And wrote that script:

#!/bin/sh
test ! -z "$(command -v mangoapp)" && \
    MANGO_HUD="--mangoapp"

OPT="--adaptive-sync --hdr-enabled"
RES="-W 3840 -H 2160"
FREQ="-r 120"
OUTPUT="-O HDMI-A-1"
gamescope $RES $FREQ $OUTPUT $OPT "$MANGO_HUD" -e -- steam -steamdeck -steamos3
exit

First it enable mangohud so we can show the performance overlay, and use the options for that within steam.

We set a few option so we have VRR and HDR, set the display resolution, the refresh rate, and the ouput.

Somehow my setup work with 120Hz and all those options you millage may vary since AMD drivers still lack HDMI 2.1 support. At HDMI 2.0 we might be loosing some color accuracy but I have yet to notice it.

We pass all those options to gamescope, and tell steam to behave like we are a steamdeck on steamos, if not you will miss on the performance tab option that allow you to tweak gamescope settings within steam

Starting steam itself when logging in

Now that we’ve set it up we can manually launch steam with all the right option, but we still need to automate the launch of steam.

Since we don’t want to logg off and go back to a Display Manager, we have another option, logging-in in a tty and autolaunching our script.

The way I do this is in my .profile I check in which tty we are and if we are let’s say on TTY3 we start steam:

$HOME/.profile:

#!/bin/sh

STEAM_TTY="/dev/tty3"

if test "$(tty)" = "$STEAM_TTY"; then
    exec bigpicture
fi

I then modified getty so that the chosen tty will autologin, but stumbled on two issues: - steam won’t launch properly until we swith to the right tty - the script will be reruned anytime we quit steam because of the autologin, which makes the whole gnome lock screen issue a pain in the ass

the first issue is solved by making a script that make sure we are focusing the steam tty, before launching steam:

~/.local/bin/bigpicture-session:

#!/bin/sh
STEAM_TTY_PATH="$1"
STEAM_TTY="$(basename "$STEAM_TTY_PATH")"
test -z "$STEAM_TTY" && exit

# wait until we have switched to the correct TTY, if not steam will fail to start

curr_tty() {
    cat /sys/devices/virtual/tty/tty0/active
}
wait_until_tty_is_active() {
    test $(curr_tty) = "$STEAM_TTY" && return
    while true; do
        inotifywait -q -e modify /sys/devices/virtual/tty/tty0/active
        test $(curr_tty) = "$STEAM_TTY" && return
    done
}

wait_until_tty_is_active && bigpicture

and then modify the .profile so that it executes bigpicture-session instead of bigpicture

#!/bin/sh

STEAM_TTY="/dev/tty8"

if test "$(tty)" = "$STEAM_TTY"; then
    exec bigpicture-session "$STEAM_TTY"
fi

Creating a new TTY

The second issue was a bit harder to fix, to prevent the autlogin to keep launching steam in a loop we have to make the tty temporary, we have to create a new tty and use systemctl to start it like a service.

this is done by editing the following file: /etc/systemd/system/getty@tty8.service.d/override.conf with the command systemctl edit getty@tty8

[Service]
ExecStartPre=chvt 8
ExecStart=
ExecStart=-/sbin/agetty --noreset --noclear --autologin liz - ${TERM}
ExecStop=chvt 2
Environment=XDG_SESSION_TYPE=wayland
Restart=no

What it does is run agetty with autologin, but prevent the service to Restart and recreate the session.

We also make use of chvt to switch to tty8 our new steam tty and at the end of the service we switch back to tty2 where gnome is running.

With all of this in place we can now start steam bigpicture in a new tty with just a call to systemctl:

systemctl start getty@tty8.service

Now we just need a way to start all of this with our tv remote and we will have evrything we need.

Automating all this with my tv remote

Right now you might be thinking how having to start a service is easier than switch to a tty and logging in?

Well… we’re not going to start it manually of course!!

Home assistant to the rescue

Okay, home assistant allows you to run ssh commands in automations, the setup is a bit weird because you can’t to it within home assitant you have to edit a config file.

Making a new user to isolate things a bit

Also I don’t want to give it to much permission so we will create a new user called tvmode that will be used to start the service and have just the right it needs, thanks to sudo configs.

We start my making our new user tvmode with useradd:

sudo useradd -s /bin/sh -g tvmode -d /var/tvmode tvmode

We set is shell to /bin/sh create a new group and set it’s home directory to /var/tvmode.

We now need a script that will start the service:

/var/tvmode/start-tv-mode:

#!/bin/sh
SERVICE="getty@tty8.service"

stop_steam() {
    steam_pids="$(pgrep -x steam)"
    [ $? -ne 0 ] && return
    for pid in $steam_pids; do
        tail_args="$tail_args --pid=$pid"
    done
    sudo -u liz -- /usr/bin/steam -shutdown
    tail $tail_args -f /dev/null
}

if systemctl is-active --quiet "$SERVICE"; then
    sudo chvt 8 
else
    stop_steam
    sudo /usr/bin/systemctl start "$SERVICE"
fi

This script does one thing we had yet to fix: you can’t have multiple session of steam running at the same time, we need to stop steam before we start the service.

Why before? because steam will not stop if we are in a different tty than the one it currently is on…

So we ask it politely to stop itself (killing it create a lot of zombie process), with steam -shutdown and wait for all it’s process top stop before countinuing.

Other than that the script will switch us back to tty8 if the service is currently running or it will start the service, after making sure steam is not running!

This script makes heavy use of sudo, to start the service, to switch to tty8 and to call steam as our main user (if not it will create a new steam install in tvmode folder..)

And to make sure we only have the right we need we had those lines to the sudoers config:

visudo:

tvmode    ALL=(root) NOPASSWD: /usr/bin/systemctl start getty@tty8.service, /usr/bin/chvt 8
tvmode    ALL=(liz) NOPASSWD: /usr/bin/steam -shutdown

Those allow tvmode to run /usr/bin/systemctl start getty@tty8.service, /usr/bin/chvt 8 as root without a password, and as our user (liz) /usr/bin/steam -shudown also without a password.

Now we can automate everything with home assistant

Finally home assistant is really here

Running shell script via ssh through home assistant

Well first we have to edit configuration.yaml within the docker config folder

it will allow us to execute the start-tv-mode script from home assistant automations

configuration.yaml:

...

shell_command:
  switch_deskbottom_to_tv: ssh -i /config/.ssh/id_ed25519 -o UserKnownHostsFile=/config/.ssh/known_hosts tvmode@192.168.1.109 /var/tvmode/start-tv-mode
  deskbottom_switch_back_to_desktop_mode: ssh -i /config/.ssh/id_ed25519 -o UserKnownHostsFile=/config/.ssh/known_hosts tvmode@192.168.1.109 sudo -u liz steam -shutdown

I had to make a ssh key just for this as it is run through docker and point ssh to it’s known_hosts and ssh key.

See home assistant docs on shell commands

Making an home assistant automation

Go to the automation tab and make a webhook automation, we will use an android tv app to post to the webhook url to start the script

this is my yaml for it:

alias: steam bigpicture
description: ""
triggers:
  - trigger: webhook
    allowed_methods:
      - POST
      - PUT
    local_only: true
    webhook_id: "your-webhook"
conditions: []
actions:
  - action: shell_command.switch_deskbottom_to_tv
    metadata: {}
    data: {}
    response_variable: steam_still_running
mode: single

I did remove the webhook_id just in case, you should set something secure, by default one is auto generated

I have a second automation to quit steam with the remote, this one have not been thorougly tested:

alias: Switch deskbottom back to desktop
description: ""
triggers:
  - trigger: webhook
    allowed_methods:
      - POST
      - PUT
    local_only: true
    webhook_id: switch-deskbottom-back-to-desktop-9s9phJ1NyQO8hi3B6F_sOTcP
conditions: []
actions:
  - action: shell_command.deskbottom_switch_back_to_desktop_mode
    metadata: {}
    data: {}
mode: single

Once we have all this I use tvQuickAction, though you have to pay for the pro version to get the http options.

And mapped the red button of the remote to switch input and then post to the webhook url!!

I did the same for quitting steam but with a long press instead.

Conclusion

The software setup is quite convoluted but works well and allows me to easilly grab a controller and just play.

To make use of wired controller I purchased a usb powered hub and extender that uses cat-6 cable as an extension, it works quite well and been able to use 4 controller at the same time on the hub.

I also plugged in an nfc reader with a pretty case printed by my gf (which own this domain ‘), so that I can use zaparoo to launch steam game. It’s a cool project from the mister community that let’s you create nfc tags to launch your mister and steam games.

One improvment I still miss is being able to detect if my pc is sleeping, wake it up and launch steam via home assistant. I have tried to implement that but left this part out, as it’s not really functional.

I hope you enjoyed reading this wall of text and if you have any question you can it me up on mastodon: @spaceluciolle@eldritch.cafe