Last active
October 30, 2021 13:03
-
-
Save Grayfox96/d00747b4da9aacd7a8346d61ec57bf6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""This script is used to find a seed by inputting the first 3 damage values | |
from Tidus and the first 5 damage values from Auron. It will look for files | |
in the ffx_ps2_seeds directory and try to find the seed that corresponds | |
to those damage values. | |
""" | |
import os | |
import time | |
import datetime | |
import array | |
from typing import List | |
DIRECTORY = 'ffx_ps2_seeds' | |
AURON_DAMAGE_VALUES = ( | |
( | |
260, 261, 262, 263, 264, 266, 267, 268, 269, 270, 271, | |
272, 273, 274, 275, 276, 278, 279, 280, 281, 282, 283, | |
284, 285, 286, 287, 288, 289, 291, 292, 293, 294 | |
), | |
( | |
520, 522, 524, 526, 528, 532, 534, 536, 538, 540, 542, | |
544, 546, 548, 550, 552, 556, 558, 560, 562, 564, 566, | |
568, 570, 572, 574, 576, 578, 582, 584, 586, 588 | |
) | |
) | |
TIDUS_DAMAGE_VALUES = ( | |
( | |
125, 126, 127, 128, 129, 130, 131, 132, 133, | |
134, 135, 136, 137, 138, 139, 140, 141 | |
), | |
( | |
250, 252, 254, 256, 258, 260, 262, 264, 266, | |
268, 270, 272, 274, 276, 278, 280, 282 | |
) | |
) | |
def get_input() -> List[int]: | |
while True: | |
input_string = input('Damage values (ATATATAA):') | |
for symbol in (',', '-', '/', '\\'): | |
input_string = input_string.replace(symbol, ' ') | |
damage_values = input_string.split() | |
try: | |
damage_values = [int(i) for i in damage_values] | |
except ValueError as error: | |
error = str(error).split(':', 1)[1] | |
print(f'{error} is not a valid damage value.') | |
continue | |
damage_values = damage_values[:8] | |
if len(damage_values) < 8: | |
print('Need at least 8 damage values.') | |
continue | |
damage_values_check = ( | |
('Auron', AURON_DAMAGE_VALUES, damage_values[0]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[1]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[2]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[3]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[4]), | |
('Tidus', TIDUS_DAMAGE_VALUES, damage_values[5]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[6]), | |
('Auron', AURON_DAMAGE_VALUES, damage_values[7]), | |
) | |
damage_values_indexes = [] | |
for character, damage_values_list, damage_value in damage_values_check: | |
try: | |
damage_values_indexes.append( | |
damage_values_list[0].index(damage_value)) | |
except ValueError: | |
try: | |
damage_values_indexes.append( | |
damage_values_list[1].index(damage_value)) | |
except ValueError: | |
print( | |
f'Invalid damage value for {character}: {damage_value}') | |
if len(damage_values_indexes) != 8: | |
continue | |
print('Damage values:', ', '.join([str(d) for d in damage_values])) | |
print(damage_values_indexes) | |
return damage_values_indexes | |
def convert_to_integer(damage_values_indexes: List[int]) -> int: | |
damage_values_as_int = 0 | |
for offset, damage_value in enumerate(damage_values_indexes): | |
damage_values_as_int += damage_value << offset * 8 | |
return damage_values_as_int | |
def find_seed(damage_values_as_int) -> None: | |
files_list = sorted(os.listdir(DIRECTORY)) | |
if input('Write anything to search in reverse: '): | |
files_list = reversed(files_list) | |
start_time = time.time() | |
for filename in files_list: | |
filename = os.path.join(DIRECTORY, filename) | |
print(datetime.datetime.now(), filename) | |
seeds_array = array.array('Q') | |
with open(filename, 'rb') as file: | |
seeds_array.fromfile(file, 0x100000) | |
try: | |
index = seeds_array.index(damage_values_as_int) | |
except ValueError: | |
continue | |
seed_number = int((filename[33:])) * 0x100000 + index | |
print(f'Seed found: {seed_number}') | |
break | |
else: | |
print('Seed not found') | |
print('Time elapsed: ' | |
f'{datetime.timedelta(seconds=time.time() - start_time)}') | |
def main() -> None: | |
damage_values_indexes = get_input() | |
damage_values_as_int = convert_to_integer(damage_values_indexes) | |
find_seed(damage_values_as_int) | |
if __name__ == '__main__': | |
main() | |
input('Press enter to quit...') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""This script will produce files in the "./ffx_ps2_seeds" directory each | |
containing the first 3 damage values from Tidus and the first 5 damage values | |
from Auron corrisponding to a given seed. | |
""" | |
import os | |
import datetime | |
import array | |
DIRECTORY = 'ffx_ps2_seeds' | |
SLICE_LENGTH = 0x100000 | |
TIDUS_DAMAGE_ROLLS = ( | |
125, 126, 126, 127, 127, 128, 128, 129, 129, 130, 130, | |
131, 131, 132, 132, 133, 134, 134, 135, 135, 136, 136, | |
137, 137, 138, 138, 139, 139, 140, 140, 141, 141 | |
) | |
TIDUS_DAMAGE_TO_INDEX = ( | |
125, 126, 127, 128, 129, 130, 131, 132, 133, | |
134, 135, 136, 137, 138, 139, 140, 141 | |
) | |
RNG_CONSTANTS_1 = ( | |
2100005341, 1700015771, 247163863, 891644838, 1352476256, | |
1563244181, 1528068162, 511705468, 1739927914, 398147329, | |
1278224951, 20980264, 1178761637, 802909981, 1130639188, | |
1599606659, 952700148, -898770777, -1097979074, -2013480859, | |
-338768120, -625456464, -2049746478, -550389733, -5384772, | |
-128808769, -1756029551, 1379661854, 904938180, -1209494558, | |
-1676357703, -1287910319, 1653802906, 393811311, -824919740, | |
1837641861, 946029195, 1248183957, -1684075875, -2108396259, | |
-681826312, 1003979812, 1607786269, -585334321, 1285195346, | |
1997056081, -106688232, 1881479866, 476193932, 307456100, | |
1290745818, 162507240, -213809065, -1135977230, -1272305475, | |
1484222417, -1559875058, 1407627502, 1206176750, -1537348094, | |
638891383, 581678511, 1164589165, -1436620514, 1412081670, | |
-1538191350, -284976976, 706005400 | |
) | |
RNG_CONSTANTS_2 = ( | |
10259, 24563, 11177, 56952, 46197, 49826, 27077, 1257, 44164, | |
56565, 31009, 46618, 64397, 46089, 58119, 13090, 19496, 47700, | |
21163, 16247, 574, 18658, 60495, 42058, 40532, 13649, 8049, | |
25369, 9373, 48949, 23157, 32735, 29605, 44013, 16623, 15090, | |
43767, 51346, 28485, 39192, 40085, 32893, 41400, 1267, 15436, | |
33645, 37189, 58137, 16264, 59665, 53663, 11528, 37584, 18427, | |
59827, 49457, 22922, 24212, 62787, 56241, 55318, 9625, 57622, | |
7580, 56469, 49208, 41671, 36458 | |
) | |
def s32(integer): | |
return ((integer & 0xffffffff) ^ 0x80000000) - 0x80000000 | |
def rng_array_generator(rng_value): | |
rng_value = s32(rng_value) | |
starting_values = [] | |
for rng_index in range(23): | |
rng_value = s32(s32(rng_value * 0x5d588b65) + 0x3c35) | |
rng_value = s32((rng_value >> 0x10) + (rng_value << 0x10)) | |
starting_values.append(rng_value & 0x7fffffff) | |
return starting_values | |
def get_rng_array(starting_value, rng_index, amount): | |
rng_value = s32(starting_value) | |
rng_constant_1 = RNG_CONSTANTS_1[rng_index] | |
rng_constant_2 = RNG_CONSTANTS_2[rng_index] | |
values = [] | |
for _ in range(amount): | |
rng_value = s32(rng_value * rng_constant_1 ^ rng_constant_2) | |
rng_value = s32((rng_value >> 0x10) + (rng_value << 0x10)) | |
values.append(rng_value & 0x7fffffff) | |
return values | |
def seed_to_file(slice_): | |
seeds = array.array('Q') | |
start = SLICE_LENGTH * slice_ | |
stop = SLICE_LENGTH * (slice_ + 1) | |
filename = f'{DIRECTORY}/ffx_ps2_seeds_part_{slice_:04}' | |
print(f'{datetime.datetime.now()}: ' | |
f'Creating {filename} with seeds ' | |
f'0x{start:08x}-0x{stop - 1:08x}') | |
for seed in range(start, stop): | |
starting_values = rng_array_generator(seed) | |
auron_rolls = get_rng_array(starting_values[22], 22, 37) | |
tidus_rolls = get_rng_array(starting_values[20], 20, 7) | |
numbers = [] | |
# first encounter | |
# get 3 damage rolls from auron | |
# and 3 damage rolls from tidus | |
for i in range(1, 6, 2): | |
numbers.append(auron_rolls[i] & 31) | |
tidus_damage_roll = TIDUS_DAMAGE_ROLLS[tidus_rolls[i] & 31] | |
numbers.append(TIDUS_DAMAGE_TO_INDEX.index(tidus_damage_roll)) | |
# second encounter after dragon fang | |
# get 2 damage rolls from auron | |
for i in range(32, 35, 2): | |
numbers.append(auron_rolls[i] & 31) | |
item = 0 | |
for offset, number in enumerate(numbers): | |
item += number << offset * 8 | |
seeds.append(item) | |
with open(filename, 'wb') as file: | |
seeds.tofile(file) | |
print(f'{datetime.datetime.now()}: Done creating {filename}') | |
def main(): | |
if not os.path.exists(DIRECTORY): | |
os.mkdir(DIRECTORY) | |
print('Created directory:', DIRECTORY) | |
start = int(input('Start:')) | |
stop = int(input('Stop:')) | |
print(f'{datetime.datetime.now()}: Creating {stop - start} files ' | |
f'(from #{start} to #{stop - 1})') | |
if start > stop: | |
quit() | |
for i in range(start, stop): | |
if i * SLICE_LENGTH > 0xffffffff + 1: | |
return | |
seed_to_file(i) | |
if __name__ == '__main__': | |
main() | |
input('Press enter to quit...') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment