aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--srb_lib.py50
1 files changed, 19 insertions, 31 deletions
diff --git a/srb_lib.py b/srb_lib.py
index 933ff6c..3daae7b 100644
--- a/srb_lib.py
+++ b/srb_lib.py
@@ -1,26 +1,31 @@
#!/usr/bin/env python3
-# Startdate: 2024-03-08-6 15:28
# File: srb_lib.py
-# Purpose: library for srb.exe savegame hacking
+# Location: https://bgstack15.ddns.net/cgit/srb_lib
+# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0-only
+# Startdate: 2024-03-08-6 15:28
+# Title: Library for manipulating savegame file for Snoopy vs. the Red Baron
+# Project: srb_lib
+# Purpose: library for srb.exe savegame hacking
# History:
# Usage:
# from srb.py
# Reference:
-# blog posts 2024-03
+# <https://bgstack15.ddns.net/blog/posts/2024/03/22/initial-research-for-hacking-savegame-files-for-snoopy-vs-the-red-baron/>
+# <https://bgstack15.ddns.net/blog/posts/2024/03/26/the-checksum-for-the-savegame-file-for-snoopy-vs-the-red-baron>
# <https://github.com/8051Enthusiast/delsum>
# crc width=32 poly=0x4c11db7 init=0x0 xorout=0x235b4b9c refin=false refout=false out_endian=little
-# Incorrect functions: https://gist.github.com/djsweet/3477115595efab31905be7000bb013bc FAILED
-# Fuctions that worked: https://gist.github.com/Lauszus/6c787a3bc26fea6e842dfb8296ebd630 Author: Lauszus
-# https://stackoverflow.com/questions/46109815/reversing-the-byte-order-of-a-string-containing-hexadecimal-characters
-# https://gamefaqs.gamespot.com/pc/930591-snoopy-vs-the-red-baron/faqs/46161
+# Incorrect functions: <https://gist.github.com/djsweet/3477115595efab31905be7000bb013bc> FAILED
+# Fuctions that worked: <https://gist.github.com/Lauszus/6c787a3bc26fea6e842dfb8296ebd630> Author: Lauszus
+# <https://stackoverflow.com/questions/46109815/reversing-the-byte-order-of-a-string-containing-hexadecimal-characters>
+# <https://gamefaqs.gamespot.com/pc/930591-snoopy-vs-the-red-baron/faqs/46161>
# Documentation:
# winetricks vd=1024x768
# winetricks vd=off
# Dependencies:
import sys, struct
-srb_lib_version = "20240318a"
+srb_lib_version = "20240320a"
# Table of byte positions of values in the savegame file, minus the first four bytes which are the checksum. Due to zero-indexing of python lists, but for ease of usage, we will always put a zero as the value of index 0. That is, profile 1 will use index 1 of the list.
# "Z<dddddddd" is the start of a profile.
@@ -29,13 +34,10 @@ PROFILE_START_POSITION = [0, 0x10, 0x142C, 0x2848]
POS_MONEY = 0x270
POS_HEALTH = 0x274 # 0-3 is available levels
POS_STUNT = 0x280 # 0-3 is available levels
-POS_GUN = 0x27C # 0-3 is available levels
+POS_GUN = 0x27C # 0-3 is available levels, although 4 is octo-gun
POS_EQUIPPED_WEAPON = 0x284
POS_PROFILE_IN_USE = 0x290
POS_NAME = 0x294
-# absolute 0x3fc is profile 1, so relative to start position
-# relative to profile: 0x3E8 is level 0, levelset 0
-# rel 0x404 is level 0 of levelset 1
NAME_CHARS = " ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!?"
@@ -193,9 +195,9 @@ def write_file(filename, checksum, data):
#f.write(struct.pack('>I',int(checksum)))
f.write(data)
-######## start copy-paste 2
-# https://gist.github.com/Lauszus/6c787a3bc26fea6e842dfb8296ebd630
-
+######## start embedded file
+# Source: https://gist.github.com/Lauszus/6c787a3bc26fea6e842dfb8296ebd630
+# Author: Lauszus
def reflect_data(x, width):
# See: https://stackoverflow.com/a/20918545
if width == 8:
@@ -216,7 +218,6 @@ def reflect_data(x, width):
else:
raise ValueError('Unsupported width')
return x
-
def crc_poly(data, n, poly, crc=0, ref_in=False, ref_out=False, xor_out=0):
g = 1 << n | poly # Generator polynomial
# Loop over the data
@@ -238,7 +239,7 @@ def crc_poly(data, n, poly, crc=0, ref_in=False, ref_out=False, xor_out=0):
crc = reflect_data(crc, n)
# Return the CRC value
return crc ^ xor_out
-##### end copy-paste 2
+######## end embedded file
def _get_data_from_data_object(data_object):
""" Helper function to either open file, or pass bytes through. """
@@ -249,28 +250,15 @@ def _get_data_from_data_object(data_object):
data = data_object
return data
-def _convert_dec_to_reverse_bytes(num_dec):
- """ Helper function to turn a given decimal value into the little-endian values for insertion into the data. """
- # Here is how to do this manually.
- #num_str = str(hex(num_dec))[2:]
- #num_str = ("0" if len(num_str) % 2 else "") + num_str
- #num_bytes = bytearray.fromhex(num_str)
- #num_bytes.reverse()
- #return bytes(num_bytes)
- # I learned how to do this the pythonic way.
- return struct.pack('<i',num_dec)
-
def get_money(data_object,profile_id):
""" Print in decimal the current money value of the profile_id. """
data = _get_data_from_data_object(data_object)
- money_dec = data[PROFILE_START_POSITION[profile_id]+POS_MONEY] + (data[PROFILE_START_POSITION[profile_id]+POS_MONEY+1] * 0x100)
- #money_dec = int(money_hex, base=16)
+ money_dec = struct.unpack_from('<1i',data,PROFILE_START_POSITION[profile_id]+POS_MONEY)[0]
return money_dec
def set_money(data_object,profile_id, money_dec):
""" Using data, set the money given in decimal for the given profile_id. """
data = _get_data_from_data_object(data_object)
- #money_bytes = _convert_dec_to_reverse_bytes(money_dec)
data = srb_pack('<i',data,PROFILE_START_POSITION[profile_id]+POS_MONEY,money_dec)
print(f"after setting money to {money_dec}, we checked and got {get_money(data,profile_id)}")
return data
bgstack15