Skip to content

Instantly share code, notes, and snippets.

@Peksa
Last active January 23, 2022 00:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Peksa/8059367b4f1a620df0ed9cba3ff6d5d2 to your computer and use it in GitHub Desktop.
Save Peksa/8059367b4f1a620df0ed9cba3ff6d5d2 to your computer and use it in GitHub Desktop.
Find recent companions and their Steam profiles from a Journey SAVE.BIN file
###################################################################
#
# Instructions!
#
# 1. Save this file as journey.ps1 somewhere
# 2. Open a PowerShell command prompt
# 3. Run this script from the powershell window, i.e.
# PS C:\code\journey-steamid-finder> .\journey.ps1
#
# Created by @peksa
# The latest version of this script is available at:
# https://gist.github.com/Peksa/8059367b4f1a620df0ed9cba3ff6d5d2
#
##################################################################
param ($saveFile)
$ErrorActionPreference = "Stop"
# Definition of the 21 different symbols a companion can have
$symbol_parts = 0x2d14d5cf4
$symbols = @(
0x7b1cd, 0x420e7, 0x7ced6, 0xb5820,
0xb1ec7, 0xb32a0, 0xad884, 0x2d5,
0x552c8, 0xb5ab5, 0x44110, 0x9cd4a,
0x63d8f, 0xaa117, 0xadd08, 0x0,
0x39ce7, 0xbd2f4, 0x55555, 0xbd0c6,
0xbd2d5
)
# Determine if a coordinate in a symbol should be filled or not
function Lookup-Pixel($lookup, $x, $y, $flags) {
$a = $x
$b = $y
If (($flags -band 1) -ne 0) {
$b = 2-$y
}
If (($flags -band 2) -ne 0) {
$a = $b
$b = $x
}
if ($a -eq 2) {
return 1
}
return ($lookup -shr $b*2+$a) -band 1
}
function Print-Companion-With-Symbol($symbol_id, $name, $url) {
$symbol = $symbols[$symbol_id]
$part = $symbol
$output = New-Object String[] 7
For ($p = 0; $p -lt 4; $p++) {
$part = $symbol -shr $p*5 -band 31
$pixels = $part -shr 2
$flags = $part -band 3
$lookup = ($symbol_parts -shr ($pixels * 6)) -band 0x3f
For ($y = 0; $y -lt 3; $y++) {
$line_no = [math]::floor($p/2)*4 + $y
For ($x = 0; $x -lt 3; $x++) {
$bit = Lookup-Pixel $lookup $x $y $flags
$output[$line_no] = $output[$line_no] + $bit
}
$output[$line_no] = $output[$line_no] + " "
}
}
Foreach ($line in $output) {
If ($line.length -eq 0) {
Write-Host -NoNewline " "
Write-Host -NoNewline $name.PadRight(24)
Write-Host $url
Continue
}
Foreach ($char in $line.ToCharArray()) {
If ($char -eq "1") {
Write-Host -NoNewline -BackgroundColor White -ForegroundColor White "##"
} else {
Write-Host -NoNewline " "
}
}
Write-Host
}
Write-Host
Write-Host
}
function Choose-Save-File {
If ($saveFile -ne $null) {
return $saveFile
}
$save_file_paths = @()
# Check for Steam cloud SAVE.BIN
$steam_cloud_path = "$env:LOCALAPPDATA\Annapurna Interactive\Journey\Steam\SAVE.BIN"
If ([System.IO.File]::Exists($steam_cloud_path)) {
$save_file_paths += $steam_cloud_path
}
# Check steam install path
$steam_install_path = (Get-ItemProperty -Path "HKCU:\SOFTWARE\Valve\Steam\" -name SteamPath).SteamPath
Get-ChildItem "$steam_install_path\userdata\*\638230\remote\SAVE.BIN" |
Foreach-Object {
$save_file_paths += $_.FullName
}
If ($save_file_paths.Count -eq 0) {
throw "Unable to automatically find a SAVE.BIN file, please specify the path to it manually using .\journey.ps1 -saveFile <path-to-save-file>"
}
ElseIf ($save_file_paths.Count -eq 1) {
Write-Host "Found SAVE.BIN in $($save_file_paths[0])"
return $save_file_paths[0]
}
Write-Host "Found multiple SAVE.BIN files, which one do you want to use?"
Write-Host "------------------------------------------------------------"
$choices = (49..57) + (65..90) | ForEach-Object { [char]$_ }
$output = ($save_file_paths | ForEach-Object { '[{0}] {1}' -f $choices[$i++], $_ }) -join [Environment]::NewLine
Write-Host $output
Write-Host
$answer = (Read-Host -Prompt 'Please make your choice').ToUpper()
return $save_file_paths[$choices.IndexOf($answer[0])]
}
$bytes = [System.IO.File]::ReadAllBytes((Choose-Save-File))
$companions_met = [System.BitConverter]::ToInt32($bytes, 0x1588)
$total_companions = [System.BitConverter]::ToInt32($bytes, 0x198c)
$total_journeys = [System.BitConverter]::ToInt32($bytes, 0x4c)
$offset_player_names = 0x19a8
$offset_symbols = 0x1200
$list = For ($player_no = 0; $player_no -lt 8; $player_no++) {
$player_offset = $offset_player_names+$player_no*32
$end_of_player_name_offset = $player_offset + [Array]::FindIndex($bytes[$player_offset..($player_offset+24)], [Predicate[Byte]]{ $args[0] -eq 0})
If ($end_of_player_name_offset -eq $player_offset) {
Break
}
$player_name = [System.Text.Encoding]::UTF8.GetString($bytes[$player_offset..$end_of_player_name_offset])
$steamid3 = [System.BitConverter]::ToInt32($bytes, $player_offset+24)
$symbol = $bytes[$offset_symbols + $player_no*60]
new-object psobject -Property @{
SteamName = $player_name
SteamID3 = "[U:1:$($steamid3)]"
ProfileURL = "https://steamcommunity.com/profiles/[U:1:$($steamid3)]"
Symbol = $symbol
Current = $player_no -lt $companions_met
}
}
Write-Host "Companions met on previous Journeys:"
$list | Where-Object { !$_.Current } | Select-Object -Property SteamName,ProfileURL,Symbol | Format-Table -AutoSize | Out-String -Width 9999
Write-Host "Met $companions_met companion(s) this journey, total journeys: $total_journeys, total companions met: $total_companions"
Write-Host
$list | Where-Object { $_.Current } | %{ Print-Companion-With-Symbol $_.Symbol $_.SteamName $_.ProfileURL }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment