🤖

Armored Core 6 Affinity Launcher

Published On:  

Tags:   Gaming Programming

Licenses:   Public Domain
Filter By License


The AC6Launcher is a small project that launches Armored Core 6 (or the AC6 Coop Launcher) without the stutters. The launcher sets the CPU affinity of armoredcore6.exe and bans the use of CPU0. This is a common solution to stop AC6 from severe stuttering.

Where to get it

https://gitlab.com/samurailink3/ac6launcher

Instructions are on the Readme on that page.

How it works

  • Launches AC6, either through the standard armoredcore6.exe or the Coop Launcher ac6_for_coop_launcher.exe
  • Watches for armoredcore6.exe
  • After it finds the process, wait 15 seconds then…
  • Sets CPU affinity to block only the first processor
  • No more stutters 🙂

Background (aka story time)

Armored Core 6 has a well documented problem with stuttering on some systems. Stuttering was so bad that pre-rendered cutscene FMVs would continue playing for a full minute after the audio completed. It was bad. Originally, this stuttering led me to just outright refund the game on Steam, but recently I decided to give it another shot.

One very strange suggestion led me to setting core affinity on the armoredcore6.exe process to ban the use of CPU0, the first CPU core. Suddenly, no more stutters. It was magical. So the workflow was now:

  • Launch AC6, either through the excellent Armored Core Coop Mod or regularly through Steam
  • Open Task Manager
  • Navigate to the Details tab
  • Right click armoredcore6.exe
  • Set affinity
  • Unchcked CPU 0 and press OK

The main issue with this is that you need to do this every time you launch the game.

I would regularly load into a mission, spend a few minutes wondering why it felt so bad to play, then remembering that I needed to do the Task Manager Dance to get a good gameplay experience.

Several other posters who had encountered this problem suggested using Process Lasso to force AC6 away from CPU0. I didn’t want yet another piece of software running just to manage a different piece of software that was being buggy, so I tried to make my own solution. First step: Simple batch file.

Stack Overflow led me to this result:

https://superuser.com/questions/908848/how-do-i-permanently-set-the-affinity-of-a-process

So I should be able to launch the game with something similar to: X:\Windows\System32\cmd.exe /C start /affinity Y game.exe

But this didn’t work…

I’m running AC6 through the Coop mod, which has its own launcher executable. If I launched the multiplayer launcher with custom affinity set, it would instantly crash. Furthermore, setting any affinity on the multiplayer launcher didn’t pass that affinity to armoredcore6.exe (you’d need to specifically launch sub-processes with affinity inherited from the parent process). Dead end.

I needed to create my own launcher launcher. A launcher to launch the launcher that launches the game. Here’s the rough steps for my application:

  • Launch ac6_for_coop_launcher.exe
  • Grab the process table and look for armoredcore6.exe
  • Once you have the AC6 PID, wait and…
  • Set the process affinity to use all cores except CPU 0

Meme: Oh yeah. It’s all coming together.

This project was relatively simple to put together, but did require me to dig into using Windows syscalls, which I don’t have a ton of experience with. I ended up testing out Notion’s AI here and it did a pretty acceptable job! I gave it a page with my current research and had it take a crack at solving the problem.

Initially the AI did a great job at building the boilerplate of the application, including this findProcess function, but struggled in some other areas. Initially it wanted me to use some deprecated syscall functions. Then it often suggested using windows.SetProcessAffinityMask, which doesn’t exist. Then it caught a bug it had introduced which was setting an invalid number of processors in the affinity mask. In the end, it suggested this bit of code that solved that particular issue:

	// Set affinity mask
	mask := ^uintptr(1)
	numCPU := runtime.NumCPU()
	if numCPU < 64 {
		mask = (1 << numCPU) - 2
	}

As a disclaimer, I hate bit-math. So I did a bunch of manual testing and it seems like it did the trick.

I’m still experimenting with using AI in programming and GameDev tasks. I have a lot of opinions on AI (room-temperature takes, mostly), but was mostly pleasantly surprised with how it saved me time with this micro-project.

In the end, I ended up very lightly cleaning up the code and writing some docs. I released the code as Public Domain software via The Unlicense. If you’d like to contribute in any way, send a PR on GitLab.

In the meantime, I’ll be playing Armored Core 6 - without the stutters.