Skip to content

Instantly share code, notes, and snippets.

@Grayfox96
Last active October 31, 2023 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Grayfox96/7ee4012edbec4e35ac83b670be78ae1b to your computer and use it in GitHub Desktop.
Save Grayfox96/7ee4012edbec4e35ac83b670be78ae1b to your computer and use it in GitHub Desktop.
from datetime import datetime, timedelta
import threading
def s32(integer: int) -> int:
return ((integer & 0xffffffff) ^ 0x80000000) - 0x80000000
def datetime_to_seed(datetime: int) -> int:
seed = s32(datetime + 1)
seed = s32(s32(seed * 1108104919) + 11786)
seed = s32(s32(seed * 1566083941) + 15413)
seed = s32(s32(seed >> 16) + s32(seed << 16))
if seed >= 0:
return seed
else:
return 0x100000000 + seed
class Clock:
def __init__(self, alarms: list[datetime]) -> None:
self.alarms = alarms
self._stopped = threading.Event()
self._thread = threading.Thread(
target=self.print_time_now, daemon=True)
def start(self) -> None:
if not self._stopped.is_set():
self._thread.start()
def stop(self) -> None:
self._stopped.set()
def print_time_now(self) -> None:
self._stopped.wait(0.5)
print()
string = ''
while not self._stopped.wait(0.01):
try:
current_alarm = self.alarms.pop(0)
except IndexError:
break
t = current_alarm - datetime.now()
time_until_alarm = 0
while time_until_alarm >= 0 and not self._stopped.wait(0.01):
time_now = datetime.now()
t = current_alarm - time_now
time_until_alarm = ((t.days * 3600 * 24)
+ t.seconds
+ t.microseconds / 1000000)
time_now = time_now.strftime('%d/%m/%Y %H:%M:%S')
string = (f'Time now: {time_now} | '
f'Time until next seed: {time_until_alarm:7.3f}')
print(string, end='\r')
print('\a', end='')
print(' ' * len(string), end='\r')
while not self._stopped.wait(0.1):
time_now = datetime.now().strftime('%d/%m/%Y %H:%M:%S')
print(f'Time now: {time_now}', end='\r')
def countdown(seconds: int = 5) -> None:
input(f'Once you press enter a countdown of {seconds} seconds '
'will begin. Press new game once it reaches 0.')
time_now = datetime.now().replace(microsecond=0)
countdown_time = time_now + timedelta(seconds=seconds)
time_until_new_game = 0
while time_until_new_game >= 0:
time_now = datetime.now()
t = countdown_time - time_now
time_until_new_game = ((t.days * 3600 * 24)
+ t.seconds
+ t.microseconds / 1000000)
time_now = time_now.strftime('%d/%m/%Y %H:%M:%S')
string = (f'Time now: {time_now} | '
f'Time until new game: {time_until_new_game:7.3f}')
print(string, end='\r')
print('\a', end='')
print(' ' * len(string), end='\r')
def get_mystery_byte(seconds: int = 5) -> int:
countdown(seconds=seconds)
dt = datetime.now()
print(f'Time when pressing new game: {dt.strftime("%d/%m/%Y %H:%M:%S")}')
dt = dt + ONE_SECOND
xored_datetime = (dt.day
^ dt.month
^ int(hex(dt.year)[-2:], 16)
^ dt.hour
^ dt.minute
^ dt.second
)
seed = None
while seed is None:
try:
seed = int(input('Type the seed you got: '))
except ValueError:
print('Seed must be an integer.')
continue
for mystery_byte in range(256):
if seed == datetime_to_seed(xored_datetime ^ mystery_byte):
print(f'\nMystery byte: {mystery_byte}\n')
break
else:
print('Seed number invalid!')
seed = None
return mystery_byte
def main():
while True:
mystery_byte = input('If you have it already, type your mystery '
'byte, otherwise just press enter: ')
if mystery_byte == '':
mystery_byte = get_mystery_byte()
break
try:
mystery_byte = int(mystery_byte)
except ValueError:
print('Mystery byte must be an integer between 0 and 255.')
continue
if not (0 <= mystery_byte <= 255):
print('Mystery byte must be an integer between 0 and 255.')
continue
break
while True:
try:
target_seed = int(input('Type the seed you want: '))
except ValueError:
print('Seed must be an integer.')
continue
if target_seed not in POSSIBLE_SEEDS:
print(f'Seed {target_seed} is not available on FFX PC version.')
continue
dt = datetime.now().replace(microsecond=0)
times: list[datetime] = []
for _ in range(600):
dt = dt + ONE_SECOND
xored_datetime = (dt.day
^ dt.month
^ int(hex(dt.year)[-2:], 16)
^ dt.hour
^ dt.minute
^ dt.second
^ mystery_byte)
if target_seed == datetime_to_seed(xored_datetime):
dt_real = dt - ONE_SECOND
times.append(dt_real)
if times:
print('Press new game at one of these seconds '
f'to get seed {target_seed}:')
for time in times:
print(f' {time.strftime("%d/%m/%Y %H:%M:%S")}')
clock = Clock(times)
clock.start()
input('Press enter to pick another seed.')
clock.stop()
else:
print(f'Impossible to manip seed {target_seed} '
f'with mystery byte {mystery_byte}.\n'
'Restart the game to reroll the mystery byte.')
POSSIBLE_SEEDS = [datetime_to_seed(i) for i in range(256)]
ONE_SECOND = timedelta(seconds=1)
if __name__ == '__main__':
main()
from datetime import datetime, timedelta
import threading
def s32(integer: int) -> int:
return ((integer & 0xffffffff) ^ 0x80000000) - 0x80000000
def datetime_to_seed(datetime: int) -> int:
seed = s32(datetime + 1)
seed = s32(s32(seed * 1108104919) + 11786)
seed = s32(s32(seed * 1566083941) + 15413)
seed = s32(s32(seed >> 16) + s32(seed << 16))
if seed >= 0:
return seed
else:
return 0x100000000 + seed
class Clock:
def __init__(self, alarms: list[datetime]) -> None:
self.alarms = alarms
self._stopped = threading.Event()
self._thread = threading.Thread(
target=self.print_time_now, daemon=True)
def start(self) -> None:
if not self._stopped.is_set():
self._thread.start()
def stop(self) -> None:
self._stopped.set()
def print_time_now(self) -> None:
self._stopped.wait(0.5)
print()
string = ''
while not self._stopped.wait(0.01):
try:
current_alarm = self.alarms.pop(0)
except IndexError:
break
t = current_alarm - datetime.now()
time_until_alarm = 0
while time_until_alarm >= 0 and not self._stopped.wait(0.01):
time_now = datetime.now()
t = current_alarm - time_now
time_until_alarm = ((t.days * 3600 * 24)
+ t.seconds
+ t.microseconds / 1000000)
time_now = time_now.strftime('%d/%m/%Y %H:%M:%S')
string = (f'Time now: {time_now} | '
f'Time until next seed: {time_until_alarm:7.3f}')
print(string, end='\r')
print('\a', end='')
print(' ' * len(string), end='\r')
while not self._stopped.wait(0.1):
time_now = datetime.now().strftime('%d/%m/%Y %H:%M:%S')
print(f'Time now: {time_now}', end='\r')
def get_mystery_byte() -> int:
clock = Clock([])
clock.start()
input('Press enter and new game at the same time.')
clock.stop()
dt = datetime.now()
print(f'Time when pressing new game: {dt.strftime("%d/%m/%Y %H:%M:%S")}')
dt = dt + ONE_SECOND
xored_datetime = (dt.day
^ dt.month
^ int(hex(dt.year)[-2:], 16)
^ dt.hour
^ dt.minute
^ dt.second
)
seed = None
while seed is None:
try:
seed = int(input('Type the seed you got: '))
except ValueError:
print('Seed must be an integer.')
continue
for mystery_byte in range(256):
if seed == datetime_to_seed(xored_datetime ^ mystery_byte):
print(f'\nMystery byte: {mystery_byte}\n')
break
else:
print('Seed number invalid!')
seed = None
return mystery_byte
def main():
while True:
mystery_byte = input('If you have it already, type your mystery '
'byte, otherwise just press enter: ')
if mystery_byte == '':
mystery_byte = get_mystery_byte()
break
try:
mystery_byte = int(mystery_byte)
except ValueError:
print('Mystery byte must be an integer between 0 and 255.')
continue
if not (0 <= mystery_byte <= 255):
print('Mystery byte must be an integer between 0 and 255.')
continue
break
while True:
try:
target_seed = int(input('Type the seed you want: '))
except ValueError:
print('Seed must be an integer.')
continue
if target_seed not in POSSIBLE_SEEDS:
print(f'Seed {target_seed} is not available on FFX PC version.')
continue
dt = datetime.now().replace(microsecond=0)
times: list[datetime] = []
for _ in range(600):
dt = dt + ONE_SECOND
xored_datetime = (dt.day
^ dt.month
^ int(hex(dt.year)[-2:], 16)
^ dt.hour
^ dt.minute
^ dt.second
^ mystery_byte)
if target_seed == datetime_to_seed(xored_datetime):
dt_real = dt - ONE_SECOND
times.append(dt_real)
if times:
print('Press new game at one of these seconds '
f'to get seed {target_seed}:')
for time in times:
print(f' {time.strftime("%d/%m/%Y %H:%M:%S")}')
clock = Clock(times)
clock.start()
input('Press enter to pick another seed.')
clock.stop()
else:
print(f'Impossible to manip seed {target_seed} '
f'with mystery byte {mystery_byte}.\n'
'Restart the game to reroll the mystery byte.')
POSSIBLE_SEEDS = [datetime_to_seed(i) for i in range(256)]
ONE_SECOND = timedelta(seconds=1)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment