Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog

## Unreleased - 2025-XX-XX
- Changelog Created

- Added: 6 new Item Locations. 3 Major/Events: Boiler, Animals, Auxiliary Power. 3 Minor/Tanks: Subzero Containment, Quarantine Bay, Northeast Stabilizer
- Added: Infrastructure to define base minimap edits that will always apply.
9 changes: 6 additions & 3 deletions src/mars_patcher/auto_generated_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@
'Level4',
'AqaData',
'WaveCoreX',
'Ridley'
'Ridley',
'Boiler',
'Animals',
'AuxiliaryPower'
]
Validitems = typ.Literal[
'None',
Expand Down Expand Up @@ -249,10 +252,10 @@ class MarsschemaLocationsMinorlocationsItem(typ.TypedDict):
class MarsschemaLocations(typ.TypedDict):
"""Specifies how the item locations in the game should be changed."""

MajorLocations: typ.Annotated[list[MarsschemaLocationsMajorlocationsItem], 'len() == 20', 'Unique items']
MajorLocations: typ.Annotated[list[MarsschemaLocationsMajorlocationsItem], 'len() == 23', 'Unique items']
"""Specifies how the major item locations should be changed. A major item location is a location where an item is obtained by defeating a boss or interacting with a device."""

MinorLocations: typ.Annotated[list[MarsschemaLocationsMinorlocationsItem], 'len() == 100', 'Unique items']
MinorLocations: typ.Annotated[list[MarsschemaLocationsMinorlocationsItem], 'len() == 103', 'Unique items']
"""Specifies how the minor item locations should be changed. A minor item location is a location where an item is obtained by touching a tank block."""


Expand Down
6 changes: 6 additions & 0 deletions src/mars_patcher/constants/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class MajorSource(Enum):
AQA_DATA = 18
WAVE_CORE_X = 19
RIDLEY = 20
BOILER = 21
ANIMALS = 22
AUXILIARYPOWER = 23


class ItemType(Enum):
Expand Down Expand Up @@ -144,6 +147,9 @@ class ItemMessagesKind(Enum):
"AqaData": MajorSource.AQA_DATA,
"WaveCoreX": MajorSource.WAVE_CORE_X,
"Ridley": MajorSource.RIDLEY,
"Boiler": MajorSource.BOILER,
"Animals": MajorSource.ANIMALS,
"AuxiliaryPower": MajorSource.AUXILIARYPOWER,
}

