-
-
Save bbayles/a5739736fc997b2606fecc2a9389ef30 to your computer and use it in GitHub Desktop.
The Crow: City of Angels for PlayStation - generate all level passwords
This file contains hidden or 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
| button_map = { | |
| "X": 0x04, | |
| "C": 0x03, | |
| "T": 0x02, | |
| "S": 0x01, | |
| } | |
| special_map = { | |
| 0x5aaa5: None, # FMV Viewer | |
| 0x3258c: None, # Debug mode | |
| 0x4e4e4: None, # Alternate credits | |
| 0x5ca35: None, # Stick man mode | |
| 0xb909b: None, # Giraffe mode | |
| } | |
| def rotate_right(value, positions, bit_width=32): | |
| mask = (1 << bit_width) - 1 | |
| value &= mask | |
| positions %= bit_width # Handle positions > bit_width | |
| return ((value >> positions) | (value << (bit_width - positions))) & mask | |
| def check_password_accumulator(acc): | |
| acc = acc ^ 0xA5A5A | |
| uVar3 = acc & 0xF | |
| starting_stage = (uVar3 ^ (acc >> 0xE)) & 0xF | |
| rotate_input = ((acc & 0x3FF0) >> 4) ^ ((acc & 3) << 8 | uVar3 << 4 | uVar3) | |
| uVar1 = rotate_right(rotate_input, starting_stage, 10) | |
| uVar3 = (uVar1 & 0xC) >> 2 | |
| if ( | |
| starting_stage == 0 | |
| or ((uVar1 >> 4) + uVar3 + (uVar1 & 3) + starting_stage) & 0x3F != acc >> 0xE | |
| ): | |
| return () | |
| sVar2 = uVar1 >> 4 | |
| lives = uVar3 | |
| difficulty_level = uVar1 & 3 | |
| if sVar2 == 0: | |
| starting_health = 2 | |
| else: | |
| starting_health = sVar2 * 2 + 1 | |
| return (starting_stage, lives, difficulty_level, starting_health) | |
| def compute_hash(all_buttons): | |
| ret = 0 | |
| for i, button in enumerate(all_buttons): | |
| next_bit = button_map.get(button, 0x00) | |
| x = (3 << ((i & 0xF) << 1)) & 0xFFFFFFFF | |
| ret = (((ret | x) - x) + (next_bit + -1 << ((i & 0xF) << 1))) & 0xFFFFFFFF | |
| return ret | |
| if __name__ == "__main__": | |
| from itertools import product | |
| seen = set() | |
| for prod in product(button_map, repeat=10): | |
| password = ''.join(prod) | |
| hash_value = compute_hash(prod) | |
| if hash_value in special_map: | |
| if special_map[hash_value] is None: | |
| special_map[hash_value] = password | |
| else: | |
| params = check_password_accumulator(hash_value) | |
| if not params: | |
| continue | |
| starting_stage, lives, difficulty_level, starting_health = params | |
| if (lives == 3) and (starting_health == 0x7F) and (1 <= difficulty_level <= 3): | |
| if (starting_stage, difficulty_level) not in seen: | |
| seen.add((starting_stage, difficulty_level)) | |
| print(password, *params, sep="\t") | |
| print() | |
| for hash_value, password in special_map.items(): | |
| print(password, hash_value, sep='\t') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment