Skip to content

Commit

Permalink
v1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesbrq committed Mar 6, 2024
1 parent f8c5f7e commit 972b275
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 81 deletions.
49 changes: 32 additions & 17 deletions worlds/mlss/Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ def __init__(self) -> None:
self.local_set_events = {}
self.local_found_key_items = {}
self.rom_slot_name = None
self.seed_verify = False
self.eCount = 0
self.eUsed = []

async def validate_rom(self, ctx: "BizHawkClientContext") -> bool:
from CommonClient import logger

try:
# Check ROM name/patch version
rom_name_bytes = ((await bizhawk.read(ctx.bizhawk_ctx, [(0xA0, 14, "ROM")]))[0])
rom_name = bytes([byte for byte in rom_name_bytes if byte != 0]).decode("UTF-8")
rom_name_bytes = (await bizhawk.read(ctx.bizhawk_ctx, [(0xA0, 14, "ROM")]))
rom_name = bytes([byte for byte in rom_name_bytes[0] if byte != 0]).decode("UTF-8")
if not rom_name.startswith("MARIO&LUIGIU"):
return False
if rom_name == "MARIO&LUIGIUA8":
Expand All @@ -64,10 +64,10 @@ async def validate_rom(self, ctx: "BizHawkClientContext") -> bool:
ctx.want_slot_data = True
ctx.watcher_timeout = 0.125
self.rom_slot_name = rom_name
name_bytes = ((await bizhawk.read(ctx.bizhawk_ctx, [(0xB0, 16, "ROM")]))[0])
self.seed_verify = False
name_bytes = ((await bizhawk.read(ctx.bizhawk_ctx, [(0xDF0000, 16, "ROM")]))[0])
name = bytes([byte for byte in name_bytes if byte != 0]).decode("UTF-8")
self.player_name = name
logger.info(name)

for i in range(59):
self.checked_flags[i] = []
Expand All @@ -77,11 +77,28 @@ async def validate_rom(self, ctx: "BizHawkClientContext") -> bool:
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
ctx.auth = self.player_name

def on_package(self, ctx, cmd, args) -> None:
if cmd == 'RoomInfo':
ctx.seed_name = args['seed_name']

async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
from CommonClient import logger
try:
if ctx.seed_name is None:
return
if not self.seed_verify:
seed = await bizhawk.read(ctx.bizhawk_ctx, [(0xDF00A0, len(ctx.seed_name), "ROM")])
seed = seed[0].decode("UTF-8")
if seed != ctx.seed_name:
logger.info("ERROR: The ROM you loaded is for a different game of AP. "
"Please make sure the host has sent you the correct patch file,"
"and that you have opened the correct ROM.")
raise bizhawk.ConnectorError("Loaded ROM is for Incorrect lobby.")
self.seed_verify = True

