[Pokémon Red and Blue] more improvements (#1208)
* Generated patch includes base patch * location ID range start match item ID start * remove unused import * Change Oak's Aides defaults to be more sync-friendly
This commit is contained in:
parent
61232ca756
commit
d10bb3c6c1
|
@ -5,7 +5,6 @@ import os
|
||||||
import bsdiff4
|
import bsdiff4
|
||||||
import subprocess
|
import subprocess
|
||||||
import zipfile
|
import zipfile
|
||||||
import hashlib
|
|
||||||
from asyncio import StreamReader, StreamWriter
|
from asyncio import StreamReader, StreamWriter
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
@ -246,31 +245,16 @@ async def patch_and_run_game(game_version, patch_file, ctx):
|
||||||
comp_path = base_name + '.gb'
|
comp_path = base_name + '.gb'
|
||||||
with open(Utils.local_path(Utils.get_options()["pokemon_rb_options"][f"{game_version}_rom_file"]), "rb") as stream:
|
with open(Utils.local_path(Utils.get_options()["pokemon_rb_options"][f"{game_version}_rom_file"]), "rb") as stream:
|
||||||
base_rom = bytes(stream.read())
|
base_rom = bytes(stream.read())
|
||||||
try:
|
|
||||||
with open(Utils.local_path('lib', 'worlds', 'pokemon_rb', f'basepatch_{game_version}.bsdiff4'), 'rb') as stream:
|
|
||||||
base_patch = bytes(stream.read())
|
|
||||||
except FileNotFoundError:
|
|
||||||
with open(Utils.local_path('worlds', 'pokemon_rb', f'basepatch_{game_version}.bsdiff4'), 'rb') as stream:
|
|
||||||
base_patch = bytes(stream.read())
|
|
||||||
base_patched_rom_data = bsdiff4.patch(base_rom, base_patch)
|
|
||||||
basemd5 = hashlib.md5()
|
|
||||||
basemd5.update(base_patched_rom_data)
|
|
||||||
|
|
||||||
with zipfile.ZipFile(patch_file, 'r') as patch_archive:
|
with zipfile.ZipFile(patch_file, 'r') as patch_archive:
|
||||||
with patch_archive.open('delta.bsdiff4', 'r') as stream:
|
with patch_archive.open('delta.bsdiff4', 'r') as stream:
|
||||||
patch = stream.read()
|
patch = stream.read()
|
||||||
patched_rom_data = bsdiff4.patch(base_patched_rom_data, patch)
|
patched_rom_data = bsdiff4.patch(base_rom, patch)
|
||||||
|
|
||||||
written_hash = patched_rom_data[0xFFCB:0xFFDB]
|
with open(comp_path, "wb") as patched_rom_file:
|
||||||
if written_hash == basemd5.digest():
|
patched_rom_file.write(patched_rom_data)
|
||||||
with open(comp_path, "wb") as patched_rom_file:
|
|
||||||
patched_rom_file.write(patched_rom_data)
|
|
||||||
|
|
||||||
async_start(run_game(comp_path))
|
async_start(run_game(comp_path))
|
||||||
else:
|
|
||||||
msg = "Patch supplied was not generated with the same base patch version as this client. Patching failed."
|
|
||||||
logger.warning(msg)
|
|
||||||
ctx.gui_error('Error', msg)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -124,7 +124,7 @@ class PokemonRedBlueWorld(World):
|
||||||
|
|
||||||
self.multiworld.itempool += item_pool
|
self.multiworld.itempool += item_pool
|
||||||
|
|
||||||
def generate_basic(self) -> None:
|
def pre_fill(self) -> None:
|
||||||
|
|
||||||
process_wild_pokemon(self)
|
process_wild_pokemon(self)
|
||||||
process_static_pokemon(self)
|
process_static_pokemon(self)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
from BaseClasses import Location
|
from BaseClasses import Location
|
||||||
from .rom_addresses import rom_addresses
|
from .rom_addresses import rom_addresses
|
||||||
loc_id_start = 17200000
|
loc_id_start = 172000000
|
||||||
|
|
||||||
class LocationData:
|
class LocationData:
|
||||||
def __init__(self, region, name, original_item, rom_address=None, ram_address=None, event=False, type="Item"):
|
def __init__(self, region, name, original_item, rom_address=None, ram_address=None, event=False, type="Item"):
|
||||||
|
@ -42,7 +42,6 @@ class Rod:
|
||||||
self.bit = flag
|
self.bit = flag
|
||||||
self.flag = flag
|
self.flag = flag
|
||||||
|
|
||||||
# def get_locations(player=None):
|
|
||||||
location_data = [
|
location_data = [
|
||||||
|
|
||||||
LocationData("Vermilion City", "Fishing Guru", "Old Rod", rom_addresses["Rod_Vermilion_City_Fishing_Guru"], Rod(3)),
|
LocationData("Vermilion City", "Fishing Guru", "Old Rod", rom_addresses["Rod_Vermilion_City_Fishing_Guru"], Rod(3)),
|
||||||
|
|
|
@ -151,7 +151,8 @@ class FreeFlyLocation(Toggle):
|
||||||
|
|
||||||
|
|
||||||
class OaksAidRt2(Range):
|
class OaksAidRt2(Range):
|
||||||
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 2"""
|
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 2.
|
||||||
|
Vanilla is 10."""
|
||||||
display_name = "Oak's Aide Route 2"
|
display_name = "Oak's Aide Route 2"
|
||||||
range_start = 0
|
range_start = 0
|
||||||
range_end = 80
|
range_end = 80
|
||||||
|
@ -159,19 +160,21 @@ class OaksAidRt2(Range):
|
||||||
|
|
||||||
|
|
||||||
class OaksAidRt11(Range):
|
class OaksAidRt11(Range):
|
||||||
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 11"""
|
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 11.
|
||||||
|
Vanilla is 30."""
|
||||||
display_name = "Oak's Aide Route 11"
|
display_name = "Oak's Aide Route 11"
|
||||||
range_start = 0
|
range_start = 0
|
||||||
range_end = 80
|
range_end = 80
|
||||||
default = 30
|
default = 20
|
||||||
|
|
||||||
|
|
||||||
class OaksAidRt15(Range):
|
class OaksAidRt15(Range):
|
||||||
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 15"""
|
"""Number of Pokemon registered in the Pokedex required to receive the item from Oak's Aide on Route 15.
|
||||||
|
Vanilla is 50."""
|
||||||
display_name = "Oak's Aide Route 15"
|
display_name = "Oak's Aide Route 15"
|
||||||
range_start = 0
|
range_start = 0
|
||||||
range_end = 80
|
range_end = 80
|
||||||
default = 50
|
default = 30
|
||||||
|
|
||||||
|
|
||||||
class ExpModifier(SpecialRange):
|
class ExpModifier(SpecialRange):
|
||||||
|
|
|
@ -348,11 +348,14 @@ def process_pokemon_data(self):
|
||||||
self.learnsets = learnsets
|
self.learnsets = learnsets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def generate_output(self, output_directory: str):
|
def generate_output(self, output_directory: str):
|
||||||
random = self.multiworld.slot_seeds[self.player]
|
random = self.multiworld.slot_seeds[self.player]
|
||||||
game_version = self.multiworld.game_version[self.player].current_key
|
game_version = self.multiworld.game_version[self.player].current_key
|
||||||
data = bytearray(get_base_rom_bytes(game_version))
|
data = bytes(get_base_rom_bytes(game_version))
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), f'basepatch_{game_version}.bsdiff4'), 'rb') as stream:
|
||||||
|
base_patch = bytes(stream.read())
|
||||||
|
data = bytearray(bsdiff4.patch(data, base_patch))
|
||||||
|
|
||||||
basemd5 = hashlib.md5()
|
basemd5 = hashlib.md5()
|
||||||
basemd5.update(data)
|
basemd5.update(data)
|
||||||
|
@ -558,12 +561,9 @@ def generate_output(self, output_directory: str):
|
||||||
write_bytes(data, self.trainer_name, rom_addresses['Player_Name'])
|
write_bytes(data, self.trainer_name, rom_addresses['Player_Name'])
|
||||||
write_bytes(data, self.rival_name, rom_addresses['Rival_Name'])
|
write_bytes(data, self.rival_name, rom_addresses['Rival_Name'])
|
||||||
|
|
||||||
write_bytes(data, basemd5.digest(), 0xFFCB)
|
|
||||||
write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDB)
|
write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDB)
|
||||||
write_bytes(data, self.multiworld.player_name[self.player].encode(), 0xFFF0)
|
write_bytes(data, self.multiworld.player_name[self.player].encode(), 0xFFF0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
outfilepname = f'_P{self.player}'
|
outfilepname = f'_P{self.player}'
|
||||||
outfilepname += f"_{self.multiworld.get_file_safe_player_name(self.player).replace(' ', '_')}" \
|
outfilepname += f"_{self.multiworld.get_file_safe_player_name(self.player).replace(' ', '_')}" \
|
||||||
if self.multiworld.player_name[self.player] != 'Player%d' % self.player else ''
|
if self.multiworld.player_name[self.player] != 'Player%d' % self.player else ''
|
||||||
|
@ -597,9 +597,6 @@ def get_base_rom_bytes(game_version: str, hash: str="") -> bytes:
|
||||||
if hash != basemd5.hexdigest():
|
if hash != basemd5.hexdigest():
|
||||||
raise Exception('Supplied Base Rom does not match known MD5 for US(1.0) release. '
|
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 the correct game and version, then dump it')
|
||||||
with open(os.path.join(os.path.dirname(__file__), f'basepatch_{game_version}.bsdiff4'), 'rb') as stream:
|
|
||||||
base_patch = bytes(stream.read())
|
|
||||||
base_rom_bytes = bsdiff4.patch(base_rom_bytes, base_patch)
|
|
||||||
return base_rom_bytes
|
return base_rom_bytes
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue