Skip to content
Open
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
4 changes: 2 additions & 2 deletions src/mars_patcher/mf/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
MAIN_HUB_TILEMAP_ADDR,
)
from mars_patcher.mf.data import get_data_path
from mars_patcher.minimap import Minimap
from mars_patcher.rom import Game, Rom
from mars_patcher.room_entry import BlockLayer, RoomEntry
from mars_patcher.tilemap import Tilemap

# Area ID, Room ID, Is area connection
ELEVATOR_TOPS = {
Expand Down Expand Up @@ -235,7 +235,7 @@ def _write_main_hub_small_nums(
bg2.set_block_value(x + 1, y, block + 1)

def remove_main_deck_minimap_area_nums(self) -> None:
with Minimap(self.rom, 0) as minimap:
with Tilemap.from_minimap(self.rom, 0) as minimap:
minimap.set_tile_value(0x2, 0x11, 0xA0, 0) # 5
minimap.set_tile_value(0x3, 0x10, 0xA0, 0) # 3
minimap.set_tile_value(0x4, 0x0F, 0xA0, 0) # 1
Expand Down
4 changes: 2 additions & 2 deletions src/mars_patcher/mf/door_locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
BLANK_TILE_IDS,
BLANK_TRANSPARENT_TILE_IDS,
)
from mars_patcher.minimap import Minimap
from mars_patcher.minimap_tile_creator import create_tile
from mars_patcher.rom import Rom
from mars_patcher.room_entry import BlockLayer, RoomEntry
from mars_patcher.tilemap import Tilemap


class HatchLock(Enum):
Expand Down Expand Up @@ -315,7 +315,7 @@ def change_minimap_tiles(
remaining_blank_transparent_tile_ids = list(BLANK_TRANSPARENT_TILE_IDS)

for area, area_map in minimap_changes.items():
with Minimap(rom, area) as minimap:
with Tilemap.from_minimap(rom, area) as minimap:
for (x, y), tile_changes in area_map.items():
tile_id, palette, h_flip, v_flip = minimap.get_tile_value(x, y)

Expand Down
2 changes: 1 addition & 1 deletion src/mars_patcher/mf/patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
from mars_patcher.mf.navigation_text import NavigationText
from mars_patcher.mf.room_names import write_room_names
from mars_patcher.mf.starting import set_starting_items, set_starting_location
from mars_patcher.minimap import apply_minimap_edits
from mars_patcher.random_palettes import PaletteRandomizer, PaletteSettings
from mars_patcher.rom import Rom
from mars_patcher.sounds import set_sounds
from mars_patcher.text import write_seed_hash
from mars_patcher.tilemap import apply_minimap_edits
from mars_patcher.titlescreen_text import write_title_text


Expand Down
82 changes: 0 additions & 82 deletions src/mars_patcher/minimap.py

This file was deleted.

97 changes: 88 additions & 9 deletions src/mars_patcher/tilemap.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
from enum import Enum, auto
from types import TracebackType

from mars_patcher.common_types import MinimapId
from mars_patcher.compress import comp_lz77, decomp_lz77
from mars_patcher.constants.game_data import minimap_ptrs
from mars_patcher.convert_array import u8_to_u16, u16_to_u8
from mars_patcher.rom import Rom


class TilemapType(Enum):
TILESET = auto()
"""Uncompressed, prefixed with 02 00"""
BACKGROUND = auto()
"""Compressed, prefixed with background size"""
MISC = auto()
"""Compressed, used for minimaps and cutscene graphics"""


class Tilemap:
def __init__(self, rom: Rom, ptr: int, compressed: bool):
def __init__(self, rom: Rom, ptr: int, type: TilemapType):
self.rom = rom
self.pointer = ptr
self.compressed = compressed
self.type = type
# Get data
addr = rom.read_ptr(ptr)
self.data: list[int] = []
if compressed:
data, self.data_size = decomp_lz77(rom.data, addr)
self.data = u8_to_u16(data)
else:
if type == TilemapType.TILESET:
addr += 2
while True:
val = rom.read_16(addr)
Expand All @@ -27,13 +38,66 @@ def __init__(self, rom: Rom, ptr: int, compressed: bool):
self.data.append(val)
addr += 2
self.data_size = len(self.data) * 2 + 4
elif type == TilemapType.BACKGROUND:
raise NotImplementedError()
elif type == TilemapType.MISC:
data, self.data_size = decomp_lz77(rom.data, addr)
self.data = u8_to_u16(data)

def __enter__(self) -> "Tilemap":
# We don't need to do anything
return self

def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
self.write(copy=False)

@classmethod
def from_minimap(cls, rom: Rom, id: MinimapId) -> "Tilemap":
ptr = minimap_ptrs(rom) + (id * 4)
return Tilemap(rom, ptr, TilemapType.MISC)

def get_tile_index(self, x: int, y: int) -> int:
if self.type == TilemapType.TILESET:
idx = (y // 2 * 64) + (y % 2 * 2) + (x // 2 * 4) + (x % 2)
else:
idx = y * 32 + x
if idx >= len(self.data):
raise IndexError(f"Tile coordinate ({x}, {y}) is not within tilemap")
return idx

def get_tile_value(self, x: int, y: int) -> tuple[int, int, bool, bool]:
idx = self.get_tile_index(x, y)
value = self.data[idx]
tile = value & 0x3FF
palette = value >> 12
h_flip = value & 0x400 != 0
v_flip = value & 0x800 != 0
return tile, palette, h_flip, v_flip

def set_tile_value(
self, x: int, y: int, tile: int, palette: int, h_flip: bool = False, v_flip: bool = False
) -> None:
idx = self.get_tile_index(x, y)
value = tile | (palette << 12)
if h_flip:
value |= 0x400
if v_flip:
value |= 0x800
self.data[idx] = value

def byte_data(self) -> bytes:
if self.compressed:
if self.type == TilemapType.TILESET:
return bytes([2, 0]) + u16_to_u8(self.data) + bytes([0, 0])
elif self.type == TilemapType.BACKGROUND:
raise NotImplementedError()
elif self.type == TilemapType.MISC:
data = comp_lz77(u16_to_u8(self.data))
return bytes(data)
else:
return bytes([2, 0]) + u16_to_u8(self.data) + bytes([0, 0])

def write(self, copy: bool) -> None:
data = self.byte_data()
Expand All @@ -42,3 +106,18 @@ def write(self, copy: bool) -> None:
else:
addr = self.rom.read_ptr(self.pointer)
self.rom.write_repointable_data(addr, self.data_size, data, [self.pointer])


def apply_minimap_edits(rom: Rom, edit_dict: dict) -> None:
# Go through every minimap
for map_id, changes in edit_dict.items():
with Tilemap.from_minimap(rom, int(map_id)) as minimap:
for change in changes:
minimap.set_tile_value(
change["X"],
change["Y"],
change["Tile"],
change["Palette"],
change.get("HFlip", False),
change.get("VFlip", False),
)
4 changes: 2 additions & 2 deletions src/mars_patcher/zm/item_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from mars_patcher.rom import Rom
from mars_patcher.room_entry import RoomEntry
from mars_patcher.text import Language, MessageType, encode_text
from mars_patcher.tilemap import Tilemap
from mars_patcher.tilemap import Tilemap, TilemapType
from mars_patcher.tileset import ANIM_TILESET_SIZE, TILESET_SIZE, Tileset
from mars_patcher.zm.auto_generated_types import MarsschemazmTankIncrements
from mars_patcher.zm.constants.game_data import (
Expand All @@ -34,7 +34,7 @@ def __init__(self, rom: Rom, id: int):
self.id = id
self.meta = Tileset(rom, id)
# Load tilemap
self.tilemap = Tilemap(rom, self.meta.tilemap_ptr(), False)
self.tilemap = Tilemap(rom, self.meta.tilemap_ptr(), TilemapType.TILESET)
# Load palette
self.palette = Palette(14, rom, self.meta.palette_addr())
# Load animated tileset
Expand Down
Loading