read_state = await bizhawk.read(ctx.bizhawk_ctx, [(0x4564, 59, "EWRAM"),
(0x2330, 2, "IWRAM"), (0x3FE0, 1, "IWRAM"), (0x304A, 1, "EWRAM"),
(0x304B, 1, "EWRAM"), (0x304C, 4, "EWRAM"), (0x4800, 6, "EWRAM"),
(0x304B, 1, "EWRAM"), (0x304C, 4, "EWRAM"), (0x3060, 6, "EWRAM"),
(0x4808, 2, "EWRAM"), (0x4407, 1, "EWRAM"), (0x2339, 1, "IWRAM")])
flags = read_state[0]
current_room = int.from_bytes(read_state[1], 'little')
Expand Down Expand Up @@ -117,12 +134,11 @@ async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
# If RAM address isn't 0x0 yet break out and try again later to give the rest of the items
for i in range(len(ctx.items_received) - received_index):
item_data = items_by_id[ctx.items_received[received_index + i].item]
b = await bizhawk.read(ctx.bizhawk_ctx, [(0x3057, 1, "EWRAM")])
if b[0][0] == 0:
await bizhawk.write(ctx.bizhawk_ctx, [(0x3057, [id_to_RAM(item_data.itemID)], "EWRAM"), (0x4808, [(received_index + i + 1) // 0x100, (received_index + i + 1) % 0x100], "EWRAM")])
await asyncio.sleep(.05)
else:
b = await bizhawk.guarded_read(ctx.bizhawk_ctx, [(0x3057, 1, "EWRAM")], [(0x3057, [0x0], "EWRAM")])
if b is None:
break
await bizhawk.write(ctx.bizhawk_ctx, [(0x3057, [id_to_RAM(item_data.itemID)], "EWRAM"), (0x4808, [(received_index + i + 1) // 0x100, (received_index + i + 1) % 0x100], "EWRAM")])
await asyncio.sleep(.05)

# Early return and location send if you are currently in a shop,
# since other flags aren't going to change
Expand All @@ -142,18 +158,15 @@ async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
address, mask, location = item
if location in self.local_checked_locations:
continue
flag_bytes = await bizhawk.read(ctx.bizhawk_ctx, [(address, 1, "EWRAM"), (0x4800, 6, "EWRAM")])
flag_bytes = await bizhawk.read(ctx.bizhawk_ctx, [(address, 1, "EWRAM"), (0x3060, 6, "EWRAM")])
flag_byte = flag_bytes[0][0]
backup_logo = bytes([byte for byte in flag_bytes[1] if byte < 0x70]).decode("UTF-8")
if backup_logo != "MLSSAP":
return
if flag_byte & mask != 0:
if location in roomException:
if roomException[location] != current_room:
if (location == 0xDA0001 or location == 0x2578e7) and current_room == 0x79:
exception = False
else:
exception = True
if current_room not in roomException[location]:
exception = True
else:
exception = False
else:
Expand Down Expand Up @@ -221,6 +234,8 @@ async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
except bizhawk.RequestFailedError:
# Exit handler and return to main loop to reconnect.
pass
except bizhawk.ConnectorError:
pass


def find_key(dictionary, target):
Expand Down
39 changes: 19 additions & 20 deletions worlds/mlss/Locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ class MLSSLocation(Location):
(0x430B, 0x10, 0x1e9433), # Extra Dress
(0x430B, 0x10, 0x1e9432), # Fake Beanstar
(0x430F, 0x1, 0x1e9440), # Popple Beanstar Piece
(0x430C, 0x80, 0x261658), # Winkle Card
(0x467E, 0xFF, 0x261658), # Winkle Card
(0x4300, 0x40, 0x2578e7), # Brooch
(0x4375, 0x2, 0x2753ea), # Surf Minigame
(0x4373, 0x1, 0x277956), # North Whirlpool Mole
Expand Down Expand Up @@ -868,16 +868,15 @@ class MLSSLocation(Location):
(0x433D, 0x10, 0xDA0008) # Birdo
]

roomException: dict[int, int] = {
0x1e9437: 0xFF,
0x24ed74: 0x95,
0x250621: 0x95,
0x24ff18: 0x95,
0x261658: 0x9E,
0x260637: 0x135,
0x1E9403: 0x4D,
0xDA0001: 0x192,
0x2578e7: 0x192
roomException: dict[int, list[int]] = {
0x1e9437: [0xFE, 0xFF, 0x100],
0x24ed74: [0x94, 0x95, 0x96, 0x99],
0x250621: [0x94, 0x95, 0x96, 0x99],
0x24ff18: [0x94, 0x95, 0x96, 0x99],
0x260637: [0x135],
0x1E9403: [0x4D],
0xDA0001: [0x79, 0x192, 0x193],
0x2578e7: [0x79, 0x192, 0x193]
}

beanstones: dict[int, int] = {
Expand All @@ -887,16 +886,16 @@ class MLSSLocation(Location):
0x22913A: 0x39dc10,
0x22890E: 0x39dba4,
0x228775: 0x39db7f,
0x25117D: 0x39d73e, # Beanstone 1 - 10
0x2511D6: 0x39d746,
0x251288: 0x39d73e, # Beanstone 1 - 10
0x2512E1: 0x39d746,
0x25122F: 0x39d74e,
0x251288: 0x39d756,
0x2512E1: 0x39d75e,
0x25170B: 0x39d76b,
0x251767: 0x39d773,
0x2517C3: 0x39d77b,
0x25181F: 0x39d783,
0x25187B: 0x39d78b
0x25117D: 0x39d756,
0x2511D6: 0x39d75e,
0x25187B: 0x39d76b,
0x25170B: 0x39d773,
0x251767: 0x39d77b,
0x2517C3: 0x39d783,
0x25181F: 0x39d78b
}

roomCount: dict[int, int] = {
Expand Down
67 changes: 23 additions & 44 deletions worlds/mlss/Rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,10 @@ def item_inject(self, location: int, item_type: int, item: Item):

def patch_options(self):
name = self.world.multiworld.player_name[self.player].encode("UTF-8")
self.stream.seek(0xB0, 0)
self.stream.seek(0xDF0000, 0)
self.stream.write(name)
self.stream.seek(0xAF, 0)
self.stream.write(self.player.to_bytes(1, 'little'))
self.stream.seek(0xDF00A0, 0)
self.stream.write(self.world.multiworld.seed_name.encode("UTF-8"))

if self.world.options.skip_intro:
# Enable Skip Intro in ROM
Expand Down Expand Up @@ -273,47 +273,26 @@ def randomize_backgrounds(self):
self.stream.write(bytes([self.random.randint(0x0, 0x26)]))

def randomize_sounds(self):
pointers = []
sounds = []
self.stream.seek(0x21CC44)
for i in range(353):
p_arr = bytearray(self.stream.read(4))
pointers.append(p_arr[0] | p_arr[1] << 8 | p_arr[2] << 16)
pointers.sort(reverse=True)

for i in range(len(pointers) - 1, -1, -1):
if i == 0:
continue
j = 1
while True:
self.stream.seek(pointers[i - 1] - j)
read_byte = self.stream.read(1)
if read_byte != b'\xFF':
j += 1
continue
else:
break
self.stream.seek(pointers[i - 1] - (j + 1))
if self.stream.read(1) >= b'\xFE' and i != 0:
pointers.pop(i)
else:
temp = bytearray([
pointers[i] & 0xFF,
(pointers[i] >> 8) & 0xFF,
(pointers[i] >> 16) & 0xFF,
0x8
])
sounds.append(temp)

self.random.shuffle(sounds)
self.stream.seek(0x21CC44)
for i in range(len(pointers)):
current_pos = self.stream.tell()
p_arr = bytearray(self.stream.read(4))
if (p_arr[0] | p_arr[1] << 8 | p_arr[2] << 16) not in pointers:
continue
self.stream.seek(current_pos)
self.stream.write(self.random.choice(sounds))
temp = pkgutil.get_data(__name__, "data/sounds.txt")
temp_io = io.BytesIO(temp)
fresh_pointers = []

for line in temp_io.readlines():
fresh_pointers += [int(line.decode('utf-8').strip(), 16)]
pointers = list(fresh_pointers)

self.world.random.shuffle(pointers)
self.stream.seek(0x21cc44, 0)
for i in range(354):
current_position = self.stream.tell()
print(format(current_position, 'x'))
value = int.from_bytes(self.stream.read(3), 'little')
if value in fresh_pointers:
print(format(value, 'x'))
self.stream.seek(current_position)
self.stream.write(pointers.pop().to_bytes(3, 'little'))
self.stream.seek(1, 1)


def disable_music(self):
self.stream.seek(0x19B118)
Expand Down
20 changes: 20 additions & 0 deletions worlds/mlss/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@


def set_rules(world: "MLSSWorld", excluded):
add_rule(world.multiworld.get_location("Queen Bean", world.player), lambda state: StateLogic.rose(state, world.player))
add_rule(world.multiworld.get_location("Chuckolator", world.player), lambda state: StateLogic.castleTown(state, world.player))
add_rule(world.multiworld.get_location("Oasis", world.player),
lambda state: (StateLogic.canDig(state, world.player) and StateLogic.canMini(state, world.player))
or (StateLogic.fire(state, world.player) and StateLogic.membership(state, world.player)) and (StateLogic.super(state, world.player) or StateLogic.canDash(state, world.player)))
add_rule(world.multiworld.get_location("Mom Piranha", world.player), lambda state: StateLogic.thunder(state, world.player))
add_rule(world.multiworld.get_location("Fungitown", world.player), lambda state: StateLogic.fungitown(state, world.player))
add_rule(world.multiworld.get_location("Beanstar", world.player),
lambda state: StateLogic.castleTown(state, world.player) and StateLogic.rose(state,world.player) and StateLogic.pieces(state,world.player))

for location in all_locations:
if "Digspot" in location.name:
if (world.options.skip_minecart and "Minecart" in location.name) or (
Expand Down Expand Up @@ -240,13 +250,23 @@ def set_rules(world: "MLSSWorld", excluded):
add_rule(world.multiworld.get_location(LocationName.ChateauRedGoblet, world.player),
lambda state: StateLogic.brooch(state, world.player) and StateLogic.canMini(state, world.player))
if world.options.difficult_logic:
add_rule(world.multiworld.get_location("Birdo", world.player),
lambda state: StateLogic.postJokes(state, world.player))
add_rule(world.multiworld.get_location("Jojora", world.player), lambda state: StateLogic.surfable(state, world.player)
and StateLogic.canDash(state, world.player) and StateLogic.canDig(state, world.player))
add_rule(world.multiworld.get_location(LocationName.GwarharLagoonSpangleReward, world.player),
lambda state: StateLogic.canCrash(state, world.player))
add_rule(world.multiworld.get_location(LocationName.BeanstarPieceHermie, world.player),
lambda state: StateLogic.canCrash(state, world.player))
if world.options.chuckle_beans != 0:
add_rule(world.multiworld.get_location(LocationName.GwarharLagoonPastHermieDigspot, world.player),
lambda state: StateLogic.canCrash(state, world.player))
else:
add_rule(world.multiworld.get_location("Birdo", world.player),
lambda state: StateLogic.postJokes(state, world.player) and StateLogic.canCrash(state, world.player))
add_rule(world.multiworld.get_location("Jojora", world.player), lambda state: StateLogic.surfable(state, world.player)
and StateLogic.canDash(state, world.player) and StateLogic.canCrash(state, world.player)
and StateLogic.canDig(state, world.player))

if world.options.coins:
add_rule(world.multiworld.get_location(LocationName.HoohooMountainBaseBooStatueCaveCoinBlock1, world.player),
Expand Down
Binary file modified worlds/mlss/data/basepatch.bsdiff
Binary file not shown.
Loading

0 comments on commit 972b275

Please sign in to comment.