2022-07-22 05:02:25 +00:00
|
|
|
import Utils
|
2022-09-29 22:36:30 +00:00
|
|
|
from Utils import read_snes_rom
|
|
|
|
from worlds.Files import APDeltaPatch
|
2022-07-22 05:02:25 +00:00
|
|
|
from .Locations import lookup_id_to_name, all_locations
|
|
|
|
from .Levels import level_list, level_dict
|
|
|
|
|
|
|
|
USHASH = '120abf304f0c40fe059f6a192ed4f947'
|
|
|
|
ROM_PLAYER_LIMIT = 65535
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
import os
|
|
|
|
import math
|
|
|
|
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
level_unlock_map = {
|
|
|
|
0x657: [0x65A],
|
|
|
|
0x65A: [0x680, 0x639, 0x659],
|
|
|
|
0x659: [0x65D],
|
|
|
|
0x65D: [0x65C],
|
|
|
|
0x65C: [0x688, 0x64F],
|
|
|
|
|
|
|
|
0x662: [0x681, 0x664],
|
|
|
|
0x664: [0x65B],
|
|
|
|
0x65B: [0x689, 0x661],
|
|
|
|
0x661: [0x63A, 0x666],
|
|
|
|
0x666: [0x650, 0x649],
|
|
|
|
|
|
|
|
0x667: [0x66A],
|
|
|
|
0x66A: [0x682, 0x658],
|
|
|
|
0x658: [0x68A, 0x66B],
|
|
|
|
0x66B: [0x668],
|
|
|
|
0x668: [0x651],
|
|
|
|
|
|
|
|
0x66D: [0x63C, 0x672],
|
|
|
|
0x672: [0x68B, 0x660],
|
|
|
|
0x660: [0x683, 0x66E],
|
|
|
|
0x66E: [0x670],
|
|
|
|
0x670: [0x652],
|
|
|
|
|
|
|
|
0x673: [0x684, 0x65F],
|
|
|
|
0x65F: [0x66C],
|
|
|
|
0x66C: [0x66F],
|
|
|
|
0x66F: [0x65E],
|
|
|
|
0x65E: [0x63D, 0x653, 0x68C, 0x64C],
|
|
|
|
|
|
|
|
0x676: [0x63E, 0x674, 0x685],
|
|
|
|
0x674: [0x63F, 0x669],
|
|
|
|
0x669: [0x677],
|
|
|
|
0x677: [0x68D, 0x675],
|
|
|
|
0x675: [0x654],
|
|
|
|
|
|
|
|
0x67A: [0x640, 0x678],
|
|
|
|
0x678: [0x665],
|
|
|
|
0x665: [0x686, 0x679],
|
|
|
|
0x679: [0x68E, 0x671],
|
|
|
|
|
|
|
|
0x67B: [0x67C],
|
|
|
|
0x67C: [0x67D],
|
|
|
|
0x67D: [0x663],
|
|
|
|
0x663: [0x67E],
|
|
|
|
}
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
location_rom_data = {
|
|
|
|
0xDC3000: [0x657, 1], # Lakeside Limbo
|
|
|
|
0xDC3001: [0x657, 2],
|
|
|
|
0xDC3002: [0x657, 3],
|
|
|
|
0xDC3003: [0x657, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3100: [0x657, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3004: [0x65A, 1], # Doorstop Dash
|
|
|
|
0xDC3005: [0x65A, 2],
|
|
|
|
0xDC3006: [0x65A, 3],
|
|
|
|
0xDC3007: [0x65A, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3104: [0x65A, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3008: [0x659, 1], # Tidal Trouble
|
|
|
|
0xDC3009: [0x659, 2],
|
|
|
|
0xDC300A: [0x659, 3],
|
|
|
|
0xDC300B: [0x659, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3108: [0x659, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC300C: [0x65D, 1], # Skidda's Row
|
|
|
|
0xDC300D: [0x65D, 2],
|
|
|
|
0xDC300E: [0x65D, 3],
|
|
|
|
0xDC300F: [0x65D, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC310C: [0x65D, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3010: [0x65C, 1], # Murky Mill
|
|
|
|
0xDC3011: [0x65C, 2],
|
|
|
|
0xDC3012: [0x65C, 3],
|
|
|
|
0xDC3013: [0x65C, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3110: [0x65C, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC3014: [0x662, 1], # Barrel Shield Bust-Up
|
|
|
|
0xDC3015: [0x662, 2],
|
|
|
|
0xDC3016: [0x662, 3],
|
|
|
|
0xDC3017: [0x662, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3114: [0x662, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3018: [0x664, 1], # Riverside Race
|
|
|
|
0xDC3019: [0x664, 2],
|
|
|
|
0xDC301A: [0x664, 3],
|
|
|
|
0xDC301B: [0x664, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3118: [0x664, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC301C: [0x65B, 1], # Squeals on Wheels
|
|
|
|
0xDC301D: [0x65B, 2],
|
|
|
|
0xDC301E: [0x65B, 3],
|
|
|
|
0xDC301F: [0x65B, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC311C: [0x65B, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3020: [0x661, 1], # Springin' Spiders
|
|
|
|
0xDC3021: [0x661, 2],
|
|
|
|
0xDC3022: [0x661, 3],
|
|
|
|
0xDC3023: [0x661, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3120: [0x661, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3024: [0x666, 1], # Bobbing Barrel Brawl
|
|
|
|
0xDC3025: [0x666, 2],
|
|
|
|
0xDC3026: [0x666, 3],
|
|
|
|
0xDC3027: [0x666, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3124: [0x666, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC3028: [0x667, 1], # Bazza's Blockade
|
|
|
|
0xDC3029: [0x667, 2],
|
|
|
|
0xDC302A: [0x667, 3],
|
|
|
|
0xDC302B: [0x667, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3128: [0x667, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC302C: [0x66A, 1], # Rocket Barrel Ride
|
|
|
|
0xDC302D: [0x66A, 2],
|
|
|
|
0xDC302E: [0x66A, 3],
|
|
|
|
0xDC302F: [0x66A, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC312C: [0x66A, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3030: [0x658, 1], # Kreeping Klasps
|
|
|
|
0xDC3031: [0x658, 2],
|
|
|
|
0xDC3032: [0x658, 3],
|
|
|
|
0xDC3033: [0x658, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3130: [0x658, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3034: [0x66B, 1], # Tracker Barrel Trek
|
|
|
|
0xDC3035: [0x66B, 2],
|
|
|
|
0xDC3036: [0x66B, 3],
|
|
|
|
0xDC3037: [0x66B, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3134: [0x66B, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3038: [0x668, 1], # Fish Food Frenzy
|
|
|
|
0xDC3039: [0x668, 2],
|
|
|
|
0xDC303A: [0x668, 3],
|
|
|
|
0xDC303B: [0x668, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3138: [0x668, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC303C: [0x66D, 1], # Fire-ball Frenzy
|
|
|
|
0xDC303D: [0x66D, 2],
|
|
|
|
0xDC303E: [0x66D, 3],
|
|
|
|
0xDC303F: [0x66D, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC313C: [0x66D, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3040: [0x672, 1], # Demolition Drainpipe
|
|
|
|
0xDC3041: [0x672, 2],
|
|
|
|
0xDC3042: [0x672, 3],
|
|
|
|
0xDC3043: [0x672, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3140: [0x672, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3044: [0x660, 1], # Ripsaw Rage
|
|
|
|
0xDC3045: [0x660, 2],
|
|
|
|
0xDC3046: [0x660, 3],
|
|
|
|
0xDC3047: [0x660, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3144: [0x660, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3048: [0x66E, 1], # Blazing Bazukas
|
|
|
|
0xDC3049: [0x66E, 2],
|
|
|
|
0xDC304A: [0x66E, 3],
|
|
|
|
0xDC304B: [0x66E, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3148: [0x66E, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC304C: [0x670, 1], # Low-G Labyrinth
|
|
|
|
0xDC304D: [0x670, 2],
|
|
|
|
0xDC304E: [0x670, 3],
|
|
|
|
0xDC304F: [0x670, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC314C: [0x670, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC3050: [0x673, 1], # Krevice Kreepers
|
|
|
|
0xDC3051: [0x673, 2],
|
|
|
|
0xDC3052: [0x673, 3],
|
|
|
|
0xDC3053: [0x673, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3150: [0x673, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3054: [0x65F, 1], # Tearaway Toboggan
|
|
|
|
0xDC3055: [0x65F, 2],
|
|
|
|
0xDC3056: [0x65F, 3],
|
|
|
|
0xDC3057: [0x65F, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3154: [0x65F, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3058: [0x66C, 1], # Barrel Drop Bounce
|
|
|
|
0xDC3059: [0x66C, 2],
|
|
|
|
0xDC305A: [0x66C, 3],
|
|
|
|
0xDC305B: [0x66C, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3158: [0x66C, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC305C: [0x66F, 1], # Krack-Shot Kroc
|
|
|
|
0xDC305D: [0x66F, 2],
|
|
|
|
0xDC305E: [0x66F, 3],
|
|
|
|
0xDC305F: [0x66F, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC315C: [0x66F, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3060: [0x65E, 1], # Lemguin Lunge
|
|
|
|
0xDC3061: [0x65E, 2],
|
|
|
|
0xDC3062: [0x65E, 3],
|
|
|
|
0xDC3063: [0x65E, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3160: [0x65E, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC3064: [0x676, 1], # Buzzer Barrage
|
|
|
|
0xDC3065: [0x676, 2],
|
|
|
|
0xDC3066: [0x676, 3],
|
|
|
|
0xDC3067: [0x676, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3164: [0x676, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3068: [0x674, 1], # Kong-Fused Cliffs
|
|
|
|
0xDC3069: [0x674, 2],
|
|
|
|
0xDC306A: [0x674, 3],
|
|
|
|
0xDC306B: [0x674, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3168: [0x674, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC306C: [0x669, 1], # Floodlit Fish
|
|
|
|
0xDC306D: [0x669, 2],
|
|
|
|
0xDC306E: [0x669, 3],
|
|
|
|
0xDC306F: [0x669, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC316C: [0x669, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3070: [0x677, 1], # Pothole Panic
|
|
|
|
0xDC3071: [0x677, 2],
|
|
|
|
0xDC3072: [0x677, 3],
|
|
|
|
0xDC3073: [0x677, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3170: [0x677, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3074: [0x675, 1], # Ropey Rumpus
|
|
|
|
0xDC3075: [0x675, 2],
|
|
|
|
0xDC3076: [0x675, 3],
|
|
|
|
0xDC3077: [0x675, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3174: [0x675, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC3078: [0x67A, 1], # Konveyor Rope Klash
|
|
|
|
0xDC3079: [0x67A, 2],
|
|
|
|
0xDC307A: [0x67A, 3],
|
|
|
|
0xDC307B: [0x67A, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3178: [0x67A, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC307C: [0x678, 1], # Creepy Caverns
|
|
|
|
0xDC307D: [0x678, 2],
|
|
|
|
0xDC307E: [0x678, 3],
|
|
|
|
0xDC307F: [0x678, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC317C: [0x678, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3080: [0x665, 1], # Lightning Lookout
|
|
|
|
0xDC3081: [0x665, 2],
|
|
|
|
0xDC3082: [0x665, 3],
|
|
|
|
0xDC3083: [0x665, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3180: [0x665, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3084: [0x679, 1], # Koindozer Klamber
|
|
|
|
0xDC3085: [0x679, 2],
|
|
|
|
0xDC3086: [0x679, 3],
|
|
|
|
0xDC3087: [0x679, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3184: [0x679, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3088: [0x671, 1], # Poisonous Pipeline
|
|
|
|
0xDC3089: [0x671, 2],
|
|
|
|
0xDC308A: [0x671, 3],
|
|
|
|
0xDC308B: [0x671, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3188: [0x671, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
0xDC308C: [0x67B, 1], # Stampede Sprint
|
|
|
|
0xDC308D: [0x67B, 2],
|
|
|
|
0xDC308E: [0x67B, 3],
|
|
|
|
0xDC308F: [0x67B, 4],
|
|
|
|
0xDC3090: [0x67B, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC318C: [0x67B, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3091: [0x67C, 1], # Criss Kross Cliffs
|
|
|
|
0xDC3092: [0x67C, 2],
|
|
|
|
0xDC3093: [0x67C, 3],
|
|
|
|
0xDC3094: [0x67C, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3191: [0x67C, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC3095: [0x67D, 1], # Tyrant Twin Tussle
|
|
|
|
0xDC3096: [0x67D, 2],
|
|
|
|
0xDC3097: [0x67D, 3],
|
|
|
|
0xDC3098: [0x67D, 4],
|
|
|
|
0xDC3099: [0x67D, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC3195: [0x67D, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC309A: [0x663, 1], # Swoopy Salvo
|
|
|
|
0xDC309B: [0x663, 2],
|
|
|
|
0xDC309C: [0x663, 3],
|
|
|
|
0xDC309D: [0x663, 4],
|
|
|
|
0xDC309E: [0x663, 5],
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC319A: [0x663, 7],
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
0xDC309F: [0x67E, 1], # Rocket Rush
|
|
|
|
0xDC30A0: [0x67E, 5],
|
|
|
|
|
|
|
|
0xDC30A1: [0x64F, 1], # Bosses
|
|
|
|
0xDC30A2: [0x650, 1],
|
|
|
|
0xDC30A3: [0x651, 1],
|
|
|
|
0xDC30A4: [0x652, 1],
|
|
|
|
0xDC30A5: [0x653, 1],
|
|
|
|
0xDC30A6: [0x654, 1],
|
|
|
|
0xDC30A7: [0x655, 1],
|
|
|
|
0xDC30A8: [0x656, 1],
|
|
|
|
|
|
|
|
0xDC30A9: [0x647, 1], # Banana Bird Caves
|
|
|
|
0xDC30AA: [0x645, 1],
|
|
|
|
0xDC30AB: [0x644, 1],
|
|
|
|
0xDC30AC: [0x642, 1],
|
|
|
|
0xDC30AD: [0x643, 1],
|
|
|
|
0xDC30AE: [0x646, 1],
|
|
|
|
0xDC30AF: [0x648, 1],
|
|
|
|
0xDC30B0: [0x649, 1],
|
|
|
|
0xDC30B1: [0x64A, 1],
|
2022-07-25 19:34:31 +00:00
|
|
|
#0xDC30B2: [0x64B, 1], # Disabled until Trade Sequence
|
2022-07-22 05:02:25 +00:00
|
|
|
0xDC30B3: [0x64C, 1],
|
2022-07-25 19:34:31 +00:00
|
|
|
#0xDC30B4: [0x64D, 1], # Disabled until Trade Sequence
|
2022-07-22 05:02:25 +00:00
|
|
|
0xDC30B5: [0x64E, 1],
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
0xDC30B6: [0x5FE, 4], # Banana Bird Mother
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
# DKC3_TODO: Disabled until Trade Sequence
|
|
|
|
#0xDC30B7: [0x615, 2, True],
|
|
|
|
#0xDC30B8: [0x615, 3, True],
|
|
|
|
#0xDC30B9: [0x619, 2],
|
|
|
|
##0xDC30BA:
|
|
|
|
#0xDC30BB: [0x61B, 3],
|
|
|
|
#0xDC30BC: [0x61D, 2],
|
|
|
|
#0xDC30BD: [0x621, 4],
|
|
|
|
#0xDC30BE: [0x625, 4, True],
|
|
|
|
}
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
boss_location_ids = [
|
|
|
|
0xDC30A1,
|
|
|
|
0xDC30A2,
|
|
|
|
0xDC30A3,
|
|
|
|
0xDC30A4,
|
|
|
|
0xDC30A5,
|
|
|
|
0xDC30A6,
|
|
|
|
0xDC30A7,
|
|
|
|
0xDC30A8,
|
|
|
|
0xDC30B6,
|
|
|
|
]
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
item_rom_data = {
|
|
|
|
0xDC3001: [0x5D5], # 1-Up Balloon
|
|
|
|
0xDC3002: [0x5C9], # Bear Coin
|
|
|
|
0xDC3003: [0x5CB], # Bonus Coin
|
|
|
|
0xDC3004: [0x5CF], # DK Coin
|
|
|
|
0xDC3005: [0x5CD], # Banana Bird
|
|
|
|
0xDC3006: [0x5D1, 0x603], # Cog
|
|
|
|
}
|
|
|
|
|
|
|
|
music_rom_data = [
|
|
|
|
0x3D06B1,
|
|
|
|
0x3D0753,
|
|
|
|
0x3D071D,
|
|
|
|
0x3D07FA,
|
|
|
|
0x3D07C4,
|
|
|
|
|
|
|
|
0x3D08FE,
|
|
|
|
0x3D096C,
|
|
|
|
0x3D078E,
|
|
|
|
0x3D08CD,
|
|
|
|
0x3D09DD,
|
|
|
|
|
|
|
|
0x3D0A0E,
|
|
|
|
0x3D0AB3,
|
|
|
|
0x3D06E7,
|
|
|
|
0x3D0AE4,
|
|
|
|
0x3D0A45,
|
|
|
|
|
|
|
|
0x3D0B46,
|
|
|
|
0x3D0C40,
|
|
|
|
0x3D0897,
|
|
|
|
0x3D0B77,
|
|
|
|
0x3D0BD9,
|
|
|
|
|
|
|
|
0x3D0C71,
|
|
|
|
0x3D0866,
|
|
|
|
0x3D0B15,
|
|
|
|
0x3D0BA8,
|
|
|
|
0x3D0830,
|
|
|
|
|
|
|
|
0x3D0D04,
|
|
|
|
0x3D0CA2,
|
|
|
|
0x3D0A7C,
|
|
|
|
0x3D0D35,
|
|
|
|
0x3D0CD3,
|
|
|
|
|
|
|
|
0x3D0DC8,
|
|
|
|
0x3D0D66,
|
|
|
|
0x3D09AC,
|
|
|
|
0x3D0D97,
|
|
|
|
0x3D0C0F,
|
|
|
|
|
|
|
|
0x3D0DF9,
|
|
|
|
0x3D0E31,
|
|
|
|
0x3D0E62,
|
|
|
|
0x3D0934,
|
|
|
|
0x3D0E9A,
|
|
|
|
]
|
|
|
|
|
|
|
|
level_music_ids = [
|
|
|
|
0x06,
|
|
|
|
0x07,
|
|
|
|
0x08,
|
|
|
|
0x0A,
|
|
|
|
0x0B,
|
|
|
|
0x0E,
|
|
|
|
0x0F,
|
|
|
|
0x10,
|
|
|
|
0x17,
|
|
|
|
0x19,
|
|
|
|
0x1C,
|
|
|
|
0x1D,
|
|
|
|
0x1E,
|
|
|
|
0x21,
|
|
|
|
]
|
|
|
|
|
|
|
|
class LocalRom(object):
|
|
|
|
|
|
|
|
def __init__(self, file, patch=True, vanillaRom=None, name=None, hash=None):
|
|
|
|
self.name = name
|
|
|
|
self.hash = hash
|
|
|
|
self.orig_buffer = None
|
|
|
|
|
|
|
|
with open(file, 'rb') as stream:
|
2022-09-29 22:36:30 +00:00
|
|
|
self.buffer = read_snes_rom(stream)
|
2022-07-22 05:02:25 +00:00
|
|
|
#if patch:
|
|
|
|
# self.patch_rom()
|
|
|
|
# self.orig_buffer = self.buffer.copy()
|
|
|
|
#if vanillaRom:
|
|
|
|
# with open(vanillaRom, 'rb') as vanillaStream:
|
2022-09-29 22:36:30 +00:00
|
|
|
# self.orig_buffer = read_snes_rom(vanillaStream)
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
def read_bit(self, address: int, bit_number: int) -> bool:
|
|
|
|
bitflag = (1 << bit_number)
|
|
|
|
return ((self.buffer[address] & bitflag) != 0)
|
|
|
|
|
|
|
|
def read_byte(self, address: int) -> int:
|
|
|
|
return self.buffer[address]
|
|
|
|
|
|
|
|
def read_bytes(self, startaddress: int, length: int) -> bytes:
|
|
|
|
return self.buffer[startaddress:startaddress + length]
|
|
|
|
|
|
|
|
def write_byte(self, address: int, value: int):
|
|
|
|
self.buffer[address] = value
|
|
|
|
|
|
|
|
def write_bytes(self, startaddress: int, values):
|
|
|
|
self.buffer[startaddress:startaddress + len(values)] = values
|
|
|
|
|
|
|
|
def write_to_file(self, file):
|
|
|
|
with open(file, 'wb') as outfile:
|
|
|
|
outfile.write(self.buffer)
|
|
|
|
|
|
|
|
def read_from_file(self, file):
|
|
|
|
with open(file, 'rb') as stream:
|
|
|
|
self.buffer = bytearray(stream.read())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def patch_rom(world, rom, player, active_level_list):
|
2023-02-02 00:14:23 +00:00
|
|
|
local_random = world.per_slot_randoms[player]
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
# Boomer Costs
|
|
|
|
bonus_coin_cost = world.krematoa_bonus_coin_cost[player]
|
|
|
|
inverted_bonus_coin_cost = 0x100 - bonus_coin_cost
|
|
|
|
rom.write_byte(0x3498B9, inverted_bonus_coin_cost)
|
|
|
|
rom.write_byte(0x3498BA, inverted_bonus_coin_cost)
|
|
|
|
rom.write_byte(0x3498BB, inverted_bonus_coin_cost)
|
|
|
|
rom.write_byte(0x3498BC, inverted_bonus_coin_cost)
|
|
|
|
rom.write_byte(0x3498BD, inverted_bonus_coin_cost)
|
|
|
|
|
|
|
|
rom.write_byte(0x349857, bonus_coin_cost)
|
|
|
|
rom.write_byte(0x349862, bonus_coin_cost)
|
|
|
|
|
|
|
|
# Gyrocopter Costs
|
|
|
|
dk_coin_cost = world.dk_coins_for_gyrocopter[player]
|
|
|
|
rom.write_byte(0x3484A6, dk_coin_cost)
|
|
|
|
rom.write_byte(0x3484D5, dk_coin_cost)
|
|
|
|
rom.write_byte(0x3484D7, 0x90)
|
|
|
|
rom.write_byte(0x3484DC, 0xEA)
|
|
|
|
rom.write_byte(0x3484DD, 0xEA)
|
|
|
|
rom.write_byte(0x3484DE, 0xEA)
|
|
|
|
rom.write_byte(0x348528, 0x80) # Prevent Single-Ski Lock
|
|
|
|
|
|
|
|
# Make Swanky free
|
|
|
|
rom.write_byte(0x348C48, 0x00)
|
|
|
|
|
2022-08-29 18:04:02 +00:00
|
|
|
rom.write_bytes(0x34AB70, bytearray([0xEA, 0xEA]))
|
|
|
|
rom.write_bytes(0x34ABF7, bytearray([0xEA, 0xEA]))
|
|
|
|
rom.write_bytes(0x34ACD0, bytearray([0xEA, 0xEA]))
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
# Banana Bird Costs
|
|
|
|
if world.goal[player] == "banana_bird_hunt":
|
|
|
|
banana_bird_cost = math.floor(world.number_of_banana_birds[player] * world.percentage_of_banana_birds[player] / 100.0)
|
|
|
|
rom.write_byte(0x34AB85, banana_bird_cost)
|
|
|
|
rom.write_byte(0x329FD8, banana_bird_cost)
|
|
|
|
rom.write_byte(0x32A025, banana_bird_cost)
|
|
|
|
rom.write_byte(0x329FDA, 0xB0)
|
|
|
|
else:
|
|
|
|
# rom.write_byte(0x34AB84, 0x20) # These cause hangs at Wrinkly's
|
|
|
|
# rom.write_byte(0x329FD8, 0x20)
|
|
|
|
# rom.write_byte(0x32A025, 0x20)
|
|
|
|
rom.write_byte(0x329FDA, 0xB0)
|
|
|
|
|
|
|
|
# Baffle Mirror Fix
|
|
|
|
rom.write_byte(0x9133, 0x08)
|
|
|
|
rom.write_byte(0x9135, 0x0C)
|
|
|
|
rom.write_byte(0x9136, 0x2B)
|
|
|
|
rom.write_byte(0x9137, 0x06)
|
|
|
|
|
|
|
|
# Palette Swap
|
|
|
|
rom.write_byte(0x3B96A5, 0xD0)
|
|
|
|
if world.kong_palette_swap[player] == "default":
|
|
|
|
rom.write_byte(0x3B96A9, 0x00)
|
|
|
|
rom.write_byte(0x3B96A8, 0x00)
|
|
|
|
elif world.kong_palette_swap[player] == "purple":
|
|
|
|
rom.write_byte(0x3B96A9, 0x00)
|
|
|
|
rom.write_byte(0x3B96A8, 0x3C)
|
|
|
|
elif world.kong_palette_swap[player] == "spooky":
|
|
|
|
rom.write_byte(0x3B96A9, 0x00)
|
|
|
|
rom.write_byte(0x3B96A8, 0xA0)
|
|
|
|
elif world.kong_palette_swap[player] == "dark":
|
|
|
|
rom.write_byte(0x3B96A9, 0x05)
|
|
|
|
rom.write_byte(0x3B96A8, 0xA0)
|
|
|
|
elif world.kong_palette_swap[player] == "chocolate":
|
|
|
|
rom.write_byte(0x3B96A9, 0x1D)
|
|
|
|
rom.write_byte(0x3B96A8, 0xA0)
|
|
|
|
elif world.kong_palette_swap[player] == "shadow":
|
|
|
|
rom.write_byte(0x3B96A9, 0x45)
|
|
|
|
rom.write_byte(0x3B96A8, 0xA0)
|
|
|
|
elif world.kong_palette_swap[player] == "red_gold":
|
|
|
|
rom.write_byte(0x3B96A9, 0x5D)
|
|
|
|
rom.write_byte(0x3B96A8, 0xA0)
|
|
|
|
elif world.kong_palette_swap[player] == "gbc":
|
|
|
|
rom.write_byte(0x3B96A9, 0x20)
|
|
|
|
rom.write_byte(0x3B96A8, 0x3C)
|
|
|
|
elif world.kong_palette_swap[player] == "halloween":
|
|
|
|
rom.write_byte(0x3B96A9, 0x70)
|
|
|
|
rom.write_byte(0x3B96A8, 0x3C)
|
|
|
|
|
|
|
|
if world.music_shuffle[player]:
|
|
|
|
for address in music_rom_data:
|
|
|
|
rand_song = local_random.choice(level_music_ids)
|
|
|
|
rom.write_byte(address, rand_song)
|
|
|
|
|
|
|
|
# Starting Lives
|
|
|
|
rom.write_byte(0x9130, world.starting_life_count[player].value)
|
|
|
|
rom.write_byte(0x913B, world.starting_life_count[player].value)
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
# Cheat options
|
|
|
|
cheat_bytes = [0x00, 0x00]
|
|
|
|
|
|
|
|
if world.merry[player]:
|
|
|
|
cheat_bytes[0] |= 0x01
|
|
|
|
|
|
|
|
if world.autosave[player]:
|
|
|
|
cheat_bytes[0] |= 0x02
|
|
|
|
|
|
|
|
if world.difficulty[player] == "tufst":
|
|
|
|
cheat_bytes[0] |= 0x80
|
|
|
|
cheat_bytes[1] |= 0x80
|
|
|
|
elif world.difficulty[player] == "hardr":
|
|
|
|
cheat_bytes[0] |= 0x00
|
|
|
|
cheat_bytes[1] |= 0x00
|
|
|
|
elif world.difficulty[player] == "norml":
|
|
|
|
cheat_bytes[1] |= 0x40
|
|
|
|
|
|
|
|
rom.write_bytes(0x8303, bytearray(cheat_bytes))
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
# Handle Level Shuffle Here
|
|
|
|
if world.level_shuffle[player]:
|
|
|
|
for i in range(len(active_level_list)):
|
|
|
|
rom.write_byte(level_dict[level_list[i]].nameIDAddress, level_dict[active_level_list[i]].nameID)
|
|
|
|
rom.write_byte(level_dict[level_list[i]].levelIDAddress, level_dict[active_level_list[i]].levelID)
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
rom.write_byte(0x3FF800 + level_dict[active_level_list[i]].levelID, level_dict[level_list[i]].levelID)
|
|
|
|
rom.write_byte(0x3FF860 + level_dict[level_list[i]].levelID, level_dict[active_level_list[i]].levelID)
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
# First levels of each world
|
|
|
|
rom.write_byte(0x34BC3E, (0x32 + level_dict[active_level_list[0]].levelID))
|
|
|
|
rom.write_byte(0x34BC47, (0x32 + level_dict[active_level_list[5]].levelID))
|
|
|
|
rom.write_byte(0x34BC4A, (0x32 + level_dict[active_level_list[10]].levelID))
|
|
|
|
rom.write_byte(0x34BC53, (0x32 + level_dict[active_level_list[15]].levelID))
|
|
|
|
rom.write_byte(0x34BC59, (0x32 + level_dict[active_level_list[20]].levelID))
|
|
|
|
rom.write_byte(0x34BC5C, (0x32 + level_dict[active_level_list[25]].levelID))
|
|
|
|
rom.write_byte(0x34BC65, (0x32 + level_dict[active_level_list[30]].levelID))
|
|
|
|
rom.write_byte(0x34BC6E, (0x32 + level_dict[active_level_list[35]].levelID))
|
|
|
|
|
|
|
|
# Cotton-Top Cove Boss Unlock
|
|
|
|
rom.write_byte(0x34C02A, (0x32 + level_dict[active_level_list[14]].levelID))
|
|
|
|
|
|
|
|
# Kong-Fused Cliffs Unlock
|
|
|
|
rom.write_byte(0x34C213, (0x32 + level_dict[active_level_list[25]].levelID))
|
|
|
|
rom.write_byte(0x34C21B, (0x32 + level_dict[active_level_list[26]].levelID))
|
|
|
|
|
|
|
|
if world.goal[player] == "knautilus":
|
|
|
|
# Swap Kastle KAOS and Knautilus
|
|
|
|
rom.write_byte(0x34D4E1, 0xC2)
|
|
|
|
rom.write_byte(0x34D4E2, 0x24)
|
|
|
|
rom.write_byte(0x34D551, 0xBA)
|
|
|
|
rom.write_byte(0x34D552, 0x23)
|
|
|
|
|
|
|
|
rom.write_byte(0x32F339, 0x55)
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
# Handle KONGsanity Here
|
|
|
|
if world.kongsanity[player]:
|
|
|
|
# Arich's Hoard KONGsanity fix
|
|
|
|
rom.write_bytes(0x34BA8C, bytearray([0xEA, 0xEA]))
|
|
|
|
|
|
|
|
# Don't hide the level flag if the 0x80 bit is set
|
|
|
|
rom.write_bytes(0x34CE92, bytearray([0x80]))
|
|
|
|
|
|
|
|
# Use the `!` next to level name for indicating KONG letters
|
|
|
|
rom.write_bytes(0x34B8F0, bytearray([0x80]))
|
|
|
|
rom.write_bytes(0x34B8F3, bytearray([0x80]))
|
|
|
|
|
|
|
|
# Hijack to code to set the 0x80 flag for the level when you complete KONG
|
|
|
|
rom.write_bytes(0x3BCD4B, bytearray([0x22, 0x80, 0xFA, 0XB8])) # JSL $B8FA80
|
|
|
|
|
|
|
|
rom.write_bytes(0x38FA80, bytearray([0xDA])) # PHX
|
|
|
|
rom.write_bytes(0x38FA81, bytearray([0x48])) # PHA
|
|
|
|
rom.write_bytes(0x38FA82, bytearray([0x08])) # PHP
|
|
|
|
rom.write_bytes(0x38FA83, bytearray([0xE2, 0x20])) # SEP #20
|
|
|
|
rom.write_bytes(0x38FA85, bytearray([0x48])) # PHA
|
|
|
|
rom.write_bytes(0x38FA86, bytearray([0x18])) # CLC
|
|
|
|
rom.write_bytes(0x38FA87, bytearray([0x6D, 0xD3, 0x18])) # ADC $18D3
|
|
|
|
rom.write_bytes(0x38FA8A, bytearray([0x8D, 0xD3, 0x18])) # STA $18D3
|
|
|
|
rom.write_bytes(0x38FA8D, bytearray([0x68])) # PLA
|
|
|
|
rom.write_bytes(0x38FA8E, bytearray([0xC2, 0x20])) # REP 20
|
|
|
|
rom.write_bytes(0x38FA90, bytearray([0X18])) # CLC
|
|
|
|
rom.write_bytes(0x38FA91, bytearray([0x6D, 0xD5, 0x05])) # ADC $05D5
|
|
|
|
rom.write_bytes(0x38FA94, bytearray([0x8D, 0xD5, 0x05])) # STA $05D5
|
|
|
|
rom.write_bytes(0x38FA97, bytearray([0xAE, 0xB9, 0x05])) # LDX $05B9
|
|
|
|
rom.write_bytes(0x38FA9A, bytearray([0xBD, 0x32, 0x06])) # LDA $0632, X
|
|
|
|
rom.write_bytes(0x38FA9D, bytearray([0x09, 0x80, 0x00])) # ORA #8000
|
|
|
|
rom.write_bytes(0x38FAA0, bytearray([0x9D, 0x32, 0x06])) # STA $0632, X
|
|
|
|
rom.write_bytes(0x38FAA3, bytearray([0xAD, 0xD5, 0x18])) # LDA $18D5
|
|
|
|
rom.write_bytes(0x38FAA6, bytearray([0xD0, 0x03])) # BNE $80EA
|
|
|
|
rom.write_bytes(0x38FAA8, bytearray([0x9C, 0xD9, 0x18])) # STZ $18D9
|
|
|
|
rom.write_bytes(0x38FAAB, bytearray([0xA9, 0x78, 0x00])) # LDA #0078
|
|
|
|
rom.write_bytes(0x38FAAE, bytearray([0x8D, 0xD5, 0x18])) # STA $18D5
|
|
|
|
rom.write_bytes(0x38FAB1, bytearray([0x28])) # PLP
|
|
|
|
rom.write_bytes(0x38FAB2, bytearray([0x68])) # PLA
|
|
|
|
rom.write_bytes(0x38FAB3, bytearray([0xFA])) # PLX
|
|
|
|
rom.write_bytes(0x38FAB4, bytearray([0x6B])) # RTL
|
|
|
|
# End Handle KONGsanity
|
|
|
|
|
|
|
|
# Handle Credits
|
|
|
|
rom.write_bytes(0x32A5DF, bytearray([0x41, 0x52, 0x43, 0x48, 0x49, 0x50, 0x45, 0x4C, 0x41, 0x47, 0x4F, 0x20, 0x4D, 0x4F, 0xC4])) # "ARCHIPELAGO MOD"
|
|
|
|
rom.write_bytes(0x32A5EE, bytearray([0x00, 0x03, 0x50, 0x4F, 0x52, 0x59, 0x47, 0x4F, 0x4E, 0xC5])) # "PORYGONE"
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
from Main import __version__
|
|
|
|
rom.name = bytearray(f'D3{__version__.replace(".", "")[0:3]}_{player}_{world.seed:11}\0', 'utf8')[:21]
|
|
|
|
rom.name.extend([0] * (21 - len(rom.name)))
|
|
|
|
rom.write_bytes(0x7FC0, rom.name)
|
|
|
|
|
|
|
|
# DKC3_TODO: This is a hack, reconsider
|
|
|
|
# Don't grant (DK, Bonus, Bear) Coins
|
|
|
|
rom.write_byte(0x3BD454, 0xEA)
|
|
|
|
rom.write_byte(0x3BD455, 0xEA)
|
|
|
|
|
|
|
|
# Don't grant Cogs
|
|
|
|
rom.write_byte(0x3BD574, 0xEA)
|
|
|
|
rom.write_byte(0x3BD575, 0xEA)
|
|
|
|
rom.write_byte(0x3BD576, 0xEA)
|
|
|
|
|
|
|
|
# Don't grant Banana Birds at their caves
|
|
|
|
rom.write_byte(0x32DD62, 0xEA)
|
|
|
|
rom.write_byte(0x32DD63, 0xEA)
|
|
|
|
rom.write_byte(0x32DD64, 0xEA)
|
|
|
|
|
2022-08-20 14:46:44 +00:00
|
|
|
# Don't grant Banana Birds at Bears
|
|
|
|
rom.write_byte(0x3492DB, 0xEA)
|
|
|
|
rom.write_byte(0x3492DC, 0xEA)
|
|
|
|
rom.write_byte(0x3492DD, 0xEA)
|
|
|
|
rom.write_byte(0x3493F4, 0xEA)
|
|
|
|
rom.write_byte(0x3493F5, 0xEA)
|
|
|
|
rom.write_byte(0x3493F6, 0xEA)
|
|
|
|
|
|
|
|
# Don't grant present at Blizzard
|
|
|
|
rom.write_byte(0x8454, 0x00)
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
# Don't grant Patch and Skis from their bosses
|
|
|
|
rom.write_byte(0x3F3762, 0x00)
|
|
|
|
rom.write_byte(0x3F377B, 0x00)
|
|
|
|
rom.write_byte(0x3F3797, 0x00)
|
|
|
|
|
|
|
|
# Always allow Start+Select
|
|
|
|
rom.write_byte(0x8BAB, 0x01)
|
|
|
|
|
|
|
|
# Handle Alt Palettes in Krematoa
|
|
|
|
rom.write_byte(0x3B97E9, 0x80)
|
|
|
|
rom.write_byte(0x3B97EA, 0xEA)
|
|
|
|
|
|
|
|
|
2022-07-28 23:51:22 +00:00
|
|
|
class DKC3DeltaPatch(APDeltaPatch):
|
|
|
|
hash = USHASH
|
|
|
|
game = "Donkey Kong Country 3"
|
|
|
|
patch_file_ending = ".apdkc3"
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_source_data(cls) -> bytes:
|
|
|
|
return get_base_rom_bytes()
|
|
|
|
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
def get_base_rom_bytes(file_name: str = "") -> bytes:
|
|
|
|
base_rom_bytes = getattr(get_base_rom_bytes, "base_rom_bytes", None)
|
|
|
|
if not base_rom_bytes:
|
|
|
|
file_name = get_base_rom_path(file_name)
|
2022-09-29 22:36:30 +00:00
|
|
|
base_rom_bytes = bytes(read_snes_rom(open(file_name, "rb")))
|
2022-07-22 05:02:25 +00:00
|
|
|
|
|
|
|
basemd5 = hashlib.md5()
|
|
|
|
basemd5.update(base_rom_bytes)
|
|
|
|
if USHASH != basemd5.hexdigest():
|
|
|
|
raise Exception('Supplied Base Rom does not match known MD5 for US(1.0) release. '
|
|
|
|
'Get the correct game and version, then dump it')
|
|
|
|
get_base_rom_bytes.base_rom_bytes = base_rom_bytes
|
|
|
|
return base_rom_bytes
|
|
|
|
|
|
|
|
def get_base_rom_path(file_name: str = "") -> str:
|
|
|
|
options = Utils.get_options()
|
|
|
|
if not file_name:
|
|
|
|
file_name = options["dkc3_options"]["rom_file"]
|
|
|
|
if not os.path.exists(file_name):
|
2023-02-28 08:11:17 +00:00
|
|
|
file_name = Utils.user_path(file_name)
|
2022-07-22 05:02:25 +00:00
|
|
|
return file_name
|