ITEM_ENUMS = {
Expand Down
2 changes: 1 addition & 1 deletion src/mars_patcher/constants/reserved_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ReservedConstants:
PATCHER_FREE_SPACE_ADDR = 0x7D0000
PATCHER_FREE_SPACE_END = PATCHER_FREE_SPACE_ADDR + 0x20000
MINOR_LOCS_TABLE_ADDR = 0x7FF000
MAJOR_LOCS_ADDR = 0x7FF01C
MAJOR_LOCS_POINTER_ADDR = 0x7FF01C
TANK_INC_ADDR = 0x7FF046
TOTAL_METROID_COUNT_ADDR = 0x7FF04C
REQUIRED_METROID_COUNT_ADDR = 0x7FF04D
Expand Down
85 changes: 85 additions & 0 deletions src/mars_patcher/data/base_minimap_edits.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
[
{
"MAP_ID": 0,
"CHANGES": [
{
"Description": "Add Item to Quarantine Bay",
"X": 8,
"Y": 9,
"Tile": 386,
"Palette": 0
},
{
"Description": "Add Item to Subzero Containment",
"X": 9,
"Y": 10,
"Tile": 386,
"Palette": 0
},
{
"Description": "Add L3 Locks to Subzero Containment",
"X": 10,
"Y": 10,
"Tile": 84,
"Palette": 0,
"HFlip": "True"
},
{
"Description": "Add L3 Locks to Dark Stairwell",
"X": 11,
"Y": 10,
"Tile": 117,
"Palette": 0,
"VFlip": "True"
}
]
},
{
"MAP_ID": 9,
"CHANGES": [
{
"Description": "Add Item to Quarantine Bay",
"X": 8,
"Y": 9,
"Tile": 386,
"Palette": 0
},
{
"Description": "Add Item to Subzero Containment",
"X": 9,
"Y": 10,
"Tile": 386,
"Palette": 0
},
{
"Description": "Add L3 Locks to Subzero Containment",
"X": 10,
"Y": 10,
"Tile": 84,
"Palette": 0,
"HFlip": "True"
},
{
"Description": "Add L3 Locks to Dark Stairwell",
"X": 11,
"Y": 10,
"Tile": 117,
"Palette": 0,
"VFlip": "True"
}
]
},
{
"MAP_ID": 1,
"CHANGES": [
{
"Description": "Add Item to Northeast Stabilizer",
"X": 16,
"Y": 1,
"Tile": 390,
"Palette": 0,
"HFlip": "True"
}
]
}
]
42 changes: 42 additions & 0 deletions src/mars_patcher/data/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,24 @@
"Room": 27,
"Source": "Ridley",
"Original": "ScrewAttack"
},
{
"Area": 3,
"Room": 25,
"Source": "Boiler",
"Original": "InfantMetroid"
},
{
"Area": 0,
"Room": 69,
"Source": "Animals",
"Original": "InfantMetroid"
},
{
"Area": 0,
"Room": 54,
"Source": "AuxiliaryPower",
"Original": "InfantMetroid"
}
],
"MinorLocations": [
Expand Down Expand Up @@ -168,6 +186,14 @@
"Hidden": true,
"Original": "MissileTank"
},
{
"Area": 0,
"Room": 46,
"BlockX": 9,
"BlockY": 8,
"Hidden": false,
"Original": "InfantMetroid"
},
{
"Area": 0,
"Room": 47,
Expand Down Expand Up @@ -208,6 +234,14 @@
"Hidden": false,
"Original": "MissileTank"
},
{
"Area": 0,
"Room": 71,
"BlockX": 6,
"BlockY": 9,
"Hidden": false,
"Original": "MissileTank"
},
{
"Area": 0,
"Room": 72,
Expand Down Expand Up @@ -272,6 +306,14 @@
"Hidden": true,
"Original": "EnergyTank"
},
{
"Area": 1,
"Room": 32,
"BlockX": 29,
"BlockY": 9,
"Hidden": false,
"Original": "InfantMetroid"
},
{
"Area": 1,
"Room": 39,
Expand Down
13 changes: 8 additions & 5 deletions src/mars_patcher/data/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"MajorLocations": {
"type": "array",
"description": "Specifies how the major item locations should be changed. A major item location is a location where an item is obtained by defeating a boss or interacting with a device.",
"minItems": 20,
"maxItems": 20,
"minItems": 23,
"maxItems": 23,
"uniqueItems": true,
"items": {
"type": "object",
Expand All @@ -41,8 +41,8 @@
"MinorLocations": {
"type": "array",
"description": "Specifies how the minor item locations should be changed. A minor item location is a location where an item is obtained by touching a tank block.",
"minItems": 100,
"maxItems": 100,
"minItems": 103,
"maxItems": 103,
"uniqueItems": true,
"items": {
"type": "object",
Expand Down Expand Up @@ -764,7 +764,10 @@
"Level4",
"AqaData",
"WaveCoreX",
"Ridley"
"Ridley",
"Boiler",
"Animals",
"AuxiliaryPower"
]
},
"ValidItems": {
Expand Down
10 changes: 7 additions & 3 deletions src/mars_patcher/item_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
MINOR_LOCS_TABLE_ADDR = ReservedConstants.MINOR_LOCS_TABLE_ADDR
MINOR_LOCS_ARRAY_ADDR = ReservedConstants.MINOR_LOCS_ARRAY_ADDR
MINOR_LOC_SIZE = 0x8
MAJOR_LOCS_ADDR = ReservedConstants.MAJOR_LOCS_ADDR
MAJOR_LOCS_POINTER_ADDR = ReservedConstants.MAJOR_LOCS_POINTER_ADDR
MAJOR_LOC_SIZE = 0x2
TANK_INC_ADDR = ReservedConstants.TANK_INC_ADDR
REQUIRED_METROID_COUNT_ADDR = ReservedConstants.REQUIRED_METROID_COUNT_ADDR
TOTAL_METROID_COUNT_ADDR = ReservedConstants.TOTAL_METROID_COUNT_ADDR
MESSAGE_TABLE_LOOKUP_ADDR = ReservedConstants.MESSAGE_TABLE_LOOKUP_ADDR
FIRST_CUSTOM_MESSAGE_ID = ReservedConstants.FIRST_CUSTOM_MESSAGE_ID
AUTO_MESSAGE_ID = 0xFF

TANK_CLIP = (0x62, 0x63, 0x68)
HIDDEN_TANK_CLIP = (0x64, 0x65, 0x69)
Expand Down Expand Up @@ -163,7 +164,9 @@ def write_items(self) -> None:
if maj_loc.new_item != ItemType.UNDEFINED:
if maj_loc.new_item == ItemType.INFANT_METROID:
total_metroids += 1
addr = MAJOR_LOCS_ADDR + (maj_loc.major_src.value * MAJOR_LOC_SIZE)
addr = rom.read_ptr(MAJOR_LOCS_POINTER_ADDR) + (
maj_loc.major_src.value * MAJOR_LOC_SIZE
)
rom.write_8(addr, maj_loc.new_item.value)
# Handle item messages
if maj_loc.item_messages is not None:
Expand All @@ -186,7 +189,8 @@ def write_items(self) -> None:
# If the kind is Message ID, write that ID
else:
rom.write_8(addr + 1, messages.message_id)

else: # Set ID to Auto Message
rom.write_8(addr + 1, AUTO_MESSAGE_ID)
# Write total metroid count
rom.write_8(TOTAL_METROID_COUNT_ADDR, total_metroids)

Expand Down
20 changes: 20 additions & 0 deletions src/mars_patcher/minimap.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations

import json
from typing import TYPE_CHECKING

from mars_patcher.compress import comp_lz77, decomp_lz77
from mars_patcher.constants.game_data import minimap_ptrs
from mars_patcher.data import get_data_path

if TYPE_CHECKING:
from types import TracebackType
Expand Down Expand Up @@ -86,3 +88,21 @@ def apply_minimap_edits(rom: Rom, edit_dict: dict) -> None:
change.get("HFlip", False),
change.get("VFlip", False),
)


def apply_base_minimap_edits(rom: Rom) -> None:
with open(get_data_path("base_minimap_edits.json")) as f:
data = json.load(f)

# Go through every minimap
for map in data:
with Minimap(rom, int(map["MAP_ID"])) as minimap:
for change in map["CHANGES"]:
minimap.set_tile_value(
change["X"],
change["Y"],
change["Tile"],
change["Palette"],
change.get("HFlip", False),
change.get("VFlip", False),
)
6 changes: 5 additions & 1 deletion src/mars_patcher/patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from mars_patcher.item_patcher import ItemPatcher, set_required_metroid_count, set_tank_increments
from mars_patcher.level_edits import apply_level_edits
from mars_patcher.locations import LocationSettings
from mars_patcher.minimap import apply_minimap_edits
from mars_patcher.minimap import apply_base_minimap_edits, apply_minimap_edits
from mars_patcher.misc_patches import (
apply_anti_softlock_edits,
apply_base_patch,
Expand Down Expand Up @@ -180,6 +180,10 @@ def patch(
if "LevelEdits" in patch_data:
apply_level_edits(rom, patch_data["LevelEdits"])

# Apply base minimap edits
apply_base_minimap_edits(rom)

# Apply JSON minimap edits
if "MinimapEdits" in patch_data:
apply_minimap_edits(rom, patch_data["MinimapEdits"])

Expand Down